2012-10-13 20:32:44 +00:00
|
|
|
/*
|
2012-10-22 00:09:51 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
2012-10-25 20:40:41 +00:00
|
|
|
* PROJECT: ReactOS Client/Server Runtime SubSystem
|
2012-10-22 00:09:51 +00:00
|
|
|
* FILE: subsystems/win32/csrsrv/api.c
|
|
|
|
* PURPOSE: CSR Server DLL API LPC Implementation
|
|
|
|
* "\windows\ApiPort" port process management functions
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
1999-12-22 14:48:30 +00:00
|
|
|
*/
|
|
|
|
|
2012-10-27 14:30:32 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
1999-12-22 14:48:30 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
#include "srv.h"
|
2005-03-20 22:55:05 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
//#define NDEBUG
|
2002-09-07 15:13:13 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2012-10-27 14:30:32 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
1999-12-30 01:51:42 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL;
|
2012-02-16 16:40:15 +00:00
|
|
|
UNICODE_STRING CsrApiPortName;
|
2012-02-19 06:32:17 +00:00
|
|
|
volatile LONG CsrpStaticThreadCount;
|
|
|
|
volatile LONG CsrpDynamicThreadTotal;
|
2012-09-05 21:38:02 +00:00
|
|
|
extern ULONG CsrMaxApiRequestThreads;
|
2003-12-02 11:38:47 +00:00
|
|
|
|
2012-10-27 14:30:32 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
1999-12-22 14:48:30 +00:00
|
|
|
|
2012-02-18 01:27:50 +00:00
|
|
|
/*++
|
|
|
|
* @name CsrCallServerFromServer
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The CsrCallServerFromServer routine calls a CSR API from within a server.
|
|
|
|
* It avoids using LPC messages since the request isn't coming from a client.
|
|
|
|
*
|
|
|
|
* @param ReceiveMsg
|
|
|
|
* Pointer to the CSR API Message to send to the server.
|
|
|
|
*
|
|
|
|
* @param ReplyMsg
|
|
|
|
* Pointer to the CSR API Message to receive from the server.
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
|
2012-10-17 23:10:40 +00:00
|
|
|
* if the ApiNumber is invalid, or STATUS_ACCESS_VIOLATION if there
|
2012-02-18 01:27:50 +00:00
|
|
|
* was a problem executing the API.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2012-10-22 00:09:51 +00:00
|
|
|
CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg,
|
|
|
|
IN OUT PCSR_API_MESSAGE ReplyMsg)
|
2012-02-18 01:27:50 +00:00
|
|
|
{
|
|
|
|
ULONG ServerId;
|
|
|
|
PCSR_SERVER_DLL ServerDll;
|
|
|
|
ULONG ApiId;
|
|
|
|
ULONG Reply;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Get the Server ID */
|
2012-10-22 00:09:51 +00:00
|
|
|
ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg->ApiNumber);
|
2012-02-18 01:27:50 +00:00
|
|
|
|
|
|
|
/* Make sure that the ID is within limits, and the Server DLL loaded */
|
|
|
|
if ((ServerId >= CSR_SERVER_DLL_MAX) ||
|
|
|
|
(!(ServerDll = CsrLoadedServerDll[ServerId])))
|
|
|
|
{
|
|
|
|
/* We are beyond the Maximum Server ID */
|
|
|
|
DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll);
|
|
|
|
ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
|
|
|
|
return STATUS_ILLEGAL_FUNCTION;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Get the API ID, normalized with our Base ID */
|
|
|
|
ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg->ApiNumber) - ServerDll->ApiBase;
|
2012-02-18 01:27:50 +00:00
|
|
|
|
|
|
|
/* Make sure that the ID is within limits, and the entry exists */
|
|
|
|
if ((ApiId >= ServerDll->HighestApiSupported) ||
|
|
|
|
((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId])))
|
|
|
|
{
|
|
|
|
/* We are beyond the Maximum API ID, or it doesn't exist */
|
|
|
|
DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
|
|
|
|
"invalid API to call from the server.\n",
|
|
|
|
ServerDll->ValidTable[ApiId],
|
|
|
|
((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ?
|
|
|
|
ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name);
|
|
|
|
DbgBreakPoint();
|
|
|
|
ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
|
|
|
|
return STATUS_ILLEGAL_FUNCTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CsrDebug & 2)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: %s Api Request received from server process\n",
|
|
|
|
ServerDll->NameTable[ApiId]);
|
|
|
|
}
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-18 01:27:50 +00:00
|
|
|
/* Validation complete, start SEH */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* Call the API and get the result */
|
2012-10-20 21:03:32 +00:00
|
|
|
/// CsrApiCallHandler(ReplyMsg, /*ProcessData*/ &ReplyCode); ///
|
2012-02-18 01:27:50 +00:00
|
|
|
Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply);
|
|
|
|
|
|
|
|
/* Return the result, no matter what it is */
|
|
|
|
ReplyMsg->Status = Status;
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
/* If we got an exception, return access violation */
|
|
|
|
ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
|
|
|
|
/* Return success */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/*++
|
2012-10-22 00:09:51 +00:00
|
|
|
* @name CsrApiHandleConnectionRequest
|
2012-02-16 16:40:15 +00:00
|
|
|
*
|
2012-10-22 00:09:51 +00:00
|
|
|
* The CsrApiHandleConnectionRequest routine handles and accepts a new
|
|
|
|
* connection request to the CSR API LPC Port.
|
2012-02-16 16:40:15 +00:00
|
|
|
*
|
2012-10-22 00:09:51 +00:00
|
|
|
* @param ApiMessage
|
|
|
|
* Pointer to the incoming CSR API Message which contains the
|
|
|
|
* connection request.
|
2012-02-16 16:40:15 +00:00
|
|
|
*
|
2012-10-22 00:09:51 +00:00
|
|
|
* @return STATUS_SUCCESS in case of success, or status code which caused
|
|
|
|
* the routine to error.
|
2012-02-16 16:40:15 +00:00
|
|
|
*
|
2012-10-22 00:09:51 +00:00
|
|
|
* @remarks This routine is responsible for attaching the Shared Section to
|
|
|
|
* new clients connecting to CSR.
|
2012-02-16 16:40:15 +00:00
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2012-10-22 00:09:51 +00:00
|
|
|
CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
|
2012-02-16 16:40:15 +00:00
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
PCSR_THREAD CsrThread = NULL;
|
|
|
|
PCSR_PROCESS CsrProcess = NULL;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PCSR_CONNECTION_INFO ConnectInfo = &ApiMessage->ConnectionInfo;
|
|
|
|
BOOLEAN AllowConnection = FALSE;
|
|
|
|
REMOTE_PORT_VIEW RemotePortView;
|
|
|
|
HANDLE hPort;
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Acquire the Process Lock */
|
|
|
|
CsrAcquireProcessLock();
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Lookup the CSR Thread */
|
|
|
|
CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId);
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Check if we have a thread */
|
|
|
|
if (CsrThread)
|
2012-02-16 16:40:15 +00:00
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Get the Process */
|
|
|
|
CsrProcess = CsrThread->Process;
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Make sure we have a Process as well */
|
|
|
|
if (CsrProcess)
|
2012-02-16 16:40:15 +00:00
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Reference the Process */
|
|
|
|
CsrLockedReferenceProcess(CsrThread->Process);
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Release the lock */
|
|
|
|
CsrReleaseProcessLock();
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Duplicate the Object Directory */
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
|
|
|
CsrObjectDirectory,
|
|
|
|
CsrProcess->ProcessHandle,
|
|
|
|
&ConnectInfo->ObjectDirectory,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
DUPLICATE_SAME_ACCESS |
|
|
|
|
DUPLICATE_SAME_ATTRIBUTES);
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Acquire the lock */
|
|
|
|
CsrAcquireProcessLock();
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Check for success */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Attach the Shared Section */
|
|
|
|
Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Check how this went */
|
|
|
|
if (NT_SUCCESS(Status)) AllowConnection = TRUE;
|
2012-02-16 16:40:15 +00:00
|
|
|
}
|
2006-10-30 18:45:22 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Dereference the project */
|
|
|
|
CsrLockedDereferenceProcess(CsrProcess);
|
2011-08-03 03:09:02 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-15 16:11:12 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Release the lock */
|
|
|
|
CsrReleaseProcessLock();
|
2012-02-19 04:18:33 +00:00
|
|
|
|
|
|
|
/* Setup the Port View Structure */
|
|
|
|
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
|
|
|
|
RemotePortView.ViewSize = 0;
|
|
|
|
RemotePortView.ViewBase = NULL;
|
|
|
|
|
|
|
|
/* Save the Process ID */
|
|
|
|
ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Accept the Connection */
|
|
|
|
Status = NtAcceptConnectPort(&hPort,
|
|
|
|
AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
|
|
|
|
&ApiMessage->Header,
|
2011-08-03 03:09:02 +00:00
|
|
|
AllowConnection,
|
2012-02-19 04:18:33 +00:00
|
|
|
NULL,
|
|
|
|
&RemotePortView);
|
2011-08-03 03:09:02 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2012-02-19 04:18:33 +00:00
|
|
|
DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status);
|
2006-10-30 18:45:22 +00:00
|
|
|
}
|
2012-02-19 04:18:33 +00:00
|
|
|
else if (AllowConnection)
|
|
|
|
{
|
|
|
|
if (CsrDebug & 2)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
|
2012-10-22 00:09:51 +00:00
|
|
|
ApiMessage->Header.ClientId.UniqueProcess,
|
|
|
|
ApiMessage->Header.ClientId.UniqueThread,
|
2012-02-19 04:18:33 +00:00
|
|
|
RemotePortView.ViewBase,
|
|
|
|
RemotePortView.ViewSize);
|
|
|
|
}
|
2006-10-30 18:45:22 +00:00
|
|
|
|
2012-02-19 04:18:33 +00:00
|
|
|
/* Set some Port Data in the Process */
|
2012-10-22 00:09:51 +00:00
|
|
|
CsrProcess->ClientPort = hPort;
|
|
|
|
CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
|
|
|
|
CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
|
|
|
|
(ULONG_PTR)RemotePortView.ViewSize);
|
2006-10-30 18:45:22 +00:00
|
|
|
|
2012-02-19 04:18:33 +00:00
|
|
|
/* Complete the connection */
|
2012-10-22 00:09:51 +00:00
|
|
|
Status = NtCompleteConnectPort(hPort);
|
2012-02-19 04:18:33 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2006-10-30 18:45:22 +00:00
|
|
|
{
|
2012-02-19 04:18:33 +00:00
|
|
|
DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
|
2012-10-22 00:09:51 +00:00
|
|
|
ApiMessage->Header.ClientId.UniqueProcess,
|
|
|
|
ApiMessage->Header.ClientId.UniqueThread);
|
2006-10-30 18:45:22 +00:00
|
|
|
}
|
2012-02-15 16:11:12 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Return status to caller */
|
2006-10-30 18:45:22 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
// TODO: See CsrApiHandleConnectionRequest
|
|
|
|
NTSTATUS WINAPI
|
|
|
|
CsrpHandleConnectionRequest(PPORT_MESSAGE Request)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE ServerPort = NULL;//, ServerThread = NULL;
|
|
|
|
PCSR_PROCESS ProcessData = NULL;
|
|
|
|
REMOTE_PORT_VIEW RemotePortView;
|
|
|
|
// CLIENT_ID ClientId;
|
|
|
|
BOOLEAN AllowConnection = FALSE;
|
|
|
|
PCSR_CONNECTION_INFO ConnectInfo;
|
|
|
|
ServerPort = NULL;
|
|
|
|
|
|
|
|
DPRINT1("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
|
|
|
|
|
|
|
|
ConnectInfo = (PCSR_CONNECTION_INFO)(Request + 1);
|
|
|
|
|
|
|
|
/* Save the process ID */
|
|
|
|
RtlZeroMemory(ConnectInfo, sizeof(CSR_CONNECTION_INFO));
|
|
|
|
|
|
|
|
CsrLockProcessByClientId(Request->ClientId.UniqueProcess, &ProcessData);
|
|
|
|
if (!ProcessData)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting connection\n",
|
|
|
|
Request->ClientId.UniqueProcess);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ProcessData) && (ProcessData != CsrRootProcess))
|
|
|
|
{
|
|
|
|
/* Attach the Shared Section */
|
|
|
|
Status = CsrSrvAttachSharedSection(ProcessData, ConnectInfo);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Connection ok\n");
|
|
|
|
AllowConnection = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Shared section map failed: %lx\n", Status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ProcessData == CsrRootProcess)
|
|
|
|
{
|
|
|
|
AllowConnection = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the process */
|
|
|
|
if (ProcessData) CsrUnlockProcess(ProcessData);
|
|
|
|
|
|
|
|
/* Setup the Port View Structure */
|
|
|
|
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
|
|
|
|
RemotePortView.ViewSize = 0;
|
|
|
|
RemotePortView.ViewBase = NULL;
|
|
|
|
|
|
|
|
/* Save the Process ID */
|
|
|
|
ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
|
|
|
|
|
|
|
|
Status = NtAcceptConnectPort(&ServerPort,
|
|
|
|
AllowConnection ? UlongToPtr(ProcessData->SequenceNumber) : 0,
|
|
|
|
Request,
|
|
|
|
AllowConnection,
|
|
|
|
NULL,
|
|
|
|
&RemotePortView);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status);
|
|
|
|
}
|
|
|
|
else if (AllowConnection)
|
|
|
|
{
|
|
|
|
if (CsrDebug & 2)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
|
|
|
|
Request->ClientId.UniqueProcess,
|
|
|
|
Request->ClientId.UniqueThread,
|
|
|
|
RemotePortView.ViewBase,
|
|
|
|
RemotePortView.ViewSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set some Port Data in the Process */
|
|
|
|
ProcessData->ClientPort = ServerPort;
|
|
|
|
ProcessData->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
|
|
|
|
ProcessData->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
|
|
|
|
(ULONG_PTR)RemotePortView.ViewSize);
|
|
|
|
|
|
|
|
/* Complete the connection */
|
|
|
|
Status = NtCompleteConnectPort(ServerPort);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
|
|
|
|
Request->ClientId.UniqueProcess,
|
|
|
|
Request->ClientId.UniqueThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2012-02-19 06:32:17 +00:00
|
|
|
/*++
|
|
|
|
* @name CsrpCheckRequestThreads
|
|
|
|
*
|
|
|
|
* The CsrpCheckRequestThreads 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
|
|
|
|
CsrpCheckRequestThreads(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,
|
2012-10-22 00:09:51 +00:00
|
|
|
(PVOID)CsrApiRequestThread,
|
2012-02-19 06:32:17 +00:00
|
|
|
NULL,
|
|
|
|
&hThread,
|
|
|
|
&ClientId);
|
|
|
|
/* Check success */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Increase the thread counts */
|
|
|
|
_InterlockedIncrement(&CsrpStaticThreadCount);
|
|
|
|
_InterlockedIncrement(&CsrpDynamicThreadTotal);
|
|
|
|
|
|
|
|
/* Add a new server thread */
|
|
|
|
if (CsrAddStaticServerThread(hThread,
|
|
|
|
&ClientId,
|
|
|
|
CsrThreadIsServerThread))
|
|
|
|
{
|
|
|
|
/* Activate it */
|
|
|
|
NtResumeThread(hThread, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Failed to create a new static thread */
|
|
|
|
_InterlockedDecrement(&CsrpStaticThreadCount);
|
|
|
|
_InterlockedDecrement(&CsrpDynamicThreadTotal);
|
|
|
|
|
|
|
|
/* Terminate it */
|
|
|
|
DPRINT1("Failing\n");
|
|
|
|
NtTerminateThread(hThread, 0);
|
|
|
|
NtClose(hThread);
|
|
|
|
|
|
|
|
/* Return */
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Success */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/*++
|
|
|
|
* @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)
|
2003-12-02 11:38:47 +00:00
|
|
|
{
|
2012-02-16 16:40:15 +00:00
|
|
|
PTEB Teb = NtCurrentTeb();
|
|
|
|
LARGE_INTEGER TimeOut;
|
2012-10-22 00:09:51 +00:00
|
|
|
PCSR_THREAD CurrentThread, CsrThread;
|
Large change to modify NTDLL'S CSR Functions to be compatible with NT. They are external and we should at least try to match the number of arguments (one vs eight? come on!). Because this is also the direction that Emanuele wants to be taking, the whole external calling interface was modified to be more compatible with NT (although internally it still isn't, and does not have a reason to be). API Names are now generated by a macro from the Server ID, like Emanuele and I noticed from traces, and I've entirely removed the concept of a reply structure. CSRSS uses full-duplex one-way structures, not dual-strutures (this would've been incompatible with the external interface anyways). I don't seem to have introduced any new bugs (console-ROS works great for me, as does the GUI), but there is still a chance some obscure bug might happen, so please bear with me, I had to hand-edit over 250 calls. Also, this now allows full removal of ntdll headers and the next commits will clean this up
svn path=/trunk/; revision=16213
2005-06-22 04:02:32 +00:00
|
|
|
NTSTATUS Status;
|
2012-10-22 00:09:51 +00:00
|
|
|
PCSR_API_MESSAGE ReplyMsg;
|
|
|
|
CSR_API_MESSAGE ReceiveMsg;
|
2012-02-19 19:40:28 +00:00
|
|
|
PCSR_PROCESS CsrProcess;
|
|
|
|
PHARDERROR_MSG HardErrorMsg;
|
2012-10-22 00:09:51 +00:00
|
|
|
PVOID PortContext;
|
|
|
|
PCSR_SERVER_DLL ServerDll;
|
2012-02-19 19:40:28 +00:00
|
|
|
PCLIENT_DIED_MSG ClientDiedMsg;
|
2012-10-22 00:09:51 +00:00
|
|
|
PDBGKM_MSG DebugMessage;
|
|
|
|
ULONG ServerId, ApiId, Reply, MessageType, i;
|
|
|
|
HANDLE ReplyPort;
|
2012-02-15 16:11:12 +00:00
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Setup LPC loop port and message */
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 06:32:17 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-02-16 16:40:15 +00:00
|
|
|
|
2010-03-09 20:23:22 +00:00
|
|
|
/* Connect to user32 */
|
|
|
|
while (!CsrConnectToUser())
|
|
|
|
{
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Set up the timeout for the connect (30 seconds) */
|
|
|
|
TimeOut.QuadPart = -30 * 1000 * 1000 * 10;
|
|
|
|
|
2010-03-09 20:23:22 +00:00
|
|
|
/* Keep trying until we get a response */
|
2012-02-16 16:40:15 +00:00
|
|
|
Teb->Win32ClientInfo[0] = 0;
|
|
|
|
NtDelayExecution(FALSE, &TimeOut);
|
2010-03-09 20:23:22 +00:00
|
|
|
}
|
Large change to modify NTDLL'S CSR Functions to be compatible with NT. They are external and we should at least try to match the number of arguments (one vs eight? come on!). Because this is also the direction that Emanuele wants to be taking, the whole external calling interface was modified to be more compatible with NT (although internally it still isn't, and does not have a reason to be). API Names are now generated by a macro from the Server ID, like Emanuele and I noticed from traces, and I've entirely removed the concept of a reply structure. CSRSS uses full-duplex one-way structures, not dual-strutures (this would've been incompatible with the external interface anyways). I don't seem to have introduced any new bugs (console-ROS works great for me, as does the GUI), but there is still a chance some obscure bug might happen, so please bear with me, I had to hand-edit over 250 calls. Also, this now allows full removal of ntdll headers and the next commits will clean this up
svn path=/trunk/; revision=16213
2005-06-22 04:02:32 +00:00
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Get our thread */
|
2012-10-22 00:09:51 +00:00
|
|
|
CurrentThread = Teb->CsrClientThread;
|
2012-02-16 16:40:15 +00:00
|
|
|
|
|
|
|
/* If we got an event... */
|
|
|
|
if (Parameter)
|
|
|
|
{
|
|
|
|
/* Set it, to let stuff waiting on us load */
|
|
|
|
Status = NtSetEvent((HANDLE)Parameter, NULL);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
|
|
/* Increase the Thread Counts */
|
2012-02-19 06:32:17 +00:00
|
|
|
_InterlockedIncrement(&CsrpStaticThreadCount);
|
|
|
|
_InterlockedIncrement(&CsrpDynamicThreadTotal);
|
2012-02-16 16:40:15 +00:00
|
|
|
}
|
2005-06-22 17:43:59 +00:00
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Now start the loop */
|
|
|
|
while (TRUE)
|
2003-12-02 11:38:47 +00:00
|
|
|
{
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Make sure the real CID is set */
|
|
|
|
Teb->RealClientId = Teb->ClientId;
|
|
|
|
|
|
|
|
/* Debug check */
|
|
|
|
if (Teb->CountOfOwnedCriticalSections)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
|
|
|
|
Teb->CountOfOwnedCriticalSections);
|
|
|
|
DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
|
2012-10-22 00:09:51 +00:00
|
|
|
&ReceiveMsg, ReplyMsg);
|
2012-02-16 16:40:15 +00:00
|
|
|
DbgBreakPoint();
|
|
|
|
}
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Wait for a message to come through */
|
2012-02-19 06:32:17 +00:00
|
|
|
Status = NtReplyWaitReceivePort(ReplyPort,
|
2012-10-22 00:09:51 +00:00
|
|
|
&PortContext,
|
|
|
|
&ReplyMsg->Header,
|
|
|
|
&ReceiveMsg.Header);
|
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Check if we didn't get success */
|
|
|
|
if (Status != STATUS_SUCCESS)
|
2007-06-15 19:14:15 +00:00
|
|
|
{
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Was it a failure or another success code? */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Check for specific status cases */
|
|
|
|
if ((Status != STATUS_INVALID_CID) &&
|
2012-02-19 06:32:17 +00:00
|
|
|
(Status != STATUS_UNSUCCESSFUL) &&
|
|
|
|
((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
|
2012-02-16 16:40:15 +00:00
|
|
|
{
|
|
|
|
/* Notify the debugger */
|
|
|
|
DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
|
2012-02-19 06:32:17 +00:00
|
|
|
DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort);
|
2012-02-16 16:40:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We failed big time, so start out fresh */
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 06:32:17 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-02-16 16:40:15 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* A bizare "success" code, just try again */
|
|
|
|
DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
|
|
|
|
continue;
|
|
|
|
}
|
2007-06-15 19:14:15 +00:00
|
|
|
}
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Use whatever Client ID we got */
|
2012-10-22 00:09:51 +00:00
|
|
|
Teb->RealClientId = ReceiveMsg.Header.ClientId;
|
2007-06-15 19:14:15 +00:00
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* Get the Message Type */
|
2012-10-22 00:09:51 +00:00
|
|
|
MessageType = ReceiveMsg.Header.u2.s2.Type;
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Handle connection requests */
|
2012-02-16 16:40:15 +00:00
|
|
|
if (MessageType == LPC_CONNECTION_REQUEST)
|
2006-10-30 18:45:22 +00:00
|
|
|
{
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Handle the Connection Request */
|
2012-10-22 00:09:51 +00:00
|
|
|
CsrApiHandleConnectionRequest(&ReceiveMsg);
|
2012-02-19 06:32:17 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2006-10-30 18:45:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* It's some other kind of request. Get the lock for the lookup */
|
|
|
|
CsrAcquireProcessLock();
|
2006-10-30 18:45:22 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Now do the lookup to get the CSR_THREAD */
|
|
|
|
CsrThread = CsrLocateThreadByClientId(&CsrProcess,
|
2012-10-22 00:09:51 +00:00
|
|
|
&ReceiveMsg.Header.ClientId);
|
2004-07-03 17:15:02 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Did we find a thread? */
|
|
|
|
if (!CsrThread)
|
2012-02-19 18:05:49 +00:00
|
|
|
{
|
2012-02-19 19:40:28 +00:00
|
|
|
/* This wasn't a CSR Thread, release lock */
|
|
|
|
CsrReleaseProcessLock();
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* If this was an exception, handle it */
|
|
|
|
if (MessageType == LPC_EXCEPTION)
|
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = &ReceiveMsg;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg->Status = DBG_CONTINUE;
|
2012-02-19 19:40:28 +00:00
|
|
|
}
|
|
|
|
else if (MessageType == LPC_PORT_CLOSED ||
|
|
|
|
MessageType == LPC_CLIENT_DIED)
|
|
|
|
{
|
|
|
|
/* The Client or Port are gone, loop again */
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
}
|
|
|
|
else if (MessageType == LPC_ERROR_EVENT)
|
|
|
|
{
|
|
|
|
/* If it's a hard error, handle this too */
|
2012-10-22 00:09:51 +00:00
|
|
|
HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;
|
2012-02-19 18:05:49 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Default it to unhandled */
|
|
|
|
HardErrorMsg->Response = ResponseNotHandled;
|
2012-02-15 16:11:12 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Check if there are free api threads */
|
2012-02-19 06:32:17 +00:00
|
|
|
CsrpCheckRequestThreads();
|
2012-02-19 19:40:28 +00:00
|
|
|
if (CsrpStaticThreadCount)
|
2012-02-19 06:32:17 +00:00
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
/* 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 */
|
2012-11-20 19:34:03 +00:00
|
|
|
ServerDll->HardErrorCallback(NULL /* CsrThread == NULL */, HardErrorMsg);
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* If it's handled, get out of here */
|
|
|
|
if (HardErrorMsg->Response != ResponseNotHandled) break;
|
|
|
|
}
|
|
|
|
}
|
2012-02-19 06:32:17 +00:00
|
|
|
}
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Increase the thread count */
|
|
|
|
_InterlockedIncrement(&CsrpStaticThreadCount);
|
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* If the response was 0xFFFFFFFF, we'll ignore it */
|
|
|
|
if (HardErrorMsg->Response == 0xFFFFFFFF)
|
2012-02-19 06:32:17 +00:00
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-02-19 06:32:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = &ReceiveMsg;
|
2012-02-19 06:32:17 +00:00
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
}
|
|
|
|
else if (MessageType == LPC_REQUEST)
|
|
|
|
{
|
|
|
|
/* This is an API Message coming from a non-CSR Thread */
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = &ReceiveMsg;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
|
2012-02-19 19:40:28 +00:00
|
|
|
}
|
|
|
|
else if (MessageType == LPC_DATAGRAM)
|
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
/* This is an API call, get the Server ID */
|
|
|
|
ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg.ApiNumber);
|
|
|
|
|
|
|
|
/* Make sure that the ID is within limits, and the Server DLL loaded */
|
|
|
|
ServerDll = NULL;
|
|
|
|
if ((ServerId >= CSR_SERVER_DLL_MAX) ||
|
|
|
|
(!(ServerDll = CsrLoadedServerDll[ServerId])))
|
|
|
|
{
|
|
|
|
/* We are beyond the Maximum Server ID */
|
|
|
|
DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
|
|
|
|
ServerId, ServerDll);
|
|
|
|
DbgBreakPoint();
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ReplyMsg = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Get the API ID, normalized with our Base ID */
|
|
|
|
ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber) - ServerDll->ApiBase;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Make sure that the ID is within limits, and the entry exists */
|
|
|
|
if (ApiId >= ServerDll->HighestApiSupported)
|
|
|
|
{
|
|
|
|
/* We are beyond the Maximum API ID, or it doesn't exist */
|
|
|
|
DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
|
|
|
|
CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber),
|
|
|
|
&ServerDll->Name);
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ReplyMsg = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CsrDebug & 2)
|
|
|
|
{
|
|
|
|
DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
|
|
|
|
Teb->ClientId.UniqueThread,
|
|
|
|
ReceiveMsg.Header.ClientId.UniqueProcess,
|
|
|
|
ReceiveMsg.Header.ClientId.UniqueThread,
|
|
|
|
ServerDll->NameTable[ApiId],
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assume success */
|
|
|
|
ReceiveMsg.Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* Validation complete, start SEH */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* Make sure we have enough threads */
|
|
|
|
CsrpCheckRequestThreads();
|
|
|
|
|
|
|
|
/* Call the API and get the result */
|
|
|
|
ReplyMsg = NULL;
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply);
|
|
|
|
|
|
|
|
/* Increase the static thread count */
|
|
|
|
_InterlockedIncrement(&CsrpStaticThreadCount);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
|
|
|
|
{
|
|
|
|
ReplyMsg = NULL;
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2012-02-19 19:40:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Some other ignored message type */
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
}
|
2012-02-19 06:32:17 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Keep going */
|
|
|
|
continue;
|
|
|
|
}
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* We have a valid thread, was this an LPC Request? */
|
|
|
|
if (MessageType != LPC_REQUEST)
|
|
|
|
{
|
|
|
|
/* It's not an API, check if the client died */
|
|
|
|
if (MessageType == LPC_CLIENT_DIED)
|
|
|
|
{
|
|
|
|
/* Get the information and check if it matches our thread */
|
2012-10-22 00:09:51 +00:00
|
|
|
ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg;
|
2012-02-19 19:40:28 +00:00
|
|
|
if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
|
2012-02-19 06:32:17 +00:00
|
|
|
{
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Reference the thread */
|
|
|
|
CsrLockedReferenceThread(CsrThread);
|
|
|
|
|
|
|
|
/* Destroy the thread in the API Message */
|
2012-10-22 00:09:51 +00:00
|
|
|
CsrDestroyThread(&ReceiveMsg.Header.ClientId);
|
2012-02-19 19:40:28 +00:00
|
|
|
|
|
|
|
/* Check if the thread was actually ourselves */
|
|
|
|
if (CsrProcess->ThreadCount == 1)
|
|
|
|
{
|
|
|
|
/* Kill the process manually here */
|
|
|
|
CsrDestroyProcess(&CsrThread->ClientId, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove our extra reference */
|
|
|
|
CsrLockedDereferenceThread(CsrThread);
|
2012-02-19 06:32:17 +00:00
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
|
|
|
|
/* Release the lock and keep looping */
|
|
|
|
CsrReleaseProcessLock();
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
continue;
|
2012-02-19 06:32:17 +00:00
|
|
|
}
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Reference the thread and release the lock */
|
|
|
|
CsrLockedReferenceThread(CsrThread);
|
|
|
|
CsrReleaseProcessLock();
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Check if this was an exception */
|
2012-02-19 19:40:28 +00:00
|
|
|
if (MessageType == LPC_EXCEPTION)
|
2012-02-19 06:32:17 +00:00
|
|
|
{
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Kill the process */
|
|
|
|
NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);
|
|
|
|
|
|
|
|
/* Destroy it from CSR */
|
2012-10-22 00:09:51 +00:00
|
|
|
CsrDestroyProcess(&ReceiveMsg.Header.ClientId, STATUS_ABANDONED);
|
2012-02-19 19:40:28 +00:00
|
|
|
|
|
|
|
/* Return a Debug Message */
|
2012-10-22 00:09:51 +00:00
|
|
|
DebugMessage = (PDBGKM_MSG)&ReceiveMsg;
|
2012-02-19 19:40:28 +00:00
|
|
|
DebugMessage->ReturnedStatus = DBG_CONTINUE;
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = &ReceiveMsg;
|
2012-02-19 06:32:17 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-02-19 20:13:07 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Remove our extra reference */
|
|
|
|
CsrDereferenceThread(CsrThread);
|
2012-02-19 06:32:17 +00:00
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
else if (MessageType == LPC_ERROR_EVENT)
|
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
/* 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 */
|
|
|
|
CsrpCheckRequestThreads();
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
ReplyMsg = NULL;
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CsrDereferenceThread(CsrThread);
|
|
|
|
ReplyMsg = &ReceiveMsg;
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Something else */
|
|
|
|
CsrDereferenceThread(CsrThread);
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Keep looping */
|
|
|
|
continue;
|
2006-10-30 14:20:45 +00:00
|
|
|
}
|
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* We got an API Request */
|
|
|
|
CsrLockedReferenceThread(CsrThread);
|
|
|
|
CsrReleaseProcessLock();
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* This is an API call, get the Server ID */
|
|
|
|
ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg.ApiNumber);
|
|
|
|
|
|
|
|
/* Make sure that the ID is within limits, and the Server DLL loaded */
|
|
|
|
ServerDll = NULL;
|
|
|
|
if ((ServerId >= CSR_SERVER_DLL_MAX) ||
|
|
|
|
(!(ServerDll = CsrLoadedServerDll[ServerId])))
|
|
|
|
{
|
|
|
|
/* We are beyond the Maximum Server ID */
|
|
|
|
DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
|
|
|
|
ServerId, ServerDll);
|
|
|
|
DbgBreakPoint();
|
|
|
|
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ReplyMsg = &ReceiveMsg;
|
|
|
|
ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
|
|
|
|
CsrDereferenceThread(CsrThread);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Get the API ID, normalized with our Base ID */
|
|
|
|
ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber) - ServerDll->ApiBase;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Make sure that the ID is within limits, and the entry exists */
|
|
|
|
if (ApiId >= ServerDll->HighestApiSupported)
|
|
|
|
{
|
|
|
|
/* We are beyond the Maximum API ID, or it doesn't exist */
|
|
|
|
DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
|
|
|
|
CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber),
|
|
|
|
&ServerDll->Name);
|
|
|
|
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ReplyMsg = &ReceiveMsg;
|
|
|
|
ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
|
|
|
|
CsrDereferenceThread(CsrThread);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CsrDebug & 2)
|
|
|
|
{
|
|
|
|
DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
|
|
|
|
Teb->ClientId.UniqueThread,
|
|
|
|
ReceiveMsg.Header.ClientId.UniqueProcess,
|
|
|
|
ReceiveMsg.Header.ClientId.UniqueThread,
|
|
|
|
ServerDll->NameTable[ApiId],
|
|
|
|
CsrThread);
|
|
|
|
}
|
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Assume success */
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = &ReceiveMsg;
|
|
|
|
ReceiveMsg.Status = STATUS_SUCCESS;
|
2012-02-19 19:40:28 +00:00
|
|
|
|
|
|
|
/* Now we reply to a particular client */
|
|
|
|
ReplyPort = CsrThread->Process->ClientPort;
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Check if there's a capture buffer */
|
|
|
|
if (ReceiveMsg.CsrCaptureData)
|
|
|
|
{
|
|
|
|
/* Capture the arguments */
|
|
|
|
if (!CsrCaptureArguments(CsrThread, &ReceiveMsg))
|
|
|
|
{
|
|
|
|
/* Ignore this message if we failed to get the arguments */
|
|
|
|
CsrDereferenceThread(CsrThread);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
|
|
|
|
/* Validation complete, start SEH */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* Make sure we have enough threads */
|
|
|
|
CsrpCheckRequestThreads();
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
Teb->CsrClientThread = CsrThread;
|
2012-02-19 19:40:28 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Call the API and get the result */
|
|
|
|
Reply = 0;
|
|
|
|
ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply);
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-02-19 19:40:28 +00:00
|
|
|
/* Increase the static thread count */
|
|
|
|
_InterlockedIncrement(&CsrpStaticThreadCount);
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
Teb->CsrClientThread = CurrentThread;
|
2012-09-15 16:33:30 +00:00
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
if (Reply == 3)
|
2012-02-19 19:40:28 +00:00
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
|
|
|
if (ReceiveMsg.CsrCaptureData)
|
|
|
|
{
|
|
|
|
CsrReleaseCapturedArguments(&ReceiveMsg);
|
|
|
|
}
|
|
|
|
CsrDereferenceThread(CsrThread);
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
2012-10-22 00:09:51 +00:00
|
|
|
}
|
|
|
|
else if (Reply == 2)
|
|
|
|
{
|
|
|
|
NtReplyPort(ReplyPort, &ReplyMsg->Header);
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
CsrDereferenceThread(CsrThread);
|
|
|
|
}
|
2012-10-22 00:09:51 +00:00
|
|
|
else if (Reply == 1)
|
|
|
|
{
|
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
ReplyMsg = NULL;
|
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
else
|
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
if (ReceiveMsg.CsrCaptureData)
|
|
|
|
{
|
|
|
|
CsrReleaseCapturedArguments(&ReceiveMsg);
|
|
|
|
}
|
2012-02-19 19:40:28 +00:00
|
|
|
CsrDereferenceThread(CsrThread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
|
|
|
|
{
|
2012-10-22 00:09:51 +00:00
|
|
|
ReplyMsg = NULL;
|
2012-02-19 19:40:28 +00:00
|
|
|
ReplyPort = CsrApiPort;
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2003-12-02 11:38:47 +00:00
|
|
|
}
|
2006-11-05 20:31:35 +00:00
|
|
|
|
2012-02-16 16:40:15 +00:00
|
|
|
/* We're out of the loop for some reason, terminate! */
|
|
|
|
NtTerminateThread(NtCurrentThread(), Status);
|
2012-10-22 00:09:51 +00:00
|
|
|
return Status;
|
1999-12-22 14:48:30 +00:00
|
|
|
}
|
2012-11-05 00:23:58 +00:00
|
|
|
|
|
|
|
/*++
|
|
|
|
* @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
|
|
|
|
* otherwise.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
CsrApiPortInitialize(VOID)
|
2012-02-16 06:57:27 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
ULONG Size;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
2012-10-22 00:09:51 +00:00
|
|
|
NTSTATUS Status;
|
2012-11-05 00:23:58 +00:00
|
|
|
HANDLE hRequestEvent, hThread;
|
|
|
|
CLIENT_ID ClientId;
|
|
|
|
PLIST_ENTRY ListHead, NextEntry;
|
|
|
|
PCSR_THREAD ServerThread;
|
2012-02-16 06:57:27 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Calculate how much space we'll need for the Port Name */
|
|
|
|
Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);
|
2012-02-16 06:57:27 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Create the buffer for it */
|
|
|
|
CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
|
|
|
|
if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY;
|
2012-02-16 06:57:27 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Setup the rest of the empty string */
|
|
|
|
CsrApiPortName.Length = 0;
|
|
|
|
CsrApiPortName.MaximumLength = (USHORT)Size;
|
|
|
|
RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName);
|
|
|
|
RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP);
|
|
|
|
RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME);
|
|
|
|
if (CsrDebug & 1)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName);
|
|
|
|
DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
|
|
|
|
sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE));
|
2012-10-22 00:09:51 +00:00
|
|
|
}
|
2012-02-16 06:57:27 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* FIXME: Create a Security Descriptor */
|
2012-10-22 00:09:51 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Initialize the Attributes */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&CsrApiPortName,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL /* FIXME*/);
|
2012-10-22 00:09:51 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Create the Port Object */
|
|
|
|
Status = NtCreatePort(&CsrApiPort,
|
|
|
|
&ObjectAttributes,
|
|
|
|
LPC_MAX_DATA_LENGTH, // HACK: the real value is: sizeof(CSR_CONNECTION_INFO),
|
|
|
|
LPC_MAX_MESSAGE_LENGTH, // HACK: the real value is: sizeof(CSR_API_MESSAGE),
|
|
|
|
16 * PAGE_SIZE);
|
|
|
|
if (NT_SUCCESS(Status))
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Create the event the Port Thread will use */
|
|
|
|
Status = NtCreateEvent(&hRequestEvent,
|
|
|
|
EVENT_ALL_ACCESS,
|
|
|
|
NULL,
|
|
|
|
SynchronizationEvent,
|
|
|
|
FALSE);
|
|
|
|
if (NT_SUCCESS(Status))
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
|
|
|
/* 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 */
|
|
|
|
Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Next thread */
|
|
|
|
NextEntry = NextEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We don't need this anymore */
|
|
|
|
NtClose(hRequestEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name CsrConnectToUser
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The CsrConnectToUser connects to the User subsystem.
|
|
|
|
*
|
|
|
|
* @param None
|
|
|
|
*
|
|
|
|
* @return A pointer to the CSR Thread
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
PCSR_THREAD
|
|
|
|
NTAPI
|
|
|
|
CsrConnectToUser(VOID)
|
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
#if 0 // This code is OK, however it is ClientThreadSetup which sucks.
|
2012-10-22 00:09:51 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
ANSI_STRING DllName;
|
|
|
|
UNICODE_STRING TempName;
|
|
|
|
HANDLE hUser32;
|
|
|
|
STRING StartupName;
|
|
|
|
PTEB Teb = NtCurrentTeb();
|
|
|
|
PCSR_THREAD CsrThread;
|
|
|
|
BOOLEAN Connected;
|
|
|
|
|
|
|
|
/* Check if we didn't already find it */
|
|
|
|
if (!CsrClientThreadSetup)
|
|
|
|
{
|
|
|
|
/* Get the DLL Handle for user32.dll */
|
|
|
|
RtlInitAnsiString(&DllName, "user32");
|
|
|
|
RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
|
|
|
|
Status = LdrGetDllHandle(NULL,
|
|
|
|
NULL,
|
|
|
|
&TempName,
|
|
|
|
&hUser32);
|
|
|
|
RtlFreeUnicodeString(&TempName);
|
|
|
|
|
2012-11-20 19:34:03 +00:00
|
|
|
/* If we got the handle, get the Client Thread Startup Entrypoint */
|
2012-10-22 00:09:51 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
RtlInitAnsiString(&StartupName,"ClientThreadSetup");
|
|
|
|
Status = LdrGetProcedureAddress(hUser32,
|
|
|
|
&StartupName,
|
|
|
|
0,
|
|
|
|
(PVOID)&CsrClientThreadSetup);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect to user32 */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
Connected = CsrClientThreadSetup();
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
Connected = FALSE;
|
|
|
|
} _SEH2_END;
|
|
|
|
|
|
|
|
if (!Connected)
|
|
|
|
{
|
|
|
|
DPRINT1("CSRSS: CsrConnectToUser failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save pointer to this thread in TEB */
|
|
|
|
CsrAcquireProcessLock();
|
|
|
|
CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
|
|
|
|
CsrReleaseProcessLock();
|
|
|
|
if (CsrThread) Teb->CsrClientThread = CsrThread;
|
|
|
|
|
|
|
|
/* Return it */
|
|
|
|
return CsrThread;
|
2012-11-05 00:23:58 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
PTEB Teb = NtCurrentTeb();
|
|
|
|
PCSR_THREAD CsrThread;
|
|
|
|
|
|
|
|
/* Save pointer to this thread in TEB */
|
|
|
|
CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
|
|
|
|
if (CsrThread) Teb->CsrClientThread = CsrThread;
|
|
|
|
|
|
|
|
/* Return it */
|
|
|
|
return CsrThread;
|
|
|
|
#endif
|
2012-10-22 00:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name CsrQueryApiPort
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The CsrQueryApiPort routine returns a handle to the CSR API LPC port.
|
|
|
|
*
|
|
|
|
* @param None.
|
|
|
|
*
|
|
|
|
* @return A handle to the port.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
HANDLE
|
|
|
|
NTAPI
|
|
|
|
CsrQueryApiPort(VOID)
|
|
|
|
{
|
|
|
|
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
|
|
|
|
return CsrApiPort;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name CsrCaptureArguments
|
|
|
|
* @implemented NT5.1
|
|
|
|
*
|
|
|
|
* The CsrCaptureArguments routine validates a CSR Capture Buffer and
|
|
|
|
* re-captures it into a server CSR Capture Buffer.
|
|
|
|
*
|
|
|
|
* @param CsrThread
|
|
|
|
* Pointer to the CSR Thread performing the validation.
|
|
|
|
*
|
|
|
|
* @param ApiMessage
|
|
|
|
* Pointer to the CSR API Message containing the Capture Buffer
|
|
|
|
* that needs to be validated.
|
|
|
|
*
|
|
|
|
* @return TRUE if validation succeeded, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
CsrCaptureArguments(IN PCSR_THREAD CsrThread,
|
|
|
|
IN PCSR_API_MESSAGE ApiMessage)
|
|
|
|
{
|
|
|
|
PCSR_CAPTURE_BUFFER LocalCaptureBuffer = NULL, RemoteCaptureBuffer = NULL;
|
2012-11-05 00:23:58 +00:00
|
|
|
SIZE_T BufferDistance;
|
|
|
|
ULONG Length = 0;
|
|
|
|
ULONG i;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Use SEH to make sure this is valid */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* Get the buffer we got from whoever called NTDLL */
|
|
|
|
LocalCaptureBuffer = ApiMessage->CsrCaptureData;
|
2012-11-05 00:23:58 +00:00
|
|
|
Length = LocalCaptureBuffer->Size;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Now check if the buffer is inside our mapped section */
|
|
|
|
if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) ||
|
2012-11-05 00:23:58 +00:00
|
|
|
(((ULONG_PTR)LocalCaptureBuffer + Length) >= CsrThread->Process->ClientViewBounds))
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
|
|
|
/* Return failure */
|
|
|
|
DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView\n");
|
|
|
|
ApiMessage->Status = STATUS_INVALID_PARAMETER;
|
|
|
|
_SEH2_YIELD(return FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the Length is valid */
|
2012-11-05 00:23:58 +00:00
|
|
|
if ((FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
|
|
|
|
(LocalCaptureBuffer->PointerCount * sizeof(PVOID)) > Length) ||
|
|
|
|
(Length > MAXWORD))
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
|
|
|
/* Return failure */
|
|
|
|
DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", LocalCaptureBuffer);
|
|
|
|
DbgBreakPoint();
|
|
|
|
ApiMessage->Status = STATUS_INVALID_PARAMETER;
|
|
|
|
_SEH2_YIELD(return FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
/* Return failure */
|
|
|
|
ApiMessage->Status = STATUS_INVALID_PARAMETER;
|
|
|
|
_SEH2_YIELD(return FALSE);
|
|
|
|
} _SEH2_END;
|
|
|
|
|
|
|
|
/* We validated the incoming buffer, now allocate the remote one */
|
2012-11-05 00:23:58 +00:00
|
|
|
RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, Length);
|
2012-10-22 00:09:51 +00:00
|
|
|
if (!RemoteCaptureBuffer)
|
|
|
|
{
|
|
|
|
/* We're out of memory */
|
|
|
|
ApiMessage->Status = STATUS_NO_MEMORY;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the client's buffer */
|
2012-11-05 00:23:58 +00:00
|
|
|
RtlMoveMemory(RemoteCaptureBuffer, LocalCaptureBuffer, Length);
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Calculate the difference between our buffer and the client's */
|
|
|
|
BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/*
|
|
|
|
* Convert all the pointer offsets into real pointers, and make
|
|
|
|
* them point to the remote data buffer instead of the local one.
|
|
|
|
*/
|
|
|
|
for (i = 0 ; i < RemoteCaptureBuffer->PointerCount ; ++i)
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
if (RemoteCaptureBuffer->PointerOffsetsArray[i] != 0)
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
RemoteCaptureBuffer->PointerOffsetsArray[i] += (ULONG_PTR)ApiMessage;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Validate the bounds of the current pointer */
|
2012-11-05 00:23:58 +00:00
|
|
|
if ((*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] >= CsrThread->Process->ClientViewBase) &&
|
|
|
|
(*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] < CsrThread->Process->ClientViewBounds))
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
|
|
|
/* Modify the pointer to take into account its new position */
|
2012-11-05 00:23:58 +00:00
|
|
|
*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] += BufferDistance;
|
2012-10-22 00:09:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Invalid pointer, fail */
|
|
|
|
DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n");
|
|
|
|
DbgBreakPoint();
|
|
|
|
ApiMessage->Status = STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if we got success */
|
|
|
|
if (ApiMessage->Status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
/* Failure. Free the buffer and return*/
|
|
|
|
RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Success, save the previous buffer */
|
|
|
|
RemoteCaptureBuffer->PreviousCaptureBuffer = LocalCaptureBuffer;
|
|
|
|
ApiMessage->CsrCaptureData = RemoteCaptureBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Success */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name CsrReleaseCapturedArguments
|
|
|
|
* @implemented NT5.1
|
|
|
|
*
|
|
|
|
* The CsrReleaseCapturedArguments routine releases a Capture Buffer
|
|
|
|
* that was previously captured with CsrCaptureArguments.
|
|
|
|
*
|
|
|
|
* @param ApiMessage
|
|
|
|
* Pointer to the CSR API Message containing the Capture Buffer
|
|
|
|
* that needs to be released.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
|
|
|
|
{
|
|
|
|
PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
|
|
|
|
SIZE_T BufferDistance;
|
2012-11-05 00:23:58 +00:00
|
|
|
ULONG i;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Get the capture buffers */
|
|
|
|
RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
|
|
|
|
LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Do not continue if there is no captured buffer */
|
|
|
|
if (!RemoteCaptureBuffer) return;
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/* Free the previous one */
|
|
|
|
RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/* Calculate the difference between our buffer and the client's */
|
|
|
|
BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/*
|
|
|
|
* Convert back all the pointers into pointer offsets, and make them
|
|
|
|
* point to the local data buffer instead of the remote one (revert
|
|
|
|
* the logic of CsrCaptureArguments).
|
|
|
|
*/
|
|
|
|
for (i = 0 ; i < RemoteCaptureBuffer->PointerCount ; ++i)
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
if (RemoteCaptureBuffer->PointerOffsetsArray[i] != 0)
|
2012-02-16 06:57:27 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] -= BufferDistance;
|
|
|
|
RemoteCaptureBuffer->PointerOffsetsArray[i] -= (ULONG_PTR)ApiMessage;
|
2012-02-16 06:57:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the data back */
|
|
|
|
RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size);
|
|
|
|
|
|
|
|
/* Free our allocated buffer */
|
|
|
|
RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
|
|
|
|
}
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name CsrValidateMessageBuffer
|
|
|
|
* @implemented NT5.1
|
|
|
|
*
|
|
|
|
* The CsrValidateMessageBuffer routine validates a captured message buffer
|
|
|
|
* present in the CSR Api Message
|
|
|
|
*
|
|
|
|
* @param ApiMessage
|
|
|
|
* Pointer to the CSR API Message containing the CSR Capture Buffer.
|
|
|
|
*
|
|
|
|
* @param Buffer
|
|
|
|
* Pointer to the message buffer to validate.
|
|
|
|
*
|
2012-11-05 00:23:58 +00:00
|
|
|
* @param ElementCount
|
|
|
|
* Number of elements contained in the message buffer.
|
2012-10-22 00:09:51 +00:00
|
|
|
*
|
2012-11-05 00:23:58 +00:00
|
|
|
* @param ElementSize
|
|
|
|
* Size of each element.
|
2012-10-22 00:09:51 +00:00
|
|
|
*
|
|
|
|
* @return TRUE if validation suceeded, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN PVOID *Buffer,
|
2012-11-05 00:23:58 +00:00
|
|
|
IN ULONG ElementCount,
|
|
|
|
IN ULONG ElementSize)
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
|
|
|
PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;
|
2012-11-05 00:23:58 +00:00
|
|
|
// SIZE_T BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check whether we have a valid buffer pointer, elements
|
|
|
|
* of non-trivial size and that we don't overflow.
|
|
|
|
*/
|
|
|
|
if (!Buffer || ElementSize == 0 ||
|
|
|
|
(ULONGLONG)ElementCount * ElementSize > (ULONGLONG)0xFFFFFFFF)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Check if didn't get a buffer and there aren't any arguments to check */
|
2012-11-05 00:23:58 +00:00
|
|
|
// if (!*Buffer && (ElementCount * ElementSize == 0))
|
|
|
|
if (!*Buffer && ElementCount == 0) // Here ElementSize != 0 therefore only ElementCount can be == 0
|
|
|
|
return TRUE;
|
2012-10-22 00:09:51 +00:00
|
|
|
|
|
|
|
/* Check if we have no capture buffer */
|
|
|
|
if (!CaptureBuffer)
|
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
/*
|
|
|
|
* In this case, check only the Process ID
|
|
|
|
* and if there is a match, we succeed.
|
|
|
|
*/
|
2012-10-22 00:09:51 +00:00
|
|
|
if (NtCurrentTeb()->ClientId.UniqueProcess ==
|
|
|
|
ApiMessage->Header.ClientId.UniqueProcess)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Make sure that there is still space left in the buffer */
|
2012-11-05 00:23:58 +00:00
|
|
|
if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) >=
|
|
|
|
(ElementCount * ElementSize))
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
for (i = 0 ; i < CaptureBuffer->PointerCount ; ++i)
|
2012-10-22 00:09:51 +00:00
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
/*
|
|
|
|
* If the pointer offset is in fact equal to the
|
|
|
|
* real address of the buffer then it's OK.
|
|
|
|
*/
|
|
|
|
if (CaptureBuffer->PointerOffsetsArray[i] == (ULONG_PTR)Buffer /* BufferDistance + (ULONG_PTR)ApiMessage */)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-10-22 00:09:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Failure */
|
2012-11-05 00:23:58 +00:00
|
|
|
DPRINT1("CSRSRV: Bad message buffer %p\n", ApiMessage);
|
2012-10-22 00:09:51 +00:00
|
|
|
DbgBreakPoint();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-11-05 00:23:58 +00:00
|
|
|
/*** This is what we have in consrv/server.c ***
|
|
|
|
|
|
|
|
/\* Ensure that a captured buffer is safe to access *\/
|
|
|
|
BOOL FASTCALL
|
|
|
|
Win32CsrValidateBuffer(PCSR_PROCESS ProcessData, PVOID Buffer,
|
|
|
|
SIZE_T NumElements, SIZE_T ElementSize)
|
|
|
|
{
|
|
|
|
/\* Check that the following conditions are true:
|
|
|
|
* 1. The start of the buffer is somewhere within the process's
|
|
|
|
* shared memory section view.
|
|
|
|
* 2. The remaining space in the view is at least as large as the buffer.
|
|
|
|
* (NB: Please don't try to "optimize" this by using multiplication
|
|
|
|
* instead of division; remember that 2147483648 * 2 = 0.)
|
|
|
|
* 3. The buffer is DWORD-aligned.
|
|
|
|
*\/
|
|
|
|
ULONG_PTR Offset = (BYTE *)Buffer - (BYTE *)ProcessData->ClientViewBase;
|
|
|
|
if (Offset >= ProcessData->ClientViewBounds
|
|
|
|
|| NumElements > (ProcessData->ClientViewBounds - Offset) / ElementSize
|
|
|
|
|| (Offset & (sizeof(DWORD) - 1)) != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Invalid buffer %p(%u*%u); section view is %p(%u)\n",
|
|
|
|
Buffer, NumElements, ElementSize,
|
|
|
|
ProcessData->ClientViewBase, ProcessData->ClientViewBounds);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
***********************************************/
|
|
|
|
|
2012-10-22 00:09:51 +00:00
|
|
|
/*++
|
|
|
|
* @name CsrValidateMessageString
|
|
|
|
* @implemented NT5.1
|
|
|
|
*
|
|
|
|
* The CsrValidateMessageString validates a captured Wide-Character String
|
|
|
|
* present in a CSR API Message.
|
|
|
|
*
|
|
|
|
* @param ApiMessage
|
|
|
|
* Pointer to the CSR API Message containing the CSR Capture Buffer.
|
|
|
|
*
|
|
|
|
* @param MessageString
|
|
|
|
* Pointer to the buffer containing the string to validate.
|
|
|
|
*
|
|
|
|
* @return TRUE if validation suceeded, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN LPWSTR *MessageString)
|
|
|
|
{
|
2012-11-05 00:23:58 +00:00
|
|
|
if (MessageString)
|
|
|
|
{
|
|
|
|
return CsrValidateMessageBuffer(ApiMessage,
|
|
|
|
(PVOID*)MessageString,
|
|
|
|
wcslen(*MessageString) + 1,
|
|
|
|
sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-10-22 00:09:51 +00:00
|
|
|
}
|
|
|
|
|
2001-08-14 12:57:16 +00:00
|
|
|
/* EOF */
|