1*48123e16SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*48123e16SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*48123e16SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*48123e16SAndrew Rist  * distributed with this work for additional information
6*48123e16SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*48123e16SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*48123e16SAndrew Rist  * "License"); you may not use this file except in compliance
9*48123e16SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*48123e16SAndrew Rist  *
11*48123e16SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*48123e16SAndrew Rist  *
13*48123e16SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*48123e16SAndrew Rist  * software distributed under the License is distributed on an
15*48123e16SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*48123e16SAndrew Rist  * KIND, either express or implied.  See the License for the
17*48123e16SAndrew Rist  * specific language governing permissions and limitations
18*48123e16SAndrew Rist  * under the License.
19*48123e16SAndrew Rist  *
20*48123e16SAndrew Rist  *************************************************************/
21*48123e16SAndrew Rist 
22*48123e16SAndrew 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
Win32Condition()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
~Win32Condition()118cdf0e10cSrcweir             ~Win32Condition()
119cdf0e10cSrcweir             {
120cdf0e10cSrcweir                 CloseHandle(m_hEvent);
121cdf0e10cSrcweir             }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir             // wait infinite for event be signaled
124cdf0e10cSrcweir             // leave messages sent through
wait()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
set()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
MarshalIDataObjectInStream(IDataObject * pIDataObject,LPSTREAM * ppStream)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
UnmarshalIDataObjectAndReleaseStream(LPSTREAM lpStream,IDataObject ** ppIDataObject)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:
CAutoComInit()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 
~CAutoComInit()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 
CMtaOleClipboard()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 
~CMtaOleClipboard()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 
flushClipboard()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 
getClipboard(IDataObject ** ppIDataObject)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 
setClipboard(IDataObject * pIDataObject)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 
registerClipViewer(LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback)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 
onRegisterClipViewer(LPFNC_CLIPVIEWER_CALLBACK_t pfncClipViewerCallback)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 
onSetClipboard(IDataObject * pIDataObject)543cdf0e10cSrcweir LRESULT CMtaOleClipboard::onSetClipboard( IDataObject* pIDataObject )
544cdf0e10cSrcweir {
545cdf0e10cSrcweir 	return static_cast<LRESULT>( OleSetClipboard( pIDataObject ) );
546cdf0e10cSrcweir }
547cdf0e10cSrcweir 
548cdf0e10cSrcweir //--------------------------------------------------------------------
549cdf0e10cSrcweir //
550cdf0e10cSrcweir //--------------------------------------------------------------------
551cdf0e10cSrcweir 
onGetClipboard(LPSTREAM * ppStream)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 
onFlushClipboard()572cdf0e10cSrcweir LRESULT CMtaOleClipboard::onFlushClipboard( )
573cdf0e10cSrcweir {
574cdf0e10cSrcweir 	return static_cast<LRESULT>( OleFlushClipboard( ) );
575cdf0e10cSrcweir }
576cdf0e10cSrcweir 
577cdf0e10cSrcweir //--------------------------------------------------------------------
578cdf0e10cSrcweir // handle clipboard chain change event
579cdf0e10cSrcweir //--------------------------------------------------------------------
580cdf0e10cSrcweir 
onChangeCBChain(HWND hWndRemove,HWND hWndNext)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 
onDrawClipboard()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 
620cdf0e10cSrcweir 	// foward 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 
sendMessage(UINT msg,WPARAM wParam,LPARAM lParam)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 
postMessage(UINT msg,WPARAM wParam,LPARAM lParam)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 
mtaOleReqWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)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 
createMtaOleReqWnd()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 
run()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 
oleThreadProc(LPVOID pParam)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 
clipboardChangedNotifierThreadProc(LPVOID pParam)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
WaitForThreadReady() const876cdf0e10cSrcweir 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