#define NDEBUG\r
#include <debug.h>\r
\r
+/* SM handle for its own \SmApiPort */\r
+HANDLE hSmApiPort = (HANDLE) 0;\r
+\r
+\r
/* TODO: this file should be totally rewritten\r
*\r
* a) look if a special option is set for smss.exe in\r
* b) make smss register with itself for IMAGE_SUBSYSTEM_NATIVE\r
* (programmatically)\r
*\r
- * c) make smss load win32k.sys as set in Kmode key\r
- * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\r
- *\r
* d) make smss initialize Debug (DBGSS) and Windows (CSRSS) as described\r
* in the registry key Required="Debug Windows"\r
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\r
NTSTATUS\r
SmLoadSubsystems(VOID)\r
{\r
- SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;\r
- NTSTATUS Status;\r
-\r
- DPRINT("SM: loading subsystems\n");\r
- \r
- /* Load kernel mode subsystem (aka win32k.sys) */\r
- RtlRosInitUnicodeStringFromLiteral(&ImageInfo.ModuleName,\r
- L"\\SystemRoot\\system32\\win32k.sys");\r
+ SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+ WCHAR Data [MAX_PATH + 1];\r
+ ULONG DataLength = sizeof Data;\r
+ ULONG DataType = 0;\r
\r
- Status = NtSetSystemInformation(SystemLoadAndCallImage,\r
- &ImageInfo,\r
- sizeof(SYSTEM_LOAD_AND_CALL_IMAGE));\r
\r
- DPRINT("SMSS: Loaded win32k.sys (Status %lx)\n", Status);\r
-#if 0\r
- if (!NT_SUCCESS(Status))\r
- {\r
- return(Status);\r
- }\r
-#endif\r
-\r
- /* FIXME: load more subsystems (csrss!) */\r
-\r
- return(Status);\r
+ DPRINT("SM: loading subsystems\n");\r
+ \r
+ /* Load Kmode subsystem (aka win32k.sys) */\r
+ Status = SmLookupSubsystem (L"Kmode",\r
+ Data,\r
+ & DataLength,\r
+ & DataType,\r
+ TRUE);\r
+ if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))\r
+ {\r
+ WCHAR ImagePath [MAX_PATH + 1] = {0};\r
+\r
+ wcscpy (ImagePath, L"\\??\\");\r
+ wcscat (ImagePath, Data);\r
+ RtlZeroMemory (& ImageInfo, sizeof ImageInfo);\r
+ RtlInitUnicodeString (& ImageInfo.ModuleName, ImagePath);\r
+ Status = NtSetSystemInformation(SystemLoadAndCallImage,\r
+ & ImageInfo,\r
+ sizeof ImageInfo);\r
+ if(!NT_SUCCESS(Status))\r
+ {\r
+ DPRINT("SM: loading Kmode failed (Status=0x%08lx)\n",\r
+ Status);\r
+ return Status;\r
+ }\r
+ }\r
+ /* TODO: load Required subsystems (Debug Windows) */\r
+ return Status;\r
}\r
\r
NTSTATUS\r
-/* $Id: $\r
+/* $Id$\r
*\r
* smapiexec.c - SM_API_EXECUTE_PROGRAM\r
*\r
* Reactos Session Manager\r
*\r
+ * --------------------------------------------------------------------\r
+ *\r
+ * This software is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License as\r
+ * published by the Free Software Foundation; either version 2 of the\r
+ * License, or (at your option) any later version.\r
+ *\r
+ * This software is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this software; see the file COPYING.LIB. If not, write\r
+ * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,\r
+ * MA 02139, USA. \r
+ *\r
+ * --------------------------------------------------------------------\r
*/\r
-\r
#include "smss.h"\r
-#include <rosrtl/string.h>\r
\r
#define NDEBUG\r
#include <debug.h>\r
return STATUS_SUCCESS;\r
}\r
\r
+/**********************************************************************\r
+ * NAME\r
+ * SmLookupSubsystem/5\r
+ *\r
+ * DESCRIPTION\r
+ * Read from the registry key\r
+ * \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems\r
+ * the value which name is Name.\r
+ *\r
+ * ARGUMENTS\r
+ * Name: name of the program to run, that is a value's name in\r
+ * the SM registry key Subsystems;\r
+ * Data: what the registry gived back for Name;\r
+ * DataLength: how much Data the registry retruns;\r
+ * DataType: what is Data?\r
+ * Expand: set it TRUE if you want this function to use the env\r
+ * to possibly expand Data before giving it back.\r
+ */\r
+NTSTATUS STDCALL\r
+SmLookupSubsystem (IN PWSTR Name,\r
+ IN OUT PWSTR Data,\r
+ IN OUT PULONG DataLength,\r
+ IN OUT PULONG DataType,\r
+ IN BOOLEAN Expand)\r
+{\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+ UNICODE_STRING usKeyName = {0};\r
+ OBJECT_ATTRIBUTES Oa = {0};\r
+ HANDLE hKey = (HANDLE) 0;\r
+\r
+ DPRINT("SM: %s called\n", __FUNCTION__);\r
+ /*\r
+ * Prepare the key name to scan and\r
+ * related object attributes.\r
+ */\r
+ RtlInitUnicodeString (& usKeyName,\r
+ L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems");\r
+\r
+ InitializeObjectAttributes (& Oa,\r
+ & usKeyName,\r
+ OBJ_CASE_INSENSITIVE,\r
+ NULL,\r
+ NULL);\r
+ /*\r
+ * Open the key. This MUST NOT fail, if the\r
+ * request is for a legitimate subsystem.\r
+ */\r
+ Status = NtOpenKey (& hKey,\r
+ MAXIMUM_ALLOWED,\r
+ & Oa);\r
+ if(NT_SUCCESS(Status))\r
+ {\r
+ UNICODE_STRING usValueName = {0};\r
+ WCHAR KeyValueInformation [1024] = {L'\0'};\r
+ ULONG ResultLength = 0L;\r
+ PKEY_VALUE_PARTIAL_INFORMATION\r
+ kvpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;\r
+\r
+ \r
+ RtlInitUnicodeString (& usValueName, Name);\r
+ Status = NtQueryValueKey (hKey,\r
+ & usValueName,\r
+ KeyValuePartialInformation,\r
+ KeyValueInformation,\r
+ sizeof KeyValueInformation,\r
+ & ResultLength);\r
+ if(NT_SUCCESS(Status))\r
+ {\r
+ DPRINT("nkvpi.TitleIndex = %ld\n", kvpi->TitleIndex);\r
+ DPRINT("kvpi.Type = %ld\n", kvpi->Type);\r
+ DPRINT("kvpi.DataLength = %ld\n", kvpi->DataLength);\r
+\r
+ if((NULL != Data) && (NULL != DataLength) && (NULL != DataType))\r
+ {\r
+ *DataType = kvpi->Type;\r
+ if((Expand) && (REG_EXPAND_SZ == *DataType))\r
+ {\r
+ UNICODE_STRING Source;\r
+ WCHAR DestinationBuffer [2048] = {0};\r
+ UNICODE_STRING Destination;\r
+ ULONG Length = 0;\r
+\r
+ DPRINT("SM: %s: value will be expanded\n", __FUNCTION__);\r
+\r
+ Source.Length = kvpi->DataLength;\r
+ Source.MaximumLength = kvpi->DataLength;\r
+ Source.Buffer = (PWCHAR) & kvpi->Data;\r
+\r
+ Destination.Length = 0;\r
+ Destination.MaximumLength = sizeof DestinationBuffer;\r
+ Destination.Buffer = DestinationBuffer;\r
+\r
+ Status = RtlExpandEnvironmentStrings_U (SmSystemEnvironment,\r
+ & Source,\r
+ & Destination,\r
+ & Length);\r
+ if(NT_SUCCESS(Status))\r
+ {\r
+ *DataLength = min(*DataLength, Destination.Length);\r
+ RtlCopyMemory (Data, Destination.Buffer, *DataLength); \r
+ }\r
+ \r
+ }else{\r
+ DPRINT("SM: %s: value won't be expanded\n", __FUNCTION__);\r
+ *DataLength = min(*DataLength, kvpi->DataLength);\r
+ RtlCopyMemory (Data, & kvpi->Data, *DataLength);\r
+ }\r
+ *DataType = kvpi->Type;\r
+ }else{\r
+ DPRINT1("SM: %s: Data or DataLength or DataType is NULL!\n", __FUNCTION__);\r
+ Status = STATUS_INVALID_PARAMETER;\r
+ }\r
+ }else{\r
+ DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);\r
+ }\r
+ NtClose (hKey);\r
+ }else{\r
+ DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);\r
+ }\r
+ return Status;\r
+}\r
+\r
+\r
/**********************************************************************\r
* SmExecPgm/1 API\r
*/\r
SMAPI(SmExecPgm)\r
{\r
+ PSM_PORT_MESSAGE_EXECPGM ExecPgm = NULL;\r
+ WCHAR Name [SM_EXEXPGM_MAX_LENGTH + 1];\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+\r
DPRINT("SM: %s called\n",__FUNCTION__);\r
- Request->Status = STATUS_NOT_IMPLEMENTED;\r
- return STATUS_SUCCESS;\r
-}\r
\r
+ if(NULL == Request)\r
+ {\r
+ DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__);\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ DPRINT("SM: %s called from CID(%lx|%lx)\n",\r
+ __FUNCTION__, Request->Header.ClientId.UniqueProcess,\r
+ Request->Header.ClientId.UniqueThread);\r
+ ExecPgm = & Request->ExecPgm;\r
+ /* Check if the name lenght is valid */\r
+ if((ExecPgm->NameLength > 0) &&\r
+ (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&\r
+ TRUE /* TODO: check LPC payload size */)\r
+ {\r
+ \r
+ RtlZeroMemory (Name, sizeof Name);\r
+ RtlCopyMemory (Name,\r
+ ExecPgm->Name,\r
+ (sizeof ExecPgm->Name[0] * ExecPgm->NameLength));\r
+ DPRINT("SM: %s: Name=[%wZ]\n", __FUNCTION__, Name);\r
+ /*\r
+ * Check if program name is internal\r
+ * (Is this correct? Debug is in the registry too)\r
+ */\r
+ if(0 == _wcsicmp(L"DEBUG", Name))\r
+ {\r
+ /*\r
+ * Initialize DBGSS.\r
+ * NOTE: probably in early prototypes it was an\r
+ * independent process; now it is embedded in the\r
+ * SM for performance or security.\r
+ */\r
+ Request->Status = SmInitializeDbgSs();\r
+ }\r
+ else\r
+ {\r
+ WCHAR ImagePath [1024] = {0};\r
+ ULONG ImagePathLength = sizeof ImagePath;\r
+ ULONG ImagePathType = REG_EXPAND_SZ;\r
+\r
+ /* Lookup Name in the registry */\r
+ Status = SmLookupSubsystem (Name,\r
+ ImagePath,\r
+ & ImagePathLength,\r
+ & ImagePathType,\r
+ TRUE); /* expand */\r
+ if(NT_SUCCESS(Status))\r
+ {\r
+ /* Create native process */\r
+ Request->Status = SmCreateUserProcess(ImagePath,\r
+ L"", /* FIXME */\r
+ FALSE, /* wait */\r
+ NULL,\r
+ FALSE, /* terminate */\r
+ NULL);\r
+ }else{\r
+ Request->Status = Status;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Request->Status = Status = STATUS_INVALID_PARAMETER;\r
+ }\r
+ return Status;\r
+}\r
\r
/* EOF */\r