📄 api.c
字号:
/*++
* @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
* if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there
* was a problem executing the API.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg,
PCSR_API_MESSAGE ReplyMsg)
{
ULONG ServerId;
PCSR_SERVER_DLL ServerDll;
ULONG ApiId;
ULONG Reply;
NTSTATUS Status;
/* 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->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
return STATUS_ILLEGAL_FUNCTION;
}
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) ||
(ServerDll->ValidTable && !ServerDll->ValidTable[ApiId]))
{
/* We are beyond the Maximum API ID, or it doesn't exist */
ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
return STATUS_ILLEGAL_FUNCTION;
}
}
/* Validation complete, start SEH */
_SEH_TRY
{
/* Call the API and get the result */
Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply);
/* Return the result, no matter what it is */
ReplyMsg->Status = Status;
}
_SEH_HANDLE
{
/* If we got an exception, return access violation */
ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
}
_SEH_END;
/* Return success */
return STATUS_SUCCESS;
}
/*++
* @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)
{
NTSTATUS Status;
ANSI_STRING DllName;
UNICODE_STRING TempName;
HANDLE hUser32;
STRING StartupName;
PTEB Teb = NtCurrentTeb();
PCSR_THREAD CsrThread;
/* 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);
/* If we got teh handle, get the Client Thread Startup Entrypoint */
if (NT_SUCCESS(Status))
{
RtlInitAnsiString(&StartupName,"ClientThreadSetup");
Status = LdrGetProcedureAddress(hUser32,
&StartupName,
0,
(PVOID)&CsrClientThreadSetup);
}
}
/* Connect to user32 */
CsrClientThreadSetup();
/* Save pointer to this thread in TEB */
CsrThread = CsrLocateThreadInProcess(NULL, &Teb->Cid);
if (CsrThread) Teb->CsrClientThread = CsrThread;
/* Return it */
return CsrThread;
}
/*++
* @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;
ULONG LocalLength = 0;
PCSR_CAPTURE_BUFFER RemoteCaptureBuffer = NULL;
SIZE_T BufferDistance = 0;
ULONG PointerCount = 0;
ULONG_PTR **PointerOffsets = NULL;
ULONG_PTR *CurrentPointer = NULL;
/* Use SEH to make sure this is valid */
_SEH_TRY
{
/* Get the buffer we got from whoever called NTDLL */
LocalCaptureBuffer = ApiMessage->CsrCaptureData;
LocalLength = LocalCaptureBuffer->Size;
/* Now check if the buffer is inside our mapped section */
if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) ||
(((ULONG_PTR)LocalCaptureBuffer + LocalLength) >= CsrThread->Process->ClientViewBounds))
{
/* Return failure */
ApiMessage->Status = STATUS_INVALID_PARAMETER;
_SEH_YIELD(return FALSE);
}
/* Check if the Length is valid */
if (((LocalCaptureBuffer->PointerCount * 4 + sizeof(CSR_CAPTURE_BUFFER)) >
LocalLength) ||(LocalLength > MAXWORD))
{
/* Return failure */
ApiMessage->Status = STATUS_INVALID_PARAMETER;
_SEH_YIELD(return FALSE);
}
}
_SEH_HANDLE
{
/* Return failure */
ApiMessage->Status = STATUS_INVALID_PARAMETER;
_SEH_YIELD(return FALSE);
} _SEH_END;
/* We validated the incoming buffer, now allocate the remote one */
RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, LocalLength);
if (!RemoteCaptureBuffer)
{
/* We're out of memory */
ApiMessage->Status = STATUS_NO_MEMORY;
return FALSE;
}
/* Copy the client's buffer */
RtlMoveMemory(RemoteCaptureBuffer, LocalCaptureBuffer, LocalLength);
/* Copy the length */
RemoteCaptureBuffer->Size = LocalLength;
/* Calculate the difference between our buffer and the client's */
BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
/* Save the pointer count and offset pointer */
PointerCount = RemoteCaptureBuffer->PointerCount;
PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
/* Start the loop */
while (PointerCount)
{
/* Get the current pointer */
if ((CurrentPointer = *PointerOffsets++))
{
/* Add it to the CSR Message structure */
CurrentPointer += (ULONG_PTR)ApiMessage;
/* Validate the bounds of the current pointer */
if ((*CurrentPointer >= CsrThread->Process->ClientViewBase) &&
(*CurrentPointer < CsrThread->Process->ClientViewBounds))
{
/* Modify the pointer to take into account its new position */
*CurrentPointer += BufferDistance;
}
else
{
/* Invalid pointer, fail */
ApiMessage->Status = (ULONG)STATUS_INVALID_PARAMETER;
}
}
/* Move to the next Pointer */
PointerCount--;
}
/* 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;
PCSR_CAPTURE_BUFFER LocalCaptureBuffer;
SIZE_T BufferDistance;
ULONG PointerCount;
ULONG_PTR **PointerOffsets;
ULONG_PTR *CurrentPointer;
/* Get the capture buffers */
RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
/* Free the previous one */
RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
/* Find out the difference between the two buffers */
BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer;
/* Save the pointer count and offset pointer */
PointerCount = RemoteCaptureBuffer->PointerCount;
PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
/* Start the loop */
while (PointerCount)
{
/* Get the current pointer */
if ((CurrentPointer = *PointerOffsets++))
{
/* Add it to the CSR Message structure */
CurrentPointer += (ULONG_PTR)ApiMessage;
/* Modify the pointer to take into account its new position */
*CurrentPointer += BufferDistance;
}
/* Move to the next Pointer */
PointerCount--;
}
/* Copy the data back */
RtlMoveMemory(LocalCaptureBuffer,
RemoteCaptureBuffer,
RemoteCaptureBuffer->Size);
/* Free our allocated buffer */
RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
}
/*++
* @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.
*
* @param ArgumentSize
* Size of the message to check.
*
* @param ArgumentCount
* Number of messages to check.
*
* @return TRUE if validation suceeded, FALSE otherwise.
*
* @remarks None.
*
*--*/
BOOLEAN
NTAPI
CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
IN PVOID *Buffer,
IN ULONG ArgumentSize,
IN ULONG ArgumentCount)
{
PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;
SIZE_T BufferDistance;
ULONG PointerCount;
ULONG_PTR **PointerOffsets;
ULONG_PTR *CurrentPointer;
ULONG i;
/* Make sure there are some arguments */
if (!ArgumentCount) return FALSE;
/* Check if didn't get a buffer and there aren't any arguments to check */
if (!(*Buffer) && (!(ArgumentCount * ArgumentSize))) return TRUE;
/* Check if we have no capture buffer */
if (!CaptureBuffer)
{
/* In this case, check only the Process ID */
if (NtCurrentTeb()->Cid.UniqueProcess ==
ApiMessage->Header.ClientId.UniqueProcess)
{
/* There is a match, validation succeeded */
return TRUE;
}
}
else
{
/* Make sure that there is still space left in the buffer */
if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) <
(ArgumentCount * ArgumentSize))
{
/* Find out the difference between the two buffers */
BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
/* Save the pointer count */
PointerCount = CaptureBuffer->PointerCount;
PointerOffsets = (ULONG_PTR**)(CaptureBuffer + 1);
/* Start the loop */
for (i = 0; i < PointerCount; i++)
{
/* Get the current pointer */
CurrentPointer = *PointerOffsets++;
/* Check if its' equal to the difference */
if (*CurrentPointer == BufferDistance) return TRUE;
}
}
}
/* Failure */
return FALSE;
}
/*++
* @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)
{
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
return FALSE;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -