1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_fpicker.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir //------------------------------------------------------------------------ 32*cdf0e10cSrcweir // includes 33*cdf0e10cSrcweir //------------------------------------------------------------------------ 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir #include <stdio.h> 36*cdf0e10cSrcweir #include <osl/diagnose.h> 37*cdf0e10cSrcweir #include "getfilenamewrapper.hxx" 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir #if defined _MSC_VER 40*cdf0e10cSrcweir #pragma warning(push, 1) 41*cdf0e10cSrcweir #endif 42*cdf0e10cSrcweir #include <objbase.h> 43*cdf0e10cSrcweir #include <process.h> 44*cdf0e10cSrcweir #if defined _MSC_VER 45*cdf0e10cSrcweir #pragma warning(pop) 46*cdf0e10cSrcweir #endif 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir namespace /* private */ 49*cdf0e10cSrcweir { 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir //----------------------------------------------- 52*cdf0e10cSrcweir // This class prevents changing of the working 53*cdf0e10cSrcweir // directory. 54*cdf0e10cSrcweir //----------------------------------------------- 55*cdf0e10cSrcweir class CurDirGuard 56*cdf0e10cSrcweir { 57*cdf0e10cSrcweir sal_Bool m_bValid; 58*cdf0e10cSrcweir wchar_t* m_pBuffer; 59*cdf0e10cSrcweir DWORD m_nBufLen; 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir public: 62*cdf0e10cSrcweir CurDirGuard() 63*cdf0e10cSrcweir : m_bValid( sal_False ) 64*cdf0e10cSrcweir , m_pBuffer( NULL ) 65*cdf0e10cSrcweir , m_nBufLen( 0 ) 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir m_nBufLen = GetCurrentDirectoryW( 0, NULL ); 68*cdf0e10cSrcweir if ( m_nBufLen ) 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir m_pBuffer = new wchar_t[m_nBufLen]; 71*cdf0e10cSrcweir m_bValid = ( GetCurrentDirectoryW( m_nBufLen, m_pBuffer ) == ( m_nBufLen - 1 ) ); 72*cdf0e10cSrcweir } 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir ~CurDirGuard() 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir bool bDirSet = false; 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir if ( m_pBuffer ) 80*cdf0e10cSrcweir { 81*cdf0e10cSrcweir if ( m_bValid ) 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir if ( m_nBufLen - 1 > MAX_PATH ) 84*cdf0e10cSrcweir { 85*cdf0e10cSrcweir if ( (LONG32)GetVersion() < 0 ) 86*cdf0e10cSrcweir { 87*cdf0e10cSrcweir // this is Win 98/ME branch, such a long path can not be set 88*cdf0e10cSrcweir // use the system path as fallback later 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir else 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir DWORD nNewLen = m_nBufLen + 8; 93*cdf0e10cSrcweir wchar_t* pNewBuffer = new wchar_t[nNewLen]; 94*cdf0e10cSrcweir if ( m_nBufLen > 3 && m_pBuffer[0] == (wchar_t)'\\' && m_pBuffer[1] == (wchar_t)'\\' ) 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir if ( m_pBuffer[2] == (wchar_t)'?' ) 97*cdf0e10cSrcweir _snwprintf( pNewBuffer, nNewLen, L"%s", m_pBuffer ); 98*cdf0e10cSrcweir else 99*cdf0e10cSrcweir _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\UNC\\%s", m_pBuffer+2 ); 100*cdf0e10cSrcweir } 101*cdf0e10cSrcweir else 102*cdf0e10cSrcweir _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\%s", m_pBuffer ); 103*cdf0e10cSrcweir bDirSet = SetCurrentDirectoryW( pNewBuffer ); 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir delete [] pNewBuffer; 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir else 109*cdf0e10cSrcweir bDirSet = SetCurrentDirectoryW( m_pBuffer ); 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir delete [] m_pBuffer; 113*cdf0e10cSrcweir m_pBuffer = NULL; 114*cdf0e10cSrcweir } 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir if ( !bDirSet ) 117*cdf0e10cSrcweir { 118*cdf0e10cSrcweir // the fallback solution 119*cdf0e10cSrcweir wchar_t pPath[MAX_PATH+1]; 120*cdf0e10cSrcweir if ( GetWindowsDirectoryW( pPath, MAX_PATH+1 ) <= MAX_PATH ) 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir SetCurrentDirectoryW( pPath ); 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir else 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir // the system path is also too long?!! 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir } 130*cdf0e10cSrcweir }; 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir //----------------------------------------------- 133*cdf0e10cSrcweir // 134*cdf0e10cSrcweir //----------------------------------------------- 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir struct GetFileNameParam 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir GetFileNameParam(bool bOpen, LPOPENFILENAME lpofn) : 139*cdf0e10cSrcweir m_bOpen(bOpen), 140*cdf0e10cSrcweir m_lpofn(lpofn), 141*cdf0e10cSrcweir m_bRet(false), 142*cdf0e10cSrcweir m_ExtErr(0) 143*cdf0e10cSrcweir {} 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir bool m_bOpen; 146*cdf0e10cSrcweir LPOPENFILENAME m_lpofn; 147*cdf0e10cSrcweir bool m_bRet; 148*cdf0e10cSrcweir int m_ExtErr; 149*cdf0e10cSrcweir }; 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir //----------------------------------------------- 152*cdf0e10cSrcweir // 153*cdf0e10cSrcweir //----------------------------------------------- 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir unsigned __stdcall ThreadProc(void* pParam) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir CurDirGuard aGuard; 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir GetFileNameParam* lpgfnp = 160*cdf0e10cSrcweir reinterpret_cast<GetFileNameParam*>(pParam); 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir HRESULT hr = OleInitialize( NULL ); 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir if (lpgfnp->m_bOpen) 165*cdf0e10cSrcweir lpgfnp->m_bRet = GetOpenFileName(lpgfnp->m_lpofn); 166*cdf0e10cSrcweir else 167*cdf0e10cSrcweir lpgfnp->m_bRet = GetSaveFileName(lpgfnp->m_lpofn); 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir lpgfnp->m_ExtErr = CommDlgExtendedError(); 170*cdf0e10cSrcweir 171*cdf0e10cSrcweir if ( SUCCEEDED( hr ) ) 172*cdf0e10cSrcweir OleUninitialize(); 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir return 0; 175*cdf0e10cSrcweir } 176*cdf0e10cSrcweir 177*cdf0e10cSrcweir //----------------------------------------------- 178*cdf0e10cSrcweir // exceutes GetOpenFileName/GetSaveFileName in 179*cdf0e10cSrcweir // a separat thread 180*cdf0e10cSrcweir //----------------------------------------------- 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir bool ThreadExecGetFileName(LPOPENFILENAME lpofn, bool bOpen, /*out*/ int& ExtErr) 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir GetFileNameParam gfnp(bOpen,lpofn); 185*cdf0e10cSrcweir unsigned id; 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir HANDLE hThread = reinterpret_cast<HANDLE>( 188*cdf0e10cSrcweir _beginthreadex(0, 0, ThreadProc, &gfnp, 0, &id)); 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir OSL_POSTCOND(hThread, "could not create STA thread"); 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir WaitForSingleObject(hThread, INFINITE); 193*cdf0e10cSrcweir CloseHandle(hThread); 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir ExtErr = gfnp.m_ExtErr; 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir return gfnp.m_bRet; 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir //----------------------------------------------- 201*cdf0e10cSrcweir // This function returns true if the calling 202*cdf0e10cSrcweir // thread belongs to a Multithreaded Appartment 203*cdf0e10cSrcweir // (MTA) 204*cdf0e10cSrcweir //----------------------------------------------- 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir bool IsMTA() 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir HRESULT hr = CoInitialize(NULL); 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir if (RPC_E_CHANGED_MODE == hr) 211*cdf0e10cSrcweir return true; 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir if(SUCCEEDED(hr)) 214*cdf0e10cSrcweir CoUninitialize(); 215*cdf0e10cSrcweir 216*cdf0e10cSrcweir return false; 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir } // namespace private 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir //----------------------------------------------- 223*cdf0e10cSrcweir // 224*cdf0e10cSrcweir //----------------------------------------------- 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir CGetFileNameWrapper::CGetFileNameWrapper() : 227*cdf0e10cSrcweir m_ExtendedDialogError(0) 228*cdf0e10cSrcweir { 229*cdf0e10cSrcweir } 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir //----------------------------------------------- 232*cdf0e10cSrcweir // 233*cdf0e10cSrcweir //----------------------------------------------- 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir bool CGetFileNameWrapper::getOpenFileName(LPOPENFILENAME lpofn) 236*cdf0e10cSrcweir { 237*cdf0e10cSrcweir OSL_PRECOND(lpofn,"invalid parameter"); 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir bool bRet = false; 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir if (IsMTA()) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir bRet = ThreadExecGetFileName( 244*cdf0e10cSrcweir lpofn, true, m_ExtendedDialogError); 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir else 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir CurDirGuard aGuard; 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir HRESULT hr = OleInitialize( NULL ); 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir bRet = GetOpenFileName(lpofn); 253*cdf0e10cSrcweir m_ExtendedDialogError = CommDlgExtendedError(); 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir if ( SUCCEEDED( hr ) ) 256*cdf0e10cSrcweir OleUninitialize(); 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir return bRet; 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir //----------------------------------------------- 263*cdf0e10cSrcweir // 264*cdf0e10cSrcweir //----------------------------------------------- 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir bool CGetFileNameWrapper::getSaveFileName(LPOPENFILENAME lpofn) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir OSL_PRECOND(lpofn,"invalid parameter"); 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir bool bRet = false; 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir if (IsMTA()) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir bRet = ThreadExecGetFileName( 275*cdf0e10cSrcweir lpofn, false, m_ExtendedDialogError); 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir else 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir CurDirGuard aGuard; 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir bRet = GetSaveFileName(lpofn); 282*cdf0e10cSrcweir m_ExtendedDialogError = CommDlgExtendedError(); 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir return bRet; 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir //----------------------------------------------- 289*cdf0e10cSrcweir // 290*cdf0e10cSrcweir //----------------------------------------------- 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir int CGetFileNameWrapper::commDlgExtendedError( ) 293*cdf0e10cSrcweir { 294*cdf0e10cSrcweir return m_ExtendedDialogError; 295*cdf0e10cSrcweir } 296*cdf0e10cSrcweir 297