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 #define UNICODE 29 #define _UNICODE 30 #define _WIN32_WINNT_0x0500 31 #include "systools/win32/uwinapi.h" 32 33 #include "osl/file.h" 34 35 #include "file_error.h" 36 #include "file_url.h" 37 #include "path_helper.hxx" 38 39 #include "osl/diagnose.h" 40 41 #include <malloc.h> 42 #include <tchar.h> 43 44 //##################################################### 45 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) 46 47 // Allocate n number of t's on the stack return a pointer to it in p 48 #ifdef __MINGW32__ 49 #define STACK_ALLOC(p, t, n) (p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t))); 50 #else 51 #define STACK_ALLOC(p, t, n) __try {(p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));} \ 52 __except(EXCEPTION_EXECUTE_HANDLER) {(p) = 0;} 53 #endif 54 55 extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle(HANDLE hFile, sal_uInt32 uFlags); 56 57 //##################################################### 58 // Temp file functions 59 //##################################################### 60 61 static oslFileError osl_setup_base_directory_impl_( 62 rtl_uString* pustrDirectoryURL, 63 rtl_uString** ppustr_base_dir) 64 { 65 rtl_uString* dir_url = 0; 66 rtl_uString* dir = 0; 67 oslFileError error = osl_File_E_None; 68 69 if (pustrDirectoryURL) 70 rtl_uString_assign(&dir_url, pustrDirectoryURL); 71 else 72 error = osl_getTempDirURL(&dir_url); 73 74 if (osl_File_E_None == error) 75 { 76 error = _osl_getSystemPathFromFileURL(dir_url, &dir, sal_False); 77 rtl_uString_release(dir_url); 78 } 79 80 if (osl_File_E_None == error ) 81 { 82 rtl_uString_assign(ppustr_base_dir, dir); 83 rtl_uString_release(dir); 84 } 85 86 return error; 87 } 88 89 //##################################################### 90 static oslFileError osl_setup_createTempFile_impl_( 91 rtl_uString* pustrDirectoryURL, 92 oslFileHandle* pHandle, 93 rtl_uString** ppustrTempFileURL, 94 rtl_uString** ppustr_base_dir, 95 sal_Bool* b_delete_on_close) 96 { 97 oslFileError osl_error; 98 99 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!"); 100 101 if ((0 == pHandle) && (0 == ppustrTempFileURL)) 102 { 103 osl_error = osl_File_E_INVAL; 104 } 105 else 106 { 107 osl_error = osl_setup_base_directory_impl_( 108 pustrDirectoryURL, ppustr_base_dir); 109 110 *b_delete_on_close = (sal_Bool)(0 == ppustrTempFileURL); 111 } 112 113 return osl_error; 114 } 115 116 //##################################################### 117 static oslFileError osl_win32_GetTempFileName_impl_( 118 rtl_uString* base_directory, LPWSTR temp_file_name) 119 { 120 oslFileError osl_error = osl_File_E_None; 121 122 if (0 == GetTempFileNameW( 123 reinterpret_cast<LPCWSTR>(rtl_uString_getStr(base_directory)), 124 L"", 125 0, 126 temp_file_name)) 127 { 128 osl_error = oslTranslateFileError(GetLastError()); 129 } 130 131 return osl_error; 132 } 133 134 //##################################################### 135 static sal_Bool osl_win32_CreateFile_impl_( 136 LPCWSTR file_name, sal_Bool b_delete_on_close, oslFileHandle* p_handle) 137 { 138 DWORD flags = FILE_ATTRIBUTE_NORMAL; 139 HANDLE hFile; 140 141 OSL_ASSERT(p_handle); 142 143 if (b_delete_on_close) 144 flags |= FILE_FLAG_DELETE_ON_CLOSE; 145 146 hFile = CreateFileW( 147 file_name, 148 GENERIC_READ | GENERIC_WRITE, 149 0, 150 NULL, 151 TRUNCATE_EXISTING, 152 flags, 153 NULL); 154 155 // @@@ ERROR HANDLING @@@ 156 if (IsValidHandle(hFile)) 157 *p_handle = osl_createFileHandleFromOSHandle(hFile, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write); 158 159 return (sal_Bool)IsValidHandle(hFile); 160 } 161 162 //############################################# 163 static oslFileError osl_createTempFile_impl_( 164 rtl_uString* base_directory, 165 LPWSTR tmp_name, 166 sal_Bool b_delete_on_close, 167 oslFileHandle* pHandle, 168 rtl_uString** ppustrTempFileURL) 169 { 170 oslFileError osl_error; 171 172 do 173 { 174 osl_error = osl_win32_GetTempFileName_impl_(base_directory, tmp_name); 175 176 /* if file could not be opened try again */ 177 178 if ((osl_File_E_None != osl_error) || (0 == pHandle) || 179 osl_win32_CreateFile_impl_(tmp_name, b_delete_on_close, pHandle)) 180 break; 181 182 } while(1); // try until success 183 184 if ((osl_File_E_None == osl_error) && !b_delete_on_close) 185 { 186 rtl_uString* pustr = 0; 187 rtl_uString_newFromStr(&pustr, reinterpret_cast<const sal_Unicode*>(tmp_name)); 188 osl_getFileURLFromSystemPath(pustr, ppustrTempFileURL); 189 rtl_uString_release(pustr); 190 } 191 192 return osl_error; 193 } 194 195 //############################################# 196 oslFileError SAL_CALL osl_createTempFile( 197 rtl_uString* pustrDirectoryURL, 198 oslFileHandle* pHandle, 199 rtl_uString** ppustrTempFileURL) 200 { 201 rtl_uString* base_directory = 0; 202 LPWSTR tmp_name; 203 sal_Bool b_delete_on_close; 204 oslFileError osl_error; 205 206 osl_error = osl_setup_createTempFile_impl_( 207 pustrDirectoryURL, 208 pHandle, 209 ppustrTempFileURL, 210 &base_directory, 211 &b_delete_on_close); 212 213 if (osl_File_E_None != osl_error) 214 return osl_error; 215 216 /* allocate enough space on the stack, the file name can not be longer than MAX_PATH */ 217 STACK_ALLOC(tmp_name, WCHAR, (rtl_uString_getLength(base_directory) + MAX_PATH)); 218 219 if (tmp_name) 220 { 221 osl_createTempFile_impl_( 222 base_directory, 223 tmp_name, 224 b_delete_on_close, 225 pHandle, 226 ppustrTempFileURL); 227 } 228 else // stack alloc failed 229 { 230 osl_error = osl_File_E_NOMEM; 231 } 232 233 if (base_directory) 234 rtl_uString_release(base_directory); 235 236 return osl_error; 237 } 238 239 //############################################# 240 oslFileError SAL_CALL osl_getTempDirURL(rtl_uString** pustrTempDir) 241 { 242 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); 243 LPWSTR lpBuffer = ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer); 244 DWORD nBufferLength = aBuffer.getBufSizeInSymbols() - 1; 245 246 DWORD nLength; 247 oslFileError error; 248 249 nLength = GetTempPathW( aBuffer.getBufSizeInSymbols(), lpBuffer ); 250 251 if ( nLength > nBufferLength ) 252 { 253 // the provided path has invalid length 254 error = osl_File_E_NOENT; 255 } 256 else if ( nLength ) 257 { 258 rtl_uString *ustrTempPath = NULL; 259 260 if ( '\\' == lpBuffer[nLength-1] ) 261 lpBuffer[nLength-1] = 0; 262 263 rtl_uString_newFromStr( &ustrTempPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) ); 264 265 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir ); 266 267 rtl_uString_release( ustrTempPath ); 268 } 269 else 270 error = oslTranslateFileError( GetLastError() ); 271 272 return error; 273 } 274 275