📄 api.c
字号:
ReplyMsg = NULL;
}
else
{
ReplyMsg = &ReceiveMsg;
}
}
else if (MessageType == LPC_REQUEST)
{
/* This is an API Message coming from a non-CSR Thread */
ReplyMsg = &ReceiveMsg;
ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
}
else if (MessageType == LPC_DATAGRAM)
{
/* This is an API call, get the Server ID */
ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg.Opcode);
/* 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 */
ReplyMsg = NULL;
}
else
{
/* Get the API ID */
ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode);
/* Normalize it with our Base ID */
ApiId -= ServerDll->ApiBase;
/* 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 */
ReplyMsg = NULL;
}
/* Assume success */
ReceiveMsg.Status = STATUS_SUCCESS;
/* Validation complete, start SEH */
_SEH_TRY
{
/* Make sure we have enough threads */
CsrCheckRequestThreads();
/* Call the API and get the result */
ReplyMsg = NULL;
(ServerDll->DispatchTable[ApiId])(&ReceiveMsg, &Reply);
/* Increase the static thread count */
InterlockedIncrement(&CsrpStaticThreadCount);
}
_SEH_EXCEPT(CsrUnhandledExceptionFilter)
{
ReplyMsg = NULL;
}
_SEH_END;
}
}
else
{
/* Some other ignored message type */
ReplyMsg = NULL;
}
/* Keep going */
continue;
}
/* 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 */
ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg;
if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
{
/* Reference the thread */
CsrThread->ReferenceCount++;
/* Destroy the thread in the API Message */
CsrDestroyThread(&ReceiveMsg.Header.ClientId);
/* 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);
}
/* Release the lock and keep looping */
CsrReleaseProcessLock();
ReplyMsg = NULL;
continue;
}
/* Reference the thread and release the lock */
CsrThread->ReferenceCount++;
CsrReleaseProcessLock();
/* Check if this was an exception */
if (MessageType == LPC_EXCEPTION)
{
/* Kill the process */
NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);
/* Destroy it from CSR */
CsrDestroyProcess(&ReceiveMsg.Header.ClientId, STATUS_ABANDONED);
/* Return a Debug Message */
DebugMessage = (PDBGKM_MSG)&ReceiveMsg;
DebugMessage->Status = DBG_CONTINUE;
ReplyMsg = &ReceiveMsg;
/* Remove our extra reference */
CsrDereferenceThread(CsrThread);
}
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)
{
ReplyMsg = NULL;
}
else
{
CsrDereferenceThread(CsrThread);
ReplyMsg = &ReceiveMsg;
}
}
else
{
/* Something else */
CsrDereferenceThread(CsrThread);
ReplyMsg = NULL;
}
/* Keep looping */
continue;
}
/* We got an API Request */
CsrDereferenceThread(CsrThread);
CsrReleaseProcessLock();
/* FIXME: Handle the API */
}
/* We're out of the loop for some reason, terminate! */
NtTerminateThread(NtCurrentThread(), Status);
return Status;
}
/*++
* @name CsrApiHandleConnectionRequest
*
* The CsrApiHandleConnectionRequest routine handles and accepts a new
* connection request to the CSR API LPC Port.
*
* @param ApiMessage
* Pointer to the incoming CSR API Message which contains the
* connection request.
*
* @return STATUS_SUCCESS in case of success, or status code which caused
* the routine to error.
*
* @remarks This routine is responsible for attaching the Shared Section to
* new clients connecting to CSR.
*
*--*/
NTSTATUS
NTAPI
CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
{
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;
/* Acquire the Process Lock */
CsrAcquireProcessLock();
/* Lookup the CSR Thread */
CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId);
/* Check if we have a thread */
if (CsrThread)
{
/* Get the Process */
CsrProcess = CsrThread->Process;
/* Make sure we have a Process as well */
if (CsrProcess)
{
/* Reference the Process */
CsrProcess->ReferenceCount++;
/* Release the lock */
CsrReleaseProcessLock();
/* Duplicate the Object Directory */
Status = NtDuplicateObject(NtCurrentProcess(),
CsrObjectDirectory,
CsrProcess->ProcessHandle,
&ConnectInfo->ObjectDirectory,
0,
0,
DUPLICATE_SAME_ACCESS |
DUPLICATE_SAME_ATTRIBUTES);
/* Acquire the lock */
CsrAcquireProcessLock();
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Attach the Shared Section */
Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);
/* Check how this went */
if (NT_SUCCESS(Status)) AllowConnection = TRUE;
}
/* Dereference the project */
CsrProcess->ReferenceCount--;
}
}
/* Release the lock */
CsrReleaseProcessLock();
/* Setup the Port View Structure */
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
RemotePortView.ViewSize = 0;
RemotePortView.ViewBase = NULL;
/* Save the Process ID */
ConnectInfo->ProcessId = NtCurrentTeb()->Cid.UniqueProcess;
/* Accept the Connection */
Status = NtAcceptConnectPort(&hPort,
AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
&ApiMessage->Header,
AllowConnection,
NULL,
&RemotePortView);
/* Check if the connection was established, or if we allowed it */
if (NT_SUCCESS(Status) && AllowConnection)
{
/* Set some Port Data in the Process */
CsrProcess->ClientPort = hPort;
CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
(ULONG_PTR)RemotePortView.ViewSize);
/* Complete the connection */
Status = NtCompleteConnectPort(hPort);
}
/* The accept or complete could've failed, let debug builds know */
if (!NT_SUCCESS(Status))
{
DPRINT1("CSRSS: Failure to accept connection. Status: %lx\n", Status);
}
/* Return status to caller */
return Status;
}
/*++
* @name CsrSbApiRequestThread
*
* The CsrSbApiRequestThread routine handles incoming messages or connection
* requests on the SM 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.
*
*--*/
VOID
NTAPI
CsrSbApiRequestThread(IN PVOID Parameter)
{
NTSTATUS Status;
SB_API_MESSAGE ReceiveMsg;
PSB_API_MESSAGE ReplyMsg = NULL;
PVOID PortContext;
ULONG MessageType;
/* Start the loop */
while (TRUE)
{
/* Wait for a message to come in */
Status = NtReplyWaitReceivePort(CsrSbApiPort,
&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;
}
/* Save the message type */
MessageType = ReceiveMsg.Header.u2.s2.Type;
/* Check if this is a connection request */
if (MessageType == LPC_CONNECTION_REQUEST)
{
/* Handle connection request */
CsrSbApiHandleConnectionRequest(&ReceiveMsg);
/* Start over */
ReplyMsg = NULL;
continue;
}
/* Check if the port died */
if (MessageType == LPC_PORT_CLOSED)
{
/* Close the handle if we have one */
if (PortContext) NtClose((HANDLE)PortContext);
/* Client died, start over */
ReplyMsg = NULL;
continue;
}
else if (MessageType == LPC_CLIENT_DIED)
{
/* Client died, start over */
ReplyMsg = NULL;
continue;
}
/*
* It's an API Message, check if it's within limits. If it's not, the
* NT Behaviour is to set this to the Maximum API.
*/
if (ReceiveMsg.Opcode > 4) ReceiveMsg.Opcode = 4;
/* Reuse the message */
ReplyMsg = &ReceiveMsg;
/* Make sure that the message is supported */
if (ReceiveMsg.Opcode < 4)
{
/* Call the API */
if (!(CsrServerSbApiDispatch[ReceiveMsg.Opcode])(&ReceiveMsg))
{
/* It failed, so return nothing */
ReplyMsg = NULL;
}
}
else
{
/* We don't support this API Number */
ReplyMsg->Status = STATUS_NOT_IMPLEMENTED;
}
}
}
/*++
* @name CsrSbApiHandleConnectionRequest
*
* The CsrSbApiHandleConnectionRequest routine handles and accepts a new
* connection request to the SM API LPC Port.
*
* @param ApiMessage
* Pointer to the incoming CSR API Message which contains the
* connection request.
*
* @return STATUS_SUCCESS in case of success, or status code which caused
* the routine to error.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrSbApiHandleConnectionRequest(IN PSB_API_MESSAGE Message)
{
NTSTATUS Status;
REMOTE_PORT_VIEW RemotePortView;
HANDLE hPort;
/* Set the Port View Structure Length */
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
/* Accept the connection */
Status = NtAcceptConnectPort(&hPort,
NULL,
(PPORT_MESSAGE)Message,
TRUE,
NULL,
&RemotePortView);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status);
return Status;
}
/* Complete the Connection */
if (!NT_SUCCESS(Status = NtCompleteConnectPort(hPort)))
{
DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status);
}
/* Return status */
return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -