997 lines
25 KiB
C++
997 lines
25 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1998 Microsoft Corporation
|
||
|
All rights reserved.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
marshall.cxx
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Code for custom marshalling spooler structures sent via RPC/LPC.
|
||
|
It handles 32-64 bit machine compatibility depending on the route the call is comming.
|
||
|
It can come either from Kernel mode (NATIVE_CALL), an in-proc winspool.drv call (NATIVE_CALL),
|
||
|
a 32 bit process (RPC_CALL) or a 64 bit process (RPC_CALL).
|
||
|
For native calls we perform basic marshalling. For RPC_CALLS we perform custom marshalling.
|
||
|
Because there is no way to distinguish if a call came from a 64b or 32b proc, we always do
|
||
|
custom marshalling across processes/wire.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Ramanathan Venkatapathy (RamanV) 4/30/98
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Adina Trufinescu (AdinaTru) 12/09/99
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "spllibp.hxx"
|
||
|
#pragma hdrstop
|
||
|
#include "cstmarsh.h"
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
GetShrinkedSize
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Calculates the size of a 64bit structure as it is on 32bit.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pFieldInfo -- structure containing information about fields inside the structure.
|
||
|
pShrinkedSize -- how much difference it between the structure'ssize on 32bit and 64bit
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Size of the 32bit structure.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Not set.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
BOOL
|
||
|
GetShrinkedSize(
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
OUT SIZE_T *pShrinkedSize
|
||
|
)
|
||
|
{
|
||
|
|
||
|
DWORD Index = 0;
|
||
|
ULONG_PTR Size = 0;
|
||
|
ULONG_PTR Alignment = 0;
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
|
||
|
*pShrinkedSize = 0;
|
||
|
|
||
|
//
|
||
|
// For each field in the structure adds the length and enforce field's alignment.
|
||
|
// For data fileds, the alignment is the same on both 32b and 64b.
|
||
|
//
|
||
|
for (Index = 0; pFieldInfo[Index].Offset != 0xffffffff; ++Index)
|
||
|
{
|
||
|
switch (pFieldInfo[Index].Type)
|
||
|
{
|
||
|
case PTR_TYPE:
|
||
|
{
|
||
|
//
|
||
|
// Treat pointers as they are on 32bit.
|
||
|
//
|
||
|
Size = sizeof(DWORD32);
|
||
|
Alignment = sizeof(DWORD32);
|
||
|
break;
|
||
|
}
|
||
|
case DATA_TYPE:
|
||
|
{
|
||
|
Size = pFieldInfo[Index].Size;
|
||
|
Alignment = pFieldInfo[Index].Alignment;
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Enforce alignment before adding the size of the next field.
|
||
|
//
|
||
|
*pShrinkedSize = (SIZE_T)(AlignIt((PBYTE)*pShrinkedSize, Alignment));
|
||
|
//
|
||
|
// Add field's size.
|
||
|
//
|
||
|
*pShrinkedSize += Size;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Almoust done. We need to align the 32b structure's size to 32bit since
|
||
|
// structures come as an array.
|
||
|
//
|
||
|
Alignment = sizeof(DWORD32);
|
||
|
*pShrinkedSize = (SIZE_T)(AlignIt((PBYTE)*pShrinkedSize, Alignment));
|
||
|
|
||
|
ReturnValue = TRUE;
|
||
|
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
MarshallDownStructure
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Marshalls down structures to be sent via RPC/LPC.
|
||
|
|
||
|
Arguments:
|
||
|
pStructure -- pointer to the structure to be marshalled down
|
||
|
pFieldInfo -- structure containing information about fileds inside the structure
|
||
|
StructureSize -- size of the unmarshalled structure
|
||
|
RpcRoute -- indicates what type of marshalling we should do
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful;
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
BOOL
|
||
|
MarshallDownStructure(
|
||
|
IN OUT PBYTE pStructure,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN CALL_ROUTE Route
|
||
|
)
|
||
|
{
|
||
|
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
if (!pStructure || !pFieldInfo)
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
//
|
||
|
// 32 bit server does not require special marshalling;
|
||
|
//
|
||
|
ReturnValue = BasicMarshallDownStructure(pStructure, pFieldInfo);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr :
|
||
|
{
|
||
|
switch (Route)
|
||
|
{
|
||
|
case NATIVE_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came from Kernel Mode. In KM the structure is basic marshalled.
|
||
|
// We need to do the same thing
|
||
|
//
|
||
|
ReturnValue = BasicMarshallDownStructure(pStructure, pFieldInfo);
|
||
|
break;
|
||
|
}
|
||
|
case RPC_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came through RPC.
|
||
|
// Do the custom marshalling regardless of caller's bitness.
|
||
|
//
|
||
|
ReturnValue = CustomMarshallDownStructure(pStructure, pFieldInfo, StructureSize);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown route; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown pointer size; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
MarshallDownEntry
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Custom marshalls down structures to be sent via RPC/LPC.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pStructure -- pointer to the structure to be marshalled down
|
||
|
pNewStructure -- pointer to the new place where the structure will lay down
|
||
|
in the array of marshalled down structures ( pStructure == pNewStructure on 32b)
|
||
|
pFieldInfo -- structure containing information about fileds inside the structure
|
||
|
StructureSize -- size of the unmarshalled structure
|
||
|
RpcRoute -- indicates what type of marshalling we should do
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful;
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
|
||
|
|
||
|
--*/
|
||
|
BOOL
|
||
|
MarshallDownEntry(
|
||
|
IN OUT PBYTE pStructure,
|
||
|
IN PBYTE pNewStructure,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN CALL_ROUTE Route
|
||
|
)
|
||
|
{
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
if (!pStructure || !pFieldInfo)
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
//
|
||
|
// 32 bit server does not require special marshalling
|
||
|
//
|
||
|
ReturnValue = BasicMarshallDownEntry(pStructure, pFieldInfo);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr :
|
||
|
{
|
||
|
switch (Route)
|
||
|
{
|
||
|
case NATIVE_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came from Kernel Mode. In KM the structure is basic marshalled.
|
||
|
// We need to do the same thing here.
|
||
|
//
|
||
|
ReturnValue = BasicMarshallDownEntry(pStructure, pFieldInfo);
|
||
|
break;
|
||
|
}
|
||
|
case RPC_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came through RPC.
|
||
|
// Do the custom marshalling regardless of caller's bitness.
|
||
|
//
|
||
|
ReturnValue = CustomMarshallDownEntry(pStructure, pNewStructure, pFieldInfo, StructureSize);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown route; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown pointer size; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
MarshallUpStructure
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Custom marshalls up structures to be sent via RPC/LPC.
|
||
|
|
||
|
Arguments:
|
||
|
pStructure -- pointer to the structure to be marshalled up
|
||
|
pFieldInfo -- structure containing information about fileds inside the structure
|
||
|
StructureSize -- size of the structure as it is to be when marsahlled up
|
||
|
Route -- indicates what type of marshalling we should do
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
BOOL
|
||
|
MarshallUpStructure(
|
||
|
IN OUT PBYTE pStructure,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN CALL_ROUTE Route
|
||
|
)
|
||
|
{
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
if (!pStructure || !pFieldInfo)
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
ReturnValue = BasicMarshallUpStructure(pStructure, pFieldInfo);
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr:
|
||
|
{
|
||
|
switch (Route)
|
||
|
{
|
||
|
case NATIVE_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came from Kernel Mode. In KM the structure is basic marshalled.
|
||
|
// We need to do the same thing here.
|
||
|
//
|
||
|
ReturnValue = BasicMarshallUpStructure(pStructure, pFieldInfo);
|
||
|
break;
|
||
|
}
|
||
|
case RPC_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came through RPC.
|
||
|
// Do the custom marshalling regardless of caller's bitness.
|
||
|
//
|
||
|
ReturnValue = CustomMarshallUpStructure(pStructure, pFieldInfo, StructureSize);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown route; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown pointer size; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
MarshallUpEntry
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Custom marshalls up structures to be sent via RPC/LPC.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pStructure -- pointer to the structure to be marshalled up
|
||
|
pNewStructure -- pointer to the new place where the structure will lay down
|
||
|
in the array of marshalled up structures ( pStructure == pNewStructure on 32b)
|
||
|
pFieldInfo -- structure containing information about fileds inside the structure
|
||
|
StructureSize -- size of the structure as it is to be when marshalled up
|
||
|
Route -- determine what type of marshalling will be performed
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
|
||
|
|
||
|
--*/
|
||
|
BOOL
|
||
|
MarshallUpEntry(
|
||
|
IN OUT PBYTE pStructure,
|
||
|
IN PBYTE pNewStructure,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN SIZE_T ShrinkedSize,
|
||
|
IN CALL_ROUTE Route
|
||
|
)
|
||
|
{
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
if (!pStructure || !pFieldInfo)
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
ReturnValue = BasicMarshallUpEntry(pStructure, pFieldInfo);
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr :
|
||
|
{
|
||
|
switch (Route)
|
||
|
{
|
||
|
case NATIVE_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came from Kernel Mode. In KM the structure is basic marshalled.
|
||
|
// We need to do the same thing here.
|
||
|
//
|
||
|
ReturnValue = BasicMarshallUpEntry(pStructure, pFieldInfo);
|
||
|
break;
|
||
|
}
|
||
|
case RPC_CALL:
|
||
|
{
|
||
|
//
|
||
|
// The call came through RPC.
|
||
|
// Do the custom marshalling regardless of caller's bitness.
|
||
|
//
|
||
|
ReturnValue = CustomMarshallUpEntry(pStructure, pNewStructure, pFieldInfo,
|
||
|
StructureSize, ShrinkedSize);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown route; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown pointer size; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
MarshallDownStructuresArray
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Custom marshalls down array of structures to be sent via RPC/LPC.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pBufferArray -- pointer to the buffer containing the array of structures and packed data
|
||
|
cReturned -- number of structures returned
|
||
|
pFieldInfo -- structure containing information about fields inside the structure
|
||
|
StructureSize -- size of the 64bit structure
|
||
|
RpcRoute -- indicates what type of marshalling we should do
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
BOOL
|
||
|
MarshallDownStructuresArray(
|
||
|
IN OUT PBYTE pBufferArray,
|
||
|
IN DWORD cReturned,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN CALL_ROUTE Route
|
||
|
)
|
||
|
{
|
||
|
DWORD Index = 0;
|
||
|
PBYTE pStructure, pNewStructure;
|
||
|
SIZE_T ShrinkedSize = 0;
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
//
|
||
|
// Check if there are any structures in the array.
|
||
|
// This check must come before the one against pBufferArray and pFieldInfo.
|
||
|
// If the Enum function didn't enumerate anything, we need to return success.
|
||
|
//
|
||
|
if (cReturned == 0) {
|
||
|
|
||
|
ReturnValue = TRUE;
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
if (!pBufferArray || !pFieldInfo)
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
//
|
||
|
// The size of the structure remains the same on 32b.
|
||
|
//
|
||
|
ShrinkedSize = StructureSize;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr:
|
||
|
{
|
||
|
switch (Route)
|
||
|
{
|
||
|
case NATIVE_CALL:
|
||
|
{
|
||
|
//
|
||
|
// There is no need of special marshalling since the structures
|
||
|
// need to stay padding unaltered.
|
||
|
//
|
||
|
ShrinkedSize = StructureSize;
|
||
|
break;
|
||
|
}
|
||
|
case RPC_CALL:
|
||
|
{
|
||
|
//
|
||
|
// Get the size of the 32b structure ; it takes care of both pointers and pointers/data alignments
|
||
|
//
|
||
|
if (!GetShrinkedSize(pFieldInfo, &ShrinkedSize))
|
||
|
{
|
||
|
goto End;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Unknown route size; should never happen
|
||
|
//
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// pStructure is the pointer to the place where the 64b structure lays down in the array
|
||
|
// pNewStructure is the pointer to the new place where the 32b structure will lay down in the array
|
||
|
// MarshallDownEntry returns a pointer to the end of the just marshalled 32b structure which is
|
||
|
// the new place where the next 32b marshalled structure will lay down in the array
|
||
|
//
|
||
|
for( Index = 0, pNewStructure = pStructure = pBufferArray;
|
||
|
Index < cReturned ;
|
||
|
Index++ , pStructure += StructureSize , pNewStructure += ShrinkedSize )
|
||
|
{
|
||
|
if (!MarshallDownEntry(pStructure, pNewStructure, pFieldInfo, StructureSize, Route))
|
||
|
{
|
||
|
goto End;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnValue = TRUE;
|
||
|
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
MarshallUpStructuresArray
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Custom marshalls up array of structures to be sent via RPC/LPC.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pBufferArray -- pointer to the buffer containing the array of structures and packed data
|
||
|
cReturned -- number of structures returned
|
||
|
pFieldInfo -- structure containing information about fileds inside the structure
|
||
|
StructureSize -- size of the 64bit structure ( including the padding )
|
||
|
Route -- determine what type of marshalling will be performed
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
BOOL
|
||
|
MarshallUpStructuresArray(
|
||
|
IN OUT PBYTE pBufferArray,
|
||
|
IN DWORD cReturned,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN CALL_ROUTE Route
|
||
|
)
|
||
|
{
|
||
|
INT32 Index = 0;
|
||
|
PBYTE pStructure, pNextStructure;
|
||
|
SIZE_T ShrinkedSize = 0;
|
||
|
BOOL ReturnValue = FALSE;
|
||
|
|
||
|
//
|
||
|
// Check if there are any structures in the array.
|
||
|
// This check must come before the one against pBufferArray and pFieldInfo.
|
||
|
// If the Enum function didn't enumerate anything, we need to return success.
|
||
|
//
|
||
|
if (cReturned == 0) {
|
||
|
|
||
|
ReturnValue = TRUE;
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
if (!pBufferArray || !pFieldInfo)
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
//
|
||
|
// The size of the structure remains the same on 32b.
|
||
|
//
|
||
|
ShrinkedSize = StructureSize;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr:
|
||
|
{
|
||
|
//
|
||
|
// Get the size of the 32b structure ; it takes care of both pointers and pointers/data alignments
|
||
|
//
|
||
|
if (!GetShrinkedSize(pFieldInfo, &ShrinkedSize))
|
||
|
{
|
||
|
goto End;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
goto End;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// pBufferArray is an array of 32b stuctures;
|
||
|
// pStructure is the pointer to the place where the 32b structure lays down in the array
|
||
|
// pNewStructure is the pointer to the new place where the 64b structure will lay down in the array
|
||
|
//
|
||
|
for (Index = cReturned - 1; Index >= 0 ; Index--)
|
||
|
{
|
||
|
pStructure = pBufferArray + Index * ShrinkedSize;
|
||
|
|
||
|
pNextStructure = pBufferArray + Index * StructureSize;
|
||
|
|
||
|
if (!MarshallUpEntry(pStructure, pNextStructure, pFieldInfo, StructureSize, ShrinkedSize, Route))
|
||
|
{
|
||
|
goto End;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnValue = TRUE;
|
||
|
End:
|
||
|
return ReturnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
UpdateBufferSize
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
UpdateBufferSize adjusts the number of bytes required for
|
||
|
returning the structures based on 32 and 64 bit clients and servers.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pOffsets - pointer to Offset struct
|
||
|
cbStruct - sizeof struct
|
||
|
cbStructAlign - sizeof struct aligned on 32b
|
||
|
pcNeeded - pointer to number of bytes needed
|
||
|
cbBuf - sizeof input buffer
|
||
|
dwError - last error from RPC call
|
||
|
pcReturned - pointer to number of returned structures
|
||
|
(valid only if dwError == ERROR_SUCCESS)
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Last Error; This function is called right after a RPC call.
|
||
|
dwError is the return value of RPC call.
|
||
|
The return value of this function is the result of applying of this code on the dwError.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Not set.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
DWORD
|
||
|
UpdateBufferSize(
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T cbStruct,
|
||
|
IN OUT LPDWORD pcbNeeded,
|
||
|
IN DWORD cbBuf,
|
||
|
IN DWORD dwError,
|
||
|
IN LPDWORD pcReturned
|
||
|
)
|
||
|
{
|
||
|
DWORD cStructures = 0;
|
||
|
SIZE_T cbShrinkedStruct = 0;
|
||
|
|
||
|
if (dwError != ERROR_SUCCESS &&
|
||
|
dwError != ERROR_MORE_DATA &&
|
||
|
dwError != ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
//
|
||
|
// RpcCall failed, no need to update required size
|
||
|
//
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
if (!cbStruct)
|
||
|
{
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
switch (kPointerSize)
|
||
|
{
|
||
|
case kSpl32Ptr:
|
||
|
{
|
||
|
//
|
||
|
// The pointers are not bigger on the server. Hence no adjustment is
|
||
|
// required.
|
||
|
//
|
||
|
break;
|
||
|
}
|
||
|
case kSpl64Ptr:
|
||
|
{
|
||
|
if (!GetShrinkedSize(pFieldInfo, &cbShrinkedStruct))
|
||
|
{
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
goto End;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Increase the required size of buffer. This may be superfluous in the 64-64
|
||
|
// connection but this solution is simpler than adjusting pcbNeeded on the server.
|
||
|
//
|
||
|
// Count the number of structures to be returned
|
||
|
// *pcbNeeded must be divided with the size of the structure on 32 bit.
|
||
|
//
|
||
|
cStructures = *pcbNeeded / (DWORD32)cbShrinkedStruct;
|
||
|
|
||
|
//
|
||
|
// For each structure, pcbNeeded is increased with the number of bites the pointers shrink
|
||
|
// and the number of bites needed fpr padding
|
||
|
// cbStruct - cbStructAlign is the number of bytes the compiler padds
|
||
|
//
|
||
|
*pcbNeeded += (DWORD) (cStructures * (cbStruct - cbShrinkedStruct));
|
||
|
|
||
|
if (cbBuf < *pcbNeeded && dwError == ERROR_SUCCESS)
|
||
|
{
|
||
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// Invalid pointer size; should not occur.
|
||
|
//
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
End:
|
||
|
return dwError;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
AdjustPointers
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
AdjustPointers adjusts pointer fields inside the structure.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pStructure -- pointer to a structructure
|
||
|
pFieldInfo -- contains information about fields inside the structure
|
||
|
cbAdjustment -- quantity to add to all pointer fields inside the structure
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Not set.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
VOID
|
||
|
AdjustPointers
|
||
|
( IN PBYTE pStructure,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN ULONG_PTR cbAdjustment
|
||
|
)
|
||
|
{ PBYTE *pOffset = NULL;
|
||
|
DWORD Index = 0;
|
||
|
DWORD32 Offset = 0;
|
||
|
|
||
|
for (Index = 0; Offset = pFieldInfo[Index].Offset, Offset != 0xffffffff; ++Index)
|
||
|
{
|
||
|
if (pFieldInfo[Index].Type == PTR_TYPE)
|
||
|
{
|
||
|
pOffset = (PBYTE *)(pStructure + Offset);
|
||
|
|
||
|
if ( *pOffset )
|
||
|
{
|
||
|
*pOffset += (ULONG_PTR)cbAdjustment;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
AdjustPointersInStructuresArray
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
AdjustPointersInStructuresArray adjusts pointer fields
|
||
|
inside the each structure of an array.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pBufferArray -- pointer to the buffer containing the array of structures
|
||
|
cReturned -- number of structures in array
|
||
|
pFieldInfo -- contains information about fields inside the structure
|
||
|
StructureSize -- size of structure
|
||
|
cbAdjustment -- quantity to add to all pointer fields inside the structure
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Last Error:
|
||
|
|
||
|
Not set.
|
||
|
|
||
|
--*/
|
||
|
EXTERN_C
|
||
|
VOID
|
||
|
AdjustPointersInStructuresArray(
|
||
|
IN PBYTE pBufferArray,
|
||
|
IN DWORD cReturned,
|
||
|
IN FieldInfo *pFieldInfo,
|
||
|
IN SIZE_T StructureSize,
|
||
|
IN ULONG_PTR cbAdjustment
|
||
|
)
|
||
|
{
|
||
|
INT32 Index = 0;
|
||
|
PBYTE pStructure;
|
||
|
|
||
|
if (cReturned && cbAdjustment && pBufferArray && pFieldInfo)
|
||
|
{
|
||
|
for (Index = cReturned - 1; Index >= 0 ; Index--)
|
||
|
{
|
||
|
pStructure = pBufferArray + Index * StructureSize;
|
||
|
|
||
|
//
|
||
|
// Call AdjustPointers for each entry in the array
|
||
|
//
|
||
|
AdjustPointers(pStructure, pFieldInfo, cbAdjustment);
|
||
|
}
|
||
|
}
|
||
|
}
|