summaryrefslogtreecommitdiffstats
path: root/private/ntos/dll/csrutil.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dll/csrutil.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/dll/csrutil.c')
-rw-r--r--private/ntos/dll/csrutil.c867
1 files changed, 867 insertions, 0 deletions
diff --git a/private/ntos/dll/csrutil.c b/private/ntos/dll/csrutil.c
new file mode 100644
index 000000000..c8cf598ee
--- /dev/null
+++ b/private/ntos/dll/csrutil.c
@@ -0,0 +1,867 @@
+/*++
+
+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 PointerOffsets;
+ ULONG CountPointers, 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;
+ CaptureBuffer->MessagePointerOffsets = (PULONG)
+ ((PCHAR)CaptureBuffer->MessagePointerOffsets +
+ CsrPortMemoryRemoteDelta);
+ CountPointers = CaptureBuffer->CountMessagePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ *(PULONG)Pointer += CsrPortMemoryRemoteDelta;
+ PointerOffsets[ -1 ] = Pointer - (ULONG)m;
+ }
+ }
+
+ //
+ // Loop over all of the pointers to Port Memory within the capture
+ // buffer and convert them into server pointers. Also, convert
+ // the pointers to pointers into offsets.
+ //
+
+ PointerOffsets = CaptureBuffer->CapturePointerOffsets;
+ CaptureBuffer->CapturePointerOffsets = (PULONG)
+ ((PCHAR)CaptureBuffer->CapturePointerOffsets +
+ CsrPortMemoryRemoteDelta);
+ CountPointers = CaptureBuffer->CountCapturePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ *(PULONG)Pointer += CsrPortMemoryRemoteDelta;
+ PointerOffsets[ -1 ] = Pointer - (ULONG)CaptureBuffer;
+ }
+ }
+ }
+
+ //
+ // 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
+ //
+
+ CaptureBuffer->MessagePointerOffsets = (PULONG)
+ ((PCHAR)CaptureBuffer->MessagePointerOffsets -
+ CsrPortMemoryRemoteDelta);
+ PointerOffsets = CaptureBuffer->MessagePointerOffsets;
+ CountPointers = CaptureBuffer->CountMessagePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ Pointer += (ULONG)m;
+ PointerOffsets[ -1 ] = Pointer;
+ *(PULONG)Pointer -= CsrPortMemoryRemoteDelta;
+ }
+ }
+
+ //
+ // Loop over all of the pointers to Port Memory within the capture
+ // buffer and convert them into client pointers. Also, convert
+ // the offsets pointers to pointers into back into pointers
+ //
+
+ CaptureBuffer->CapturePointerOffsets = (PULONG)
+ ((PCHAR)CaptureBuffer->CapturePointerOffsets -
+ CsrPortMemoryRemoteDelta);
+ PointerOffsets = CaptureBuffer->CapturePointerOffsets;
+ CountPointers = CaptureBuffer->CountCapturePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ Pointer += (ULONG)CaptureBuffer;
+ PointerOffsets[ -1 ] = Pointer;
+ *(PULONG)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 );
+}
+
+
+PCSR_CAPTURE_HEADER
+CsrAllocateCaptureBuffer(
+ IN ULONG CountMessagePointers,
+ IN ULONG CountCapturePointers,
+ 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.
+
+ CountCapturePointers - Number of pointers within the capture buffer
+ that will point to other 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 + CountCapturePointers;
+
+ //
+ // 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 += sizeof( CSR_CAPTURE_HEADER ) + (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;
+ CaptureBuffer->CountCapturePointers = 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.
+ //
+
+ if (CountPointers != 0) {
+ CaptureBuffer->MessagePointerOffsets = (PULONG)(CaptureBuffer + 1);
+
+ CaptureBuffer->CapturePointerOffsets =
+ CaptureBuffer->MessagePointerOffsets + CountMessagePointers;
+
+ RtlZeroMemory( CaptureBuffer->MessagePointerOffsets,
+ CountPointers * sizeof( ULONG )
+ );
+
+ CaptureBuffer->FreeSpace = (PCHAR)
+ (CaptureBuffer->CapturePointerOffsets + CountCapturePointers);
+ }
+ else {
+ CaptureBuffer->MessagePointerOffsets = NULL;
+ CaptureBuffer->CapturePointerOffsets = NULL;
+ CaptureBuffer->FreeSpace = (PCHAR)(CaptureBuffer + 1);
+ }
+
+ //
+ // 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)Pointer;
+
+ //
+ // Returned the actual length allocated.
+ //
+
+ return( Length );
+}
+
+
+ULONG
+CsrAllocateCapturePointer(
+ 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 within
+ the capture buffer itself.
+
+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 capture buffer 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.
+
+--*/
+
+{
+ //
+ // 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
+ //
+
+ 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->CapturePointerOffsets[ CaptureBuffer->CountCapturePointers++ ] =
+ (ULONG)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 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.
+
+ Buffer - Optional pointer to the buffer. If this parameter is
+ not present, then the counted string data structure is set to
+ the null string and no space is allocated from the capture
+ buffer.
+
+ Length - Length of the buffer.
+
+ CaptureString - 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 and no space is allocated from the capture
+ buffer.
+
+ Length - Length of the ASCII string.
+
+ MaximumLength - Maximum length of the string. Different for null
+ terminated strings, where Length does not include the null and
+ MaximumLength does.
+
+ CaptureString - Pointer to the counted string data structure that will
+ be filled in to point to the capture ASCII string.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // 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
+ );
+ 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;
+}
+
+
+
+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)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)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)StartAddress & (Alignment - 1)) != 0) {
+ RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
+ } else {
+ Temp = *StartAddress;
+ EndAddress = StartAddress + Length - 1;
+ Temp = *EndAddress;
+ }
+ }
+}