mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 19:55:41 +00:00
SM: simplify and fix client (subsystem servers) management.
svn path=/trunk/; revision=17567
This commit is contained in:
parent
40a9efb724
commit
3c693f90bc
6 changed files with 288 additions and 143 deletions
|
@ -31,12 +31,14 @@
|
||||||
|
|
||||||
/* Private ADT */
|
/* Private ADT */
|
||||||
|
|
||||||
|
#define SM_MAX_CLIENT_COUNT 16
|
||||||
|
#define SM_INVALID_CLIENT_INDEX -1
|
||||||
|
|
||||||
struct _SM_CLIENT_DIRECTORY
|
struct _SM_CLIENT_DIRECTORY
|
||||||
{
|
{
|
||||||
RTL_CRITICAL_SECTION Lock;
|
RTL_CRITICAL_SECTION Lock;
|
||||||
ULONG Count;
|
ULONG Count;
|
||||||
PSM_CLIENT_DATA Client;
|
PSM_CLIENT_DATA Client [SM_MAX_CLIENT_COUNT];
|
||||||
PSM_CLIENT_DATA CandidateClient;
|
PSM_CLIENT_DATA CandidateClient;
|
||||||
|
|
||||||
} SmpClientDirectory;
|
} SmpClientDirectory;
|
||||||
|
@ -51,7 +53,7 @@ SmInitializeClientManagement (VOID)
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s called\n", __FUNCTION__);
|
||||||
RtlInitializeCriticalSection(& SmpClientDirectory.Lock);
|
RtlInitializeCriticalSection(& SmpClientDirectory.Lock);
|
||||||
SmpClientDirectory.Count = 0;
|
SmpClientDirectory.Count = 0;
|
||||||
SmpClientDirectory.Client = NULL;
|
RtlZeroMemory (SmpClientDirectory.Client, sizeof SmpClientDirectory.Client);
|
||||||
SmpClientDirectory.CandidateClient = NULL;
|
SmpClientDirectory.CandidateClient = NULL;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -66,56 +68,85 @@ SmpSetClientInitialized (PSM_CLIENT_DATA Client)
|
||||||
Client->Flags |= SM_CLIENT_FLAG_INITIALIZED;
|
Client->Flags |= SM_CLIENT_FLAG_INITIALIZED;
|
||||||
}
|
}
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SmpLookupClient/2 PRIVATE
|
* SmpGetFirstFreeClientEntry/0 PRIVATE
|
||||||
|
*
|
||||||
|
* NOTE: call it holding SmpClientDirectory.Lock only
|
||||||
|
*/
|
||||||
|
static INT STDCALL SmpGetFirstFreeClientEntry (VOID)
|
||||||
|
{
|
||||||
|
INT ClientIndex = 0;
|
||||||
|
|
||||||
|
DPRINT("SM: %s called\n", __FUNCTION__);
|
||||||
|
|
||||||
|
if (SmpClientDirectory.Count < SM_MAX_CLIENT_COUNT)
|
||||||
|
{
|
||||||
|
for (ClientIndex = 0;
|
||||||
|
(ClientIndex < SM_MAX_CLIENT_COUNT);
|
||||||
|
ClientIndex ++)
|
||||||
|
{
|
||||||
|
if (NULL == SmpClientDirectory.Client[ClientIndex])
|
||||||
|
{
|
||||||
|
DPRINT("SM: %s => %d\n", __FUNCTION__, ClientIndex);
|
||||||
|
return ClientIndex; // found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SM_INVALID_CLIENT_INDEX; // full!
|
||||||
|
}
|
||||||
|
/**********************************************************************
|
||||||
|
* SmpLookupClient/1 PRIVATE
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* Lookup the subsystem server descriptor given its image ID.
|
* Lookup the subsystem server descriptor (client data) given its
|
||||||
|
* base image ID.
|
||||||
*
|
*
|
||||||
* ARGUMENTS
|
* ARGUMENTS
|
||||||
* SubsystemId: IMAGE_SUBSYSTEM_xxx
|
* 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
|
* RETURN VALUES
|
||||||
* NULL on error; otherwise a pointer to the SM_CLIENT_DATA
|
* SM_INVALID_CLIENT_INDEX on error;
|
||||||
* looked up object.
|
* otherwise an index in the range (0..SM_MAX_CLIENT_COUNT).
|
||||||
*
|
*
|
||||||
* WARNING
|
* WARNING
|
||||||
* SmpClientDirectory.Lock must be held by the caller.
|
* SmpClientDirectory.Lock must be held by the caller.
|
||||||
*/
|
*/
|
||||||
static PSM_CLIENT_DATA FASTCALL
|
static INT FASTCALL
|
||||||
SmpLookupClient (USHORT SubsystemId,
|
SmpLookupClient (USHORT SubsystemId)
|
||||||
PSM_CLIENT_DATA * Parent)
|
|
||||||
{
|
{
|
||||||
PSM_CLIENT_DATA Client = NULL;
|
INT ClientIndex = 0;
|
||||||
|
|
||||||
DPRINT("SM: %s(%d) called\n", __FUNCTION__, SubsystemId);
|
DPRINT("SM: %s(%d) called\n", __FUNCTION__, SubsystemId);
|
||||||
|
|
||||||
if(NULL != Parent)
|
if (0 != SmpClientDirectory.Count)
|
||||||
{
|
{
|
||||||
*Parent = NULL;
|
for (ClientIndex = 0; (ClientIndex < SM_MAX_CLIENT_COUNT); ClientIndex ++)
|
||||||
}
|
|
||||||
if (SmpClientDirectory.Count > 0)
|
|
||||||
{
|
{
|
||||||
Client = SmpClientDirectory.Client;
|
if (NULL != SmpClientDirectory.Client[ClientIndex])
|
||||||
while (NULL != Client)
|
|
||||||
{
|
{
|
||||||
DPRINT("SM: %s: Client==%08lx\n", __FUNCTION__, Client);
|
if (SubsystemId == SmpClientDirectory.Client[ClientIndex]->SubsystemId)
|
||||||
if (SubsystemId == Client->SubsystemId)
|
|
||||||
{
|
{
|
||||||
DPRINT("SM: %s: FOUND Client==%08lx\n", __FUNCTION__, Client);
|
return ClientIndex;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(NULL != Parent)
|
|
||||||
{
|
|
||||||
*Parent = Client;
|
|
||||||
}
|
|
||||||
Client = Client->Next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Client;
|
}
|
||||||
|
}
|
||||||
|
return SM_INVALID_CLIENT_INDEX;
|
||||||
|
}
|
||||||
|
/**********************************************************************
|
||||||
|
* SmpDestroyClientObject/2 PRIVATE
|
||||||
|
*
|
||||||
|
* WARNING
|
||||||
|
* SmpClientDirectory.Lock must be held by the caller.
|
||||||
|
*/
|
||||||
|
static NTSTATUS STDCALL
|
||||||
|
SmpDestroyClientObject (PSM_CLIENT_DATA Client, NTSTATUS DestroyReason)
|
||||||
|
{
|
||||||
|
DPRINT("SM:%s(%08lx,%08lx) called\n", __FUNCTION__, DestroyReason);
|
||||||
|
/* TODO: send shutdown to the SB port */
|
||||||
|
NtTerminateProcess (Client->ServerProcess, DestroyReason);
|
||||||
|
RtlFreeHeap (SmpHeap, 0, Client);
|
||||||
|
-- SmpClientDirectory.Count;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SmBeginClientInitialization/1
|
* SmBeginClientInitialization/1
|
||||||
|
@ -138,15 +169,17 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);
|
PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);
|
||||||
ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
|
ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
|
||||||
|
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
|
||||||
|
|
||||||
|
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s(%08lx,%08lx) called\n", __FUNCTION__,
|
||||||
|
Request, ClientData);
|
||||||
|
|
||||||
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
/*
|
/*
|
||||||
* Is there a subsystem bootstrap in progress?
|
* Is there a subsystem bootstrap in progress?
|
||||||
*/
|
*/
|
||||||
if (SmpClientDirectory.CandidateClient)
|
if (NULL != SmpClientDirectory.CandidateClient)
|
||||||
{
|
{
|
||||||
PROCESS_BASIC_INFORMATION pbi;
|
PROCESS_BASIC_INFORMATION pbi;
|
||||||
|
|
||||||
|
@ -164,7 +197,6 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlFreeHeap (SmpHeap, 0, SmpClientDirectory.CandidateClient);
|
|
||||||
DPRINT1("SM: %s: subsys booting with no descriptor!\n", __FUNCTION__);
|
DPRINT1("SM: %s: subsys booting with no descriptor!\n", __FUNCTION__);
|
||||||
Status = STATUS_NOT_FOUND;
|
Status = STATUS_NOT_FOUND;
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
@ -173,14 +205,28 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
/*
|
/*
|
||||||
* Check if a client for the ID already exist.
|
* Check if a client for the ID already exist.
|
||||||
*/
|
*/
|
||||||
if (SmpLookupClient(ConnectData->SubSystemId, NULL))
|
if (SM_INVALID_CLIENT_INDEX != SmpLookupClient(ConnectData->SubSystemId))
|
||||||
{
|
{
|
||||||
DPRINT("SM: %s: attempt to register again subsystem %d.\n",
|
DPRINT("SM: %s: attempt to register again subsystem %d.\n",
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
ConnectData->SubSystemId);
|
ConnectData->SubSystemId);
|
||||||
|
// TODO something else to do here?
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Check if a free entry exists in SmpClientDirectory.Client[].
|
||||||
|
*/
|
||||||
|
ClientIndex = SmpGetFirstFreeClientEntry();
|
||||||
|
if (SM_INVALID_CLIENT_INDEX == ClientIndex)
|
||||||
|
{
|
||||||
|
DPRINT("SM: %s: SM_INVALID_CLIENT_INDEX == ClientIndex ", __FUNCTION__);
|
||||||
|
SmpDestroyClientObject (SmpClientDirectory.CandidateClient, STATUS_NO_MEMORY);
|
||||||
|
SmpClientDirectory.CandidateClient = NULL;
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK! */
|
||||||
DPRINT("SM: %s: registering subsystem ID=%d \n",
|
DPRINT("SM: %s: registering subsystem ID=%d \n",
|
||||||
__FUNCTION__, ConnectData->SubSystemId);
|
__FUNCTION__, ConnectData->SubSystemId);
|
||||||
|
|
||||||
|
@ -191,12 +237,13 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
/* SM && DBG auto-initializes; other subsystems are required to call
|
/* SM && DBG auto-initializes; other subsystems are required to call
|
||||||
* SM_API_COMPLETE_SESSION via SMDLL. */
|
* SM_API_COMPLETE_SESSION via SMDLL. */
|
||||||
if ((IMAGE_SUBSYSTEM_NATIVE == SmpClientDirectory.CandidateClient->SubsystemId) ||
|
if ((IMAGE_SUBSYSTEM_NATIVE == SmpClientDirectory.CandidateClient->SubsystemId) ||
|
||||||
(IMAGE_SUBSYSTEM_UNKNOWN == SmpClientDirectory.CandidateClient->SubsystemId))
|
((USHORT)-1 == SmpClientDirectory.CandidateClient->SubsystemId))
|
||||||
{
|
{
|
||||||
SmpSetClientInitialized (SmpClientDirectory.CandidateClient);
|
SmpSetClientInitialized (SmpClientDirectory.CandidateClient);
|
||||||
}
|
}
|
||||||
if (SbApiPortNameSize > 0)
|
if (SbApiPortNameSize > 0)
|
||||||
{
|
{
|
||||||
|
/* Only external servers have an SB port */
|
||||||
RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName,
|
RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName,
|
||||||
ConnectData->SbName,
|
ConnectData->SbName,
|
||||||
SbApiPortNameSize);
|
SbApiPortNameSize);
|
||||||
|
@ -205,18 +252,7 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
* Insert the new descriptor in the
|
* Insert the new descriptor in the
|
||||||
* client directory.
|
* client directory.
|
||||||
*/
|
*/
|
||||||
if (NULL == SmpClientDirectory.Client)
|
SmpClientDirectory.Client [ClientIndex] = SmpClientDirectory.CandidateClient;
|
||||||
{
|
|
||||||
SmpClientDirectory.Client = SmpClientDirectory.CandidateClient;
|
|
||||||
} else {
|
|
||||||
PSM_CLIENT_DATA pCD = NULL;
|
|
||||||
|
|
||||||
for (pCD=SmpClientDirectory.Client;
|
|
||||||
(NULL != pCD->Next);
|
|
||||||
pCD = pCD->Next);
|
|
||||||
pCD->Next = SmpClientDirectory.CandidateClient;
|
|
||||||
}
|
|
||||||
SmpClientDirectory.CandidateClient->Next = NULL;
|
|
||||||
/*
|
/*
|
||||||
* Increment the number of active subsystems.
|
* Increment the number of active subsystems.
|
||||||
*/
|
*/
|
||||||
|
@ -233,6 +269,7 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
*/
|
*/
|
||||||
SmpClientDirectory.CandidateClient = NULL;
|
SmpClientDirectory.CandidateClient = NULL;
|
||||||
|
|
||||||
|
/* Done */
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -248,29 +285,100 @@ NTSTATUS STDCALL
|
||||||
SmCompleteClientInitialization (ULONG ProcessId)
|
SmCompleteClientInitialization (ULONG ProcessId)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_NOT_FOUND;
|
NTSTATUS Status = STATUS_NOT_FOUND;
|
||||||
PSM_CLIENT_DATA Client = NULL;
|
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
|
||||||
|
|
||||||
DPRINT("SM: %s(%lu) called\n", __FUNCTION__, ProcessId);
|
DPRINT("SM: %s(%lu) called\n", __FUNCTION__, ProcessId);
|
||||||
|
|
||||||
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
if (SmpClientDirectory.Count > 0)
|
if (SmpClientDirectory.Count > 0)
|
||||||
{
|
{
|
||||||
Client = SmpClientDirectory.Client;
|
for (ClientIndex = 0; ClientIndex < SM_MAX_CLIENT_COUNT; ClientIndex ++)
|
||||||
while (NULL != Client)
|
|
||||||
{
|
{
|
||||||
if (ProcessId == Client->ServerProcessId)
|
if ((NULL != SmpClientDirectory.Client [ClientIndex]) &&
|
||||||
|
(ProcessId == SmpClientDirectory.Client [ClientIndex]->ServerProcessId))
|
||||||
{
|
{
|
||||||
SmpSetClientInitialized (Client);
|
SmpSetClientInitialized (SmpClientDirectory.Client [ClientIndex]);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Client = Client->Next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
/**********************************************************************
|
||||||
|
* SmpDestroyClientByClientIndex/1 PRIVATE
|
||||||
|
*/
|
||||||
|
static NTSTATUS STDCALL
|
||||||
|
SmpDestroyClientByClientIndex (INT ClientIndex)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PSM_CLIENT_DATA Client = NULL;
|
||||||
|
|
||||||
|
DPRINT("SM: %s(%d) called\n", __FUNCTION__, ClientIndex);
|
||||||
|
|
||||||
|
if (SM_INVALID_CLIENT_INDEX == ClientIndex)
|
||||||
|
{
|
||||||
|
DPRINT1("SM: %s: SM_INVALID_CLIENT_INDEX == ClientIndex!\n",
|
||||||
|
__FUNCTION__);
|
||||||
|
Status = STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client = SmpClientDirectory.Client [ClientIndex];
|
||||||
|
SmpClientDirectory.Client [ClientIndex] = NULL;
|
||||||
|
if (NULL != Client)
|
||||||
|
{
|
||||||
|
Status = SmpDestroyClientObject (Client, STATUS_SUCCESS);
|
||||||
|
} else {
|
||||||
|
DPRINT("SM:%s: NULL == Client[%d]!\n", __FUNCTION__,
|
||||||
|
ClientIndex);
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
/**********************************************************************
|
||||||
|
* SmpTimeoutCandidateClient/1
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* Give the candidate client time to bootstrap and complete
|
||||||
|
* session initialization. If the client fails in any way,
|
||||||
|
* drop the pending client and kill the process.
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* x: HANDLE for the candidate process.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* NONE.
|
||||||
|
*/
|
||||||
|
static VOID STDCALL SmpTimeoutCandidateClient (PVOID x)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
HANDLE CandidateClientProcessHandle = (HANDLE) x;
|
||||||
|
LARGE_INTEGER TimeOut;
|
||||||
|
|
||||||
|
DPRINT("SM: %s(%lx) called\n", __FUNCTION__, x);
|
||||||
|
|
||||||
|
TimeOut.QuadPart = (LONGLONG) -300000000L; // 30s
|
||||||
|
Status = NtWaitForSingleObject (CandidateClientProcessHandle,
|
||||||
|
FALSE,
|
||||||
|
& TimeOut);
|
||||||
|
if (STATUS_TIMEOUT == Status)
|
||||||
|
{
|
||||||
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
if (NULL != SmpClientDirectory.CandidateClient)
|
||||||
|
{
|
||||||
|
DPRINT("SM:%s: destroy candidate %08lx\n", __FUNCTION__,
|
||||||
|
SmpClientDirectory.CandidateClient);
|
||||||
|
Status = SmpDestroyClientObject (SmpClientDirectory.CandidateClient,
|
||||||
|
STATUS_TIMEOUT);
|
||||||
|
SmpClientDirectory.CandidateClient = NULL;
|
||||||
|
}
|
||||||
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
}
|
||||||
|
NtTerminateThread (NtCurrentThread(), Status);
|
||||||
|
}
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SmpCreateClient/1
|
* SmpCreateClient/1
|
||||||
*
|
*
|
||||||
|
@ -295,8 +403,7 @@ SmCreateClient (PRTL_USER_PROCESS_INFORMATION ProcessInfo, PWSTR ProgramName)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
DPRINT("SM: %s(%lx, %S) called\n", __FUNCTION__, ProcessInfo->ProcessHandle, ProgramName);
|
||||||
DPRINT("SM: %s(%lx) called\n", __FUNCTION__, ProcessInfo->ProcessHandle);
|
|
||||||
|
|
||||||
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
/*
|
/*
|
||||||
|
@ -304,6 +411,16 @@ SmCreateClient (PRTL_USER_PROCESS_INFORMATION ProcessInfo, PWSTR ProgramName)
|
||||||
*/
|
*/
|
||||||
if (NULL == SmpClientDirectory.CandidateClient)
|
if (NULL == SmpClientDirectory.CandidateClient)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Check if there exist a free entry in the
|
||||||
|
* SmpClientDirectory.Client array.
|
||||||
|
*/
|
||||||
|
if (SM_INVALID_CLIENT_INDEX == SmpGetFirstFreeClientEntry())
|
||||||
|
{
|
||||||
|
DPRINT("SM: %s(%lx): out of memory!\n",
|
||||||
|
__FUNCTION__, ProcessInfo->ProcessHandle);
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Allocate the storage for client data
|
* Allocate the storage for client data
|
||||||
*/
|
*/
|
||||||
|
@ -319,6 +436,8 @@ SmCreateClient (PRTL_USER_PROCESS_INFORMATION ProcessInfo, PWSTR ProgramName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DPRINT("SM:%s(%08lx,%S): candidate is %08lx\n", __FUNCTION__,
|
||||||
|
ProcessInfo, ProgramName, SmpClientDirectory.CandidateClient);
|
||||||
/* Initialize the candidate client. */
|
/* Initialize the candidate client. */
|
||||||
RtlInitializeCriticalSection(& SmpClientDirectory.CandidateClient->Lock);
|
RtlInitializeCriticalSection(& SmpClientDirectory.CandidateClient->Lock);
|
||||||
SmpClientDirectory.CandidateClient->ServerProcess =
|
SmpClientDirectory.CandidateClient->ServerProcess =
|
||||||
|
@ -333,16 +452,35 @@ SmCreateClient (PRTL_USER_PROCESS_INFORMATION ProcessInfo, PWSTR ProgramName)
|
||||||
SM_SB_NAME_MAX_LENGTH);
|
SM_SB_NAME_MAX_LENGTH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DPRINT1("SM: %s: CandidateClient pending!\n", __FUNCTION__);
|
DPRINT1("SM: %s: CandidateClient %08lx pending!\n", __FUNCTION__,
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
SmpClientDirectory.CandidateClient);
|
||||||
Status = STATUS_DEVICE_BUSY;
|
Status = STATUS_DEVICE_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
|
||||||
|
/* Create the timeout thread for external subsystems */
|
||||||
|
if (_wcsicmp (ProgramName, L"Session Manager") && _wcsicmp (ProgramName, L"Debug"))
|
||||||
|
{
|
||||||
|
Status = RtlCreateUserThread (NtCurrentProcess(),
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(PTHREAD_START_ROUTINE) SmpTimeoutCandidateClient,
|
||||||
|
SmpClientDirectory.CandidateClient->ServerProcess,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("SM:%s: RtlCreateUserThread() failed (Status=%08lx)\n",
|
||||||
|
__FUNCTION__, Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SmpDestroyClient/1
|
* SmpDestroyClient/1
|
||||||
*
|
*
|
||||||
|
@ -354,41 +492,19 @@ NTSTATUS STDCALL
|
||||||
SmDestroyClient (ULONG SubsystemId)
|
SmDestroyClient (ULONG SubsystemId)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PSM_CLIENT_DATA Parent = NULL;
|
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
|
||||||
PSM_CLIENT_DATA Client = NULL;
|
|
||||||
|
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s(%lu) called\n", __FUNCTION__, SubsystemId);
|
||||||
|
|
||||||
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
Client = SmpLookupClient (SubsystemId, & Parent);
|
ClientIndex = SmpLookupClient (SubsystemId);
|
||||||
if(NULL == Client)
|
if (SM_INVALID_CLIENT_INDEX == ClientIndex)
|
||||||
{
|
{
|
||||||
DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
|
DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
|
||||||
__FUNCTION__, SubsystemId);
|
__FUNCTION__, SubsystemId);
|
||||||
Status = STATUS_NOT_FOUND;
|
return STATUS_NOT_FOUND;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 1st in the list? */
|
|
||||||
if(NULL == Parent)
|
|
||||||
{
|
|
||||||
SmpClientDirectory.Client = Client->Next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(NULL != Parent)
|
|
||||||
{
|
|
||||||
Parent->Next = Client->Next;
|
|
||||||
} else {
|
|
||||||
DPRINT1("SM: %s: n-th has no parent!\n", __FUNCTION__);
|
|
||||||
Status = STATUS_UNSUCCESSFUL; /* FIXME */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* TODO: send shutdown or kill */
|
|
||||||
NtTerminateProcess (Client->ServerProcess, 0); //FIXME
|
|
||||||
RtlFreeHeap (SmpHeap, 0, Client);
|
|
||||||
-- SmpClientDirectory.Count;
|
|
||||||
}
|
}
|
||||||
|
Status = SmpDestroyClientByClientIndex (ClientIndex);
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -401,10 +517,10 @@ SmDestroyClient (ULONG SubsystemId)
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
|
SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
|
||||||
{
|
{
|
||||||
|
INT ClientIndex = 0;
|
||||||
INT Index = 0;
|
INT Index = 0;
|
||||||
PSM_CLIENT_DATA ClientData = NULL;
|
|
||||||
|
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, i);
|
||||||
|
|
||||||
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
|
||||||
|
@ -413,13 +529,16 @@ SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
|
||||||
|
|
||||||
if (SmpClientDirectory.Count > 0)
|
if (SmpClientDirectory.Count > 0)
|
||||||
{
|
{
|
||||||
ClientData = SmpClientDirectory.Client;
|
for (ClientIndex = 0; (ClientIndex < SM_MAX_CLIENT_COUNT); ClientIndex ++)
|
||||||
while ((NULL != ClientData) && (Index < SM_QRYINFO_MAX_SS_COUNT))
|
|
||||||
{
|
{
|
||||||
i->SubSystem[Index].Id = ClientData->SubsystemId;
|
if ((NULL != SmpClientDirectory.Client [ClientIndex]) &&
|
||||||
i->SubSystem[Index].Flags = ClientData->Flags;
|
(Index < SM_QRYINFO_MAX_SS_COUNT))
|
||||||
i->SubSystem[Index].ProcessId = ClientData->ServerProcessId;
|
{
|
||||||
ClientData = ClientData->Next;
|
i->SubSystem[Index].Id = SmpClientDirectory.Client [ClientIndex]->SubsystemId;
|
||||||
|
i->SubSystem[Index].Flags = SmpClientDirectory.Client [ClientIndex]->Flags;
|
||||||
|
i->SubSystem[Index].ProcessId = SmpClientDirectory.Client [ClientIndex]->ServerProcessId;
|
||||||
|
++ Index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,22 +553,22 @@ NTSTATUS FASTCALL
|
||||||
SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)
|
SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PSM_CLIENT_DATA ClientData = NULL;
|
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
|
||||||
|
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, i);
|
||||||
|
|
||||||
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
|
||||||
ClientData = SmpLookupClient (i->SubSystemId, NULL);
|
ClientIndex = SmpLookupClient (i->SubSystemId);
|
||||||
if (NULL == ClientData)
|
if (SM_INVALID_CLIENT_INDEX == ClientIndex)
|
||||||
{
|
{
|
||||||
Status = STATUS_NOT_FOUND;
|
Status = STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i->Flags = ClientData->Flags;
|
i->Flags = SmpClientDirectory.Client [ClientIndex]->Flags;
|
||||||
i->ProcessId = ClientData->ServerProcessId;
|
i->ProcessId = SmpClientDirectory.Client [ClientIndex]->ServerProcessId;
|
||||||
RtlCopyMemory (i->NameSpaceRootNode,
|
RtlCopyMemory (i->NameSpaceRootNode,
|
||||||
ClientData->SbApiPortName,
|
SmpClientDirectory.Client [ClientIndex]->SbApiPortName,
|
||||||
(SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0])));
|
(SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0])));
|
||||||
}
|
}
|
||||||
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
HANDLE DbgSsApiPort = (HANDLE) 0;
|
HANDLE DbgSsApiPort = (HANDLE) 0;
|
||||||
HANDLE DbgUiApiPort = (HANDLE) 0;
|
HANDLE DbgUiApiPort = (HANDLE) 0;
|
||||||
|
HANDLE hSmDbgApiPort = (HANDLE) 0;
|
||||||
|
|
||||||
/* FUNCTIONS *********************************************************/
|
/* FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
@ -135,8 +136,21 @@ SmInitializeDbgSs (VOID)
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
HANDLE hDbgSsApiPortThread = (HANDLE) 0;
|
HANDLE hDbgSsApiPortThread = (HANDLE) 0;
|
||||||
|
|
||||||
|
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s called\n", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Self register */
|
||||||
|
#if 0
|
||||||
|
Status = SmRegisterInternalSubsystem (L"Debug",
|
||||||
|
(USHORT)-1,
|
||||||
|
& hSmDbgApiPort);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("DBG:%s: SmRegisterInternalSubsystem failed with Status=%08lx\n",
|
||||||
|
__FUNCTION__, Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Create the \DbgSsApiPort object (LPC) */
|
/* Create the \DbgSsApiPort object (LPC) */
|
||||||
Status = SmpCreatePT(& DbgSsApiPort,
|
Status = SmpCreatePT(& DbgSsApiPort,
|
||||||
SM_DBGSS_PORT_NAME,
|
SM_DBGSS_PORT_NAME,
|
||||||
|
|
|
@ -39,22 +39,21 @@ HANDLE hSmApiPort = (HANDLE) 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SmpRegisterSmss/0
|
* SmRegisterInternalSubsystem/3
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* Make smss register with itself for IMAGE_SUBSYSTEM_NATIVE
|
* Register with itself for ImageSubsystemId
|
||||||
* (programmatically). This also opens hSmApiPort to be used
|
* (programmatically).
|
||||||
* in loading required subsystems.
|
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS STDCALL SmRegisterInternalSubsystem (LPWSTR PgmName,
|
||||||
static NTSTATUS
|
USHORT ImageSubsystemId,
|
||||||
SmpRegisterSmss(VOID)
|
PHANDLE ApiPort)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
RTL_USER_PROCESS_INFORMATION ProcessInfo;
|
RTL_USER_PROCESS_INFORMATION ProcessInfo;
|
||||||
|
|
||||||
|
|
||||||
DPRINT("SM: %s called\n",__FUNCTION__);
|
DPRINT("SM: %s(%S,%d) called\n",__FUNCTION__, PgmName, ImageSubsystemId);
|
||||||
|
|
||||||
RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo);
|
RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo);
|
||||||
ProcessInfo.Size = sizeof ProcessInfo;
|
ProcessInfo.Size = sizeof ProcessInfo;
|
||||||
|
@ -62,38 +61,37 @@ SmpRegisterSmss(VOID)
|
||||||
ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId;
|
ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId;
|
||||||
DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n",
|
DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n",
|
||||||
__FUNCTION__,ProcessInfo.ProcessHandle);
|
__FUNCTION__,ProcessInfo.ProcessHandle);
|
||||||
Status = SmCreateClient (& ProcessInfo, L"Session Manager");
|
Status = SmCreateClient (& ProcessInfo, PgmName);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
UNICODE_STRING SbApiPortName = {0,0,NULL};
|
UNICODE_STRING SbApiPortName = {0,0,NULL};
|
||||||
|
|
||||||
RtlInitUnicodeString (& SbApiPortName, L"");
|
RtlInitUnicodeString (& SbApiPortName, L"");
|
||||||
Status = SmConnectApiPort(& SbApiPortName,
|
Status = SmConnectApiPort(& SbApiPortName,
|
||||||
(HANDLE) -1, /* SM has no SB port */
|
(HANDLE) -1, /* internal SS have no SB port */
|
||||||
IMAGE_SUBSYSTEM_NATIVE,
|
ImageSubsystemId,
|
||||||
& hSmApiPort);
|
ApiPort);
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",
|
DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",
|
||||||
__FUNCTION__,Status);
|
__FUNCTION__,Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
DPRINT("SM self registered\n");
|
DPRINT("SM:%s: %S self registered\n", __FUNCTION__, PgmName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
|
DPRINT1("SM: %s: SmCreateClient(%S) failed (Status=0x%08lx)\n",
|
||||||
__FUNCTION__, Status);
|
__FUNCTION__, PgmName, Status);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Note that you don't need to call complete session
|
* Note that you don't need to call complete session
|
||||||
* because connection handling code autocompletes
|
* here because connection handling code autocompletes
|
||||||
* the client structure for IMAGE_SUBSYSTEM_NATIVE.
|
* the client structure for IMAGE_SUBSYSTEM_NATIVE and
|
||||||
|
* -1.
|
||||||
*/
|
*/
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* SmpLoadRequiredSubsystems/0
|
* SmpLoadRequiredSubsystems/0
|
||||||
*/
|
*/
|
||||||
|
@ -157,15 +155,27 @@ SmLoadSubsystems(VOID)
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
DPRINT("SM: loading subsystems\n");
|
DPRINT("SM: loading subsystems...\n");
|
||||||
|
|
||||||
/* SM self registers */
|
/*
|
||||||
Status = SmpRegisterSmss();
|
* SM self registers: this also opens hSmApiPort to be used
|
||||||
if(!NT_SUCCESS(Status)) return Status;
|
* in loading required subsystems.
|
||||||
|
*/
|
||||||
|
Status = SmRegisterInternalSubsystem (L"Session Manager", IMAGE_SUBSYSTEM_NATIVE, & hSmApiPort);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("SM: SmRegisterInternalSubsystem failed Status=%08lx\n", __FUNCTION__, Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/* Load Required subsystems (Debug Windows) */
|
/* Load Required subsystems (Debug Windows) */
|
||||||
Status = SmpLoadRequiredSubsystems();
|
Status = SmpLoadRequiredSubsystems();
|
||||||
if(!NT_SUCCESS(Status)) return Status;
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("SM: SmpLoadRequiredSubsystems failed Status=%08lx\n", __FUNCTION__, Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/* done */
|
/* done */
|
||||||
|
DPRINT("SM: done loading subsystems\n");
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ SmpCallbackServer (PSM_PORT_MESSAGE Request,
|
||||||
|
|
||||||
DPRINT("SM: %s called\n", __FUNCTION__);
|
DPRINT("SM: %s called\n", __FUNCTION__);
|
||||||
|
|
||||||
if ( (IMAGE_SUBSYSTEM_UNKNOWN == ConnectData->SubSystemId) ||
|
if ( ((USHORT)-1 == ConnectData->SubSystemId) ||
|
||||||
(IMAGE_SUBSYSTEM_NATIVE == ConnectData->SubSystemId))
|
(IMAGE_SUBSYSTEM_NATIVE == ConnectData->SubSystemId))
|
||||||
{
|
{
|
||||||
DPRINT("SM: %s: we do not need calling back SM!\n",
|
DPRINT("SM: %s: we do not need calling back SM!\n",
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
*
|
*
|
||||||
* ARGUMENTS
|
* ARGUMENTS
|
||||||
* ImagePath: bsolute path of the image to run;
|
* ImagePath: absolute path of the image to run;
|
||||||
* CommandLine: arguments and options for ImagePath;
|
* CommandLine: arguments and options for ImagePath;
|
||||||
* WaitForIt: TRUE for boot time processes and FALSE for
|
* WaitForIt: TRUE for boot time processes and FALSE for
|
||||||
* subsystems bootstrapping;
|
* subsystems bootstrapping;
|
||||||
|
@ -215,6 +215,8 @@ SMAPI(SmExecPgm)
|
||||||
Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
|
Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
|
||||||
|
__FUNCTION__, Status);
|
||||||
//Status = SmDestroyClient TODO
|
//Status = SmDestroyClient TODO
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -48,6 +48,7 @@ NTSTATUS SmCreatePagingFiles(VOID);
|
||||||
NTSTATUS SmInitializeRegistry(VOID);
|
NTSTATUS SmInitializeRegistry(VOID);
|
||||||
|
|
||||||
/* initss.c */
|
/* initss.c */
|
||||||
|
NTSTATUS STDCALL SmRegisterInternalSubsystem(LPWSTR,USHORT,PHANDLE);
|
||||||
NTSTATUS SmLoadSubsystems(VOID);
|
NTSTATUS SmLoadSubsystems(VOID);
|
||||||
|
|
||||||
/* smapi.c */
|
/* smapi.c */
|
||||||
|
@ -89,7 +90,6 @@ typedef struct _SM_CLIENT_DATA
|
||||||
HANDLE ApiPortThread;
|
HANDLE ApiPortThread;
|
||||||
HANDLE SbApiPort;
|
HANDLE SbApiPort;
|
||||||
WCHAR SbApiPortName [SM_SB_NAME_MAX_LENGTH];
|
WCHAR SbApiPortName [SM_SB_NAME_MAX_LENGTH];
|
||||||
struct _SM_CLIENT_DATA * Next;
|
|
||||||
|
|
||||||
} SM_CLIENT_DATA, *PSM_CLIENT_DATA;
|
} SM_CLIENT_DATA, *PSM_CLIENT_DATA;
|
||||||
NTSTATUS SmInitializeClientManagement (VOID);
|
NTSTATUS SmInitializeClientManagement (VOID);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue