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