700 lines
20 KiB
C++
700 lines
20 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 2000.
|
||
|
//
|
||
|
// File: hglobal.cxx
|
||
|
//
|
||
|
// Contents: Support for Windows/OLE data types for oleprx32.dll.
|
||
|
// Used to be transmit_as routines, now user_marshal routines.
|
||
|
//
|
||
|
// This file contains support for HGLOBAL.
|
||
|
//
|
||
|
// Functions:
|
||
|
// HGLOBAL_UserSize
|
||
|
// HGLOBAL_UserMarshal
|
||
|
// HGLOBAL_UserUnmarshal
|
||
|
// HGLOBAL_UserFree
|
||
|
// HGLOBAL_UserSize64
|
||
|
// HGLOBAL_UserMarshal64
|
||
|
// HGLOBAL_UserUnmarshal64
|
||
|
// HGLOBAL_UserFree64
|
||
|
//
|
||
|
// History: 13-Dec-00 JohnDoty Migrated from transmit.cxx
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
#include "stdrpc.hxx"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <oleauto.h>
|
||
|
#include <objbase.h>
|
||
|
#include "transmit.hxx"
|
||
|
#include <rpcwdt.h>
|
||
|
#include <storext.h>
|
||
|
#include "widewrap.h"
|
||
|
#include <valid.h>
|
||
|
#include <obase.h>
|
||
|
#include <stream.hxx>
|
||
|
|
||
|
#include "carefulreader.hxx"
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserSize
|
||
|
//
|
||
|
// Synopsis: Get the wire size the HGLOBAL handle and data.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align + 12 + data size.
|
||
|
//
|
||
|
// history: May-95 Ryszardk Created.
|
||
|
// Dec-98 Ryszardk Ported to 64b.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned long __RPC_USER
|
||
|
HGLOBAL_UserSize (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned long Offset,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
if ( !pGlobal )
|
||
|
return Offset;
|
||
|
|
||
|
// userHGLOBAL: the encapsulated union.
|
||
|
// Discriminant and then handle or pointer from the union arm.
|
||
|
|
||
|
LENGTH_ALIGN( Offset, 3 );
|
||
|
|
||
|
// Union discriminent is 4 bytes
|
||
|
Offset += sizeof( long );
|
||
|
|
||
|
// Handle represented by a polymorphic type - for inproc case only!
|
||
|
if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
|
||
|
{
|
||
|
LENGTH_ALIGN( Offset, sizeof( HGLOBAL )-1 );
|
||
|
Offset += sizeof( HGLOBAL );
|
||
|
}
|
||
|
else
|
||
|
Offset += ( sizeof(long) + sizeof(HGLOBAL) );
|
||
|
|
||
|
if ( ! *pGlobal )
|
||
|
return Offset;
|
||
|
|
||
|
if ( HGLOBAL_DATA_PASSING(*pFlags) )
|
||
|
{
|
||
|
unsigned long ulDataSize = (ULONG) GlobalSize( *pGlobal );
|
||
|
|
||
|
Offset += 3 * sizeof(long) + ulDataSize;
|
||
|
}
|
||
|
|
||
|
return( Offset );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserMarshall
|
||
|
//
|
||
|
// Synopsis: Marshalls an HGLOBAL object into the RPC buffer.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align, size, null flag, size, data (bytes, if any)
|
||
|
//
|
||
|
// history: May-95 Ryszardk Created.
|
||
|
// Dec-98 Ryszardk Ported to 64b.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned char __RPC_FAR * __RPC_USER
|
||
|
HGLOBAL_UserMarshal (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned char * pBuffer,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
if ( !pGlobal )
|
||
|
return pBuffer;
|
||
|
|
||
|
// We marshal a null handle, too.
|
||
|
|
||
|
UserNdrDebugOut((UNDR_OUT4, "HGLOBAL_UserMarshal\n"));
|
||
|
|
||
|
ALIGN( pBuffer, 3 );
|
||
|
|
||
|
// Discriminant of the encapsulated union and union arm.
|
||
|
|
||
|
if ( HGLOBAL_DATA_PASSING(*pFlags) )
|
||
|
{
|
||
|
unsigned long ulDataSize;
|
||
|
|
||
|
// userHGLOBAL
|
||
|
|
||
|
*( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
|
||
|
*( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
|
||
|
|
||
|
|
||
|
if ( ! *pGlobal )
|
||
|
return pBuffer;
|
||
|
|
||
|
// FLAGGED_BYTE_BLOB
|
||
|
|
||
|
ulDataSize = (ULONG) GlobalSize( *pGlobal );
|
||
|
|
||
|
*( PULONG_LV_CAST pBuffer)++ = ulDataSize;
|
||
|
|
||
|
// Handle is the non-null flag
|
||
|
|
||
|
*( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
|
||
|
*( PULONG_LV_CAST pBuffer)++ = ulDataSize;
|
||
|
|
||
|
if( ulDataSize )
|
||
|
{
|
||
|
void * pData = GlobalLock( *pGlobal);
|
||
|
memcpy( pBuffer, pData, ulDataSize );
|
||
|
GlobalUnlock( *pGlobal);
|
||
|
}
|
||
|
|
||
|
pBuffer += ulDataSize;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sending a handle.
|
||
|
// For WIN64 HGLOBALs, 64 bits may by significant (e.i. GPTR).
|
||
|
#if defined(_WIN64)
|
||
|
*( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER;
|
||
|
ALIGN( pBuffer, 7 );
|
||
|
*( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)pGlobal;
|
||
|
#else
|
||
|
*( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
|
||
|
*( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return( pBuffer );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: WdtpGlobalUnmarshal
|
||
|
//
|
||
|
// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align, size, null flag, size, data (bytes, if any)
|
||
|
//
|
||
|
// Note: Reallocation is forbidden when the hglobal is part of
|
||
|
// an [in,out] STGMEDIUM in IDataObject::GetDataHere.
|
||
|
// This affects only data passing with old handles being
|
||
|
// non null.
|
||
|
//
|
||
|
// history: May-95 Ryszardk Created.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned char __RPC_FAR * __RPC_USER
|
||
|
WdtpGlobalUnmarshal (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned char * pBuffer,
|
||
|
HGLOBAL * pGlobal,
|
||
|
BOOL fCanReallocate,
|
||
|
ULONG_PTR BufferSize )
|
||
|
{
|
||
|
unsigned long ulDataSize, fHandle, UnionDisc;
|
||
|
HGLOBAL hGlobal;
|
||
|
|
||
|
// Align the buffer and save the fixup size.
|
||
|
UCHAR* pBufferStart = pBuffer;
|
||
|
ALIGN( pBuffer, 3 );
|
||
|
ULONG_PTR cbFixup = (ULONG_PTR)(pBuffer - pBufferStart);
|
||
|
|
||
|
// Check for EOB before accessing discriminant and handle.
|
||
|
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (2 * sizeof( ULONG )) );
|
||
|
|
||
|
// Get the tag from buffer.
|
||
|
UnionDisc = *( PULONG_LV_CAST pBuffer)++;
|
||
|
|
||
|
if ( IS_DATA_MARKER( UnionDisc) )
|
||
|
{
|
||
|
// Get the marker from the buffer.
|
||
|
hGlobal = (HGLOBAL) LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
|
||
|
|
||
|
// If handle is NULL, we are done.
|
||
|
if ( ! hGlobal )
|
||
|
{
|
||
|
if ( *pGlobal )
|
||
|
GlobalFree( *pGlobal );
|
||
|
*pGlobal = NULL;
|
||
|
return pBuffer;
|
||
|
}
|
||
|
|
||
|
// Check for EOB before accessing header.
|
||
|
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (5 * sizeof( ULONG )) );
|
||
|
|
||
|
// Get the rest of the header from the buffer.
|
||
|
ulDataSize = *( PULONG_LV_CAST pBuffer)++;
|
||
|
HGLOBAL hGlobalDup = (HGLOBAL) LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
|
||
|
ULONG ulDataSizeDup = *( PULONG_LV_CAST pBuffer)++;
|
||
|
|
||
|
// Validate the header: handle and size are put on wire twice, make
|
||
|
// sure both instances of each are the same.
|
||
|
if ( (hGlobalDup != hGlobal) ||
|
||
|
(ulDataSizeDup != ulDataSize) )
|
||
|
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
|
||
|
|
||
|
if ( *pGlobal )
|
||
|
{
|
||
|
// Check for reallocation
|
||
|
|
||
|
if ( GlobalSize( *pGlobal ) == ulDataSize )
|
||
|
hGlobal = *pGlobal;
|
||
|
else
|
||
|
{
|
||
|
if ( fCanReallocate )
|
||
|
{
|
||
|
GlobalFree( *pGlobal );
|
||
|
hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( GlobalSize(*pGlobal) < ulDataSize )
|
||
|
{
|
||
|
RAISE_RPC_EXCEPTION( STG_E_MEDIUMFULL );
|
||
|
}
|
||
|
else
|
||
|
hGlobal = *pGlobal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// allocate a new block
|
||
|
|
||
|
hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
|
||
|
}
|
||
|
|
||
|
if ( hGlobal == NULL )
|
||
|
{
|
||
|
RAISE_RPC_EXCEPTION(E_OUTOFMEMORY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Check for EOB before accessing data.
|
||
|
CHECK_BUFFER_SIZE( BufferSize,
|
||
|
cbFixup + (5 * sizeof( ULONG )) + ulDataSize );
|
||
|
|
||
|
// Get the data from the buffer.
|
||
|
void * pData = GlobalLock( hGlobal);
|
||
|
memcpy( pData, pBuffer, ulDataSize );
|
||
|
pBuffer += ulDataSize;
|
||
|
GlobalUnlock( hGlobal);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sending a handle only.
|
||
|
// Reallocation problem doesn't apply to handle passing.
|
||
|
|
||
|
if ( IS_HANDLE_MARKER( UnionDisc ) )
|
||
|
{
|
||
|
hGlobal = (HGLOBAL) LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
|
||
|
}
|
||
|
else if (IS_HANDLE64_MARKER( UnionDisc ) )
|
||
|
{
|
||
|
ALIGN( pBuffer, 7 );
|
||
|
|
||
|
// Must be enough buffer to do alignment fixup.
|
||
|
CHECK_BUFFER_SIZE( BufferSize, cbFixup +
|
||
|
(ULONG_PTR) (pBuffer - pBufferStart) + sizeof( __int64 ));
|
||
|
|
||
|
hGlobal = (HGLOBAL) ( *( PHYPER_LV_CAST pBuffer)++ );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
|
||
|
}
|
||
|
|
||
|
if ( *pGlobal != hGlobal && *pGlobal )
|
||
|
GlobalFree( *pGlobal );
|
||
|
}
|
||
|
|
||
|
*pGlobal = hGlobal;
|
||
|
|
||
|
return( pBuffer );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserUnmarshall
|
||
|
//
|
||
|
// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align, size, null flag, size, data (bytes, if any)
|
||
|
//
|
||
|
// history: May-95 Ryszardk Created.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned char __RPC_FAR * __RPC_USER
|
||
|
HGLOBAL_UserUnmarshal (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned char * pBuffer,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
// Get the buffer size and the start of the buffer.
|
||
|
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
|
||
|
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
|
||
|
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
|
||
|
|
||
|
pBuffer = WdtpGlobalUnmarshal( pFlags,
|
||
|
pBufferStart,
|
||
|
pGlobal,
|
||
|
TRUE, // reallocation possible
|
||
|
BufferSize );
|
||
|
return( pBuffer );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserFree
|
||
|
//
|
||
|
// Synopsis: Free an HGLOBAL.
|
||
|
//
|
||
|
// history: May-95 Ryszardk Created.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void __RPC_USER
|
||
|
HGLOBAL_UserFree(
|
||
|
unsigned long * pFlags,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
if( pGlobal && *pGlobal )
|
||
|
{
|
||
|
if ( HGLOBAL_DATA_PASSING(*pFlags) )
|
||
|
GlobalFree( *pGlobal);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(_WIN64)
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserSize64
|
||
|
//
|
||
|
// Synopsis: Get the wire size the HGLOBAL handle and data.
|
||
|
//
|
||
|
// Derivation: Union around a pointer to a conformant struct with a
|
||
|
// flag field.
|
||
|
//
|
||
|
// history: Dec-00 JohnDoty Created from 32bit function
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned long __RPC_USER
|
||
|
HGLOBAL_UserSize64 (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned long Offset,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
if ( !pGlobal )
|
||
|
return Offset;
|
||
|
|
||
|
// userHGLOBAL: the encapsulated union.
|
||
|
// Discriminant and then handle or pointer from the union arm.
|
||
|
|
||
|
// Union discriminent is 4 bytes, but it contains a pointer, so
|
||
|
// align on union is 8 bytes.
|
||
|
LENGTH_ALIGN( Offset, 7 );
|
||
|
Offset += sizeof( long );
|
||
|
LENGTH_ALIGN( Offset, 7 );
|
||
|
|
||
|
// Handle represented by a polymorphic type - for inproc case only!
|
||
|
if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
|
||
|
{
|
||
|
// Doesn't matter which arm we take inproc, it's size of native
|
||
|
// HGLOBAL.
|
||
|
Offset += sizeof( HGLOBAL );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Pointer representation...
|
||
|
Offset += 8;
|
||
|
}
|
||
|
|
||
|
if ( ! *pGlobal )
|
||
|
return Offset;
|
||
|
|
||
|
if ( HGLOBAL_DATA_PASSING(*pFlags) )
|
||
|
{
|
||
|
// Struct must be aligned on 8, but already aligned on
|
||
|
// 8...
|
||
|
|
||
|
unsigned long ulDataSize = (ULONG) GlobalSize( *pGlobal );
|
||
|
|
||
|
Offset += 8 + 2 * sizeof(long) + ulDataSize;
|
||
|
}
|
||
|
|
||
|
return( Offset );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserMarshal64
|
||
|
//
|
||
|
// Synopsis: Marshalls an HGLOBAL object into the RPC buffer.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align, size, null flag, size, data (bytes, if any)
|
||
|
//
|
||
|
// history: Dec-00 JohnDoty Created from 32bit function
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned char __RPC_FAR * __RPC_USER
|
||
|
HGLOBAL_UserMarshal64 (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned char * pBuffer,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
if ( !pGlobal )
|
||
|
return pBuffer;
|
||
|
|
||
|
// We marshal a null handle, too.
|
||
|
|
||
|
UserNdrDebugOut((UNDR_OUT4, "HGLOBAL_UserMarshal\n"));
|
||
|
|
||
|
ALIGN( pBuffer, 7 );
|
||
|
|
||
|
// Discriminant of the encapsulated union and union arm.
|
||
|
if ( HGLOBAL_DATA_PASSING(*pFlags) )
|
||
|
{
|
||
|
unsigned long ulDataSize;
|
||
|
|
||
|
// userHGLOBAL
|
||
|
*( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
|
||
|
ALIGN( pBuffer, 7 );
|
||
|
*( PHYPER_LV_CAST pBuffer)++ = (hyper)*pGlobal;
|
||
|
|
||
|
if ( ! *pGlobal )
|
||
|
return pBuffer;
|
||
|
|
||
|
// FLAGGED_BYTE_BLOB
|
||
|
ulDataSize = (ULONG) GlobalSize( *pGlobal );
|
||
|
|
||
|
*( PHYPER_LV_CAST pBuffer)++ = ulDataSize;
|
||
|
|
||
|
// Handle is the non-null flag
|
||
|
*( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
|
||
|
*( PULONG_LV_CAST pBuffer)++ = ulDataSize;
|
||
|
|
||
|
if( ulDataSize )
|
||
|
{
|
||
|
void * pData = GlobalLock( *pGlobal);
|
||
|
memcpy( pBuffer, pData, ulDataSize );
|
||
|
GlobalUnlock( *pGlobal);
|
||
|
}
|
||
|
|
||
|
pBuffer += ulDataSize;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sending a handle.
|
||
|
// For WIN64 HGLOBALs, 64 bits may by significant (e.i. GPTR).
|
||
|
*( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER;
|
||
|
ALIGN( pBuffer, 7 );
|
||
|
*( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)pGlobal;
|
||
|
}
|
||
|
|
||
|
return( pBuffer );
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: WdtpGlobalUnmarshal64
|
||
|
//
|
||
|
// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align, size, null flag, size, data (bytes, if any)
|
||
|
//
|
||
|
// Note: Reallocation is forbidden when the hglobal is part of
|
||
|
// an [in,out] STGMEDIUM in IDataObject::GetDataHere.
|
||
|
// This affects only data passing with old handles being
|
||
|
// non null.
|
||
|
//
|
||
|
// history: Dec-00 JohnDoty Created from 32bit function
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned char __RPC_FAR * __RPC_USER
|
||
|
WdtpGlobalUnmarshal64 (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned char * pBuffer,
|
||
|
HGLOBAL * pGlobal,
|
||
|
BOOL fCanReallocate,
|
||
|
ULONG_PTR BufferSize )
|
||
|
{
|
||
|
CarefulBufferReader stream(pBuffer, BufferSize);
|
||
|
unsigned long ulDataSize, fHandle, UnionDisc;
|
||
|
HGLOBAL hGlobal;
|
||
|
|
||
|
// Align the buffer and save the fixup size.
|
||
|
stream.Align(8);
|
||
|
|
||
|
// Get the tag from buffer.
|
||
|
UnionDisc = stream.ReadULONGNA();
|
||
|
|
||
|
// Get the marker from the buffer.
|
||
|
hGlobal = (HGLOBAL)stream.ReadHYPER();
|
||
|
|
||
|
if ( IS_DATA_MARKER(UnionDisc) )
|
||
|
{
|
||
|
// If the handle was NULL, return out now.
|
||
|
if (!hGlobal)
|
||
|
{
|
||
|
if (*pGlobal)
|
||
|
GlobalFree(*pGlobal);
|
||
|
*pGlobal = NULL;
|
||
|
return stream.GetBuffer();
|
||
|
}
|
||
|
|
||
|
// Get the rest of the header from the buffer.
|
||
|
ulDataSize = (ULONG)stream.ReadHYPERNA();
|
||
|
LONG hGlobalDup = stream.ReadLONGNA();
|
||
|
ULONG ulDataSizeDup = stream.ReadULONGNA();
|
||
|
|
||
|
// Validate the header: handle and size are put on wire twice, make
|
||
|
// sure both instances of each are the same.
|
||
|
if ( (hGlobalDup != HandleToLong(hGlobal)) ||
|
||
|
(ulDataSizeDup != ulDataSize) )
|
||
|
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
|
||
|
|
||
|
if ( *pGlobal )
|
||
|
{
|
||
|
// Check for reallocation
|
||
|
if ( GlobalSize( *pGlobal ) == ulDataSize )
|
||
|
hGlobal = *pGlobal;
|
||
|
else
|
||
|
{
|
||
|
if ( fCanReallocate )
|
||
|
{
|
||
|
GlobalFree( *pGlobal );
|
||
|
hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( GlobalSize(*pGlobal) < ulDataSize )
|
||
|
{
|
||
|
RAISE_RPC_EXCEPTION( STG_E_MEDIUMFULL );
|
||
|
}
|
||
|
else
|
||
|
hGlobal = *pGlobal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// allocate a new block
|
||
|
hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
|
||
|
}
|
||
|
|
||
|
if ( hGlobal == NULL )
|
||
|
{
|
||
|
RAISE_RPC_EXCEPTION(E_OUTOFMEMORY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Check for EOB before accessing data.
|
||
|
stream.CheckSize(ulDataSize);
|
||
|
|
||
|
// Get the data from the buffer.
|
||
|
void * pData = GlobalLock( hGlobal);
|
||
|
memcpy( pData, stream.GetBuffer(), ulDataSize );
|
||
|
GlobalUnlock( hGlobal);
|
||
|
|
||
|
stream.Advance(ulDataSize);
|
||
|
}
|
||
|
}
|
||
|
else if (IS_HANDLE64_MARKER( UnionDisc ))
|
||
|
{
|
||
|
// Make sure the old stuff is cleaned up...
|
||
|
if ( *pGlobal != hGlobal && *pGlobal )
|
||
|
GlobalFree( *pGlobal );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
|
||
|
}
|
||
|
|
||
|
*pGlobal = hGlobal;
|
||
|
|
||
|
return( stream.GetBuffer() );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserUnmarshal64
|
||
|
//
|
||
|
// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
|
||
|
//
|
||
|
// Derivation: Conformant struct with a flag field:
|
||
|
// align, size, null flag, size, data (bytes, if any)
|
||
|
//
|
||
|
// history: Dec-00 JohnDoty Created from 32bit function
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
unsigned char __RPC_FAR * __RPC_USER
|
||
|
HGLOBAL_UserUnmarshal64 (
|
||
|
unsigned long * pFlags,
|
||
|
unsigned char * pBuffer,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
// Get the buffer size and the start of the buffer.
|
||
|
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
|
||
|
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
|
||
|
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
|
||
|
|
||
|
pBuffer = WdtpGlobalUnmarshal64( pFlags,
|
||
|
pBufferStart,
|
||
|
pGlobal,
|
||
|
TRUE, // reallocation possible
|
||
|
BufferSize );
|
||
|
return( pBuffer );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: HGLOBAL_UserFree64
|
||
|
//
|
||
|
// Synopsis: Free an HGLOBAL.
|
||
|
//
|
||
|
// history: Dec-00 JohnDoty Created from 32bit function
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void __RPC_USER
|
||
|
HGLOBAL_UserFree64 (
|
||
|
unsigned long * pFlags,
|
||
|
HGLOBAL * pGlobal)
|
||
|
{
|
||
|
if( pGlobal && *pGlobal )
|
||
|
{
|
||
|
if ( HGLOBAL_DATA_PASSING(*pFlags) )
|
||
|
GlobalFree( *pGlobal);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|