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
10cdf0e10cSrcweir *
11*48123e16SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
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.
19cdf0e10cSrcweir *
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