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