887 lines
22 KiB
C
887 lines
22 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1989 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
dllutil.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains utility procedures for the Windows Client DLL
|
||
|
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Steve Wood (stevewo) 8-Oct-1990
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "csrdll.h"
|
||
|
|
||
|
NTSTATUS
|
||
|
CsrClientCallServer(
|
||
|
IN OUT PCSR_API_MSG m,
|
||
|
IN OUT PCSR_CAPTURE_HEADER CaptureBuffer OPTIONAL,
|
||
|
IN CSR_API_NUMBER ApiNumber,
|
||
|
IN ULONG ArgLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function sends an API request to the Windows Emulation Subsystem
|
||
|
Server and waits for a reply.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
m - Pointer to the API request message to send.
|
||
|
|
||
|
CaptureBuffer - Optional pointer to a capture buffer located in the
|
||
|
Port Memory section that contains additional data being sent
|
||
|
to the server. Since Port Memory is also visible to the server,
|
||
|
no data needs to be copied, but pointers to locations within the
|
||
|
capture buffer need to be converted into pointers valid in the
|
||
|
server's process context, since the server's view of the Port Memory
|
||
|
is not at the same virtual address as the client's view.
|
||
|
|
||
|
ApiNumber - Small integer that is the number of the API being called.
|
||
|
|
||
|
ArgLength - Length, in bytes, of the argument portion located at the
|
||
|
end of the request message. Used to calculate the length of the
|
||
|
request message.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status Code from either client or server
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
PULONG_PTR PointerOffsets;
|
||
|
ULONG CountPointers;
|
||
|
ULONG_PTR Pointer;
|
||
|
|
||
|
//
|
||
|
// Initialize the header of the message.
|
||
|
//
|
||
|
|
||
|
if ((LONG)ArgLength < 0) {
|
||
|
ArgLength = (ULONG)(-(LONG)ArgLength);
|
||
|
m->h.u2.s2.Type = 0;
|
||
|
}
|
||
|
else {
|
||
|
m->h.u2.ZeroInit = 0;
|
||
|
}
|
||
|
|
||
|
ArgLength |= (ArgLength << 16);
|
||
|
ArgLength += ((sizeof( CSR_API_MSG ) - sizeof( m->u )) << 16) |
|
||
|
(FIELD_OFFSET( CSR_API_MSG, u ) - sizeof( m->h ));
|
||
|
m->h.u1.Length = ArgLength;
|
||
|
m->CaptureBuffer = NULL;
|
||
|
m->ApiNumber = ApiNumber;
|
||
|
|
||
|
//
|
||
|
// if the caller is within the server process, do the API call directly
|
||
|
// and skip the capture buffer fixups and LPC call.
|
||
|
//
|
||
|
|
||
|
if (CsrServerProcess == FALSE) {
|
||
|
|
||
|
//
|
||
|
// If the CaptureBuffer argument is present, then there is data located
|
||
|
// in the Port Memory section that is being passed to the server. All
|
||
|
// Port Memory pointers need to be converted so they are valid in the
|
||
|
// Server's view of the Port Memory.
|
||
|
//
|
||
|
|
||
|
if (ARGUMENT_PRESENT( CaptureBuffer )) {
|
||
|
//
|
||
|
// Store a pointer to the capture buffer in the message that is valid
|
||
|
// in the server process's context.
|
||
|
//
|
||
|
|
||
|
m->CaptureBuffer = (PCSR_CAPTURE_HEADER)
|
||
|
((PCHAR)CaptureBuffer + CsrPortMemoryRemoteDelta);
|
||
|
|
||
|
//
|
||
|
// Mark the fact that we are done allocating space from the end of
|
||
|
// the capture buffer.
|
||
|
//
|
||
|
|
||
|
CaptureBuffer->FreeSpace = NULL;
|
||
|
|
||
|
//
|
||
|
// Loop over all of the pointers to Port Memory within the message
|
||
|
// itself and convert them into server pointers. Also, convert
|
||
|
// the pointers to pointers into offsets.
|
||
|
//
|
||
|
|
||
|
PointerOffsets = CaptureBuffer->MessagePointerOffsets;
|
||
|
CountPointers = CaptureBuffer->CountMessagePointers;
|
||
|
while (CountPointers--) {
|
||
|
Pointer = *PointerOffsets++;
|
||
|
if (Pointer != 0) {
|
||
|
*(PULONG_PTR)Pointer += CsrPortMemoryRemoteDelta;
|
||
|
PointerOffsets[ -1 ] = Pointer - (ULONG_PTR)m;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Send the request to the server and wait for a reply. The wait is
|
||
|
// NOT alertable, because ? FIX,FIX
|
||
|
//
|
||
|
|
||
|
Status = NtRequestWaitReplyPort( CsrPortHandle,
|
||
|
(PPORT_MESSAGE)m,
|
||
|
(PPORT_MESSAGE)m
|
||
|
);
|
||
|
//
|
||
|
// If the CaptureBuffer argument is present then reverse what we did
|
||
|
// to the pointers above so that the client side code can use them
|
||
|
// again.
|
||
|
//
|
||
|
|
||
|
if (ARGUMENT_PRESENT( CaptureBuffer )) {
|
||
|
//
|
||
|
// Convert the capture buffer pointer back to a client pointer.
|
||
|
//
|
||
|
|
||
|
m->CaptureBuffer = (PCSR_CAPTURE_HEADER)
|
||
|
((PCHAR)m->CaptureBuffer - CsrPortMemoryRemoteDelta);
|
||
|
|
||
|
//
|
||
|
// Loop over all of the pointers to Port Memory within the message
|
||
|
// itself and convert them into client pointers. Also, convert
|
||
|
// the offsets pointers to pointers into back into pointers
|
||
|
//
|
||
|
|
||
|
PointerOffsets = CaptureBuffer->MessagePointerOffsets;
|
||
|
CountPointers = CaptureBuffer->CountMessagePointers;
|
||
|
while (CountPointers--) {
|
||
|
Pointer = *PointerOffsets++;
|
||
|
if (Pointer != 0) {
|
||
|
Pointer += (ULONG_PTR)m;
|
||
|
PointerOffsets[ -1 ] = Pointer;
|
||
|
*(PULONG_PTR)Pointer -= CsrPortMemoryRemoteDelta;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check for failed status and do something.
|
||
|
//
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
IF_DEBUG {
|
||
|
if (Status != STATUS_PORT_DISCONNECTED &&
|
||
|
Status != STATUS_INVALID_HANDLE
|
||
|
) {
|
||
|
DbgPrint( "CSRDLL: NtRequestWaitReplyPort failed - Status == %X\n",
|
||
|
Status
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
m->ReturnValue = Status;
|
||
|
}
|
||
|
} else {
|
||
|
m->h.ClientId = NtCurrentTeb()->ClientId;
|
||
|
Status = (CsrServerApiRoutine)((PCSR_API_MSG)m,
|
||
|
(PCSR_API_MSG)m
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Check for failed status and do something.
|
||
|
//
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
IF_DEBUG {
|
||
|
DbgPrint( "CSRDLL: Server side client call failed - Status == %X\n",
|
||
|
Status
|
||
|
);
|
||
|
}
|
||
|
|
||
|
m->ReturnValue = Status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The value of this function is whatever the server function returned.
|
||
|
//
|
||
|
|
||
|
return( m->ReturnValue );
|
||
|
}
|
||
|
|
||
|
HANDLE
|
||
|
CsrGetProcessId (
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function gets the process ID of the CSR process (for the session)
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Process ID of CSR
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
return CsrProcessId;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCSR_CAPTURE_HEADER
|
||
|
CsrAllocateCaptureBuffer(
|
||
|
IN ULONG CountMessagePointers,
|
||
|
IN ULONG Size
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function allocates a buffer from the Port Memory section for
|
||
|
use by the client in capture arguments into Port Memory. In addition to
|
||
|
specifying the size of the data that needs to be captured, the caller
|
||
|
needs to specify how many pointers to captured data will be passed.
|
||
|
Pointers can be located in either the request message itself, and/or
|
||
|
the capture buffer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CountMessagePointers - Number of pointers within the request message
|
||
|
that will point to locations within the allocated capture buffer.
|
||
|
|
||
|
Size - Total size of the data that will be captured into the capture
|
||
|
buffer.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
A pointer to the capture buffer header.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PCSR_CAPTURE_HEADER CaptureBuffer;
|
||
|
ULONG CountPointers;
|
||
|
|
||
|
//
|
||
|
// Calculate the total number of pointers that will be passed
|
||
|
//
|
||
|
|
||
|
CountPointers = CountMessagePointers;
|
||
|
|
||
|
//
|
||
|
// Calculate the total size of the capture buffer. This includes the
|
||
|
// header, the array of pointer offsets and the data length. We round
|
||
|
// the data length to a 32-bit boundary, assuming that each pointer
|
||
|
// points to data whose length is not aligned on a 32-bit boundary.
|
||
|
//
|
||
|
|
||
|
if (Size >= MAXLONG) {
|
||
|
//
|
||
|
// Bail early if too big
|
||
|
//
|
||
|
return NULL;
|
||
|
}
|
||
|
Size += FIELD_OFFSET(CSR_CAPTURE_HEADER, MessagePointerOffsets) + (CountPointers * sizeof( PVOID ));
|
||
|
Size = (Size + (3 * (CountPointers+1))) & ~3;
|
||
|
|
||
|
//
|
||
|
// Allocate the capture buffer from the Port Memory Heap.
|
||
|
//
|
||
|
|
||
|
CaptureBuffer = RtlAllocateHeap( CsrPortHeap, MAKE_CSRPORT_TAG( CAPTURE_TAG ), Size );
|
||
|
if (CaptureBuffer == NULL) {
|
||
|
|
||
|
//
|
||
|
// FIX, FIX - need to attempt the receive lost reply messages to
|
||
|
// to see if they contain CaptureBuffer pointers that can be freed.
|
||
|
//
|
||
|
|
||
|
return( NULL );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize the capture buffer header
|
||
|
//
|
||
|
|
||
|
CaptureBuffer->Length = Size;
|
||
|
CaptureBuffer->CountMessagePointers = 0;
|
||
|
|
||
|
//
|
||
|
// If there are pointers being passed then initialize the arrays of
|
||
|
// pointer offsets to zero. In either case set the free space pointer
|
||
|
// in the capture buffer header to point to the first 32-bit aligned
|
||
|
// location after the header, the arrays of pointer offsets are considered
|
||
|
// part of the header.
|
||
|
//
|
||
|
|
||
|
RtlZeroMemory( CaptureBuffer->MessagePointerOffsets,
|
||
|
CountPointers * sizeof( ULONG_PTR )
|
||
|
);
|
||
|
|
||
|
CaptureBuffer->FreeSpace = (PCHAR)
|
||
|
(CaptureBuffer->MessagePointerOffsets + CountPointers);
|
||
|
|
||
|
//
|
||
|
// Returned the address of the capture buffer.
|
||
|
//
|
||
|
|
||
|
return( CaptureBuffer );
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
CsrFreeCaptureBuffer(
|
||
|
IN PCSR_CAPTURE_HEADER CaptureBuffer
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function frees a capture buffer allocated by CsrAllocateCaptureBuffer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CaptureBuffer - Pointer to a capture buffer allocated by
|
||
|
CsrAllocateCaptureBuffer.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Free the capture buffer back to the Port Memory heap.
|
||
|
//
|
||
|
|
||
|
RtlFreeHeap( CsrPortHeap, 0, CaptureBuffer );
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
CsrAllocateMessagePointer(
|
||
|
IN OUT PCSR_CAPTURE_HEADER CaptureBuffer,
|
||
|
IN ULONG Length,
|
||
|
OUT PVOID *Pointer
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function allocates space from the capture buffer along with a
|
||
|
pointer to point to it. The pointer is presumed to be located in
|
||
|
the request message structure.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CaptureBuffer - Pointer to a capture buffer allocated by
|
||
|
CsrAllocateCaptureBuffer.
|
||
|
|
||
|
Length - Size of data being allocated from the capture buffer.
|
||
|
|
||
|
Pointer - Address of the pointer within the request message that
|
||
|
is to point to the space allocated out of the capture buffer.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The actual length of the buffer allocated, after it has been rounded
|
||
|
up to a multiple of 4.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
if (Length == 0) {
|
||
|
*Pointer = NULL;
|
||
|
Pointer = NULL;
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
|
||
|
//
|
||
|
// Set the returned pointer value to point to the next free byte in
|
||
|
// the capture buffer.
|
||
|
//
|
||
|
|
||
|
*Pointer = CaptureBuffer->FreeSpace;
|
||
|
|
||
|
//
|
||
|
// Round the length up to a multiple of 4
|
||
|
//
|
||
|
|
||
|
if (Length >= MAXLONG) {
|
||
|
//
|
||
|
// Bail early if too big
|
||
|
//
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Length = (Length + 3) & ~3;
|
||
|
|
||
|
//
|
||
|
// Update the free space pointer to point to the next available byte
|
||
|
// in the capture buffer.
|
||
|
//
|
||
|
|
||
|
CaptureBuffer->FreeSpace += Length;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Remember the location of this pointer so that CsrClientCallServer can
|
||
|
// convert it into a server pointer prior to sending the request to
|
||
|
// the server.
|
||
|
//
|
||
|
|
||
|
CaptureBuffer->MessagePointerOffsets[ CaptureBuffer->CountMessagePointers++ ] =
|
||
|
(ULONG_PTR)Pointer;
|
||
|
|
||
|
//
|
||
|
// Returned the actual length allocated.
|
||
|
//
|
||
|
|
||
|
return( Length );
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
CsrCaptureMessageBuffer(
|
||
|
IN OUT PCSR_CAPTURE_HEADER CaptureBuffer,
|
||
|
IN PVOID Buffer OPTIONAL,
|
||
|
IN ULONG Length,
|
||
|
OUT PVOID *CapturedBuffer
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function captures a buffer of bytes in an API request message.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CaptureBuffer - Pointer to a capture buffer allocated by
|
||
|
CsrAllocateCaptureBuffer.
|
||
|
|
||
|
Buffer - Optional pointer to the buffer. If this parameter is
|
||
|
not present, then no data is copied into capture buffer.
|
||
|
|
||
|
Length - Length of the buffer.
|
||
|
|
||
|
CapturedBuffer - Pointer to the field in the message that will
|
||
|
be filled in to point to the capture buffer.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Set the length fields of the captured string structure and allocated
|
||
|
// the Length for the string from the capture buffer.
|
||
|
//
|
||
|
|
||
|
CsrAllocateMessagePointer( CaptureBuffer,
|
||
|
Length,
|
||
|
CapturedBuffer
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// If Buffer parameter is not present or the length of the data is zero,
|
||
|
// return.
|
||
|
//
|
||
|
|
||
|
if (!ARGUMENT_PRESENT( Buffer ) || (Length == 0)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the buffer data to the capture area.
|
||
|
//
|
||
|
|
||
|
RtlMoveMemory( *CapturedBuffer, Buffer, Length );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CsrCaptureMessageString(
|
||
|
IN OUT PCSR_CAPTURE_HEADER CaptureBuffer,
|
||
|
IN PCSTR String OPTIONAL,
|
||
|
IN ULONG Length,
|
||
|
IN ULONG MaximumLength,
|
||
|
OUT PSTRING CapturedString
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function captures an ASCII string into a counted string data
|
||
|
structure located in an API request message.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CaptureBuffer - Pointer to a capture buffer allocated by
|
||
|
CsrAllocateCaptureBuffer.
|
||
|
|
||
|
String - Optional pointer to the ASCII string. If this parameter is
|
||
|
not present, then the counted string data structure is set to
|
||
|
the null string.
|
||
|
|
||
|
Length - Length of the ASCII string, ignored if String is NULL.
|
||
|
|
||
|
MaximumLength - Maximum length of the string. Different for null
|
||
|
terminated strings, where Length does not include the null and
|
||
|
MaximumLength does. This is always how much space is allocated
|
||
|
from the capture buffer.
|
||
|
|
||
|
CaptureString - Pointer to the counted string data structure that will
|
||
|
be filled in to point to the captured ASCII string.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
ASSERT(CapturedString != NULL);
|
||
|
//
|
||
|
// If String parameter is not present, then set the captured string
|
||
|
// to be the null string and returned.
|
||
|
//
|
||
|
|
||
|
if (!ARGUMENT_PRESENT( String )) {
|
||
|
CapturedString->Length = 0;
|
||
|
CapturedString->MaximumLength = (USHORT)MaximumLength;
|
||
|
CsrAllocateMessagePointer( CaptureBuffer,
|
||
|
MaximumLength,
|
||
|
(PVOID *)&CapturedString->Buffer
|
||
|
);
|
||
|
//
|
||
|
// Make it nul terminated if there is any room.
|
||
|
//
|
||
|
if (MaximumLength != 0) {
|
||
|
CapturedString->Buffer[0] = 0;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the length fields of the captured string structure and allocated
|
||
|
// the MaximumLength for the string from the capture buffer.
|
||
|
//
|
||
|
|
||
|
CapturedString->Length = (USHORT)Length;
|
||
|
CapturedString->MaximumLength = (USHORT)
|
||
|
CsrAllocateMessagePointer( CaptureBuffer,
|
||
|
MaximumLength,
|
||
|
(PVOID *)&CapturedString->Buffer
|
||
|
);
|
||
|
//
|
||
|
// If the Length of the ASCII string is non-zero then move it to the
|
||
|
// capture area.
|
||
|
//
|
||
|
|
||
|
if (Length != 0) {
|
||
|
RtlMoveMemory( CapturedString->Buffer, String, MaximumLength );
|
||
|
}
|
||
|
if (CapturedString->Length < CapturedString->MaximumLength) {
|
||
|
CapturedString->Buffer[ CapturedString->Length ] = '\0';
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CsrCaptureMessageUnicodeStringInPlace(
|
||
|
IN OUT PCSR_CAPTURE_HEADER CaptureBuffer,
|
||
|
IN OUT PUNICODE_STRING String
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function captures an ASCII string into a counted string data
|
||
|
structure located in an API request message.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CaptureBuffer - Pointer to a capture buffer allocated by
|
||
|
CsrAllocateCaptureBuffer.
|
||
|
|
||
|
String - Optional pointer to the Unicode string. If this parameter is
|
||
|
not present, then the counted string data structure is set to
|
||
|
the null string.
|
||
|
|
||
|
Length - Length of the Unicode string in bytes, ignored if String is NULL.
|
||
|
|
||
|
MaximumLength - Maximum length of the string. Different for null
|
||
|
terminated strings, where Length does not include the null and
|
||
|
MaximumLength does. This is always how much space is allocated
|
||
|
from the capture buffer.
|
||
|
|
||
|
CaptureString - Pointer to the counted string data structure that will
|
||
|
be filled in to point to the captured Unicode string.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None, but if you don't trust the String parameter, use a __try block.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ASSERT(String != NULL);
|
||
|
|
||
|
CsrCaptureMessageString(
|
||
|
CaptureBuffer,
|
||
|
(PCSTR)String->Buffer,
|
||
|
String->Length,
|
||
|
String->MaximumLength,
|
||
|
(PSTRING)String
|
||
|
);
|
||
|
|
||
|
// test > before substraction due to unsignedness
|
||
|
if (String->MaximumLength > String->Length) {
|
||
|
if ((String->MaximumLength - String->Length) >= sizeof(WCHAR)) {
|
||
|
String->Buffer[ String->Length / sizeof(WCHAR) ] = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
CsrCaptureMessageMultiUnicodeStringsInPlace(
|
||
|
IN OUT PCSR_CAPTURE_HEADER* InOutCaptureBuffer,
|
||
|
IN ULONG NumberOfStringsToCapture,
|
||
|
IN const PUNICODE_STRING* StringsToCapture
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Capture multiple unicode strings.
|
||
|
If the CaptureBuffer hasn't been allocated yet (passed as NULL), first
|
||
|
allocate it.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CaptureBuffer - Pointer to a capture buffer allocated by
|
||
|
CsrAllocateCaptureBuffer, or NULL, in which case we call CsrAllocateCaptureBuffer
|
||
|
for you; this is the case if you are only capturing these strings
|
||
|
and nothing else.
|
||
|
|
||
|
NumberOfStringsToCapture -
|
||
|
|
||
|
StringsToCapture -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
ULONG Length = 0;
|
||
|
ULONG i = 0;
|
||
|
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
|
||
|
|
||
|
if (InOutCaptureBuffer == NULL) {
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
CaptureBuffer = *InOutCaptureBuffer;
|
||
|
|
||
|
if (CaptureBuffer == NULL) {
|
||
|
Length = 0;
|
||
|
for (i = 0 ; i != NumberOfStringsToCapture ; ++i) {
|
||
|
if (StringsToCapture[i] != NULL) {
|
||
|
Length += StringsToCapture[i]->MaximumLength;
|
||
|
}
|
||
|
}
|
||
|
CaptureBuffer = CsrAllocateCaptureBuffer(NumberOfStringsToCapture, Length);
|
||
|
if (CaptureBuffer == NULL) {
|
||
|
Status = STATUS_NO_MEMORY;
|
||
|
goto Exit;
|
||
|
}
|
||
|
*InOutCaptureBuffer = CaptureBuffer;
|
||
|
}
|
||
|
for (i = 0 ; i != NumberOfStringsToCapture ; ++i) {
|
||
|
if (StringsToCapture[i] != NULL) {
|
||
|
CsrCaptureMessageUnicodeStringInPlace(
|
||
|
CaptureBuffer,
|
||
|
StringsToCapture[i]
|
||
|
);
|
||
|
} else {
|
||
|
}
|
||
|
}
|
||
|
Status = STATUS_SUCCESS;
|
||
|
Exit:
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
PLARGE_INTEGER
|
||
|
CsrCaptureTimeout(
|
||
|
IN ULONG MilliSeconds,
|
||
|
OUT PLARGE_INTEGER Timeout
|
||
|
)
|
||
|
{
|
||
|
if (MilliSeconds == -1) {
|
||
|
return( NULL );
|
||
|
}
|
||
|
else {
|
||
|
Timeout->QuadPart = Int32x32To64( MilliSeconds, -10000 );
|
||
|
return( (PLARGE_INTEGER)Timeout );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CsrProbeForWrite(
|
||
|
IN PVOID Address,
|
||
|
IN ULONG Length,
|
||
|
IN ULONG Alignment
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function probes a structure for read accessibility.
|
||
|
If the structure is not accessible, then an exception is raised.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Address - Supplies a pointer to the structure to be probed.
|
||
|
|
||
|
Length - Supplies the length of the structure.
|
||
|
|
||
|
Alignment - Supplies the required alignment of the structure expressed
|
||
|
as the number of bytes in the primitive datatype (e.g., 1 for char,
|
||
|
2 for short, 4 for long, and 8 for quad).
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
volatile CHAR *StartAddress;
|
||
|
volatile CHAR *EndAddress;
|
||
|
CHAR Temp;
|
||
|
|
||
|
//
|
||
|
// If the structure has zero length, then do not probe the structure for
|
||
|
// write accessibility or alignment.
|
||
|
//
|
||
|
|
||
|
if (Length != 0) {
|
||
|
|
||
|
//
|
||
|
// If the structure is not properly aligned, then raise a data
|
||
|
// misalignment exception.
|
||
|
//
|
||
|
|
||
|
ASSERT((Alignment == 1) || (Alignment == 2) ||
|
||
|
(Alignment == 4) || (Alignment == 8));
|
||
|
StartAddress = (volatile CHAR *)Address;
|
||
|
|
||
|
if (((ULONG_PTR)StartAddress & (Alignment - 1)) != 0) {
|
||
|
RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
|
||
|
} else {
|
||
|
//
|
||
|
// BUG, BUG - this should not be necessary once the 386 kernel
|
||
|
// makes system space inaccessable to user mode.
|
||
|
//
|
||
|
if ((ULONG_PTR)StartAddress > CsrNtSysInfo.MaximumUserModeAddress) {
|
||
|
RtlRaiseStatus(STATUS_ACCESS_VIOLATION);
|
||
|
}
|
||
|
|
||
|
Temp = *StartAddress;
|
||
|
*StartAddress = Temp;
|
||
|
EndAddress = StartAddress + Length - 1;
|
||
|
Temp = *EndAddress;
|
||
|
*EndAddress = Temp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CsrProbeForRead(
|
||
|
IN PVOID Address,
|
||
|
IN ULONG Length,
|
||
|
IN ULONG Alignment
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function probes a structure for read accessibility.
|
||
|
If the structure is not accessible, then an exception is raised.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Address - Supplies a pointer to the structure to be probed.
|
||
|
|
||
|
Length - Supplies the length of the structure.
|
||
|
|
||
|
Alignment - Supplies the required alignment of the structure expressed
|
||
|
as the number of bytes in the primitive datatype (e.g., 1 for char,
|
||
|
2 for short, 4 for long, and 8 for quad).
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
volatile CHAR *StartAddress;
|
||
|
volatile CHAR *EndAddress;
|
||
|
CHAR Temp;
|
||
|
|
||
|
//
|
||
|
// If the structure has zero length, then do not probe the structure for
|
||
|
// read accessibility or alignment.
|
||
|
//
|
||
|
|
||
|
if (Length != 0) {
|
||
|
|
||
|
//
|
||
|
// If the structure is not properly aligned, then raise a data
|
||
|
// misalignment exception.
|
||
|
//
|
||
|
|
||
|
ASSERT((Alignment == 1) || (Alignment == 2) ||
|
||
|
(Alignment == 4) || (Alignment == 8));
|
||
|
StartAddress = (volatile CHAR *)Address;
|
||
|
|
||
|
if (((ULONG_PTR)StartAddress & (Alignment - 1)) != 0) {
|
||
|
RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
|
||
|
} else {
|
||
|
Temp = *StartAddress;
|
||
|
EndAddress = StartAddress + Length - 1;
|
||
|
Temp = *EndAddress;
|
||
|
}
|
||
|
}
|
||
|
}
|