//+------------------------------------------------------------------------- // // 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 #include #include "transmit.hxx" #include #include #include #include #include #include #include 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(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