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