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