1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MtaOleClipb.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dtrans.hxx"
35 MtaOleClipb.cxx - documentation
37 This class setup a single threaded apartment (sta) thread to deal with
38 the ole clipboard, which runs only in an sta thread.
39 The consequence is that callback from the ole clipboard are in the
40 context of this sta thread. In the soffice applications this may lead
41 to problems because they all use the one and only mutex called
43 In order to transfer clipboard requests to our sta thread we use a
44 hidden window an forward these requests via window messages.
48 #pragma warning( disable : 4786 ) // identifier was truncated to 'number'
49 // characters in the debug information
53 #include <osl/diagnose.h>
55 #include "..\..\inc\MtaOleClipb.hxx"
56 #include <osl/conditn.hxx>
61 #include <systools/win32/comtools.hxx>
63 #define __uuidof(I) IID_##I
66 //----------------------------------------------------------------
67 // namespace directives
68 //----------------------------------------------------------------
72 using osl::MutexGuard
;
73 using osl::ClearableMutexGuard
;
75 //----------------------------------------------------------------
77 //----------------------------------------------------------------
79 namespace /* private */
81 char CLIPSRV_DLL_NAME
[] = "sysdtrans.dll";
82 char g_szWndClsName
[] = "MtaOleReqWnd###";
84 //--------------------------------------------------------
86 //--------------------------------------------------------
88 const sal_uInt32 MSG_SETCLIPBOARD
= WM_USER
+ 0x0001;
89 const sal_uInt32 MSG_GETCLIPBOARD
= WM_USER
+ 0x0002;
90 const sal_uInt32 MSG_REGCLIPVIEWER
= WM_USER
+ 0x0003;
91 const sal_uInt32 MSG_FLUSHCLIPBOARD
= WM_USER
+ 0x0004;
92 const sal_uInt32 MSG_SHUTDOWN
= WM_USER
+ 0x0005;
94 const sal_uInt32 MAX_WAITTIME
= 10000; // msec
95 const sal_uInt32 MAX_WAIT_SHUTDOWN
= 10000; // msec
96 const sal_uInt32 MAX_CLIPEVENT_PROCESSING_TIME
= 5000; // msec
98 const sal_Bool MANUAL_RESET
= sal_True
;
99 const sal_Bool AUTO_RESET
= sal_False
;
100 const sal_Bool INIT_NONSIGNALED
= sal_False
;
102 //------------------------------------------------------
103 /* Cannot use osl conditions because they are blocking
104 without waking up on messages sent by another thread
105 this leads to deadlocks because we are blocking the
106 communication between inter-thread marshalled COM
108 COM Proxy-Stub communication uses SendMessages for
109 synchronization purposes.
117 m_hEvent
= CreateEvent(
119 true, /* manual reset */
120 false, /* initial state not signaled */
121 0); /* automatic name */
127 CloseHandle(m_hEvent
);
130 // wait infinite for event be signaled
131 // leave messages sent through
137 MsgWaitForMultipleObjects(1, &m_hEvent
, FALSE
, INFINITE
, QS_SENDMESSAGE
);
144 case WAIT_OBJECT_0
+ 1:
146 /* PeekMessage processes all messages in the SendMessage
147 queue that's what we want, messages from the PostMessage
148 queue stay untouched */
150 PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
167 // prevent copy/assignment
169 Win32Condition(const Win32Condition
&);
170 Win32Condition
& operator=(const Win32Condition
&);
173 //------------------------------------------
174 // we use one condition for every request
175 //------------------------------------------
179 Win32Condition aCondition
;
183 } /* namespace private */
185 //----------------------------------------------------------------
186 // static member initialization
187 //----------------------------------------------------------------
189 CMtaOleClipboard
* CMtaOleClipboard::s_theMtaOleClipboardInst
= NULL
;
191 //--------------------------------------------------------------------
192 // marshal an IDataObject
193 //--------------------------------------------------------------------
196 HRESULT
MarshalIDataObjectInStream( IDataObject
* pIDataObject
, LPSTREAM
* ppStream
)
198 OSL_ASSERT( NULL
!= pIDataObject
);
199 OSL_ASSERT( NULL
!= ppStream
);
202 return CoMarshalInterThreadInterfaceInStream(
203 __uuidof(IDataObject
), //The IID of inteface to be marshaled
204 pIDataObject
, //The interface pointer
205 ppStream
//IStream pointer
209 //--------------------------------------------------------------------
210 // unmarshal an IDataObject
211 //--------------------------------------------------------------------
214 HRESULT
UnmarshalIDataObjectAndReleaseStream( LPSTREAM lpStream
, IDataObject
** ppIDataObject
)
216 OSL_ASSERT( NULL
!= lpStream
);
217 OSL_ASSERT( NULL
!= ppIDataObject
);
219 *ppIDataObject
= NULL
;
220 return CoGetInterfaceAndReleaseStream(
222 __uuidof(IDataObject
),
223 reinterpret_cast<LPVOID
*>(ppIDataObject
));
226 //--------------------------------------------------------------------
227 // helper class to ensure that the calling thread has com initialized
228 //--------------------------------------------------------------------
236 to be safe we call CoInitialize
237 although it is not necessary if
238 the calling thread was created
239 using osl_CreateThread because
240 this function calls CoInitialize
241 for every thread it creates
243 m_hResult
= CoInitialize( NULL
);
245 if ( S_OK
== m_hResult
)
246 OSL_ENSURE( sal_False
, \
247 "com was not yet initialzed, the thread was not created using osl_createThread" );
248 else if ( FAILED( m_hResult
) && !( RPC_E_CHANGED_MODE
== m_hResult
) )
249 OSL_ENSURE( sal_False
, \
250 "com could not be initialized, maybe the thread was not created using osl_createThread" );
256 we only call CoUninitialize when
257 CoInitailize returned S_FALSE, what
258 means that com was already initialize
259 for that thread so we keep the balance
260 if CoInitialize returned S_OK what means
261 com was not yet initialized we better
262 let com initialized or we may run into
263 the realm of undefined behaviour
265 if ( m_hResult
== S_FALSE
)
273 //--------------------------------------------------------------------
275 //--------------------------------------------------------------------
277 CMtaOleClipboard::CMtaOleClipboard( ) :
278 m_hOleThread( NULL
),
280 m_hEvtThrdReady( NULL
),
281 m_hwndMtaOleReqWnd( NULL
),
282 m_MtaOleReqWndClassAtom( 0 ),
283 m_hwndNextClipViewer( NULL
),
284 m_pfncClipViewerCallback( NULL
),
285 m_bRunClipboardNotifierThread( sal_True
),
286 m_hClipboardChangedEvent( m_hClipboardChangedNotifierEvents
[0] ),
287 m_hTerminateClipboardChangedNotifierEvent( m_hClipboardChangedNotifierEvents
[1] ),
288 m_ClipboardChangedEventCount( 0 )
290 // signals that the thread was successfully setup
291 m_hEvtThrdReady
= CreateEventA( 0, MANUAL_RESET
, INIT_NONSIGNALED
, NULL
);
293 OSL_ASSERT( NULL
!= m_hEvtThrdReady
);
295 s_theMtaOleClipboardInst
= this;
297 m_hOleThread
= (HANDLE
)_beginthreadex(
298 NULL
, 0, CMtaOleClipboard::oleThreadProc
, this, 0, &m_uOleThreadId
);
299 OSL_ASSERT( NULL
!= m_hOleThread
);
301 //----------------------------------------------
302 // setup the clipboard changed notifier thread
303 //----------------------------------------------
305 m_hClipboardChangedNotifierEvents
[0] = CreateEventA( 0, MANUAL_RESET
, INIT_NONSIGNALED
, NULL
);
306 OSL_ASSERT( NULL
!= m_hClipboardChangedNotifierEvents
[0] );
308 m_hClipboardChangedNotifierEvents
[1] = CreateEventA( 0, MANUAL_RESET
, INIT_NONSIGNALED
, NULL
);
309 OSL_ASSERT( NULL
!= m_hClipboardChangedNotifierEvents
[1] );
312 m_hClipboardChangedNotifierThread
= (HANDLE
)_beginthreadex(
313 NULL
, 0, CMtaOleClipboard::clipboardChangedNotifierThreadProc
, this, 0, &uThreadId
);
315 OSL_ASSERT( NULL
!= m_hClipboardChangedNotifierThread
);
318 //--------------------------------------------------------------------
320 //--------------------------------------------------------------------
322 CMtaOleClipboard::~CMtaOleClipboard( )
324 // block calling threads out
325 if ( NULL
!= m_hEvtThrdReady
)
326 ResetEvent( m_hEvtThrdReady
);
328 // terminate the clipboard changed notifier thread
329 m_bRunClipboardNotifierThread
= sal_False
;
330 SetEvent( m_hTerminateClipboardChangedNotifierEvent
);
332 sal_uInt32 dwResult
= WaitForSingleObject(
333 m_hClipboardChangedNotifierThread
, MAX_WAIT_SHUTDOWN
);
335 OSL_ENSURE( dwResult
== WAIT_OBJECT_0
, "clipboard notifier thread could not terminate" );
337 if ( NULL
!= m_hClipboardChangedNotifierThread
)
338 CloseHandle( m_hClipboardChangedNotifierThread
);
340 if ( NULL
!= m_hClipboardChangedNotifierEvents
[0] )
341 CloseHandle( m_hClipboardChangedNotifierEvents
[0] );
343 if ( NULL
!= m_hClipboardChangedNotifierEvents
[1] )
344 CloseHandle( m_hClipboardChangedNotifierEvents
[1] );
347 // because DestroyWindow can only be called
348 // from within the thread that created the window
349 sendMessage( MSG_SHUTDOWN
,
350 static_cast< WPARAM
>( 0 ),
351 static_cast< LPARAM
>( 0 ) );
353 // wait for thread shutdown
354 dwResult
= WaitForSingleObject( m_hOleThread
, MAX_WAIT_SHUTDOWN
);
355 OSL_ENSURE( dwResult
== WAIT_OBJECT_0
, "OleThread could not terminate" );
357 if ( NULL
!= m_hOleThread
)
358 CloseHandle( m_hOleThread
);
360 if ( NULL
!= m_hEvtThrdReady
)
361 CloseHandle( m_hEvtThrdReady
);
363 if ( m_MtaOleReqWndClassAtom
)
364 UnregisterClassA( g_szWndClsName
, NULL
);
366 OSL_ENSURE( ( NULL
== m_pfncClipViewerCallback
) &&
367 !IsWindow( m_hwndNextClipViewer
), \
368 "Clipboard viewer not properly unregistered" );
372 //--------------------------------------------------------------------
374 //--------------------------------------------------------------------
376 HRESULT
CMtaOleClipboard::flushClipboard( )
378 if ( !WaitForThreadReady( ) )
380 OSL_ENSURE( sal_False
, "clipboard sta thread not ready" );
384 OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId
, \
385 "flushClipboard from within clipboard sta thread called" );
389 postMessage( MSG_FLUSHCLIPBOARD
,
390 static_cast< WPARAM
>( 0 ),
391 reinterpret_cast< LPARAM
>( &aMsgCtx
) );
393 aMsgCtx
.aCondition
.wait( /* infinite */ );
398 //--------------------------------------------------------------------
400 //--------------------------------------------------------------------
402 HRESULT
CMtaOleClipboard::getClipboard( IDataObject
** ppIDataObject
)
404 OSL_PRECOND( NULL
!= ppIDataObject
, "invalid parameter" );
405 OSL_PRECOND( GetCurrentThreadId( ) != m_uOleThreadId
, "getClipboard from within clipboard sta thread called" );
407 if ( !WaitForThreadReady( ) )
409 OSL_ENSURE( sal_False
, "clipboard sta thread not ready" );
413 CAutoComInit comAutoInit
;
418 *ppIDataObject
= NULL
;
422 postMessage( MSG_GETCLIPBOARD
,
423 reinterpret_cast< WPARAM
>( &lpStream
),
424 reinterpret_cast< LPARAM
>( &aMsgCtx
) );
426 aMsgCtx
.aCondition
.wait( /* infinite */ );
430 if ( SUCCEEDED( hr
) )
432 hr
= UnmarshalIDataObjectAndReleaseStream( lpStream
, ppIDataObject
);
433 OSL_ENSURE( SUCCEEDED( hr
), "unmarshalling clipboard data object failed" );
439 //--------------------------------------------------------------------
440 // this is an asynchronous method that's why we don't wait until the
441 // request is completed
442 //--------------------------------------------------------------------
444 HRESULT
CMtaOleClipboard::setClipboard( IDataObject
* pIDataObject
)
446 if ( !WaitForThreadReady( ) )
448 OSL_ENSURE( sal_False
, "clipboard sta thread not ready" );
452 CAutoComInit comAutoInit
;
454 OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId
, "setClipboard from within the clipboard sta thread called" );
456 // because we marshall this request
457 // into the sta thread we better
458 // acquire the interface here so
459 // that the object will not be
460 // destroyed before the ole clipboard
462 // remember: pIDataObject may be NULL
463 // which is an request to clear the
464 // current clipboard content
466 pIDataObject
->AddRef( );
470 reinterpret_cast< WPARAM
>( pIDataObject
),
473 // because this is an asynchronous function
474 // the return value is useless
478 //--------------------------------------------------------------------
479 // register a clipboard viewer
480 //--------------------------------------------------------------------
482 sal_Bool
CMtaOleClipboard::registerClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback
)
484 if ( !WaitForThreadReady( ) )
486 OSL_ENSURE( sal_False
, "clipboard sta thread not ready" );
490 sal_Bool bRet
= sal_False
;
492 OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId
, "registerClipViewer from within the OleThread called" );
496 postMessage( MSG_REGCLIPVIEWER
,
497 reinterpret_cast<WPARAM
>( pfncClipViewerCallback
),
498 reinterpret_cast<LPARAM
>( &aMsgCtx
) );
500 aMsgCtx
.aCondition
.wait( /* infinite */ );
505 //--------------------------------------------------------------------
506 // register a clipboard viewer
507 //--------------------------------------------------------------------
509 sal_Bool
CMtaOleClipboard::onRegisterClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback
)
511 sal_Bool bRet
= sal_True
;
513 // we need exclusive access because the clipboard changed notifier
514 // thread also accesses this variable
515 MutexGuard
aGuard( m_pfncClipViewerCallbackMutex
);
517 // register if not yet done
518 if ( ( NULL
!= pfncClipViewerCallback
) && ( NULL
== m_pfncClipViewerCallback
) )
520 // SetClipboardViewer sends a WM_DRAWCLIPBOARD message we ignore
521 // this message if we register ourself as clip viewer
522 m_bInRegisterClipViewer
= sal_True
;
523 m_hwndNextClipViewer
= SetClipboardViewer( m_hwndMtaOleReqWnd
);
524 m_bInRegisterClipViewer
= sal_False
;
526 // if there is no other cb-viewer the
527 // return value is NULL!!!
528 bRet
= IsWindow( m_hwndNextClipViewer
) ? sal_True
: sal_False
;
530 // save the new callback function
531 m_pfncClipViewerCallback
= pfncClipViewerCallback
;
533 else if ( ( NULL
== pfncClipViewerCallback
) && ( NULL
!= m_pfncClipViewerCallback
) )
535 m_pfncClipViewerCallback
= NULL
;
537 // unregister if input parameter is NULL and we previously registered
538 // as clipboard viewer
539 ChangeClipboardChain( m_hwndMtaOleReqWnd
, m_hwndNextClipViewer
);
540 m_hwndNextClipViewer
= NULL
;
546 //--------------------------------------------------------------------
548 //--------------------------------------------------------------------
550 LRESULT
CMtaOleClipboard::onSetClipboard( IDataObject
* pIDataObject
)
552 return static_cast<LRESULT
>( OleSetClipboard( pIDataObject
) );
555 //--------------------------------------------------------------------
557 //--------------------------------------------------------------------
559 LRESULT
CMtaOleClipboard::onGetClipboard( LPSTREAM
* ppStream
)
561 OSL_ASSERT(NULL
!= ppStream
);
563 IDataObjectPtr pIDataObject
;
565 // forward the request to the OleClipboard
566 HRESULT hr
= OleGetClipboard( &pIDataObject
);
567 if ( SUCCEEDED( hr
) )
569 hr
= MarshalIDataObjectInStream(pIDataObject
.get(), ppStream
);
570 OSL_ENSURE(SUCCEEDED(hr
), "marshalling cliboard data object failed");
572 return static_cast<LRESULT
>(hr
);
575 //--------------------------------------------------------------------
576 // flush the ole-clipboard
577 //--------------------------------------------------------------------
579 LRESULT
CMtaOleClipboard::onFlushClipboard( )
581 return static_cast<LRESULT
>( OleFlushClipboard( ) );
584 //--------------------------------------------------------------------
585 // handle clipboard chain change event
586 //--------------------------------------------------------------------
588 LRESULT
CMtaOleClipboard::onChangeCBChain( HWND hWndRemove
, HWND hWndNext
)
590 if ( hWndRemove
== m_hwndNextClipViewer
)
591 m_hwndNextClipViewer
= hWndNext
;
592 else if ( IsWindow( m_hwndNextClipViewer
) )
594 // forward the message to the next one
597 m_hwndNextClipViewer
,
599 reinterpret_cast<WPARAM
>(hWndRemove
),
600 reinterpret_cast<LPARAM
>(hWndNext
),
602 MAX_CLIPEVENT_PROCESSING_TIME
,
609 //--------------------------------------------------------------------
610 // handle draw clipboard event
611 //--------------------------------------------------------------------
613 LRESULT
CMtaOleClipboard::onDrawClipboard( )
615 // we don't send a notification if we are
616 // registering ourself as clipboard
617 if ( !m_bInRegisterClipViewer
)
619 ClearableMutexGuard
aGuard( m_ClipboardChangedEventCountMutex
);
621 m_ClipboardChangedEventCount
++;
622 SetEvent( m_hClipboardChangedEvent
);
627 // foward the message to the next viewer in the chain
628 if ( IsWindow( m_hwndNextClipViewer
) )
632 m_hwndNextClipViewer
,
634 static_cast< WPARAM
>( 0 ),
635 static_cast< LPARAM
>( 0 ),
637 MAX_CLIPEVENT_PROCESSING_TIME
,
644 //--------------------------------------------------------------------
645 // SendMessage so we don't need to supply the HWND if we send
646 // something to our wrapped window
647 //--------------------------------------------------------------------
649 LRESULT
CMtaOleClipboard::sendMessage( UINT msg
, WPARAM wParam
, LPARAM lParam
)
651 return ::SendMessageA( m_hwndMtaOleReqWnd
, msg
, wParam
, lParam
);
654 //--------------------------------------------------------------------
655 // PostMessage so we don't need to supply the HWND if we send
656 // something to our wrapped window
657 //--------------------------------------------------------------------
659 sal_Bool
CMtaOleClipboard::postMessage( UINT msg
, WPARAM wParam
, LPARAM lParam
)
661 return PostMessageA( m_hwndMtaOleReqWnd
, msg
, wParam
, lParam
) ? sal_True
: sal_False
;
665 //--------------------------------------------------------------------
667 //--------------------------------------------------------------------
669 LRESULT CALLBACK
CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
673 // get a connection to the class-instance via the static member
674 CMtaOleClipboard
* pImpl
= CMtaOleClipboard::s_theMtaOleClipboardInst
;
675 OSL_ASSERT( NULL
!= pImpl
);
679 case MSG_SETCLIPBOARD
:
681 IDataObject
* pIDataObject
= reinterpret_cast< IDataObject
* >( wParam
);
682 pImpl
->onSetClipboard( pIDataObject
);
684 // in setClipboard we did acquire the
685 // interface pointer in order to prevent
686 // destruction of the object before the
687 // ole clipboard can acquire the interface
688 // now we release the interface so that
689 // our lostOwnership mechanism works
690 // remember: pIDataObject may be NULL
692 pIDataObject
->Release( );
696 case MSG_GETCLIPBOARD
:
698 MsgCtx
* aMsgCtx
= reinterpret_cast< MsgCtx
* >( lParam
);
699 OSL_ASSERT( aMsgCtx
);
701 aMsgCtx
->hr
= pImpl
->onGetClipboard( reinterpret_cast< LPSTREAM
* >(wParam
) );
702 aMsgCtx
->aCondition
.set( );
706 case MSG_FLUSHCLIPBOARD
:
708 MsgCtx
* aMsgCtx
= reinterpret_cast< MsgCtx
* >( lParam
);
709 OSL_ASSERT( aMsgCtx
);
711 aMsgCtx
->hr
= pImpl
->onFlushClipboard( );
712 aMsgCtx
->aCondition
.set( );
716 case MSG_REGCLIPVIEWER
:
718 MsgCtx
* aMsgCtx
= reinterpret_cast< MsgCtx
* >( lParam
);
719 OSL_ASSERT( aMsgCtx
);
721 pImpl
->onRegisterClipViewer( reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t
>(wParam
) );
722 aMsgCtx
->aCondition
.set( );
726 case WM_CHANGECBCHAIN
:
727 lResult
= pImpl
->onChangeCBChain(
728 reinterpret_cast< HWND
>( wParam
), reinterpret_cast< HWND
>( lParam
) );
731 case WM_DRAWCLIPBOARD
:
732 lResult
= pImpl
->onDrawClipboard( );
736 DestroyWindow( pImpl
->m_hwndMtaOleReqWnd
);
739 // force the sta thread to end
741 PostQuitMessage( 0 );
745 lResult
= DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
752 //--------------------------------------------------------------------
754 //--------------------------------------------------------------------
756 void CMtaOleClipboard::createMtaOleReqWnd( )
760 HINSTANCE hInst
= GetModuleHandleA( CLIPSRV_DLL_NAME
);
761 OSL_ENSURE( NULL
!= hInst
, "The name of the clipboard service dll must have changed" );
763 ZeroMemory( &wcex
, sizeof( WNDCLASSEXA
) );
765 wcex
.cbSize
= sizeof(WNDCLASSEXA
);
767 wcex
.lpfnWndProc
= static_cast< WNDPROC
>( CMtaOleClipboard::mtaOleReqWndProc
);
770 wcex
.hInstance
= hInst
;
773 wcex
.hbrBackground
= NULL
;
774 wcex
.lpszMenuName
= NULL
;
775 wcex
.lpszClassName
= g_szWndClsName
;
778 m_MtaOleReqWndClassAtom
= RegisterClassExA( &wcex
);
780 if ( 0 != m_MtaOleReqWndClassAtom
)
781 m_hwndMtaOleReqWnd
= CreateWindowA(
782 g_szWndClsName
, NULL
, 0, 0, 0, 0, 0, NULL
, NULL
, hInst
, NULL
);
785 //--------------------------------------------------------------------
787 //--------------------------------------------------------------------
789 unsigned int CMtaOleClipboard::run( )
791 #if OSL_DEBUG_LEVEL > 0
794 OleInitialize( NULL
);
795 OSL_ASSERT( SUCCEEDED( hr
) );
797 createMtaOleReqWnd( );
801 if ( IsWindow( m_hwndMtaOleReqWnd
) )
803 if ( NULL
!= m_hEvtThrdReady
)
804 SetEvent( m_hEvtThrdReady
);
808 while( GetMessageA( &msg
, NULL
, 0, 0 ) )
809 DispatchMessageA( &msg
);
821 //--------------------------------------------------------------------
823 //--------------------------------------------------------------------
825 unsigned int WINAPI
CMtaOleClipboard::oleThreadProc( LPVOID pParam
)
827 CMtaOleClipboard
* pInst
=
828 reinterpret_cast<CMtaOleClipboard
*>( pParam
);
829 OSL_ASSERT( NULL
!= pInst
);
831 return pInst
->run( );
834 //--------------------------------------------------------------------
836 //--------------------------------------------------------------------
838 unsigned int WINAPI
CMtaOleClipboard::clipboardChangedNotifierThreadProc( LPVOID pParam
)
840 CMtaOleClipboard
* pInst
= reinterpret_cast< CMtaOleClipboard
* >( pParam
);
841 OSL_ASSERT( NULL
!= pInst
);
843 CoInitialize( NULL
);
845 // assuming we don't need a lock for
846 // a boolean variable like m_bRun...
847 while ( pInst
->m_bRunClipboardNotifierThread
)
849 // wait for clipboard changed or terminate event
850 WaitForMultipleObjects( 2, pInst
->m_hClipboardChangedNotifierEvents
, false, INFINITE
);
852 ClearableMutexGuard
aGuard( pInst
->m_ClipboardChangedEventCountMutex
);
854 if ( pInst
->m_ClipboardChangedEventCount
> 0 )
856 pInst
->m_ClipboardChangedEventCount
--;
857 if ( 0 == pInst
->m_ClipboardChangedEventCount
)
858 ResetEvent( pInst
->m_hClipboardChangedEvent
);
862 // nobody should touch m_pfncClipViewerCallback while we do
863 MutexGuard
aClipViewerGuard( pInst
->m_pfncClipViewerCallbackMutex
);
865 // notify all clipboard listener
866 if ( pInst
->m_pfncClipViewerCallback
)
867 pInst
->m_pfncClipViewerCallback( );
878 //--------------------------------------------------------------------
880 //--------------------------------------------------------------------
883 sal_Bool
CMtaOleClipboard::WaitForThreadReady( ) const
885 sal_Bool bRet
= sal_False
;
887 if ( NULL
!= m_hEvtThrdReady
)
889 DWORD dwResult
= WaitForSingleObject(
890 m_hEvtThrdReady
, MAX_WAITTIME
);
891 bRet
= ( dwResult
== WAIT_OBJECT_0
);