windows-nt/Source/XPSP1/NT/com/ole32/oleprx32/proxy/transmit.cxx
2020-09-26 16:20:57 +08:00

1867 lines
51 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: transmit.cxx
//
// Contents: Support for Windows/OLE data types for oleprx32.dll.
// Used to be transmit_as routines, now user_marshal routines.
//
// Functions:
// HBRUSH_UserSize
// HBRUSH_UserMarshal
// HBRUSH_UserUnmarshal
// HBRUSH_UserFree
// HACCEL_UserSize
// HACCEL_UserMarshal
// HACCEL_UserUnmarshal
// HACCEL_UserFree
// HWND_UserSize
// HWND_UserMarshal
// HWND_UserUnmarshal
// HWND_UserFree
// HMENU_UserSize
// HMENU_UserMarshal
// HMENU_UserUnmarshal
// HMENU_UserFree
// HICON_User*
// HDC_UserSize
// HDC_UserMarshal
// HDC_UserUnmarshal
// HDC_UserFree
//
// History: 24-Aug-93 ShannonC Created
// 24-Nov-93 ShannonC Added HGLOBAL
// 14-May-94 DavePl Added HENHMETAFILE
// 18-May-94 ShannonC Added HACCEL, UINT, WPARAM
// 19-May-94 DavePl Added HENHMETAFILE to STGMEDIUM code
// May-95 Ryszardk Wrote all the _User* routines
// Feb-96 Ryszardk Added CLIPFORMAT support
// 25-Jun-99 a-olegi Added HDC code
// 14-Dec-00 JohnDoty Because the size of the code nearly
// doubled for NDR64, factored out the
// involved routines to seperate files.
// see:
// clipformat.cxx
// bitmap.cxx
// hpalette.cxx
// metafile.cxx
// snb.cxx
// hglobal.cxx
// stgmedium.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>
WINOLEAPI_(void) ReleaseStgMedium(LPSTGMEDIUM pStgMed);
#pragma code_seg(".orpc")
EXTERN_C const CLSID CLSID_MyPSFactoryBuffer = {0x6f11fe5c,0x2fc5,0x101b,{0x9e,0x45,0x00,0x00,0x0b,0x65,0xc7,0xef}};
// Used to detect if the channel is a CRpcChannelBuffer object
extern const IID IID_CPPRpcChannelBuffer;
class CRpcChannelBuffer;
extern HRESULT GetIIDFromObjRef(OBJREF &objref, IID **piid);
// These methods are needed as the object is used for interface marshaling.
/***************************************************************************/
STDMETHODIMP_(ULONG) CStreamOnMessage::AddRef( THIS )
{
return ref_count += 1;
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Clone(THIS_ IStream * *ppstm)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Commit(THIS_ DWORD grfCommitFlags)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::CopyTo(THIS_ IStream *pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER *pcbRead,
ULARGE_INTEGER *pcbWritten)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
CStreamOnMessage::CStreamOnMessage(unsigned char **ppMessageBuffer)
: ref_count(1), ppBuffer(ppMessageBuffer), cbMaxStreamLength(0xFFFFFFFF)
{
pStartOfStream = *ppMessageBuffer;
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::LockRegion(THIS_ ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown))
{
*ppvObj = (IUnknown *) this;
ref_count += 1;
return ResultFromScode(S_OK);
}
else if (IsEqualIID(riid, IID_IStream))
{
*ppvObj = (IStream *) this;
ref_count += 1;
return ResultFromScode(S_OK);
}
else
return ResultFromScode(E_NOINTERFACE);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Read(THIS_ VOID HUGEP *pv,
ULONG cb, ULONG *pcbRead)
{
memcpy( pv, *ppBuffer, cb );
*ppBuffer += cb;
if (pcbRead != NULL)
*pcbRead = cb;
return ResultFromScode(S_OK);
}
/***************************************************************************/
STDMETHODIMP_(ULONG) CStreamOnMessage::Release( THIS )
{
ref_count -= 1;
if (ref_count == 0)
{
delete this;
return 0;
}
else
return ref_count;
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Revert(THIS)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Seek(THIS_ LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER *plibNewPosition)
{
ULONG pos;
// Verify that the offset isn't out of range.
if (dlibMove.HighPart != 0)
return ResultFromScode( E_FAIL );
// Determine the new seek pointer.
switch (dwOrigin)
{
case STREAM_SEEK_SET:
pos = dlibMove.LowPart;
break;
case STREAM_SEEK_CUR:
/* Must use signed math here. */
pos = (ULONG) (*ppBuffer - pStartOfStream);
if ((long) dlibMove.LowPart < 0 &&
pos < (unsigned long) - (long) dlibMove.LowPart)
return ResultFromScode( E_FAIL );
pos += (long) dlibMove.LowPart;
break;
case STREAM_SEEK_END:
return ResultFromScode(E_NOTIMPL);
break;
default:
return ResultFromScode( E_FAIL );
}
// Set the seek pointer.
*ppBuffer = pStartOfStream + pos;
if (plibNewPosition != NULL)
{
plibNewPosition->LowPart = pos;
plibNewPosition->HighPart = 0;
}
return ResultFromScode(S_OK);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::SetSize(THIS_ ULARGE_INTEGER libNewSize)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Stat(THIS_ STATSTG *pstatstg, DWORD grfStatFlag)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::UnlockRegion(THIS_ ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
return ResultFromScode(E_NOTIMPL);
}
/***************************************************************************/
STDMETHODIMP CStreamOnMessage::Write(THIS_ VOID const HUGEP *pv,
ULONG cb,
ULONG *pcbWritten)
{
// Write the data.
memcpy( *ppBuffer, pv, cb );
if (pcbWritten != NULL)
*pcbWritten = cb;
*ppBuffer += cb;
return ResultFromScode(S_OK);
}
// #########################################################################
//
// WdtpRemotableHandle helper
//
// #########################################################################
//+-------------------------------------------------------------------------
//
// Function: WdtpRemotableHandle_UserSize
//
// Synopsis: Sizes a void star handle as a union with a long.
// Handle size may be 8 bytes but on wire it is still a long.
//
// history: Dec-95 Ryszardk Created.
// Dec-98 Ryszardk Ported to 64b.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
WdtpRemotableHandle_UserSize (
unsigned long * pFlags,
unsigned long Offset,
LONG_PTR * pHandle )
{
if ( !pHandle )
return Offset;
if ( *pHandle && DIFFERENT_MACHINE_CALL(*pFlags) )
RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
LENGTH_ALIGN( Offset, 3 );
// 4 bytes for discriminator, 4 bytes for the long.
return( Offset + 8 ) ;
}
//+-------------------------------------------------------------------------
//
// Function: WdtpRemotableHandle_UserMarshall
//
// Synopsis: Marshalls a handle as a union with a long.
// We represent a GDI or USER handle, which may be 4 or 8 bytes,
// as a long on wire.
//
// history: Dec-95 Ryszardk Created.
// Dec-98 Ryszardk Ported to 64b.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
WdtpRemotableHandle_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
LONG_PTR * pHandle )
{
if ( !pHandle )
return pBuffer;
if ( *pHandle && DIFFERENT_MACHINE_CALL(*pFlags) )
RpcRaiseException( RPC_S_INVALID_TAG );
ALIGN( pBuffer, 3 );
*( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
*( PLONG_LV_CAST pBuffer)++ = (long)*pHandle;
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpRemotableHandle_UserUnmarshall
//
// Synopsis: Unmarshalls a remotable void star as union with ulong.
// Handle is represented as a long on wire.
// On 64b platforms, we sign extended it to 8 bytes to get
// the proper USER or GDI handle representation.
//
// history: Dec-95 Ryszardk Created.
// Dec-98 Ryszardk Ported to 64b.
// Aug-99 JohnStra Added consistency checks.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
WdtpRemotableHandle_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
LONG_PTR * pHandle )
{
unsigned long HandleMarker;
// Get the buffer size and the start of the buffer.
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
// Align the buffer and save fixup size.
ALIGN( pBuffer, 3 );
ULONG_PTR cbFixup = (ULONG_PTR)(pBuffer - pBufferStart);
// Check for EOB before accessing data.
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (2 * sizeof( ULONG )) );
HandleMarker = *( PULONG_LV_CAST pBuffer)++;
if ( HandleMarker == WDT_HANDLE_MARKER )
*pHandle = *( PLONG_LV_CAST pBuffer)++;
else
RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpRemotableHandle_UserFree
//
//--------------------------------------------------------------------------
void __RPC_USER
WdtpRemotableHandle_UserFree(
unsigned long * pFlags,
LONG_PTR * pHandle )
{
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserSize
//
// Synopsis: Sizes an HWND handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HWND_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HWND * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserMarshall
//
// Synopsis: Marshalls an HWND handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HWND_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HWND * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserUnmarshall
//
// Synopsis: Unmarshalls an HWND handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HWND_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HWND * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserFree
//
// Synopsis: Shouldn't be called.
//
//--------------------------------------------------------------------------
void __RPC_USER
HWND_UserFree(
unsigned long * pFlags,
HWND * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserSize
//
// Synopsis: Sizes an HMENU handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HMENU_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HMENU * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserMarshall
//
// Synopsis: Marshalls an HMENU handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HMENU_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HMENU * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserUnmarshall
//
// Synopsis: Unmarshalls an HMENU handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HMENU_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HMENU * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserFree
//
// Synopsis: Free an HMENU.
//
//--------------------------------------------------------------------------
void __RPC_USER
HMENU_UserFree(
unsigned long * pFlags,
HMENU * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserSize
//
// Synopsis: Sizes an HACCEL handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HACCEL_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HACCEL * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserMarshall
//
// Synopsis: Marshalls an HACCEL handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HACCEL_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HACCEL * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserUnmarshall
//
// Synopsis: Unmarshalls an HACCEL handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HACCEL_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HACCEL * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserFree
//
// Synopsis: Free an HACCEL.
//
//--------------------------------------------------------------------------
void __RPC_USER
HACCEL_UserFree(
unsigned long * pFlags,
HACCEL * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserSize
//
// Synopsis: Sizes an HBRUSH handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HBRUSH_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HBRUSH * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserMarshall
//
// Synopsis: Marshalls an HBRUSH handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBRUSH_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HBRUSH * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserUnmarshall
//
// Synopsis: Unmarshalls an HBRUSH handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBRUSH_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HBRUSH * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserFree
//
// Synopsis: Free an HBRUSH.
//
//--------------------------------------------------------------------------
void __RPC_USER
HBRUSH_UserFree(
unsigned long * pFlags,
HBRUSH * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserSize
//
// Synopsis: Sizes an HICON handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HICON_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HICON * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserMarshall
//
// Synopsis: Marshalls an HICON handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HICON_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HICON * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserUnmarshall
//
// Synopsis: Unmarshalls an HICON handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HICON_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HICON * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserFree
//
// Synopsis: Free an HICON.
//
//--------------------------------------------------------------------------
void __RPC_USER
HICON_UserFree(
unsigned long * pFlags,
HICON * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserSize
//
// Synopsis: Sizes an HDC handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HDC_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HDC * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserMarshall
//
// Synopsis: Marshalls an HICON handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HDC_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HDC * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserUnmarshall
//
// Synopsis: Unmarshalls an HICON handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HDC_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HDC * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserFree
//
// Synopsis: Free an HDC.
//
//--------------------------------------------------------------------------
void __RPC_USER
HDC_UserFree(
unsigned long * pFlags,
HDC * pH )
{
}
// #########################################################################
//
// Interface pointers.
//
// #########################################################################
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserSize
//
// Synopsis: Get the wire size for an interface pointer.
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
EXTERN_C unsigned long __RPC_USER __stdcall
WdtpInterfacePointer_UserSize (
USER_MARSHAL_CB * pContext,
unsigned long Flags,
unsigned long Offset,
IUnknown * pIf,
const IID & IId )
{
if ( pIf )
{
LENGTH_ALIGN( Offset, 3 );
//Leave space for array bounds and length
Offset += 2 * sizeof(long);
HRESULT hr;
unsigned long cbSize = 0;
hr = CoGetMarshalSizeMax( &cbSize,
IId,
pIf,
USER_CALL_CTXT_MASK( Flags ),
pContext->pStubMsg->pvDestContext,
MSHLFLAGS_NORMAL );
if ( FAILED(hr) )
RAISE_RPC_EXCEPTION( hr );
Offset += cbSize;
}
return( Offset ) ;
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserMarshal
//
// Synopsis: Marshalls an interface pointer.
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
EXTERN_C unsigned char __RPC_FAR * __RPC_USER __stdcall
WdtpInterfacePointer_UserMarshal (
USER_MARSHAL_CB * pContext,
unsigned long Flags,
unsigned char * pBuffer,
IUnknown * pIf,
const IID & IId )
{
unsigned long * pMaxCount, *pSize;
unsigned long cbData = 0;
UserNdrDebugOut((UNDR_OUT1, "WdtpInterface_PointerMarshal\n"));
if ( pIf )
{
// Always marshaled because of the apartment model.
CStreamOnMessage MemStream( (unsigned char **) &pBuffer );
ALIGN( pBuffer, 3 );
pMaxCount = (unsigned long *) pBuffer;
pBuffer += 4;
// Leave space for length
pSize = (unsigned long *) pBuffer;
pBuffer += 4;
HRESULT hr;
unsigned char * pBufferMark = pBuffer;
hr = CoMarshalInterface( &MemStream,
IId,
pIf,
USER_CALL_CTXT_MASK( Flags ),
pContext->pStubMsg->pvDestContext,
MSHLFLAGS_NORMAL );
if( FAILED(hr) )
{
RpcRaiseException(hr);
}
// Calculate the size of the data written
DWORD cbData = (ULONG) (pBuffer - pBufferMark);
// Update the array bounds.
*pMaxCount = cbData;
*pSize = cbData;
}
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserUnmarshalWorker
//
// Synopsis: Unmarshalls an interface pointer from the RPC buffer.
//
// history: Aug-99 JohnStra Created.
// Oct-00 ScottRob/
// YongQu NDR64 Support.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
WdtpInterfacePointer_UserUnmarshalWorker (
USER_MARSHAL_CB * pContext,
unsigned char * pBuffer,
IUnknown ** ppIf,
const IID & IId,
ULONG_PTR BufferSize,
BOOL fNDR64 )
{
unsigned long *pMaxCount, *pSize;
unsigned long cbData = 0;
// Align the buffer and save the fixup size.
UCHAR* pBufferStart = pBuffer;
if (fNDR64) ALIGN(pBuffer, 7); else ALIGN( pBuffer, 3 );
ULONG_PTR cbFixup = (ULONG_PTR)(pBuffer - pBufferStart);
// Check for EOB before accessing data.
int cbHeader = (int)((fNDR64) ? 3*sizeof( ULONG ) : 2*sizeof( ULONG ));
CHECK_BUFFER_SIZE( BufferSize, cbFixup + cbHeader + 2*sizeof( ULONG ) + sizeof( GUID ) );
UserNdrDebugOut((UNDR_OUT1, "WdtpInterfacePointerUnmarshal\n"));
pMaxCount = (unsigned long *) pBuffer;
pBuffer += sizeof(long);
if (fNDR64) pBuffer += sizeof(long); //NDR64 Padding
//Unmarshal count
pSize = (unsigned long *) pBuffer;
pBuffer += sizeof(long);
// max count and unmarshal count must be the same.
if ( *pSize != *pMaxCount )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Get IID from the OBJREF and verify that it matches the supplied IID.
IID* piid;
if( FAILED( GetIIDFromObjRef( *(OBJREF *)pBuffer, &piid ) ) )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
if( 0 != memcmp( &IId, piid, sizeof(IID) ) )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Check for EOB before unmarshaling.
CHECK_BUFFER_SIZE( BufferSize, cbFixup + cbHeader + *pSize );
// Release the old pointer after unmarshalling the new one
// to prevent object from getting released too early.
// Then release the old one only when successful.
IUnknown * punkTemp = 0;
//CodeReview: The original code
// CNdrStream MemStream( pBuffer,
// (ULONG) BufferSize + (2 * sizeof(ULONG)) + *pSize );
// Doesn't look right... We just verified that BufferSize was large enough to
// hold the data. Then we tell the CNdrStream that the size of buffer is double
// that size when we should be only unmarshaling pSize bytes.
// Is this to prevent CoUnmarshalInterface from running up against the end of a corrupted stream?
// Use a CNdrStream for unmarshaling because it checks for buffer overruns.
CNdrStream MemStream( pBuffer,
(ULONG) *pSize );
HRESULT hr = CoUnmarshalInterface( &MemStream,
IId,
(void **) &punkTemp );
if(FAILED(hr))
{
RAISE_RPC_EXCEPTION(hr);
}
else
{
// Get the number of bytes read from the stream.
LARGE_INTEGER lOffset = { 0, 0 };
ULARGE_INTEGER ulCurPos;
hr = MemStream.Seek( lOffset, STREAM_SEEK_CUR, &ulCurPos );
if ( FAILED(hr) )
RAISE_RPC_EXCEPTION( hr );
// Make sure the number of bytes read is what we expected.
if ( ulCurPos.LowPart != *pSize )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Increment pBuffer pointer by the amount we unmarshaled from it.
pBuffer += ulCurPos.LowPart;
// On the client side, release the [in,out] interface pointer.
// The pointer may be different from NULL only on the client side.
// release the old one, keep the new one.
if ( *ppIf )
(*ppIf)->Release();
*ppIf = punkTemp;
}
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserUnmarshal
//
// Synopsis: Unmarshalls an interface pointer from the RPC buffer.
//
// history: May-95 Ryszardk Created.
// Aug-99 JohnStra Factored bulk of work out into
// worker routine in order to add
// consistency checks.
//
//--------------------------------------------------------------------------
EXTERN_C unsigned char __RPC_FAR * __RPC_USER __stdcall
WdtpInterfacePointer_UserUnmarshal (
USER_MARSHAL_CB * pContext,
unsigned char * pBuffer,
IUnknown ** ppIf,
const IID & IId )
{
// Get the buffer size and the start of the buffer.
CUserMarshalInfo MarshalInfo( (ULONG*)pContext, pBuffer );
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
// Delegate to worker routine.
pBuffer = WdtpInterfacePointer_UserUnmarshalWorker( pContext,
pBufferStart,
ppIf,
IId,
BufferSize,
FALSE );
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserFree
//
// Synopsis: Releases an interface pointer.
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER __stdcall
WdtpInterfacePointer_UserFree(
IUnknown * pIf )
{
UserNdrDebugOut((UNDR_OUT1, "WdtpInterfacePointer_UserFree\n"));
if( pIf )
{
pIf->Release();
}
}
#if (DBG==1)
//+-------------------------------------------------------------------------
//
// Function: WdtpGetStgmedName
//
// Synopsis: Debug support
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
char *
WdtpGetStgmedName( STGMEDIUM * pStgmed)
{
char * Name;
if ( pStgmed )
{
switch (pStgmed->tymed)
{
case TYMED_NULL:
Name = "TYMED_NULL";
break;
case TYMED_MFPICT:
Name = "TYMED_MFPICT";
break;
case TYMED_ENHMF:
Name = "TYMED_ENHMF";
break;
case TYMED_GDI:
Name = "TYMED_GDI";
break;
case TYMED_HGLOBAL:
Name = "TYMED_HGLOBAL";
break;
case TYMED_FILE:
Name = "TYMED_FILE";
break;
case TYMED_ISTREAM:
Name = "TYMED_ISTREAM";
break;
case TYMED_ISTORAGE:
Name = "TYMED_ISTORAGE";
break;
default:
Name = "TYMED invalid";
break;
}
return Name;
}
else
return "STGMED * is null";
}
#endif
//+-------------------------------------------------------------------------
//
// Class: CContinue
//
// Synopsis: Notification object
//
//--------------------------------------------------------------------------
class CContinue : public IContinue
{
private:
long _cRef;
BOOL (__stdcall *_pfnContinue)(LONG_PTR);
LONG_PTR _dwContinue;
~CContinue(void);
public:
CContinue(BOOL (__stdcall *pfnContinue)(LONG_PTR dwContinue), LONG_PTR dwContinue);
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void **);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE FContinue();
};
//+-------------------------------------------------------------------------
//
// Method: CContinue::CContinue, public
//
// Synopsis: Constructor for CContinue
//
//--------------------------------------------------------------------------
CContinue::CContinue(BOOL (__stdcall *pfnContinue)(LONG_PTR dwContinue), LONG_PTR dwContinue)
: _cRef(1), _pfnContinue(pfnContinue), _dwContinue(dwContinue)
{
}
CContinue::~CContinue()
{
}
//+-------------------------------------------------------------------------
//
// Method: CContinue::QueryInterface, public
//
// Synopsis: Query for an interface on the notification object.
//
//--------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE
CContinue::QueryInterface (
REFIID iid,
void **ppv )
{
HRESULT hr = E_NOINTERFACE;
if ((IID_IUnknown == iid) || (IID_IContinue == iid))
{
this->AddRef();
*ppv = (IContinue *) this;
hr = S_OK;
}
else
{
*ppv = 0;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Method: CContinue::AddRef, public
//
// Synopsis: Increment the reference count.
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE
CContinue::AddRef()
{
InterlockedIncrement((long *) &_cRef);
return (unsigned long) _cRef;
}
//+-------------------------------------------------------------------------
//
// Method: CContinue::Release, public
//
// Synopsis: Decrement the reference count.
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE
CContinue::Release()
{
unsigned long count = _cRef - 1;
if(0 == InterlockedDecrement((long *)&_cRef))
{
count = 0;
delete this;
}
return count;
}
//+-------------------------------------------------------------------------
//
// Method: CContinue::FContinue, public
//
// Synopsis: Calls the callback function.
//
//--------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE
CContinue::FContinue()
{
HRESULT hr;
BOOL bResult;
bResult = (*_pfnContinue) (_dwContinue);
if(bResult == FALSE)
{
hr = S_FALSE;
}
else
{
hr = S_OK;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: CreateCallback
//
// Synopsis: Create a callback notification object .
//
//--------------------------------------------------------------------------
extern "C" HRESULT CreateCallback(
BOOL (__stdcall *pfnContinue)(LONG_PTR dwContinue),
LONG_PTR dwContinue,
IContinue **ppContinue)
{
HRESULT hr;
if(pfnContinue != 0)
{
CContinue *pContinue = new CContinue(pfnContinue, dwContinue);
*ppContinue = (IContinue *) pContinue;
if(pContinue != 0)
{
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_INVALIDARG;
*ppContinue = 0;
}
return hr;
}
////// NDR64 funcs
#ifdef _WIN64
//+-------------------------------------------------------------------------
//
// Function: HWND_UserSize
//
// Synopsis: Sizes an HWND handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HWND_UserSize64 (
unsigned long * pFlags,
unsigned long Offset,
HWND * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserMarshall
//
// Synopsis: Marshalls an HWND handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HWND_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HWND * pH )
{
return HWND_UserMarshal( pFlags, pBuffer, pH );
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserUnmarshall
//
// Synopsis: Unmarshalls an HWND handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HWND_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HWND * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HWND_UserFree
//
// Synopsis: Shouldn't be called.
//
//--------------------------------------------------------------------------
void __RPC_USER
HWND_UserFree64(
unsigned long * pFlags,
HWND * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserSize
//
// Synopsis: Sizes an HMENU handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HMENU_UserSize64(
unsigned long * pFlags,
unsigned long Offset,
HMENU * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserMarshall
//
// Synopsis: Marshalls an HMENU handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HMENU_UserMarshal64(
unsigned long * pFlags,
unsigned char * pBuffer,
HMENU * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserUnmarshall
//
// Synopsis: Unmarshalls an HMENU handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HMENU_UserUnmarshal64(
unsigned long * pFlags,
unsigned char * pBuffer,
HMENU * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_UserFree
//
// Synopsis: Free an HMENU.
//
//--------------------------------------------------------------------------
void __RPC_USER
HMENU_UserFree64(
unsigned long * pFlags,
HMENU * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserSize
//
// Synopsis: Sizes an HACCEL handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HACCEL_UserSize64 (
unsigned long * pFlags,
unsigned long Offset,
HACCEL * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserMarshall
//
// Synopsis: Marshalls an HACCEL handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HACCEL_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HACCEL * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserUnmarshall
//
// Synopsis: Unmarshalls an HACCEL handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HACCEL_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HACCEL * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_UserFree
//
// Synopsis: Free an HACCEL.
//
//--------------------------------------------------------------------------
void __RPC_USER
HACCEL_UserFree64(
unsigned long * pFlags,
HACCEL * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserSize
//
// Synopsis: Sizes an HBRUSH handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HBRUSH_UserSize64(
unsigned long * pFlags,
unsigned long Offset,
HBRUSH * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserMarshall
//
// Synopsis: Marshalls an HBRUSH handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBRUSH_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HBRUSH * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserUnmarshall
//
// Synopsis: Unmarshalls an HBRUSH handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBRUSH_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HBRUSH * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserFree
//
// Synopsis: Free an HBRUSH.
//
//--------------------------------------------------------------------------
void __RPC_USER
HBRUSH_UserFree64(
unsigned long * pFlags,
HBRUSH * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserSize
//
// Synopsis: Sizes an HICON handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HICON_UserSize64 (
unsigned long * pFlags,
unsigned long Offset,
HICON * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserMarshall
//
// Synopsis: Marshalls an HICON handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HICON_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HICON * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserUnmarshall
//
// Synopsis: Unmarshalls an HICON handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HICON_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HICON * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HICON_UserFree
//
// Synopsis: Free an HICON.
//
//--------------------------------------------------------------------------
void __RPC_USER
HICON_UserFree64(
unsigned long * pFlags,
HICON * pH )
{
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserSize
//
// Synopsis: Sizes an HDC handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HDC_UserSize64 (
unsigned long * pFlags,
unsigned long Offset,
HDC * pH )
{
return WdtpRemotableHandle_UserSize( pFlags, Offset, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserMarshall
//
// Synopsis: Marshalls an HICON handle into the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HDC_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HDC * pH )
{
return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserUnmarshall
//
// Synopsis: Unmarshalls an HICON handle from the RPC buffer.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HDC_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HDC * pH )
{
return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (LONG_PTR*)pH );
}
//+-------------------------------------------------------------------------
//
// Function: HDC_UserFree
//
// Synopsis: Free an HDC.
//
//--------------------------------------------------------------------------
void __RPC_USER
HDC_UserFree64(
unsigned long * pFlags,
HDC * pH )
{
}
// #########################################################################
//
// Interface pointers.
//
// #########################################################################
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserSize64
//
// Synopsis: Get the wire size for an interface pointer.
//
// history: Oct-00 ScottRob/
// YongQu Created for NDR64 Support
//
//--------------------------------------------------------------------------
EXTERN_C unsigned long __RPC_USER __stdcall
WdtpInterfacePointer_UserSize64 (
USER_MARSHAL_CB * pContext,
unsigned long Flags,
unsigned long Offset,
IUnknown * pIf,
const IID & IId )
{
if ( pIf )
{
LENGTH_ALIGN( Offset, 7 );
//Leave space for array bounds, padding, and length
Offset += 3 * sizeof(long);
HRESULT hr;
unsigned long cbSize = 0;
hr = CoGetMarshalSizeMax( &cbSize,
IId,
pIf,
USER_CALL_CTXT_MASK( Flags ),
pContext->pStubMsg->pvDestContext,
MSHLFLAGS_NORMAL );
if ( FAILED(hr) )
RAISE_RPC_EXCEPTION( hr );
Offset += cbSize;
}
return( Offset ) ;
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserMarshal64
//
// Synopsis: Marshalls an interface pointer.
//
// history: Oct-2000 ScottRob/YongQu Created for NDR64.
//
//--------------------------------------------------------------------------
EXTERN_C unsigned char __RPC_FAR * __RPC_USER __stdcall
WdtpInterfacePointer_UserMarshal64 (
USER_MARSHAL_CB * pContext,
unsigned long Flags,
unsigned char * pBuffer,
IUnknown * pIf,
const IID & IId )
{
unsigned long * pMaxCount, *pSize;
unsigned long cbData = 0;
UserNdrDebugOut((UNDR_OUT1, "WdtpInterface_PointerMarshal64\n"));
if ( pIf )
{
// Always marshaled because of the apartment model.
CStreamOnMessage MemStream( (unsigned char **) &pBuffer );
ALIGN( pBuffer, 7 ); // need to align to 8
pMaxCount = (unsigned long *) pBuffer;
pBuffer += 2 * sizeof( long ); // conformant size is 8
// Leave space for length
pSize = (unsigned long *) pBuffer;
pBuffer += sizeof( long );
HRESULT hr;
unsigned char * pBufferMark = pBuffer;
hr = CoMarshalInterface( &MemStream,
IId,
pIf,
USER_CALL_CTXT_MASK( Flags ),
pContext->pStubMsg->pvDestContext,
MSHLFLAGS_NORMAL );
if ( FAILED(hr) )
{
RpcRaiseException(hr);
}
// Calculate the size of the data written
DWORD cbData = (ULONG) (pBuffer - pBufferMark);
// Update the array bounds.
*pMaxCount = cbData;
*pSize = cbData;
}
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserUnmarshal64
//
// Synopsis: Unmarshalls an interface pointer from the RPC buffer.
//
// history: Oct-00 ScottRob/
// YongQu Created for NDR64.
//
//--------------------------------------------------------------------------
EXTERN_C unsigned char __RPC_FAR * __RPC_USER __stdcall
WdtpInterfacePointer_UserUnmarshal64 (
USER_MARSHAL_CB * pContext,
unsigned char * pBuffer,
IUnknown ** ppIf,
const IID & IId )
{
// Get the buffer size and the start of the buffer.
CUserMarshalInfo MarshalInfo( (ULONG*)pContext, pBuffer );
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
// Delegate to worker routine.
pBuffer = WdtpInterfacePointer_UserUnmarshalWorker( pContext,
pBufferStart,
ppIf,
IId,
BufferSize,
TRUE );
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: WdtpInterfacePointer_UserFree64
//
// Synopsis: Frees the unmarshaled interface
//
// history: Oct-2000 ScottRob/YongQu Created for NDR64.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER __stdcall
WdtpInterfacePointer_UserFree64(
IUnknown * pIf )
{
WdtpInterfacePointer_UserFree(pIf);
}
#endif // _WIN64