1b557fc96SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3b557fc96SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4b557fc96SAndrew Rist * or more contributor license agreements. See the NOTICE file
5b557fc96SAndrew Rist * distributed with this work for additional information
6b557fc96SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7b557fc96SAndrew Rist * to you under the Apache License, Version 2.0 (the
8b557fc96SAndrew Rist * "License"); you may not use this file except in compliance
9b557fc96SAndrew Rist * with the License. You may obtain a copy of the License at
10b557fc96SAndrew Rist *
11b557fc96SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12b557fc96SAndrew Rist *
13b557fc96SAndrew Rist * Unless required by applicable law or agreed to in writing,
14b557fc96SAndrew Rist * software distributed under the License is distributed on an
15b557fc96SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b557fc96SAndrew Rist * KIND, either express or implied. See the License for the
17b557fc96SAndrew Rist * specific language governing permissions and limitations
18b557fc96SAndrew Rist * under the License.
19b557fc96SAndrew Rist *
20b557fc96SAndrew Rist *************************************************************/
21b557fc96SAndrew Rist
22b557fc96SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_fpicker.hxx"
26cdf0e10cSrcweir #include <osl/diagnose.h>
27cdf0e10cSrcweir #include <osl/conditn.hxx>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "MtaFop.hxx"
30cdf0e10cSrcweir #include <wchar.h>
31cdf0e10cSrcweir #include <process.h>
32cdf0e10cSrcweir #include "..\misc\resourceprovider.hxx"
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include <systools/win32/comtools.hxx>
35cdf0e10cSrcweir
36cdf0e10cSrcweir using rtl::OUString;
37cdf0e10cSrcweir using osl::Condition;
38cdf0e10cSrcweir
39cdf0e10cSrcweir const sal_uInt32 MSG_BROWSEFORFOLDER = WM_USER + 1;
40cdf0e10cSrcweir const sal_uInt32 MSG_SHUTDOWN = WM_USER + 2;
41cdf0e10cSrcweir
42cdf0e10cSrcweir const sal_uInt32 MAX_WAITTIME = 2000; // msec
43cdf0e10cSrcweir
44cdf0e10cSrcweir const sal_Bool MANUAL_RESET = sal_True;
45cdf0e10cSrcweir const sal_Bool AUTO_RESET = sal_False;
46cdf0e10cSrcweir const sal_Bool INIT_NONSIGNALED = sal_False;
47cdf0e10cSrcweir
48cdf0e10cSrcweir typedef sal::systools::COMReference<IMalloc> IMallocPtr;
49cdf0e10cSrcweir typedef sal::systools::COMReference<IShellFolder> IShellFolderPtr;
50cdf0e10cSrcweir
51cdf0e10cSrcweir namespace
52cdf0e10cSrcweir {
53cdf0e10cSrcweir const char* FOLDERPICKER_SRV_DLL_NAME = "fop.dll";
54cdf0e10cSrcweir const char g_szWndClsName[] = "FopStaReqWnd###";
55cdf0e10cSrcweir const char* CURRENT_INSTANCE = "CurrInst";
56cdf0e10cSrcweir
57cdf0e10cSrcweir typedef struct _RequestContext
58cdf0e10cSrcweir {
59cdf0e10cSrcweir HANDLE hEvent;
60cdf0e10cSrcweir sal_Bool bRet;
61cdf0e10cSrcweir } RequestContext;
62cdf0e10cSrcweir
InitializeRequestContext(RequestContext * aRequestContext)63cdf0e10cSrcweir inline sal_Bool InitializeRequestContext( RequestContext* aRequestContext )
64cdf0e10cSrcweir {
65cdf0e10cSrcweir OSL_ASSERT( aRequestContext );
66cdf0e10cSrcweir
67cdf0e10cSrcweir aRequestContext->hEvent = CreateEventA(
68cdf0e10cSrcweir 0, AUTO_RESET, INIT_NONSIGNALED, NULL );
69cdf0e10cSrcweir
70cdf0e10cSrcweir aRequestContext->bRet = sal_False;
71cdf0e10cSrcweir
72cdf0e10cSrcweir return ( 0 != aRequestContext->hEvent );
73cdf0e10cSrcweir }
74cdf0e10cSrcweir
DeinitializeRequestContext(RequestContext * aRequestContext)75cdf0e10cSrcweir inline void DeinitializeRequestContext( RequestContext* aRequestContext )
76cdf0e10cSrcweir {
77cdf0e10cSrcweir OSL_ASSERT( aRequestContext && aRequestContext->hEvent );
78cdf0e10cSrcweir CloseHandle( aRequestContext->hEvent );
79cdf0e10cSrcweir }
80cdf0e10cSrcweir
81cdf0e10cSrcweir //-------------------------------
82cdf0e10cSrcweir // Determine if current thread is
83cdf0e10cSrcweir // an MTA or STA thread
84cdf0e10cSrcweir //-------------------------------
IsMTA()85cdf0e10cSrcweir bool IsMTA()
86cdf0e10cSrcweir {
87cdf0e10cSrcweir HRESULT hr = CoInitialize(NULL);
88cdf0e10cSrcweir
89cdf0e10cSrcweir if (RPC_E_CHANGED_MODE == hr)
90cdf0e10cSrcweir return true;
91cdf0e10cSrcweir
92cdf0e10cSrcweir if(SUCCEEDED(hr))
93cdf0e10cSrcweir CoUninitialize();
94cdf0e10cSrcweir
95cdf0e10cSrcweir return false;
96cdf0e10cSrcweir }
97cdf0e10cSrcweir }
98cdf0e10cSrcweir
99cdf0e10cSrcweir //----------------------------------------------------------------
100cdf0e10cSrcweir // static member initialization
101cdf0e10cSrcweir //----------------------------------------------------------------
102cdf0e10cSrcweir
103cdf0e10cSrcweir ATOM CMtaFolderPicker::s_ClassAtom = 0;
104cdf0e10cSrcweir osl::Mutex CMtaFolderPicker::s_Mutex;
105cdf0e10cSrcweir sal_Int32 CMtaFolderPicker::s_StaRequestWndRegisterCount = 0;
106cdf0e10cSrcweir
107cdf0e10cSrcweir //--------------------------------------------------------------------
108cdf0e10cSrcweir // ctor
109cdf0e10cSrcweir //--------------------------------------------------------------------
110cdf0e10cSrcweir
CMtaFolderPicker(sal_uInt32 Flags)111cdf0e10cSrcweir CMtaFolderPicker::CMtaFolderPicker( sal_uInt32 Flags ) :
112cdf0e10cSrcweir m_hStaThread( NULL ),
113cdf0e10cSrcweir m_uStaThreadId( 0 ),
114cdf0e10cSrcweir m_hEvtThrdReady( NULL ),
115cdf0e10cSrcweir m_hwndStaRequestWnd( NULL )
116cdf0e10cSrcweir {
117cdf0e10cSrcweir m_hInstance = GetModuleHandleA( FOLDERPICKER_SRV_DLL_NAME );
118cdf0e10cSrcweir OSL_ENSURE( m_hInstance, "The name of the FolderPicker service dll must have changed" );
119cdf0e10cSrcweir
120cdf0e10cSrcweir ZeroMemory( &m_bi, sizeof( m_bi ) );
121cdf0e10cSrcweir
122cdf0e10cSrcweir // !!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!
123cdf0e10cSrcweir //
124cdf0e10cSrcweir // Remember: This HACK prevents you from stepping
125cdf0e10cSrcweir // through your code in the debugger because if you
126cdf0e10cSrcweir // set a break point in the ctor here the debugger
127cdf0e10cSrcweir // may become the owner of the FolderBrowse dialog
128cdf0e10cSrcweir // and so it seems that the Visual Studio and the
129cdf0e10cSrcweir // office are hanging
130cdf0e10cSrcweir m_bi.hwndOwner = GetForegroundWindow( );
131cdf0e10cSrcweir
132cdf0e10cSrcweir /*
133cdf0e10cSrcweir Flag Available
134cdf0e10cSrcweir --------------------------------
135cdf0e10cSrcweir BIF_EDITBOX Version 4.71
136cdf0e10cSrcweir BIF_NEWDIALOGSTYLE Version 5.0
137cdf0e10cSrcweir BIF_SHAREABLE Version 5.0
138cdf0e10cSrcweir BIF_VALIDATE Version 4.71
139cdf0e10cSrcweir
140cdf0e10cSrcweir Version 4.71 - Internet Explorer 4.0
141cdf0e10cSrcweir Version 5.0 - Internet Explorer 5.0
142cdf0e10cSrcweir Windows 2000
143cdf0e10cSrcweir */
144cdf0e10cSrcweir m_bi.ulFlags = Flags;
145cdf0e10cSrcweir
146cdf0e10cSrcweir m_bi.lpfn = CMtaFolderPicker::FolderPickerCallback;
147cdf0e10cSrcweir m_bi.lParam = reinterpret_cast< LPARAM >( this );
148cdf0e10cSrcweir
149cdf0e10cSrcweir //---------------------------------------
150cdf0e10cSrcweir // read the default strings for title and
151cdf0e10cSrcweir // description from a resource file
152cdf0e10cSrcweir
153cdf0e10cSrcweir CResourceProvider ResProvider;
154cdf0e10cSrcweir
155cdf0e10cSrcweir m_dialogTitle = ResProvider.getResString( 500 );
156cdf0e10cSrcweir m_Description = ResProvider.getResString( 501 );
157cdf0e10cSrcweir
158cdf0e10cSrcweir // signals that the thread was successfully set up
159cdf0e10cSrcweir m_hEvtThrdReady = CreateEventA(
160cdf0e10cSrcweir 0,
161cdf0e10cSrcweir MANUAL_RESET,
162cdf0e10cSrcweir INIT_NONSIGNALED,
163cdf0e10cSrcweir NULL );
164cdf0e10cSrcweir
165cdf0e10cSrcweir if ( m_hEvtThrdReady )
166cdf0e10cSrcweir {
167cdf0e10cSrcweir // setup the sta thread
168cdf0e10cSrcweir m_hStaThread = (HANDLE)_beginthreadex(
169cdf0e10cSrcweir NULL,
170cdf0e10cSrcweir 0,
171cdf0e10cSrcweir CMtaFolderPicker::StaThreadProc,
172cdf0e10cSrcweir this,
173cdf0e10cSrcweir 0,
174cdf0e10cSrcweir &m_uStaThreadId );
175cdf0e10cSrcweir
176cdf0e10cSrcweir OSL_ASSERT( m_hStaThread );
177cdf0e10cSrcweir }
178cdf0e10cSrcweir
179cdf0e10cSrcweir OSL_ASSERT( m_hEvtThrdReady );
180cdf0e10cSrcweir }
181cdf0e10cSrcweir
182cdf0e10cSrcweir //--------------------------------------------------------------------
183cdf0e10cSrcweir // dtor
184cdf0e10cSrcweir //--------------------------------------------------------------------
185cdf0e10cSrcweir
~CMtaFolderPicker()186cdf0e10cSrcweir CMtaFolderPicker::~CMtaFolderPicker( )
187cdf0e10cSrcweir {
188cdf0e10cSrcweir // only if the is a valid event handle
189cdf0e10cSrcweir // there may also be a thread a hidden
190cdf0e10cSrcweir // target request window and so on
191cdf0e10cSrcweir // see ctor
192cdf0e10cSrcweir if ( m_hEvtThrdReady )
193cdf0e10cSrcweir {
194cdf0e10cSrcweir // block calling threads because we
195cdf0e10cSrcweir // are about to shutdown
196cdf0e10cSrcweir ResetEvent( m_hEvtThrdReady );
197cdf0e10cSrcweir
198cdf0e10cSrcweir // force the destruction of the sta thread request window
199cdf0e10cSrcweir // and the end of the thread
200*07a3d7f1SPedro Giffuni // remember: DestroyWindow may only be called from within
201cdf0e10cSrcweir // the thread that created the window
202cdf0e10cSrcweir if ( IsWindow( m_hwndStaRequestWnd ) )
203cdf0e10cSrcweir {
204cdf0e10cSrcweir SendMessageA( m_hwndStaRequestWnd, MSG_SHUTDOWN, 0, 0 );
205cdf0e10cSrcweir
206cdf0e10cSrcweir // we place unregister class here because
207cdf0e10cSrcweir // if we have a valid window we must have
208*07a3d7f1SPedro Giffuni // successfully registered a window class
209cdf0e10cSrcweir // if the creation of the window itself
210cdf0e10cSrcweir // failed after registering the window
211cdf0e10cSrcweir // class we have unregistered it immediately
212cdf0e10cSrcweir // in createStaRequestWindow below
213cdf0e10cSrcweir UnregisterStaRequestWindowClass( );
214cdf0e10cSrcweir }
215cdf0e10cSrcweir
216cdf0e10cSrcweir if ( m_hStaThread )
217cdf0e10cSrcweir {
218cdf0e10cSrcweir // wait for thread shutdown
219cdf0e10cSrcweir sal_uInt32 dwResult = WaitForSingleObject( m_hStaThread, MAX_WAITTIME );
220cdf0e10cSrcweir OSL_ENSURE( dwResult == WAIT_OBJECT_0, "sta thread could not terminate" );
221cdf0e10cSrcweir
222cdf0e10cSrcweir // terminate the thread if it
223cdf0e10cSrcweir // doesn't shutdown itself
224cdf0e10cSrcweir if ( WAIT_OBJECT_0 != dwResult )
225cdf0e10cSrcweir TerminateThread(
226cdf0e10cSrcweir m_hStaThread, sal::static_int_cast< DWORD >(-1) );
227cdf0e10cSrcweir
228cdf0e10cSrcweir CloseHandle( m_hStaThread );
229cdf0e10cSrcweir }
230cdf0e10cSrcweir
231cdf0e10cSrcweir CloseHandle( m_hEvtThrdReady );
232cdf0e10cSrcweir }
233cdf0e10cSrcweir }
234cdf0e10cSrcweir
235cdf0e10cSrcweir //--------------------------------------------------------------------
236cdf0e10cSrcweir //
237cdf0e10cSrcweir //--------------------------------------------------------------------
238cdf0e10cSrcweir
browseForFolder()239cdf0e10cSrcweir sal_Bool CMtaFolderPicker::browseForFolder( )
240cdf0e10cSrcweir {
241cdf0e10cSrcweir sal_Bool bRet = sal_False;
242cdf0e10cSrcweir
243cdf0e10cSrcweir if (IsMTA())
244cdf0e10cSrcweir {
245cdf0e10cSrcweir
246cdf0e10cSrcweir OSL_ASSERT( m_hEvtThrdReady );
247cdf0e10cSrcweir
248cdf0e10cSrcweir if ( WaitForSingleObject( m_hEvtThrdReady, MAX_WAITTIME ) != WAIT_OBJECT_0 )
249cdf0e10cSrcweir {
250cdf0e10cSrcweir OSL_ENSURE( sal_False, "sta thread not ready" );
251cdf0e10cSrcweir return sal_False;
252cdf0e10cSrcweir }
253cdf0e10cSrcweir
254cdf0e10cSrcweir RequestContext aReqCtx;
255cdf0e10cSrcweir
256cdf0e10cSrcweir if ( !InitializeRequestContext( &aReqCtx ) )
257cdf0e10cSrcweir {
258cdf0e10cSrcweir OSL_ASSERT( sal_False );
259cdf0e10cSrcweir return sal_False;
260cdf0e10cSrcweir }
261cdf0e10cSrcweir
262cdf0e10cSrcweir // marshall request into the sta thread
263cdf0e10cSrcweir PostMessageA(
264cdf0e10cSrcweir m_hwndStaRequestWnd,
265cdf0e10cSrcweir MSG_BROWSEFORFOLDER,
266cdf0e10cSrcweir 0,
267cdf0e10cSrcweir reinterpret_cast< LPARAM >( &aReqCtx ) );
268cdf0e10cSrcweir
269cdf0e10cSrcweir // waiting for the event to be signaled or
270cdf0e10cSrcweir // window messages so that we don't block
271cdf0e10cSrcweir // our parent window
272cdf0e10cSrcweir
273cdf0e10cSrcweir sal_Bool bContinue = sal_True;
274cdf0e10cSrcweir
275cdf0e10cSrcweir while ( bContinue )
276cdf0e10cSrcweir {
277cdf0e10cSrcweir DWORD dwResult = MsgWaitForMultipleObjects(
278cdf0e10cSrcweir 1, &aReqCtx.hEvent, sal_False, INFINITE, QS_ALLEVENTS );
279cdf0e10cSrcweir
280cdf0e10cSrcweir switch ( dwResult )
281cdf0e10cSrcweir {
282cdf0e10cSrcweir // the request context event is signaled
283cdf0e10cSrcweir case WAIT_OBJECT_0:
284cdf0e10cSrcweir bContinue = sal_False;
285cdf0e10cSrcweir break;
286cdf0e10cSrcweir
287cdf0e10cSrcweir // a window message has arrived
288cdf0e10cSrcweir case WAIT_OBJECT_0 + 1:
289cdf0e10cSrcweir {
290cdf0e10cSrcweir // dispatching all messages but we expect to
291cdf0e10cSrcweir // receive only paint or timer messages that's
292cdf0e10cSrcweir // why we don't need to call TranslateMessage or
293cdf0e10cSrcweir // TranslateAccelerator, because keybord or
294cdf0e10cSrcweir // mouse messages are for the FolderPicker which
295cdf0e10cSrcweir // is in the foreground and should not arrive here
296cdf0e10cSrcweir MSG msg;
297cdf0e10cSrcweir while ( PeekMessageA( &msg, NULL, 0, 0, PM_REMOVE ) )
298cdf0e10cSrcweir DispatchMessageA(&msg);
299cdf0e10cSrcweir }
300cdf0e10cSrcweir break;
301cdf0e10cSrcweir
302cdf0e10cSrcweir // should not happen
303cdf0e10cSrcweir default:
304cdf0e10cSrcweir OSL_ASSERT( sal_False );
305cdf0e10cSrcweir }
306cdf0e10cSrcweir }
307cdf0e10cSrcweir
308cdf0e10cSrcweir /*sal_Bool*/ bRet = aReqCtx.bRet;
309cdf0e10cSrcweir DeinitializeRequestContext( &aReqCtx );
310cdf0e10cSrcweir }
311cdf0e10cSrcweir else
312cdf0e10cSrcweir {
313cdf0e10cSrcweir bRet = onBrowseForFolder();
314cdf0e10cSrcweir }
315cdf0e10cSrcweir
316cdf0e10cSrcweir return bRet;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir
319cdf0e10cSrcweir //--------------------------------------------------------------------
320cdf0e10cSrcweir //
321cdf0e10cSrcweir //--------------------------------------------------------------------
322cdf0e10cSrcweir
setDisplayDirectory(const OUString & aDirectory)323cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::setDisplayDirectory( const OUString& aDirectory )
324cdf0e10cSrcweir {
325cdf0e10cSrcweir m_displayDir = aDirectory;
326cdf0e10cSrcweir }
327cdf0e10cSrcweir
328cdf0e10cSrcweir //--------------------------------------------------------------------
329cdf0e10cSrcweir //
330cdf0e10cSrcweir //--------------------------------------------------------------------
331cdf0e10cSrcweir
getDisplayDirectory()332cdf0e10cSrcweir OUString SAL_CALL CMtaFolderPicker::getDisplayDirectory( )
333cdf0e10cSrcweir {
334cdf0e10cSrcweir return m_displayDir;
335cdf0e10cSrcweir }
336cdf0e10cSrcweir
337cdf0e10cSrcweir //--------------------------------------------------------------------
338cdf0e10cSrcweir //
339cdf0e10cSrcweir //--------------------------------------------------------------------
340cdf0e10cSrcweir
getDirectory()341cdf0e10cSrcweir OUString SAL_CALL CMtaFolderPicker::getDirectory( )
342cdf0e10cSrcweir {
343cdf0e10cSrcweir return m_SelectedDir;
344cdf0e10cSrcweir }
345cdf0e10cSrcweir
346cdf0e10cSrcweir //--------------------------------------------------------------------
347cdf0e10cSrcweir //
348cdf0e10cSrcweir //--------------------------------------------------------------------
349cdf0e10cSrcweir
setDescription(const rtl::OUString & aDescription)350cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::setDescription( const rtl::OUString& aDescription )
351cdf0e10cSrcweir {
352cdf0e10cSrcweir m_Description = aDescription;
353cdf0e10cSrcweir }
354cdf0e10cSrcweir
355cdf0e10cSrcweir //--------------------------------------------------------------------
356cdf0e10cSrcweir //
357cdf0e10cSrcweir //--------------------------------------------------------------------
358cdf0e10cSrcweir
setTitle(const OUString & aTitle)359cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::setTitle( const OUString& aTitle )
360cdf0e10cSrcweir {
361cdf0e10cSrcweir m_dialogTitle = aTitle;
362cdf0e10cSrcweir }
363cdf0e10cSrcweir
364cdf0e10cSrcweir //--------------------------------------------------------------------
365cdf0e10cSrcweir //
366cdf0e10cSrcweir //--------------------------------------------------------------------
367cdf0e10cSrcweir
getTitle()368cdf0e10cSrcweir OUString SAL_CALL CMtaFolderPicker::getTitle( )
369cdf0e10cSrcweir {
370cdf0e10cSrcweir return m_dialogTitle;
371cdf0e10cSrcweir }
372cdf0e10cSrcweir
373cdf0e10cSrcweir //-----------------------------------------------------
374cdf0e10cSrcweir // XCancellable
375cdf0e10cSrcweir //-----------------------------------------------------
376cdf0e10cSrcweir
cancel()377cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::cancel( )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir if ( IsWindow( m_hwnd ) )
380cdf0e10cSrcweir {
381cdf0e10cSrcweir // simulate a mouse click to the
382cdf0e10cSrcweir // cancel button
383cdf0e10cSrcweir PostMessageA(
384cdf0e10cSrcweir m_hwnd,
385cdf0e10cSrcweir WM_COMMAND,
386cdf0e10cSrcweir MAKEWPARAM( IDCANCEL, BN_CLICKED ),
387cdf0e10cSrcweir (LPARAM)GetDlgItem( m_hwnd, IDCANCEL ) );
388cdf0e10cSrcweir }
389cdf0e10cSrcweir }
390cdf0e10cSrcweir
391cdf0e10cSrcweir //--------------------------------------------------------------------
392cdf0e10cSrcweir //
393cdf0e10cSrcweir //--------------------------------------------------------------------
394cdf0e10cSrcweir
onBrowseForFolder()395cdf0e10cSrcweir sal_Bool SAL_CALL CMtaFolderPicker::onBrowseForFolder( )
396cdf0e10cSrcweir {
397cdf0e10cSrcweir sal_Bool bRet;
398cdf0e10cSrcweir LPITEMIDLIST lpiid;
399cdf0e10cSrcweir
400cdf0e10cSrcweir // pre SHBrowseFroFolder
401cdf0e10cSrcweir
402cdf0e10cSrcweir m_bi.pidlRoot = 0;
403cdf0e10cSrcweir m_bi.pszDisplayName = reinterpret_cast<LPWSTR>(m_pathBuff.get());
404cdf0e10cSrcweir
405cdf0e10cSrcweir if ( m_Description.getLength( ) )
406cdf0e10cSrcweir m_bi.lpszTitle = reinterpret_cast<LPCWSTR>(m_Description.getStr( ));
407cdf0e10cSrcweir
408cdf0e10cSrcweir lpiid = SHBrowseForFolderW( &m_bi );
409cdf0e10cSrcweir bRet = ( NULL != lpiid );
410cdf0e10cSrcweir
411cdf0e10cSrcweir // post SHBrowseForFolder
412cdf0e10cSrcweir
413cdf0e10cSrcweir m_SelectedDir = getPathFromItemIdList( lpiid );
414cdf0e10cSrcweir releaseItemIdList( lpiid );
415cdf0e10cSrcweir
416cdf0e10cSrcweir return bRet;
417cdf0e10cSrcweir }
418cdf0e10cSrcweir
419cdf0e10cSrcweir //--------------------------------------------------------------------
420cdf0e10cSrcweir //
421cdf0e10cSrcweir //--------------------------------------------------------------------
422cdf0e10cSrcweir
releaseItemIdList(LPITEMIDLIST lpItemIdList)423cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::releaseItemIdList( LPITEMIDLIST lpItemIdList )
424cdf0e10cSrcweir {
425cdf0e10cSrcweir IMallocPtr pIMalloc;
426cdf0e10cSrcweir SHGetMalloc(&pIMalloc);
427cdf0e10cSrcweir if (pIMalloc.is())
428cdf0e10cSrcweir {
429cdf0e10cSrcweir pIMalloc->Free(lpItemIdList);
430cdf0e10cSrcweir lpItemIdList = NULL;
431cdf0e10cSrcweir }
432cdf0e10cSrcweir }
433cdf0e10cSrcweir
434cdf0e10cSrcweir //--------------------------------------------------------------------
435cdf0e10cSrcweir //
436cdf0e10cSrcweir //--------------------------------------------------------------------
437cdf0e10cSrcweir
getItemIdListFromPath(const rtl::OUString & aDirectory)438cdf0e10cSrcweir LPITEMIDLIST SAL_CALL CMtaFolderPicker::getItemIdListFromPath( const rtl::OUString& aDirectory )
439cdf0e10cSrcweir {
440cdf0e10cSrcweir // parameter checking
441cdf0e10cSrcweir if ( !aDirectory.getLength( ) )
442cdf0e10cSrcweir return NULL;
443cdf0e10cSrcweir
444cdf0e10cSrcweir LPITEMIDLIST lpItemIdList(NULL);
445cdf0e10cSrcweir
446cdf0e10cSrcweir IShellFolderPtr pIShellFolder;
447cdf0e10cSrcweir SHGetDesktopFolder(&pIShellFolder);
448cdf0e10cSrcweir
449cdf0e10cSrcweir if (pIShellFolder.is())
450cdf0e10cSrcweir {
451cdf0e10cSrcweir pIShellFolder->ParseDisplayName(
452cdf0e10cSrcweir NULL,
453cdf0e10cSrcweir NULL,
454cdf0e10cSrcweir reinterpret_cast<LPWSTR>(const_cast< sal_Unicode* >( aDirectory.getStr( ) )),
455cdf0e10cSrcweir NULL,
456cdf0e10cSrcweir &lpItemIdList,
457cdf0e10cSrcweir NULL );
458cdf0e10cSrcweir }
459cdf0e10cSrcweir
460cdf0e10cSrcweir return lpItemIdList;
461cdf0e10cSrcweir }
462cdf0e10cSrcweir
463cdf0e10cSrcweir //--------------------------------------------------------------------
464cdf0e10cSrcweir //
465cdf0e10cSrcweir //--------------------------------------------------------------------
466cdf0e10cSrcweir
getPathFromItemIdList(LPCITEMIDLIST lpItemIdList)467cdf0e10cSrcweir OUString SAL_CALL CMtaFolderPicker::getPathFromItemIdList( LPCITEMIDLIST lpItemIdList )
468cdf0e10cSrcweir {
469cdf0e10cSrcweir OUString path;
470cdf0e10cSrcweir
471cdf0e10cSrcweir if ( lpItemIdList )
472cdf0e10cSrcweir {
473cdf0e10cSrcweir bool bRet = SHGetPathFromIDListW( lpItemIdList, reinterpret_cast<LPWSTR>(m_pathBuff.get()) );
474cdf0e10cSrcweir if ( bRet )
475cdf0e10cSrcweir path = m_pathBuff.get( );
476cdf0e10cSrcweir }
477cdf0e10cSrcweir
478cdf0e10cSrcweir return path;
479cdf0e10cSrcweir }
480cdf0e10cSrcweir
481cdf0e10cSrcweir //--------------------------------------------------------------------
482cdf0e10cSrcweir //
483cdf0e10cSrcweir //--------------------------------------------------------------------
484cdf0e10cSrcweir
enableOk(sal_Bool bEnable)485cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::enableOk( sal_Bool bEnable )
486cdf0e10cSrcweir {
487cdf0e10cSrcweir OSL_ASSERT( IsWindow( m_hwnd ) );
488cdf0e10cSrcweir
489cdf0e10cSrcweir SendMessageW(
490cdf0e10cSrcweir m_hwnd,
491cdf0e10cSrcweir BFFM_ENABLEOK,
492cdf0e10cSrcweir static_cast< WPARAM >( 0 ),
493cdf0e10cSrcweir static_cast< LPARAM >( bEnable ) );
494cdf0e10cSrcweir }
495cdf0e10cSrcweir
496cdf0e10cSrcweir //--------------------------------------------------------------------
497cdf0e10cSrcweir //
498cdf0e10cSrcweir //--------------------------------------------------------------------
499cdf0e10cSrcweir
setSelection(const rtl::OUString & aDirectory)500cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::setSelection( const rtl::OUString& aDirectory )
501cdf0e10cSrcweir {
502cdf0e10cSrcweir OSL_ASSERT( IsWindow( m_hwnd ) );
503cdf0e10cSrcweir
504cdf0e10cSrcweir #ifdef _MSC_VER
505cdf0e10cSrcweir #pragma message( "#######################################" )
506cdf0e10cSrcweir #pragma message( "SendMessageW wrapper has to be extended" )
507cdf0e10cSrcweir #pragma message( "#######################################" )
508cdf0e10cSrcweir #endif
509cdf0e10cSrcweir
510cdf0e10cSrcweir SendMessageW(
511cdf0e10cSrcweir m_hwnd,
512cdf0e10cSrcweir BFFM_SETSELECTIONW,
513cdf0e10cSrcweir static_cast< WPARAM >( sal_True ),
514cdf0e10cSrcweir reinterpret_cast< LPARAM >( aDirectory.getStr( ) ) );
515cdf0e10cSrcweir }
516cdf0e10cSrcweir
517cdf0e10cSrcweir //--------------------------------------------------------------------
518cdf0e10cSrcweir //
519cdf0e10cSrcweir //--------------------------------------------------------------------
520cdf0e10cSrcweir
setStatusText(const rtl::OUString & aStatusText)521cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::setStatusText( const rtl::OUString& aStatusText )
522cdf0e10cSrcweir {
523cdf0e10cSrcweir OSL_ASSERT( IsWindow( m_hwnd ) );
524cdf0e10cSrcweir
525cdf0e10cSrcweir SendMessageW(
526cdf0e10cSrcweir m_hwnd,
527cdf0e10cSrcweir BFFM_SETSTATUSTEXTW,
528cdf0e10cSrcweir static_cast< WPARAM >( 0 ),
529cdf0e10cSrcweir reinterpret_cast< LPARAM >( aStatusText.getStr( ) ) );
530cdf0e10cSrcweir }
531cdf0e10cSrcweir
532cdf0e10cSrcweir //--------------------------------------------------------------------
533cdf0e10cSrcweir //
534cdf0e10cSrcweir //--------------------------------------------------------------------
535cdf0e10cSrcweir
onInitialized()536cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::onInitialized( )
537cdf0e10cSrcweir {
538cdf0e10cSrcweir LPITEMIDLIST lpiidDisplayDir = getItemIdListFromPath( m_displayDir );
539cdf0e10cSrcweir
540cdf0e10cSrcweir if ( lpiidDisplayDir )
541cdf0e10cSrcweir {
542cdf0e10cSrcweir SendMessageA(
543cdf0e10cSrcweir m_hwnd,
544cdf0e10cSrcweir BFFM_SETSELECTION,
545cdf0e10cSrcweir (WPARAM)sal_False,
546cdf0e10cSrcweir (LPARAM) lpiidDisplayDir );
547cdf0e10cSrcweir
548cdf0e10cSrcweir releaseItemIdList( lpiidDisplayDir );
549cdf0e10cSrcweir }
550cdf0e10cSrcweir }
551cdf0e10cSrcweir
552cdf0e10cSrcweir //--------------------------------------------------------------------
553cdf0e10cSrcweir //
554cdf0e10cSrcweir //--------------------------------------------------------------------
555cdf0e10cSrcweir
onValidateFailed()556cdf0e10cSrcweir sal_uInt32 CMtaFolderPicker::onValidateFailed()
557cdf0e10cSrcweir {
558cdf0e10cSrcweir // to be overwritten by subclasses
559cdf0e10cSrcweir return 1;
560cdf0e10cSrcweir }
561cdf0e10cSrcweir
562cdf0e10cSrcweir //--------------------------------------------------------------------
563cdf0e10cSrcweir //
564cdf0e10cSrcweir //--------------------------------------------------------------------
565cdf0e10cSrcweir
FolderPickerCallback(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)566cdf0e10cSrcweir int CALLBACK CMtaFolderPicker::FolderPickerCallback( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
567cdf0e10cSrcweir {
568cdf0e10cSrcweir CMtaFolderPicker* pImpl = reinterpret_cast< CMtaFolderPicker* >( lpData );
569cdf0e10cSrcweir OSL_ASSERT( pImpl );
570cdf0e10cSrcweir
571cdf0e10cSrcweir int nRC = 0;
572cdf0e10cSrcweir
573cdf0e10cSrcweir switch( uMsg )
574cdf0e10cSrcweir {
575cdf0e10cSrcweir case BFFM_INITIALIZED:
576cdf0e10cSrcweir pImpl->m_hwnd = hwnd;
577cdf0e10cSrcweir pImpl->onInitialized( );
578cdf0e10cSrcweir SetWindowTextW( hwnd, reinterpret_cast<LPCWSTR>(pImpl->m_dialogTitle.getStr()) );
579cdf0e10cSrcweir break;
580cdf0e10cSrcweir
581cdf0e10cSrcweir case BFFM_SELCHANGED:
582cdf0e10cSrcweir pImpl->m_hwnd = hwnd;
583cdf0e10cSrcweir pImpl->onSelChanged(
584cdf0e10cSrcweir pImpl->getPathFromItemIdList(
585cdf0e10cSrcweir reinterpret_cast< LPITEMIDLIST >( lParam ) ) );
586cdf0e10cSrcweir break;
587cdf0e10cSrcweir
588cdf0e10cSrcweir case BFFM_VALIDATEFAILEDW:
589cdf0e10cSrcweir nRC = pImpl->onValidateFailed();
590cdf0e10cSrcweir break;
591cdf0e10cSrcweir
592cdf0e10cSrcweir default:
593cdf0e10cSrcweir OSL_ASSERT( sal_False );
594cdf0e10cSrcweir }
595cdf0e10cSrcweir
596cdf0e10cSrcweir return nRC;
597cdf0e10cSrcweir }
598cdf0e10cSrcweir
599cdf0e10cSrcweir //--------------------------------------------------------------------
600cdf0e10cSrcweir // the window proc
601cdf0e10cSrcweir //--------------------------------------------------------------------
602cdf0e10cSrcweir
StaWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)603cdf0e10cSrcweir LRESULT CALLBACK CMtaFolderPicker::StaWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
604cdf0e10cSrcweir {
605cdf0e10cSrcweir LRESULT lResult = 0;
606cdf0e10cSrcweir CMtaFolderPicker* pImpl = NULL;
607cdf0e10cSrcweir
608cdf0e10cSrcweir /*
609cdf0e10cSrcweir we connect to the belonging class instance of this
610cdf0e10cSrcweir window using SetProp, GetProp etc.
611cdf0e10cSrcweir this may fail if somehow the class instance destroyed
612cdf0e10cSrcweir before the window
613cdf0e10cSrcweir */
614cdf0e10cSrcweir
615cdf0e10cSrcweir switch( uMsg )
616cdf0e10cSrcweir {
617cdf0e10cSrcweir case WM_CREATE:
618cdf0e10cSrcweir {
619cdf0e10cSrcweir LPCREATESTRUCT lpcs =
620cdf0e10cSrcweir reinterpret_cast< LPCREATESTRUCT >( lParam );
621cdf0e10cSrcweir
622cdf0e10cSrcweir OSL_ASSERT( lpcs->lpCreateParams );
623cdf0e10cSrcweir
624cdf0e10cSrcweir // connect the instance handle to the window
625cdf0e10cSrcweir SetPropA( hWnd, CURRENT_INSTANCE, lpcs->lpCreateParams );
626cdf0e10cSrcweir }
627cdf0e10cSrcweir break;
628cdf0e10cSrcweir
629cdf0e10cSrcweir case WM_NCDESTROY:
630cdf0e10cSrcweir // RemoveProp returns the saved value on success
631cdf0e10cSrcweir pImpl = reinterpret_cast< CMtaFolderPicker* >(
632cdf0e10cSrcweir RemovePropA( hWnd, CURRENT_INSTANCE ) );
633cdf0e10cSrcweir
634cdf0e10cSrcweir OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
635cdf0e10cSrcweir break;
636cdf0e10cSrcweir
637cdf0e10cSrcweir case MSG_BROWSEFORFOLDER:
638cdf0e10cSrcweir {
639cdf0e10cSrcweir RequestContext* aReqCtx = reinterpret_cast< RequestContext* >( lParam );
640cdf0e10cSrcweir OSL_ASSERT( aReqCtx );
641cdf0e10cSrcweir
642cdf0e10cSrcweir pImpl = reinterpret_cast< CMtaFolderPicker* >(
643cdf0e10cSrcweir GetPropA( hWnd, CURRENT_INSTANCE ) );
644cdf0e10cSrcweir
645cdf0e10cSrcweir OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
646cdf0e10cSrcweir
647cdf0e10cSrcweir aReqCtx->bRet = pImpl->onBrowseForFolder( );
648cdf0e10cSrcweir SetEvent( aReqCtx->hEvent );
649cdf0e10cSrcweir }
650cdf0e10cSrcweir break;
651cdf0e10cSrcweir
652cdf0e10cSrcweir case MSG_SHUTDOWN:
653cdf0e10cSrcweir pImpl = reinterpret_cast< CMtaFolderPicker* >(
654cdf0e10cSrcweir GetPropA( hWnd, CURRENT_INSTANCE ) );
655cdf0e10cSrcweir
656cdf0e10cSrcweir OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
657cdf0e10cSrcweir
658cdf0e10cSrcweir DestroyWindow( pImpl->m_hwndStaRequestWnd );
659cdf0e10cSrcweir break;
660cdf0e10cSrcweir
661cdf0e10cSrcweir case WM_DESTROY:
662cdf0e10cSrcweir PostQuitMessage( 0 );
663cdf0e10cSrcweir break;
664cdf0e10cSrcweir
665cdf0e10cSrcweir default:
666cdf0e10cSrcweir lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
667cdf0e10cSrcweir break;
668cdf0e10cSrcweir }
669cdf0e10cSrcweir
670cdf0e10cSrcweir return lResult;
671cdf0e10cSrcweir }
672cdf0e10cSrcweir
673cdf0e10cSrcweir //--------------------------------------------------------------------
674cdf0e10cSrcweir //
675cdf0e10cSrcweir //--------------------------------------------------------------------
676cdf0e10cSrcweir
createStaRequestWindow()677cdf0e10cSrcweir sal_Bool SAL_CALL CMtaFolderPicker::createStaRequestWindow( )
678cdf0e10cSrcweir {
679cdf0e10cSrcweir bool bIsWnd = false;
680cdf0e10cSrcweir
681cdf0e10cSrcweir if ( RegisterStaRequestWindowClass( ) )
682cdf0e10cSrcweir {
683cdf0e10cSrcweir m_hwndStaRequestWnd = CreateWindowA(
684cdf0e10cSrcweir g_szWndClsName, NULL,
685cdf0e10cSrcweir 0, 0, 0, 0, 0,
686cdf0e10cSrcweir NULL, NULL, m_hInstance,
687cdf0e10cSrcweir (LPVOID)this // provide the instance of the class
688cdf0e10cSrcweir );
689cdf0e10cSrcweir
690cdf0e10cSrcweir bIsWnd = IsWindow( m_hwndStaRequestWnd );
691cdf0e10cSrcweir
692cdf0e10cSrcweir // we do immediately unregister the window class
693cdf0e10cSrcweir // if the creation of the window fails because we
694cdf0e10cSrcweir // don't want to spoil the register class counter
695cdf0e10cSrcweir if ( !bIsWnd )
696cdf0e10cSrcweir UnregisterStaRequestWindowClass( );
697cdf0e10cSrcweir
698cdf0e10cSrcweir OSL_ENSURE( bIsWnd, "sta request window creation failed" );
699cdf0e10cSrcweir }
700cdf0e10cSrcweir
701cdf0e10cSrcweir return bIsWnd;
702cdf0e10cSrcweir }
703cdf0e10cSrcweir
704cdf0e10cSrcweir //--------------------------------------------------------------------
705cdf0e10cSrcweir //
706cdf0e10cSrcweir //--------------------------------------------------------------------
707cdf0e10cSrcweir
run()708cdf0e10cSrcweir unsigned int CMtaFolderPicker::run( )
709cdf0e10cSrcweir {
710cdf0e10cSrcweir OSL_ASSERT( m_hEvtThrdReady );
711cdf0e10cSrcweir
712cdf0e10cSrcweir // setup an sta environment
713cdf0e10cSrcweir HRESULT hr = CoInitialize( NULL );
714cdf0e10cSrcweir
715cdf0e10cSrcweir // if we can't setup an sta environment
716cdf0e10cSrcweir // we stop here and return
717cdf0e10cSrcweir if ( FAILED( hr ) )
718cdf0e10cSrcweir {
719cdf0e10cSrcweir OSL_ENSURE( sal_False, "CoInitialize failed" );
720cdf0e10cSrcweir return sal::static_int_cast< unsigned int >(-1);
721cdf0e10cSrcweir }
722cdf0e10cSrcweir
723cdf0e10cSrcweir unsigned int nRet;
724cdf0e10cSrcweir
725cdf0e10cSrcweir if ( createStaRequestWindow( ) )
726cdf0e10cSrcweir {
727cdf0e10cSrcweir SetEvent( m_hEvtThrdReady );
728cdf0e10cSrcweir
729cdf0e10cSrcweir // pumping messages
730cdf0e10cSrcweir MSG msg;
731cdf0e10cSrcweir while( GetMessageA( &msg, NULL, 0, 0 ) )
732cdf0e10cSrcweir DispatchMessageA( &msg );
733cdf0e10cSrcweir
734cdf0e10cSrcweir nRet = 0;
735cdf0e10cSrcweir }
736cdf0e10cSrcweir else
737cdf0e10cSrcweir {
738cdf0e10cSrcweir OSL_ENSURE( sal_False, "failed to create sta thread" );
739cdf0e10cSrcweir nRet = sal::static_int_cast< unsigned int >(-1);
740cdf0e10cSrcweir }
741cdf0e10cSrcweir
742cdf0e10cSrcweir // shutdown sta environment
743cdf0e10cSrcweir CoUninitialize( );
744cdf0e10cSrcweir
745cdf0e10cSrcweir return nRet;
746cdf0e10cSrcweir }
747cdf0e10cSrcweir
748cdf0e10cSrcweir //--------------------------------------------------------------------
749cdf0e10cSrcweir //
750cdf0e10cSrcweir //--------------------------------------------------------------------
751cdf0e10cSrcweir
StaThreadProc(LPVOID pParam)752cdf0e10cSrcweir unsigned int WINAPI CMtaFolderPicker::StaThreadProc( LPVOID pParam )
753cdf0e10cSrcweir {
754cdf0e10cSrcweir CMtaFolderPicker* pInst =
755cdf0e10cSrcweir reinterpret_cast<CMtaFolderPicker*>( pParam );
756cdf0e10cSrcweir
757cdf0e10cSrcweir OSL_ASSERT( pInst );
758cdf0e10cSrcweir
759cdf0e10cSrcweir HRESULT hr = OleInitialize( NULL );
760cdf0e10cSrcweir
761cdf0e10cSrcweir unsigned int result = pInst->run( );
762cdf0e10cSrcweir
763cdf0e10cSrcweir if ( SUCCEEDED( hr ) )
764cdf0e10cSrcweir OleUninitialize();
765cdf0e10cSrcweir
766cdf0e10cSrcweir return result;
767cdf0e10cSrcweir }
768cdf0e10cSrcweir
769cdf0e10cSrcweir //---------------------------------------------------
770cdf0e10cSrcweir //
771cdf0e10cSrcweir //---------------------------------------------------
772cdf0e10cSrcweir
RegisterStaRequestWindowClass()773cdf0e10cSrcweir ATOM SAL_CALL CMtaFolderPicker::RegisterStaRequestWindowClass( )
774cdf0e10cSrcweir {
775cdf0e10cSrcweir osl::MutexGuard aGuard( s_Mutex );
776cdf0e10cSrcweir
777cdf0e10cSrcweir if ( 0 == s_ClassAtom )
778cdf0e10cSrcweir {
779cdf0e10cSrcweir WNDCLASSEXA wcex;
780cdf0e10cSrcweir
781cdf0e10cSrcweir ZeroMemory( &wcex, sizeof( WNDCLASSEXA ) );
782cdf0e10cSrcweir
783cdf0e10cSrcweir wcex.cbSize = sizeof(WNDCLASSEXA);
784cdf0e10cSrcweir wcex.style = 0;
785cdf0e10cSrcweir wcex.lpfnWndProc = static_cast< WNDPROC >( CMtaFolderPicker::StaWndProc );
786cdf0e10cSrcweir wcex.cbClsExtra = 0;
787cdf0e10cSrcweir wcex.cbWndExtra = 0;
788cdf0e10cSrcweir wcex.hInstance = m_hInstance;
789cdf0e10cSrcweir wcex.hIcon = NULL;
790cdf0e10cSrcweir wcex.hCursor = NULL;
791cdf0e10cSrcweir wcex.hbrBackground = NULL;
792cdf0e10cSrcweir wcex.lpszMenuName = NULL;
793cdf0e10cSrcweir wcex.lpszClassName = g_szWndClsName;
794cdf0e10cSrcweir wcex.hIconSm = NULL;
795cdf0e10cSrcweir
796cdf0e10cSrcweir s_ClassAtom = RegisterClassExA( &wcex );
797cdf0e10cSrcweir OSL_ASSERT( s_ClassAtom );
798cdf0e10cSrcweir }
799cdf0e10cSrcweir
800cdf0e10cSrcweir // increment the register class counter
801cdf0e10cSrcweir // so that we keep track of the number
802cdf0e10cSrcweir // of class registrations
803cdf0e10cSrcweir if ( 0 != s_ClassAtom )
804cdf0e10cSrcweir s_StaRequestWndRegisterCount++;
805cdf0e10cSrcweir
806cdf0e10cSrcweir return s_ClassAtom;
807cdf0e10cSrcweir }
808cdf0e10cSrcweir
809cdf0e10cSrcweir //---------------------------------------------------
810cdf0e10cSrcweir //
811cdf0e10cSrcweir //---------------------------------------------------
812cdf0e10cSrcweir
UnregisterStaRequestWindowClass()813cdf0e10cSrcweir void SAL_CALL CMtaFolderPicker::UnregisterStaRequestWindowClass( )
814cdf0e10cSrcweir {
815cdf0e10cSrcweir osl::MutexGuard aGuard( s_Mutex );
816cdf0e10cSrcweir
817cdf0e10cSrcweir OSL_ASSERT( 0 != s_ClassAtom );
818cdf0e10cSrcweir
819cdf0e10cSrcweir // update the register class counter
820cdf0e10cSrcweir // and unregister the window class if
821cdf0e10cSrcweir // counter drops to zero
822cdf0e10cSrcweir if ( 0 != s_ClassAtom )
823cdf0e10cSrcweir {
824cdf0e10cSrcweir s_StaRequestWndRegisterCount--;
825cdf0e10cSrcweir OSL_ASSERT( s_StaRequestWndRegisterCount >= 0 );
826cdf0e10cSrcweir }
827cdf0e10cSrcweir
828cdf0e10cSrcweir if ( 0 == s_StaRequestWndRegisterCount )
829cdf0e10cSrcweir {
830cdf0e10cSrcweir UnregisterClass(
831cdf0e10cSrcweir (LPCTSTR)MAKELONG( s_ClassAtom, 0 ), m_hInstance );
832cdf0e10cSrcweir
833cdf0e10cSrcweir s_ClassAtom = 0;
834cdf0e10cSrcweir }
835cdf0e10cSrcweir }
836