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