office-gobmx/fpicker/source/win32/filepicker/getfilenamewrapper.cxx
Ivo Hinkelmann 0a68153b4c INTEGRATION: CWS fwk56 (1.8.22); FILE MERGED
2006/11/28 09:26:47 mav 1.8.22.2: #i21747# fix long path handling
2006/11/15 14:42:49 mav 1.8.22.1: #i21747# preserv the current directory value
2006-12-19 12:54:09 +00:00

310 lines
8.4 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: getfilenamewrapper.cxx,v $
*
* $Revision: 1.9 $
*
* last change: $Author: ihi $ $Date: 2006-12-19 13:54:09 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_fpicker.hxx"
//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------
#include <stdio.h>
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef _GETFILENAMEWRAPPER_HXX_
#include "getfilenamewrapper.hxx"
#endif
#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#include <objbase.h>
#include <process.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif
namespace /* private */
{
//-----------------------------------------------
// This class prevents changing of the working
// directory.
//-----------------------------------------------
class CurDirGuard
{
BOOL m_bValid;
wchar_t* m_pBuffer;
DWORD m_nBufLen;
public:
CurDirGuard()
: m_bValid( FALSE )
, m_pBuffer( NULL )
, m_nBufLen( 0 )
{
m_nBufLen = GetCurrentDirectoryW( 0, NULL );
if ( m_nBufLen )
{
m_pBuffer = new wchar_t[m_nBufLen];
m_bValid = ( GetCurrentDirectoryW( m_nBufLen, m_pBuffer ) == ( m_nBufLen - 1 ) );
}
}
~CurDirGuard()
{
BOOL bDirSet = FALSE;
if ( m_pBuffer )
{
if ( m_bValid )
{
if ( m_nBufLen - 1 > MAX_PATH )
{
if ( (LONG32)GetVersion() < 0 )
{
// this is Win 98/ME branch, such a long path can not be set
// use the system path as fallback later
}
else
{
DWORD nNewLen = m_nBufLen + 8;
wchar_t* pNewBuffer = new wchar_t[nNewLen];
if ( m_nBufLen > 3 && m_pBuffer[0] == (wchar_t)'\\' && m_pBuffer[1] == (wchar_t)'\\' )
{
if ( m_pBuffer[2] == (wchar_t)'?' )
_snwprintf( pNewBuffer, nNewLen, L"%s", m_pBuffer );
else
_snwprintf( pNewBuffer, nNewLen, L"\\\\?\\UNC\\%s", m_pBuffer+2 );
}
else
_snwprintf( pNewBuffer, nNewLen, L"\\\\?\\%s", m_pBuffer );
bDirSet = SetCurrentDirectoryW( pNewBuffer );
delete [] pNewBuffer;
}
}
else
bDirSet = SetCurrentDirectoryW( m_pBuffer );
}
delete [] m_pBuffer;
m_pBuffer = NULL;
}
if ( !bDirSet )
{
// the fallback solution
wchar_t pPath[MAX_PATH+1];
if ( GetWindowsDirectoryW( pPath, MAX_PATH+1 ) <= MAX_PATH )
{
SetCurrentDirectoryW( pPath );
}
else
{
// the system path is also too long?!!
}
}
}
};
//-----------------------------------------------
//
//-----------------------------------------------
struct GetFileNameParam
{
GetFileNameParam(bool bOpen, LPOPENFILENAME lpofn) :
m_bOpen(bOpen),
m_lpofn(lpofn),
m_bRet(false),
m_ExtErr(0)
{}
bool m_bOpen;
LPOPENFILENAME m_lpofn;
bool m_bRet;
int m_ExtErr;
};
//-----------------------------------------------
//
//-----------------------------------------------
unsigned __stdcall ThreadProc(void* pParam)
{
CurDirGuard aGuard;
GetFileNameParam* lpgfnp =
reinterpret_cast<GetFileNameParam*>(pParam);
HRESULT hr = OleInitialize( NULL );
if (lpgfnp->m_bOpen)
lpgfnp->m_bRet = GetOpenFileName(lpgfnp->m_lpofn);
else
lpgfnp->m_bRet = GetSaveFileName(lpgfnp->m_lpofn);
lpgfnp->m_ExtErr = CommDlgExtendedError();
if ( SUCCEEDED( hr ) )
OleUninitialize();
return 0;
}
//-----------------------------------------------
// exceutes GetOpenFileName/GetSaveFileName in
// a separat thread
//-----------------------------------------------
bool ThreadExecGetFileName(LPOPENFILENAME lpofn, bool bOpen, /*out*/ int& ExtErr)
{
GetFileNameParam gfnp(bOpen,lpofn);
unsigned id;
HANDLE hThread = reinterpret_cast<HANDLE>(
_beginthreadex(0, 0, ThreadProc, &gfnp, 0, &id));
OSL_POSTCOND(hThread, "could not create STA thread");
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
ExtErr = gfnp.m_ExtErr;
return gfnp.m_bRet;
}
//-----------------------------------------------
// This function returns true if the calling
// thread belongs to a Multithreaded Appartment
// (MTA)
//-----------------------------------------------
bool IsMTA()
{
HRESULT hr = CoInitialize(NULL);
if (RPC_E_CHANGED_MODE == hr)
return true;
if(SUCCEEDED(hr))
CoUninitialize();
return false;
}
} // namespace private
//-----------------------------------------------
//
//-----------------------------------------------
CGetFileNameWrapper::CGetFileNameWrapper() :
m_ExtendedDialogError(0)
{
}
//-----------------------------------------------
//
//-----------------------------------------------
bool CGetFileNameWrapper::getOpenFileName(LPOPENFILENAME lpofn)
{
OSL_PRECOND(lpofn,"invalid parameter");
bool bRet = false;
if (IsMTA())
{
bRet = ThreadExecGetFileName(
lpofn, true, m_ExtendedDialogError);
}
else
{
CurDirGuard aGuard;
HRESULT hr = OleInitialize( NULL );
bRet = GetOpenFileName(lpofn);
m_ExtendedDialogError = CommDlgExtendedError();
if ( SUCCEEDED( hr ) )
OleUninitialize();
}
return bRet;
}
//-----------------------------------------------
//
//-----------------------------------------------
bool CGetFileNameWrapper::getSaveFileName(LPOPENFILENAME lpofn)
{
OSL_PRECOND(lpofn,"invalid parameter");
bool bRet = false;
if (IsMTA())
{
bRet = ThreadExecGetFileName(
lpofn, false, m_ExtendedDialogError);
}
else
{
CurDirGuard aGuard;
bRet = GetSaveFileName(lpofn);
m_ExtendedDialogError = CommDlgExtendedError();
}
return bRet;
}
//-----------------------------------------------
//
//-----------------------------------------------
int CGetFileNameWrapper::commDlgExtendedError( )
{
return m_ExtendedDialogError;
}