client.c
来自「一个类似windows」· C语言 代码 · 共 579 行 · 第 1/2 页
C
579 行
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
if (SmpClientDirectory.Count > 0)
{
for (ClientIndex = 0; ClientIndex < SM_MAX_CLIENT_COUNT; ClientIndex ++)
{
if ((NULL != SmpClientDirectory.Client [ClientIndex]) &&
(ProcessId == SmpClientDirectory.Client [ClientIndex]->ServerProcessId))
{
SmpSetClientInitialized (SmpClientDirectory.Client [ClientIndex]);
Status = STATUS_SUCCESS;
break;
}
}
}
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
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
*
* 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:
* STATUS_SUCCESS if all OK;
* STATUS_DEVICE_BUSY if another SS is still booting;
* STATUS_NO_MEMORY if client descriptor allocation failed;
*
*
*/
NTSTATUS STDCALL
SmCreateClient (PRTL_USER_PROCESS_INFORMATION ProcessInfo, PWSTR ProgramName)
{
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("SM: %s(%lx, %S) called\n", __FUNCTION__, ProcessInfo->ProcessHandle, ProgramName);
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
/*
* Check if the candidate client slot is empty.
*/
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
*/
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
{
DPRINT("SM:%s(%08lx,%S): candidate is %08lx\n", __FUNCTION__,
ProcessInfo, ProgramName, SmpClientDirectory.CandidateClient);
/* 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);
}
} else {
DPRINT1("SM: %s: CandidateClient %08lx pending!\n", __FUNCTION__,
SmpClientDirectory.CandidateClient);
Status = STATUS_DEVICE_BUSY;
}
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;
}
/**********************************************************************
* SmpDestroyClient/1
*
* 1. close any handle
* 2. kill client process
* 3. release resources
*/
NTSTATUS STDCALL
SmDestroyClient (ULONG SubsystemId)
{
NTSTATUS Status = STATUS_SUCCESS;
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
DPRINT("SM: %s(%lu) called\n", __FUNCTION__, SubsystemId);
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
ClientIndex = SmpLookupClient (SubsystemId);
if (SM_INVALID_CLIENT_INDEX == ClientIndex)
{
DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
__FUNCTION__, SubsystemId);
return STATUS_NOT_FOUND;
}
Status = SmpDestroyClientByClientIndex (ClientIndex);
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
return Status;
}
/* === Utilities for SmQryInfo === */
/**********************************************************************
* SmGetClientBasicInformation/1
*/
NTSTATUS FASTCALL
SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
{
INT ClientIndex = 0;
INT Index = 0;
DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, i);
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
i->SubSystemCount = SmpClientDirectory.Count;
i->Unused = 0;
if (SmpClientDirectory.Count > 0)
{
for (ClientIndex = 0; (ClientIndex < SM_MAX_CLIENT_COUNT); ClientIndex ++)
{
if ((NULL != SmpClientDirectory.Client [ClientIndex]) &&
(Index < SM_QRYINFO_MAX_SS_COUNT))
{
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;
}
}
}
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
return STATUS_SUCCESS;
}
/**********************************************************************
* SmGetSubSystemInformation/1
*/
NTSTATUS FASTCALL
SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)
{
NTSTATUS Status = STATUS_SUCCESS;
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, i);
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
ClientIndex = SmpLookupClient (i->SubSystemId);
if (SM_INVALID_CLIENT_INDEX == ClientIndex)
{
Status = STATUS_NOT_FOUND;
}
else
{
i->Flags = SmpClientDirectory.Client [ClientIndex]->Flags;
i->ProcessId = SmpClientDirectory.Client [ClientIndex]->ServerProcessId;
RtlCopyMemory (i->NameSpaceRootNode,
SmpClientDirectory.Client [ClientIndex]->SbApiPortName,
(SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0])));
}
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
return Status;
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?