//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000. // // File: metafile.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 HMETAFILEPICT, HENHMETAFILE, and // HMETAFILE. // // Functions: // HMETAFILEPICT_UserSize // HMETAFILEPICT_UserMarshal // HMETAFILEPICT_UserUnmarshal // HMETAFILEPICT_UserFree // HMETAFILEPICT_UserSize64 // HMETAFILEPICT_UserMarshal64 // HMETAFILEPICT_UserUnmarshal64 // HMETAFILEPICT_UserFree64 // HENHMETAFILE_UserSize // HENHMETAFILE_UserMarshal // HENHMETAFILE_UserUnmarshal // HENHMETAFILE_UserFree // HENHMETAFILE_UserSize64 // HENHMETAFILE_UserMarshal64 // HENHMETAFILE_UserUnmarshal64 // HENHMETAFILE_UserFree64 // HMETAFILE_UserSize // HMETAFILE_UserMarshal // HMETAFILE_UserUnmarshal // HMETAFILE_UserFree // HMETAFILE_UserSize64 // HMETAFILE_UserMarshal64 // HMETAFILE_UserUnmarshal64 // HMETAFILE_UserFree64 // // History: 13-Dec-00 JohnDoty Migrated from transmit.cxx // //-------------------------------------------------------------------------- #include "stdrpc.hxx" #pragma hdrstop #include #include #include "transmit.hxx" #include #include #include "widewrap.h" #include #include #include #include "carefulreader.hxx" // ######################################################################### // // HMETAFILEPICT // See transmit.h for explanation of hglobal vs. gdi data/handle passing. // // ######################################################################### //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserSize // // Synopsis: Get the wire size the HMETAFILEPICT handle and data. // // Derivation: Union of a long and the meta file pict handle. // Then struct with top layer (and a hmetafile handle). // The the representation of the metafile. // // history: May-95 Ryszardk Created. // //-------------------------------------------------------------------------- unsigned long __RPC_USER HMETAFILEPICT_UserSize ( unsigned long * pFlags, unsigned long Offset, HMETAFILEPICT * pHMetaFilePict ) { if ( !pHMetaFilePict ) return Offset; LENGTH_ALIGN( Offset, 3 ); // Discriminant of the encapsulated union and the union arm. // Union discriminant is 4 bytes + handle is represented by a long. Offset += 8; if ( ! *pHMetaFilePict ) return Offset; if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) { #if defined(_WIN64) //Win64, inproc, we need a bit more space for the handle. Offset -= 4; //Get rid of that bogus long... LENGTH_ALIGN( Offset, 7 ); //Make sure alignment is right... Offset += 8; //And add in the real size of the handle... #endif return Offset; } // Now, this is a two layer object with HGLOBAL on top. // Upper layer - hglobal part - needs to be sent as data. METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); // Upper layer: 3 long fields + ptr marker + enc. union Offset += 4 * sizeof(long) + sizeof(userHMETAFILE); // The lower part is a metafile handle. if ( GDI_DATA_PASSING( *pFlags) ) { ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL ); Offset += 12 + ulDataSize; } GlobalUnlock( *(HANDLE *)pHMetaFilePict ); return( Offset ) ; } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserMarshal // // Synopsis: Marshalls an HMETAFILEPICT object into the RPC buffer. // // history: May-95 Ryszardk Created. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserMarshal ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict ) { if ( !pHMetaFilePict ) return pBuffer; UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserMarshal\n")); ALIGN( pBuffer, 3 ); if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) { // Sending only the top level global handle. #if defined(_WIN64) *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)( pHMetaFilePict ); #else *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pHMetaFilePict ); #endif return pBuffer; } // userHMETAFILEPICT // We need to send the data from the top (hglobal) layer. *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pHMetaFilePict ); if ( ! *pHMetaFilePict ) return pBuffer; // remoteHMETAFILEPICT METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RpcRaiseException( E_OUTOFMEMORY ); *( PULONG_LV_CAST pBuffer)++ = pMFP->mm; *( PULONG_LV_CAST pBuffer)++ = pMFP->xExt; *( PULONG_LV_CAST pBuffer)++ = pMFP->yExt; *( PULONG_LV_CAST pBuffer)++ = USER_MARSHAL_MARKER; // See if the HMETAFILE needs to be sent as data, too. if ( GDI_DATA_PASSING(*pFlags) ) { // userHMETAFILE *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; *( PLONG_LV_CAST pBuffer)++ = HandleToLong( pMFP->hMF ); if ( pMFP->hMF ) { ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL ); // conformant size then the size field *( PULONG_LV_CAST pBuffer)++ = ulDataSize; *( PULONG_LV_CAST pBuffer)++ = ulDataSize; GetMetaFileBitsEx( pMFP->hMF, ulDataSize , pBuffer ); pBuffer += ulDataSize; }; } else { // Sending only an HMETAFILE handle. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; *( PLONG_LV_CAST pBuffer)++ = HandleToLong( pMFP->hMF ); } GlobalUnlock( *(HANDLE *)pHMetaFilePict ); return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserUnmarshalWorker // // Synopsis: Unmarshalls an HMETAFILEPICT object from the RPC buffer. // // history: Aug-99 JohnStra Created. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserUnmarshalWorker ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict, ULONG_PTR BufferSize ) { unsigned long ulDataSize, fHandle; HMETAFILEPICT hMetaFilePict; // 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 and handle from the buffer. Caller checked for EOB. unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; if (IS_HANDLE64_MARKER(UnionDisc)) { ALIGN( pBuffer, 7 ); hMetaFilePict = (HMETAFILEPICT)(*( PHYPER_LV_CAST pBuffer)++ ); } else { hMetaFilePict = (HMETAFILEPICT)LongToHandle( *( PLONG_LV_CAST pBuffer)++ ); } if ( IS_DATA_MARKER( UnionDisc ) ) { if ( hMetaFilePict ) { HGLOBAL hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) ); hMetaFilePict = (HMETAFILEPICT) hGlobal; if ( hMetaFilePict == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock((HANDLE) hMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); // Check for EOB before accessing metadata. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (8 * sizeof( ULONG )) ); pMFP->mm = *( PULONG_LV_CAST pBuffer)++; pMFP->xExt = *( PULONG_LV_CAST pBuffer)++; pMFP->yExt = *( PULONG_LV_CAST pBuffer)++; // validate marker. if ( *( PULONG_LV_CAST pBuffer)++ != USER_MARSHAL_MARKER ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); UnionDisc = *( PULONG_LV_CAST pBuffer)++; pMFP->hMF = (HMETAFILE) LongToHandle( *( PLONG_LV_CAST pBuffer)++ ); ULONG ulExcept = 0; if ( pMFP->hMF ) { if (IS_DATA_MARKER( UnionDisc ) ) { // Check for EOB. if ( BufferSize < cbFixup + (10 * sizeof( ULONG )) ) ulExcept = RPC_X_BAD_STUB_DATA; else { // Conformant size then the size field. These must be the same. ulong ulDataSize = *( PULONG_LV_CAST pBuffer)++; if ( ulDataSize == *( PULONG_LV_CAST pBuffer)++ ) { // Check for EOB before accessing data. if ( BufferSize < cbFixup + (10 * sizeof(ULONG)) + ulDataSize ) ulExcept = RPC_X_BAD_STUB_DATA; else { pMFP->hMF = SetMetaFileBitsEx( ulDataSize, (uchar*)pBuffer ); pBuffer += ulDataSize; } } else ulExcept = RPC_X_BAD_STUB_DATA; } } else if ( !IS_HANDLE_MARKER( UnionDisc ) ) { ulExcept = RPC_S_INVALID_TAG; } } GlobalUnlock( (HANDLE) hMetaFilePict ); // wait until we've called GlobalUnlock before raising any exceptions. if ( ulExcept != 0 ) { RAISE_RPC_EXCEPTION( ulExcept ); } } } else if ( !(IS_HANDLE_MARKER( UnionDisc ) || IS_HANDLE64_MARKER( UnionDisc )) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } // no reusage, just release the previous one. if ( *pHMetaFilePict ) { // This may happen on the client only and doesn't depend on // how the other one was passed. METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); if ( pMFP->hMF ) DeleteMetaFile( pMFP->hMF ); GlobalUnlock( *pHMetaFilePict ); GlobalFree( *pHMetaFilePict ); } *pHMetaFilePict = hMetaFilePict; return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserUnmarshal // // Synopsis: Unmarshalls an HMETAFILEPICT object from the RPC buffer. // // history: May-95 Ryszardk Created. // Aug-99 JohnStra Factored out bulk of work into a // worker routine in order to add // consistency checks. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserUnmarshal ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict ) { UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserUnmarshal\n")); // Get the buffer size. CUserMarshalInfo MarshalInfo( pFlags, pBuffer ); ULONG_PTR BufferSize = MarshalInfo.GetBufferSize(); UCHAR* pBufferStart = MarshalInfo.GetBuffer(); pBuffer = HMETAFILEPICT_UserUnmarshalWorker( pFlags, pBufferStart, pHMetaFilePict, BufferSize ); return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserFree // // Synopsis: Free an HMETAFILEPICT. // // history: May-95 Ryszardk Created. // //-------------------------------------------------------------------------- void __RPC_USER HMETAFILEPICT_UserFree( unsigned long * pFlags, HMETAFILEPICT * pHMetaFilePict ) { UserNdrDebugOut((UNDR_FORCE, "HMETAFILEPICT_UserFree\n")); if( pHMetaFilePict && *pHMetaFilePict ) { if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) return; // Need to free the upper hglobal part. METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); // See if we need to free the hglobal, too. if ( pMFP->hMF && HGLOBAL_DATA_PASSING(*pFlags) ) DeleteMetaFile( pMFP->hMF ); GlobalUnlock( *pHMetaFilePict ); GlobalFree( *pHMetaFilePict ); } } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserSize // // Synopsis: Get the wire size the HENHMETAFILE handle and data. // // Derivation: Union of a long and the meta file handle and then struct. // // history: May-95 Ryszardk Created. // //-------------------------------------------------------------------------- unsigned long __RPC_USER HENHMETAFILE_UserSize ( unsigned long * pFlags, unsigned long Offset, HENHMETAFILE * pHEnhMetafile ) { if ( !pHEnhMetafile ) return Offset; LENGTH_ALIGN( Offset, 3 ); // The encapsulated union. // Discriminant and then handle or pointer from the union arm. // Union discriminant is 4 bytes + handle is represented by a long. Offset += sizeof(long) + sizeof(long); if ( ! *pHEnhMetafile ) return Offset; if ( GDI_DATA_PASSING(*pFlags) ) { // Pointee of the union arm for the remote case. // Byte blob : conformant size, size field, data Offset += 2 * sizeof(long); ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL ); Offset += ulDataSize; } return( Offset ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserMarshall // // Synopsis: Marshalls an HENHMETAFILE object into the RPC buffer. // // history: May-95 Ryszardk Created. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserMarshal ( unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHEnhMetafile ) { if ( !pHEnhMetafile ) return pBuffer; UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserMarshal\n")); ALIGN( pBuffer, 3 ); // Discriminant of the encapsulated union and union arm. if ( GDI_DATA_PASSING(*pFlags) ) { // userHENHMETAFILE *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pHEnhMetafile ); if ( !*pHEnhMetafile ) return pBuffer; // BYTE_BLOB: conformant size, size field, data ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL ); *( PULONG_LV_CAST pBuffer)++ = ulDataSize; *( PULONG_LV_CAST pBuffer)++ = ulDataSize; if ( 0 == GetEnhMetaFileBits( *pHEnhMetafile, ulDataSize, (uchar*)pBuffer ) ) RpcRaiseException( HRESULT_FROM_WIN32(GetLastError())); pBuffer += ulDataSize; } else { // Sending a handle. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; *( PLONG_LV_CAST pBuffer)++ = HandleToLong(*(HANDLE *)pHEnhMetafile); } return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserUnmarshallWorker // // Synopsis: Unmarshalls an HENHMETAFILE object from the RPC buffer. // // history: Aug-99 JohnStra Created. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserUnmarshalWorker ( unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHEnhMetafile, ULONG_PTR BufferSize ) { HENHMETAFILE hEnhMetafile; // 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 and handle. Caller checked for EOB. unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; hEnhMetafile = (HENHMETAFILE) LongToHandle( *( PLONG_LV_CAST pBuffer)++ ); if ( IS_DATA_MARKER( UnionDisc) ) { if ( hEnhMetafile ) { // Check for EOB before accessing metadata. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (4 * sizeof( ULONG )) ); // Byte blob : conformant size, size field, data ulong ulDataSize = *( PULONG_LV_CAST pBuffer)++; if ( *( PULONG_LV_CAST pBuffer)++ != ulDataSize ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); // Check for EOB before accessing data. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (4 * sizeof(ULONG)) + ulDataSize ); hEnhMetafile = SetEnhMetaFileBits( ulDataSize, (uchar*) pBuffer ); pBuffer += ulDataSize; } } else if ( !IS_HANDLE_MARKER( UnionDisc ) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } // No reusage of the old object. if (*pHEnhMetafile) DeleteEnhMetaFile( *pHEnhMetafile ); *pHEnhMetafile = hEnhMetafile; return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserUnmarshall // // Synopsis: Unmarshalls an HENHMETAFILE object from the RPC buffer. // // history: May-95 Ryszardk Created. // Aug-99 JohnStra Factored bulk of work out into a // worker routine in order to add // consistency checks. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserUnmarshal ( unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHEnhMetafile ) { UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserUnmarshal\n")); // Get the buffer size and start of buffer. CUserMarshalInfo MarshalInfo( pFlags, pBuffer ); ULONG_PTR BufferSize = MarshalInfo.GetBufferSize(); UCHAR* pBufferStart = MarshalInfo.GetBuffer(); pBuffer = HENHMETAFILE_UserUnmarshalWorker( pFlags, pBufferStart, pHEnhMetafile, BufferSize ); return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserFree // // Synopsis: Free an HENHMETAFILE. // // history: May-95 Ryszardk Created. // //-------------------------------------------------------------------------- void __RPC_USER HENHMETAFILE_UserFree( unsigned long * pFlags, HENHMETAFILE * pHEnhMetafile ) { UserNdrDebugOut((UNDR_FORCE, "HENHMETAFILE_UserFree\n")); if( pHEnhMetafile && *pHEnhMetafile ) { if ( GDI_DATA_PASSING(*pFlags) ) { DeleteEnhMetaFile( *pHEnhMetafile ); } } } // ######################################################################### // // HMETAFILE // See transmit.h for explanation of gdi data/handle passing. // // ######################################################################### //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserSize // // Synopsis: Get the wire size the HMETAFILE handle and data. // // Derivation: Same wire layout as HENHMETAFILE // //-------------------------------------------------------------------------- unsigned long __RPC_USER HMETAFILE_UserSize ( unsigned long * pFlags, unsigned long Offset, HMETAFILE * pHMetafile ) { if ( !pHMetafile ) return Offset; LENGTH_ALIGN( Offset, 3 ); // The encapsulated union. // Discriminant and then handle or pointer from the union arm. // Union discriminant is 4 bytes + handle is represented by a long. Offset += sizeof(long) + sizeof(long); if ( ! *pHMetafile ) return Offset; if ( GDI_DATA_PASSING(*pFlags) ) { // Pointee of the union arm for the remote case. // Byte blob : conformant size, size field, data Offset += 2 * sizeof(long); ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL ); Offset += ulDataSize; } return( Offset ); } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserMarshal // // Synopsis: Marshals an HMETAFILE object into the RPC buffer. // // Derivation: Same wire layout as HENHMETAFILE // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILE_UserMarshal ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILE * pHMetafile ) { if ( !pHMetafile ) return pBuffer; UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserMarshal\n")); ALIGN( pBuffer, 3 ); // Discriminant of the encapsulated union and union arm. if ( GDI_DATA_PASSING(*pFlags) ) { // userHMETAFILE *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; *( PULONG_LV_CAST pBuffer)++ = PtrToUlong(*pHMetafile); if ( !*pHMetafile ) return pBuffer; // BYTE_BLOB: conformant size, size field, data ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL ); *( PULONG_LV_CAST pBuffer)++ = ulDataSize; *( PULONG_LV_CAST pBuffer)++ = ulDataSize; if ( 0 == GetMetaFileBitsEx( *pHMetafile, ulDataSize, (uchar*)pBuffer ) ) RpcRaiseException( HRESULT_FROM_WIN32(GetLastError())); pBuffer += ulDataSize; } else { // Sending a handle. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; *( PULONG_LV_CAST pBuffer)++ = PtrToUlong(*(HANDLE *)pHMetafile); } return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserUnmarshal // // Synopsis: Unmarshalls an HMETAFILE object from the RPC buffer. // // Derivation: Same wire layout as HENHMETAFILE // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILE_UserUnmarshal ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILE * pHMetafile ) { HMETAFILE hMetafile; UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserUnmarshal\n")); // 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 the fixup size. 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)) ); unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; hMetafile = (HMETAFILE) LongToHandle( *( PLONG_LV_CAST pBuffer)++ ); if ( IS_DATA_MARKER( UnionDisc) ) { if ( hMetafile ) { // Check for EOB before accessing metadata. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (4 * sizeof( ULONG )) ); // Byte blob : conformant size, size field, data ulong ulDataSize = *( PULONG_LV_CAST pBuffer)++; if ( *( PULONG_LV_CAST pBuffer)++ != ulDataSize ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); // Check for EOB before accessing data. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (4 * sizeof( ULONG )) + ulDataSize ); hMetafile = SetMetaFileBitsEx( ulDataSize, (uchar*) pBuffer ); pBuffer += ulDataSize; } } else if ( !IS_HANDLE_MARKER( UnionDisc ) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } // No reusage of the old object. if (*pHMetafile) DeleteMetaFile( *pHMetafile ); *pHMetafile = hMetafile; return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserFree // // Synopsis: Free an HMETAFILE. // //-------------------------------------------------------------------------- void __RPC_USER HMETAFILE_UserFree( unsigned long * pFlags, HMETAFILE * pHMetafile ) { UserNdrDebugOut((UNDR_FORCE, "HMETAFILE_UserFree\n")); if( pHMetafile && *pHMetafile ) { if ( GDI_DATA_PASSING(*pFlags) ) { DeleteMetaFile( *pHMetafile ); } } } #if defined(_WIN64) //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserSize64 // // Synopsis: Get the wire size the HMETAFILEPICT handle and data. // // Derivation: Union of a long and the meta file pict handle. // Then struct with top layer (and a hmetafile handle). // The the representation of the metafile. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned long __RPC_USER HMETAFILEPICT_UserSize64 ( unsigned long * pFlags, unsigned long Offset, HMETAFILEPICT * pHMetaFilePict ) { if ( !pHMetaFilePict ) return Offset; // Discriminant of the encapsulated union and the union arm. // Union discriminant is 4 bytes LENGTH_ALIGN( Offset, 7 ); Offset += 4; LENGTH_ALIGN( Offset, 7 ); // Rest of the upper layer: // (already aligned on 8) // pointer marker (or handle) 8 Offset += 8; if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) { return Offset; } if ( ! *pHMetaFilePict ) { return Offset; } // METAFILEPICT is a structure containing an HMETAFILE. // The structure is GlobalAlloc'd. METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); // 3xlong 12 // (align on 8) 4 // lower lev ptr. 8 // Lower level: // (already aligned on 8) // discriminant 4 // (align on 8) 4 Offset += 32; // Lower layer: userHMETAFILE union... if ( GDI_DATA_PASSING( *pFlags) ) { // pointer 8 // BYTE_BLOB: // conformance 8 // size 4 // bytes ulDataSize ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL ); if (0 == ulDataSize) RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); Offset += 20 + ulDataSize; } else { // handle 8 Offset += 8; } GlobalUnlock( *(HANDLE *)pHMetaFilePict ); return( Offset ) ; } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserMarshal64 // // Synopsis: Marshalls an HMETAFILEPICT object into the RPC buffer. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserMarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict ) { if ( !pHMetaFilePict ) return pBuffer; UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserMarshal64\n")); ALIGN( pBuffer, 7 ); if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) { *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)( pHMetaFilePict ); return pBuffer; } // userHMETAFILEPICT // We need to send the data from the top (hglobal) layer. *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)( pHMetaFilePict ); if ( ! *pHMetaFilePict ) return pBuffer; // remoteHMETAFILEPICT METAFILEPICT * pMFP = (METAFILEPICT*)GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RpcRaiseException( E_OUTOFMEMORY ); *( PULONG_LV_CAST pBuffer)++ = pMFP->mm; *( PULONG_LV_CAST pBuffer)++ = pMFP->xExt; *( PULONG_LV_CAST pBuffer)++ = pMFP->yExt; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = USER_MARSHAL_MARKER; // See if the HMETAFILE needs to be sent as data, too. if ( GDI_DATA_PASSING(*pFlags) ) { // userHMETAFILE *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = (hyper)( pMFP->hMF ); if ( pMFP->hMF ) { ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL ); if (0 == ulDataSize) { GlobalUnlock (*(HANDLE *)pHMetaFilePict); RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); } // conformant size then the size field *( PHYPER_LV_CAST pBuffer)++ = ulDataSize; *( PULONG_LV_CAST pBuffer)++ = ulDataSize; GetMetaFileBitsEx( pMFP->hMF, ulDataSize , pBuffer ); pBuffer += ulDataSize; } } else { // Sending only an HMETAFILE handle. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = (hyper)( pMFP->hMF ); } GlobalUnlock( *(HANDLE *)pHMetaFilePict ); return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserUnmarshalWorker64 // // Synopsis: Unmarshalls an HMETAFILEPICT object from the RPC buffer. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserUnmarshalWorker64 ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict, ULONG_PTR BufferSize ) { CarefulBufferReader stream(pBuffer, BufferSize); unsigned long ulDataSize, fHandle; HMETAFILEPICT hMetaFilePict; stream.Align(8); unsigned long UnionDisc = stream.ReadULONGNA(); hMetaFilePict = (HMETAFILEPICT)stream.ReadHYPER(); if ( IS_DATA_MARKER( UnionDisc ) ) { if ( hMetaFilePict ) { HGLOBAL hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) ); hMetaFilePict = (HMETAFILEPICT) hGlobal; if ( hMetaFilePict == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock((HANDLE) hMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); RpcTryFinally { pMFP->mm = stream.ReadULONGNA(); pMFP->xExt = stream.ReadULONGNA(); pMFP->yExt = stream.ReadULONGNA(); // validate marker. if ( stream.ReadHYPER() != USER_MARSHAL_MARKER ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); UnionDisc = stream.ReadULONGNA(); pMFP->hMF = (HMETAFILE)stream.ReadHYPER(); if ( pMFP->hMF ) { if ( IS_DATA_MARKER( UnionDisc ) ) { // Conformant size then the size field. These must be the same. ULONG ulDataSize = (ULONG)stream.ReadHYPERNA(); if ( ulDataSize == stream.ReadULONGNA() ) { stream.CheckSize(ulDataSize); pMFP->hMF = SetMetaFileBitsEx( ulDataSize, (uchar*)stream.GetBuffer() ); if (NULL == pMFP->hMF) RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); stream.Advance(ulDataSize); } else RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); } else if ( !IS_HANDLE64_MARKER( UnionDisc ) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } } } RpcFinally { GlobalUnlock( (HANDLE) hMetaFilePict ); } RpcEndFinally; } } else if ( !IS_HANDLE64_MARKER( UnionDisc ) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } // no reusage, just release the previous one. if ( *pHMetaFilePict ) { // This may happen on the client only and doesn't depend on // how the other one was passed. METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); if ( pMFP->hMF ) DeleteMetaFile( pMFP->hMF ); GlobalUnlock( *pHMetaFilePict ); GlobalFree( *pHMetaFilePict ); } *pHMetaFilePict = hMetaFilePict; return( stream.GetBuffer() ); } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserUnmarshal64 // // Synopsis: Unmarshalls an HMETAFILEPICT object from the RPC buffer. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserUnmarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict ) { UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserUnmarshal64\n")); // Get the buffer size. CUserMarshalInfo MarshalInfo( pFlags, pBuffer ); ULONG_PTR BufferSize = MarshalInfo.GetBufferSize(); UCHAR* pBufferStart = MarshalInfo.GetBuffer(); pBuffer = HMETAFILEPICT_UserUnmarshalWorker64( pFlags, pBufferStart, pHMetaFilePict, BufferSize ); return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILEPICT_UserFree64 // // Synopsis: Free an HMETAFILEPICT. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- void __RPC_USER HMETAFILEPICT_UserFree64 ( unsigned long * pFlags, HMETAFILEPICT * pHMetaFilePict ) { UserNdrDebugOut((UNDR_FORCE, "HMETAFILEPICT_UserFree64\n")); if( pHMetaFilePict && *pHMetaFilePict ) { if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) return; // Need to free the upper hglobal part. METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); if ( pMFP == NULL ) RAISE_RPC_EXCEPTION( E_OUTOFMEMORY ); // See if we need to free the hglobal, too. if ( pMFP->hMF && HGLOBAL_DATA_PASSING(*pFlags) ) DeleteMetaFile( pMFP->hMF ); GlobalUnlock( *pHMetaFilePict ); GlobalFree( *pHMetaFilePict ); } } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserSize64 // // Synopsis: Get the wire size the HENHMETAFILE handle and data. // // Derivation: Union of a long and the meta file handle and then struct. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned long __RPC_USER HENHMETAFILE_UserSize64 ( unsigned long * pFlags, unsigned long Offset, HENHMETAFILE * pHEnhMetafile ) { if ( !pHEnhMetafile ) return Offset; LENGTH_ALIGN( Offset, 7 ); // The encapsulated union. // (aligned on 8) // discriminant 4 // (align on 8) 4 // pointer or handle 8 Offset += 16; if ( ! *pHEnhMetafile ) return Offset; if ( GDI_DATA_PASSING(*pFlags) ) { // BYTE_BLOB // (aligned on 8) // conformance 8 // size 4 // data ulDataSize ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL ); if (0 == ulDataSize) RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); Offset += 12 + ulDataSize; } return( Offset ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserMarshal64 // // Synopsis: Marshalls an HENHMETAFILE object into the RPC buffer. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserMarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHEnhMetafile ) { if ( !pHEnhMetafile ) return pBuffer; UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserMarshal64\n")); ALIGN( pBuffer, 7 ); // Discriminant of the encapsulated union and union arm. if ( GDI_DATA_PASSING(*pFlags) ) { // userHENHMETAFILE *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; ALIGN( pBuffer, 7 ); *( PHYPER_LV_CAST pBuffer)++ = (hyper)(*pHEnhMetafile); if ( !*pHEnhMetafile ) return pBuffer; // BYTE_BLOB: conformant size, size field, data ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL ); *( PHYPER_LV_CAST pBuffer)++ = ulDataSize; *( PULONG_LV_CAST pBuffer)++ = ulDataSize; if ( 0 == GetEnhMetaFileBits( *pHEnhMetafile, ulDataSize, (uchar*)pBuffer ) ) RpcRaiseException( HRESULT_FROM_WIN32(GetLastError())); pBuffer += ulDataSize; } else { // Sending a handle. *(PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER; ALIGN( pBuffer, 7 ); *(PHYPER_LV_CAST pBuffer)++ = (hyper)(*pHEnhMetafile); } return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserUnmarshallWorker64 // // Synopsis: Unmarshalls an HENHMETAFILE object from the RPC buffer. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserUnmarshalWorker64 ( unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHEnhMetafile, ULONG_PTR BufferSize ) { CarefulBufferReader stream(pBuffer, BufferSize); HENHMETAFILE hEnhMetafile; stream.Align(8); // Get the tag and handle. Caller checked for EOB. unsigned long UnionDisc = stream.ReadULONGNA(); hEnhMetafile = (HENHMETAFILE)stream.ReadHYPER(); if ( IS_DATA_MARKER( UnionDisc) ) { if ( hEnhMetafile ) { // Byte blob : conformant size, size field, data ulong ulDataSize = (ulong)stream.ReadHYPERNA(); if ( stream.ReadULONGNA() != ulDataSize ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); stream.CheckSize(ulDataSize); hEnhMetafile = SetEnhMetaFileBits( ulDataSize, (uchar*)stream.GetBuffer() ); if (NULL == hEnhMetafile) RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); stream.Advance(ulDataSize); } } else if ( !IS_HANDLE64_MARKER( UnionDisc ) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } // No reusage of the old object. if (*pHEnhMetafile) DeleteEnhMetaFile( *pHEnhMetafile ); *pHEnhMetafile = hEnhMetafile; return( stream.GetBuffer() ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserUnmarshal64 // // Synopsis: Unmarshalls an HENHMETAFILE object from the RPC buffer. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserUnmarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHEnhMetafile ) { UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserUnmarshal64\n")); // Get the buffer size and start of buffer. CUserMarshalInfo MarshalInfo( pFlags, pBuffer ); ULONG_PTR BufferSize = MarshalInfo.GetBufferSize(); UCHAR* pBufferStart = MarshalInfo.GetBuffer(); pBuffer = HENHMETAFILE_UserUnmarshalWorker64( pFlags, pBufferStart, pHEnhMetafile, BufferSize ); return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HENHMETAFILE_UserFree64 // // Synopsis: Free an HENHMETAFILE. // // history: Dec-00 JohnDoty Created from 32bit functions. // //-------------------------------------------------------------------------- void __RPC_USER HENHMETAFILE_UserFree64 ( unsigned long * pFlags, HENHMETAFILE * pHEnhMetafile ) { UserNdrDebugOut((UNDR_FORCE, "HENHMETAFILE_UserFree64\n")); if( pHEnhMetafile && *pHEnhMetafile ) { if ( GDI_DATA_PASSING(*pFlags) ) { DeleteEnhMetaFile( *pHEnhMetafile ); } } } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserSize64 // // Synopsis: Get the wire size the HMETAFILE handle and data. // // Derivation: Same wire layout as HENHMETAFILE // //-------------------------------------------------------------------------- unsigned long __RPC_USER HMETAFILE_UserSize64 ( unsigned long * pFlags, unsigned long Offset, HMETAFILE * pHMetafile ) { if ( !pHMetafile ) return Offset; LENGTH_ALIGN( Offset, 7 ); // The encapsulated union. // (aligned on 8) // discriminant 4 // (align on 8) 4 // ptr or handle 8 Offset += 16; if ( ! *pHMetafile ) return Offset; if ( GDI_DATA_PASSING(*pFlags) ) { // Byte blob // (aligned on 8) // conformance 8 // size 4 // data ulDataSize ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL ); if (0 == ulDataSize) RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); Offset += 12 + ulDataSize; } return( Offset ); } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserMarshal64 // // Synopsis: Marshals an HMETAFILE object into the RPC buffer. // // Derivation: Same wire layout as HENHMETAFILE // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILE_UserMarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILE * pHMetafile ) { if ( !pHMetafile ) return pBuffer; UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserMarshal64\n")); ALIGN( pBuffer, 7 ); // Discriminant of the encapsulated union and union arm. if ( GDI_DATA_PASSING(*pFlags) ) { // userHMETAFILE *(PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; ALIGN( pBuffer, 7 ); *(PHYPER_LV_CAST pBuffer)++ = (hyper)(*pHMetafile); if ( !*pHMetafile ) return pBuffer; // BYTE_BLOB: conformant size, size field, data ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL ); *( PHYPER_LV_CAST pBuffer)++ = ulDataSize; *( PULONG_LV_CAST pBuffer)++ = ulDataSize; if ( 0 == GetMetaFileBitsEx( *pHMetafile, ulDataSize, (uchar*)pBuffer ) ) RpcRaiseException( HRESULT_FROM_WIN32(GetLastError())); pBuffer += ulDataSize; } else { // Sending a handle. *(PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER; ALIGN( pBuffer, 7 ); *(PHYPER_LV_CAST pBuffer)++ = (hyper)(*(HANDLE *)pHMetafile); } return( pBuffer ); } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserUnmarshal64 // // Synopsis: Unmarshalls an HMETAFILE object from the RPC buffer. // // Derivation: Same wire layout as HENHMETAFILE // //-------------------------------------------------------------------------- unsigned char __RPC_FAR * __RPC_USER HMETAFILE_UserUnmarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, HMETAFILE * pHMetafile ) { HMETAFILE hMetafile; UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserUnmarshal64\n")); // Get the buffer size and the start of the buffer. CUserMarshalInfo MarshalInfo( pFlags, pBuffer ); CarefulBufferReader stream( pBuffer, MarshalInfo.GetBufferSize() ); // Align the buffer and save the fixup size. stream.Align(8); unsigned long UnionDisc = stream.ReadULONGNA(); hMetafile = (HMETAFILE)stream.ReadHYPER(); if ( IS_DATA_MARKER( UnionDisc) ) { if ( hMetafile ) { // Byte blob : conformant size, size field, data ulong ulDataSize = (ulong)stream.ReadHYPERNA(); if ( stream.ReadULONGNA() != ulDataSize ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); stream.CheckSize(ulDataSize); hMetafile = SetMetaFileBitsEx( ulDataSize, (uchar*) stream.GetBuffer() ); if (NULL == hMetafile) RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); stream.Advance(ulDataSize); } } else if ( !IS_HANDLE64_MARKER( UnionDisc ) ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); } // No reusage of the old object. if (*pHMetafile) DeleteMetaFile( *pHMetafile ); *pHMetafile = hMetafile; return( stream.GetBuffer() ); } //+------------------------------------------------------------------------- // // Function: HMETAFILE_UserFree64 // // Synopsis: Free an HMETAFILE. // //-------------------------------------------------------------------------- void __RPC_USER HMETAFILE_UserFree64( unsigned long * pFlags, HMETAFILE * pHMetafile ) { UserNdrDebugOut((UNDR_FORCE, "HMETAFILE_UserFree64\n")); if( pHMetafile && *pHMetafile ) { if ( GDI_DATA_PASSING(*pFlags) ) { DeleteMetaFile( *pHMetafile ); } } } #endif // win64