diff --git a/reactos/subsys/smss/client.c b/reactos/subsys/smss/client.c index 212e3332e86..94e52b7a37b 100644 --- a/reactos/subsys/smss/client.c +++ b/reactos/subsys/smss/client.c @@ -39,9 +39,11 @@ struct _SM_CLIENT_DIRECTORY RTL_CRITICAL_SECTION Lock; ULONG Count; PSM_CLIENT_DATA Client; + PSM_CLIENT_DATA CandidateClient; } SmpClientDirectory; + /********************************************************************** * SmInitializeClientManagement/0 */ @@ -52,56 +54,41 @@ SmInitializeClientManagement (VOID) RtlInitializeCriticalSection(& SmpClientDirectory.Lock); SmpClientDirectory.Count = 0; SmpClientDirectory.Client = NULL; + SmpClientDirectory.CandidateClient = NULL; return STATUS_SUCCESS; } - /********************************************************************** - * SmCompleteClientInitialization/1 - * - * DESCRIPTION - * Lookup the subsystem server descriptor given the process handle - * of the subsystem server process. + * SmpSetClientInitialized/1 */ -NTSTATUS STDCALL -SmCompleteClientInitialization (HANDLE hProcess) +VOID FASTCALL +SmpSetClientInitialized (PSM_CLIENT_DATA Client) { - NTSTATUS Status = STATUS_SUCCESS; - PSM_CLIENT_DATA Client = NULL; - - DPRINT("SM: %s called\n", __FUNCTION__); - - RtlEnterCriticalSection (& SmpClientDirectory.Lock); - if (SmpClientDirectory.Count > 0) - { - Client = SmpClientDirectory.Client; - while (NULL != Client) - { - if (hProcess == Client->ServerProcess) - { - Client->Initialized = TRUE; - break; - } - Client = Client->Next; - } - Status = STATUS_NOT_FOUND; - } - RtlLeaveCriticalSection (& SmpClientDirectory.Lock); - return Status; + Client->Flags |= SM_CLIENT_FLAG_INITIALIZED; } - /********************************************************************** - * SmpLookupClient/1 PRIVATE + * SmpLookupClient/2 PRIVATE * * DESCRIPTION * Lookup the subsystem server descriptor given its image ID. * - * SIDE EFFECTS - * SmpClientDirectory.Lock is released only on success. + * ARGUMENTS + * SubsystemId: IMAGE_SUBSYSTEM_xxx + * Parent: optional: caller provided storage for the + * the pointer to the SM_CLIENT_DATA which + * Next field contains the value returned by + * the function (on success). + * + * RETURN VALUES + * NULL on error; otherwise a pointer to the SM_CLIENT_DATA + * looked up object. + * + * WARNING + * SmpClientDirectory.Lock must be held by the caller. */ static PSM_CLIENT_DATA FASTCALL -SmpLookupClientUnsafe (USHORT SubsystemId, - PSM_CLIENT_DATA * Parent) +SmpLookupClient (USHORT SubsystemId, + PSM_CLIENT_DATA * Parent) { PSM_CLIENT_DATA Client = NULL; @@ -129,72 +116,86 @@ SmpLookupClientUnsafe (USHORT SubsystemId, } return Client; } - -static PSM_CLIENT_DATA STDCALL -SmpLookupClient (USHORT SubsystemId) -{ - PSM_CLIENT_DATA Client = NULL; - - DPRINT("SM: %s called\n", __FUNCTION__); - - RtlEnterCriticalSection (& SmpClientDirectory.Lock); - Client = SmpLookupClientUnsafe (SubsystemId, NULL); - if(NULL != Client) - { - RtlLeaveCriticalSection (& SmpClientDirectory.Lock); - } - /* - * Note that we do *not* release SmpClientDirectory.Lock here - * because SmpLookupClient is called to FAIL when SubsystemId - * is not registered yet. - */ - return Client; -} - /********************************************************************** - * SmpCreateClient/2 + * SmBeginClientInitialization/1 + * + * DESCRIPTION + * Check if the candidate client matches the begin session + * message from the subsystem process. + * + * ARGUMENTS + * Request: message received by \SmApiPort + * ClientData: + * + * RETURN VALUES + * NTSTATUS */ NTSTATUS STDCALL -SmCreateClient(PSM_PORT_MESSAGE Request, PSM_CLIENT_DATA * ClientData) +SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request, + OUT PSM_CLIENT_DATA * ClientData) { - PSM_CLIENT_DATA pClient = NULL; + NTSTATUS Status = STATUS_SUCCESS; PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request); ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request); - DPRINT("SM: %s called\n", __FUNCTION__); + DPRINT("SM: %s called\n", __FUNCTION__); + + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + /* + * Is there a subsystem bootstrap in progress? + */ + if (SmpClientDirectory.CandidateClient) + { + PROCESS_BASIC_INFORMATION pbi; + + RtlZeroMemory (& pbi, sizeof pbi); + Status = NtQueryInformationProcess (Request->Header.ClientId.UniqueProcess, + ProcessBasicInformation, + & pbi, + sizeof pbi, + NULL); + if (NT_SUCCESS(Status)) + { + SmpClientDirectory.CandidateClient->ServerProcessId = + (ULONG) pbi.UniqueProcessId; + } + } + else + { + RtlFreeHeap (SmpHeap, 0, SmpClientDirectory.CandidateClient); + DPRINT1("SM: %s: subsys booting with no descriptor!\n", __FUNCTION__); + Status = STATUS_NOT_FOUND; + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return Status; + } /* * Check if a client for the ID already exist. */ - if (SmpLookupClient(ConnectData->SubSystemId)) + if (SmpLookupClient(ConnectData->SubSystemId, NULL)) { DPRINT("SM: %s: attempt to register again subsystem %d.\n", __FUNCTION__, ConnectData->SubSystemId); return STATUS_UNSUCCESSFUL; } - DPRINT("SM: %s: registering subsystem ID=%d \n", __FUNCTION__, ConnectData->SubSystemId); - /* - * Allocate the storage for client data - */ - pClient = RtlAllocateHeap (SmpHeap, - HEAP_ZERO_MEMORY, - sizeof (SM_CLIENT_DATA)); - if (NULL == pClient) - { - DPRINT("SM: %s: out of memory!\n",__FUNCTION__); - return STATUS_NO_MEMORY; - } + DPRINT("SM: %s: registering subsystem ID=%d \n", + __FUNCTION__, ConnectData->SubSystemId); + /* * Initialize the client data */ - pClient->SubsystemId = ConnectData->SubSystemId; - /* SM auto-initializes; other subsystems are required to call + SmpClientDirectory.CandidateClient->SubsystemId = ConnectData->SubSystemId; + /* SM && DBG auto-initializes; other subsystems are required to call * SM_API_COMPLETE_SESSION via SMDLL. */ - pClient->Initialized = (IMAGE_SUBSYSTEM_NATIVE == pClient->SubsystemId); + if ((IMAGE_SUBSYSTEM_NATIVE == SmpClientDirectory.CandidateClient->SubsystemId) || + (IMAGE_SUBSYSTEM_UNKNOWN == SmpClientDirectory.CandidateClient->SubsystemId)) + { + SmpSetClientInitialized (SmpClientDirectory.CandidateClient); + } if (SbApiPortNameSize > 0) { - RtlCopyMemory (pClient->SbApiPortName, + RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName, ConnectData->SbName, SbApiPortNameSize); } @@ -204,28 +205,132 @@ SmCreateClient(PSM_PORT_MESSAGE Request, PSM_CLIENT_DATA * ClientData) */ if (NULL == SmpClientDirectory.Client) { - SmpClientDirectory.Client = pClient; + SmpClientDirectory.Client = SmpClientDirectory.CandidateClient; } else { PSM_CLIENT_DATA pCD = NULL; for (pCD=SmpClientDirectory.Client; (NULL != pCD->Next); pCD = pCD->Next); - pCD->Next = pClient; + pCD->Next = SmpClientDirectory.CandidateClient; } - pClient->Next = NULL; + SmpClientDirectory.CandidateClient->Next = NULL; + /* + * Increment the number of active subsystems. + */ ++ SmpClientDirectory.Count; /* - * Note we unlock the client directory here, because - * it was locked by SmpLookupClient on failure. + * Notify to the caller the reference to the client data. */ - RtlLeaveCriticalSection (& SmpClientDirectory.Lock); if (ClientData) { - *ClientData = pClient; + *ClientData = SmpClientDirectory.CandidateClient; } + /* + * Free the slot for the candidate subsystem. + */ + SmpClientDirectory.CandidateClient = NULL; + + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return STATUS_SUCCESS; } +/********************************************************************** + * SmCompleteClientInitialization/1 + * + * DESCRIPTION + * Lookup the subsystem server descriptor given the process ID + * of the subsystem server process. + */ +NTSTATUS STDCALL +SmCompleteClientInitialization (ULONG ProcessId) +{ + NTSTATUS Status = STATUS_SUCCESS; + PSM_CLIENT_DATA Client = NULL; + + DPRINT("SM: %s called\n", __FUNCTION__); + + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + if (SmpClientDirectory.Count > 0) + { + Client = SmpClientDirectory.Client; + while (NULL != Client) + { + if (ProcessId == Client->ServerProcessId) + { + SmpSetClientInitialized (Client); + break; + } + Client = Client->Next; + } + Status = STATUS_NOT_FOUND; + } + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return Status; +} + +/********************************************************************** + * SmpCreateClient/1 + * + * DESCRIPTION + * Create a "candidate" client. Client descriptor will enter the + * client directory only at the end of the registration + * procedure. Otherwise, we will kill the associated process. + * + * ARGUMENTS + * ProcessHandle: handle of the subsystem server process. + * + * RETURN VALUE + * NTSTATUS: + */ +NTSTATUS STDCALL +SmCreateClient (PRTL_PROCESS_INFO ProcessInfo, PWSTR ProgramName) +{ + NTSTATUS Status = STATUS_SUCCESS; + + + DPRINT("SM: %s(%lx) called\n", __FUNCTION__, ProcessInfo->ProcessHandle); + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + /* + * Check if the candidate client slot is empty. + */ + if (NULL != SmpClientDirectory.CandidateClient) + { + DPRINT1("SM: %s: CandidateClient pending!\n", __FUNCTION__); + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return STATUS_UNSUCCESSFUL; + } + /* + * Allocate the storage for client data + */ + SmpClientDirectory.CandidateClient = + RtlAllocateHeap (SmpHeap, + HEAP_ZERO_MEMORY, + sizeof (SM_CLIENT_DATA)); + if (NULL == SmpClientDirectory.CandidateClient) + { + DPRINT("SM: %s(%lx): out of memory!\n", + __FUNCTION__, ProcessInfo->ProcessHandle); + Status = STATUS_NO_MEMORY; + } + else + { + /* Initialize the candidate client. */ + RtlInitializeCriticalSection(& SmpClientDirectory.CandidateClient->Lock); + SmpClientDirectory.CandidateClient->ServerProcess = + (HANDLE) ProcessInfo->ProcessHandle; + SmpClientDirectory.CandidateClient->ServerProcessId = + (ULONG) ProcessInfo->ClientId.UniqueProcess; + } + /* + * Copy the program name + */ + RtlCopyMemory (SmpClientDirectory.CandidateClient->ProgramName, + ProgramName, + SM_SB_NAME_MAX_LENGTH); + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return Status; +} /********************************************************************** * SmpDestroyClient/1 @@ -244,7 +349,7 @@ SmDestroyClient (ULONG SubsystemId) DPRINT("SM: %s called\n", __FUNCTION__); RtlEnterCriticalSection (& SmpClientDirectory.Lock); - Client = SmpLookupClientUnsafe (SubsystemId, & Parent); + Client = SmpLookupClient (SubsystemId, & Parent); if(NULL == Client) { DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n", @@ -269,6 +374,7 @@ SmDestroyClient (ULONG SubsystemId) } } /* TODO: send shutdown or kill */ + NtTerminateProcess (Client->ServerProcess, 0); //FIXME RtlFreeHeap (SmpHeap, 0, Client); -- SmpClientDirectory.Count; } @@ -285,7 +391,7 @@ NTSTATUS FASTCALL SmGetClientBasicInformation (PSM_BASIC_INFORMATION i) { INT Index = 0; - PSM_CLIENT_DATA Client = NULL; + PSM_CLIENT_DATA ClientData = NULL; DPRINT("SM: %s called\n", __FUNCTION__); @@ -296,13 +402,13 @@ SmGetClientBasicInformation (PSM_BASIC_INFORMATION i) if (SmpClientDirectory.Count > 0) { - Client = SmpClientDirectory.Client; - while ((NULL != Client) && (Index < SM_QRYINFO_MAX_SS_COUNT)) + ClientData = SmpClientDirectory.Client; + while ((NULL != ClientData) && (Index < SM_QRYINFO_MAX_SS_COUNT)) { - i->SubSystem[Index].Id = Client->SubsystemId; - i->SubSystem[Index].Flags = 0; /* TODO */ - i->SubSystem[Index].ProcessId = 0; /* TODO */ - Client = Client->Next; + i->SubSystem[Index].Id = ClientData->SubsystemId; + i->SubSystem[Index].Flags = ClientData->Flags; + i->SubSystem[Index].ProcessId = ClientData->ServerProcessId; + ClientData = ClientData->Next; } } @@ -316,9 +422,27 @@ SmGetClientBasicInformation (PSM_BASIC_INFORMATION i) NTSTATUS FASTCALL SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i) { + NTSTATUS Status = STATUS_SUCCESS; + PSM_CLIENT_DATA ClientData = NULL; + DPRINT("SM: %s called\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + ClientData = SmpLookupClient (i->SubSystemId, NULL); + if (NULL == ClientData) + { + Status = STATUS_NOT_FOUND; + } + else + { + i->Flags = ClientData->Flags; + i->ProcessId = ClientData->ServerProcessId; + RtlCopyMemory (i->NameSpaceRootNode, + ClientData->SbApiPortName, + (SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0]))); + } + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return Status; } /* EOF */ diff --git a/reactos/subsys/smss/initmv.c b/reactos/subsys/smss/initmv.c index aa78ea5e187..786a298913f 100644 --- a/reactos/subsys/smss/initmv.c +++ b/reactos/subsys/smss/initmv.c @@ -23,6 +23,7 @@ * * -------------------------------------------------------------------- */ + #include "smss.h" @@ -35,6 +36,13 @@ SmProcessFileRenameList(VOID) DPRINT("SmProcessFileRenameList() called\n"); /* FIXME: implement it! */ +/* + * open HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\FileRenameOperations + * for each item in its value + * clone the old file in the new name, + * delete the source. + * + */ DPRINT("SmProcessFileRenameList() done\n"); diff --git a/reactos/subsys/smss/initrun.c b/reactos/subsys/smss/initrun.c index 1c0ecdc01bc..e19a172b8d7 100644 --- a/reactos/subsys/smss/initrun.c +++ b/reactos/subsys/smss/initrun.c @@ -29,7 +29,7 @@ #define NDEBUG #include -HANDLE Children[2] = {0, 0}; /* csrss, winlogon */ +//HANDLE Children[2] = {0, 0}; /* csrss, winlogon */ /********************************************************************** @@ -99,10 +99,12 @@ SmpRunBootAppsQueryRoutine(PWSTR ValueName, Status = SmCreateUserProcess (ImagePath, CommandLine, TRUE, /* wait */ - NULL, - TRUE, /* terminate */ - NULL); - + NULL, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SM: %s: running '$S' failed (Status=0x%08lx)\n", + __FUNCTION__, Status); + } return(STATUS_SUCCESS); } diff --git a/reactos/subsys/smss/initss.c b/reactos/subsys/smss/initss.c index 464cfe6d689..bc8f7fa412a 100644 --- a/reactos/subsys/smss/initss.c +++ b/reactos/subsys/smss/initss.c @@ -55,23 +55,40 @@ static NTSTATUS SmpRegisterSmss(VOID) { NTSTATUS Status = STATUS_SUCCESS; - UNICODE_STRING SbApiPortName = {0,0,NULL}; + RTL_PROCESS_INFO ProcessInfo; DPRINT("SM: %s called\n",__FUNCTION__); - - RtlInitUnicodeString (& SbApiPortName, L""); - Status = SmConnectApiPort(& SbApiPortName, - (HANDLE) -1, /* SM has no SB port */ - IMAGE_SUBSYSTEM_NATIVE, - & hSmApiPort); - if(!NT_SUCCESS(Status)) + + RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo); + ProcessInfo.Size = sizeof ProcessInfo; + ProcessInfo.ProcessHandle = (HANDLE) SmSsProcessId; + ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId; + DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n", + __FUNCTION__,ProcessInfo.ProcessHandle); + Status = SmCreateClient (& ProcessInfo, L"Session Manager"); + if (NT_SUCCESS(Status)) { - DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n", - __FUNCTION__,Status); - return Status; + UNICODE_STRING SbApiPortName = {0,0,NULL}; + + RtlInitUnicodeString (& SbApiPortName, L""); + Status = SmConnectApiPort(& SbApiPortName, + (HANDLE) -1, /* SM has no SB port */ + IMAGE_SUBSYSTEM_NATIVE, + & hSmApiPort); + if(!NT_SUCCESS(Status)) + { + DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n", + __FUNCTION__,Status); + return Status; + } + DPRINT("SM self registered\n"); + } + else + { + DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n", + __FUNCTION__, Status); } - DPRINT("SM self registered\n"); /* * Note that you don't need to call complete session * because connection handling code autocompletes diff --git a/reactos/subsys/smss/smapi.c b/reactos/subsys/smss/smapi.c index ed2979631a8..17e169e2fa0 100644 --- a/reactos/subsys/smss/smapi.c +++ b/reactos/subsys/smss/smapi.c @@ -52,12 +52,13 @@ SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request); #endif /********************************************************************** - * SmpCallback/2 + * SmpCallbackServer/2 * - * The SM calls back a previously connected subsystem process to - * authorizes it to bootstrap (initialize). The SM connects to a - * named LPC port which name was sent in the connection data by the - * candidate subsystem server process. + * DESCRIPTION + * The SM calls back a previously connected subsystem process to + * authorize it to bootstrap (initialize). The SM connects to a + * named LPC port which name was sent in the connection data by + * the candidate subsystem server process. */ static NTSTATUS SmpCallbackServer (PSM_PORT_MESSAGE Request, @@ -72,7 +73,8 @@ SmpCallbackServer (PSM_PORT_MESSAGE Request, DPRINT("SM: %s called\n", __FUNCTION__); - if(IMAGE_SUBSYSTEM_NATIVE == ConnectData->SubSystemId) + if ( (IMAGE_SUBSYSTEM_UNKNOWN == ConnectData->SubSystemId) || + (IMAGE_SUBSYSTEM_NATIVE == ConnectData->SubSystemId)) { DPRINT("SM: %s: we do not need calling back SM!\n", __FUNCTION__); @@ -210,12 +212,10 @@ SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request) { DPRINT("SM: %s: id = %d\n", __FUNCTION__, ConnectData->SubSystemId); /* - * SmCreateClient/2 is called here explicitly to *fail*. - * If it succeeds, there is something wrong in the - * connection request. An environment subsystem *never* - * registers twice. (security issue) + * SmBeginClientInitialization/2 will succeed only if there + * is a candidate client ready. */ - Status = SmCreateClient (Request, & ClientData); + Status = SmBeginClientInitialization (Request, & ClientData); if(STATUS_SUCCESS == Status) { DPRINT("SM: %s: ClientData = 0x%08lx\n", @@ -310,7 +310,7 @@ SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request) * * DECRIPTION * Due to differences in LPC implementation between NT and ROS, - * we need a thread to listen for connection request that + * we need a thread to listen to for connection request that * creates a new thread for each connected port. This is not * necessary in NT LPC, because server side connected ports are * never used to receive requests. diff --git a/reactos/subsys/smss/smapicomp.c b/reactos/subsys/smss/smapicomp.c index 94abeb96ef1..f4d42220f3e 100644 --- a/reactos/subsys/smss/smapicomp.c +++ b/reactos/subsys/smss/smapicomp.c @@ -34,16 +34,20 @@ */ SMAPI(SmCompSes) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status = STATUS_SUCCESS; DPRINT("SM: %s called\n", __FUNCTION__); - - Status = SmCompleteClientInitialization (Request->Header.ClientId.UniqueProcess); - if(!NT_SUCCESS(Status)) + + DPRINT("SM: %s: ClientId.UniqueProcess=%lx\n", + __FUNCTION__, Request->Header.ClientId.UniqueProcess); + Status = SmCompleteClientInitialization ((ULONG) Request->Header.ClientId.UniqueProcess); + if (!NT_SUCCESS(Status)) { - Request->SmHeader.Status = STATUS_UNSUCCESSFUL; + DPRINT1("SM: %s: NtQueryInformationProcess failed (Status=0x%08lx)\n", + __FUNCTION__, Status); } - return Status; + Request->SmHeader.Status = Status; + return STATUS_SUCCESS; } diff --git a/reactos/subsys/smss/smapiexec.c b/reactos/subsys/smss/smapiexec.c index f74ac34b3b9..445966bac65 100644 --- a/reactos/subsys/smss/smapiexec.c +++ b/reactos/subsys/smss/smapiexec.c @@ -31,15 +31,27 @@ /********************************************************************** * SmCreateUserProcess/5 * + * DESCRIPTION + * + * ARGUMENTS + * ImagePath: bsolute path of the image to run; + * CommandLine: arguments and options for ImagePath; + * WaitForIt: TRUE for boot time processes and FALSE for + * subsystems bootstrapping; + * Timeout: optional: used if WaitForIt==TRUE; + * ProcessHandle: optional: a duplicated handle for + the child process (storage provided by the caller). + * + * RETURN VALUE + * NTSTATUS: + * */ NTSTATUS STDCALL SmCreateUserProcess (LPWSTR ImagePath, LPWSTR CommandLine, BOOLEAN WaitForIt, PLARGE_INTEGER Timeout OPTIONAL, - BOOLEAN TerminateIt, - PRTL_PROCESS_INFO UserProcessInfo OPTIONAL - ) + PRTL_PROCESS_INFO UserProcessInfo OPTIONAL) { UNICODE_STRING ImagePathString = {0}; UNICODE_STRING CommandLineString = {0}; @@ -48,8 +60,12 @@ SmCreateUserProcess (LPWSTR ImagePath, PRTL_PROCESS_INFO pProcessInfo = & ProcessInfo; NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("SM: %s called\n",__FUNCTION__); + DPRINT("SM: %s called\n", __FUNCTION__); + + if (NULL != UserProcessInfo) + { + pProcessInfo = UserProcessInfo; + } RtlInitUnicodeString (& ImagePathString, ImagePath); RtlInitUnicodeString (& CommandLineString, CommandLine); @@ -65,12 +81,6 @@ SmCreateUserProcess (LPWSTR ImagePath, NULL, NULL); - if(NULL != UserProcessInfo) - { - /* Use caller provided storage */ - pProcessInfo = UserProcessInfo; - } - Status = RtlCreateUserProcess (& ImagePathString, OBJ_CASE_INSENSITIVE, ProcessParameters, @@ -82,7 +92,7 @@ SmCreateUserProcess (LPWSTR ImagePath, NULL, pProcessInfo); - RtlDestroyProcessParameters (ProcessParameters); + RtlDestroyProcessParameters (ProcessParameters); if (!NT_SUCCESS(Status)) { @@ -90,25 +100,52 @@ SmCreateUserProcess (LPWSTR ImagePath, __FUNCTION__, ImagePathString.Buffer, Status); return Status; } - - ZwResumeThread(pProcessInfo->ThreadHandle, NULL); - + /* + * It the caller is *not* interested in the child info, + * resume it immediately. + */ + if (NULL == UserProcessInfo) + { + Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL); + if(!NT_SUCCESS(Status)) + { + DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n", + __FUNCTION__, Status); + } + } + else + { + HANDLE DupProcessHandle = (HANDLE) 0; + + Status = NtDuplicateObject (NtCurrentProcess(), + pProcessInfo->ProcessHandle, + NtCurrentProcess(), + & DupProcessHandle, + PROCESS_ALL_ACCESS, + 0, 0); + if(!NT_SUCCESS(Status)) + { + DPRINT1("SM: %s: NtDuplicateObject failed (Status=0x%08lx)\n", + __FUNCTION__, Status); + } + pProcessInfo->ProcessHandle = DupProcessHandle; + + } /* Wait for process termination */ - if(WaitForIt) + if (WaitForIt) { - NtWaitForSingleObject (pProcessInfo->ProcessHandle, - FALSE, - Timeout); + Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle, + FALSE, + Timeout); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n", + __FUNCTION__, Status); + } + } - - /* Terminate process */ - if(TerminateIt) - { - NtClose(pProcessInfo->ThreadHandle); - NtClose(pProcessInfo->ProcessHandle); - } - return STATUS_SUCCESS; + return Status; } /********************************************************************** @@ -259,61 +296,94 @@ SMAPI(SmExecPgm) (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) && TRUE /* TODO: check LPC payload size */) { + WCHAR Data [MAX_PATH + 1] = {0}; + ULONG DataLength = sizeof Data; + ULONG DataType = REG_EXPAND_SZ; + RtlZeroMemory (Name, sizeof Name); RtlCopyMemory (Name, ExecPgm->Name, (sizeof ExecPgm->Name[0] * ExecPgm->NameLength)); DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name); - /* - * Check if program name is internal - * (Is this correct? Debug is in the registry too) - */ - if(0 == _wcsicmp(L"DEBUG", Name)) + /* Lookup Name in the registry */ + Status = SmLookupSubsystem (Name, + Data, + & DataLength, + & DataType, + TRUE); /* expand */ + if(NT_SUCCESS(Status)) { - /* - * Initialize DBGSS. - * NOTE: probably in early prototypes it was an - * independent process; now it is embedded in the - * SM for performance or security. - */ - Request->SmHeader.Status = SmInitializeDbgSs(); - } - else - { - WCHAR Data [MAX_PATH + 1] = {0}; - ULONG DataLength = sizeof Data; - ULONG DataType = REG_EXPAND_SZ; - - /* Lookup Name in the registry */ - Status = SmLookupSubsystem (Name, - Data, - & DataLength, - & DataType, - TRUE); /* expand */ - if(NT_SUCCESS(Status)) + /* Is the subsystem definition non-empty? */ + if (DataLength > sizeof Data[0]) { WCHAR ImagePath [MAX_PATH + 1] = {0}; + PWCHAR CommandLine = ImagePath; + RTL_PROCESS_INFO ProcessInfo = {0}; wcscpy (ImagePath, L"\\??\\"); wcscat (ImagePath, Data); - - /* Create native process */ - Request->SmHeader.Status = SmCreateUserProcess(ImagePath, - L"", /* FIXME */ - FALSE, /* wait */ - NULL, - FALSE, /* terminate */ - NULL); - }else{ - Request->SmHeader.Status = Status; + /* + * Look for the beginning of the command line. + */ + for (; (*CommandLine != L'\0') && (*CommandLine != L' '); + CommandLine ++); + for (; *CommandLine == L' '; CommandLine ++) + { + *CommandLine = L'\0'; + } + /* + * Create a native process (suspended). + */ + ProcessInfo.Size = sizeof ProcessInfo; + Request->SmHeader.Status = + SmCreateUserProcess(ImagePath, + CommandLine, + FALSE, /* wait */ + NULL, /* timeout */ + & ProcessInfo); + if (NT_SUCCESS(Request->SmHeader.Status)) + { + Status = SmCreateClient (& ProcessInfo, Name); + if (NT_SUCCESS(Status)) + { + Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL); + if (!NT_SUCCESS(Status)) + { + //Status = SmDestroyClient TODO + } + } else { + DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n", + __FUNCTION__, Status); + } + } } + else + { + /* + * OK, the definition is empty, but check + * if it is the name of an embedded subsystem. + */ + if(0 == _wcsicmp(L"DEBUG", Name)) + { + /* + * Initialize the embedded DBGSS. + */ + Request->SmHeader.Status = SmInitializeDbgSs(); + } + else + { + /* + * Badly defined subsystem. Check the registry! + */ + Request->SmHeader.Status = STATUS_NOT_FOUND; + } + } + } else { + /* It couldn't lookup the Name! */ + Request->SmHeader.Status = Status; } } - else - { - Request->SmHeader.Status = Status = STATUS_INVALID_PARAMETER; - } return Status; } diff --git a/reactos/subsys/smss/smss.c b/reactos/subsys/smss/smss.c index 03d8d37b212..627677a1c85 100644 --- a/reactos/subsys/smss/smss.c +++ b/reactos/subsys/smss/smss.c @@ -30,16 +30,18 @@ #define NDEBUG #include -HANDLE SmSsProcessId = 0; +ULONG SmSsProcessId = 0; /* Native image's entry point */ VOID STDCALL NtProcessStartup(PPEB Peb) { - NTSTATUS Status; + NTSTATUS Status = STATUS_SUCCESS; PROCESS_BASIC_INFORMATION PBI = {0}; +PrintString("*** EXPERIMENTAL ***\n"); + PrintString("ReactOS Session Manager %s (Build %s)\n", KERNEL_RELEASE_STR, KERNEL_VERSION_BUILD_STR); @@ -52,7 +54,7 @@ NtProcessStartup(PPEB Peb) NULL); if(NT_SUCCESS(Status)) { - SmSsProcessId = PBI.UniqueProcessId; + SmSsProcessId = (ULONG) PBI.UniqueProcessId; } /* Initialize the system */ Status = InitSessionManager(); diff --git a/reactos/subsys/smss/smss.h b/reactos/subsys/smss/smss.h index 6b1bb4018af..bc099bf1d36 100644 --- a/reactos/subsys/smss/smss.h +++ b/reactos/subsys/smss/smss.h @@ -6,11 +6,8 @@ #include #include -#define CHILD_CSRSS 0 -#define CHILD_WINLOGON 1 - /* smss.c */ -extern HANDLE SmSsProcessId; +extern ULONG SmSsProcessId; /* init.c */ NTSTATUS InitSessionManager(VOID); @@ -63,8 +60,7 @@ NTSTATUS STDCALL SmCreateUserProcess(LPWSTR ImagePath, LPWSTR CommandLine, BOOLEAN WaitForIt, PLARGE_INTEGER Timeout OPTIONAL, - BOOLEAN TerminateIt, - PRTL_PROCESS_INFO ProcessInfo OPTIONAL); + PRTL_PROCESS_INFO UserProcessInfo OPTIONAL); NTSTATUS STDCALL SmLookupSubsystem (IN PWSTR Name, IN OUT PWSTR Data, @@ -80,22 +76,30 @@ NTSTATUS FASTCALL SmCompSes(PSM_PORT_MESSAGE); NTSTATUS FASTCALL SmQryInfo(PSM_PORT_MESSAGE); /* client.c */ +#define SM_CLIENT_FLAG_CANDIDATE 0x8000 +#define SM_CLIENT_FLAG_INITIALIZED 0x0001 +#define SM_CLIENT_FLAG_REQUIRED 0x0002 typedef struct _SM_CLIENT_DATA { - USHORT SubsystemId; - BOOL Initialized; - HANDLE ServerProcess; - HANDLE ApiPort; - HANDLE ApiPortThread; - HANDLE SbApiPort; - WCHAR SbApiPortName [SM_SB_NAME_MAX_LENGTH]; - struct _SM_CLIENT_DATA * Next; + RTL_CRITICAL_SECTION Lock; + WCHAR ProgramName [SM_SB_NAME_MAX_LENGTH]; + USHORT SubsystemId; + WORD Flags; + WORD Unused; + ULONG ServerProcessId; + HANDLE ServerProcess; + HANDLE ApiPort; + HANDLE ApiPortThread; + HANDLE SbApiPort; + WCHAR SbApiPortName [SM_SB_NAME_MAX_LENGTH]; + struct _SM_CLIENT_DATA * Next; } SM_CLIENT_DATA, *PSM_CLIENT_DATA; -NTSTATUS SmInitializeClientManagement(VOID); -NTSTATUS STDCALL SmCreateClient(PSM_PORT_MESSAGE,PSM_CLIENT_DATA*); -NTSTATUS STDCALL SmDestroyClient(ULONG); -NTSTATUS STDCALL SmCompleteClientInitialization (HANDLE hProcess); +NTSTATUS SmInitializeClientManagement (VOID); +NTSTATUS STDCALL SmCreateClient (PRTL_PROCESS_INFO,PWSTR); +NTSTATUS STDCALL SmDestroyClient (ULONG); +NTSTATUS STDCALL SmBeginClientInitialization (PSM_PORT_MESSAGE,PSM_CLIENT_DATA*); +NTSTATUS STDCALL SmCompleteClientInitialization (ULONG); NTSTATUS FASTCALL SmGetClientBasicInformation (PSM_BASIC_INFORMATION); NTSTATUS FASTCALL SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION);