407 lines
11 KiB
C
407 lines
11 KiB
C
/*++
|
|
|
|
Copyright (c) 1991-1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Examine.c
|
|
|
|
Abstract:
|
|
|
|
This module contains Remote Admin Protocol (RAP) routines. These routines
|
|
are shared between XactSrv and RpcXlate.
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 07-Jan-1991
|
|
|
|
Environment:
|
|
|
|
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
|
|
05-Mar-1991 JohnRo
|
|
Converted from Xs (XactSrv) to Rap (Remote Admin Protocol) names.
|
|
15-Mar-1991 W-Shanku
|
|
Additional character support; changes to make code neater.
|
|
14-Apr-1991 JohnRo
|
|
Reduce recompiles.
|
|
15-May-1991 JohnRo
|
|
Added first cut at native vs. RAP handling.
|
|
Added support for REM_SEND_LENBUF for print APIs.
|
|
04-Jun-1991 JohnRo
|
|
Made changes suggested by PC-LINT.
|
|
11-Jul-1991 JohnRo
|
|
Support StructureAlignment parameter.
|
|
07-Oct-1991 JohnRo
|
|
Made changes suggested by PC-LINT.
|
|
16-Aug-1992 JohnRo
|
|
RAID 2920: Support UTC timezone in net code.
|
|
Use PREFIX_ equates.
|
|
|
|
--*/
|
|
|
|
|
|
// These must be included first:
|
|
|
|
#include <windef.h> // IN, LPDWORD, NULL, OPTIONAL, DWORD, etc.
|
|
#include <lmcons.h> // NET_API_STATUS
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <align.h> // ALIGN_WORD, etc.
|
|
#include <netdebug.h> // NetpAssert().
|
|
#include <prefix.h> // PREFIX_ equates.
|
|
#include <rap.h> // My prototype, LPDESC.
|
|
#include <remtypes.h> // REM_WORD, etc.
|
|
|
|
VOID
|
|
RapExamineDescriptor (
|
|
IN LPDESC DescriptorString,
|
|
IN LPDWORD ParmNum OPTIONAL,
|
|
OUT LPDWORD StructureSize OPTIONAL,
|
|
OUT LPDWORD LastPointerOffset OPTIONAL,
|
|
OUT LPDWORD AuxDataCountOffset OPTIONAL,
|
|
OUT LPDESC * ParmNumDescriptor OPTIONAL,
|
|
OUT LPDWORD StructureAlignment OPTIONAL,
|
|
IN RAP_TRANSMISSION_MODE TransmissionMode,
|
|
IN BOOL Native
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Performs various examination functions on a descriptor string, including
|
|
|
|
- finding the size of the fixed structure.
|
|
- finding the last pointer to variable-length data in the structure.
|
|
- finding the auxiliary descriptor character in the string.
|
|
- finding the type of a given field in the descriptor.
|
|
|
|
These functions traverse the descriptor string in a similar manner, and
|
|
are thus grouped together, with wrappers for individual functions
|
|
elsewhere.
|
|
|
|
Arguments:
|
|
|
|
DescriptorString - a string that describes a fixed-length structure.
|
|
|
|
ParmNum - an optional pointer to a DWORD indicating the field within
|
|
the descriptor to find.
|
|
|
|
StructureSize - a pointer to a DWORD to receive the size, in bytes,
|
|
of the structure.
|
|
|
|
LastPointerOffset - a pointer to a DWORD to receive the last pointer
|
|
to variable-length data in the structure. If there is no pointer
|
|
in the structure, the DWORD receives the constant value
|
|
NO_POINTER_IN_STRUCTURE.
|
|
|
|
AuxDataCountOffset - an optional pointer to a DWORD to receive the offset
|
|
of the auxiliary data structure count. This is set to
|
|
NO_AUX_DATA if none is found.
|
|
|
|
ParmNumDescriptor - an optional pointer to a LPDESC to receive a
|
|
pointer to a specific field within the descriptor.
|
|
|
|
StructureAlignment - an optional pointer to a DWORD to receive the
|
|
alignment of this structure if it must be aligned and padded to appear
|
|
in an array. (This will be set to 1 if no alignment is necessary.)
|
|
|
|
Transmission Mode - Indicates whether this array is part of a response,
|
|
a request, or both.
|
|
|
|
Native - TRUE iff the descriptor defines a native structure. (This flag is
|
|
used to decide whether or not to align fields.)
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
LPDESC s;
|
|
DWORD field;
|
|
DWORD size = 0;
|
|
DWORD auxDataCountOffset = NO_AUX_DATA;
|
|
DWORD lastPointerOffset = NO_POINTER_IN_STRUCTURE;
|
|
LPDESC parmNumDescriptor = NULL;
|
|
DWORD worstAlignmentSoFar = ALIGN_BYTE;
|
|
|
|
#define UPDATE_WORST_ALIGNMENT(value) \
|
|
if ( (value) > worstAlignmentSoFar) { \
|
|
worstAlignmentSoFar = value; \
|
|
}
|
|
|
|
#define POINTER_SIZE (Native ? sizeof(PVOID) : sizeof(DWORD))
|
|
|
|
//
|
|
// Check for wierdness that could break null pointer handling.
|
|
//
|
|
|
|
NetpAssert(sizeof(LPSTR) == sizeof(LPVOID));
|
|
|
|
//
|
|
// Walk through the descriptor string, updating the length count
|
|
// for each field described.
|
|
//
|
|
|
|
field = 1;
|
|
|
|
for ( s = DescriptorString; *s != '\0'; field++ ) {
|
|
|
|
if (( ParmNum != NULL ) && ( *ParmNum == field )) {
|
|
|
|
parmNumDescriptor = s;
|
|
}
|
|
|
|
switch ( *(s++) ) {
|
|
|
|
case REM_RCV_BYTE_PTR:
|
|
|
|
if (TransmissionMode == Request) {
|
|
|
|
//
|
|
// These aren't sent as part of request. Just skip past any
|
|
// array size numeric characters in descriptor.
|
|
//
|
|
|
|
(void) RapAsciiToDecimal( &s );
|
|
|
|
break;
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case REM_BYTE:
|
|
|
|
//
|
|
// A byte or array of bytes.
|
|
//
|
|
|
|
size += sizeof(CHAR) * RapDescArrayLength( s );
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_BYTE );
|
|
|
|
break;
|
|
|
|
case REM_BYTE_PTR:
|
|
case REM_FILL_BYTES:
|
|
|
|
//
|
|
// A pointer to a byte or array of bytes.
|
|
//
|
|
|
|
if (TransmissionMode == Response ) {
|
|
|
|
//
|
|
// In a response (Xactsrv-style) context, this type
|
|
// is allocated enough room for the pointer. Also skip
|
|
// over any array size numeric characters.
|
|
//
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_LPBYTE, Native);
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_LPBYTE );
|
|
lastPointerOffset = size;
|
|
|
|
size += POINTER_SIZE;
|
|
|
|
} else {
|
|
|
|
size += POINTER_SIZE;
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_BYTE );
|
|
|
|
}
|
|
|
|
//
|
|
// must move the descriptor past any arraylength info
|
|
//
|
|
|
|
(void) RapAsciiToDecimal( &s );
|
|
break;
|
|
|
|
case REM_RCV_WORD_PTR :
|
|
case REM_SEND_BUF_LEN :
|
|
|
|
if (TransmissionMode == Request) {
|
|
|
|
//
|
|
// These aren't sent as part of request. Just skip past any
|
|
// array size numeric characters in descriptor.
|
|
//
|
|
|
|
(void) RapAsciiToDecimal( &s );
|
|
|
|
break;
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case REM_WORD:
|
|
case REM_PARMNUM:
|
|
case REM_RCV_BUF_LEN:
|
|
case REM_ENTRIES_READ:
|
|
|
|
//
|
|
// A word or array of words.
|
|
//
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_WORD, Native);
|
|
size += sizeof(WORD) * RapDescArrayLength( s );
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_WORD );
|
|
|
|
break;
|
|
|
|
case REM_RCV_DWORD_PTR :
|
|
|
|
if (TransmissionMode == Request) {
|
|
|
|
//
|
|
// These aren't sent as part of request. Just skip past any
|
|
// array size numeric characters in descriptor.
|
|
//
|
|
|
|
(void) RapAsciiToDecimal( &s );
|
|
|
|
break;
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case REM_DWORD:
|
|
case REM_SIGNED_DWORD:
|
|
|
|
//
|
|
// A doubleword or array of doublewords.
|
|
//
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_DWORD, Native);
|
|
size += sizeof(DWORD) * RapDescArrayLength( s );
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
case REM_ASCIZ: // ptr to ASCIIZ string
|
|
case REM_ASCIZ_TRUNCATABLE: // ptr to truncatable ASCIZ string
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_LPSTR, Native);
|
|
lastPointerOffset = size;
|
|
size += POINTER_SIZE;
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_LPBYTE );
|
|
(void) RapDescStringLength( s );
|
|
|
|
break;
|
|
|
|
case REM_SEND_BUF_PTR: // ptr to send buffer
|
|
case REM_SEND_LENBUF: // FAR ptr to send buffer w/ len.
|
|
|
|
if (TransmissionMode == Request) {
|
|
|
|
//
|
|
// These aren't sent as part of request.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case REM_RCV_BUF_PTR: // ptr to receive buffer
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_LPBYTE, Native);
|
|
lastPointerOffset = size;
|
|
/* FALLTHROUGH */
|
|
|
|
case REM_NULL_PTR: // null ptr
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_LPSTR, Native);
|
|
size += POINTER_SIZE;
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_LPBYTE );
|
|
|
|
break;
|
|
|
|
case REM_AUX_NUM: // 16-bit aux. data count
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_WORD, Native);
|
|
auxDataCountOffset = size;
|
|
|
|
size += sizeof(WORD);
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_WORD );
|
|
|
|
break;
|
|
|
|
case REM_AUX_NUM_DWORD: // 32-bit aux. data count
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_DWORD, Native);
|
|
auxDataCountOffset = size;
|
|
|
|
size += sizeof(DWORD);
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
case REM_IGNORE :
|
|
case REM_UNSUPPORTED_FIELD :
|
|
|
|
//
|
|
// A placeholder for pad bytes. It represents no space in the
|
|
// structure.
|
|
//
|
|
|
|
break;
|
|
|
|
case REM_EPOCH_TIME_GMT: /*FALLTHROUGH*/
|
|
case REM_EPOCH_TIME_LOCAL:
|
|
|
|
//
|
|
// A time in seconds since 1970. 32-bits, unsigned.
|
|
//
|
|
|
|
size = RapPossiblyAlignCount(size, ALIGN_DWORD, Native);
|
|
size += sizeof(DWORD);
|
|
UPDATE_WORST_ALIGNMENT( ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// !!!!
|
|
NetpKdPrint(( PREFIX_NETRAP
|
|
"RapExamineDescriptor: unsupported character: "
|
|
FORMAT_DESC_CHAR " at " FORMAT_LPVOID ".\n",
|
|
*(s - 1), s - 1 ));
|
|
NetpAssert(FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set up return information as appropriate.
|
|
//
|
|
|
|
if ( StructureSize != NULL ) {
|
|
*StructureSize = size;
|
|
}
|
|
|
|
if ( LastPointerOffset != NULL ) {
|
|
*LastPointerOffset = lastPointerOffset;
|
|
}
|
|
|
|
if ( AuxDataCountOffset != NULL ) {
|
|
*AuxDataCountOffset = auxDataCountOffset;
|
|
}
|
|
|
|
if ( ParmNumDescriptor != NULL ) {
|
|
*ParmNumDescriptor = parmNumDescriptor;
|
|
}
|
|
|
|
if ( StructureAlignment != NULL ) {
|
|
*StructureAlignment = worstAlignmentSoFar;
|
|
}
|
|
|
|
return;
|
|
|
|
} // RapExamineDescriptor
|