2045 lines
52 KiB
C
2045 lines
52 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991-92 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
XsSubs.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains various subroutines for XACTSRV.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
David Treadwell (davidtr) 07-Jan-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
05-Oct-1992 JohnRo
|
|||
|
RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. (4&5 too.)
|
|||
|
(Fixed XsFillAuxEnumBuffer.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "XactSrvP.h"
|
|||
|
#include <WinBase.h> // GetCurrentProcessId prototype
|
|||
|
#include <align.h>
|
|||
|
|
|||
|
VOID
|
|||
|
SmbCapturePtr(
|
|||
|
LPBYTE PointerDestination,
|
|||
|
LPBYTE PointerSource
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
XsBytesForConvertedStructure (
|
|||
|
IN LPBYTE InStructure,
|
|||
|
IN LPDESC InStructureDesc,
|
|||
|
IN LPDESC OutStructureDesc,
|
|||
|
IN RAP_CONVERSION_MODE Mode,
|
|||
|
IN BOOL MeaninglessInputPointers
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine determines the number of bytes that would be required
|
|||
|
to hold the input structure when converted to the structure
|
|||
|
described by OutStructureDesc.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InStructure - a pointer to the actual input structure.
|
|||
|
|
|||
|
InStructureDesc - a pointer to an ASCIIZ describing the format of the
|
|||
|
input structure.
|
|||
|
|
|||
|
OutStructureDesc - a pointer to an ASCIIZ describing the format of the
|
|||
|
output structure.
|
|||
|
|
|||
|
Mode - indicates mode of conversion (native to RAP or vice versa).
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD - The number of bytes required to hold the converted structure.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
DWORD bytesRequired = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Use RapConvertSingleEntry to get the size that the input structure
|
|||
|
// will take when converted to the format specified in the output
|
|||
|
// structure description. That routine should not actually write
|
|||
|
// anything--it should simply appear that there is no room to
|
|||
|
// write more data into, just as if an Enum buffer is full.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Should handle errors from RapConvertSingleEntry.
|
|||
|
// But the way this is used, existing code probably
|
|||
|
// won't break if we just ignore them.
|
|||
|
//
|
|||
|
|
|||
|
status = RapConvertSingleEntry(
|
|||
|
InStructure,
|
|||
|
InStructureDesc,
|
|||
|
MeaninglessInputPointers,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
OutStructureDesc,
|
|||
|
FALSE,
|
|||
|
NULL,
|
|||
|
&bytesRequired,
|
|||
|
Response,
|
|||
|
Mode
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// For native structures, we should make sure the buffer is an even amount,
|
|||
|
// to allow an even boundary for strings, as in Unicode.
|
|||
|
//
|
|||
|
|
|||
|
if ( Mode == RapToNative ) {
|
|||
|
|
|||
|
bytesRequired = ROUND_UP_COUNT( bytesRequired, ALIGN_DWORD );
|
|||
|
}
|
|||
|
|
|||
|
return bytesRequired;
|
|||
|
|
|||
|
} // XsBytesForConvertedStructure
|
|||
|
|
|||
|
|
|||
|
LPVOID
|
|||
|
XsCaptureParameters (
|
|||
|
IN LPTRANSACTION Transaction,
|
|||
|
OUT LPDESC *AuxDescriptor
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine captures all input parameters from the transaction block
|
|||
|
and puts them into a consistent structure that API handlers can access.
|
|||
|
It allocates memory to hold this structure. This memory should be
|
|||
|
freed by XsSetParameters after the API handler has done its work.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Transaction - a pointer to the transaction block describing the
|
|||
|
request.
|
|||
|
|
|||
|
AuxDescriptor - a pointer to a LPDESC which will hold a pointer to
|
|||
|
the auxiliary descriptor string if there is one, or NULL if there
|
|||
|
is not.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
LPVOID - a pointer to a buffer containing the captured parameters.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPDESC descriptorString;
|
|||
|
LPDESC descriptor;
|
|||
|
LPBYTE inParams;
|
|||
|
DWORD outParamsLength;
|
|||
|
LPBYTE outParams;
|
|||
|
LPBYTE outParamsPtr;
|
|||
|
WORD rcvBufferLength;
|
|||
|
|
|||
|
//
|
|||
|
// The first two bytes of the parameter section are the API number,
|
|||
|
// then comes the descriptor string.
|
|||
|
//
|
|||
|
|
|||
|
descriptorString = Transaction->InParameters + 2;
|
|||
|
|
|||
|
//
|
|||
|
// Find the actual parameter data in the input.
|
|||
|
//
|
|||
|
|
|||
|
inParams = XsFindParameters( Transaction );
|
|||
|
|
|||
|
//
|
|||
|
// Find out how much space to allocate to hold the parameters.
|
|||
|
//
|
|||
|
|
|||
|
outParamsLength = RapStructureSize( descriptorString, Response, FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// Allocate space to hold the output parameters.
|
|||
|
// In addition when the request fails the current APIs set the buflen field
|
|||
|
// In order to account for this additional buffer space is allocated. Since
|
|||
|
// this field is not located at the same offset we need to compute the
|
|||
|
// additional space reqd. to be the maximum of all the offsets. Currently
|
|||
|
// the 16 byte offset seems to suffice. When modifying apiparam.h ensure
|
|||
|
// that this is the case.
|
|||
|
//
|
|||
|
|
|||
|
outParams = NetpMemoryAllocate( sizeof(XS_PARAMETER_HEADER)
|
|||
|
+ outParamsLength +
|
|||
|
sizeof(DWORD) * 4);
|
|||
|
|
|||
|
if ( outParams == NULL ) {
|
|||
|
IF_DEBUG(ERRORS) {
|
|||
|
NetpKdPrint(( "XsCaptureParameters: unable to allocate %ld bytes\n",
|
|||
|
outParamsLength ));
|
|||
|
}
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Zero out the parameters and set outParamsPtr to the start of the
|
|||
|
// actual parameters.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( outParams, sizeof(XS_PARAMETER_HEADER) + outParamsLength );
|
|||
|
outParamsPtr = outParams + sizeof(XS_PARAMETER_HEADER);
|
|||
|
|
|||
|
//
|
|||
|
// For each character in the descriptor string, fill in the output
|
|||
|
// parameters as appropriate.
|
|||
|
//
|
|||
|
|
|||
|
for ( descriptor = descriptorString; *descriptor != '\0'; ) {
|
|||
|
|
|||
|
switch ( *descriptor++ ) {
|
|||
|
|
|||
|
case REM_ASCIZ:
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a pointer to a string. The actual string
|
|||
|
// is in the parameter data, so put a pointer to it in the
|
|||
|
// output structure.
|
|||
|
//
|
|||
|
// String parameters just get passed as is. It
|
|||
|
// is up to the API handler to convert the actual data.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// !!! Parameter string descriptors may not have maximum length
|
|||
|
// counts.
|
|||
|
//
|
|||
|
|
|||
|
if( isdigit( *descriptor ) ) {
|
|||
|
NetpMemoryFree( outParams );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
SmbCapturePtr( outParamsPtr, inParams );
|
|||
|
|
|||
|
//
|
|||
|
// Update pointers -- move inParams past end of string.
|
|||
|
//
|
|||
|
|
|||
|
inParams += ( strlen( inParams ) + 1 );
|
|||
|
outParamsPtr += sizeof(LPSTR);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_BYTE_PTR:
|
|||
|
case REM_FILL_BYTES:
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a pointer to a byte or array of bytes.
|
|||
|
//
|
|||
|
|
|||
|
SmbCapturePtr( outParamsPtr, inParams );
|
|||
|
|
|||
|
inParams += sizeof(BYTE) * RapDescArrayLength( descriptor );
|
|||
|
outParamsPtr += sizeof(LPBYTE);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_DWORD:
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a dword or array of dwords.
|
|||
|
//
|
|||
|
// !!! This assumes that an array of words will never be passed
|
|||
|
// as a parameter.
|
|||
|
|
|||
|
if( isdigit( *descriptor ) ) {
|
|||
|
NetpMemoryFree( outParams );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy over the double word and update pointers.
|
|||
|
//
|
|||
|
|
|||
|
SmbPutUlong(
|
|||
|
(LPDWORD)outParamsPtr,
|
|||
|
SmbGetUlong( (LPDWORD)inParams )
|
|||
|
);
|
|||
|
|
|||
|
inParams += sizeof(DWORD);
|
|||
|
outParamsPtr += sizeof(DWORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_ENTRIES_READ:
|
|||
|
case REM_RCV_WORD_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// Count of entries read (e) or receive word pointer (h).
|
|||
|
// This is an output parameter, so just zero it and
|
|||
|
// increment the output parameter pointer.
|
|||
|
//
|
|||
|
|
|||
|
SmbPutUshort( (LPWORD)outParamsPtr, 0 );
|
|||
|
|
|||
|
outParamsPtr += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_DWORD_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// Count of receive dword pointer (i).
|
|||
|
// This is an output parameter, so just zero it and
|
|||
|
// increment the output parameter pointer.
|
|||
|
//
|
|||
|
|
|||
|
SmbPutUlong( (LPDWORD)outParamsPtr, 0 );
|
|||
|
|
|||
|
outParamsPtr += sizeof(DWORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_NULL_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// Null pointer. Set output parameter to NULL, and increment
|
|||
|
// pointers.
|
|||
|
//
|
|||
|
|
|||
|
SmbCapturePtr( outParamsPtr, NULL );
|
|||
|
outParamsPtr += sizeof(LPSTR);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_BUF_LEN:
|
|||
|
|
|||
|
//
|
|||
|
// The length of the receive buffer (r).
|
|||
|
//
|
|||
|
|
|||
|
rcvBufferLength = SmbGetUshort( (LPWORD)inParams );
|
|||
|
|
|||
|
//
|
|||
|
// If the indicated buffer length is greater than the max
|
|||
|
// data count on the transaction, somebody messed up. Set
|
|||
|
// the length to MaxDataCount.
|
|||
|
//
|
|||
|
|
|||
|
if ( rcvBufferLength > (WORD)Transaction->MaxDataCount ) {
|
|||
|
|
|||
|
IF_DEBUG(ERRORS) {
|
|||
|
NetpKdPrint(( "XsCaptureParameters: OutBufLen %lx greater than MaxDataCount %lx.\n",
|
|||
|
rcvBufferLength, Transaction->MaxDataCount ));
|
|||
|
}
|
|||
|
|
|||
|
rcvBufferLength = (WORD)Transaction->MaxDataCount;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put the max output data length in the output parameters.
|
|||
|
//
|
|||
|
|
|||
|
SmbPutUshort( (LPWORD)outParamsPtr, rcvBufferLength );
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the receive buffer with zeroes for security.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( Transaction->OutData, (DWORD)rcvBufferLength );
|
|||
|
|
|||
|
inParams += sizeof(WORD);
|
|||
|
outParamsPtr += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_BUF_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// A pointer to a receive data buffer. There is nothing in
|
|||
|
// the transaction corresponding to this, but set a longword
|
|||
|
// in the output parameters to point to the data output
|
|||
|
// section of the transaction.
|
|||
|
//
|
|||
|
|
|||
|
SmbCapturePtr(
|
|||
|
outParamsPtr,
|
|||
|
Transaction->OutData
|
|||
|
);
|
|||
|
|
|||
|
outParamsPtr += sizeof(LPBYTE);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_BYTE_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// Return bytes, so just increment output parameter pointer.
|
|||
|
//
|
|||
|
|
|||
|
outParamsPtr += sizeof(BYTE) * RapDescArrayLength( descriptor );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_SEND_BUF_LEN:
|
|||
|
|
|||
|
//
|
|||
|
// The size of an input data buffer. Put the size of the
|
|||
|
// received data in the output structure.
|
|||
|
//
|
|||
|
|
|||
|
SmbPutUshort(
|
|||
|
(LPWORD)outParamsPtr,
|
|||
|
(WORD)Transaction->DataCount
|
|||
|
);
|
|||
|
|
|||
|
outParamsPtr += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_SEND_BUF_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// A pointer to a send data buffer. There is nothing in the
|
|||
|
// transaction corresponding to this, but set a longword in
|
|||
|
// the output parameters to point to the data input section
|
|||
|
// of the transaction.
|
|||
|
//
|
|||
|
|
|||
|
SmbCapturePtr( outParamsPtr, Transaction->InData );
|
|||
|
|
|||
|
outParamsPtr += sizeof(LPBYTE);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_WORD:
|
|||
|
case REM_PARMNUM:
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a word.
|
|||
|
//
|
|||
|
// !!! This assumes that an array of words will never be passed
|
|||
|
// as a parameter.
|
|||
|
|
|||
|
if( isdigit( *descriptor ) ) {
|
|||
|
NetpMemoryFree( outParams );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy over the word and update pointers.
|
|||
|
//
|
|||
|
|
|||
|
SmbPutUshort(
|
|||
|
(LPWORD)outParamsPtr,
|
|||
|
SmbGetUshort( (LPWORD)inParams )
|
|||
|
);
|
|||
|
|
|||
|
inParams += sizeof(WORD);
|
|||
|
outParamsPtr += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
IF_DEBUG(ERRORS) {
|
|||
|
NetpKdPrint(( "XsCaptureParameters: unsupported character at %lx: "
|
|||
|
"%c\n", descriptor - 1, *( descriptor - 1 ) ));
|
|||
|
NetpBreakPoint( );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Examine the data descriptor string to see if an auxiliary descriptor
|
|||
|
// string exists. If it does, the string starts right after the end
|
|||
|
// of the parameters.
|
|||
|
//
|
|||
|
|
|||
|
*AuxDescriptor = XsAuxiliaryDescriptor( ++descriptor, inParams );
|
|||
|
|
|||
|
return outParams;
|
|||
|
|
|||
|
} // XsCaptureParameters
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
XsCheckBufferSize (
|
|||
|
IN WORD BufferLength,
|
|||
|
IN LPDESC Descriptor,
|
|||
|
IN BOOL NativeFormat
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine determines if there is enough room in the buffer for the
|
|||
|
fixed component of at least one entry of the described structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BufferLength - the length of the buffer to test.
|
|||
|
|
|||
|
Descriptor - the format of the structure in the buffer.
|
|||
|
|
|||
|
NativeFormat - TRUE iff the buffer is in native (as opposed to RAP) format.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL - True if there is enough room, false if there isn't.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
if ( (DWORD)BufferLength
|
|||
|
>= RapStructureSize( Descriptor, Response, NativeFormat )) {
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} // XsCheckBufferSize
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
XsCheckSmbDescriptor(
|
|||
|
IN LPDESC SmbDescriptor,
|
|||
|
IN LPDESC ActualDescriptor
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks whether a descriptor passed in the SMB matches
|
|||
|
the actual descriptor expected, taking into account that the actual
|
|||
|
descriptor may have ignore fields which have no corresponding field in
|
|||
|
the SMB descriptor, and that the SMB descriptor may have null pointer
|
|||
|
fields instead of normal pointer fields. However, array-type fields
|
|||
|
have to be of the same length in both descriptors.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SmbDescriptor - the descriptor to be validated.
|
|||
|
|
|||
|
ActualDescriptor - the descriptor expected. Does not have to be an
|
|||
|
exact match - see the description above.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL - TRUE if the descriptor is valid,
|
|||
|
FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DESC_CHAR smbField;
|
|||
|
DESC_CHAR expField;
|
|||
|
DWORD smbFieldSize;
|
|||
|
DWORD expFieldSize;
|
|||
|
|
|||
|
while (( smbField = *SmbDescriptor++ ) != '\0' ) {
|
|||
|
|
|||
|
smbFieldSize = RapDescArrayLength( SmbDescriptor );
|
|||
|
|
|||
|
//
|
|||
|
// Skip over ignore fields.
|
|||
|
//
|
|||
|
|
|||
|
while ( *ActualDescriptor == REM_IGNORE ) {
|
|||
|
ActualDescriptor++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// There should be a corresponding field expected.
|
|||
|
//
|
|||
|
|
|||
|
if (( expField = *ActualDescriptor++ ) == '\0' ) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
expFieldSize = RapDescArrayLength( ActualDescriptor );
|
|||
|
|
|||
|
//
|
|||
|
// If both are actual data fields, they must be the same type and of
|
|||
|
// same length.
|
|||
|
//
|
|||
|
|
|||
|
if (( !RapIsPointer( expField ) || smbField != REM_NULL_PTR ) &&
|
|||
|
( smbField != expField || smbFieldSize != expFieldSize )) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// SMB provides a null pointer field, we are expecting any pointer.
|
|||
|
// This is OK, as long as there is no input array length.
|
|||
|
//
|
|||
|
|
|||
|
if ( smbField == REM_NULL_PTR &&
|
|||
|
( !RapIsPointer( expField ) || smbFieldSize != 1 )) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // XsCheckSmbDescriptor
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
XsConvertSetInfoBuffer(
|
|||
|
IN LPBYTE InBuffer,
|
|||
|
IN WORD BufferLength,
|
|||
|
IN WORD ParmNum,
|
|||
|
IN BOOL ConvertStrings,
|
|||
|
IN BOOL MeaninglessInputPointers,
|
|||
|
IN LPDESC InStructureDesc,
|
|||
|
IN LPDESC OutStructureDesc,
|
|||
|
IN LPDESC InSetInfoDesc,
|
|||
|
IN LPDESC OutSetInfoDesc,
|
|||
|
OUT LPBYTE * OutBuffer,
|
|||
|
OUT LPDWORD OutBufferLength OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine converts data for a SetInfo call based on the parameter
|
|||
|
number (ParmNum) value. The ParmNum indicates the field in the whole
|
|||
|
structure which has to be changed, and may be 0.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InBuffer - a pointer to the input buffer in 16-bit format.
|
|||
|
|
|||
|
BufferLength - the length of the input buffer.
|
|||
|
|
|||
|
ParmNum - the parameter number.
|
|||
|
|
|||
|
ConvertStrings - a boolean indicating whether string parameter data
|
|||
|
should be converted to a pointer form. If TRUE, the return data
|
|||
|
buffer will have a pointer to another place in the buffer where
|
|||
|
the string will be. If FALSE, the data buffer will have only the
|
|||
|
physical string.
|
|||
|
|
|||
|
InStructureDesc - the exact descriptor of the input buffer.
|
|||
|
|
|||
|
OutStructureDesc - the descriptor of the 32-bit output data, as found
|
|||
|
in RemDef.h.
|
|||
|
|
|||
|
InSetInfoDesc - the setinfo-specific descriptor of the input structure
|
|||
|
format, as found in RemDef.h.
|
|||
|
|
|||
|
OutSetInfoDesc - the setinfo-specific descriptor of the output structure
|
|||
|
format, as found in RemDef.h.
|
|||
|
|
|||
|
OutBuffer - a pointer to an LPBYTE which will get a pointer to the
|
|||
|
resulting output buffer.
|
|||
|
|
|||
|
OutBufferLength - an optional pointer to a DWORD which will get the
|
|||
|
length of the resulting output buffer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success if conversion was successful; otherwise
|
|||
|
the appropriate status to return to the user. The only exception is
|
|||
|
ERROR_NOT_SUPPORTED, which indicates that the particular parameter
|
|||
|
number is valid, but not on NT.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
LPDESC fieldDesc = NULL;
|
|||
|
DWORD stringLength;
|
|||
|
LPDESC subDesc = NULL;
|
|||
|
LPDESC subDesc2 = NULL;
|
|||
|
DWORD bufferSize;
|
|||
|
LPBYTE stringLocation;
|
|||
|
DWORD bytesRequired = 0;
|
|||
|
LPDESC OutDescCopy = OutStructureDesc;
|
|||
|
NET_API_STATUS status = NERR_Success;
|
|||
|
|
|||
|
//
|
|||
|
// The buffer length should be greater than 0.
|
|||
|
//
|
|||
|
|
|||
|
if ( BufferLength == 0 ) {
|
|||
|
|
|||
|
return NERR_BufTooSmall;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ( ParmNum != PARMNUM_ALL ) {
|
|||
|
|
|||
|
//
|
|||
|
// Check 16-bit parameter to see if it could be changed in OS/2.
|
|||
|
//
|
|||
|
|
|||
|
fieldDesc = RapParmNumDescriptor( InSetInfoDesc, (DWORD)ParmNum,
|
|||
|
Both, FALSE );
|
|||
|
|
|||
|
if ( fieldDesc == NULL ) {
|
|||
|
|
|||
|
return NERR_NoRoom;
|
|||
|
}
|
|||
|
|
|||
|
if ( fieldDesc[0] == REM_UNSUPPORTED_FIELD ) {
|
|||
|
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
InStructureDesc = RapParmNumDescriptor( InStructureDesc,
|
|||
|
(DWORD)ParmNum, Both, FALSE );
|
|||
|
}
|
|||
|
|
|||
|
NetpMemoryFree( fieldDesc );
|
|||
|
|
|||
|
//
|
|||
|
// Check 32-bit parameter to see if it is valid in NT.
|
|||
|
//
|
|||
|
|
|||
|
fieldDesc = RapParmNumDescriptor( OutSetInfoDesc, (DWORD)ParmNum,
|
|||
|
Both, TRUE );
|
|||
|
|
|||
|
if ( fieldDesc == NULL ) {
|
|||
|
|
|||
|
return NERR_NoRoom;
|
|||
|
}
|
|||
|
|
|||
|
if ( fieldDesc[0] == REM_IGNORE ) {
|
|||
|
|
|||
|
status = ERROR_NOT_SUPPORTED;
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
OutStructureDesc = RapParmNumDescriptor( OutStructureDesc,
|
|||
|
(DWORD)ParmNum, Both, TRUE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Filter out strings that are too long for LM2.x.
|
|||
|
//
|
|||
|
|
|||
|
if ( InStructureDesc[0] == REM_ASCIZ
|
|||
|
|| InStructureDesc[0] == REM_ASCIZ_TRUNCATABLE ) {
|
|||
|
|
|||
|
subDesc = InStructureDesc + 1;
|
|||
|
stringLength = RapDescStringLength( subDesc );
|
|||
|
subDesc = NULL;
|
|||
|
if ( stringLength && strlen( InBuffer ) >= stringLength ) {
|
|||
|
switch( InStructureDesc[0] ) {
|
|||
|
case REM_ASCIZ:
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
case REM_ASCIZ_TRUNCATABLE:
|
|||
|
InBuffer[stringLength - 1] = '\0';
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If a descriptor is a string pointer, the data is the actual
|
|||
|
// string, rather than a pointer. Find the length of the string,
|
|||
|
// and create a descriptor.
|
|||
|
//
|
|||
|
// Assuming all these arrays are string data, we
|
|||
|
// use available macros to generate an array big
|
|||
|
// enough to hold the converted string.
|
|||
|
|
|||
|
if ( InStructureDesc[0] == REM_ASCIZ
|
|||
|
|| InStructureDesc[0] == REM_ASCIZ_TRUNCATABLE ) {
|
|||
|
|
|||
|
if (( subDesc = NetpMemoryAllocate( MAX_DESC_SUBSTRING + 1 ))
|
|||
|
== NULL ) {
|
|||
|
status = NERR_NoRoom;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
stringLength = strlen( InBuffer ) + 1;
|
|||
|
subDesc[0] = REM_BYTE;
|
|||
|
_ltoa( stringLength, &subDesc[1], 10 );
|
|||
|
InStructureDesc = subDesc;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If output descriptor is a string pointer, and we are asked to keep
|
|||
|
// strings inline, make the target data an array of bytes. We find out
|
|||
|
// the length required by "walking" the input descriptor, and then
|
|||
|
// allocate memory to hold a similar descriptor.
|
|||
|
//
|
|||
|
// Assuming all these arrays are string data, we
|
|||
|
// use available macros to generate an array big
|
|||
|
// enough to hold the converted string. Because of the way
|
|||
|
// RAP works, if the destination string is Unicode, the destination
|
|||
|
// array will be exactly twice as long, and RAP will automatically
|
|||
|
// do the Unicode conversion.
|
|||
|
//
|
|||
|
|
|||
|
if (( OutStructureDesc[0] == REM_ASCIZ
|
|||
|
|| OutStructureDesc[0] == REM_ASCIZ_TRUNCATABLE )
|
|||
|
&& !ConvertStrings ) {
|
|||
|
|
|||
|
OutDescCopy = OutStructureDesc;
|
|||
|
subDesc2 = InStructureDesc + 1;
|
|||
|
stringLength = RapDescArrayLength( subDesc2 );
|
|||
|
if (( subDesc2 = NetpMemoryAllocate( MAX_DESC_SUBSTRING + 1 ))
|
|||
|
== NULL ) {
|
|||
|
status = NERR_NoRoom;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
subDesc2[0] = REM_BYTE;
|
|||
|
_ltoa( STRING_SPACE_REQD( stringLength ), &subDesc2[1], 10 ) ;
|
|||
|
OutStructureDesc = subDesc2;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ( !XsCheckBufferSize( BufferLength, InStructureDesc, FALSE )) {
|
|||
|
|
|||
|
status = NERR_BufTooSmall;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Find out how big a 32-bit data buffer we need.
|
|||
|
//
|
|||
|
|
|||
|
bufferSize = XsBytesForConvertedStructure(
|
|||
|
InBuffer,
|
|||
|
InStructureDesc,
|
|||
|
OutStructureDesc,
|
|||
|
RapToNative,
|
|||
|
MeaninglessInputPointers
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Allocate enough memory to hold the converted native buffer.
|
|||
|
//
|
|||
|
|
|||
|
*OutBuffer = NetpMemoryAllocate( bufferSize );
|
|||
|
|
|||
|
if ( *OutBuffer == NULL ) {
|
|||
|
|
|||
|
status = NERR_NoRoom;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Convert 16-bit data into 32-bit data and store it in the native
|
|||
|
// buffer.
|
|||
|
//
|
|||
|
|
|||
|
stringLocation = *OutBuffer + bufferSize;
|
|||
|
bytesRequired = 0;
|
|||
|
|
|||
|
status = RapConvertSingleEntry(
|
|||
|
InBuffer,
|
|||
|
InStructureDesc,
|
|||
|
MeaninglessInputPointers,
|
|||
|
*OutBuffer,
|
|||
|
*OutBuffer,
|
|||
|
OutStructureDesc,
|
|||
|
FALSE,
|
|||
|
&stringLocation,
|
|||
|
&bytesRequired,
|
|||
|
Response,
|
|||
|
RapToNative
|
|||
|
);
|
|||
|
|
|||
|
if ( status != NERR_Success ) {
|
|||
|
IF_DEBUG(ERRORS) {
|
|||
|
NetpKdPrint(( "XsConvertSetInfoBuffer: RapConvertSingleEntry "
|
|||
|
"failed %X\n", status ));
|
|||
|
}
|
|||
|
|
|||
|
status = NERR_InternalError;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
cleanup:
|
|||
|
|
|||
|
//
|
|||
|
// Free buffers.
|
|||
|
//
|
|||
|
|
|||
|
NetpMemoryFree( subDesc );
|
|||
|
NetpMemoryFree( subDesc2 );
|
|||
|
NetpMemoryFree( fieldDesc );
|
|||
|
|
|||
|
if ( OutBufferLength != NULL ) {
|
|||
|
|
|||
|
*OutBufferLength = bytesRequired;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
} // XsConvertSetInfoBuffer
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
XsDefaultEnumVerifyFunction (
|
|||
|
NET_API_STATUS ConvertStatus,
|
|||
|
PBYTE ConvertedEntry,
|
|||
|
PBYTE BaseAddress
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the default routine called by XsFillEnumBuffer to determine
|
|||
|
whether each converted entry should be retained or discarded. This
|
|||
|
routine directs XsFillEnumBuffer to discard any entry which
|
|||
|
RapConvertSingleEntry encountered an error trying to convert.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
ConvertStatus - the status which RapConvertSingleEntry encountered
|
|||
|
trying to convert this entry.
|
|||
|
|
|||
|
ConvertedEntry - a pointer to the buffer containing the converted entry.
|
|||
|
|
|||
|
BaseAddress - A pointer to the base used to calculate offsets.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success if the entry should be retained,
|
|||
|
or an error code if the entry should be discarded.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(ConvertedEntry);
|
|||
|
UNREFERENCED_PARAMETER(BaseAddress);
|
|||
|
|
|||
|
return ConvertStatus;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
XsFillAuxEnumBuffer (
|
|||
|
IN LPBYTE InBuffer,
|
|||
|
IN DWORD NumberOfEntries,
|
|||
|
IN LPDESC InStructureDesc,
|
|||
|
IN LPDESC InAuxStructureDesc,
|
|||
|
IN OUT LPBYTE OutBuffer,
|
|||
|
IN LPBYTE OutBufferStart,
|
|||
|
IN DWORD OutBufferLength,
|
|||
|
IN LPDESC OutStructureDesc,
|
|||
|
IN LPDESC OutAuxStructureDesc,
|
|||
|
IN PXACTSRV_ENUM_VERIFY_FUNCTION VerifyFunction OPTIONAL,
|
|||
|
OUT LPDWORD BytesRequired,
|
|||
|
OUT LPDWORD EntriesFilled,
|
|||
|
OUT LPDWORD InvalidEntries OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine copies all Enum structures which have auxiliary data
|
|||
|
from 32-bit format to 16-bit format. As many complete entries as
|
|||
|
possible are copied, then possibly some incomplete entries.
|
|||
|
All pointer fields are converted to offsets so that this buffer
|
|||
|
may be returned directly to the requesting client.
|
|||
|
|
|||
|
Enum buffers with auxiliary data have one or more auxiliary
|
|||
|
structures, with possible variable data, after each entry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InBuffer - a pointer to the input information in 32-bit format.
|
|||
|
|
|||
|
NumberOfEntries - the count of fixed structures in the input buffer.
|
|||
|
|
|||
|
InStructureDesc - description of the input fixed structure.
|
|||
|
|
|||
|
InAuxStructureDesc - description of the input auxiliary structure.
|
|||
|
|
|||
|
OutBuffer - a pointer to where to write the 16-bit buffer.
|
|||
|
|
|||
|
OutBufferStart - a pointer to the actual start of the 16-bit buffer.
|
|||
|
Used to calculate offsets for all pointers in structures.
|
|||
|
|
|||
|
OutBufferLength - length of the output buffer.
|
|||
|
|
|||
|
OutStructureDesc - description of the output fixed structure.
|
|||
|
|
|||
|
OutAuxStructureDesc - description of the output fixed structure.
|
|||
|
|
|||
|
VerifyFunction - a pointer to a function which is be called after
|
|||
|
each enum record is converted in order to determine whether
|
|||
|
the record should be retained or discarded. The function
|
|||
|
is passed the return code from RapConvertSingleEntry and
|
|||
|
a pointer to the converted entry. It must return NERR_SUCCESS
|
|||
|
if the entry is to be retained, or any error code if the entry
|
|||
|
is to be discarded. If no function is supplied, a default function
|
|||
|
is used, which discards an entry only if RapConvertSingleEntry
|
|||
|
returned an error trying to convert it.
|
|||
|
|
|||
|
BytesRequired - a pointer to a DWORD to receive the total number of
|
|||
|
bytes that would be required to hold the entire output buffer.
|
|||
|
|
|||
|
EntriesFilled - a pointer to a DWORD to receive the total number of
|
|||
|
entries that could be put in the buffer given.
|
|||
|
|
|||
|
InvalidEntries - an optional pointer to a DWORD to receive the total
|
|||
|
number of entries discarded by the verify function. If NULL, this
|
|||
|
value will be not be available to the caller.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NET_API_STATUS status;
|
|||
|
DWORD currentEntry;
|
|||
|
LPBYTE currentInEntryPtr;
|
|||
|
LPBYTE currentOutEntryPtr;
|
|||
|
LPBYTE outputStringLocation;
|
|||
|
LPBYTE oldStringLocation;
|
|||
|
DWORD inputStructureSize;
|
|||
|
DWORD inputAuxStructureSize;
|
|||
|
DWORD outputStructureSize;
|
|||
|
DWORD outputAuxStructureSize;
|
|||
|
DWORD inputAuxCount;
|
|||
|
DWORD currentAux;
|
|||
|
DWORD outputAuxOffset;
|
|||
|
DWORD newBytesRequired;
|
|||
|
DWORD auxBytesRequired;
|
|||
|
DWORD remainingSize;
|
|||
|
DWORD invalidEntries = 0;
|
|||
|
|
|||
|
//
|
|||
|
// In degenerate case, just call FillEnumBuffer.
|
|||
|
//
|
|||
|
|
|||
|
if ( InAuxStructureDesc == NULL || OutAuxStructureDesc == NULL ) {
|
|||
|
|
|||
|
XsFillEnumBuffer (
|
|||
|
InBuffer,
|
|||
|
NumberOfEntries,
|
|||
|
InStructureDesc,
|
|||
|
OutBuffer,
|
|||
|
OutBufferStart,
|
|||
|
OutBufferLength,
|
|||
|
OutStructureDesc,
|
|||
|
VerifyFunction,
|
|||
|
BytesRequired,
|
|||
|
EntriesFilled,
|
|||
|
InvalidEntries
|
|||
|
);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( VerifyFunction == NULL ) {
|
|||
|
VerifyFunction = &XsDefaultEnumVerifyFunction;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set up sizes of input and output structures.
|
|||
|
//
|
|||
|
|
|||
|
inputStructureSize = RapStructureSize( InStructureDesc, Response, TRUE );
|
|||
|
inputAuxStructureSize
|
|||
|
= RapStructureSize( InAuxStructureDesc, Response, TRUE );
|
|||
|
outputStructureSize = RapStructureSize( OutStructureDesc, Response, FALSE );
|
|||
|
outputAuxStructureSize
|
|||
|
= RapStructureSize( OutAuxStructureDesc, Response, FALSE );
|
|||
|
outputAuxOffset = RapAuxDataCountOffset( InStructureDesc, Response, TRUE );
|
|||
|
|
|||
|
outputStringLocation = (LPBYTE)OutBuffer + OutBufferLength;
|
|||
|
*BytesRequired = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Check if one fixed entry will fit.
|
|||
|
//
|
|||
|
|
|||
|
if ( inputStructureSize > OutBufferLength ) {
|
|||
|
|
|||
|
*EntriesFilled = 0;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Loop through the entries, converting along the way.
|
|||
|
//
|
|||
|
|
|||
|
currentInEntryPtr = InBuffer;
|
|||
|
currentOutEntryPtr = OutBuffer;
|
|||
|
*EntriesFilled = 0;
|
|||
|
|
|||
|
for ( currentEntry = 0; currentEntry < NumberOfEntries; currentEntry++ ) {
|
|||
|
|
|||
|
//
|
|||
|
// If there wasn't enough room for the conversion, we can quit now.
|
|||
|
//
|
|||
|
|
|||
|
if ( currentOutEntryPtr + outputStructureSize > outputStringLocation ) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
newBytesRequired = *BytesRequired;
|
|||
|
oldStringLocation = outputStringLocation;
|
|||
|
|
|||
|
//
|
|||
|
// Get the auxiliary number count.
|
|||
|
//
|
|||
|
|
|||
|
inputAuxCount = RapAuxDataCount(
|
|||
|
currentInEntryPtr,
|
|||
|
InStructureDesc,
|
|||
|
Response,
|
|||
|
TRUE
|
|||
|
);
|
|||
|
|
|||
|
NetpAssert( inputAuxCount != NO_AUX_DATA );
|
|||
|
|
|||
|
//
|
|||
|
// Convert the fixed entry.
|
|||
|
//
|
|||
|
|
|||
|
status = RapConvertSingleEntry(
|
|||
|
currentInEntryPtr,
|
|||
|
InStructureDesc,
|
|||
|
FALSE,
|
|||
|
OutBufferStart,
|
|||
|
currentOutEntryPtr,
|
|||
|
OutStructureDesc,
|
|||
|
TRUE,
|
|||
|
&outputStringLocation,
|
|||
|
&newBytesRequired,
|
|||
|
Response,
|
|||
|
NativeToRap
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Check if the entry is valid. If it is not, fix up pointers,
|
|||
|
// and start with the next entry in the list.
|
|||
|
// If there are more than 65536 auxiliary structures (which
|
|||
|
// probably never happens anyway), this entry is automatically
|
|||
|
// invalid.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
status = (*VerifyFunction)(
|
|||
|
status,
|
|||
|
currentOutEntryPtr,
|
|||
|
OutBufferStart
|
|||
|
);
|
|||
|
|
|||
|
if ( status != NERR_Success || inputAuxCount > 0xFFFF ) {
|
|||
|
|
|||
|
invalidEntries++;
|
|||
|
currentInEntryPtr += inputStructureSize
|
|||
|
+ inputAuxCount * inputAuxStructureSize;
|
|||
|
outputStringLocation = oldStringLocation;
|
|||
|
continue;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Prepare pointers for converting the auxiliary structures.
|
|||
|
//
|
|||
|
|
|||
|
currentInEntryPtr += inputStructureSize;
|
|||
|
currentOutEntryPtr += outputStructureSize;
|
|||
|
|
|||
|
//
|
|||
|
// Try to add the auxiliary structures.
|
|||
|
//
|
|||
|
|
|||
|
for ( currentAux = 0; currentAux < inputAuxCount; currentAux++ ) {
|
|||
|
|
|||
|
remainingSize = (DWORD)(outputStringLocation - currentOutEntryPtr);
|
|||
|
auxBytesRequired = 0;
|
|||
|
|
|||
|
status = RapConvertSingleEntry(
|
|||
|
currentInEntryPtr,
|
|||
|
InAuxStructureDesc,
|
|||
|
FALSE,
|
|||
|
OutBufferStart,
|
|||
|
currentOutEntryPtr,
|
|||
|
OutAuxStructureDesc,
|
|||
|
TRUE,
|
|||
|
&outputStringLocation,
|
|||
|
&auxBytesRequired,
|
|||
|
Response,
|
|||
|
NativeToRap
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Did this aux. entry fit? If all the aux. entries do not fit,
|
|||
|
// we are going to play it safe and say the main entry did not
|
|||
|
// fit.
|
|||
|
//
|
|||
|
|
|||
|
if ( status != NERR_Success || auxBytesRequired > remainingSize ) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
currentInEntryPtr += inputAuxStructureSize;
|
|||
|
currentOutEntryPtr += outputAuxStructureSize;
|
|||
|
newBytesRequired += auxBytesRequired;
|
|||
|
}
|
|||
|
|
|||
|
*BytesRequired = newBytesRequired;
|
|||
|
*EntriesFilled += 1;
|
|||
|
}
|
|||
|
|
|||
|
cleanup:
|
|||
|
|
|||
|
if ( InvalidEntries != NULL ) {
|
|||
|
|
|||
|
*InvalidEntries = invalidEntries;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // XsFillAuxEnumBuffer
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
XsFillEnumBuffer (
|
|||
|
IN LPBYTE InBuffer,
|
|||
|
IN DWORD NumberOfEntries,
|
|||
|
IN LPDESC InStructureDesc,
|
|||
|
IN OUT LPBYTE OutBuffer,
|
|||
|
IN LPBYTE OutBufferStart,
|
|||
|
IN DWORD OutBufferLength,
|
|||
|
IN LPDESC OutStructureDesc,
|
|||
|
IN PXACTSRV_ENUM_VERIFY_FUNCTION VerifyFunction OPTIONAL,
|
|||
|
OUT LPDWORD BytesRequired,
|
|||
|
OUT LPDWORD EntriesFilled,
|
|||
|
OUT LPDWORD InvalidEntries OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine copies all Enum structures from 32-bit format to
|
|||
|
16-bit format. As many complete entries as possible are copied,
|
|||
|
then possibly some incomplete entries. All pointer fields
|
|||
|
are converted to offsets so that this buffer may be returned
|
|||
|
directly to the requesting client.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InBuffer - a pointer to the input information in 32-bit format.
|
|||
|
|
|||
|
NumberOfEntries - the count of fixed structures in the input buffer.
|
|||
|
|
|||
|
InStructureDesc - description of the input fixed structure.
|
|||
|
|
|||
|
OutBuffer - a pointer to where to write the 16-bit buffer.
|
|||
|
|
|||
|
OutBufferStart - a pointer to the actual start of the 16-bit buffer.
|
|||
|
Used to calculate offsets for all pointers in structures.
|
|||
|
|
|||
|
OutBufferLength - length of the output buffer.
|
|||
|
|
|||
|
OutStructureDesc - description of the output fixed structure.
|
|||
|
|
|||
|
VerifyFunction - a pointer to a function which is be called after
|
|||
|
each enum record is converted in order to determine whether
|
|||
|
the record should be retained or discarded. The function
|
|||
|
is passed the return code from RapConvertSingleEntry and
|
|||
|
a pointer to the converted entry. It must return NERR_SUCCESS
|
|||
|
if the entry is to be retained, or any error code if the entry
|
|||
|
is to be discarded. If no function is supplied, a default function
|
|||
|
is used, which discards an entry only if RapConvertSingleEntry
|
|||
|
returned an error trying to convert it.
|
|||
|
|
|||
|
BytesRequired - a pointer to a DWORD to receive the total number of
|
|||
|
bytes that would be required to hold the entire output buffer.
|
|||
|
|
|||
|
EntriesFilled - a pointer to a DWORD to receive the total number of
|
|||
|
entries that could be put in the buffer given.
|
|||
|
|
|||
|
InvalidEntries - an optional pointer to a DWORD to receive the total
|
|||
|
number of entries discarded by the verify function. If NULL, this
|
|||
|
value will be not be available to the caller.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
DWORD currentEntry;
|
|||
|
LPBYTE currentInEntryPtr;
|
|||
|
LPBYTE currentOutEntryPtr;
|
|||
|
LPBYTE outputStringLocation;
|
|||
|
LPBYTE oldStringLocation;
|
|||
|
DWORD inputStructureSize;
|
|||
|
DWORD outputStructureSize;
|
|||
|
DWORD newBytesRequired;
|
|||
|
DWORD invalidEntries = 0;
|
|||
|
|
|||
|
if ( VerifyFunction == NULL ) {
|
|||
|
VerifyFunction = &XsDefaultEnumVerifyFunction;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set up sizes of input and output structures.
|
|||
|
//
|
|||
|
|
|||
|
inputStructureSize = RapStructureSize( InStructureDesc, Response, TRUE );
|
|||
|
outputStructureSize = RapStructureSize( OutStructureDesc, Response, FALSE );
|
|||
|
|
|||
|
outputStringLocation = (LPBYTE)OutBuffer + OutBufferLength;
|
|||
|
*BytesRequired = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Check if one fixed entry will fit.
|
|||
|
//
|
|||
|
|
|||
|
if ( inputStructureSize > OutBufferLength ) {
|
|||
|
|
|||
|
*EntriesFilled = 0;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Loop through the entries, converting along the way.
|
|||
|
//
|
|||
|
|
|||
|
currentInEntryPtr = InBuffer;
|
|||
|
currentOutEntryPtr = OutBuffer;
|
|||
|
*EntriesFilled = 0;
|
|||
|
|
|||
|
for ( currentEntry = 0; currentEntry < NumberOfEntries; currentEntry++ ) {
|
|||
|
|
|||
|
//
|
|||
|
// If there wasn't enough room for the conversion, we can quit now.
|
|||
|
//
|
|||
|
|
|||
|
if ( currentOutEntryPtr + outputStructureSize > outputStringLocation ) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
newBytesRequired = *BytesRequired;
|
|||
|
oldStringLocation = outputStringLocation;
|
|||
|
|
|||
|
status = RapConvertSingleEntry(
|
|||
|
currentInEntryPtr,
|
|||
|
InStructureDesc,
|
|||
|
FALSE,
|
|||
|
OutBufferStart,
|
|||
|
currentOutEntryPtr,
|
|||
|
OutStructureDesc,
|
|||
|
TRUE,
|
|||
|
&outputStringLocation,
|
|||
|
&newBytesRequired,
|
|||
|
Response,
|
|||
|
NativeToRap
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If the conversion was successful, increment the buffer pointers,
|
|||
|
// the count of bytes required, and the number of converted entries.
|
|||
|
//
|
|||
|
|
|||
|
status = (*VerifyFunction)(
|
|||
|
status,
|
|||
|
currentOutEntryPtr,
|
|||
|
OutBufferStart
|
|||
|
);
|
|||
|
|
|||
|
if ( status == NERR_Success ) {
|
|||
|
|
|||
|
currentInEntryPtr += inputStructureSize;
|
|||
|
currentOutEntryPtr += outputStructureSize;
|
|||
|
*BytesRequired = newBytesRequired;
|
|||
|
*EntriesFilled += 1;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
invalidEntries++;
|
|||
|
currentInEntryPtr += inputStructureSize;
|
|||
|
outputStringLocation = oldStringLocation;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
cleanup:
|
|||
|
|
|||
|
if ( InvalidEntries != NULL ) {
|
|||
|
|
|||
|
*InvalidEntries = invalidEntries;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // XsFillEnumBuffer
|
|||
|
|
|||
|
|
|||
|
LPBYTE
|
|||
|
XsFindParameters (
|
|||
|
IN LPTRANSACTION Transaction
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine finds the start of the parameters section in the
|
|||
|
transaction block of a remote down-level API request.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Transaction - a pointer to a transaction block containing information
|
|||
|
about the API to process.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPBYTE s;
|
|||
|
|
|||
|
//
|
|||
|
// Skip over the API number and parameters description string.
|
|||
|
//
|
|||
|
|
|||
|
for ( s = Transaction->InParameters + 2; *s != '\0'; s++ );
|
|||
|
|
|||
|
//
|
|||
|
// Skip over the zero terminator and the data description string.
|
|||
|
//
|
|||
|
|
|||
|
for ( s++; *s != '\0'; s++ );
|
|||
|
|
|||
|
//
|
|||
|
// Return a pointer to the location after the zero terminator.
|
|||
|
//
|
|||
|
|
|||
|
return s + 1;
|
|||
|
|
|||
|
} // XsFindParameters
|
|||
|
|
|||
|
|
|||
|
WORD
|
|||
|
XsPackReturnData (
|
|||
|
IN LPVOID Buffer,
|
|||
|
IN WORD BufferLength,
|
|||
|
IN LPDESC Descriptor,
|
|||
|
IN DWORD EntriesRead
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine, called by get info and enum API handlers, packs the
|
|||
|
output data so that no unused data is returned to the client. This
|
|||
|
is necessary because buffers are filled with variable-length data
|
|||
|
starting at the end, thereby leaving potentially large gaps of
|
|||
|
unused space between the end of fixed structures and the beginning
|
|||
|
of variable-length data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Buffer - a pointer to the buffer to pack.
|
|||
|
|
|||
|
BufferLength - the length of this buffer.
|
|||
|
|
|||
|
Descriptor - a pointer to a string which describes the fixed structures
|
|||
|
in the buffer.
|
|||
|
|
|||
|
EntriesRead - the count of fixed structures in the buffer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
WORD - the "converter word" which informs the client how much
|
|||
|
to adjust pointers in the fixed structures so that they are
|
|||
|
meaningful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD structureSize;
|
|||
|
LPBYTE lastFixedStructure;
|
|||
|
LPBYTE endOfFixedStructures;
|
|||
|
DWORD lastPointerOffset;
|
|||
|
DWORD beginningOfVariableData;
|
|||
|
|
|||
|
//
|
|||
|
// If there is no data, return immediately.
|
|||
|
//
|
|||
|
|
|||
|
if ( EntriesRead == 0 ) {
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Find the size of a single fixed-length structure.
|
|||
|
//
|
|||
|
|
|||
|
structureSize = RapStructureSize( Descriptor, Response, FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// Use this and the number of entries to find the location of the
|
|||
|
// last fixed structure and where the fixed structures end.
|
|||
|
//
|
|||
|
|
|||
|
endOfFixedStructures = (LPBYTE)Buffer + EntriesRead * structureSize;
|
|||
|
lastFixedStructure = endOfFixedStructures - structureSize;
|
|||
|
|
|||
|
//
|
|||
|
// Find the offset into the fixed structure of the last pointer
|
|||
|
// to variable data. The value stored at this offset in the last
|
|||
|
// structure is the offset to the first variable data.
|
|||
|
//
|
|||
|
|
|||
|
lastPointerOffset = RapLastPointerOffset( Descriptor, Response, FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// If there are no pointers, there is obviously no data to pack.
|
|||
|
//
|
|||
|
|
|||
|
if ( lastPointerOffset == NO_POINTER_IN_STRUCTURE ) {
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
beginningOfVariableData =
|
|||
|
SmbGetUlong( (LPDWORD)(lastFixedStructure + lastPointerOffset) );
|
|||
|
|
|||
|
//
|
|||
|
// If this offset is NULL, then the data overflowed, hence the buffer
|
|||
|
// is nearly full. Don't do any packing.
|
|||
|
//
|
|||
|
// Also, if the gap is less than MAXIMUM_ALLOWABLE_DATA_GAP then it
|
|||
|
// isn't worth doing the packing because of the time involved in
|
|||
|
// the data copy.
|
|||
|
//
|
|||
|
|
|||
|
if ( beginningOfVariableData == (DWORD)0 ||
|
|||
|
(DWORD_PTR)Buffer + beginningOfVariableData -
|
|||
|
(DWORD_PTR)endOfFixedStructures <= MAXIMUM_ALLOWABLE_DATA_GAP ) {
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move the variable data up to follow the fixed structures.
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
endOfFixedStructures,
|
|||
|
(LPBYTE)Buffer + beginningOfVariableData,
|
|||
|
BufferLength - beginningOfVariableData
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Return the distance we moved the variable data.
|
|||
|
//
|
|||
|
|
|||
|
return (WORD)( (DWORD_PTR)Buffer + beginningOfVariableData -
|
|||
|
(DWORD_PTR)endOfFixedStructures );
|
|||
|
|
|||
|
} // XsPackReturnData
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
XsSetDataCount(
|
|||
|
IN OUT LPWORD DataCount,
|
|||
|
IN LPDESC Descriptor,
|
|||
|
IN WORD Converter,
|
|||
|
IN DWORD EntriesRead,
|
|||
|
IN WORD ReturnStatus
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine calculates the return data count based on a number
|
|||
|
of characteristics of the return data. This routine will examine
|
|||
|
the buffer size, the number of entries placed in the buffer,
|
|||
|
whether the data was packed, and what the return code was to
|
|||
|
determine the return data size. The following assumptions are made
|
|||
|
about the data: only calls with ReturnCode = NERR_Success or
|
|||
|
ERROR_MORE_DATA return any data to the client; and if there is
|
|||
|
no pointer in the fixed entries, then there is no variable data.
|
|||
|
Handlers which cannot assure these two assumptions must determine
|
|||
|
the data count manually.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DataCount - a pointer to a short word indicating the maximum
|
|||
|
return data count (usually the BufLen parameter). On return,
|
|||
|
this word will hold the actual return data count.
|
|||
|
|
|||
|
Descriptor - a string describing the structure of the fixed
|
|||
|
entries in the buffer.
|
|||
|
|
|||
|
Converter - The adjustment value for pointers in data. A non-zero
|
|||
|
value indicates data in the buffer is packed.
|
|||
|
|
|||
|
EntriesRead - Number of entries placed in the buffer. Used to
|
|||
|
determine data count for buffers with no variable data.
|
|||
|
|
|||
|
ReturnStatus - Return status of the API call, as it will be returned
|
|||
|
to the client (in other words, converted to a WORD).
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
if (( ReturnStatus != NERR_Success )
|
|||
|
&& ( ReturnStatus != ERROR_MORE_DATA)) {
|
|||
|
|
|||
|
//
|
|||
|
// If the return status is not NERR_Success or ERROR_MORE_DATA, then
|
|||
|
// the return data count is 0.
|
|||
|
|
|||
|
SmbPutUshort( DataCount, 0 );
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ( RapLastPointerOffset( Descriptor, Response, FALSE )
|
|||
|
== NO_POINTER_IN_STRUCTURE ) {
|
|||
|
|
|||
|
//
|
|||
|
// If there is no variable data, the return data count is the size
|
|||
|
// of the fixed structures.
|
|||
|
|
|||
|
SmbPutUshort( DataCount,
|
|||
|
(WORD)(RapStructureSize( Descriptor, Response, FALSE )
|
|||
|
* EntriesRead ));
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
SmbPutUshort( DataCount, SmbGetUshort( DataCount ) - Converter );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // XsSetDataCount
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
XsSetParameters (
|
|||
|
IN LPTRANSACTION Transaction,
|
|||
|
IN LPXS_PARAMETER_HEADER Header,
|
|||
|
IN LPVOID Parameters
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine takes parameters from the structure allocated by
|
|||
|
XsCaptureParameters and uses the descriptor string to place them in
|
|||
|
the correct format in the transaction block. It also frees the
|
|||
|
buffer holding the parameter structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Transaction - a pointer to the transaction block describing the
|
|||
|
request.
|
|||
|
|
|||
|
Header - a pointer to the parameter header, which contains information
|
|||
|
from the API handler such as the converter word and return status.
|
|||
|
|
|||
|
Parameters - a pointer to the parameter structure.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPBYTE inParams = Parameters;
|
|||
|
LPBYTE outParams = Transaction->OutParameters;
|
|||
|
LPDESC descriptorString;
|
|||
|
LPDESC descriptor;
|
|||
|
LPBYTE outParamsMax = outParams + Transaction->MaxParameterCount;
|
|||
|
|
|||
|
//
|
|||
|
// The first two bytes of the parameter section are the API number,
|
|||
|
// then comes the descriptor string.
|
|||
|
//
|
|||
|
|
|||
|
descriptorString = Transaction->InParameters + 2;
|
|||
|
|
|||
|
//
|
|||
|
// Set up the first part of the output parameters from the parameter
|
|||
|
// header.
|
|||
|
//
|
|||
|
|
|||
|
if( outParams + sizeof(WORD) > outParamsMax ) goto insuff_buffer;
|
|||
|
SmbPutUshort( (LPWORD)outParams, Header->Status );
|
|||
|
outParams += sizeof(WORD);
|
|||
|
|
|||
|
if( outParams + sizeof(WORD) > outParamsMax ) goto insuff_buffer;
|
|||
|
SmbPutUshort( (LPWORD)outParams, Header->Converter );
|
|||
|
outParams += sizeof(WORD);
|
|||
|
|
|||
|
//
|
|||
|
// Initially set the size of the return data to 0. If there is a
|
|||
|
// receive buffer for this call, the API handler has changed the
|
|||
|
// buffer length parameter to the count of data returned, which
|
|||
|
// will be transferred to the DataCount variable later.
|
|||
|
//
|
|||
|
|
|||
|
Transaction->DataCount = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Walk through the descriptor string, converting from the total
|
|||
|
// parameter set to the smaller set passed back to the client. In
|
|||
|
// general, only information the client does not already know is
|
|||
|
// passed back as parameters.
|
|||
|
//
|
|||
|
|
|||
|
for ( descriptor = descriptorString; *descriptor != '\0'; ) {
|
|||
|
|
|||
|
switch ( *descriptor++ ) {
|
|||
|
|
|||
|
case REM_ASCIZ:
|
|||
|
case REM_NULL_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// !!! Parameter string descriptors may not have maximum length
|
|||
|
// counts.
|
|||
|
//
|
|||
|
|
|||
|
NetpAssert( !isdigit( *descriptor ));
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a pointer to a string, which is
|
|||
|
// not returned to the client.
|
|||
|
//
|
|||
|
|
|||
|
inParams += sizeof(LPSTR);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_BYTE_PTR:
|
|||
|
case REM_FILL_BYTES:
|
|||
|
|
|||
|
//
|
|||
|
// Array of bytes, doesn't get sent back.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Skip over any numeric characters in descriptor.
|
|||
|
//
|
|||
|
|
|||
|
RapAsciiToDecimal( &descriptor );
|
|||
|
|
|||
|
inParams += sizeof(LPBYTE);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_DWORD:
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a input word not returned to the client.
|
|||
|
//
|
|||
|
// !!! This assumes that an array of dwords will never be passed
|
|||
|
// as a parameter.
|
|||
|
|
|||
|
NetpAssert( !isdigit( *descriptor ));
|
|||
|
|
|||
|
inParams += sizeof(DWORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_ENTRIES_READ:
|
|||
|
case REM_RCV_WORD_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// Count of entries read (e) or receive word pointer (h).
|
|||
|
// This is an output parameter, so copy over the word.
|
|||
|
//
|
|||
|
|
|||
|
if( outParams + sizeof(WORD) > outParamsMax ) goto insuff_buffer;
|
|||
|
|
|||
|
SmbPutUshort(
|
|||
|
(LPWORD)outParams,
|
|||
|
SmbGetUshort( (LPWORD)inParams )
|
|||
|
);
|
|||
|
|
|||
|
inParams += sizeof(WORD);
|
|||
|
outParams += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_DWORD_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// Count of receive dword pointer (h).
|
|||
|
// This is an output parameter, so copy over the word.
|
|||
|
//
|
|||
|
|
|||
|
if( outParams + sizeof(DWORD) > outParamsMax ) goto insuff_buffer;
|
|||
|
|
|||
|
SmbPutUlong(
|
|||
|
(LPDWORD)outParams,
|
|||
|
SmbGetUlong( (LPDWORD)inParams )
|
|||
|
);
|
|||
|
|
|||
|
inParams += sizeof(DWORD);
|
|||
|
outParams += sizeof(DWORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_BUF_LEN:
|
|||
|
|
|||
|
//
|
|||
|
// The length of the receive buffer (r). The parameter is not
|
|||
|
// returned to the client, but it is used to set the return
|
|||
|
// data count.
|
|||
|
//
|
|||
|
|
|||
|
Transaction->DataCount = (DWORD)SmbGetUshort( (LPWORD)inParams );
|
|||
|
inParams += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_BUF_PTR:
|
|||
|
case REM_SEND_BUF_PTR:
|
|||
|
|
|||
|
//
|
|||
|
// A pointer to a data buffer. This is not returned to the
|
|||
|
// client.
|
|||
|
//
|
|||
|
|
|||
|
inParams += sizeof(LPBYTE);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REM_RCV_BYTE_PTR: {
|
|||
|
|
|||
|
//
|
|||
|
// The parameter indicates return bytes.
|
|||
|
//
|
|||
|
|
|||
|
DWORD arraySize;
|
|||
|
|
|||
|
arraySize = sizeof(BYTE) * RapDescArrayLength( descriptor );
|
|||
|
|
|||
|
if( outParams + arraySize > outParamsMax ) goto insuff_buffer;
|
|||
|
|
|||
|
RtlCopyMemory( outParams, inParams, arraySize );
|
|||
|
|
|||
|
outParams += arraySize;
|
|||
|
inParams += arraySize;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
case REM_SEND_BUF_LEN:
|
|||
|
case REM_WORD:
|
|||
|
case REM_PARMNUM:
|
|||
|
|
|||
|
//
|
|||
|
// The parameter is a input word not returned to the client.
|
|||
|
//
|
|||
|
// !!! This assumes that an array of words will never be passed
|
|||
|
// as a parameter.
|
|||
|
|
|||
|
NetpAssert( !isdigit( *descriptor ));
|
|||
|
|
|||
|
inParams += sizeof(WORD);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
IF_DEBUG(ERRORS) {
|
|||
|
NetpKdPrint(( "XsSetParameters: unsupported character at %lx: %c\n",
|
|||
|
descriptor - 1, *( descriptor - 1 )));
|
|||
|
NetpBreakPoint( );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Indicate the number of response parameter bytes.
|
|||
|
//
|
|||
|
|
|||
|
Transaction->ParameterCount =
|
|||
|
(DWORD)((DWORD_PTR)outParams - (DWORD_PTR)(Transaction->OutParameters) );
|
|||
|
|
|||
|
//
|
|||
|
// Free the parameter buffer allocated by XsCaptureParameters.
|
|||
|
//
|
|||
|
|
|||
|
NetpMemoryFree( Header );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
insuff_buffer:
|
|||
|
Header->Status = NERR_BufTooSmall;
|
|||
|
return;
|
|||
|
|
|||
|
} // XsSetParameters
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
XsValidateShareName(
|
|||
|
IN LPSTR ShareName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine determines whether the supplied string is a valid share
|
|||
|
name of the format \\computer\share, with both computer name and
|
|||
|
share name no longer than permitted by LanMan 2.0. It does not
|
|||
|
attempt to determine whether the share actually exists.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ShareName - The share name to be validated (an ASCII string)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success if the share name is valid,
|
|||
|
ERROR_INVALID_PARAMETER otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD componentLength;
|
|||
|
NET_API_STATUS status = NERR_Success;
|
|||
|
|
|||
|
if ( ShareName == NULL ) { // NULL is OK
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
componentLength = 0;
|
|||
|
while ( *ShareName == '\\' ) {
|
|||
|
componentLength++;
|
|||
|
ShareName++;
|
|||
|
}
|
|||
|
|
|||
|
if ( componentLength != 2 ) {
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
componentLength = 0;
|
|||
|
while (( *ShareName != '\\' ) && ( *ShareName != '\0' )) {
|
|||
|
componentLength++;
|
|||
|
ShareName++;
|
|||
|
}
|
|||
|
|
|||
|
if (( *ShareName == '\0' ) ||
|
|||
|
( componentLength < 1 ) || ( componentLength > MAX_PATH )) {
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
componentLength = 0;
|
|||
|
while ( *ShareName == '\\' ) {
|
|||
|
componentLength++;
|
|||
|
ShareName++;
|
|||
|
}
|
|||
|
|
|||
|
if ( componentLength != 1 ) {
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
componentLength = 0;
|
|||
|
while (( *ShareName != '\\' ) && ( *ShareName != '\0' )) {
|
|||
|
componentLength++;
|
|||
|
ShareName++;
|
|||
|
}
|
|||
|
|
|||
|
if (( *ShareName == '\\' ) ||
|
|||
|
( componentLength < 1 ) || ( componentLength > MAX_PATH )) {
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
cleanup:
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
SmbCapturePtr(
|
|||
|
LPBYTE PointerDestination,
|
|||
|
LPBYTE PointerValue
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine captures a pointer from the supplied buffer and places it
|
|||
|
into the destination buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
PointerDestination - A pointer to the pointer value destination.
|
|||
|
|
|||
|
PointerSource - A pointer to the pointer value source.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
XsSmbPutPointer( PointerDestination, PointerValue );
|
|||
|
}
|
|||
|
|
|||
|
|