client.c
来自「一个类似windows」· C语言 代码 · 共 579 行 · 第 1/2 页
C
579 行
/* $Id: client.c 21257 2006-03-08 23:07:09Z audit $
*
* client.c - Session Manager client Management
*
* ReactOS Operating System
*
* --------------------------------------------------------------------
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING.LIB. If not, write
* to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
* MA 02139, USA.
*
* --------------------------------------------------------------------
*/
#include "smss.h"
#include <sm/helper.h>
#define NDEBUG
#include <debug.h>
/* Private ADT */
#define SM_MAX_CLIENT_COUNT 16
#define SM_INVALID_CLIENT_INDEX -1
struct _SM_CLIENT_DIRECTORY
{
RTL_CRITICAL_SECTION Lock;
ULONG Count;
PSM_CLIENT_DATA Client [SM_MAX_CLIENT_COUNT];
PSM_CLIENT_DATA CandidateClient;
} SmpClientDirectory;
/**********************************************************************
* SmInitializeClientManagement/0
*/
NTSTATUS
SmInitializeClientManagement (VOID)
{
DPRINT("SM: %s called\n", __FUNCTION__);
RtlInitializeCriticalSection(& SmpClientDirectory.Lock);
SmpClientDirectory.Count = 0;
RtlZeroMemory (SmpClientDirectory.Client, sizeof SmpClientDirectory.Client);
SmpClientDirectory.CandidateClient = NULL;
return STATUS_SUCCESS;
}
/**********************************************************************
* SmpSetClientInitialized/1
*/
VOID FASTCALL
SmpSetClientInitialized (PSM_CLIENT_DATA Client)
{
DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, Client);
Client->Flags |= SM_CLIENT_FLAG_INITIALIZED;
}
/**********************************************************************
* 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
* Lookup the subsystem server descriptor (client data) given its
* base image ID.
*
* ARGUMENTS
* SubsystemId: IMAGE_SUBSYSTEM_xxx
*
* RETURN VALUES
* SM_INVALID_CLIENT_INDEX on error;
* otherwise an index in the range (0..SM_MAX_CLIENT_COUNT).
*
* WARNING
* SmpClientDirectory.Lock must be held by the caller.
*/
static INT FASTCALL
SmpLookupClient (USHORT SubsystemId)
{
INT ClientIndex = 0;
DPRINT("SM: %s(%d) called\n", __FUNCTION__, SubsystemId);
if (0 != SmpClientDirectory.Count)
{
for (ClientIndex = 0; (ClientIndex < SM_MAX_CLIENT_COUNT); ClientIndex ++)
{
if (NULL != SmpClientDirectory.Client[ClientIndex])
{
if (SubsystemId == SmpClientDirectory.Client[ClientIndex]->SubsystemId)
{
return ClientIndex;
}
}
}
}
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
*
* 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
SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
OUT PSM_CLIENT_DATA * ClientData)
{
NTSTATUS Status = STATUS_SUCCESS;
PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);
ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
DPRINT("SM: %s(%08lx,%08lx) called\n", __FUNCTION__,
Request, ClientData);
RtlEnterCriticalSection (& SmpClientDirectory.Lock);
/*
* Is there a subsystem bootstrap in progress?
*/
if (NULL != 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
{
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 (SM_INVALID_CLIENT_INDEX != SmpLookupClient(ConnectData->SubSystemId))
{
DPRINT("SM: %s: attempt to register again subsystem %d.\n",
__FUNCTION__,
ConnectData->SubSystemId);
// TODO something else to do here?
RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
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",
__FUNCTION__, ConnectData->SubSystemId);
/*
* Initialize the client data
*/
SmpClientDirectory.CandidateClient->SubsystemId = ConnectData->SubSystemId;
/* SM && DBG auto-initializes; other subsystems are required to call
* SM_API_COMPLETE_SESSION via SMDLL. */
if ((IMAGE_SUBSYSTEM_NATIVE == SmpClientDirectory.CandidateClient->SubsystemId) ||
((USHORT)-1 == SmpClientDirectory.CandidateClient->SubsystemId))
{
SmpSetClientInitialized (SmpClientDirectory.CandidateClient);
}
if (SbApiPortNameSize > 0)
{
/* Only external servers have an SB port */
RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName,
ConnectData->SbName,
SbApiPortNameSize);
}
/*
* Insert the new descriptor in the
* client directory.
*/
SmpClientDirectory.Client [ClientIndex] = SmpClientDirectory.CandidateClient;
/*
* Increment the number of active subsystems.
*/
++ SmpClientDirectory.Count;
/*
* Notify to the caller the reference to the client data.
*/
if (ClientData)
{
*ClientData = SmpClientDirectory.CandidateClient;
}
/*
* Free the slot for the candidate subsystem.
*/
SmpClientDirectory.CandidateClient = NULL;
/* Done */
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_NOT_FOUND;
INT ClientIndex = SM_INVALID_CLIENT_INDEX;
DPRINT("SM: %s(%lu) called\n", __FUNCTION__, ProcessId);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?