xref: /trunk/main/dtrans/source/win32/mtaole/MtaOleClipb.cxx (revision e53c7ad2a84deacc7f4366655618732549e4d1d3)
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