1180 lines
33 KiB
C++
1180 lines
33 KiB
C++
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
dataconv.cxx
|
||
|
||
Abstract:
|
||
|
||
This file contains routines used by the RPC stubs to assist in marshalling
|
||
and unmarshalling data to and from an RPC message buffer. Each routine
|
||
receives as a parameter a format string which drives its actions. The
|
||
valid characters for the format string are :
|
||
c - charater
|
||
b - byte
|
||
w - wide charater or short
|
||
l - long
|
||
f - float
|
||
d - double
|
||
s1, s2, sb - string of chars, wide chars, or bytes
|
||
z - byte string
|
||
)2, )4, )8,
|
||
(2, (4, (8,
|
||
1, 2, 4, 8 - various alignment directives
|
||
|
||
For more details consult the Network Computing Architecture documentation
|
||
on Network Data Representation.
|
||
|
||
Author:
|
||
|
||
Donna Liu (donnali) 09-Nov-1990
|
||
|
||
Revision History:
|
||
|
||
26-Feb-1992 donnali
|
||
|
||
Moved toward NT coding style.
|
||
|
||
09-Jul-1993 DKays
|
||
|
||
Made wholesale source level optimizations for speed and size.
|
||
|
||
--*/
|
||
|
||
#include <sysinc.h>
|
||
#include <rpc.h>
|
||
#include <rpcndr.h>
|
||
#include <ndrlibp.h>
|
||
|
||
//
|
||
// alignment macros
|
||
//
|
||
|
||
#define ALIGN(buffer,increment) \
|
||
(((ULONG_PTR)buffer + increment) & ~ increment)
|
||
|
||
#define ALIGN2(buffer) \
|
||
(((ULONG_PTR)buffer + 1) & ~1)
|
||
|
||
#define ALIGN4(buffer) \
|
||
(((ULONG_PTR)buffer + 3) & ~3)
|
||
|
||
#define ALIGN8(buffer) \
|
||
(((ULONG_PTR)buffer + 7) & ~7)
|
||
|
||
// local routines
|
||
static unsigned long NdrStrlenStrcpy ( char *, char * );
|
||
static unsigned long NdrWStrlenStrcpy ( wchar_t *, wchar_t * );
|
||
|
||
|
||
void RPC_ENTRY
|
||
data_from_ndr (
|
||
PRPC_MESSAGE source,
|
||
void * target,
|
||
char * format,
|
||
unsigned char MscPak)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine copies data from the runtime buffer.
|
||
|
||
Arguments:
|
||
|
||
source - RPC message structure passed from the runtime to the stub.
|
||
|
||
target - Buffer to receive the unmarshalled data.
|
||
|
||
format - Format of the data.
|
||
|
||
MscPak - Packing level.
|
||
|
||
--*/
|
||
{
|
||
unsigned long valid_lower;
|
||
unsigned long valid_total;
|
||
register char *pSource;
|
||
register char *pTarget;
|
||
unsigned long pack2, pack4, pack8;
|
||
unsigned long pack, align;
|
||
|
||
// pre-compute the possible alignment masks
|
||
if ( MscPak )
|
||
MscPak--;
|
||
pack2 = MscPak & 0x1;
|
||
pack4 = MscPak & 0x3;
|
||
pack8 = MscPak & 0x7;
|
||
|
||
pSource = (char *) source->Buffer;
|
||
|
||
if ((source->DataRepresentation & (unsigned long)0X0000FFFF) ==
|
||
NDR_LOCAL_DATA_REPRESENTATION)
|
||
{
|
||
|
||
pTarget = (char *) target;
|
||
|
||
for (;;)
|
||
{
|
||
switch ( *format++ )
|
||
{
|
||
case 'b' :
|
||
case 'c' :
|
||
*((char *)pTarget) = *((char *)pSource);
|
||
pTarget += 1;
|
||
pSource += 1;
|
||
break;
|
||
case 'w' :
|
||
pSource = (char *) ALIGN2(pSource);
|
||
pTarget = (char *) ALIGN(pTarget,pack2);
|
||
|
||
*((short *)pTarget) = *((short *)pSource);
|
||
pTarget += 2;
|
||
pSource += 2;
|
||
break;
|
||
case 'l' :
|
||
case 'f' :
|
||
pSource = (char *) ALIGN4(pSource);
|
||
pTarget = (char *) ALIGN(pTarget,pack4);
|
||
|
||
*((long *)pTarget) = *((long *)pSource);
|
||
pTarget += 4;
|
||
pSource += 4;
|
||
break;
|
||
case 'h' :
|
||
case 'd' :
|
||
pSource = (char *) ALIGN8(pSource);
|
||
pTarget = (char *) ALIGN(pTarget,pack8);
|
||
|
||
#if defined(DOS) || defined(WIN)
|
||
*((DWORD *) pTarget) = *((DWORD *) &pSource);
|
||
*(((DWORD *) pTarget) + 1) = *(((DWORD *) &pSource) + 1);
|
||
#else
|
||
*((__int64 *)pTarget) = *((__int64 *)pSource);
|
||
#endif
|
||
pTarget += 8;
|
||
pSource += 8;
|
||
break;
|
||
case 's' :
|
||
pSource = (char *) ALIGN4(pSource);
|
||
|
||
valid_lower = *((long *)pSource);
|
||
pSource += 4;
|
||
valid_total = *((long *)pSource);
|
||
pSource += 4;
|
||
|
||
// double the valid_total if this is a wide char string
|
||
if ( *format++ == '2' )
|
||
valid_total <<= 1;
|
||
|
||
RpcpMemoryCopy(pTarget,
|
||
pSource,
|
||
valid_total);
|
||
pTarget += valid_total;
|
||
pSource += valid_total;
|
||
break;
|
||
case 'z' :
|
||
pSource = (char *) ALIGN4(pSource);
|
||
|
||
valid_total = *((long *)pSource);
|
||
pSource += 4;
|
||
|
||
*((int *)pTarget - 1) = (int) valid_total;
|
||
|
||
// double the valid_total if this is a wide char string
|
||
if ( *format++ == '2' )
|
||
valid_total <<= 1;
|
||
|
||
RpcpMemoryCopy(pTarget,
|
||
pSource,
|
||
valid_total);
|
||
pTarget += valid_total;
|
||
pSource += valid_total;
|
||
break;
|
||
case 'p' :
|
||
pSource = (char *) ALIGN4(pSource);
|
||
pTarget = (char *) ALIGN(pTarget,pack4);
|
||
|
||
pTarget += 4;
|
||
pSource += 4;
|
||
break;
|
||
case '(' :
|
||
// *format == '2', '4', or '8'; align = 1, 3, or 7
|
||
align = *format - '0' - 1;
|
||
pSource = (char *) ALIGN(pSource,align);
|
||
case ')' :
|
||
switch ( *format++ )
|
||
{
|
||
case '8' :
|
||
pack = pack8;
|
||
break;
|
||
case '4' :
|
||
pack = pack4;
|
||
break;
|
||
case '2' :
|
||
pack = pack2;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
pTarget = (char *) ALIGN(pTarget,pack);
|
||
break;
|
||
case '8' :
|
||
pSource = (char *) ALIGN8(pSource);
|
||
break;
|
||
case '4' :
|
||
pSource = (char *) ALIGN4(pSource);
|
||
break;
|
||
case '2' :
|
||
pSource = (char *) ALIGN2(pSource);
|
||
break;
|
||
case '1' :
|
||
break;
|
||
default :
|
||
source->Buffer = pSource;
|
||
return;
|
||
} // switch
|
||
} // for
|
||
} // if
|
||
else
|
||
{
|
||
for (;;)
|
||
{
|
||
switch ( *format++ )
|
||
{
|
||
case 'b' :
|
||
*((char *)target) = *((char *)source->Buffer);
|
||
source->Buffer = (void *)((ULONG_PTR)source->Buffer + 1);
|
||
target = (void *)((ULONG_PTR)target + 1);
|
||
break;
|
||
case 'c' :
|
||
char_from_ndr(source,(unsigned char *)target);
|
||
target = (void *)((ULONG_PTR)target + 1);
|
||
break;
|
||
case 'w' :
|
||
target = (void *) ALIGN(target,pack2);
|
||
short_from_ndr(source,(unsigned short *)target);
|
||
target = (void *)((ULONG_PTR)target + 2);
|
||
break;
|
||
case 'l' :
|
||
target = (void *) ALIGN(target,pack4);
|
||
long_from_ndr(source,(unsigned long *)target);
|
||
target = (void *)((ULONG_PTR)target + 4);
|
||
break;
|
||
case 'f' :
|
||
target = (void *) ALIGN(target,pack4);
|
||
float_from_ndr(source, target);
|
||
target = (void *)((ULONG_PTR)target + 4);
|
||
break;
|
||
case 'd' :
|
||
target = (void *) ALIGN(target,pack8);
|
||
double_from_ndr(source, target);
|
||
target = (void *)((ULONG_PTR)target + 8);
|
||
break;
|
||
case 'h' :
|
||
target = (void *) ALIGN(target,pack8);
|
||
hyper_from_ndr(source, (hyper *)target);
|
||
target = (void *)((ULONG_PTR)target + 8);
|
||
break;
|
||
case 's' :
|
||
long_from_ndr(source, &valid_lower);
|
||
long_from_ndr(source, &valid_total);
|
||
switch ( *format++ )
|
||
{
|
||
case '2' :
|
||
short_array_from_ndr (source,
|
||
0,
|
||
valid_total,
|
||
(unsigned short *)target);
|
||
valid_total <<= 1;
|
||
break;
|
||
case '1' :
|
||
char_array_from_ndr (source,
|
||
0,
|
||
valid_total,
|
||
(unsigned char *)target);
|
||
break;
|
||
case 'b' :
|
||
byte_array_from_ndr(source,
|
||
0,
|
||
valid_total,
|
||
target);
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
target = (void *)((ULONG_PTR)target + valid_total);
|
||
break;
|
||
case 'z' :
|
||
long_from_ndr(source, &valid_total);
|
||
|
||
*((int *)target - 1) = (int) valid_total;
|
||
|
||
switch ( *format++ )
|
||
{
|
||
case '2' :
|
||
short_array_from_ndr(source,
|
||
0,
|
||
valid_total,
|
||
(unsigned short *)target);
|
||
valid_total <<= 1;
|
||
break;
|
||
case '1' :
|
||
byte_array_from_ndr(source,
|
||
0,
|
||
valid_total,
|
||
target);
|
||
break;
|
||
}
|
||
target = (void *)((ULONG_PTR)target + valid_total);
|
||
break;
|
||
case 'p' :
|
||
source->Buffer = (void *) ALIGN4(source->Buffer);
|
||
target = (void *) ALIGN(target,pack4);
|
||
source->Buffer = (void *)((ULONG_PTR)source->Buffer + 4);
|
||
target = (void *)((ULONG_PTR)target + 4);
|
||
break;
|
||
case '(' :
|
||
// *format == '2', '4', or '8'; align = 1, 3, or 7
|
||
align = *format - '0' - 1;
|
||
pSource = (char *) ALIGN(pSource,align);
|
||
case ')' :
|
||
switch (*format++)
|
||
{
|
||
case '8' :
|
||
pack = pack8;
|
||
break;
|
||
case '4' :
|
||
pack = pack4;
|
||
break;
|
||
case '2' :
|
||
pack = pack2;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
target = (void *) ALIGN(target,pack);
|
||
break;
|
||
case '8' :
|
||
source->Buffer = (void *)ALIGN8(source->Buffer);
|
||
break;
|
||
case '4' :
|
||
source->Buffer = (void *)ALIGN4(source->Buffer);
|
||
break;
|
||
case '2' :
|
||
source->Buffer = (void *)ALIGN2(source->Buffer);
|
||
break;
|
||
case '1' :
|
||
break;
|
||
default :
|
||
return;
|
||
} // switch
|
||
} // for
|
||
} // else
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
data_into_ndr (
|
||
void * source,
|
||
PRPC_MESSAGE target,
|
||
char * format,
|
||
unsigned char MscPak)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine copies data into the runtime buffer.
|
||
|
||
Arguments:
|
||
|
||
source - Buffer of data to be marshalled into the RPC message.
|
||
|
||
target - RPC message structure to be passed to the runtime.
|
||
|
||
format - Format of the data.
|
||
|
||
MscPak - Packing level.
|
||
|
||
--*/
|
||
{
|
||
unsigned long valid_total;
|
||
register char *pSource;
|
||
register char *pTarget;
|
||
unsigned long pack2, pack4, pack8;
|
||
unsigned long increment;
|
||
unsigned long pack, align;
|
||
|
||
pSource = (char *)source;
|
||
pTarget = (char *)target->Buffer;
|
||
|
||
// pre-compute the possible alignment masks
|
||
if ( MscPak )
|
||
MscPak--;
|
||
pack2 = MscPak & 0x1;
|
||
pack4 = MscPak & 0x3;
|
||
pack8 = MscPak & 0x7;
|
||
|
||
for (;;)
|
||
{
|
||
switch (*format++)
|
||
{
|
||
case 'b' :
|
||
case 'c' :
|
||
*((char *)pTarget) = *((char *)pSource);
|
||
pTarget += 1;
|
||
pSource += 1;
|
||
break;
|
||
case 'w' :
|
||
pTarget = (char *) ALIGN2(pTarget);
|
||
pSource = (char *) ALIGN(pSource,pack2);
|
||
|
||
*((short *)pTarget) = *((short *)pSource);
|
||
pTarget += 2;
|
||
pSource += 2;
|
||
break;
|
||
case 'l' :
|
||
case 'f' :
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
*((long *)pTarget) = *((long *)pSource);
|
||
pTarget += 4;
|
||
pSource += 4;
|
||
break;
|
||
case 'h' :
|
||
case 'd' :
|
||
pTarget = (char *) ALIGN8(pTarget);
|
||
pSource = (char *) ALIGN(pSource,pack8);
|
||
|
||
#if defined(DOS) || defined(WIN)
|
||
*((DWORD *) pTarget) = *((DWORD *) &pSource);
|
||
*(((DWORD *) pTarget) + 1) = *(((DWORD *) &pSource) + 1);
|
||
#else
|
||
*((__int64 *)pTarget) = *((__int64 *)pSource);
|
||
#endif
|
||
pTarget += 8;
|
||
pSource += 8;
|
||
break;
|
||
case 's' :
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
|
||
switch (*format++)
|
||
{
|
||
case '2' :
|
||
valid_total = NdrWStrlenStrcpy((wchar_t *)(pTarget + 8),
|
||
(wchar_t *)pSource);
|
||
increment = valid_total << 1;
|
||
break;
|
||
case '1' :
|
||
valid_total = NdrStrlenStrcpy(pTarget + 8,pSource);
|
||
increment = valid_total;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
|
||
*((long *)pTarget) = 0; // offset
|
||
pTarget += 4;
|
||
*((long *)pTarget) = valid_total; // count
|
||
pTarget += 4;
|
||
|
||
pTarget += increment;
|
||
pSource += increment;
|
||
break;
|
||
case 'z' :
|
||
valid_total = (long) *((int *)pSource - 1);
|
||
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
|
||
*((long *)pTarget) = valid_total;
|
||
pTarget += 4;
|
||
|
||
if ( *format++ == '2' )
|
||
valid_total <<= 1;
|
||
|
||
RpcpMemoryCopy(pTarget,
|
||
pSource,
|
||
valid_total);
|
||
pTarget += valid_total;
|
||
pSource += valid_total;
|
||
break;
|
||
case 'p' :
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
pTarget += 4;
|
||
pSource += 4;
|
||
break;
|
||
case '(' :
|
||
// *format == '2', '4', or '8'; align = 1, 3, or 7
|
||
align = *format - '0' - 1;
|
||
pTarget = (char *) ALIGN(pTarget,align);
|
||
case ')' :
|
||
switch (*format++)
|
||
{
|
||
case '8' :
|
||
pack = pack8;
|
||
break;
|
||
case '4' :
|
||
pack = pack4;
|
||
break;
|
||
case '2' :
|
||
pack = pack2;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
pSource = (char *) ALIGN(pSource,pack);
|
||
break;
|
||
case '8' :
|
||
pTarget = (char *) ALIGN8(pTarget);
|
||
break;
|
||
case '4' :
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
break;
|
||
case '2' :
|
||
pTarget = (char *) ALIGN2(pTarget);
|
||
break;
|
||
case '1' :
|
||
break;
|
||
default :
|
||
target->Buffer = pTarget;
|
||
return;
|
||
} // switch
|
||
} // for
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
tree_into_ndr (
|
||
void * source,
|
||
PRPC_MESSAGE target,
|
||
char * format,
|
||
unsigned char MscPak)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine copies data into the runtime buffer.
|
||
|
||
Arguments:
|
||
|
||
source - Buffer of data to be marshalled into the RPC message.
|
||
|
||
target - RPC message structure to be passed to the runtime.
|
||
|
||
format - Format of the data.
|
||
|
||
MscPak - Packing level.
|
||
|
||
--*/
|
||
{
|
||
unsigned long valid_total;
|
||
register char *pSource;
|
||
register char *pTarget;
|
||
unsigned long pack2, pack4, pack8;
|
||
unsigned long increment;
|
||
|
||
pSource = (char *)source;
|
||
pTarget = (char *)target->Buffer;
|
||
|
||
// pre-compute the possible alignment masks
|
||
if ( MscPak )
|
||
MscPak--;
|
||
pack2 = MscPak & 0x1;
|
||
pack4 = MscPak & 0x3;
|
||
pack8 = MscPak & 0x7;
|
||
|
||
for (;;)
|
||
{
|
||
switch (*format++)
|
||
{
|
||
case 'b' :
|
||
case 'c' :
|
||
pSource += 1;
|
||
break;
|
||
case 'w' :
|
||
pSource = (char *) ALIGN(pSource,pack2);
|
||
pSource += 2;
|
||
break;
|
||
case 'l' :
|
||
case 'f' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
pSource += 4;
|
||
break;
|
||
case 'h' :
|
||
case 'd' :
|
||
pSource = (char *) ALIGN(pSource,pack8);
|
||
pSource += 8;
|
||
break;
|
||
case 's' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
if ( ! *(void **)pSource )
|
||
{
|
||
pSource += 4;
|
||
format++;
|
||
break;
|
||
}
|
||
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
|
||
switch (*format++)
|
||
{
|
||
case '2' :
|
||
valid_total = NdrWStrlenStrcpy((wchar_t *)(pTarget+12),
|
||
*(wchar_t **)pSource);
|
||
increment = valid_total << 1;
|
||
break;
|
||
case '1' :
|
||
valid_total = NdrStrlenStrcpy(pTarget + 12,
|
||
*(char **)pSource);
|
||
increment = valid_total;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
|
||
*((long *)pTarget) = valid_total; // max count
|
||
pTarget += 4;
|
||
*((long *)pTarget) = 0; // offset
|
||
pTarget += 4;
|
||
*((long *)pTarget) = valid_total; // actual count
|
||
pTarget += 4;
|
||
|
||
pSource += 4;
|
||
pTarget += increment;
|
||
break;
|
||
case 'z' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
if ( ! *(void **)pSource )
|
||
{
|
||
pSource += 4;
|
||
break;
|
||
}
|
||
|
||
valid_total = (long) *(*(int **)pSource - 1);
|
||
|
||
pTarget = (char *) ALIGN4(pTarget);
|
||
|
||
*((long *)pTarget) = valid_total; // max count
|
||
pTarget += 4;
|
||
*((long *)pTarget) = valid_total; // actual count
|
||
pTarget += 4;
|
||
|
||
if ( *format++ == '2' )
|
||
valid_total <<= 1;
|
||
|
||
RpcpMemoryCopy(pTarget,
|
||
*(char **)pSource,
|
||
valid_total);
|
||
pSource += 4;
|
||
pTarget += valid_total;
|
||
break;
|
||
case '(' :
|
||
case ')' :
|
||
switch (*format++)
|
||
{
|
||
case '8' :
|
||
pSource = (char *) ALIGN(pSource,pack8);
|
||
break;
|
||
case '4' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
break;
|
||
case '2' :
|
||
pSource = (char *) ALIGN(pSource,pack2);
|
||
break;
|
||
default :
|
||
break;
|
||
}
|
||
break;
|
||
case '8' :
|
||
case '4' :
|
||
case '2' :
|
||
case '1' :
|
||
break;
|
||
default :
|
||
target->Buffer = pTarget;
|
||
return;
|
||
} // switch
|
||
} // for
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
data_size_ndr (
|
||
void * source,
|
||
PRPC_MESSAGE target,
|
||
char * format,
|
||
unsigned char MscPak)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine calculates the size of the runtime buffer.
|
||
|
||
Arguments:
|
||
|
||
source - Buffer of data to be marshalled into the RPC message.
|
||
|
||
target - RPC message structure to be passed to the runtime.
|
||
|
||
format - Format of the data.
|
||
|
||
MscPak - Packing level.
|
||
|
||
--*/
|
||
{
|
||
unsigned long valid_total;
|
||
register char *pSource;
|
||
register unsigned long targetLength;
|
||
unsigned long pack2, pack4, pack8;
|
||
unsigned long pack, align;
|
||
|
||
pSource = (char *)source;
|
||
targetLength = target->BufferLength;
|
||
|
||
// pre-compute the possible alignment masks
|
||
if ( MscPak )
|
||
MscPak--;
|
||
pack2 = MscPak & 0x1;
|
||
pack4 = MscPak & 0x3;
|
||
pack8 = MscPak & 0x7;
|
||
|
||
for (;;)
|
||
{
|
||
switch (*format++)
|
||
{
|
||
case 'b' :
|
||
case 'c' :
|
||
targetLength += 1;
|
||
break;
|
||
case 'w' :
|
||
targetLength = (unsigned long) ALIGN2(targetLength);
|
||
pSource = (char *) ALIGN(pSource,pack2);
|
||
|
||
targetLength += 2;
|
||
pSource += 2;
|
||
break;
|
||
case 'l' :
|
||
case 'f' :
|
||
targetLength = (unsigned long) ALIGN4(targetLength);
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
targetLength += 4;
|
||
pSource += 4;
|
||
break;
|
||
case 'h' :
|
||
case 'd' :
|
||
targetLength = (unsigned long) ALIGN8(targetLength);
|
||
pSource = (char *) ALIGN(pSource,pack8);
|
||
|
||
targetLength += 8;
|
||
pSource += 8;
|
||
break;
|
||
case 's' :
|
||
switch (*format++)
|
||
{
|
||
case '2' :
|
||
valid_total = MIDL_wchar_strlen((wchar_t *)pSource) + 1;
|
||
valid_total <<= 1;
|
||
break;
|
||
case '1' :
|
||
valid_total = strlen(pSource) + 1;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
|
||
targetLength = (unsigned long) ALIGN4(targetLength);
|
||
|
||
// add string length plus two longs (for offset and count)
|
||
targetLength += 8 + valid_total;
|
||
break;
|
||
case 'z' :
|
||
targetLength = (unsigned long) ALIGN4(targetLength);
|
||
|
||
valid_total = (long) *((int *)pSource - 1);
|
||
if ( *format++ == '2' )
|
||
valid_total <<= 1;
|
||
|
||
// add byte string length plus one long (for count)
|
||
targetLength += 4 + valid_total;
|
||
break;
|
||
case 'p' :
|
||
targetLength = (unsigned long) ALIGN4(targetLength);
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
target->Buffer = (void *)((ULONG_PTR)target->Buffer + 4);
|
||
pSource += 4;
|
||
break;
|
||
case '(' :
|
||
// *format == '2', '4', or '8'; align = 1, 3, or 7
|
||
align = *format - '0' - 1;
|
||
targetLength = (unsigned long) ALIGN(targetLength,align);
|
||
case ')' :
|
||
switch (*format++)
|
||
{
|
||
case '8' :
|
||
pack = pack8;
|
||
break;
|
||
case '4' :
|
||
pack = pack4;
|
||
break;
|
||
case '2' :
|
||
pack = pack2;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
pSource = (char *) ALIGN(pSource,pack);
|
||
break;
|
||
case '8' :
|
||
targetLength = (unsigned long) ALIGN8(targetLength);
|
||
break;
|
||
case '4' :
|
||
targetLength = (unsigned long) ALIGN4(targetLength);
|
||
break;
|
||
case '2' :
|
||
targetLength = (unsigned long) ALIGN2(targetLength);
|
||
break;
|
||
case '1' :
|
||
break;
|
||
default :
|
||
target->BufferLength = targetLength;
|
||
return;
|
||
} // switch
|
||
} // for
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
tree_size_ndr (
|
||
void * source,
|
||
PRPC_MESSAGE target,
|
||
char * format,
|
||
unsigned char MscPak)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine calculates the size of the runtime buffer.
|
||
|
||
Arguments:
|
||
|
||
source - Buffer of data to be marshalled into the RPC message.
|
||
|
||
target - RPC message structure to be passed to the runtime.
|
||
|
||
format - Format of the data.
|
||
|
||
MscPak - Packing level.
|
||
|
||
--*/
|
||
{
|
||
unsigned long valid_total;
|
||
register char *pSource;
|
||
unsigned long pack2, pack4, pack8;
|
||
|
||
pSource = (char *)source;
|
||
|
||
// pre-compute the possible alignment masks
|
||
if ( MscPak )
|
||
MscPak--;
|
||
pack2 = MscPak & 0x1;
|
||
pack4 = MscPak & 0x3;
|
||
pack8 = MscPak & 0x7;
|
||
|
||
for (;;)
|
||
{
|
||
switch (*format++)
|
||
{
|
||
case 'b' :
|
||
case 'c' :
|
||
pSource += 1;
|
||
break;
|
||
case 'w' :
|
||
pSource = (char *) ALIGN(pSource,pack2);
|
||
pSource += 2;
|
||
break;
|
||
case 'l' :
|
||
case 'f' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
pSource += 4;
|
||
break;
|
||
case 'h' :
|
||
case 'd' :
|
||
pSource = (char *) ALIGN(pSource,pack8);
|
||
pSource += 8;
|
||
break;
|
||
case 's' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
if ( ! *(void __RPC_FAR * __RPC_FAR *)pSource )
|
||
{
|
||
pSource += 4;
|
||
format++;
|
||
break;
|
||
}
|
||
|
||
switch (*format++)
|
||
{
|
||
case '2' :
|
||
valid_total = MIDL_wchar_strlen(
|
||
*(wchar_t __RPC_FAR * __RPC_FAR *)pSource)+1;
|
||
valid_total <<= 1;
|
||
break;
|
||
case '1' :
|
||
valid_total =
|
||
strlen (*(char __RPC_FAR * __RPC_FAR *)pSource) + 1;
|
||
break;
|
||
default :
|
||
continue;
|
||
}
|
||
|
||
target->BufferLength = (unsigned int)
|
||
ALIGN4(target->BufferLength);
|
||
|
||
// add string length plus 3 longs (max count, offset, and
|
||
// actual count)
|
||
target->BufferLength += 12 + valid_total;
|
||
pSource += 4;
|
||
break;
|
||
case 'z' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
|
||
if ( ! *(void __RPC_FAR * __RPC_FAR *)pSource )
|
||
{
|
||
pSource += 4;
|
||
break;
|
||
}
|
||
|
||
valid_total = (long) *(*(int **)pSource - 1);
|
||
if ( *format++ == '2' )
|
||
valid_total <<= 1;
|
||
|
||
target->BufferLength = (unsigned int)
|
||
ALIGN4(target->BufferLength);
|
||
|
||
// add string length plus 2 longs (max count and actual count)
|
||
target->BufferLength += 8 + valid_total;
|
||
pSource += 4;
|
||
break;
|
||
case '(' :
|
||
case ')' :
|
||
switch (*format++)
|
||
{
|
||
case '8' :
|
||
pSource = (char *) ALIGN(pSource,pack8);
|
||
break;
|
||
case '4' :
|
||
pSource = (char *) ALIGN(pSource,pack4);
|
||
break;
|
||
case '2' :
|
||
pSource = (char *) ALIGN(pSource,pack2);
|
||
break;
|
||
default :
|
||
break;
|
||
}
|
||
break;
|
||
case '8' :
|
||
case '4' :
|
||
case '2' :
|
||
case '1' :
|
||
break;
|
||
default :
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
tree_peek_ndr (
|
||
PRPC_MESSAGE source,
|
||
unsigned char ** buffer,
|
||
char * format,
|
||
unsigned char MscPak)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine peeks the runtime buffer.
|
||
|
||
Arguments:
|
||
|
||
source - RPC message structure passed from the runtime to the stubs.
|
||
|
||
target - Buffer to receive the unmarshalled data.
|
||
|
||
format - Format of the data.
|
||
|
||
MscPak - Packing level.
|
||
|
||
--*/
|
||
{
|
||
unsigned long valid_total;
|
||
register unsigned char *pBuffer;
|
||
unsigned long pack8;
|
||
int IsString;
|
||
|
||
pBuffer = *buffer;
|
||
|
||
// pre-compute the possible alignment masks
|
||
if ( MscPak )
|
||
MscPak--;
|
||
pack8 = MscPak & 0x7;
|
||
|
||
IsString = (*format == 's' || *format == 'z');
|
||
|
||
for (;;)
|
||
{
|
||
switch (*format++)
|
||
{
|
||
case 'b' :
|
||
case 'c' :
|
||
pBuffer += 1;
|
||
break;
|
||
case 'w' :
|
||
pBuffer = (unsigned char *) ALIGN2(pBuffer);
|
||
pBuffer += 2;
|
||
break;
|
||
case 'l' :
|
||
case 'f' :
|
||
pBuffer = (unsigned char *) ALIGN4(pBuffer);
|
||
pBuffer += 4;
|
||
break;
|
||
case 'h' :
|
||
case 'd' :
|
||
pBuffer = (unsigned char *) ALIGN8(pBuffer);
|
||
pBuffer += 8;
|
||
break;
|
||
case 's' :
|
||
if ( ! IsString )
|
||
{
|
||
pBuffer = (unsigned char *) ALIGN4(pBuffer);
|
||
if ( ! *(long *)pBuffer )
|
||
{
|
||
pBuffer += 4;
|
||
format++;
|
||
break;
|
||
}
|
||
pBuffer += 4;
|
||
long_from_ndr (source, &valid_total); // max count (ignore)
|
||
}
|
||
|
||
long_from_ndr (source, &valid_total); // offset (ignore)
|
||
long_from_ndr (source, &valid_total); // actual count
|
||
|
||
// if it's a wide char string
|
||
if ( *format++ == '2' )
|
||
{
|
||
// wide char string must be aligned on at least a
|
||
// short boundary
|
||
if ( ! MscPak )
|
||
pack8 = 0x1;
|
||
valid_total <<= 1;
|
||
}
|
||
|
||
source->BufferLength = (unsigned int)
|
||
ALIGN(source->BufferLength,pack8);
|
||
|
||
*((unsigned long *)pBuffer - 1) = source->BufferLength;
|
||
source->BufferLength += valid_total;
|
||
source->Buffer = (void *)((ULONG_PTR)source->Buffer + valid_total);
|
||
break;
|
||
case 'z' :
|
||
if ( ! IsString )
|
||
{
|
||
pBuffer = (unsigned char *) ALIGN4(pBuffer);
|
||
if ( ! *(long *)pBuffer )
|
||
{
|
||
pBuffer += 4;
|
||
format++;
|
||
break;
|
||
}
|
||
pBuffer += 4;
|
||
long_from_ndr (source, &valid_total); // max count (ignore)
|
||
}
|
||
|
||
long_from_ndr (source, &valid_total); // actual count
|
||
|
||
// if it's a wide byte string
|
||
if ( *format++ == '2' )
|
||
{
|
||
// wide byte string must be aligned on at least a
|
||
// short boundary
|
||
if ( ! MscPak )
|
||
pack8 = 0x1;
|
||
valid_total <<= 1;
|
||
}
|
||
|
||
source->BufferLength = (unsigned int)
|
||
ALIGN(source->BufferLength,pack8);
|
||
|
||
*((unsigned long *)pBuffer - 1) = source->BufferLength;
|
||
source->BufferLength += valid_total;
|
||
source->Buffer = (void *)((ULONG_PTR)source->Buffer + valid_total);
|
||
break;
|
||
case '(' :
|
||
switch (*format++)
|
||
{
|
||
case '8' :
|
||
pBuffer = (unsigned char *) ALIGN8(pBuffer);
|
||
break;
|
||
case '4' :
|
||
pBuffer = (unsigned char *) ALIGN4(pBuffer);
|
||
break;
|
||
case '2' :
|
||
pBuffer = (unsigned char *) ALIGN2(pBuffer);
|
||
break;
|
||
default :
|
||
break;
|
||
}
|
||
break;
|
||
case ')' :
|
||
format++;
|
||
break;
|
||
case '8' :
|
||
pBuffer = (unsigned char *) ALIGN8(pBuffer);
|
||
break;
|
||
case '4' :
|
||
pBuffer = (unsigned char *) ALIGN4(pBuffer);
|
||
break;
|
||
case '2' :
|
||
pBuffer = (unsigned char *) ALIGN2(pBuffer);
|
||
break;
|
||
case '1' :
|
||
break;
|
||
default :
|
||
*buffer = pBuffer;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
static unsigned long NdrStrlenStrcpy ( char *pTarget,
|
||
char *pSource )
|
||
{
|
||
register unsigned int count;
|
||
|
||
for ( count = 1; *pTarget++ = *pSource++; count++ )
|
||
;
|
||
|
||
return count;
|
||
}
|
||
|
||
static unsigned long NdrWStrlenStrcpy ( wchar_t *pTarget,
|
||
wchar_t *pSource )
|
||
{
|
||
register unsigned int count;
|
||
|
||
for ( count = 1; *pTarget++ = *pSource++; count++ )
|
||
;
|
||
|
||
return count;
|
||
}
|