1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_dtrans.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir /* 32*cdf0e10cSrcweir MtaOleClipb.cxx - documentation 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir This class setup a single threaded apartment (sta) thread to deal with 35*cdf0e10cSrcweir the ole clipboard, which runs only in an sta thread. 36*cdf0e10cSrcweir The consequence is that callback from the ole clipboard are in the 37*cdf0e10cSrcweir context of this sta thread. In the soffice applications this may lead 38*cdf0e10cSrcweir to problems because they all use the one and only mutex called 39*cdf0e10cSrcweir SolarMutex. 40*cdf0e10cSrcweir In order to transfer clipboard requests to our sta thread we use a 41*cdf0e10cSrcweir hidden window an forward these requests via window messages. 42*cdf0e10cSrcweir */ 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir #ifdef _MSC_VER 45*cdf0e10cSrcweir #pragma warning( disable : 4786 ) // identifier was truncated to 'number' 46*cdf0e10cSrcweir // characters in the debug information 47*cdf0e10cSrcweir #endif 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir //#define UNICODE 50*cdf0e10cSrcweir #include <osl/diagnose.h> 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir #include "..\..\inc\MtaOleClipb.hxx" 53*cdf0e10cSrcweir #include <osl/conditn.hxx> 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir #include <wchar.h> 56*cdf0e10cSrcweir #include <process.h> 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir #include <systools/win32/comtools.hxx> 59*cdf0e10cSrcweir #ifdef __MINGW32__ 60*cdf0e10cSrcweir #define __uuidof(I) IID_##I 61*cdf0e10cSrcweir #endif 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir //---------------------------------------------------------------- 64*cdf0e10cSrcweir // namespace directives 65*cdf0e10cSrcweir //---------------------------------------------------------------- 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir using osl::Condition; 68*cdf0e10cSrcweir using osl::Mutex; 69*cdf0e10cSrcweir using osl::MutexGuard; 70*cdf0e10cSrcweir using osl::ClearableMutexGuard; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir //---------------------------------------------------------------- 73*cdf0e10cSrcweir // defines 74*cdf0e10cSrcweir //---------------------------------------------------------------- 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir namespace /* private */ 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir char CLIPSRV_DLL_NAME[] = "sysdtrans.dll"; 79*cdf0e10cSrcweir char g_szWndClsName[] = "MtaOleReqWnd###"; 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir //-------------------------------------------------------- 82*cdf0e10cSrcweir // messages constants 83*cdf0e10cSrcweir //-------------------------------------------------------- 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir const sal_uInt32 MSG_SETCLIPBOARD = WM_USER + 0x0001; 86*cdf0e10cSrcweir const sal_uInt32 MSG_GETCLIPBOARD = WM_USER + 0x0002; 87*cdf0e10cSrcweir const sal_uInt32 MSG_REGCLIPVIEWER = WM_USER + 0x0003; 88*cdf0e10cSrcweir const sal_uInt32 MSG_FLUSHCLIPBOARD = WM_USER + 0x0004; 89*cdf0e10cSrcweir const sal_uInt32 MSG_SHUTDOWN = WM_USER + 0x0005; 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir const sal_uInt32 MAX_WAITTIME = 10000; // msec 92*cdf0e10cSrcweir const sal_uInt32 MAX_WAIT_SHUTDOWN = 10000; // msec 93*cdf0e10cSrcweir const sal_uInt32 MAX_CLIPEVENT_PROCESSING_TIME = 5000; // msec 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir const sal_Bool MANUAL_RESET = sal_True; 96*cdf0e10cSrcweir const sal_Bool AUTO_RESET = sal_False; 97*cdf0e10cSrcweir const sal_Bool INIT_NONSIGNALED = sal_False; 98*cdf0e10cSrcweir 99*cdf0e10cSrcweir //------------------------------------------------------ 100*cdf0e10cSrcweir /* Cannot use osl conditions because they are blocking 101*cdf0e10cSrcweir without waking up on messages sent by another thread 102*cdf0e10cSrcweir this leads to deadlocks because we are blocking the 103*cdf0e10cSrcweir communication between inter-thread marshalled COM 104*cdf0e10cSrcweir pointers. 105*cdf0e10cSrcweir COM Proxy-Stub communication uses SendMessages for 106*cdf0e10cSrcweir synchronization purposes. 107*cdf0e10cSrcweir */ 108*cdf0e10cSrcweir class Win32Condition 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir public: 111*cdf0e10cSrcweir // ctor 112*cdf0e10cSrcweir Win32Condition() 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir m_hEvent = CreateEvent( 115*cdf0e10cSrcweir 0, /* no security */ 116*cdf0e10cSrcweir true, /* manual reset */ 117*cdf0e10cSrcweir false, /* initial state not signaled */ 118*cdf0e10cSrcweir 0); /* automatic name */ 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir 121*cdf0e10cSrcweir // dtor 122*cdf0e10cSrcweir ~Win32Condition() 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir CloseHandle(m_hEvent); 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir // wait infinite for event be signaled 128*cdf0e10cSrcweir // leave messages sent through 129*cdf0e10cSrcweir void wait() 130*cdf0e10cSrcweir { 131*cdf0e10cSrcweir while(1) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir DWORD dwResult = 134*cdf0e10cSrcweir MsgWaitForMultipleObjects(1, &m_hEvent, FALSE, INFINITE, QS_SENDMESSAGE); 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir switch (dwResult) 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir case WAIT_OBJECT_0: 139*cdf0e10cSrcweir return; 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir case WAIT_OBJECT_0 + 1: 142*cdf0e10cSrcweir { 143*cdf0e10cSrcweir /* PeekMessage processes all messages in the SendMessage 144*cdf0e10cSrcweir queue that's what we want, messages from the PostMessage 145*cdf0e10cSrcweir queue stay untouched */ 146*cdf0e10cSrcweir MSG msg; 147*cdf0e10cSrcweir PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir break; 150*cdf0e10cSrcweir } 151*cdf0e10cSrcweir } 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir } 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir // reset the event 156*cdf0e10cSrcweir void set() 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir SetEvent(m_hEvent); 159*cdf0e10cSrcweir } 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir private: 162*cdf0e10cSrcweir HANDLE m_hEvent; 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir // prevent copy/assignment 165*cdf0e10cSrcweir private: 166*cdf0e10cSrcweir Win32Condition(const Win32Condition&); 167*cdf0e10cSrcweir Win32Condition& operator=(const Win32Condition&); 168*cdf0e10cSrcweir }; 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir //------------------------------------------ 171*cdf0e10cSrcweir // we use one condition for every request 172*cdf0e10cSrcweir //------------------------------------------ 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir struct MsgCtx 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir Win32Condition aCondition; 177*cdf0e10cSrcweir HRESULT hr; 178*cdf0e10cSrcweir }; 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir } /* namespace private */ 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir //---------------------------------------------------------------- 183*cdf0e10cSrcweir // static member initialization 184*cdf0e10cSrcweir //---------------------------------------------------------------- 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir CMtaOleClipboard* CMtaOleClipboard::s_theMtaOleClipboardInst = NULL; 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir //-------------------------------------------------------------------- 189*cdf0e10cSrcweir // marshal an IDataObject 190*cdf0e10cSrcweir //-------------------------------------------------------------------- 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir //inline 193*cdf0e10cSrcweir HRESULT MarshalIDataObjectInStream( IDataObject* pIDataObject, LPSTREAM* ppStream ) 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir OSL_ASSERT( NULL != pIDataObject ); 196*cdf0e10cSrcweir OSL_ASSERT( NULL != ppStream ); 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir *ppStream = NULL; 199*cdf0e10cSrcweir return CoMarshalInterThreadInterfaceInStream( 200*cdf0e10cSrcweir __uuidof(IDataObject), //The IID of inteface to be marshaled 201*cdf0e10cSrcweir pIDataObject, //The interface pointer 202*cdf0e10cSrcweir ppStream //IStream pointer 203*cdf0e10cSrcweir ); 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir //-------------------------------------------------------------------- 207*cdf0e10cSrcweir // unmarshal an IDataObject 208*cdf0e10cSrcweir //-------------------------------------------------------------------- 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir //inline 211*cdf0e10cSrcweir HRESULT UnmarshalIDataObjectAndReleaseStream( LPSTREAM lpStream, IDataObject** ppIDataObject ) 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir OSL_ASSERT( NULL != lpStream ); 214*cdf0e10cSrcweir OSL_ASSERT( NULL != ppIDataObject ); 215*cdf0e10cSrcweir 216*cdf0e10cSrcweir *ppIDataObject = NULL; 217*cdf0e10cSrcweir return CoGetInterfaceAndReleaseStream( 218*cdf0e10cSrcweir lpStream, 219*cdf0e10cSrcweir __uuidof(IDataObject), 220*cdf0e10cSrcweir reinterpret_cast<LPVOID*>(ppIDataObject)); 221*cdf0e10cSrcweir } 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir //-------------------------------------------------------------------- 224*cdf0e10cSrcweir // helper class to ensure that the calling thread has com initialized 225*cdf0e10cSrcweir //-------------------------------------------------------------------- 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir class CAutoComInit 228*cdf0e10cSrcweir { 229*cdf0e10cSrcweir public: 230*cdf0e10cSrcweir CAutoComInit( ) 231*cdf0e10cSrcweir { 232*cdf0e10cSrcweir /* 233*cdf0e10cSrcweir to be safe we call CoInitialize 234*cdf0e10cSrcweir although it is not necessary if 235*cdf0e10cSrcweir the calling thread was created 236*cdf0e10cSrcweir using osl_CreateThread because 237*cdf0e10cSrcweir this function calls CoInitialize 238*cdf0e10cSrcweir for every thread it creates 239*cdf0e10cSrcweir */ 240*cdf0e10cSrcweir m_hResult = CoInitialize( NULL ); 241*cdf0e10cSrcweir 242*cdf0e10cSrcweir if ( S_OK == m_hResult ) 243*cdf0e10cSrcweir OSL_ENSURE( sal_False, \ 244*cdf0e10cSrcweir "com was not yet initialzed, the thread was not created using osl_createThread" ); 245*cdf0e10cSrcweir else if ( FAILED( m_hResult ) && !( RPC_E_CHANGED_MODE == m_hResult ) ) 246*cdf0e10cSrcweir OSL_ENSURE( sal_False, \ 247*cdf0e10cSrcweir "com could not be initialized, maybe the thread was not created using osl_createThread" ); 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir ~CAutoComInit( ) 251*cdf0e10cSrcweir { 252*cdf0e10cSrcweir /* 253*cdf0e10cSrcweir we only call CoUninitialize when 254*cdf0e10cSrcweir CoInitailize returned S_FALSE, what 255*cdf0e10cSrcweir means that com was already initialize 256*cdf0e10cSrcweir for that thread so we keep the balance 257*cdf0e10cSrcweir if CoInitialize returned S_OK what means 258*cdf0e10cSrcweir com was not yet initialized we better 259*cdf0e10cSrcweir let com initialized or we may run into 260*cdf0e10cSrcweir the realm of undefined behaviour 261*cdf0e10cSrcweir */ 262*cdf0e10cSrcweir if ( m_hResult == S_FALSE ) 263*cdf0e10cSrcweir CoUninitialize( ); 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir private: 267*cdf0e10cSrcweir HRESULT m_hResult; 268*cdf0e10cSrcweir }; 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir //-------------------------------------------------------------------- 271*cdf0e10cSrcweir // ctor 272*cdf0e10cSrcweir //-------------------------------------------------------------------- 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir CMtaOleClipboard::CMtaOleClipboard( ) : 275*cdf0e10cSrcweir m_hOleThread( NULL ), 276*cdf0e10cSrcweir m_uOleThreadId( 0 ), 277*cdf0e10cSrcweir m_hEvtThrdReady( NULL ), 278*cdf0e10cSrcweir m_hwndMtaOleReqWnd( NULL ), 279*cdf0e10cSrcweir m_MtaOleReqWndClassAtom( 0 ), 280*cdf0e10cSrcweir m_hwndNextClipViewer( NULL ), 281*cdf0e10cSrcweir m_pfncClipViewerCallback( NULL ), 282*cdf0e10cSrcweir m_bRunClipboardNotifierThread( sal_True ), 283*cdf0e10cSrcweir m_hClipboardChangedEvent( m_hClipboardChangedNotifierEvents[0] ), 284*cdf0e10cSrcweir m_hTerminateClipboardChangedNotifierEvent( m_hClipboardChangedNotifierEvents[1] ), 285*cdf0e10cSrcweir m_ClipboardChangedEventCount( 0 ) 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir // signals that the thread was successfully setup 288*cdf0e10cSrcweir m_hEvtThrdReady = CreateEventA( 0, MANUAL_RESET, INIT_NONSIGNALED, NULL ); 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir OSL_ASSERT( NULL != m_hEvtThrdReady ); 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir s_theMtaOleClipboardInst = this; 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir m_hOleThread = (HANDLE)_beginthreadex( 295*cdf0e10cSrcweir NULL, 0, CMtaOleClipboard::oleThreadProc, this, 0, &m_uOleThreadId ); 296*cdf0e10cSrcweir OSL_ASSERT( NULL != m_hOleThread ); 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir //---------------------------------------------- 299*cdf0e10cSrcweir // setup the clipboard changed notifier thread 300*cdf0e10cSrcweir //---------------------------------------------- 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir m_hClipboardChangedNotifierEvents[0] = CreateEventA( 0, MANUAL_RESET, INIT_NONSIGNALED, NULL ); 303*cdf0e10cSrcweir OSL_ASSERT( NULL != m_hClipboardChangedNotifierEvents[0] ); 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir m_hClipboardChangedNotifierEvents[1] = CreateEventA( 0, MANUAL_RESET, INIT_NONSIGNALED, NULL ); 306*cdf0e10cSrcweir OSL_ASSERT( NULL != m_hClipboardChangedNotifierEvents[1] ); 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir unsigned uThreadId; 309*cdf0e10cSrcweir m_hClipboardChangedNotifierThread = (HANDLE)_beginthreadex( 310*cdf0e10cSrcweir NULL, 0, CMtaOleClipboard::clipboardChangedNotifierThreadProc, this, 0, &uThreadId ); 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir OSL_ASSERT( NULL != m_hClipboardChangedNotifierThread ); 313*cdf0e10cSrcweir } 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir //-------------------------------------------------------------------- 316*cdf0e10cSrcweir // dtor 317*cdf0e10cSrcweir //-------------------------------------------------------------------- 318*cdf0e10cSrcweir 319*cdf0e10cSrcweir CMtaOleClipboard::~CMtaOleClipboard( ) 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir // block calling threads out 322*cdf0e10cSrcweir if ( NULL != m_hEvtThrdReady ) 323*cdf0e10cSrcweir ResetEvent( m_hEvtThrdReady ); 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir // terminate the clipboard changed notifier thread 326*cdf0e10cSrcweir m_bRunClipboardNotifierThread = sal_False; 327*cdf0e10cSrcweir SetEvent( m_hTerminateClipboardChangedNotifierEvent ); 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir sal_uInt32 dwResult = WaitForSingleObject( 330*cdf0e10cSrcweir m_hClipboardChangedNotifierThread, MAX_WAIT_SHUTDOWN ); 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir OSL_ENSURE( dwResult == WAIT_OBJECT_0, "clipboard notifier thread could not terminate" ); 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir if ( NULL != m_hClipboardChangedNotifierThread ) 335*cdf0e10cSrcweir CloseHandle( m_hClipboardChangedNotifierThread ); 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir if ( NULL != m_hClipboardChangedNotifierEvents[0] ) 338*cdf0e10cSrcweir CloseHandle( m_hClipboardChangedNotifierEvents[0] ); 339*cdf0e10cSrcweir 340*cdf0e10cSrcweir if ( NULL != m_hClipboardChangedNotifierEvents[1] ) 341*cdf0e10cSrcweir CloseHandle( m_hClipboardChangedNotifierEvents[1] ); 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir // end the thread 344*cdf0e10cSrcweir // because DestroyWindow can only be called 345*cdf0e10cSrcweir // from within the thread that created the window 346*cdf0e10cSrcweir sendMessage( MSG_SHUTDOWN, 347*cdf0e10cSrcweir static_cast< WPARAM >( 0 ), 348*cdf0e10cSrcweir static_cast< LPARAM >( 0 ) ); 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir // wait for thread shutdown 351*cdf0e10cSrcweir dwResult = WaitForSingleObject( m_hOleThread, MAX_WAIT_SHUTDOWN ); 352*cdf0e10cSrcweir OSL_ENSURE( dwResult == WAIT_OBJECT_0, "OleThread could not terminate" ); 353*cdf0e10cSrcweir 354*cdf0e10cSrcweir if ( NULL != m_hOleThread ) 355*cdf0e10cSrcweir CloseHandle( m_hOleThread ); 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir if ( NULL != m_hEvtThrdReady ) 358*cdf0e10cSrcweir CloseHandle( m_hEvtThrdReady ); 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir if ( m_MtaOleReqWndClassAtom ) 361*cdf0e10cSrcweir UnregisterClassA( g_szWndClsName, NULL ); 362*cdf0e10cSrcweir 363*cdf0e10cSrcweir OSL_ENSURE( ( NULL == m_pfncClipViewerCallback ) && 364*cdf0e10cSrcweir !IsWindow( m_hwndNextClipViewer ), \ 365*cdf0e10cSrcweir "Clipboard viewer not properly unregistered" ); 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir //-------------------------------------------------------------------- 370*cdf0e10cSrcweir // 371*cdf0e10cSrcweir //-------------------------------------------------------------------- 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir HRESULT CMtaOleClipboard::flushClipboard( ) 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir if ( !WaitForThreadReady( ) ) 376*cdf0e10cSrcweir { 377*cdf0e10cSrcweir OSL_ENSURE( sal_False, "clipboard sta thread not ready" ); 378*cdf0e10cSrcweir return E_FAIL; 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, \ 382*cdf0e10cSrcweir "flushClipboard from within clipboard sta thread called" ); 383*cdf0e10cSrcweir 384*cdf0e10cSrcweir MsgCtx aMsgCtx; 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir postMessage( MSG_FLUSHCLIPBOARD, 387*cdf0e10cSrcweir static_cast< WPARAM >( 0 ), 388*cdf0e10cSrcweir reinterpret_cast< LPARAM >( &aMsgCtx ) ); 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir aMsgCtx.aCondition.wait( /* infinite */ ); 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir return aMsgCtx.hr; 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir //-------------------------------------------------------------------- 396*cdf0e10cSrcweir // 397*cdf0e10cSrcweir //-------------------------------------------------------------------- 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir HRESULT CMtaOleClipboard::getClipboard( IDataObject** ppIDataObject ) 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir OSL_PRECOND( NULL != ppIDataObject, "invalid parameter" ); 402*cdf0e10cSrcweir OSL_PRECOND( GetCurrentThreadId( ) != m_uOleThreadId, "getClipboard from within clipboard sta thread called" ); 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir if ( !WaitForThreadReady( ) ) 405*cdf0e10cSrcweir { 406*cdf0e10cSrcweir OSL_ENSURE( sal_False, "clipboard sta thread not ready" ); 407*cdf0e10cSrcweir return E_FAIL; 408*cdf0e10cSrcweir } 409*cdf0e10cSrcweir 410*cdf0e10cSrcweir CAutoComInit comAutoInit; 411*cdf0e10cSrcweir 412*cdf0e10cSrcweir LPSTREAM lpStream; 413*cdf0e10cSrcweir HRESULT hr = E_FAIL; 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir *ppIDataObject = NULL; 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir MsgCtx aMsgCtx; 418*cdf0e10cSrcweir 419*cdf0e10cSrcweir postMessage( MSG_GETCLIPBOARD, 420*cdf0e10cSrcweir reinterpret_cast< WPARAM >( &lpStream ), 421*cdf0e10cSrcweir reinterpret_cast< LPARAM >( &aMsgCtx ) ); 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir aMsgCtx.aCondition.wait( /* infinite */ ); 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir hr = aMsgCtx.hr; 426*cdf0e10cSrcweir 427*cdf0e10cSrcweir if ( SUCCEEDED( hr ) ) 428*cdf0e10cSrcweir { 429*cdf0e10cSrcweir hr = UnmarshalIDataObjectAndReleaseStream( lpStream, ppIDataObject ); 430*cdf0e10cSrcweir OSL_ENSURE( SUCCEEDED( hr ), "unmarshalling clipboard data object failed" ); 431*cdf0e10cSrcweir } 432*cdf0e10cSrcweir 433*cdf0e10cSrcweir return hr; 434*cdf0e10cSrcweir } 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir //-------------------------------------------------------------------- 437*cdf0e10cSrcweir // this is an asynchronous method that's why we don't wait until the 438*cdf0e10cSrcweir // request is completed 439*cdf0e10cSrcweir //-------------------------------------------------------------------- 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir HRESULT CMtaOleClipboard::setClipboard( IDataObject* pIDataObject ) 442*cdf0e10cSrcweir { 443*cdf0e10cSrcweir if ( !WaitForThreadReady( ) ) 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir OSL_ENSURE( sal_False, "clipboard sta thread not ready" ); 446*cdf0e10cSrcweir return E_FAIL; 447*cdf0e10cSrcweir } 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir CAutoComInit comAutoInit; 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "setClipboard from within the clipboard sta thread called" ); 452*cdf0e10cSrcweir 453*cdf0e10cSrcweir // because we marshall this request 454*cdf0e10cSrcweir // into the sta thread we better 455*cdf0e10cSrcweir // acquire the interface here so 456*cdf0e10cSrcweir // that the object will not be 457*cdf0e10cSrcweir // destroyed before the ole clipboard 458*cdf0e10cSrcweir // can acquire it 459*cdf0e10cSrcweir // remember: pIDataObject may be NULL 460*cdf0e10cSrcweir // which is an request to clear the 461*cdf0e10cSrcweir // current clipboard content 462*cdf0e10cSrcweir if ( pIDataObject ) 463*cdf0e10cSrcweir pIDataObject->AddRef( ); 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir postMessage( 466*cdf0e10cSrcweir MSG_SETCLIPBOARD, 467*cdf0e10cSrcweir reinterpret_cast< WPARAM >( pIDataObject ), 468*cdf0e10cSrcweir 0 ); 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir // because this is an asynchronous function 471*cdf0e10cSrcweir // the return value is useless 472*cdf0e10cSrcweir return S_OK; 473*cdf0e10cSrcweir } 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir //-------------------------------------------------------------------- 476*cdf0e10cSrcweir // register a clipboard viewer 477*cdf0e10cSrcweir //-------------------------------------------------------------------- 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir sal_Bool CMtaOleClipboard::registerClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback ) 480*cdf0e10cSrcweir { 481*cdf0e10cSrcweir if ( !WaitForThreadReady( ) ) 482*cdf0e10cSrcweir { 483*cdf0e10cSrcweir OSL_ENSURE( sal_False, "clipboard sta thread not ready" ); 484*cdf0e10cSrcweir return sal_False; 485*cdf0e10cSrcweir } 486*cdf0e10cSrcweir 487*cdf0e10cSrcweir sal_Bool bRet = sal_False; 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "registerClipViewer from within the OleThread called" ); 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir MsgCtx aMsgCtx; 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir postMessage( MSG_REGCLIPVIEWER, 494*cdf0e10cSrcweir reinterpret_cast<WPARAM>( pfncClipViewerCallback ), 495*cdf0e10cSrcweir reinterpret_cast<LPARAM>( &aMsgCtx ) ); 496*cdf0e10cSrcweir 497*cdf0e10cSrcweir aMsgCtx.aCondition.wait( /* infinite */ ); 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir return bRet; 500*cdf0e10cSrcweir } 501*cdf0e10cSrcweir 502*cdf0e10cSrcweir //-------------------------------------------------------------------- 503*cdf0e10cSrcweir // register a clipboard viewer 504*cdf0e10cSrcweir //-------------------------------------------------------------------- 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir sal_Bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback ) 507*cdf0e10cSrcweir { 508*cdf0e10cSrcweir sal_Bool bRet = sal_True; 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir // we need exclusive access because the clipboard changed notifier 511*cdf0e10cSrcweir // thread also accesses this variable 512*cdf0e10cSrcweir MutexGuard aGuard( m_pfncClipViewerCallbackMutex ); 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir // register if not yet done 515*cdf0e10cSrcweir if ( ( NULL != pfncClipViewerCallback ) && ( NULL == m_pfncClipViewerCallback ) ) 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir // SetClipboardViewer sends a WM_DRAWCLIPBOARD message we ignore 518*cdf0e10cSrcweir // this message if we register ourself as clip viewer 519*cdf0e10cSrcweir m_bInRegisterClipViewer = sal_True; 520*cdf0e10cSrcweir m_hwndNextClipViewer = SetClipboardViewer( m_hwndMtaOleReqWnd ); 521*cdf0e10cSrcweir m_bInRegisterClipViewer = sal_False; 522*cdf0e10cSrcweir 523*cdf0e10cSrcweir // if there is no other cb-viewer the 524*cdf0e10cSrcweir // return value is NULL!!! 525*cdf0e10cSrcweir bRet = IsWindow( m_hwndNextClipViewer ) ? sal_True : sal_False; 526*cdf0e10cSrcweir 527*cdf0e10cSrcweir // save the new callback function 528*cdf0e10cSrcweir m_pfncClipViewerCallback = pfncClipViewerCallback; 529*cdf0e10cSrcweir } 530*cdf0e10cSrcweir else if ( ( NULL == pfncClipViewerCallback ) && ( NULL != m_pfncClipViewerCallback ) ) 531*cdf0e10cSrcweir { 532*cdf0e10cSrcweir m_pfncClipViewerCallback = NULL; 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir // unregister if input parameter is NULL and we previously registered 535*cdf0e10cSrcweir // as clipboard viewer 536*cdf0e10cSrcweir ChangeClipboardChain( m_hwndMtaOleReqWnd, m_hwndNextClipViewer ); 537*cdf0e10cSrcweir m_hwndNextClipViewer = NULL; 538*cdf0e10cSrcweir } 539*cdf0e10cSrcweir 540*cdf0e10cSrcweir return bRet; 541*cdf0e10cSrcweir } 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir //-------------------------------------------------------------------- 544*cdf0e10cSrcweir // 545*cdf0e10cSrcweir //-------------------------------------------------------------------- 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir LRESULT CMtaOleClipboard::onSetClipboard( IDataObject* pIDataObject ) 548*cdf0e10cSrcweir { 549*cdf0e10cSrcweir return static_cast<LRESULT>( OleSetClipboard( pIDataObject ) ); 550*cdf0e10cSrcweir } 551*cdf0e10cSrcweir 552*cdf0e10cSrcweir //-------------------------------------------------------------------- 553*cdf0e10cSrcweir // 554*cdf0e10cSrcweir //-------------------------------------------------------------------- 555*cdf0e10cSrcweir 556*cdf0e10cSrcweir LRESULT CMtaOleClipboard::onGetClipboard( LPSTREAM* ppStream ) 557*cdf0e10cSrcweir { 558*cdf0e10cSrcweir OSL_ASSERT(NULL != ppStream); 559*cdf0e10cSrcweir 560*cdf0e10cSrcweir IDataObjectPtr pIDataObject; 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir // forward the request to the OleClipboard 563*cdf0e10cSrcweir HRESULT hr = OleGetClipboard( &pIDataObject ); 564*cdf0e10cSrcweir if ( SUCCEEDED( hr ) ) 565*cdf0e10cSrcweir { 566*cdf0e10cSrcweir hr = MarshalIDataObjectInStream(pIDataObject.get(), ppStream); 567*cdf0e10cSrcweir OSL_ENSURE(SUCCEEDED(hr), "marshalling cliboard data object failed"); 568*cdf0e10cSrcweir } 569*cdf0e10cSrcweir return static_cast<LRESULT>(hr); 570*cdf0e10cSrcweir } 571*cdf0e10cSrcweir 572*cdf0e10cSrcweir //-------------------------------------------------------------------- 573*cdf0e10cSrcweir // flush the ole-clipboard 574*cdf0e10cSrcweir //-------------------------------------------------------------------- 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir LRESULT CMtaOleClipboard::onFlushClipboard( ) 577*cdf0e10cSrcweir { 578*cdf0e10cSrcweir return static_cast<LRESULT>( OleFlushClipboard( ) ); 579*cdf0e10cSrcweir } 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir //-------------------------------------------------------------------- 582*cdf0e10cSrcweir // handle clipboard chain change event 583*cdf0e10cSrcweir //-------------------------------------------------------------------- 584*cdf0e10cSrcweir 585*cdf0e10cSrcweir LRESULT CMtaOleClipboard::onChangeCBChain( HWND hWndRemove, HWND hWndNext ) 586*cdf0e10cSrcweir { 587*cdf0e10cSrcweir if ( hWndRemove == m_hwndNextClipViewer ) 588*cdf0e10cSrcweir m_hwndNextClipViewer = hWndNext; 589*cdf0e10cSrcweir else if ( IsWindow( m_hwndNextClipViewer ) ) 590*cdf0e10cSrcweir { 591*cdf0e10cSrcweir // forward the message to the next one 592*cdf0e10cSrcweir DWORD dwResult; 593*cdf0e10cSrcweir SendMessageTimeoutA( 594*cdf0e10cSrcweir m_hwndNextClipViewer, 595*cdf0e10cSrcweir WM_CHANGECBCHAIN, 596*cdf0e10cSrcweir reinterpret_cast<WPARAM>(hWndRemove), 597*cdf0e10cSrcweir reinterpret_cast<LPARAM>(hWndNext), 598*cdf0e10cSrcweir SMTO_BLOCK, 599*cdf0e10cSrcweir MAX_CLIPEVENT_PROCESSING_TIME, 600*cdf0e10cSrcweir &dwResult ); 601*cdf0e10cSrcweir } 602*cdf0e10cSrcweir 603*cdf0e10cSrcweir return 0; 604*cdf0e10cSrcweir } 605*cdf0e10cSrcweir 606*cdf0e10cSrcweir //-------------------------------------------------------------------- 607*cdf0e10cSrcweir // handle draw clipboard event 608*cdf0e10cSrcweir //-------------------------------------------------------------------- 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir LRESULT CMtaOleClipboard::onDrawClipboard( ) 611*cdf0e10cSrcweir { 612*cdf0e10cSrcweir // we don't send a notification if we are 613*cdf0e10cSrcweir // registering ourself as clipboard 614*cdf0e10cSrcweir if ( !m_bInRegisterClipViewer ) 615*cdf0e10cSrcweir { 616*cdf0e10cSrcweir ClearableMutexGuard aGuard( m_ClipboardChangedEventCountMutex ); 617*cdf0e10cSrcweir 618*cdf0e10cSrcweir m_ClipboardChangedEventCount++; 619*cdf0e10cSrcweir SetEvent( m_hClipboardChangedEvent ); 620*cdf0e10cSrcweir 621*cdf0e10cSrcweir aGuard.clear( ); 622*cdf0e10cSrcweir } 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir // foward the message to the next viewer in the chain 625*cdf0e10cSrcweir if ( IsWindow( m_hwndNextClipViewer ) ) 626*cdf0e10cSrcweir { 627*cdf0e10cSrcweir DWORD dwResult; 628*cdf0e10cSrcweir SendMessageTimeoutA( 629*cdf0e10cSrcweir m_hwndNextClipViewer, 630*cdf0e10cSrcweir WM_DRAWCLIPBOARD, 631*cdf0e10cSrcweir static_cast< WPARAM >( 0 ), 632*cdf0e10cSrcweir static_cast< LPARAM >( 0 ), 633*cdf0e10cSrcweir SMTO_BLOCK, 634*cdf0e10cSrcweir MAX_CLIPEVENT_PROCESSING_TIME, 635*cdf0e10cSrcweir &dwResult ); 636*cdf0e10cSrcweir } 637*cdf0e10cSrcweir 638*cdf0e10cSrcweir return 0; 639*cdf0e10cSrcweir } 640*cdf0e10cSrcweir 641*cdf0e10cSrcweir //-------------------------------------------------------------------- 642*cdf0e10cSrcweir // SendMessage so we don't need to supply the HWND if we send 643*cdf0e10cSrcweir // something to our wrapped window 644*cdf0e10cSrcweir //-------------------------------------------------------------------- 645*cdf0e10cSrcweir 646*cdf0e10cSrcweir LRESULT CMtaOleClipboard::sendMessage( UINT msg, WPARAM wParam, LPARAM lParam ) 647*cdf0e10cSrcweir { 648*cdf0e10cSrcweir return ::SendMessageA( m_hwndMtaOleReqWnd, msg, wParam, lParam ); 649*cdf0e10cSrcweir } 650*cdf0e10cSrcweir 651*cdf0e10cSrcweir //-------------------------------------------------------------------- 652*cdf0e10cSrcweir // PostMessage so we don't need to supply the HWND if we send 653*cdf0e10cSrcweir // something to our wrapped window 654*cdf0e10cSrcweir //-------------------------------------------------------------------- 655*cdf0e10cSrcweir 656*cdf0e10cSrcweir sal_Bool CMtaOleClipboard::postMessage( UINT msg, WPARAM wParam, LPARAM lParam ) 657*cdf0e10cSrcweir { 658*cdf0e10cSrcweir return PostMessageA( m_hwndMtaOleReqWnd, msg, wParam, lParam ) ? sal_True : sal_False; 659*cdf0e10cSrcweir } 660*cdf0e10cSrcweir 661*cdf0e10cSrcweir 662*cdf0e10cSrcweir //-------------------------------------------------------------------- 663*cdf0e10cSrcweir // the window proc 664*cdf0e10cSrcweir //-------------------------------------------------------------------- 665*cdf0e10cSrcweir 666*cdf0e10cSrcweir LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 667*cdf0e10cSrcweir { 668*cdf0e10cSrcweir LRESULT lResult = 0; 669*cdf0e10cSrcweir 670*cdf0e10cSrcweir // get a connection to the class-instance via the static member 671*cdf0e10cSrcweir CMtaOleClipboard* pImpl = CMtaOleClipboard::s_theMtaOleClipboardInst; 672*cdf0e10cSrcweir OSL_ASSERT( NULL != pImpl ); 673*cdf0e10cSrcweir 674*cdf0e10cSrcweir switch( uMsg ) 675*cdf0e10cSrcweir { 676*cdf0e10cSrcweir case MSG_SETCLIPBOARD: 677*cdf0e10cSrcweir { 678*cdf0e10cSrcweir IDataObject* pIDataObject = reinterpret_cast< IDataObject* >( wParam ); 679*cdf0e10cSrcweir pImpl->onSetClipboard( pIDataObject ); 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir // in setClipboard we did acquire the 682*cdf0e10cSrcweir // interface pointer in order to prevent 683*cdf0e10cSrcweir // destruction of the object before the 684*cdf0e10cSrcweir // ole clipboard can acquire the interface 685*cdf0e10cSrcweir // now we release the interface so that 686*cdf0e10cSrcweir // our lostOwnership mechanism works 687*cdf0e10cSrcweir // remember: pIDataObject may be NULL 688*cdf0e10cSrcweir if ( pIDataObject ) 689*cdf0e10cSrcweir pIDataObject->Release( ); 690*cdf0e10cSrcweir } 691*cdf0e10cSrcweir break; 692*cdf0e10cSrcweir 693*cdf0e10cSrcweir case MSG_GETCLIPBOARD: 694*cdf0e10cSrcweir { 695*cdf0e10cSrcweir MsgCtx* aMsgCtx = reinterpret_cast< MsgCtx* >( lParam ); 696*cdf0e10cSrcweir OSL_ASSERT( aMsgCtx ); 697*cdf0e10cSrcweir 698*cdf0e10cSrcweir aMsgCtx->hr = pImpl->onGetClipboard( reinterpret_cast< LPSTREAM* >(wParam) ); 699*cdf0e10cSrcweir aMsgCtx->aCondition.set( ); 700*cdf0e10cSrcweir } 701*cdf0e10cSrcweir break; 702*cdf0e10cSrcweir 703*cdf0e10cSrcweir case MSG_FLUSHCLIPBOARD: 704*cdf0e10cSrcweir { 705*cdf0e10cSrcweir MsgCtx* aMsgCtx = reinterpret_cast< MsgCtx* >( lParam ); 706*cdf0e10cSrcweir OSL_ASSERT( aMsgCtx ); 707*cdf0e10cSrcweir 708*cdf0e10cSrcweir aMsgCtx->hr = pImpl->onFlushClipboard( ); 709*cdf0e10cSrcweir aMsgCtx->aCondition.set( ); 710*cdf0e10cSrcweir } 711*cdf0e10cSrcweir break; 712*cdf0e10cSrcweir 713*cdf0e10cSrcweir case MSG_REGCLIPVIEWER: 714*cdf0e10cSrcweir { 715*cdf0e10cSrcweir MsgCtx* aMsgCtx = reinterpret_cast< MsgCtx* >( lParam ); 716*cdf0e10cSrcweir OSL_ASSERT( aMsgCtx ); 717*cdf0e10cSrcweir 718*cdf0e10cSrcweir pImpl->onRegisterClipViewer( reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t>(wParam) ); 719*cdf0e10cSrcweir aMsgCtx->aCondition.set( ); 720*cdf0e10cSrcweir } 721*cdf0e10cSrcweir break; 722*cdf0e10cSrcweir 723*cdf0e10cSrcweir case WM_CHANGECBCHAIN: 724*cdf0e10cSrcweir lResult = pImpl->onChangeCBChain( 725*cdf0e10cSrcweir reinterpret_cast< HWND >( wParam ), reinterpret_cast< HWND >( lParam ) ); 726*cdf0e10cSrcweir break; 727*cdf0e10cSrcweir 728*cdf0e10cSrcweir case WM_DRAWCLIPBOARD: 729*cdf0e10cSrcweir lResult = pImpl->onDrawClipboard( ); 730*cdf0e10cSrcweir break; 731*cdf0e10cSrcweir 732*cdf0e10cSrcweir case MSG_SHUTDOWN: 733*cdf0e10cSrcweir DestroyWindow( pImpl->m_hwndMtaOleReqWnd ); 734*cdf0e10cSrcweir break; 735*cdf0e10cSrcweir 736*cdf0e10cSrcweir // force the sta thread to end 737*cdf0e10cSrcweir case WM_DESTROY: 738*cdf0e10cSrcweir PostQuitMessage( 0 ); 739*cdf0e10cSrcweir break; 740*cdf0e10cSrcweir 741*cdf0e10cSrcweir default: 742*cdf0e10cSrcweir lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam ); 743*cdf0e10cSrcweir break; 744*cdf0e10cSrcweir } 745*cdf0e10cSrcweir 746*cdf0e10cSrcweir return lResult; 747*cdf0e10cSrcweir } 748*cdf0e10cSrcweir 749*cdf0e10cSrcweir //-------------------------------------------------------------------- 750*cdf0e10cSrcweir // 751*cdf0e10cSrcweir //-------------------------------------------------------------------- 752*cdf0e10cSrcweir 753*cdf0e10cSrcweir void CMtaOleClipboard::createMtaOleReqWnd( ) 754*cdf0e10cSrcweir { 755*cdf0e10cSrcweir WNDCLASSEXA wcex; 756*cdf0e10cSrcweir 757*cdf0e10cSrcweir HINSTANCE hInst = GetModuleHandleA( CLIPSRV_DLL_NAME ); 758*cdf0e10cSrcweir OSL_ENSURE( NULL != hInst, "The name of the clipboard service dll must have changed" ); 759*cdf0e10cSrcweir 760*cdf0e10cSrcweir ZeroMemory( &wcex, sizeof( WNDCLASSEXA ) ); 761*cdf0e10cSrcweir 762*cdf0e10cSrcweir wcex.cbSize = sizeof(WNDCLASSEXA); 763*cdf0e10cSrcweir wcex.style = 0; 764*cdf0e10cSrcweir wcex.lpfnWndProc = static_cast< WNDPROC >( CMtaOleClipboard::mtaOleReqWndProc ); 765*cdf0e10cSrcweir wcex.cbClsExtra = 0; 766*cdf0e10cSrcweir wcex.cbWndExtra = 0; 767*cdf0e10cSrcweir wcex.hInstance = hInst; 768*cdf0e10cSrcweir wcex.hIcon = NULL; 769*cdf0e10cSrcweir wcex.hCursor = NULL; 770*cdf0e10cSrcweir wcex.hbrBackground = NULL; 771*cdf0e10cSrcweir wcex.lpszMenuName = NULL; 772*cdf0e10cSrcweir wcex.lpszClassName = g_szWndClsName; 773*cdf0e10cSrcweir wcex.hIconSm = NULL; 774*cdf0e10cSrcweir 775*cdf0e10cSrcweir m_MtaOleReqWndClassAtom = RegisterClassExA( &wcex ); 776*cdf0e10cSrcweir 777*cdf0e10cSrcweir if ( 0 != m_MtaOleReqWndClassAtom ) 778*cdf0e10cSrcweir m_hwndMtaOleReqWnd = CreateWindowA( 779*cdf0e10cSrcweir g_szWndClsName, NULL, 0, 0, 0, 0, 0, NULL, NULL, hInst, NULL ); 780*cdf0e10cSrcweir } 781*cdf0e10cSrcweir 782*cdf0e10cSrcweir //-------------------------------------------------------------------- 783*cdf0e10cSrcweir // 784*cdf0e10cSrcweir //-------------------------------------------------------------------- 785*cdf0e10cSrcweir 786*cdf0e10cSrcweir unsigned int CMtaOleClipboard::run( ) 787*cdf0e10cSrcweir { 788*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 789*cdf0e10cSrcweir HRESULT hr = 790*cdf0e10cSrcweir #endif 791*cdf0e10cSrcweir OleInitialize( NULL ); 792*cdf0e10cSrcweir OSL_ASSERT( SUCCEEDED( hr ) ); 793*cdf0e10cSrcweir 794*cdf0e10cSrcweir createMtaOleReqWnd( ); 795*cdf0e10cSrcweir 796*cdf0e10cSrcweir unsigned int nRet; 797*cdf0e10cSrcweir 798*cdf0e10cSrcweir if ( IsWindow( m_hwndMtaOleReqWnd ) ) 799*cdf0e10cSrcweir { 800*cdf0e10cSrcweir if ( NULL != m_hEvtThrdReady ) 801*cdf0e10cSrcweir SetEvent( m_hEvtThrdReady ); 802*cdf0e10cSrcweir 803*cdf0e10cSrcweir // pumping messages 804*cdf0e10cSrcweir MSG msg; 805*cdf0e10cSrcweir while( GetMessageA( &msg, NULL, 0, 0 ) ) 806*cdf0e10cSrcweir DispatchMessageA( &msg ); 807*cdf0e10cSrcweir 808*cdf0e10cSrcweir nRet = 0; 809*cdf0e10cSrcweir } 810*cdf0e10cSrcweir else 811*cdf0e10cSrcweir nRet = ~0U; 812*cdf0e10cSrcweir 813*cdf0e10cSrcweir OleUninitialize( ); 814*cdf0e10cSrcweir 815*cdf0e10cSrcweir return nRet; 816*cdf0e10cSrcweir } 817*cdf0e10cSrcweir 818*cdf0e10cSrcweir //-------------------------------------------------------------------- 819*cdf0e10cSrcweir // 820*cdf0e10cSrcweir //-------------------------------------------------------------------- 821*cdf0e10cSrcweir 822*cdf0e10cSrcweir unsigned int WINAPI CMtaOleClipboard::oleThreadProc( LPVOID pParam ) 823*cdf0e10cSrcweir { 824*cdf0e10cSrcweir CMtaOleClipboard* pInst = 825*cdf0e10cSrcweir reinterpret_cast<CMtaOleClipboard*>( pParam ); 826*cdf0e10cSrcweir OSL_ASSERT( NULL != pInst ); 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir return pInst->run( ); 829*cdf0e10cSrcweir } 830*cdf0e10cSrcweir 831*cdf0e10cSrcweir //-------------------------------------------------------------------- 832*cdf0e10cSrcweir // 833*cdf0e10cSrcweir //-------------------------------------------------------------------- 834*cdf0e10cSrcweir 835*cdf0e10cSrcweir unsigned int WINAPI CMtaOleClipboard::clipboardChangedNotifierThreadProc( LPVOID pParam ) 836*cdf0e10cSrcweir { 837*cdf0e10cSrcweir CMtaOleClipboard* pInst = reinterpret_cast< CMtaOleClipboard* >( pParam ); 838*cdf0e10cSrcweir OSL_ASSERT( NULL != pInst ); 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir CoInitialize( NULL ); 841*cdf0e10cSrcweir 842*cdf0e10cSrcweir // assuming we don't need a lock for 843*cdf0e10cSrcweir // a boolean variable like m_bRun... 844*cdf0e10cSrcweir while ( pInst->m_bRunClipboardNotifierThread ) 845*cdf0e10cSrcweir { 846*cdf0e10cSrcweir // wait for clipboard changed or terminate event 847*cdf0e10cSrcweir WaitForMultipleObjects( 2, pInst->m_hClipboardChangedNotifierEvents, false, INFINITE ); 848*cdf0e10cSrcweir 849*cdf0e10cSrcweir ClearableMutexGuard aGuard( pInst->m_ClipboardChangedEventCountMutex ); 850*cdf0e10cSrcweir 851*cdf0e10cSrcweir if ( pInst->m_ClipboardChangedEventCount > 0 ) 852*cdf0e10cSrcweir { 853*cdf0e10cSrcweir pInst->m_ClipboardChangedEventCount--; 854*cdf0e10cSrcweir if ( 0 == pInst->m_ClipboardChangedEventCount ) 855*cdf0e10cSrcweir ResetEvent( pInst->m_hClipboardChangedEvent ); 856*cdf0e10cSrcweir 857*cdf0e10cSrcweir aGuard.clear( ); 858*cdf0e10cSrcweir 859*cdf0e10cSrcweir // nobody should touch m_pfncClipViewerCallback while we do 860*cdf0e10cSrcweir MutexGuard aClipViewerGuard( pInst->m_pfncClipViewerCallbackMutex ); 861*cdf0e10cSrcweir 862*cdf0e10cSrcweir // notify all clipboard listener 863*cdf0e10cSrcweir if ( pInst->m_pfncClipViewerCallback ) 864*cdf0e10cSrcweir pInst->m_pfncClipViewerCallback( ); 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir else 867*cdf0e10cSrcweir aGuard.clear( ); 868*cdf0e10cSrcweir } 869*cdf0e10cSrcweir 870*cdf0e10cSrcweir CoUninitialize( ); 871*cdf0e10cSrcweir 872*cdf0e10cSrcweir return ( 0 ); 873*cdf0e10cSrcweir } 874*cdf0e10cSrcweir 875*cdf0e10cSrcweir //-------------------------------------------------------------------- 876*cdf0e10cSrcweir // 877*cdf0e10cSrcweir //-------------------------------------------------------------------- 878*cdf0e10cSrcweir 879*cdf0e10cSrcweir inline 880*cdf0e10cSrcweir sal_Bool CMtaOleClipboard::WaitForThreadReady( ) const 881*cdf0e10cSrcweir { 882*cdf0e10cSrcweir sal_Bool bRet = sal_False; 883*cdf0e10cSrcweir 884*cdf0e10cSrcweir if ( NULL != m_hEvtThrdReady ) 885*cdf0e10cSrcweir { 886*cdf0e10cSrcweir DWORD dwResult = WaitForSingleObject( 887*cdf0e10cSrcweir m_hEvtThrdReady, MAX_WAITTIME ); 888*cdf0e10cSrcweir bRet = ( dwResult == WAIT_OBJECT_0 ); 889*cdf0e10cSrcweir } 890*cdf0e10cSrcweir 891*cdf0e10cSrcweir return bRet; 892*cdf0e10cSrcweir } 893*cdf0e10cSrcweir 894