mirror of https://github.com/tongzx/nt5src
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.
1179 lines
33 KiB
1179 lines
33 KiB
/*++
|
|
|
|
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;
|
|
}
|