Fixes #fdo30794 Based on bin/add-modelines script (originally posted in mail 1286706307.1871.1399280959@webmail.messagingengine.com) Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
843 lines
23 KiB
C++
843 lines
23 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_fpicker.hxx"
|
|
#include <osl/diagnose.h>
|
|
#include <osl/conditn.hxx>
|
|
|
|
#include "MtaFop.hxx"
|
|
#include <wchar.h>
|
|
#include <process.h>
|
|
#include "..\misc\resourceprovider.hxx"
|
|
|
|
#include <systools/win32/comtools.hxx>
|
|
|
|
using rtl::OUString;
|
|
using osl::Condition;
|
|
|
|
const sal_uInt32 MSG_BROWSEFORFOLDER = WM_USER + 1;
|
|
const sal_uInt32 MSG_SHUTDOWN = WM_USER + 2;
|
|
|
|
const sal_uInt32 MAX_WAITTIME = 2000; // msec
|
|
|
|
const sal_Bool MANUAL_RESET = sal_True;
|
|
const sal_Bool AUTO_RESET = sal_False;
|
|
const sal_Bool INIT_NONSIGNALED = sal_False;
|
|
|
|
typedef sal::systools::COMReference<IMalloc> IMallocPtr;
|
|
typedef sal::systools::COMReference<IShellFolder> IShellFolderPtr;
|
|
|
|
namespace
|
|
{
|
|
const char* FOLDERPICKER_SRV_DLL_NAME = "fop.dll";
|
|
const char g_szWndClsName[] = "FopStaReqWnd###";
|
|
const char* CURRENT_INSTANCE = "CurrInst";
|
|
|
|
typedef struct _RequestContext
|
|
{
|
|
HANDLE hEvent;
|
|
sal_Bool bRet;
|
|
} RequestContext;
|
|
|
|
inline sal_Bool InitializeRequestContext( RequestContext* aRequestContext )
|
|
{
|
|
OSL_ASSERT( aRequestContext );
|
|
|
|
aRequestContext->hEvent = CreateEventA(
|
|
0, AUTO_RESET, INIT_NONSIGNALED, NULL );
|
|
|
|
aRequestContext->bRet = sal_False;
|
|
|
|
return ( 0 != aRequestContext->hEvent );
|
|
}
|
|
|
|
inline void DeinitializeRequestContext( RequestContext* aRequestContext )
|
|
{
|
|
OSL_ASSERT( aRequestContext && aRequestContext->hEvent );
|
|
CloseHandle( aRequestContext->hEvent );
|
|
}
|
|
|
|
//-------------------------------
|
|
// Determine if current thread is
|
|
// an MTA or STA thread
|
|
//-------------------------------
|
|
bool IsMTA()
|
|
{
|
|
HRESULT hr = CoInitialize(NULL);
|
|
|
|
if (RPC_E_CHANGED_MODE == hr)
|
|
return true;
|
|
|
|
if(SUCCEEDED(hr))
|
|
CoUninitialize();
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
// static member initialization
|
|
//----------------------------------------------------------------
|
|
|
|
ATOM CMtaFolderPicker::s_ClassAtom = 0;
|
|
osl::Mutex CMtaFolderPicker::s_Mutex;
|
|
sal_Int32 CMtaFolderPicker::s_StaRequestWndRegisterCount = 0;
|
|
|
|
//--------------------------------------------------------------------
|
|
// ctor
|
|
//--------------------------------------------------------------------
|
|
|
|
CMtaFolderPicker::CMtaFolderPicker( sal_uInt32 Flags ) :
|
|
m_hStaThread( NULL ),
|
|
m_uStaThreadId( 0 ),
|
|
m_hEvtThrdReady( NULL ),
|
|
m_hwndStaRequestWnd( NULL )
|
|
{
|
|
m_hInstance = GetModuleHandleA( FOLDERPICKER_SRV_DLL_NAME );
|
|
OSL_ENSURE( m_hInstance, "The name of the FolderPicker service dll must have changed" );
|
|
|
|
ZeroMemory( &m_bi, sizeof( m_bi ) );
|
|
|
|
// !!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!
|
|
//
|
|
// Remember: This HACK prevents you from stepping
|
|
// through your code in the debugger because if you
|
|
// set a break point in the ctor here the debugger
|
|
// may become the owner of the FolderBrowse dialog
|
|
// and so it seems that the Visual Studio and the
|
|
// office are hanging
|
|
m_bi.hwndOwner = GetForegroundWindow( );
|
|
|
|
/*
|
|
Flag Available
|
|
--------------------------------
|
|
BIF_EDITBOX Version 4.71
|
|
BIF_NEWDIALOGSTYLE Version 5.0
|
|
BIF_SHAREABLE Version 5.0
|
|
BIF_VALIDATE Version 4.71
|
|
|
|
Version 4.71 - Internet Explorer 4.0
|
|
Version 5.0 - Internet Explorer 5.0
|
|
Windows 2000
|
|
*/
|
|
m_bi.ulFlags = Flags;
|
|
|
|
m_bi.lpfn = CMtaFolderPicker::FolderPickerCallback;
|
|
m_bi.lParam = reinterpret_cast< LPARAM >( this );
|
|
|
|
//---------------------------------------
|
|
// read the default strings for title and
|
|
// description from a resource file
|
|
|
|
CResourceProvider ResProvider;
|
|
|
|
m_dialogTitle = ResProvider.getResString( 500 );
|
|
m_Description = ResProvider.getResString( 501 );
|
|
|
|
// signals that the thread was successfully set up
|
|
m_hEvtThrdReady = CreateEventA(
|
|
0,
|
|
MANUAL_RESET,
|
|
INIT_NONSIGNALED,
|
|
NULL );
|
|
|
|
if ( m_hEvtThrdReady )
|
|
{
|
|
// setup the sta thread
|
|
m_hStaThread = (HANDLE)_beginthreadex(
|
|
NULL,
|
|
0,
|
|
CMtaFolderPicker::StaThreadProc,
|
|
this,
|
|
0,
|
|
&m_uStaThreadId );
|
|
|
|
OSL_ASSERT( m_hStaThread );
|
|
}
|
|
|
|
OSL_ASSERT( m_hEvtThrdReady );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// dtor
|
|
//--------------------------------------------------------------------
|
|
|
|
CMtaFolderPicker::~CMtaFolderPicker( )
|
|
{
|
|
// only if the is a valid event handle
|
|
// there may also be a thread a hidden
|
|
// target request window and so on
|
|
// see ctor
|
|
if ( m_hEvtThrdReady )
|
|
{
|
|
// block calling threads because we
|
|
// are about to shutdown
|
|
ResetEvent( m_hEvtThrdReady );
|
|
|
|
// force the destruction of the sta thread request window
|
|
// and the end of the thread
|
|
// remeber: DestroyWindow may only be called from within
|
|
// the thread that created the window
|
|
if ( IsWindow( m_hwndStaRequestWnd ) )
|
|
{
|
|
SendMessageA( m_hwndStaRequestWnd, MSG_SHUTDOWN, 0, 0 );
|
|
|
|
// we place unregister class here because
|
|
// if we have a valid window we must have
|
|
// sucessfully registered a window class
|
|
// if the creation of the window itself
|
|
// failed after registering the window
|
|
// class we have unregistered it immediately
|
|
// in createStaRequestWindow below
|
|
UnregisterStaRequestWindowClass( );
|
|
}
|
|
|
|
if ( m_hStaThread )
|
|
{
|
|
// wait for thread shutdown
|
|
sal_uInt32 dwResult = WaitForSingleObject( m_hStaThread, MAX_WAITTIME );
|
|
OSL_ENSURE( dwResult == WAIT_OBJECT_0, "sta thread could not terminate" );
|
|
|
|
// terminate the thread if it
|
|
// doesn't shutdown itself
|
|
if ( WAIT_OBJECT_0 != dwResult )
|
|
TerminateThread(
|
|
m_hStaThread, sal::static_int_cast< DWORD >(-1) );
|
|
|
|
CloseHandle( m_hStaThread );
|
|
}
|
|
|
|
CloseHandle( m_hEvtThrdReady );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
sal_Bool CMtaFolderPicker::browseForFolder( )
|
|
{
|
|
sal_Bool bRet = sal_False;
|
|
|
|
if (IsMTA())
|
|
{
|
|
|
|
OSL_ASSERT( m_hEvtThrdReady );
|
|
|
|
if ( WaitForSingleObject( m_hEvtThrdReady, MAX_WAITTIME ) != WAIT_OBJECT_0 )
|
|
{
|
|
OSL_ENSURE( sal_False, "sta thread not ready" );
|
|
return sal_False;
|
|
}
|
|
|
|
RequestContext aReqCtx;
|
|
|
|
if ( !InitializeRequestContext( &aReqCtx ) )
|
|
{
|
|
OSL_ASSERT( sal_False );
|
|
return sal_False;
|
|
}
|
|
|
|
// marshall request into the sta thread
|
|
PostMessageA(
|
|
m_hwndStaRequestWnd,
|
|
MSG_BROWSEFORFOLDER,
|
|
0,
|
|
reinterpret_cast< LPARAM >( &aReqCtx ) );
|
|
|
|
// waiting for the event to be signaled or
|
|
// window messages so that we don't block
|
|
// our parent window
|
|
|
|
sal_Bool bContinue = sal_True;
|
|
|
|
while ( bContinue )
|
|
{
|
|
DWORD dwResult = MsgWaitForMultipleObjects(
|
|
1, &aReqCtx.hEvent, FALSE, INFINITE, QS_ALLEVENTS );
|
|
|
|
switch ( dwResult )
|
|
{
|
|
// the request context event is signaled
|
|
case WAIT_OBJECT_0:
|
|
bContinue = sal_False;
|
|
break;
|
|
|
|
// a window message has arrived
|
|
case WAIT_OBJECT_0 + 1:
|
|
{
|
|
// dispatching all messages but we expect to
|
|
// receive only paint or timer messages that's
|
|
// why we don't need to call TranslateMessage or
|
|
// TranslateAccelerator, because keybord or
|
|
// mouse messages are for the FolderPicker which
|
|
// is in the foreground and should not arrive here
|
|
MSG msg;
|
|
while ( PeekMessageA( &msg, NULL, 0, 0, PM_REMOVE ) )
|
|
DispatchMessageA(&msg);
|
|
}
|
|
break;
|
|
|
|
// should not happen
|
|
default:
|
|
OSL_ASSERT( sal_False );
|
|
}
|
|
}
|
|
|
|
/*sal_Bool*/ bRet = aReqCtx.bRet;
|
|
DeinitializeRequestContext( &aReqCtx );
|
|
}
|
|
else
|
|
{
|
|
bRet = onBrowseForFolder();
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::setDisplayDirectory( const OUString& aDirectory )
|
|
{
|
|
m_displayDir = aDirectory;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
OUString SAL_CALL CMtaFolderPicker::getDisplayDirectory( )
|
|
{
|
|
return m_displayDir;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
OUString SAL_CALL CMtaFolderPicker::getDirectory( )
|
|
{
|
|
return m_SelectedDir;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::setDescription( const rtl::OUString& aDescription )
|
|
{
|
|
m_Description = aDescription;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::setTitle( const OUString& aTitle )
|
|
{
|
|
m_dialogTitle = aTitle;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
OUString SAL_CALL CMtaFolderPicker::getTitle( )
|
|
{
|
|
return m_dialogTitle;
|
|
}
|
|
|
|
//-----------------------------------------------------
|
|
// XCancellable
|
|
//-----------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::cancel( )
|
|
{
|
|
if ( IsWindow( m_hwnd ) )
|
|
{
|
|
// simulate a mouse click to the
|
|
// cancel button
|
|
PostMessageA(
|
|
m_hwnd,
|
|
WM_COMMAND,
|
|
MAKEWPARAM( IDCANCEL, BN_CLICKED ),
|
|
(LPARAM)GetDlgItem( m_hwnd, IDCANCEL ) );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL CMtaFolderPicker::onBrowseForFolder( )
|
|
{
|
|
sal_Bool bRet;
|
|
LPITEMIDLIST lpiid;
|
|
|
|
// pre SHBrowseFroFolder
|
|
|
|
m_bi.pidlRoot = 0;
|
|
m_bi.pszDisplayName = reinterpret_cast<LPWSTR>(m_pathBuff.get());
|
|
|
|
if ( m_Description.getLength( ) )
|
|
m_bi.lpszTitle = reinterpret_cast<LPCWSTR>(m_Description.getStr( ));
|
|
|
|
lpiid = SHBrowseForFolderW( &m_bi );
|
|
bRet = ( NULL != lpiid );
|
|
|
|
// post SHBrowseForFolder
|
|
|
|
m_SelectedDir = getPathFromItemIdList( lpiid );
|
|
releaseItemIdList( lpiid );
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::releaseItemIdList( LPITEMIDLIST lpItemIdList )
|
|
{
|
|
IMallocPtr pIMalloc;
|
|
SHGetMalloc(&pIMalloc);
|
|
if (pIMalloc.is())
|
|
{
|
|
pIMalloc->Free(lpItemIdList);
|
|
lpItemIdList = NULL;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LPITEMIDLIST SAL_CALL CMtaFolderPicker::getItemIdListFromPath( const rtl::OUString& aDirectory )
|
|
{
|
|
// parameter checking
|
|
if ( !aDirectory.getLength( ) )
|
|
return NULL;
|
|
|
|
LPITEMIDLIST lpItemIdList(NULL);
|
|
|
|
IShellFolderPtr pIShellFolder;
|
|
SHGetDesktopFolder(&pIShellFolder);
|
|
|
|
if (pIShellFolder.is())
|
|
{
|
|
pIShellFolder->ParseDisplayName(
|
|
NULL,
|
|
NULL,
|
|
reinterpret_cast<LPWSTR>(const_cast< sal_Unicode* >( aDirectory.getStr( ) )),
|
|
NULL,
|
|
&lpItemIdList,
|
|
NULL );
|
|
}
|
|
|
|
return lpItemIdList;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
OUString SAL_CALL CMtaFolderPicker::getPathFromItemIdList( LPCITEMIDLIST lpItemIdList )
|
|
{
|
|
OUString path;
|
|
|
|
if ( lpItemIdList )
|
|
{
|
|
bool bRet = SHGetPathFromIDListW( lpItemIdList, reinterpret_cast<LPWSTR>(m_pathBuff.get()) );
|
|
if ( bRet )
|
|
path = m_pathBuff.get( );
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::enableOk( sal_Bool bEnable )
|
|
{
|
|
OSL_ASSERT( IsWindow( m_hwnd ) );
|
|
|
|
SendMessageW(
|
|
m_hwnd,
|
|
BFFM_ENABLEOK,
|
|
static_cast< WPARAM >( 0 ),
|
|
static_cast< LPARAM >( bEnable ) );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::setSelection( const rtl::OUString& aDirectory )
|
|
{
|
|
OSL_ASSERT( IsWindow( m_hwnd ) );
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma message( "#######################################" )
|
|
#pragma message( "SendMessageW wrapper has to be extended" )
|
|
#pragma message( "#######################################" )
|
|
#endif
|
|
|
|
SendMessageW(
|
|
m_hwnd,
|
|
BFFM_SETSELECTIONW,
|
|
static_cast< WPARAM >( sal_True ),
|
|
reinterpret_cast< LPARAM >( aDirectory.getStr( ) ) );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::setStatusText( const rtl::OUString& aStatusText )
|
|
{
|
|
OSL_ASSERT( IsWindow( m_hwnd ) );
|
|
|
|
SendMessageW(
|
|
m_hwnd,
|
|
BFFM_SETSTATUSTEXTW,
|
|
static_cast< WPARAM >( 0 ),
|
|
reinterpret_cast< LPARAM >( aStatusText.getStr( ) ) );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::onInitialized( )
|
|
{
|
|
LPITEMIDLIST lpiidDisplayDir = getItemIdListFromPath( m_displayDir );
|
|
|
|
if ( lpiidDisplayDir )
|
|
{
|
|
SendMessageA(
|
|
m_hwnd,
|
|
BFFM_SETSELECTION,
|
|
(WPARAM)FALSE,
|
|
(LPARAM) lpiidDisplayDir );
|
|
|
|
releaseItemIdList( lpiidDisplayDir );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
sal_uInt32 CMtaFolderPicker::onValidateFailed()
|
|
{
|
|
// to be overwritten by subclasses
|
|
return 1;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
int CALLBACK CMtaFolderPicker::FolderPickerCallback( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
|
|
{
|
|
CMtaFolderPicker* pImpl = reinterpret_cast< CMtaFolderPicker* >( lpData );
|
|
OSL_ASSERT( pImpl );
|
|
|
|
int nRC = 0;
|
|
|
|
switch( uMsg )
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
pImpl->m_hwnd = hwnd;
|
|
pImpl->onInitialized( );
|
|
SetWindowTextW( hwnd, reinterpret_cast<LPCWSTR>(pImpl->m_dialogTitle.getStr()) );
|
|
break;
|
|
|
|
case BFFM_SELCHANGED:
|
|
pImpl->m_hwnd = hwnd;
|
|
pImpl->onSelChanged(
|
|
pImpl->getPathFromItemIdList(
|
|
reinterpret_cast< LPITEMIDLIST >( lParam ) ) );
|
|
break;
|
|
|
|
case BFFM_VALIDATEFAILEDW:
|
|
nRC = pImpl->onValidateFailed();
|
|
break;
|
|
|
|
default:
|
|
OSL_ASSERT( sal_False );
|
|
}
|
|
|
|
return nRC;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// the window proc
|
|
//--------------------------------------------------------------------
|
|
|
|
LRESULT CALLBACK CMtaFolderPicker::StaWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LRESULT lResult = 0;
|
|
CMtaFolderPicker* pImpl = NULL;
|
|
|
|
/*
|
|
we connect to the belonging class instance of this
|
|
window using SetProp, GetProp etc.
|
|
this may fail if somehow the class instance destroyed
|
|
before the window
|
|
*/
|
|
|
|
switch( uMsg )
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
LPCREATESTRUCT lpcs =
|
|
reinterpret_cast< LPCREATESTRUCT >( lParam );
|
|
|
|
OSL_ASSERT( lpcs->lpCreateParams );
|
|
|
|
// connect the instance handle to the window
|
|
SetPropA( hWnd, CURRENT_INSTANCE, lpcs->lpCreateParams );
|
|
}
|
|
break;
|
|
|
|
case WM_NCDESTROY:
|
|
// RemoveProp returns the saved value on success
|
|
pImpl = reinterpret_cast< CMtaFolderPicker* >(
|
|
RemovePropA( hWnd, CURRENT_INSTANCE ) );
|
|
|
|
OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
|
|
break;
|
|
|
|
case MSG_BROWSEFORFOLDER:
|
|
{
|
|
RequestContext* aReqCtx = reinterpret_cast< RequestContext* >( lParam );
|
|
OSL_ASSERT( aReqCtx );
|
|
|
|
pImpl = reinterpret_cast< CMtaFolderPicker* >(
|
|
GetPropA( hWnd, CURRENT_INSTANCE ) );
|
|
|
|
OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
|
|
|
|
aReqCtx->bRet = pImpl->onBrowseForFolder( );
|
|
SetEvent( aReqCtx->hEvent );
|
|
}
|
|
break;
|
|
|
|
case MSG_SHUTDOWN:
|
|
pImpl = reinterpret_cast< CMtaFolderPicker* >(
|
|
GetPropA( hWnd, CURRENT_INSTANCE ) );
|
|
|
|
OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
|
|
|
|
DestroyWindow( pImpl->m_hwndStaRequestWnd );
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage( 0 );
|
|
break;
|
|
|
|
default:
|
|
lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
|
|
break;
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL CMtaFolderPicker::createStaRequestWindow( )
|
|
{
|
|
bool bIsWnd = false;
|
|
|
|
if ( RegisterStaRequestWindowClass( ) )
|
|
{
|
|
m_hwndStaRequestWnd = CreateWindowA(
|
|
g_szWndClsName, NULL,
|
|
0, 0, 0, 0, 0,
|
|
NULL, NULL, m_hInstance,
|
|
(LPVOID)this // provide the instance of the class
|
|
);
|
|
|
|
bIsWnd = IsWindow( m_hwndStaRequestWnd );
|
|
|
|
// we do immediately unregister the window class
|
|
// if the creation of the window fails because we
|
|
// don't want to spoil the register class counter
|
|
if ( !bIsWnd )
|
|
UnregisterStaRequestWindowClass( );
|
|
|
|
OSL_ENSURE( bIsWnd, "sta request window creation failed" );
|
|
}
|
|
|
|
return bIsWnd;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
unsigned int CMtaFolderPicker::run( )
|
|
{
|
|
OSL_ASSERT( m_hEvtThrdReady );
|
|
|
|
// setup an sta environment
|
|
HRESULT hr = CoInitialize( NULL );
|
|
|
|
// if we can't setup an sta environment
|
|
// we stop here and return
|
|
if ( FAILED( hr ) )
|
|
{
|
|
OSL_ENSURE( sal_False, "CoInitialize failed" );
|
|
return sal::static_int_cast< unsigned int >(-1);
|
|
}
|
|
|
|
unsigned int nRet;
|
|
|
|
if ( createStaRequestWindow( ) )
|
|
{
|
|
SetEvent( m_hEvtThrdReady );
|
|
|
|
// pumping messages
|
|
MSG msg;
|
|
while( GetMessageA( &msg, NULL, 0, 0 ) )
|
|
DispatchMessageA( &msg );
|
|
|
|
nRet = 0;
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE( sal_False, "failed to create sta thread" );
|
|
nRet = sal::static_int_cast< unsigned int >(-1);
|
|
}
|
|
|
|
// shutdown sta environment
|
|
CoUninitialize( );
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
unsigned int WINAPI CMtaFolderPicker::StaThreadProc( LPVOID pParam )
|
|
{
|
|
CMtaFolderPicker* pInst =
|
|
reinterpret_cast<CMtaFolderPicker*>( pParam );
|
|
|
|
OSL_ASSERT( pInst );
|
|
|
|
HRESULT hr = OleInitialize( NULL );
|
|
|
|
unsigned int result = pInst->run( );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
OleUninitialize();
|
|
|
|
return result;
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
ATOM SAL_CALL CMtaFolderPicker::RegisterStaRequestWindowClass( )
|
|
{
|
|
osl::MutexGuard aGuard( s_Mutex );
|
|
|
|
if ( 0 == s_ClassAtom )
|
|
{
|
|
WNDCLASSEXA wcex;
|
|
|
|
ZeroMemory( &wcex, sizeof( WNDCLASSEXA ) );
|
|
|
|
wcex.cbSize = sizeof(WNDCLASSEXA);
|
|
wcex.style = 0;
|
|
wcex.lpfnWndProc = static_cast< WNDPROC >( CMtaFolderPicker::StaWndProc );
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = m_hInstance;
|
|
wcex.hIcon = NULL;
|
|
wcex.hCursor = NULL;
|
|
wcex.hbrBackground = NULL;
|
|
wcex.lpszMenuName = NULL;
|
|
wcex.lpszClassName = g_szWndClsName;
|
|
wcex.hIconSm = NULL;
|
|
|
|
s_ClassAtom = RegisterClassExA( &wcex );
|
|
OSL_ASSERT( s_ClassAtom );
|
|
}
|
|
|
|
// increment the register class counter
|
|
// so that we keep track of the number
|
|
// of class registrations
|
|
if ( 0 != s_ClassAtom )
|
|
s_StaRequestWndRegisterCount++;
|
|
|
|
return s_ClassAtom;
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
void SAL_CALL CMtaFolderPicker::UnregisterStaRequestWindowClass( )
|
|
{
|
|
osl::MutexGuard aGuard( s_Mutex );
|
|
|
|
OSL_ASSERT( 0 != s_ClassAtom );
|
|
|
|
// update the register class counter
|
|
// and unregister the window class if
|
|
// counter drops to zero
|
|
if ( 0 != s_ClassAtom )
|
|
{
|
|
s_StaRequestWndRegisterCount--;
|
|
OSL_ASSERT( s_StaRequestWndRegisterCount >= 0 );
|
|
}
|
|
|
|
if ( 0 == s_StaRequestWndRegisterCount )
|
|
{
|
|
UnregisterClass(
|
|
(LPCTSTR)MAKELONG( s_ClassAtom, 0 ), m_hInstance );
|
|
|
|
s_ClassAtom = 0;
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|