|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: clipformat.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 CLIPFORMAT.
//
// Functions:
// CLIPFORMAT_UserSize
// CLIPFORMAT_UserMarshal
// CLIPFORMAT_UserUnmarshal
// CLIPFORMAT_UserFree
// CLIPFORMAT_UserSize64
// CLIPFORMAT_UserMarshal64
// CLIPFORMAT_UserUnmarshal64
// CLIPFORMAT_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 <valid.h>
#include <obase.h>
#include <stream.hxx>
#include <winsta.h>
#include <allproc.h>
typedef HANDLE __stdcall FN_WinStationOpenServerW(LPWSTR); typedef BOOLEAN __stdcall FN_WinStationGetTermSrvCountersValue(HANDLE, ULONG, PVOID); typedef BOOLEAN __stdcall FN_WinStationCloseServer(HANDLE);
static DWORD g_cTSSessions = -1;
#include "carefulreader.hxx"
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
void CountTSSessions() { DWORD cTSSessions = 0; HINSTANCE hTSLib = LoadLibraryW(L"winsta.dll"); if (hTSLib) { FN_WinStationOpenServerW *pFNOpen = (FN_WinStationOpenServerW *)GetProcAddress(hTSLib, "WinStationOpenServerW"); FN_WinStationGetTermSrvCountersValue *pFNCount = (FN_WinStationGetTermSrvCountersValue *)GetProcAddress(hTSLib, "WinStationGetTermSrvCountersValue"); FN_WinStationCloseServer *pFNClose = (FN_WinStationCloseServer *)GetProcAddress(hTSLib, "WinStationCloseServer"); if (pFNOpen && pFNCount && pFNClose) { HANDLE hServer = pFNOpen(reinterpret_cast<WCHAR*>(SERVERNAME_CURRENT)); if (hServer != NULL) { TS_COUNTER tsCounters[2] = {0}; tsCounters[0].counterHead.dwCounterID = TERMSRV_CURRENT_DISC_SESSIONS; tsCounters[1].counterHead.dwCounterID = TERMSRV_CURRENT_ACTIVE_SESSIONS; if (pFNCount(hServer, ARRAYSIZE(tsCounters), tsCounters)) { int i; for (i = 0; i < ARRAYSIZE(tsCounters); i++) { if (tsCounters[i].counterHead.bResult) { cTSSessions += tsCounters[i].dwValue; } } } pFNClose(hServer); } } FreeLibrary(hTSLib); } g_cTSSessions = cTSSessions; }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserSize
//
// Synopsis: Sizes a CLIPFORMAT.
//
// Derivation: A union of a long and a string.
//
// history: Feb-96 Ryszardk Created
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER CLIPFORMAT_UserSize( unsigned long * pFlags, unsigned long Offset, CLIPFORMAT * pObject ) { if ( !pObject ) return( Offset );
if (g_cTSSessions == -1) { CountTSSessions(); }
// userCLIPFORMAT is an encapsulated union with a string.
LENGTH_ALIGN( Offset, 3); Offset += sizeof(long) + sizeof(void *);
if ( (NON_STANDARD_CLIPFORMAT(pObject)) && ((REMOTE_CLIPFORMAT( pFlags) ) || (g_cTSSessions > 1 ))) // ignore console session
{ wchar_t temp[CLIPFORMAT_BUFFER_MAX];
int ret = GetClipboardFormatName( *pObject, temp, CLIPFORMAT_BUFFER_MAX - 1 );
if ( ret ) { Offset += 3 * sizeof(long) + (ret+1) * sizeof(wchar_t); } else RAISE_RPC_EXCEPTION( DV_E_CLIPFORMAT ); }
return( Offset ); }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserMarshal
//
// Synopsis: Marshals a CLIPFORMAT.
//
// Derivation: A union of a long and a string.
//
// history: Feb-96 Ryszardk Created
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER CLIPFORMAT_UserMarshal( unsigned long * pFlags, unsigned char * pBuffer, CLIPFORMAT * pObject ) { if ( !pObject ) return pBuffer;
// userCLIPFORMAT is an encapsulated union with a string.
ALIGN( pBuffer, 3);
if ( (NON_STANDARD_CLIPFORMAT(pObject)) && (( REMOTE_CLIPFORMAT(pFlags) ) || (g_cTSSessions > 1 ))) // ignore console session
{ // sending a wide string
unsigned long ret;
*(PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject;
// On Chicago this is GetClipboardFormatNameX.
// When the buffer is too short, this call would still
// return a decent, null terminated, truncated string.
//
wchar_t temp[CLIPFORMAT_BUFFER_MAX]; ret = (ulong) GetClipboardFormatName( *pObject, temp, CLIPFORMAT_BUFFER_MAX - 1 );
if ( ret ) { ret++; lstrcpynW( (wchar_t *)(pBuffer + 12), temp, ret); // conformat size etc. for string.
*(PULONG_LV_CAST pBuffer)++ = ret; *(PULONG_LV_CAST pBuffer)++ = 0; *(PULONG_LV_CAST pBuffer)++ = ret; // skip the string in the bbuffer, including the terminator
pBuffer += ret * sizeof(wchar_t); } else RpcRaiseException( DV_E_CLIPFORMAT ); } else { // sending the number itself
*(PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject; }
return( pBuffer ); }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserUnmarshal
//
// Synopsis: Unmarshals a CLIPFORMAT; registers if needed.
//
// Derivation: A union of a long and a string.
//
// history: Feb-96 Ryszardk Created
// Aug-99 JohnStra Added consistency checks
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER CLIPFORMAT_UserUnmarshal( unsigned long * pFlags, unsigned char * pBuffer, CLIPFORMAT * pObject ) { ulong UnionDisc; UINT cf;
if (g_cTSSessions == -1) CountTSSessions();
// 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 buffer.
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (2 * sizeof( ULONG )) );
UnionDisc = *(PULONG_LV_CAST pBuffer)++; cf = (WORD) *(PULONG_LV_CAST pBuffer)++;
if ( WDT_DATA_MARKER == UnionDisc ) { // CLIPFORMAT value must be in valid range.
if ( cf < 0xc000 || cf > 0xffff ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Check for EOB before accessing string header.
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (5 * sizeof( ULONG )) );
// Get the string header from the buffer and subtract the string
// header from the BufferSize.
ULONG ConfSize = *(PULONG_LV_CAST pBuffer)++; ULONG Offset = *(PULONG_LV_CAST pBuffer)++; ULONG ActualSize = *(PULONG_LV_CAST pBuffer)++;
// Verify the header: Offset must always be zero, length must match
// size, and size can't be zero since that would mean no NULL
// terminator.
if ( 0 != Offset || ActualSize != ConfSize || 0 == ActualSize ) RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND );
// Check for EOB before accessing string.
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (5 * sizeof(ULONG)) + (ActualSize * sizeof(WCHAR)) );
// Last two bytes of the buffer must be unicode terminator
if ( *(WCHAR*)(pBuffer + ((ActualSize-1) * sizeof(WCHAR))) != 0x0000 ) RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND );
// Must be only 1 unicode terminator.
if ( (ULONG)(lstrlenW( (WCHAR*)pBuffer ) + 1) != ActualSize ) RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND );
// Register the clipboard format.
cf = RegisterClipboardFormat( (wchar_t *)pBuffer ); if ( cf == 0 ) RAISE_RPC_EXCEPTION( DV_E_CLIPFORMAT );
// Advance buffer pointer past string.
pBuffer += ActualSize * sizeof(wchar_t); } else { if ( WDT_HANDLE_MARKER != UnionDisc ) { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); }
if ( (NON_STANDARD_CLIPFORMAT(&cf)) && (( REMOTE_CLIPFORMAT(pFlags) ) || (g_cTSSessions > 1 ))) { // Should have sent this one by value!
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA ); } }
*pObject = (CLIPFORMAT) cf;
return( pBuffer ); }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserFree
//
// Synopsis: Frees remnants of CLIPFORMAT.
//
// Derivation: A union of a long and a string.
//
// history: Feb-96 Ryszardk Created
//
//--------------------------------------------------------------------------
void __RPC_USER CLIPFORMAT_UserFree( unsigned long * pFlags, CLIPFORMAT * pObject ) { // Nothing to free, as nothing gets allocated when we unmarshal.
}
#if defined(_WIN64)
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserSize64
//
// Synopsis: Sizes a CLIPFORMAT.
//
// Derivation: A union of a long and a string.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER CLIPFORMAT_UserSize64 ( unsigned long * pFlags, unsigned long Offset, CLIPFORMAT * pObject ) { if ( !pObject ) return( Offset );
if (g_cTSSessions == -1) CountTSSessions();
// userCLIPFORMAT is an encapsulated union with a string.
// max align of the union is size of 64b pointer.
LENGTH_ALIGN( Offset, 7 ); Offset += 8; // 4 byte discriminant, 4 byte alignment
if ( (NON_STANDARD_CLIPFORMAT(pObject)) && ((REMOTE_CLIPFORMAT( pFlags) ) || (g_cTSSessions > 1 ))) // ignore console session
{ // Writing another pointer...
Offset += 8; // 64b pointer
wchar_t temp[CLIPFORMAT_BUFFER_MAX + 1];
int ret = GetClipboardFormatName( *pObject, temp, CLIPFORMAT_BUFFER_MAX );
if ( ret ) { // This string has 3 conformance fields (64b) followed by an
// array of 16b chars.
Offset += (3 * 8) + ((ret + 1) * 2); } else RAISE_RPC_EXCEPTION( DV_E_CLIPFORMAT ); } else { // Writing a DWORD
Offset += 4; }
return( Offset ); }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserMarshal64
//
// Synopsis: Marshals a CLIPFORMAT.
//
// Derivation: A union of a long and a string.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER CLIPFORMAT_UserMarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, CLIPFORMAT * pObject ) { if ( !pObject ) return pBuffer;
// userCLIPFORMAT is an encapsulated union with a string.
ALIGN( pBuffer, 7 );
if ( (NON_STANDARD_CLIPFORMAT(pObject)) && ((REMOTE_CLIPFORMAT( pFlags) ) || (g_cTSSessions > 1 ))) // ignore console session
{ // sending a wide string
unsigned long ret;
*(PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; ALIGN( pBuffer, 7 ); *(PHYPER_LV_CAST pBuffer)++ = (hyper) *pObject;
// On Chicago this is GetClipboardFormatNameX.
// When the buffer is too short, this call would still
// return a decent, null terminated, truncated string.
//
wchar_t temp[CLIPFORMAT_BUFFER_MAX]; ret = (ulong) GetClipboardFormatName( *pObject, temp, CLIPFORMAT_BUFFER_MAX - 1 );
if ( ret ) { // Account for the trailing NULL.
ret ++; lstrcpynW( (wchar_t *)(pBuffer + (3 * 8)), temp, ret);
// conformat size etc. for string.
*(PHYPER_LV_CAST pBuffer)++ = ret; // Conformance
*(PHYPER_LV_CAST pBuffer)++ = 0; // Offset
*(PHYPER_LV_CAST pBuffer)++ = ret; // Actual Size
// skip the string in the buffer, including the terminator
pBuffer += (ret * 2); } else RpcRaiseException( DV_E_CLIPFORMAT ); } else { // sending the number itself
*(PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; ALIGN( pBuffer, 7 ); *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject; }
return( pBuffer ); }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserUnmarshal64
//
// Synopsis: Unmarshals a CLIPFORMAT; registers if needed.
//
// Derivation: A union of a long and a string.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER CLIPFORMAT_UserUnmarshal64 ( unsigned long * pFlags, unsigned char * pBuffer, CLIPFORMAT * pObject ) { ulong UnionDisc; hyper cf;
if (g_cTSSessions == -1) CountTSSessions();
// Get the buffer size and the start of the buffer.
CUserMarshalInfo MarshalInfo( pFlags, pBuffer ); CarefulBufferReader stream( pBuffer, MarshalInfo.GetBufferSize() );
stream.Align( 8 ); // Must align on 8, union rules.
UnionDisc = stream.ReadULONGNA(); // ...so no need to align on 4 here...
stream.Align( 8 ); // ...but must explicitly align to 8 here again.
if ( WDT_DATA_MARKER == UnionDisc ) { cf = stream.ReadHYPERNA(); // Just aligned 8, so don't align again.
// CLIPFORMAT value must be in valid range.
if ( cf < 0xc000 || cf > 0xffff ) RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Get the string header from the buffer and subtract the string
// header from the BufferSize.
hyper ConfSize = stream.ReadHYPERNA(); hyper Offset = stream.ReadHYPERNA(); hyper ActualSize = stream.ReadHYPERNA();
// Verify the header: Offset must always be zero, length must match
// size, and size can't be zero since that would mean no NULL
// terminator.
if ( 0 != Offset || ActualSize != ConfSize || 0 == ActualSize ) RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND );
// Check for EOB before accessing string.
stream.CheckSize((unsigned long)(ActualSize * sizeof(WCHAR)));
// Last two bytes of the buffer must be unicode terminator
WCHAR *pCheck = (WCHAR *)stream.GetBuffer(); if ( pCheck[ActualSize-1] != 0x0000 ) RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND ); // Must be only 1 unicode terminator.
if ( (ULONG)(lstrlenW( pCheck ) + 1) != ActualSize ) RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND );
// Register the clipboard format.
cf = RegisterClipboardFormat( pCheck ); if ( cf == 0 ) RAISE_RPC_EXCEPTION( DV_E_CLIPFORMAT );
// Advance buffer pointer past string.
stream.Advance((unsigned long)(ActualSize * sizeof(WCHAR))); } else if ( WDT_HANDLE_MARKER == UnionDisc ) { cf = (hyper)stream.ReadULONGNA(); // Just aligned on 8...
if ( (NON_STANDARD_CLIPFORMAT(&cf)) && ((REMOTE_CLIPFORMAT(pFlags)) || (g_cTSSessions > 1 )) ) { // We should have marshalled this by value-- this is a bogus clipboard format!
RAISE_RPC_EXCEPTION( RPC_X_INVALID_BOUND ); } } else { RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG ); }
*pObject = (CLIPFORMAT) cf;
return( stream.GetBuffer() ); }
//+-------------------------------------------------------------------------
//
// Function: CLIPFORMAT_UserFree64
//
// Synopsis: Frees remnants of CLIPFORMAT.
//
// Derivation: A union of a long and a string.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
void __RPC_USER CLIPFORMAT_UserFree64 ( unsigned long * pFlags, CLIPFORMAT * pObject ) { // Nothing to free, as nothing gets allocated when we unmarshal.
}
#endif // win64
|