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
osl_setup_base_directory_impl_(rtl_uString * pustrDirectoryURL,rtl_uString ** ppustr_base_dir)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 //#####################################################
osl_setup_createTempFile_impl_(rtl_uString * pustrDirectoryURL,oslFileHandle * pHandle,rtl_uString ** ppustrTempFileURL,rtl_uString ** ppustr_base_dir,sal_Bool * b_delete_on_close)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 //#####################################################
osl_win32_GetTempFileName_impl_(rtl_uString * base_directory,LPWSTR temp_file_name)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 //#####################################################
osl_win32_CreateFile_impl_(LPCWSTR file_name,sal_Bool b_delete_on_close,oslFileHandle * p_handle)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 //#############################################
osl_createTempFile_impl_(rtl_uString * base_directory,LPWSTR tmp_name,sal_Bool b_delete_on_close,oslFileHandle * pHandle,rtl_uString ** ppustrTempFileURL)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 //#############################################
osl_createTempFile(rtl_uString * pustrDirectoryURL,oslFileHandle * pHandle,rtl_uString ** ppustrTempFileURL)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 //#############################################
osl_getTempDirURL(rtl_uString ** pustrTempDir)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