You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
698 lines
18 KiB
698 lines
18 KiB
|
|
/*++
|
|
|
|
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
|
|
//
|
|
|