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