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