|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
intconv.c
Abstract:
Short and long conversion routines.
Author:
Dov Harel (DovH) 21-Apr-1992
Environment:
This code should execute in all environments supported by RPC (DOS, Win 3.X, and Win/NT as well as OS2).
Comments:
Split charconv.cxx into
charconv.cxx - Character related conversion. intconv.cxx - Integral type conversion. dataconv.cxx - Interpretation style converstion.
Revision history:
Donna Liu 07-23-1992 Added LowerIndex parameter to <basetype>_array_from_ndr routines Dov Harel 08-19-1992 Added RpcpMemoryCopy ([_f]memcpy) to ..._array_from_ndr routines Ryszard Kott 06-15-1993 Added hyper support
--*/
#include <sysinc.h>
#include <rpc.h>
#include <rpcdcep.h>
#include <rpcndr.h>
#include <ndrlibp.h>
//
// Definitions from rpcndr.h
//
// Network Computing Architecture (NCA) definition:
//
// Network Data Representation: (NDR) Label format:
// An unsigned long (32 bits) with the following layout:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---------------+---------------+---------------+-------+-------+
// | Reserved | Reserved |Floating point | Int | Char |
// | | |Representation | Rep. | Rep. |
// +---------------+---------------+---------------+-------+-------+
//
// Where
//
// Reserved:
//
// Must be zero (0) for NCA 1.5 and NCA 2.0.
//
// Floating point Representation is:
//
// 0 - IEEE
// 1 - VAX
// 2 - Cray
// 3 - IBM
//
// Int Rep. is Integer Representation:
//
// 0 - Big Endian
// 1 - Little Endian
//
// Char Rep. is Character Representation:
//
// 0 - ASCII
// 1 - EBCDIC
//
// #define NDR_CHAR_REP_MASK (unsigned long)0X0000000FL
// #define NDR_INT_REP_MASK (unsigned long)0X000000F0L
// #define NDR_FLOAT_REP_MASK (unsigned long)0X0000FF00L
//
// #define NDR_LITTLE_ENDIAN (unsigned long)0X00000010L
// #define NDR_BIG_ENDIAN (unsigned long)0X00000000L
//
// #define NDR_IEEE_FLOAT (unsigned long)0X00000000L
// #define NDR_VAX_FLOAT (unsigned long)0X00000100L
//
// #define NDR_ASCII_CHAR (unsigned long)0X00000000L
// #define NDR_EBCDIC_CHAR (unsigned long)0X00000001L
//
// #define NDR_LOCAL_DATA_REPRESENTATION (unsigned long)0X00000010L
//
//
// For shorts assume the following 16-bit word layout:
//
// 1 1 1 1 1 1
// 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---------------+---------------+
// | A | B |
// +---------------+---------------+
//
// For longs assume the following 32-bit word layout:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---------------+---------------+---------------+---------------+
// | A | B | C | D |
// +---------------+---------------+---------------+---------------+
//
void RPC_ENTRY short_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, OUT unsigned short * Target )
/*++
Routine Description:
Unmarshall a short from an RPC message buffer into the target (*Target). This routine:
o Aligns the buffer pointer to the next (0 mod 2) boundary, o Unmarshalls the short (as unsigned short); performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the unmarshalled short.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the short to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the short which was just unmarshalled.
Target - A pointer to the short to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer;
aBuffer++; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~1);
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { *(unsigned short *)Target = RtlUshortByteSwap(*(unsigned short *)aBuffer); } else { *(short *)Target = *((short *)aBuffer); }
//
// Update SourceMessage->Buffer before returning:
//
SourceMessage->Buffer = aBuffer + 2; }
//
// end short_from_ndr
//
void RPC_ENTRY short_array_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, IN unsigned long LowerIndex, IN unsigned long UpperIndex, OUT unsigned short *Target )
/*++
Routine Description:
Unmarshall an array of shorts from an RPC message buffer into the range Target[LowerIndex] .. Target[UpperIndex-1] of the target array of shorts (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 2) boundary, o Unmarshalls MemberCount shorts; performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the last unmarshalled short.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the first short to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the last short which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - An array of shorts to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer; register unsigned int index;
aBuffer++; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~1);
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { //
// Big Endian Sender
//
for (index = (int)LowerIndex; index < UpperIndex; index++) { Target[index] = RtlUshortByteSwap(*(unsigned short *)aBuffer); aBuffer += 2;
} //
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)aBuffer;
} else {
int byteCount = 2*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy( &Target[LowerIndex], aBuffer, byteCount ); //
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(aBuffer + byteCount); } }
//
// end short_array_from_ndr
//
void RPC_ENTRY short_from_ndr_temp ( IN OUT unsigned char ** source, OUT unsigned short * target, IN unsigned long format ) {
/*++
Routine Description:
Unmarshall a short from a given buffer into the target (*target). This routine:
o Aligns the *source pointer to the next (0 mod 2) boundary, o Unmarshalls a short (as unsigned short); performs data conversion if necessary, and o Advances the *source pointer to the address immediately following the unmarshalled short.
Arguments:
source - A pointer to a pointer to a buffer
IN - *source points to the address just prior to the short to be unmarshalled. OUT - *source points to the address just following the short which was just unmarshalled.
target - A pointer to the short to unmarshall the data into.
format - The sender data representation.
Return Values:
None.
--*/
register unsigned char PAPI * aBuffer = *source;
aBuffer++; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~1);
if ( (format & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { *(unsigned short *)target = RtlUshortByteSwap(*(unsigned short *)aBuffer); } else { *(short *)target = *((short *)aBuffer); }
//
// Update *source (== aBuffer) before returning:
//
*source = aBuffer + 2; }
//
// end short_from_ndr_temp
//
void RPC_ENTRY long_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, OUT unsigned long * Target )
/*++
Routine Description:
Unmarshall a long from an RPC message buffer into the target (*Target). This routine:
o Aligns the buffer pointer to the next (0 mod 4) boundary, o Unmarshalls the long (as unsigned long); performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the unmarshalled long.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the short to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the short which was just unmarshalled.
Target - A pointer to the long to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer;
aBuffer = aBuffer + 3; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~3);
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { *(unsigned long *)Target = RtlUlongByteSwap(*(unsigned long *)aBuffer); } else { *(long *)Target = (*(long *)aBuffer); }
//
// Update SourceMessage->Buffer before returning:
//
SourceMessage->Buffer = aBuffer + 4; }
//
// end long_from_ndr
//
void RPC_ENTRY long_array_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, IN unsigned long LowerIndex, IN unsigned long UpperIndex, OUT unsigned long * Target )
/*++
Routine Description:
Unmarshall an array of longs from an RPC message buffer into the range Target[LowerIndex] .. Target[UpperIndex-1] of the target array of longs (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 4) boundary, o Unmarshalls MemberCount longs; performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the last unmarshalled long.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the first long to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the last long which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - An array of longs to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer; register unsigned int index;
aBuffer = (unsigned char *)aBuffer + 3; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~3);
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { for (index = (int)LowerIndex; index < UpperIndex; index++) { Target[index] = RtlUlongByteSwap(*(unsigned long *)aBuffer); aBuffer += 4; }
//
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)aBuffer;
} else {
int byteCount = 4*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy( &Target[LowerIndex], aBuffer, byteCount ); //
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(aBuffer + byteCount); } }
//
// end long_array_from_ndr
//
void RPC_ENTRY long_from_ndr_temp ( IN OUT unsigned char ** source, OUT unsigned long * target, IN unsigned long format )
/*++
Routine Description:
Unmarshall a long from a given buffer into the target (*target). This routine:
o Aligns the *source pointer to the next (0 mod 2) boundary, o Unmarshalls a long (as unsigned long); performs data conversion if necessary, and o Advances the *source pointer to the address immediately following the unmarshalled long.
Arguments:
source - A pointer to a pointer to a buffer
IN - *source points to the address just prior to the long to be unmarshalled. OUT - *source points to the address just following the long which was just unmarshalled.
target - A pointer to the long to unmarshall the data into.
format - The sender data representation.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = *source;
aBuffer = (unsigned char *)aBuffer + 3; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~3);
if ( (format & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { *(unsigned long *)target = RtlUlongByteSwap(*(unsigned long *)aBuffer); } else { *(long *)target = (*(long *)aBuffer); }
//
// Update SourceMessage->Buffer before returning:
//
*source = aBuffer + 4; }
//
// end long_from_ndr_temp
//
void RPC_ENTRY enum_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, OUT unsigned int * Target )
/*++
Routine Description:
Unmarshall an int from an RPC message buffer into the target (*Target). Note: this is based on the assumption, valid in all C compilers we currently support, that "enum" is treated as an "int" by the compiler.
This routine:
o Aligns the buffer pointer to the next (0 mod 2) boundary, o Unmarshalls the int (as unsigned int); performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the unmarshalled int.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the int to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the int which was just unmarshalled.
Target - A pointer to the int to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer;
aBuffer++; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~1);
//
// Zeroe *Target to be on the safe side later for 32-bit
// int systems!
//
*Target = 0;
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { *(unsigned short *)Target = RtlUshortByteSwap(*(unsigned short *)aBuffer); } else { // The following code will copy two bytes from the wire
// to the two low order bytes of (*Target) independently of
// the size of int.
//
*(short *)Target = *((short *)aBuffer); }
//
// Update SourceMessage->Buffer before returning:
//
SourceMessage->Buffer = aBuffer + 2; }
//
// end enum_from_ndr
//
void RPC_ENTRY hyper_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, // OUT unsigned hyper * Target
OUT hyper * Target )
/*++
Routine Description:
Unmarshall a hyper from an RPC message buffer into the target (*Target). This routine:
o Aligns the buffer pointer to the next (0 mod 8) boundary, o Unmarshalls the hyper (as unsigned hyper); performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the unmarshalled hyper.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the hyper to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the hyper which was just unmarshalled.
Target - A pointer to the hyper to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer;
aBuffer = aBuffer + 7; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~7);
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { *Target = RtlUlonglongByteSwap(*(unsigned hyper *)aBuffer); } else { *Target = *(hyper *)aBuffer; }
//
// Update SourceMessage->Buffer before returning:
//
SourceMessage->Buffer = aBuffer + 8; }
//
// end hyper_from_ndr
//
#if 0
void RPC_ENTRY hyper_array_from_ndr( IN OUT PRPC_MESSAGE SourceMessage, IN unsigned long LowerIndex, IN unsigned long UpperIndex, // OUT unsigned hyper Target[]
OUT hyper * Target )
/*++
Routine Description:
Unmarshall an array of hypers from an RPC message buffer into the range Target[LowerIndex] .. Target[UpperIndex-1] of the target array of hypers (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 8) boundary, o Unmarshalls MemberCount hypers; performs data conversion if necessary, and o Advances the buffer pointer to the address immediately following the last unmarshalled hyper.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the first hyper to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the last hyper which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - An array of hypers to unmarshall the data into.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = (unsigned char *)SourceMessage->Buffer; register unsigned int index;
aBuffer = (unsigned char *)aBuffer + 7; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~7);
if ( (SourceMessage->DataRepresentation & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) { for (index = (int)LowerIndex; index < UpperIndex; index++) {
//.. We are doing ABCDEFGH -> HGFEDCBA
//.. We start with ABCD going as DCBA into second word of Target
//
// Swap bytes:
//
// First apply the transformation: ABCD => BADC
//
*(unsigned long *)Target = (*(unsigned long *)aBuffer & MASK_A_C_) >> 8 | (*(unsigned long *)aBuffer & MASK__B_D) << 8 ;
//
// Now swap the left and right halves of the Target long word
// achieving full swap: BADC => DCBA
//
//.. Put it into second word, without changing Target pointer yet.
*((unsigned long *)Target + 1) = (*(unsigned long *)Target & MASK_AB__) >> 16 | (*(unsigned long *)Target & MASK___CD) << 16 ;
//.. What's left is EFGH going into first word at Target
//.. Compiler can't do this: ((long *)aBuffer)++;
aBuffer += 4;
// Swap bytes:
//
// First apply the transformation: EFGH => FEHG
//
*(unsigned long *)Target = (*(unsigned long *)aBuffer & MASK_A_C_) >> 8 | (*(unsigned long *)aBuffer & MASK__B_D) << 8 ;
//
// Now swap the left and right halves of the Target long word
// achieving full swap: FEHG => HGFE
//
//.. Put it into first word, at the Target pointer
*(unsigned long *)Target = (*(unsigned long *)Target & MASK_AB__) >> 16 | (*(unsigned long *)Target & MASK___CD) << 16 ;
//.. Loop, advance pointers.
Target++; aBuffer += 4; //.. ((long *)aBuffer)++;
}
//
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)aBuffer;
} else {
int byteCount = 8*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy( &Target[LowerIndex], aBuffer, byteCount ); //
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(aBuffer + byteCount);
} }
//
// end long_array_from_ndr
//
void RPC_ENTRY hyper_from_ndr_temp ( IN OUT unsigned char ** source, // OUT unsigned hyper * Target,
OUT hyper * Target, IN unsigned long format )
/*++
Routine Description:
Unmarshall a hyper from a given buffer into the target (*target). This routine:
o Aligns the *source pointer to the next (0 mod 2) boundary, o Unmarshalls a hyper (as unsigned hyper); performs data conversion if necessary, and o Advances the *source pointer to the address immediately following the unmarshalled hyper.
Arguments:
source - A pointer to a pointer to a buffer
IN - *source points to the address just prior to the hyper to be unmarshalled. OUT - *source points to the address just following the hyper which was just unmarshalled.
Target - A pointer to the hyper to unmarshall the data into.
format - The sender data representation.
Return Values:
None.
--*/
{ register unsigned char PAPI * aBuffer = *source;
aBuffer = (unsigned char *)aBuffer + 3; aBuffer = (unsigned char *)((ULONG_PTR) aBuffer & ~3);
if ( (format & NDR_INT_REP_MASK) == NDR_BIG_ENDIAN ) {
//.. We are doing ABCDEFGH -> HGFEDCBA
//.. We start with ABCD going as DCBA into second word of Target
//
// Swap bytes:
//
// First apply the transformation: ABCD => BADC
//
*(unsigned long *)Target = (*(unsigned long *)aBuffer & MASK_A_C_) >> 8 | (*(unsigned long *)aBuffer & MASK__B_D) << 8 ;
//
// Now swap the left and right halves of the Target long word
// achieving full swap: BADC => DCBA
//
//.. and put it into second word, without changing Target pointer
*((unsigned long *)Target + 1) = (*(unsigned long *)Target & MASK_AB__) >> 16 | (*(unsigned long *)Target & MASK___CD) << 16 ;
//.. What's left is EFGH going into first word at Target
//.. Compiler can't do this: ((long *)aBuffer)++;
aBuffer += 4;
// Swap bytes:
//
// First apply the transformation: EFGH => FEHG
//
*(unsigned long *)Target = (*(unsigned long *)aBuffer & MASK_A_C_) >> 8 | (*(unsigned long *)aBuffer & MASK__B_D) << 8 ;
//
// Now swap the left and right halves of the Target long word
// achieving full swap: FEHG => HGFE
//
//.. Put it into the first word, at the original Target pointer.
*(unsigned long *)Target = (*(unsigned long *)Target & MASK_AB__) >> 16 | (*(unsigned long *)Target & MASK___CD) << 16 ;
} else { //.. Copy hyper as two longs, don't change Target pointer.
//.. Advance aBuffer by a long though to get the same as from above.
//.. Compiler can't do this: ((long *)aBuffer)++;
*(unsigned long *)Target = (*(unsigned long *)aBuffer); aBuffer += 4; *((unsigned long *)Target + 1) = (*(unsigned long *)aBuffer); }
//
// Update SourceMessage->Buffer before returning:
//
*source = aBuffer + 4; }
//
// end hyper_from_ndr_temp
//
#endif
|