windows-nt/Source/XPSP1/NT/com/rpc/ndrlib/intconv.cxx
2020-09-26 16:20:57 +08:00

970 lines
24 KiB
C++

/*++
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