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

698 lines
17 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
floatc.cxx
Abstract:
Float and double conversion routines.
Author:
Dov Harel (DovH) 23-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:
This file was completely rewritten to incorporate DCE floating
point conversion. Currently the only supported DCE interoperation
is with DEC system. The vax conversion routines used
(cvt_vax_f_to_ieee_single, and cvt_vax_g_to_ieee_double)
were supplied by Digital, and are used for full compatibility with
DCE RPC. (See name.map for Digital files used).
Also added floating point array conversion routines.
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
Dov Harel 08-25-1992 Added byte swapping for IEEE big endian
machines (such as HP).
--*/
#include <sysinc.h>
#include <rpc.h>
#include <rpcdcep.h>
#include <rpcndr.h>
#include <..\..\ndr20\cvt.h>
#include <ndrlibp.h>
//
// 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 |
// +---------------+---------------+---------------+---------------+
//
//
// Masks defined for long byte swapping:
//
#define MASK_AB__ (unsigned long)0XFFFF0000L
#define MASK___CD (unsigned long)0X0000FFFFL
#define MASK_A_C_ (unsigned long)0XFF00FF00L
#define MASK__B_D (unsigned long)0X00FF00FFL
//
// #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
//
#define NDR_FLOAT_INT_MASK (unsigned long)0X0000FFF0L
#define NDR_BIG_IEEE_REP (unsigned long)0X00000000L
#define NDR_LITTLE_IEEE_REP (unsigned long)0X00000010L
void RPC_ENTRY
NdrpLongByteSwap(
IN void PAPI * Source,
OUT void PAPI * Target
)
/*++
Routine Description:
Assuming both Source and Target point to aligned unsigned longs,
move the bytes of *Source into *Target in reverse oreder. The value
of (*Target) following the call is the bate swapped value of
(*Source).
Arguments:
Source - A pointer to an aligned unsigned long.
Target - A pointer to the long to swap the *Source bytes into.
Return Values:
None.
--*/
{
//
// Swap bytes:
//
// First apply the transformation: ABCD => BADC
//
*(unsigned long *)Target =
(*(unsigned long *)Source & MASK_A_C_) >> 8 |
(*(unsigned long *)Source & MASK__B_D) << 8 ;
//
// Now swap the left and right halves of the Target long word
// achieving full swap: BADC => DCBA
//
*(unsigned long *)Target =
(*(unsigned long *)Target & MASK_AB__) >> 16 |
(*(unsigned long *)Target & MASK___CD) << 16 ;
}
//
// end NdrpLongByteSwap
//
/*
//
// Relevant definitions from cvt.h (Digital):
//
typedef unsigned char CVT_BYTE;
typedef CVT_BYTE *CVT_BYTE_PTR;
typedef CVT_BYTE CVT_VAX_F[4];
typedef CVT_BYTE CVT_VAX_D[8];
typedef CVT_BYTE CVT_VAX_G[8];
typedef CVT_BYTE CVT_IEEE_SINGLE[4];
typedef CVT_BYTE CVT_IEEE_DOUBLE[8];
//
// Relevant definitions from vaxout.c
// (previous floating point conversion test):
//
CVT_VAX_F inputf;
CVT_IEEE_SINGLE outputf;
CVT_VAX_G inputg;
CVT_IEEE_DOUBLE outputg;
cvt_vax_f_to_ieee_single( inputf, 0, outputf );
cvt_vax_g_to_ieee_double( inputg, 0, outputg );
*/
void RPC_ENTRY
float_from_ndr (
IN OUT PRPC_MESSAGE SourceMessage,
OUT void * Target
)
/*++
Routine Description:
Unmarshall a float 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 float; performs data conversion if necessary
(only VAX and IEEE Big Endian conversion currently supported).
o Advances the buffer pointer to the address immediately
following the unmarshalled float.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to
the float to be unmarshalled.
OUT - SourceMessage->Buffer points to the address just following
the float which was just unmarshalled.
Target - A pointer to the float to unmarshall the data into.
A (void*) pointer is used, so that the runtime library code
is not loaded, unless the application code actually uses
floating point.
Return Values:
None.
--*/
{
unsigned char PAPI * F_Input =
(unsigned char *)SourceMessage->Buffer;
unsigned char PAPI * F_Output = (unsigned char PAPI *)Target;
// CVT_IEEE_SINGLE F_Output = (unsigned char PAPI *)Target;
unsigned long SenderDataRepresentation;
//
// Align F_Input to next (0 mod 4) address
//
*(unsigned long *)&F_Input += 3;
*(unsigned long *)&F_Input &= 0XFFFFFFFCL;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
//
// Robust check for little endian IEEE (local data representation)
//
{
*(unsigned long *)Target = *(unsigned long*)F_Input;
}
else if ( (SenderDataRepresentation & NDR_FLOAT_REP_MASK) ==
NDR_VAX_FLOAT )
{
cvt_vax_f_to_ieee_single(F_Input, 0, F_Output);
}
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
NDR_BIG_IEEE_REP )
//
// Big endian IEEE sender:
//
{
NdrpLongByteSwap(F_Input, F_Output);
}
else
{
RpcRaiseException( RPC_X_BAD_STUB_DATA );
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input + 4;
}
//
// end float_from_ndr
//
void RPC_ENTRY
float_array_from_ndr (
IN OUT PRPC_MESSAGE SourceMessage,
IN unsigned long LowerIndex,
IN unsigned long UpperIndex,
OUT void * Target
)
/*++
Routine Description:
Unmarshall an array of floats from an RPC message buffer into
the range Target[LowerIndex] .. Target[UpperIndex-1] of the
target array of floats (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 4) boundary,
o Unmarshalls MemberCount floats; performs data
conversion if necessary (Currently VAX format only), and
o Advances the buffer pointer to the address immediately
following the last unmarshalled float.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to
the first float to be unmarshalled.
OUT - SourceMessage->Buffer points to the address just following
the last float which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - A pointer to an array of floats to unmarshall the data into.
A (void*) pointer is used, so that the runtime library code
is not loaded, unless the application code actually uses
floating point.
Return Values:
None.
--*/
{
unsigned char PAPI * F_Input =
(unsigned char PAPI *)SourceMessage->Buffer;
unsigned char PAPI * F_Output = (unsigned char PAPI *)Target;
register unsigned int Index;
unsigned long SenderDataRepresentation;
//
// Align F_Input to next (0 mod 4) address
//
*(unsigned long *)&F_Input += 3;
*(unsigned long *)&F_Input &= 0XFFFFFFFCL;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
//
// Robust check for little endian IEEE (local data representation)
//
{
int byteCount = 4*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy(
F_Output,
F_Input,
byteCount
);
//
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(F_Input + byteCount);
/* Replaced by RpcpMemoryCopy:
for (Index = LowerIndex; Index < UpperIndex; Index++)
{
((unsigned long *)F_Output)[Index] =
*(unsigned long *)F_Input;
F_Input += 4;
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input;
*/
}
else if ( (SenderDataRepresentation & NDR_FLOAT_REP_MASK) ==
NDR_VAX_FLOAT )
{
F_Output += 4 * LowerIndex;
for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
{
cvt_vax_f_to_ieee_single(F_Input, 0, F_Output);
F_Input += 4;
F_Output += 4;
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input;
}
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
NDR_BIG_IEEE_REP )
//
// Big endian IEEE sender:
//
{
F_Output += 4 * LowerIndex;
for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
{
NdrpLongByteSwap(F_Input, F_Output);
F_Input += 4;
F_Output += 4;
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input;
}
else
{
RpcRaiseException( RPC_X_BAD_STUB_DATA );
}
}
//
// end float_array_from_ndr
//
void RPC_ENTRY
double_from_ndr (
IN OUT PRPC_MESSAGE SourceMessage,
OUT void * Target
)
/*++
Routine Description:
Unmarshall a double 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 double; performs data conversion if necessary
(only VAX conversion currently supported).
o Advances the buffer pointer to the address immediately
following the unmarshalled double.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to
the double to be unmarshalled.
OUT - SourceMessage->Buffer points to the address just following
the double which was just unmarshalled.
Target - A pointer to the double to unmarshall the data into.
A (void*) pointer is used, so that the runtime library code
is not loaded, unless the application code actually uses
floating point.
Return Values:
None.
--*/
{
unsigned char PAPI * D_Input =
(unsigned char PAPI *)SourceMessage->Buffer;
unsigned char PAPI * D_Output = (unsigned char PAPI *)Target;
unsigned long SenderDataRepresentation;
//
// Align D_Input to next (0 mod 8) address
//
*(unsigned long *)&D_Input += 7;
*(unsigned long *)&D_Input &= 0XFFFFFFF8L;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
//
// Robust check for little endian IEEE (local data representation)
//
{
((unsigned long *)Target)[0] = ((unsigned long*)D_Input)[0];
((unsigned long *)Target)[1] = ((unsigned long*)D_Input)[1];
}
else if ( (SourceMessage->DataRepresentation & NDR_FLOAT_REP_MASK) ==
NDR_VAX_FLOAT )
{
cvt_vax_g_to_ieee_double(D_Input, 0, D_Output);
}
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
NDR_BIG_IEEE_REP )
//
// Big endian IEEE sender:
//
{
//
// Swap the low half of D_Input into the high half of D_Output
//
NdrpLongByteSwap(
&((unsigned long*)D_Input)[0],
&((unsigned long *)Target)[1]
);
//
// Swap the high half of D_Input into the low half of D_Output
//
NdrpLongByteSwap(
&((unsigned long*)D_Input)[1],
&((unsigned long *)Target)[0]
);
}
else
{
RpcRaiseException( RPC_X_BAD_STUB_DATA );
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input + 8;
}
//
// end double_from_ndr
//
void RPC_ENTRY
double_array_from_ndr (
IN OUT PRPC_MESSAGE SourceMessage,
IN unsigned long LowerIndex,
IN unsigned long UpperIndex,
OUT void * Target
)
/*++
Routine Description:
Unmarshall an array of doubles from an RPC message buffer into
the range Target[LowerIndex] .. Target[UpperIndex-1] of the
target array of (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 8) boundary,
o Unmarshalls MemberCount doubles; performs data
conversion if necessary (Currently VAX format only), and
o Advances the buffer pointer to the address immediately
following the last unmarshalled double.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to
the first double to be unmarshalled.
OUT - SourceMessage->Buffer points to the address just following
the last double which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - A pointer to an array of doubles to unmarshall the data into.
A (void*) pointer is used, so that the runtime library code
is not loaded, unless the application code actually uses
floating point.
Return Values:
None.
--*/
{
unsigned char PAPI * D_Input =
(unsigned char PAPI *)SourceMessage->Buffer;
unsigned char PAPI * D_Output = (unsigned char PAPI *)Target;
register unsigned int Index;
unsigned long SenderDataRepresentation;
//
// Align D_Input to next (0 mod 8) address
//
*(unsigned long *)&D_Input += 7;
*(unsigned long *)&D_Input &= 0XFFFFFFF8L;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
//
// Robust check for little endian IEEE (local data representation)
//
{
int byteCount = 8*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy(
D_Output,
D_Input,
byteCount
);
//
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(D_Input + byteCount);
/* Replaced by RpcpMemoryCopy:
for (Index = LowerIndex; Index < UpperIndex; Index++)
{
((unsigned long *)D_Output)[(Index * 2)] =
*(unsigned long *)D_Input;
D_Input += 4;
((unsigned long *)D_Output)[(Index * 2 + 1)] =
*((unsigned long *)D_Input) ;
D_Input += 4;
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input;
*/
}
else if ( (SourceMessage->DataRepresentation & NDR_FLOAT_REP_MASK) ==
NDR_VAX_FLOAT )
{
for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
{
cvt_vax_g_to_ieee_double(D_Input, 0, D_Output);
D_Input += 8;
D_Output += 8;
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input;
}
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
NDR_BIG_IEEE_REP )
//
// Big endian IEEE sender:
//
{
for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
{
NdrpLongByteSwap(
&((unsigned long PAPI *)D_Input)[0],
&((unsigned long PAPI *)D_Output)[1]
);
NdrpLongByteSwap(
&((unsigned long PAPI *)D_Input)[1],
&((unsigned long PAPI *)D_Output)[0]
);
D_Input += 8;
D_Output += 8;
}
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input;
}
else
{
RpcRaiseException( RPC_X_BAD_STUB_DATA );
}
}
//
// end double_array_from_ndr
//