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 31 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 35 #include <stdio.h> 36 #include <osl/diagnose.h> 37 #include "getfilenamewrapper.hxx" 38 39 #if defined _MSC_VER 40 #pragma warning(push, 1) 41 #endif 42 #include <objbase.h> 43 #include <process.h> 44 #if defined _MSC_VER 45 #pragma warning(pop) 46 #endif 47 48 namespace /* private */ 49 { 50 51 //----------------------------------------------- 52 // This class prevents changing of the working 53 // directory. 54 //----------------------------------------------- 55 class CurDirGuard 56 { 57 sal_Bool m_bValid; 58 wchar_t* m_pBuffer; 59 DWORD m_nBufLen; 60 61 public: 62 CurDirGuard() 63 : m_bValid( sal_False ) 64 , m_pBuffer( NULL ) 65 , m_nBufLen( 0 ) 66 { 67 m_nBufLen = GetCurrentDirectoryW( 0, NULL ); 68 if ( m_nBufLen ) 69 { 70 m_pBuffer = new wchar_t[m_nBufLen]; 71 m_bValid = ( GetCurrentDirectoryW( m_nBufLen, m_pBuffer ) == ( m_nBufLen - 1 ) ); 72 } 73 } 74 75 ~CurDirGuard() 76 { 77 bool bDirSet = false; 78 79 if ( m_pBuffer ) 80 { 81 if ( m_bValid ) 82 { 83 if ( m_nBufLen - 1 > MAX_PATH ) 84 { 85 if ( (LONG32)GetVersion() < 0 ) 86 { 87 // this is Win 98/ME branch, such a long path can not be set 88 // use the system path as fallback later 89 } 90 else 91 { 92 DWORD nNewLen = m_nBufLen + 8; 93 wchar_t* pNewBuffer = new wchar_t[nNewLen]; 94 if ( m_nBufLen > 3 && m_pBuffer[0] == (wchar_t)'\\' && m_pBuffer[1] == (wchar_t)'\\' ) 95 { 96 if ( m_pBuffer[2] == (wchar_t)'?' ) 97 _snwprintf( pNewBuffer, nNewLen, L"%s", m_pBuffer ); 98 else 99 _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\UNC\\%s", m_pBuffer+2 ); 100 } 101 else 102 _snwprintf( pNewBuffer, nNewLen, L"\\\\?\\%s", m_pBuffer ); 103 bDirSet = SetCurrentDirectoryW( pNewBuffer ); 104 105 delete [] pNewBuffer; 106 } 107 } 108 else 109 bDirSet = SetCurrentDirectoryW( m_pBuffer ); 110 } 111 112 delete [] m_pBuffer; 113 m_pBuffer = NULL; 114 } 115 116 if ( !bDirSet ) 117 { 118 // the fallback solution 119 wchar_t pPath[MAX_PATH+1]; 120 if ( GetWindowsDirectoryW( pPath, MAX_PATH+1 ) <= MAX_PATH ) 121 { 122 SetCurrentDirectoryW( pPath ); 123 } 124 else 125 { 126 // the system path is also too long?!! 127 } 128 } 129 } 130 }; 131 132 //----------------------------------------------- 133 // 134 //----------------------------------------------- 135 136 struct GetFileNameParam 137 { 138 GetFileNameParam(bool bOpen, LPOPENFILENAME lpofn) : 139 m_bOpen(bOpen), 140 m_lpofn(lpofn), 141 m_bRet(false), 142 m_ExtErr(0) 143 {} 144 145 bool m_bOpen; 146 LPOPENFILENAME m_lpofn; 147 bool m_bRet; 148 int m_ExtErr; 149 }; 150 151 //----------------------------------------------- 152 // 153 //----------------------------------------------- 154 155 unsigned __stdcall ThreadProc(void* pParam) 156 { 157 CurDirGuard aGuard; 158 159 GetFileNameParam* lpgfnp = 160 reinterpret_cast<GetFileNameParam*>(pParam); 161 162 HRESULT hr = OleInitialize( NULL ); 163 164 if (lpgfnp->m_bOpen) 165 lpgfnp->m_bRet = GetOpenFileName(lpgfnp->m_lpofn); 166 else 167 lpgfnp->m_bRet = GetSaveFileName(lpgfnp->m_lpofn); 168 169 lpgfnp->m_ExtErr = CommDlgExtendedError(); 170 171 if ( SUCCEEDED( hr ) ) 172 OleUninitialize(); 173 174 return 0; 175 } 176 177 //----------------------------------------------- 178 // exceutes GetOpenFileName/GetSaveFileName in 179 // a separat thread 180 //----------------------------------------------- 181 182 bool ThreadExecGetFileName(LPOPENFILENAME lpofn, bool bOpen, /*out*/ int& ExtErr) 183 { 184 GetFileNameParam gfnp(bOpen,lpofn); 185 unsigned id; 186 187 HANDLE hThread = reinterpret_cast<HANDLE>( 188 _beginthreadex(0, 0, ThreadProc, &gfnp, 0, &id)); 189 190 OSL_POSTCOND(hThread, "could not create STA thread"); 191 192 WaitForSingleObject(hThread, INFINITE); 193 CloseHandle(hThread); 194 195 ExtErr = gfnp.m_ExtErr; 196 197 return gfnp.m_bRet; 198 } 199 200 //----------------------------------------------- 201 // This function returns true if the calling 202 // thread belongs to a Multithreaded Appartment 203 // (MTA) 204 //----------------------------------------------- 205 206 bool IsMTA() 207 { 208 HRESULT hr = CoInitialize(NULL); 209 210 if (RPC_E_CHANGED_MODE == hr) 211 return true; 212 213 if(SUCCEEDED(hr)) 214 CoUninitialize(); 215 216 return false; 217 } 218 219 } // namespace private 220 221 222 //----------------------------------------------- 223 // 224 //----------------------------------------------- 225 226 CGetFileNameWrapper::CGetFileNameWrapper() : 227 m_ExtendedDialogError(0) 228 { 229 } 230 231 //----------------------------------------------- 232 // 233 //----------------------------------------------- 234 235 bool CGetFileNameWrapper::getOpenFileName(LPOPENFILENAME lpofn) 236 { 237 OSL_PRECOND(lpofn,"invalid parameter"); 238 239 bool bRet = false; 240 241 if (IsMTA()) 242 { 243 bRet = ThreadExecGetFileName( 244 lpofn, true, m_ExtendedDialogError); 245 } 246 else 247 { 248 CurDirGuard aGuard; 249 250 HRESULT hr = OleInitialize( NULL ); 251 252 bRet = GetOpenFileName(lpofn); 253 m_ExtendedDialogError = CommDlgExtendedError(); 254 255 if ( SUCCEEDED( hr ) ) 256 OleUninitialize(); 257 } 258 259 return bRet; 260 } 261 262 //----------------------------------------------- 263 // 264 //----------------------------------------------- 265 266 bool CGetFileNameWrapper::getSaveFileName(LPOPENFILENAME lpofn) 267 { 268 OSL_PRECOND(lpofn,"invalid parameter"); 269 270 bool bRet = false; 271 272 if (IsMTA()) 273 { 274 bRet = ThreadExecGetFileName( 275 lpofn, false, m_ExtendedDialogError); 276 } 277 else 278 { 279 CurDirGuard aGuard; 280 281 bRet = GetSaveFileName(lpofn); 282 m_ExtendedDialogError = CommDlgExtendedError(); 283 } 284 285 return bRet; 286 } 287 288 //----------------------------------------------- 289 // 290 //----------------------------------------------- 291 292 int CGetFileNameWrapper::commDlgExtendedError( ) 293 { 294 return m_ExtendedDialogError; 295 } 296 297