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