/*++ Copyright (c) 1987-1993 Microsoft Corporation Module Name: RcvConv.c Abstract: This module contains support routines for the RpcXlate code. Author: John Rogers (JohnRo) 01-Apr-1991 (NT version) (unknown Microsoft programmer) (original LM 2.x version) Environment: Portable to any flat, 32-bit environment. (Uses Win32 typedefs.) Requires ANSI C extensions: slash-slash comments, long external names. Revision History: (various NBU people) LanMan 2.x code 01-Apr-1991 JohnRo Created portable version from LanMan 2.x sources. 13-Apr-1991 JohnRo Added some (quiet) debug output. Reduced recompile hits from header files. 03-May-1991 JohnRo Don't use NET_API_FUNCTION for non-APIs. 11-May-1991 JohnRo Fixed string ptr bug in RxpSetPointer(). Added assertions and. debug output. 13-May-1991 JohnRo Use DESC_CHAR typedef. Print num_aux for debugging. 17-May-1991 JohnRo Handle array of aux structs. 19-May-1991 JohnRo Make LINT-suggested changes (use DBGSTATIC). 20-May-1991 JohnRo Cast expression in RxpSetPointer more carefully. 02-Jun-1991 JohnRo Allow use on big-endian machines. (PC-LINT discovered a portability problem.) 17-Jul-1991 JohnRo Extracted RxpDebug.h from Rxp.h. 10-Sep-1991 JohnRo Made changes suggested by PC-LINT. 13-Nov-1991 JohnRo RAID 4408: Fixed MIPS alignment problems. 21-Nov-1991 JohnRo Removed NT dependencies to reduce recompiles. 07-May-1993 JohnRo RAID 6167: avoid access violation or assert with WFW print server. Corrected copyright and authorship. Use NetpKdPrint() where possible. Use PREFIX_ equates. --*/ // These must be included first: #include // IN, DWORD, VOID, etc. #include // Private header file. // These may be included in any order: #include // NetpKdPrint(), FORMAT_ equates, etc. #include // NetpPointerPlusSomeBytes(), etc. #include // PREFIX_ equates. #include // REM_BYTE, etc. #include // IF_DEBUG(). #include // RapGetWord(), etc. #include // Inputs to this function haven't been converted to 32-bit yet. #define INPUTS_ARE_NATIVE FALSE DBGSTATIC NET_API_STATUS RxpSetPointer( IN LPBYTE RcvBufferStart, IN DWORD RcvDataSize, IN OUT LPBYTE * RcvPointerPointer, IN DWORD Converter ); DWORD RxpGetFieldSizeDl( IN LPDESC TypePointer, IN OUT LPDESC * TypePointerAddress, IN RAP_TRANSMISSION_MODE TransmissionMode ); NET_API_STATUS RxpReceiveBufferConvert( IN OUT LPVOID RcvDataPointer, IN DWORD RcvDataSize, IN DWORD Converter, IN DWORD NumberOfStructures, IN LPDESC DataDescriptorString, IN LPDESC AuxDescriptorString, OUT LPDWORD NumAuxStructs ) /*++ Routine Description: RxpReceiveBufferConvert corrects all pointer fields present in a receive buffer. All pointers in the receive buffer are returned from the API worker as pointers into the buffer position given to the API on the API worker's station. This routine steps through the receive buffer and calls RxpSetPointer to perform the pointer conversions. On exit, all pointers (except NULL pointers) in receive buffer converted to local format. Arguments: RcvDataPointer - Pointer to receive buffer. This will be updated in place. RcvDataSize - Length of the data area that RcvDataPointer points to. Converter - Converter word from API worker. NumberOfStructures - Entries read parm (or 1 for GetInfo). DataDescriptorString - Descriptor string for data format. AuxDescriptorString - Descriptor string for aux format. NumAuxStructs - Points to a DWORD which will be set with the number of entries in the aux array. (This will be set to 0 if none.) Return Value: NET_API_STATUS (NO_ERROR or ERROR_INVALID_PARAMETER). --*/ { NET_API_STATUS ApiStatus; DESC_CHAR c; DWORD i,j; LPBYTE data_ptr; LPBYTE end_of_data; LPDESC l_data; LPDESC l_aux; NetpAssert( RcvDataPointer != NULL ); NetpAssert( RcvDataSize != 0 ); NetpAssert( NumAuxStructs != NULL ); data_ptr = RcvDataPointer; /* start of rcv data buffer */ end_of_data = NetpPointerPlusSomeBytes( RcvDataPointer, RcvDataSize ); IF_DEBUG(RCVCONV) { NetpKdPrint(( PREFIX_NETAPI "RxpReceiveBufferConvert: starting, Converter=" FORMAT_HEX_DWORD "...\n", Converter )); } *NumAuxStructs = 0; for (i = 0; i < NumberOfStructures; i++) { /* For each entries read */ for (l_data=DataDescriptorString; (c = *l_data) != '\0'; l_data++) { if (c == REM_AUX_NUM) { *NumAuxStructs = RapGetWord( data_ptr, INPUTS_ARE_NATIVE ); IF_DEBUG(RCVCONV) { NetpKdPrint(( PREFIX_NETAPI "RxpReceiveBufferConvert: num aux is now " FORMAT_DWORD ".\n", *NumAuxStructs )); } } if (RapIsPointer(c)) { /* If field is pointer */ ApiStatus = RxpSetPointer( RcvDataPointer, RcvDataSize, (LPBYTE *) data_ptr, Converter); if (ApiStatus != NO_ERROR) { goto Cleanup; } } data_ptr += RxpGetFieldSizeDl( l_data, &l_data, Both); if (data_ptr > end_of_data) { ApiStatus = ERROR_INVALID_PARAMETER; goto Cleanup; } } for (j = 0; j < *NumAuxStructs; j++) { /* For each aux struct */ for (l_aux = AuxDescriptorString; (c = *l_aux) != '\0'; l_aux++) { if (RapIsPointer(c)) { /* If field is pointer */ ApiStatus = RxpSetPointer( RcvDataPointer, RcvDataSize, (LPBYTE *) data_ptr, Converter); if (ApiStatus != NO_ERROR) { goto Cleanup; } } data_ptr += RxpGetFieldSizeDl( l_aux, &l_aux, Both); if (data_ptr > end_of_data) { ApiStatus = ERROR_INVALID_PARAMETER; goto Cleanup; } } } } ApiStatus = NO_ERROR; Cleanup: IF_DEBUG(RCVCONV) { NetpKdPrint(( PREFIX_NETAPI "RxpReceiveBufferConvert: done, status=" FORMAT_API_STATUS ".\n", ApiStatus )); } return (ApiStatus); } // RxpReceiveBufferConvert DBGSTATIC NET_API_STATUS RxpSetPointer( IN LPBYTE RcvBufferStart, IN DWORD RcvDataSize, IN OUT LPBYTE * RcvPointerPointer, IN DWORD Converter ) /*++ Routine Description: RxpSetPointer corrects a pointer field in the rcv buffer. All pointers in the receive buffer are returned from the API worker as pointers into the buffer position given to the API on the API worker's station. The pointer will be set to: addr(rcv buffer) + pointer - converter word. This routine performs the above conversion on a rcv buffer pointer. On exit, the pointer (unless NULL) in receive buffer will be converted to local format. Arguments: RcvBufferStart - pointer to start of receive buffer. RcvDataSize - Length of the data area that RcvBufferStart points to. RcvPointerPointer - pointer to pointer to convert. Converter - Converter word from API worker. Return Value: NET_API_STATUS (NO_ERROR or ERROR_INVALID_PARAMETER). --*/ { DWORD BufferOffsetToData; // offset within buffer DWORD OldOffset; // offset within segment NetpAssert( ! RapValueWouldBeTruncated(Converter) ); NetpAssert(RcvBufferStart != NULL); NetpAssert(RcvPointerPointer != NULL); NetpAssert( ((LPBYTE)(LPVOID)RcvPointerPointer) // First byte of pointer >= RcvBufferStart ); // can't be before buffer. NetpAssert( (((LPBYTE)(LPVOID)RcvPointerPointer) + sizeof(NETPTR)-1) // Last byte of pointer <= (RcvBufferStart+RcvDataSize) ); // can't be after buffer. // // Null pointer is (segment:offset) 0:0, which just appears as 4 bytes // of zeros. Check for that here. // if (RapGetDword( RcvPointerPointer, INPUTS_ARE_NATIVE ) == 0) { return (NO_ERROR); } // OK, this gets fun. What's in the buffer is a 2 byte offset followed // by a 2 byte (useless) segment number. So, we cast to LPWORD to get // the offset. We'll adjust the offset by the converter to OldOffset = (DWORD) RapGetWord( RcvPointerPointer, INPUTS_ARE_NATIVE ); IF_DEBUG(RCVCONV) { NetpKdPrint(( PREFIX_NETAPI "RxpSetPointer: OldOffset is " FORMAT_HEX_DWORD ".\n", OldOffset )); } BufferOffsetToData = (DWORD) (( OldOffset - (WORD) Converter ) & 0xffff); IF_DEBUG(RCVCONV) { NetpKdPrint(( PREFIX_NETAPI "RxpSetPointer: BufferOffsetToData is " FORMAT_HEX_DWORD ".\n", BufferOffsetToData )); } // // Make sure that what we point to is still in the buffer. // if (BufferOffsetToData >= RcvDataSize) { NetpKdPrint(( PREFIX_NETAPI "RxpSetPointer: *** BUFFER OFFSET TOO LARGE *** " "(conv=" FORMAT_HEX_DWORD ", " "offset=" FORMAT_HEX_DWORD ", " "size=" FORMAT_HEX_DWORD ").\n", Converter, BufferOffsetToData, RcvDataSize )); return (ERROR_INVALID_PARAMETER); } #if defined (_WIN64) // // Store only the 32-bit buffer offset. Later, RapGetPointer() will // add the buffer start address. // RapPutDword( RcvPointerPointer, BufferOffsetToData, INPUTS_ARE_NATIVE ); #else // // For 32-bit, the pointers are stored directly, and will be retrieved // directly from RapGetPointer(). // RapPutDword(RcvPointerPointer, NetpPointerPlusSomeBytes( RcvBufferStart, BufferOffsetToData ), INPUTS_ARE_NATIVE); #endif return (NO_ERROR); } // RxpSetPointer DWORD RxpGetFieldSizeDl( IN LPDESC TypePointer, IN OUT LPDESC * TypePointerAddress, IN RAP_TRANSMISSION_MODE TransmissionMode ) /*++ Routine Description: This is a wrapper for RapGetFieldSize(). The pointer fields in the downlevel buffers that this module deals with are always 32 bits in width. RapGetFieldSize() will return the size of a native pointer, which is not necessarily 32 bits in width. This wrapper overrides the result of RapGetFieldSize() with sizeof(DWORD) for all pointer types. See the description of RapGetFieldSize() for additional info. --*/ { DWORD fieldSize; BOOL isPointer; fieldSize = RapGetFieldSize( TypePointer, TypePointerAddress, TransmissionMode ); #if defined (_WIN64) isPointer = RapIsPointer(*TypePointer); if (isPointer != FALSE){ fieldSize = sizeof(DWORD); } #endif return fieldSize; } // RxpGetFieldSizeDl