mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 04:13:31 +00:00
SM: change the way sessions are managed.
(it may be buggy) svn path=/trunk/; revision=15467
This commit is contained in:
+219
-95
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+12
-12
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+137
-67
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,16 +30,18 @@
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
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();
|
||||
|
||||
+22
-18
@@ -6,11 +6,8 @@
|
||||
#include <sm/api.h>
|
||||
#include <sm/helper.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user