lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / sal / osl / w32 / tempfile.cxx
blob5424bfbde077eba919450d96f51cab0fbcc88bb2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <systools/win32/uwinapi.h>
22 #include <osl/file.h>
23 #include <o3tl/char16_t2wchar_t.hxx>
25 #include "file-impl.hxx"
26 #include "file_error.hxx"
27 #include "file_url.hxx"
28 #include "path_helper.hxx"
30 #include <malloc.h>
31 #include <cassert>
33 // Allocate n number of t's on the stack return a pointer to it in p
34 #define STACK_ALLOC(p, t, n) __try {(p) = static_cast<t*>(_alloca((n)*sizeof(t)));} \
35 __except(EXCEPTION_EXECUTE_HANDLER) {(p) = nullptr;}
37 // Temp file functions
39 static oslFileError osl_setup_base_directory_impl_(
40 rtl_uString* pustrDirectoryURL,
41 rtl_uString** ppustr_base_dir)
43 rtl_uString* dir_url = nullptr;
44 rtl_uString* dir = nullptr;
45 oslFileError error = osl_File_E_None;
47 if (pustrDirectoryURL)
48 rtl_uString_assign(&dir_url, pustrDirectoryURL);
49 else
50 error = osl_getTempDirURL(&dir_url);
52 if (error == osl_File_E_None)
54 error = osl_getSystemPathFromFileURL_(dir_url, &dir, false);
55 rtl_uString_release(dir_url);
58 if (error == osl_File_E_None)
60 rtl_uString_assign(ppustr_base_dir, dir);
61 rtl_uString_release(dir);
64 return error;
67 static oslFileError osl_setup_createTempFile_impl_(
68 rtl_uString* pustrDirectoryURL,
69 oslFileHandle* pHandle,
70 rtl_uString** ppustrTempFileURL,
71 rtl_uString** ppustr_base_dir,
72 sal_Bool* b_delete_on_close)
74 oslFileError osl_error;
76 OSL_PRECOND(((pHandle != nullptr) || (ppustrTempFileURL != nullptr)), "Invalid parameter!");
78 if ((pHandle == nullptr) && (ppustrTempFileURL == nullptr))
80 osl_error = osl_File_E_INVAL;
82 else
84 osl_error = osl_setup_base_directory_impl_(
85 pustrDirectoryURL, ppustr_base_dir);
87 *b_delete_on_close = (ppustrTempFileURL == nullptr);
90 return osl_error;
93 static oslFileError osl_win32_GetTempFileName_impl_(
94 rtl_uString* base_directory, LPWSTR temp_file_name)
96 oslFileError osl_error = osl_File_E_None;
98 if (GetTempFileNameW(
99 o3tl::toW(rtl_uString_getStr(base_directory)),
100 L"",
102 temp_file_name) == 0)
104 osl_error = oslTranslateFileError(GetLastError());
107 return osl_error;
110 static bool osl_win32_CreateFile_impl_(
111 LPCWSTR file_name, bool b_delete_on_close, oslFileHandle* p_handle)
113 DWORD flags = FILE_ATTRIBUTE_NORMAL;
114 HANDLE hFile;
116 assert(p_handle);
118 if (b_delete_on_close)
119 flags |= FILE_FLAG_DELETE_ON_CLOSE;
121 hFile = CreateFileW(
122 file_name,
123 GENERIC_READ | GENERIC_WRITE,
125 nullptr,
126 TRUNCATE_EXISTING,
127 flags,
128 nullptr);
130 // @@@ ERROR HANDLING @@@
131 if (IsValidHandle(hFile))
132 *p_handle = osl_createFileHandleFromOSHandle(hFile, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
134 return IsValidHandle(hFile);
137 static oslFileError osl_createTempFile_impl_(
138 rtl_uString* base_directory,
139 LPWSTR tmp_name,
140 bool b_delete_on_close,
141 oslFileHandle* pHandle,
142 rtl_uString** ppustrTempFileURL)
144 oslFileError osl_error;
148 osl_error = osl_win32_GetTempFileName_impl_(base_directory, tmp_name);
150 /* if file could not be opened try again */
152 if ((osl_File_E_None != osl_error) || (nullptr == pHandle) ||
153 osl_win32_CreateFile_impl_(tmp_name, b_delete_on_close, pHandle))
154 break;
156 } while(true); // try until success
158 if ((osl_error == osl_File_E_None) && !b_delete_on_close)
160 rtl_uString* pustr = nullptr;
161 rtl_uString_newFromStr(&pustr, o3tl::toU(tmp_name));
162 osl_getFileURLFromSystemPath(pustr, ppustrTempFileURL);
163 rtl_uString_release(pustr);
166 return osl_error;
169 oslFileError SAL_CALL osl_createTempFile(
170 rtl_uString* pustrDirectoryURL,
171 oslFileHandle* pHandle,
172 rtl_uString** ppustrTempFileURL)
174 rtl_uString* base_directory = nullptr;
175 LPWSTR tmp_name;
176 sal_Bool b_delete_on_close;
177 oslFileError osl_error;
179 osl_error = osl_setup_createTempFile_impl_(
180 pustrDirectoryURL,
181 pHandle,
182 ppustrTempFileURL,
183 &base_directory,
184 &b_delete_on_close);
186 if (osl_error != osl_File_E_None)
187 return osl_error;
189 /* allocate enough space on the stack, the file name can not be longer than MAX_PATH */
190 STACK_ALLOC(tmp_name, WCHAR, (rtl_uString_getLength(base_directory) + MAX_PATH));
192 if (tmp_name)
194 osl_createTempFile_impl_(
195 base_directory,
196 tmp_name,
197 b_delete_on_close,
198 pHandle,
199 ppustrTempFileURL);
201 else // stack alloc failed
203 osl_error = osl_File_E_NOMEM;
206 if (base_directory)
207 rtl_uString_release(base_directory);
209 return osl_error;
212 oslFileError SAL_CALL osl_getTempDirURL(rtl_uString** pustrTempDir)
214 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
215 LPWSTR lpBuffer = o3tl::toW(aBuffer);
216 DWORD nBufferLength = aBuffer.getBufSizeInSymbols() - 1;
218 DWORD nLength;
219 oslFileError error;
221 nLength = GetTempPathW( aBuffer.getBufSizeInSymbols(), lpBuffer );
223 if ( nLength > nBufferLength )
225 // the provided path has invalid length
226 error = osl_File_E_NOENT;
228 else if ( nLength )
230 rtl_uString *ustrTempPath = nullptr;
232 if ( '\\' == lpBuffer[nLength-1] )
233 lpBuffer[nLength-1] = 0;
235 rtl_uString_newFromStr( &ustrTempPath, o3tl::toU(lpBuffer) );
237 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
239 rtl_uString_release( ustrTempPath );
241 else
242 error = oslTranslateFileError( GetLastError() );
244 return error;
247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */