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

586 lines
16 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: bitmap.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 HBITMAP.
//
// Functions:
// HBITMAP_UserSize
// HBITMAP_UserMarshal
// HBITMAP_UserUnmarshal
// HBITMAP_UserFree
// HBITMAP_UserSize64
// HBITMAP_UserMarshal64
// HBITMAP_UserUnmarshal64
// HBITMAP_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: HBITMAP_UserSize
//
// Synopsis: Get the wire size the HBITMAP handle and data.
//
// Derivation: Union of a long and the bitmap handle and then struct.
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HBITMAP_UserSize (
unsigned long * pFlags,
unsigned long Offset,
HBITMAP * pHBitmap )
{
if ( !pHBitmap )
return Offset;
BITMAP bm;
HBITMAP hBitmap = *pHBitmap;
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 ( ! *pHBitmap )
return Offset;
if ( GDI_DATA_PASSING(*pFlags) )
{
// Pointee of the union arm for the remote case.
// Conformat size, 6 fields, size, conf array.
Offset += 4 + 4 * sizeof(LONG) + 2 * sizeof(WORD) + 4;
// Get information about the bitmap
#if defined(_CHICAGO_)
if (FALSE == GetObjectA(hBitmap, sizeof(BITMAP), &bm))
#else
if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm))
#endif
{
RAISE_RPC_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
}
ULONG ulDataSize = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
Offset += ulDataSize;
}
return( Offset ) ;
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserMarshall
//
// Synopsis: Marshalls an HBITMAP object into the RPC buffer.
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBITMAP_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HBITMAP * pHBitmap )
{
if ( !pHBitmap )
return pBuffer;
UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserMarshal\n"));
ALIGN( pBuffer, 3 );
// Discriminant of the encapsulated union and union arm.
if ( GDI_DATA_PASSING(*pFlags) )
{
// userHBITMAP
*( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
*( PULONG_LV_CAST pBuffer)++ = PtrToUlong(*pHBitmap);
if ( ! *pHBitmap )
return pBuffer;
// Get information about the bitmap
BITMAP bm;
HBITMAP hBitmap = *pHBitmap;
#if defined(_CHICAGO_)
if (FALSE == GetObjectA(hBitmap, sizeof(BITMAP), &bm))
#else
if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm))
#endif
{
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
DWORD dwCount = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
*( PULONG_LV_CAST pBuffer)++ = dwCount;
// Get the bm structure fields.
ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD );
memcpy( pBuffer, (void *) &bm, ulBmSize );
pBuffer += ulBmSize;
// Get the raw bits.
if (0 == GetBitmapBits( hBitmap, dwCount, pBuffer ) )
{
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
pBuffer += dwCount;
}
else
{
// Sending a handle.
*( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
*( PULONG_LV_CAST pBuffer)++ = PtrToUlong(*(HANDLE *)pHBitmap);
}
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserUnmarshallWorker
//
// Synopsis: Unmarshalls an HBITMAP object from the RPC buffer.
//
// history: Aug-99 JohnStra Created.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBITMAP_UserUnmarshalWorker (
unsigned long * pFlags,
unsigned char * pBuffer,
HBITMAP * pHBitmap,
ULONG_PTR BufferSize )
{
HBITMAP hBitmap;
// 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 Discriminant and handle. Caller checked for EOB.
unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
hBitmap = (HBITMAP)LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
if ( IS_DATA_MARKER( UnionDisc) )
{
if ( hBitmap )
{
ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD );
// Check for EOB before accessing metadata.
CHECK_BUFFER_SIZE(
BufferSize,
cbFixup + (3 * sizeof( ULONG )) + ulBmSize );
DWORD dwCount = *( PULONG_LV_CAST pBuffer)++;
BITMAP * pBm = (BITMAP *) pBuffer;
// verify dwCount matches the bitmap.
if ( dwCount != (DWORD) pBm->bmPlanes * pBm->bmHeight * pBm->bmWidthBytes )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
pBuffer += ulBmSize;
// Check for EOB before accessing data.
CHECK_BUFFER_SIZE(
BufferSize,
cbFixup + (3 * sizeof(ULONG)) + ulBmSize + dwCount);
// Create a bitmap based on the BITMAP structure and the raw bits in
// the transmission buffer
hBitmap = CreateBitmap( pBm->bmWidth,
pBm->bmHeight,
pBm->bmPlanes,
pBm->bmBitsPixel,
pBuffer );
pBuffer += dwCount;
}
}
else if ( !IS_HANDLE_MARKER( UnionDisc ) )
{
RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
}
// A new bitmap handle is ready, destroy the old one, if needed.
if ( *pHBitmap )
DeleteObject( *pHBitmap );
*pHBitmap = hBitmap;
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserUnmarshall
//
// Synopsis: Unmarshalls an HBITMAP object from the RPC buffer.
//
// history: May-95 Ryszardk Created.
// Aug-99 JohnStra Factored bulk of work into a worker
// routine in order to add consistency
// checks.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBITMAP_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
HBITMAP * pHBitmap )
{
UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserUnmarshal\n"));
// Get the buffer size and ptr to buffer.
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
pBuffer = HBITMAP_UserUnmarshalWorker( pFlags,
pBufferStart,
pHBitmap,
BufferSize );
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserFree
//
// Synopsis: Free an HBITMAP.
//
// history: May-95 Ryszardk Created.
//
//--------------------------------------------------------------------------
void __RPC_USER
HBITMAP_UserFree(
unsigned long * pFlags,
HBITMAP * pHBitmap )
{
UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserFree\n"));
if( pHBitmap && *pHBitmap )
{
if ( GDI_DATA_PASSING(*pFlags) )
{
DeleteObject( *pHBitmap );
}
}
}
#if defined(_WIN64)
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserSize64
//
// Synopsis: Get the wire size the HBITMAP handle and data.
//
// Derivation: Union of a long and the bitmap handle and then struct.
//
// history: Dec-00 JohnDoty Created from 32bit functions.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
HBITMAP_UserSize64 (
unsigned long * pFlags,
unsigned long Offset,
HBITMAP * pHBitmap )
{
if ( !pHBitmap )
return Offset;
BITMAP bm;
HBITMAP hBitmap = *pHBitmap;
LENGTH_ALIGN( Offset, 7 );
// The encapsulated union.
// (aligned on 8)
// discriminant 4
// (align on 8) 4
// handle or ptr 8
Offset += 16;
if ( ! *pHBitmap )
return Offset;
if ( GDI_DATA_PASSING(*pFlags) )
{
// Pointee of the union arm for the remote case.
// (aligned on 8)
// conformance 8
// 4xlong 16
// 2xword 4
// size 4
// data ulDataSize;
if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm))
RAISE_RPC_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
ULONG ulDataSize = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
Offset += 32 + ulDataSize;
}
return( Offset ) ;
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserMarshal64
//
// Synopsis: Marshalls an HBITMAP object into the RPC buffer.
//
// history: Dec-00 JohnDoty Created from 32bit functions.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBITMAP_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HBITMAP * pHBitmap )
{
if ( !pHBitmap )
return pBuffer;
UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserMarshal64\n"));
ALIGN( pBuffer, 7 );
// Discriminant of the encapsulated union and union arm.
if ( GDI_DATA_PASSING(*pFlags) )
{
// userHBITMAP
*( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
ALIGN( pBuffer, 7 );
*( PHYPER_LV_CAST pBuffer)++ = (hyper)(*pHBitmap);
if ( ! *pHBitmap )
return pBuffer;
// Get information about the bitmap
BITMAP bm;
HBITMAP hBitmap = *pHBitmap;
if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm))
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
ULONG ulCount = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
// Conformance...
*(PHYPER_LV_CAST pBuffer)++ = ulCount;
// Get the bm structure fields.
ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD );
memcpy( pBuffer, &bm, ulBmSize );
pBuffer += ulBmSize;
// Get the raw bits.
*(PULONG_LV_CAST pBuffer)++ = ulCount;
if (0 == GetBitmapBits( hBitmap, ulCount, pBuffer ) )
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
pBuffer += ulCount;
}
else
{
// Sending a handle.
*( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER;
ALIGN( pBuffer, 7 );
*( PHYPER_LV_CAST pBuffer)++ = (hyper)(*(HANDLE *)pHBitmap);
}
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserUnmarshallWorker64
//
// Synopsis: Unmarshalls an HBITMAP object from the RPC buffer.
//
// history: Dec-00 JohnDoty Created from 32bit functions.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBITMAP_UserUnmarshalWorker64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HBITMAP * pHBitmap,
ULONG_PTR BufferSize )
{
CarefulBufferReader stream(pBuffer, BufferSize);
stream.Align(8);
// Get Discriminant and handle.
unsigned long UnionDisc = stream.ReadULONGNA();
HBITMAP hBitmap = (HBITMAP)stream.ReadHYPER();
if ( IS_DATA_MARKER( UnionDisc) )
{
if ( hBitmap )
{
DWORD dwCount = (DWORD)stream.ReadHYPERNA();
// Check for EOB before accessing metadata.
ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof(WORD);
stream.CheckSize(ulBmSize);
BITMAP * pBm = (BITMAP *)stream.GetBuffer();
// verify dwCount matches the bitmap.
if ( dwCount != (DWORD) pBm->bmPlanes * pBm->bmHeight * pBm->bmWidthBytes )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
stream.Advance(ulBmSize);
if (stream.ReadULONGNA() != dwCount)
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Check for EOB before accessing data.
stream.CheckSize(dwCount);
// Create a bitmap based on the BITMAP structure and the raw bits in
// the transmission buffer
hBitmap = CreateBitmap( pBm->bmWidth,
pBm->bmHeight,
pBm->bmPlanes,
pBm->bmBitsPixel,
stream.GetBuffer() );
if (hBitmap == NULL)
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
stream.Advance(dwCount);
}
}
else if ( !IS_HANDLE64_MARKER( UnionDisc ) )
{
RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
}
// A new bitmap handle is ready, destroy the old one, if needed.
if ( *pHBitmap )
DeleteObject( *pHBitmap );
*pHBitmap = hBitmap;
return( stream.GetBuffer() );
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserUnmarshal64
//
// Synopsis: Unmarshalls an HBITMAP object from the RPC buffer.
//
// history: Dec-00 JohnDoty Created from 32bit functions.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
HBITMAP_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
HBITMAP * pHBitmap )
{
UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserUnmarshal\n"));
// Get the buffer size and ptr to buffer.
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
pBuffer = HBITMAP_UserUnmarshalWorker64( pFlags,
pBufferStart,
pHBitmap,
BufferSize );
return( pBuffer );
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_UserFree64
//
// Synopsis: Free an HBITMAP.
//
// history: Dec-00 JohnDoty Created from 32bit functions.
//
//--------------------------------------------------------------------------
void __RPC_USER
HBITMAP_UserFree64 (
unsigned long * pFlags,
HBITMAP * pHBitmap )
{
UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserFree\n"));
if( pHBitmap && *pHBitmap )
{
if ( GDI_DATA_PASSING(*pFlags) )
{
DeleteObject( *pHBitmap );
}
}
}
#endif