fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / dtrans / source / win32 / clipb / MtaOleClipb.cxx
blob99ca9991ea13666aaab1cfc752e54e3484384008
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 MtaOleClipb.cxx - documentation
23 This class setup a single threaded apartment (sta) thread to deal with
24 the ole clipboard, which runs only in an sta thread.
25 The consequence is that callback from the ole clipboard are in the
26 context of this sta thread. In the soffice applications this may lead
27 to problems because they all use the one and only mutex called
28 SolarMutex.
29 In order to transfer clipboard requests to our sta thread we use a
30 hidden window an forward these requests via window messages.
33 #ifdef _MSC_VER
34 #pragma warning( disable : 4786 ) // identifier was truncated to 'number'
35 // characters in the debug information
36 #endif
38 //#define UNICODE
39 #include <osl/diagnose.h>
41 #include "MtaOleClipb.hxx"
42 #include <osl/conditn.hxx>
43 #include <osl/thread.h>
45 #include <wchar.h>
46 #include <process.h>
48 #include <systools/win32/comtools.hxx>
49 #ifdef __MINGW32__
50 #if defined __uuidof
51 #undef __uuidof
52 #endif
53 #define __uuidof(I) IID_##I
54 #endif
56 // namespace directives
58 using osl::Condition;
59 using osl::Mutex;
60 using osl::MutexGuard;
61 using osl::ClearableMutexGuard;
63 namespace /* private */
65 char CLIPSRV_DLL_NAME[] = "sysdtrans.dll";
66 char g_szWndClsName[] = "MtaOleReqWnd###";
68 // messages constants
70 const sal_uInt32 MSG_SETCLIPBOARD = WM_USER + 0x0001;
71 const sal_uInt32 MSG_GETCLIPBOARD = WM_USER + 0x0002;
72 const sal_uInt32 MSG_REGCLIPVIEWER = WM_USER + 0x0003;
73 const sal_uInt32 MSG_FLUSHCLIPBOARD = WM_USER + 0x0004;
74 const sal_uInt32 MSG_SHUTDOWN = WM_USER + 0x0005;
76 const sal_uInt32 MAX_WAITTIME = 10000; // msec
77 const sal_uInt32 MAX_WAIT_SHUTDOWN = 10000; // msec
78 const sal_uInt32 MAX_CLIPEVENT_PROCESSING_TIME = 5000; // msec
80 const sal_Bool MANUAL_RESET = sal_True;
81 const sal_Bool AUTO_RESET = sal_False;
82 const sal_Bool INIT_NONSIGNALED = sal_False;
84 /* Cannot use osl conditions because they are blocking
85 without waking up on messages sent by another thread
86 this leads to deadlocks because we are blocking the
87 communication between inter-thread marshalled COM
88 pointers.
89 COM Proxy-Stub communication uses SendMessages for
90 synchronization purposes.
92 class Win32Condition
94 public:
95 // ctor
96 Win32Condition()
98 m_hEvent = CreateEvent(
99 0, /* no security */
100 true, /* manual reset */
101 false, /* initial state not signaled */
102 0); /* automatic name */
105 // dtor
106 ~Win32Condition()
108 CloseHandle(m_hEvent);
111 // wait infinite for event be signaled
112 // leave messages sent through
113 void wait()
115 while(1)
117 DWORD dwResult =
118 MsgWaitForMultipleObjects(1, &m_hEvent, FALSE, INFINITE, QS_SENDMESSAGE);
120 switch (dwResult)
122 case WAIT_OBJECT_0:
123 return;
125 case WAIT_OBJECT_0 + 1:
127 /* PeekMessage processes all messages in the SendMessage
128 queue that's what we want, messages from the PostMessage
129 queue stay untouched */
130 MSG msg;
131 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
133 break;
139 // reset the event
140 void set()
142 SetEvent(m_hEvent);
145 private:
146 HANDLE m_hEvent;
148 // prevent copy/assignment
149 private:
150 Win32Condition(const Win32Condition&);
151 Win32Condition& operator=(const Win32Condition&);
154 // we use one condition for every request
156 struct MsgCtx
158 Win32Condition aCondition;
159 HRESULT hr;
162 } /* namespace private */
164 // static member initialization
166 CMtaOleClipboard* CMtaOleClipboard::s_theMtaOleClipboardInst = NULL;
168 // marshal an IDataObject
170 //inline
171 HRESULT MarshalIDataObjectInStream( IDataObject* pIDataObject, LPSTREAM* ppStream )
173 OSL_ASSERT( NULL != pIDataObject );
174 OSL_ASSERT( NULL != ppStream );
176 *ppStream = NULL;
177 return CoMarshalInterThreadInterfaceInStream(
178 __uuidof(IDataObject), //The IID of interface to be marshaled
179 pIDataObject, //The interface pointer
180 ppStream //IStream pointer
184 // unmarshal an IDataObject
186 //inline
187 HRESULT UnmarshalIDataObjectAndReleaseStream( LPSTREAM lpStream, IDataObject** ppIDataObject )
189 OSL_ASSERT( NULL != lpStream );
190 OSL_ASSERT( NULL != ppIDataObject );
192 *ppIDataObject = NULL;
193 return CoGetInterfaceAndReleaseStream(
194 lpStream,
195 __uuidof(IDataObject),
196 reinterpret_cast<LPVOID*>(ppIDataObject));
199 // helper class to ensure that the calling thread has com initialized
201 class CAutoComInit
203 public:
204 CAutoComInit( )
207 to be safe we call CoInitialize
208 although it is not necessary if
209 the calling thread was created
210 using osl_CreateThread because
211 this function calls CoInitialize
212 for every thread it creates
214 m_hResult = CoInitialize( NULL );
216 if ( S_OK == m_hResult )
217 OSL_FAIL( \
218 "com was not yet initialzed, the thread was not created using osl_createThread" );
219 else if ( FAILED( m_hResult ) && !( RPC_E_CHANGED_MODE == m_hResult ) )
220 OSL_FAIL( \
221 "com could not be initialized, maybe the thread was not created using osl_createThread" );
224 ~CAutoComInit( )
227 we only call CoUninitialize when
228 CoInitailize returned S_FALSE, what
229 means that com was already initialize
230 for that thread so we keep the balance
231 if CoInitialize returned S_OK what means
232 com was not yet initialized we better
233 let com initialized or we may run into
234 the realm of undefined behaviour
236 if ( m_hResult == S_FALSE )
237 CoUninitialize( );
240 private:
241 HRESULT m_hResult;
244 // ctor
246 CMtaOleClipboard::CMtaOleClipboard( ) :
247 m_hOleThread( NULL ),
248 m_uOleThreadId( 0 ),
249 m_hEvtThrdReady( NULL ),
250 m_hwndMtaOleReqWnd( NULL ),
251 m_MtaOleReqWndClassAtom( 0 ),
252 m_hwndNextClipViewer( NULL ),
253 m_pfncClipViewerCallback( NULL ),
254 m_bRunClipboardNotifierThread( true ),
255 m_hClipboardChangedEvent( m_hClipboardChangedNotifierEvents[0] ),
256 m_hTerminateClipboardChangedNotifierEvent( m_hClipboardChangedNotifierEvents[1] ),
257 m_ClipboardChangedEventCount( 0 )
259 // signals that the thread was successfully setup
260 m_hEvtThrdReady = CreateEventA( 0, MANUAL_RESET, INIT_NONSIGNALED, NULL );
262 OSL_ASSERT( NULL != m_hEvtThrdReady );
264 s_theMtaOleClipboardInst = this;
266 m_hOleThread = (HANDLE)_beginthreadex(
267 NULL, 0, CMtaOleClipboard::oleThreadProc, this, 0, &m_uOleThreadId );
268 OSL_ASSERT( NULL != m_hOleThread );
270 // setup the clipboard changed notifier thread
272 m_hClipboardChangedNotifierEvents[0] = CreateEventA( 0, MANUAL_RESET, INIT_NONSIGNALED, NULL );
273 OSL_ASSERT( NULL != m_hClipboardChangedNotifierEvents[0] );
275 m_hClipboardChangedNotifierEvents[1] = CreateEventA( 0, MANUAL_RESET, INIT_NONSIGNALED, NULL );
276 OSL_ASSERT( NULL != m_hClipboardChangedNotifierEvents[1] );
278 unsigned uThreadId;
279 m_hClipboardChangedNotifierThread = (HANDLE)_beginthreadex(
280 NULL, 0, CMtaOleClipboard::clipboardChangedNotifierThreadProc, this, 0, &uThreadId );
282 OSL_ASSERT( NULL != m_hClipboardChangedNotifierThread );
285 // dtor
287 CMtaOleClipboard::~CMtaOleClipboard( )
289 // block calling threads out
290 if ( NULL != m_hEvtThrdReady )
291 ResetEvent( m_hEvtThrdReady );
293 // terminate the clipboard changed notifier thread
294 m_bRunClipboardNotifierThread = false;
295 SetEvent( m_hTerminateClipboardChangedNotifierEvent );
297 sal_uInt32 dwResult = WaitForSingleObject(
298 m_hClipboardChangedNotifierThread, MAX_WAIT_SHUTDOWN );
300 (void) dwResult;
301 OSL_ENSURE( dwResult == WAIT_OBJECT_0, "clipboard notifier thread could not terminate" );
303 if ( NULL != m_hClipboardChangedNotifierThread )
304 CloseHandle( m_hClipboardChangedNotifierThread );
306 if ( NULL != m_hClipboardChangedNotifierEvents[0] )
307 CloseHandle( m_hClipboardChangedNotifierEvents[0] );
309 if ( NULL != m_hClipboardChangedNotifierEvents[1] )
310 CloseHandle( m_hClipboardChangedNotifierEvents[1] );
312 // end the thread
313 // because DestroyWindow can only be called
314 // from within the thread that created the window
315 sendMessage( MSG_SHUTDOWN,
316 static_cast< WPARAM >( 0 ),
317 static_cast< LPARAM >( 0 ) );
319 // wait for thread shutdown
320 dwResult = WaitForSingleObject( m_hOleThread, MAX_WAIT_SHUTDOWN );
321 OSL_ENSURE( dwResult == WAIT_OBJECT_0, "OleThread could not terminate" );
323 if ( NULL != m_hOleThread )
324 CloseHandle( m_hOleThread );
326 if ( NULL != m_hEvtThrdReady )
327 CloseHandle( m_hEvtThrdReady );
329 if ( m_MtaOleReqWndClassAtom )
330 UnregisterClassA( g_szWndClsName, NULL );
332 OSL_ENSURE( ( NULL == m_pfncClipViewerCallback ) &&
333 !IsWindow( m_hwndNextClipViewer ), \
334 "Clipboard viewer not properly unregistered" );
337 HRESULT CMtaOleClipboard::flushClipboard( )
339 if ( !WaitForThreadReady( ) )
341 OSL_FAIL( "clipboard sta thread not ready" );
342 return E_FAIL;
345 OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, \
346 "flushClipboard from within clipboard sta thread called" );
348 MsgCtx aMsgCtx;
350 postMessage( MSG_FLUSHCLIPBOARD,
351 static_cast< WPARAM >( 0 ),
352 reinterpret_cast< LPARAM >( &aMsgCtx ) );
354 aMsgCtx.aCondition.wait( /* infinite */ );
356 return aMsgCtx.hr;
359 HRESULT CMtaOleClipboard::getClipboard( IDataObject** ppIDataObject )
361 OSL_PRECOND( NULL != ppIDataObject, "invalid parameter" );
362 OSL_PRECOND( GetCurrentThreadId( ) != m_uOleThreadId, "getClipboard from within clipboard sta thread called" );
364 if ( !WaitForThreadReady( ) )
366 OSL_FAIL( "clipboard sta thread not ready" );
367 return E_FAIL;
370 CAutoComInit comAutoInit;
372 LPSTREAM lpStream;
374 *ppIDataObject = NULL;
376 MsgCtx aMsgCtx;
378 postMessage( MSG_GETCLIPBOARD,
379 reinterpret_cast< WPARAM >( &lpStream ),
380 reinterpret_cast< LPARAM >( &aMsgCtx ) );
382 aMsgCtx.aCondition.wait( /* infinite */ );
384 HRESULT hr = aMsgCtx.hr;
386 if ( SUCCEEDED( hr ) )
388 hr = UnmarshalIDataObjectAndReleaseStream( lpStream, ppIDataObject );
389 OSL_ENSURE( SUCCEEDED( hr ), "unmarshalling clipboard data object failed" );
392 return hr;
395 // this is an asynchronous method that's why we don't wait until the
396 // request is completed
398 HRESULT CMtaOleClipboard::setClipboard( IDataObject* pIDataObject )
400 if ( !WaitForThreadReady( ) )
402 OSL_FAIL( "clipboard sta thread not ready" );
403 return E_FAIL;
406 CAutoComInit comAutoInit;
408 OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "setClipboard from within the clipboard sta thread called" );
410 // because we marshall this request
411 // into the sta thread we better
412 // acquire the interface here so
413 // that the object will not be
414 // destroyed before the ole clipboard
415 // can acquire it
416 // remember: pIDataObject may be NULL
417 // which is an request to clear the
418 // current clipboard content
419 if ( pIDataObject )
420 pIDataObject->AddRef( );
422 postMessage(
423 MSG_SETCLIPBOARD,
424 reinterpret_cast< WPARAM >( pIDataObject ),
425 0 );
427 // because this is an asynchronous function
428 // the return value is useless
429 return S_OK;
432 // register a clipboard viewer
434 bool CMtaOleClipboard::registerClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback )
436 if ( !WaitForThreadReady( ) )
438 OSL_FAIL( "clipboard sta thread not ready" );
439 return false;
442 bool bRet = false;
444 OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "registerClipViewer from within the OleThread called" );
446 MsgCtx aMsgCtx;
448 postMessage( MSG_REGCLIPVIEWER,
449 reinterpret_cast<WPARAM>( pfncClipViewerCallback ),
450 reinterpret_cast<LPARAM>( &aMsgCtx ) );
452 aMsgCtx.aCondition.wait( /* infinite */ );
454 return bRet;
457 // register a clipboard viewer
459 bool CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback )
461 bool bRet = true;
463 // we need exclusive access because the clipboard changed notifier
464 // thread also accesses this variable
465 MutexGuard aGuard( m_pfncClipViewerCallbackMutex );
467 // register if not yet done
468 if ( ( NULL != pfncClipViewerCallback ) && ( NULL == m_pfncClipViewerCallback ) )
470 // SetClipboardViewer sends a WM_DRAWCLIPBOARD message we ignore
471 // this message if we register ourself as clip viewer
472 m_bInRegisterClipViewer = true;
473 m_hwndNextClipViewer = SetClipboardViewer( m_hwndMtaOleReqWnd );
474 m_bInRegisterClipViewer = false;
476 // if there is no other cb-viewer the
477 // return value is NULL!!!
478 bRet = IsWindow( m_hwndNextClipViewer ) ? true : false;
480 // save the new callback function
481 m_pfncClipViewerCallback = pfncClipViewerCallback;
483 else if ( ( NULL == pfncClipViewerCallback ) && ( NULL != m_pfncClipViewerCallback ) )
485 m_pfncClipViewerCallback = NULL;
487 // unregister if input parameter is NULL and we previously registered
488 // as clipboard viewer
489 ChangeClipboardChain( m_hwndMtaOleReqWnd, m_hwndNextClipViewer );
490 m_hwndNextClipViewer = NULL;
493 return bRet;
496 LRESULT CMtaOleClipboard::onSetClipboard( IDataObject* pIDataObject )
498 return static_cast<LRESULT>( OleSetClipboard( pIDataObject ) );
501 LRESULT CMtaOleClipboard::onGetClipboard( LPSTREAM* ppStream )
503 OSL_ASSERT(NULL != ppStream);
505 IDataObjectPtr pIDataObject;
507 // forward the request to the OleClipboard
508 HRESULT hr = OleGetClipboard( &pIDataObject );
509 if ( SUCCEEDED( hr ) )
511 hr = MarshalIDataObjectInStream(pIDataObject.get(), ppStream);
512 OSL_ENSURE(SUCCEEDED(hr), "marshalling cliboard data object failed");
514 return static_cast<LRESULT>(hr);
517 // flush the ole-clipboard
519 LRESULT CMtaOleClipboard::onFlushClipboard( )
521 return static_cast<LRESULT>( OleFlushClipboard( ) );
524 // handle clipboard chain change event
526 LRESULT CMtaOleClipboard::onChangeCBChain( HWND hWndRemove, HWND hWndNext )
528 if ( hWndRemove == m_hwndNextClipViewer )
529 m_hwndNextClipViewer = hWndNext;
530 else if ( IsWindow( m_hwndNextClipViewer ) )
532 // forward the message to the next one
533 DWORD_PTR dwpResult;
534 SendMessageTimeoutA(
535 m_hwndNextClipViewer,
536 WM_CHANGECBCHAIN,
537 reinterpret_cast<WPARAM>(hWndRemove),
538 reinterpret_cast<LPARAM>(hWndNext),
539 SMTO_BLOCK,
540 MAX_CLIPEVENT_PROCESSING_TIME,
541 &dwpResult );
544 return 0;
547 // handle draw clipboard event
549 LRESULT CMtaOleClipboard::onDrawClipboard( )
551 // we don't send a notification if we are
552 // registering ourself as clipboard
553 if ( !m_bInRegisterClipViewer )
555 ClearableMutexGuard aGuard( m_ClipboardChangedEventCountMutex );
557 m_ClipboardChangedEventCount++;
558 SetEvent( m_hClipboardChangedEvent );
560 aGuard.clear( );
563 // forward the message to the next viewer in the chain
564 if ( IsWindow( m_hwndNextClipViewer ) )
566 DWORD_PTR dwpResult;
567 SendMessageTimeoutA(
568 m_hwndNextClipViewer,
569 WM_DRAWCLIPBOARD,
570 static_cast< WPARAM >( 0 ),
571 static_cast< LPARAM >( 0 ),
572 SMTO_BLOCK,
573 MAX_CLIPEVENT_PROCESSING_TIME,
574 &dwpResult );
577 return 0;
580 // SendMessage so we don't need to supply the HWND if we send
581 // something to our wrapped window
583 LRESULT CMtaOleClipboard::sendMessage( UINT msg, WPARAM wParam, LPARAM lParam )
585 return ::SendMessageA( m_hwndMtaOleReqWnd, msg, wParam, lParam );
588 // PostMessage so we don't need to supply the HWND if we send
589 // something to our wrapped window
591 bool CMtaOleClipboard::postMessage( UINT msg, WPARAM wParam, LPARAM lParam )
593 return PostMessageA( m_hwndMtaOleReqWnd, msg, wParam, lParam ) ? true : false;
596 // the window proc
598 LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
600 LRESULT lResult = 0;
602 // get a connection to the class-instance via the static member
603 CMtaOleClipboard* pImpl = CMtaOleClipboard::s_theMtaOleClipboardInst;
604 OSL_ASSERT( NULL != pImpl );
606 switch( uMsg )
608 case MSG_SETCLIPBOARD:
610 IDataObject* pIDataObject = reinterpret_cast< IDataObject* >( wParam );
611 pImpl->onSetClipboard( pIDataObject );
613 // in setClipboard we did acquire the
614 // interface pointer in order to prevent
615 // destruction of the object before the
616 // ole clipboard can acquire the interface
617 // now we release the interface so that
618 // our lostOwnership mechanism works
619 // remember: pIDataObject may be NULL
620 if ( pIDataObject )
621 pIDataObject->Release( );
623 break;
625 case MSG_GETCLIPBOARD:
627 MsgCtx* aMsgCtx = reinterpret_cast< MsgCtx* >( lParam );
628 OSL_ASSERT( aMsgCtx );
630 aMsgCtx->hr = pImpl->onGetClipboard( reinterpret_cast< LPSTREAM* >(wParam) );
631 aMsgCtx->aCondition.set( );
633 break;
635 case MSG_FLUSHCLIPBOARD:
637 MsgCtx* aMsgCtx = reinterpret_cast< MsgCtx* >( lParam );
638 OSL_ASSERT( aMsgCtx );
640 aMsgCtx->hr = pImpl->onFlushClipboard( );
641 aMsgCtx->aCondition.set( );
643 break;
645 case MSG_REGCLIPVIEWER:
647 MsgCtx* aMsgCtx = reinterpret_cast< MsgCtx* >( lParam );
648 OSL_ASSERT( aMsgCtx );
650 pImpl->onRegisterClipViewer( reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t>(wParam) );
651 aMsgCtx->aCondition.set( );
653 break;
655 case WM_CHANGECBCHAIN:
656 lResult = pImpl->onChangeCBChain(
657 reinterpret_cast< HWND >( wParam ), reinterpret_cast< HWND >( lParam ) );
658 break;
660 case WM_DRAWCLIPBOARD:
661 lResult = pImpl->onDrawClipboard( );
662 break;
664 case MSG_SHUTDOWN:
665 DestroyWindow( pImpl->m_hwndMtaOleReqWnd );
666 break;
668 // force the sta thread to end
669 case WM_DESTROY:
670 PostQuitMessage( 0 );
671 break;
673 default:
674 lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
675 break;
678 return lResult;
681 void CMtaOleClipboard::createMtaOleReqWnd( )
683 WNDCLASSEXA wcex;
685 HINSTANCE hInst = GetModuleHandleA( CLIPSRV_DLL_NAME );
686 OSL_ENSURE( NULL != hInst, "The name of the clipboard service dll must have changed" );
688 ZeroMemory( &wcex, sizeof( WNDCLASSEXA ) );
690 wcex.cbSize = sizeof(WNDCLASSEXA);
691 wcex.style = 0;
692 wcex.lpfnWndProc = static_cast< WNDPROC >( CMtaOleClipboard::mtaOleReqWndProc );
693 wcex.cbClsExtra = 0;
694 wcex.cbWndExtra = 0;
695 wcex.hInstance = hInst;
696 wcex.hIcon = NULL;
697 wcex.hCursor = NULL;
698 wcex.hbrBackground = NULL;
699 wcex.lpszMenuName = NULL;
700 wcex.lpszClassName = g_szWndClsName;
701 wcex.hIconSm = NULL;
703 m_MtaOleReqWndClassAtom = RegisterClassExA( &wcex );
705 if ( 0 != m_MtaOleReqWndClassAtom )
706 m_hwndMtaOleReqWnd = CreateWindowA(
707 g_szWndClsName, NULL, 0, 0, 0, 0, 0, NULL, NULL, hInst, NULL );
710 unsigned int CMtaOleClipboard::run( )
712 #if OSL_DEBUG_LEVEL > 0
713 HRESULT hr =
714 #endif
715 OleInitialize( NULL );
716 OSL_ASSERT( SUCCEEDED( hr ) );
718 createMtaOleReqWnd( );
720 unsigned int nRet;
722 if ( IsWindow( m_hwndMtaOleReqWnd ) )
724 if ( NULL != m_hEvtThrdReady )
725 SetEvent( m_hEvtThrdReady );
727 // pumping messages
728 MSG msg;
729 while( GetMessageA( &msg, NULL, 0, 0 ) )
730 DispatchMessageA( &msg );
732 nRet = 0;
734 else
735 nRet = ~0U;
737 OleUninitialize( );
739 return nRet;
742 unsigned int WINAPI CMtaOleClipboard::oleThreadProc( LPVOID pParam )
744 osl_setThreadName("CMtaOleClipboard::run()");
746 CMtaOleClipboard* pInst =
747 reinterpret_cast<CMtaOleClipboard*>( pParam );
748 OSL_ASSERT( NULL != pInst );
750 return pInst->run( );
753 unsigned int WINAPI CMtaOleClipboard::clipboardChangedNotifierThreadProc( LPVOID pParam )
755 osl_setThreadName("CMtaOleClipboard::clipboardChangedNotifierThreadProc()");
756 CMtaOleClipboard* pInst = reinterpret_cast< CMtaOleClipboard* >( pParam );
757 OSL_ASSERT( NULL != pInst );
759 CoInitialize( NULL );
761 // assuming we don't need a lock for
762 // a boolean variable like m_bRun...
763 while ( pInst->m_bRunClipboardNotifierThread )
765 // wait for clipboard changed or terminate event
766 WaitForMultipleObjects( 2, pInst->m_hClipboardChangedNotifierEvents, false, INFINITE );
768 ClearableMutexGuard aGuard( pInst->m_ClipboardChangedEventCountMutex );
770 if ( pInst->m_ClipboardChangedEventCount > 0 )
772 pInst->m_ClipboardChangedEventCount--;
773 if ( 0 == pInst->m_ClipboardChangedEventCount )
774 ResetEvent( pInst->m_hClipboardChangedEvent );
776 aGuard.clear( );
778 // nobody should touch m_pfncClipViewerCallback while we do
779 MutexGuard aClipViewerGuard( pInst->m_pfncClipViewerCallbackMutex );
781 // notify all clipboard listener
782 if ( pInst->m_pfncClipViewerCallback )
783 pInst->m_pfncClipViewerCallback( );
785 else
786 aGuard.clear( );
789 CoUninitialize( );
791 return 0;
794 bool CMtaOleClipboard::WaitForThreadReady( ) const
796 bool bRet = false;
798 if ( NULL != m_hEvtThrdReady )
800 DWORD dwResult = WaitForSingleObject(
801 m_hEvtThrdReady, MAX_WAITTIME );
802 bRet = ( dwResult == WAIT_OBJECT_0 );
805 return bRet;
808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */