?? api.c
字號:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS CSR Sub System
* FILE: subsys/csr/csrsrv/api.c
* PURPOSE: CSR Server DLL API LPC Implementation
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES ******************************************************************/
#include "srv.h"
#define NDEBUG
#include <debug.h>
/* DATA **********************************************************************/
BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL;
ULONG CsrMaxApiRequestThreads;
UNICODE_STRING CsrSbApiPortName;
UNICODE_STRING CsrApiPortName;
HANDLE CsrSbApiPort;
HANDLE CsrApiPort;
PCSR_THREAD CsrSbApiRequestThreadPtr;
ULONG CsrpStaticThreadCount;
ULONG CsrpDynamicThreadTotal;
/* PRIVATE FUNCTIONS *********************************************************/
/*++
* @name CsrCheckRequestThreads
*
* The CsrCheckRequestThreads routine checks if there are no more threads
* to handle CSR API Requests, and creates a new thread if possible, to
* avoid starvation.
*
* @param None.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* if a new thread couldn't be created.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrCheckRequestThreads(VOID)
{
HANDLE hThread;
CLIENT_ID ClientId;
NTSTATUS Status;
/* Decrease the count, and see if we're out */
if (!(InterlockedDecrement(&CsrpStaticThreadCount)))
{
/* Check if we've still got space for a Dynamic Thread */
if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
{
/* Create a new dynamic thread */
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
TRUE,
0,
0,
0,
(PVOID)CsrApiRequestThread,
NULL,
&hThread,
&ClientId);
/* Check success */
if(NT_SUCCESS(Status))
{
/* Increase the thread counts */
CsrpStaticThreadCount++;
CsrpDynamicThreadTotal++;
/* Add a new server thread */
if (CsrAddStaticServerThread(hThread,
&ClientId,
CsrThreadIsServerThread))
{
/* Activate it */
NtResumeThread(hThread,NULL);
}
else
{
/* Failed to create a new static thread */
CsrpStaticThreadCount--;
CsrpDynamicThreadTotal--;
/* Terminate it */
NtTerminateThread(hThread,0);
NtClose(hThread);
/* Return */
return STATUS_UNSUCCESSFUL;
}
}
}
}
/* Success */
return STATUS_SUCCESS;
}
/*++
* @name CsrSbApiPortInitialize
*
* The CsrSbApiPortInitialize routine initializes the LPC Port used for
* communications with the Session Manager (SM) and initializes the static
* thread that will handle connection requests and APIs.
*
* @param None
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* othwerwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrSbApiPortInitialize(VOID)
{
ULONG Size;
PSECURITY_DESCRIPTOR PortSd;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE hRequestThread;
CLIENT_ID ClientId;
/* Calculate how much space we'll need for the Port Name */
Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR);
/* Allocate space for it, and create it */
CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
CsrSbApiPortName.Length = 0;
CsrSbApiPortName.MaximumLength = (USHORT)Size;
RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName);
RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP);
RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME);
/* Create Security Descriptor for this Port */
CsrCreateLocalSystemSD(&PortSd);
/* Initialize the Attributes */
InitializeObjectAttributes(&ObjectAttributes,
&CsrSbApiPortName,
0,
PortSd,
NULL);
/* Create the Port Object */
Status = NtCreatePort(&CsrSbApiPort,
&ObjectAttributes,
sizeof(SB_CONNECTION_INFO),
sizeof(SB_API_MESSAGE),
32 * sizeof(SB_API_MESSAGE));
if(!NT_SUCCESS(Status))
{
}
/* Create the Thread to handle the API Requests */
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
TRUE,
0,
0,
0,
(PVOID)CsrSbApiRequestThread,
NULL,
&hRequestThread,
&ClientId);
if(!NT_SUCCESS(Status))
{
}
/* Add it as a Static Server Thread */
CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread,
&ClientId,
0);
/* Activate it */
return NtResumeThread(hRequestThread, NULL);
}
/*++
* @name CsrApiPortInitialize
*
* The CsrApiPortInitialize routine initializes the LPC Port used for
* communications with the Client/Server Runtime (CSR) and initializes the
* static thread that will handle connection requests and APIs.
*
* @param None
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* othwerwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrApiPortInitialize(VOID)
{
ULONG Size;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE hRequestEvent, hThread;
CLIENT_ID ClientId;
PLIST_ENTRY ListHead, NextEntry;
PCSR_THREAD ServerThread;
/* Calculate how much space we'll need for the Port Name */
Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);
/* Allocate space for it, and create it */
CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
CsrApiPortName.Length = 0;
CsrApiPortName.MaximumLength = (USHORT)Size;
RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName);
RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP);
RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME);
/* FIXME: Create a Security Descriptor */
/* Initialize the Attributes */
InitializeObjectAttributes(&ObjectAttributes,
&CsrApiPortName,
0,
NULL,
NULL /* FIXME*/);
/* Create the Port Object */
Status = NtCreatePort(&CsrApiPort,
&ObjectAttributes,
sizeof(CSR_CONNECTION_INFO),
sizeof(CSR_API_MESSAGE),
16 * PAGE_SIZE);
if(!NT_SUCCESS(Status))
{
}
/* Create the event the Port Thread will use */
Status = NtCreateEvent(&hRequestEvent,
EVENT_ALL_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if(!NT_SUCCESS(Status))
{
}
/* Create the Request Thread */
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
TRUE,
0,
0,
0,
(PVOID)CsrApiRequestThread,
(PVOID)hRequestEvent,
&hThread,
&ClientId);
if(!NT_SUCCESS(Status))
{
}
/* Add this as a static thread to CSRSRV */
CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread);
/* Get the Thread List Pointers */
ListHead = &CsrRootProcess->ThreadList;
NextEntry = ListHead->Flink;
/* Start looping the list */
while (NextEntry != ListHead)
{
/* Get the Thread */
ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
/* Start it up */
Status = NtResumeThread(ServerThread->ThreadHandle, NULL);
/* Is this a Server Thread? */
if (ServerThread->Flags & CsrThreadIsServerThread)
{
/* If so, then wait for it to initialize */
NtWaitForSingleObject(hRequestEvent, FALSE, NULL);
}
/* Next thread */
NextEntry = NextEntry->Flink;
}
/* We don't need this anymore */
NtClose(hRequestEvent);
/* Return */
return Status;
}
/*++
* @name CsrApiRequestThread
*
* The CsrApiRequestThread routine handles incoming messages or connection
* requests on the CSR API LPC Port.
*
* @param Parameter
* System-default user-defined parameter. Unused.
*
* @return The thread exit code, if the thread is terminated.
*
* @remarks Before listening on the port, the routine will first attempt
* to connect to the user subsystem.
*
*--*/
NTSTATUS
NTAPI
CsrApiRequestThread(IN PVOID Parameter)
{
PTEB Teb = NtCurrentTeb();
LARGE_INTEGER TimeOut;
PCSR_THREAD CurrentThread;
NTSTATUS Status;
PCSR_API_MESSAGE ReplyMsg = NULL;
CSR_API_MESSAGE ReceiveMsg;
PCSR_THREAD CsrThread;
PCSR_PROCESS CsrProcess;
PHARDERROR_MSG HardErrorMsg;
PVOID PortContext;
ULONG MessageType;
ULONG i;
PCSR_SERVER_DLL ServerDll;
PCLIENT_DIED_MSG ClientDiedMsg;
PDBGKM_MSG DebugMessage;
ULONG ServerId, ApiId;
ULONG Reply;
/* Probably because of the way GDI is loaded, this has to be done here */
Teb->GdiClientPID = HandleToUlong(Teb->Cid.UniqueProcess);
Teb->GdiClientTID = HandleToUlong(Teb->Cid.UniqueThread);
/* Set up the timeout for the connect (30 seconds) */
TimeOut.QuadPart = -30 * 1000 * 1000 * 10;
/* Connect to user32 */
while (!CsrConnectToUser())
{
/* Keep trying until we get a response */
Teb->Win32ClientInfo[0] = 0;
NtDelayExecution(FALSE, &TimeOut);
}
/* Get our thread */
CurrentThread = Teb->CsrClientThread;
/* If we got an event... */
if (Parameter)
{
/* Set it, to let stuff waiting on us load */
NtSetEvent((HANDLE)Parameter, NULL);
/* Increase the Thread Counts */
InterlockedIncrement(&CsrpStaticThreadCount);
InterlockedIncrement(&CsrpDynamicThreadTotal);
}
/* Now start the loop */
while (TRUE)
{
/* Make sure the real CID is set */
Teb->RealClientId = Teb->Cid;
/* Wait for a message to come through */
Status = NtReplyWaitReceivePort(CsrApiPort,
&PortContext,
(PPORT_MESSAGE)ReplyMsg,
(PPORT_MESSAGE)&ReceiveMsg);
/* Check if we didn't get success */
if(Status != STATUS_SUCCESS)
{
/* If we only got a warning, keep going */
if (NT_SUCCESS(Status)) continue;
/* We failed big time, so start out fresh */
ReplyMsg = NULL;
continue;
}
/* Use whatever Client ID we got */
Teb->RealClientId = ReceiveMsg.Header.ClientId;
/* Get the Message Type */
MessageType = ReceiveMsg.Header.u2.s2.Type;
/* Handle connection requests */
if (MessageType == LPC_CONNECTION_REQUEST)
{
/* Handle the Connection Request */
CsrApiHandleConnectionRequest(&ReceiveMsg);
ReplyMsg = NULL;
continue;
}
/* It's some other kind of request. Get the lock for the lookup*/
CsrAcquireProcessLock();
/* Now do the lookup to get the CSR_THREAD */
CsrThread = CsrLocateThreadByClientId(&CsrProcess,
&ReceiveMsg.Header.ClientId);
/* Did we find a thread? */
if(!CsrThread)
{
/* This wasn't a CSR Thread, release lock */
CsrReleaseProcessLock();
/* If this was an exception, handle it */
if (MessageType == LPC_EXCEPTION)
{
ReplyMsg = &ReceiveMsg;
ReplyMsg->Status = DBG_CONTINUE;
}
else if (MessageType == LPC_PORT_CLOSED ||
MessageType == LPC_CLIENT_DIED)
{
/* The Client or Port are gone, loop again */
ReplyMsg = NULL;
}
else if (MessageType == LPC_ERROR_EVENT)
{
/* If it's a hard error, handle this too */
HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;
/* Default it to unhandled */
HardErrorMsg->Response = ResponseNotHandled;
/* Check if there are free api threads */
CsrCheckRequestThreads();
if (CsrpStaticThreadCount)
{
/* Loop every Server DLL */
for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
{
/* Get the Server DLL */
ServerDll = CsrLoadedServerDll[i];
/* Check if it's valid and if it has a Hard Error Callback */
if (ServerDll && ServerDll->HardErrorCallback)
{
/* Call it */
(*ServerDll->HardErrorCallback)(CsrThread, HardErrorMsg);
/* If it's handled, get out of here */
if (HardErrorMsg->Response != ResponseNotHandled) break;
}
}
}
/* Increase the thread count */
InterlockedIncrement(&CsrpStaticThreadCount);
/* If the response was 0xFFFFFFFF, we'll ignore it */
if (HardErrorMsg->Response == 0xFFFFFFFF)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -