SM: change the way sessions are managed.

(it may be buggy)

svn path=/trunk/; revision=15467
This commit is contained in:
Emanuele Aliberti
2005-05-22 15:54:15 +00:00
parent f4e960c324
commit 6481ed1ea7
9 changed files with 449 additions and 218 deletions
+219 -95
View File
@@ -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 */
+8
View File
@@ -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");
+7 -5
View File
@@ -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);
}
+29 -12
View File
@@ -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
View File
@@ -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.
+10 -6
View File
@@ -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
View File
@@ -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;
}
+5 -3
View File
@@ -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
View File
@@ -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);