summaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/pathutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/pathutil.cpp104
1 files changed, 74 insertions, 30 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
index 99be003c..a9a19b9f 100644
--- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
@@ -157,11 +157,12 @@ DAPI_(HRESULT) PathExpand(
157 __in DWORD dwResolveFlags 157 __in DWORD dwResolveFlags
158 ) 158 )
159{ 159{
160 Assert(wzRelativePath && *wzRelativePath); 160 Assert(wzRelativePath);
161 161
162 HRESULT hr = S_OK; 162 HRESULT hr = S_OK;
163 DWORD cch = 0; 163 DWORD cch = 0;
164 LPWSTR sczExpandedPath = NULL; 164 LPWSTR sczExpandedPath = NULL;
165 SIZE_T cchWritten = 0;
165 DWORD cchExpandedPath = 0; 166 DWORD cchExpandedPath = 0;
166 SIZE_T cbSize = 0; 167 SIZE_T cbSize = 0;
167 168
@@ -221,37 +222,12 @@ DAPI_(HRESULT) PathExpand(
221 // 222 //
222 if (dwResolveFlags & PATH_EXPAND_FULLPATH) 223 if (dwResolveFlags & PATH_EXPAND_FULLPATH)
223 { 224 {
224 LPWSTR wzFileName = NULL;
225 LPCWSTR wzPath = sczExpandedPath ? sczExpandedPath : wzRelativePath; 225 LPCWSTR wzPath = sczExpandedPath ? sczExpandedPath : wzRelativePath;
226 DWORD cchFullPath = max(PATH_GOOD_ENOUGH, cchExpandedPath);
227 226
228 hr = StrAlloc(&sczFullPath, cchFullPath); 227 hr = PathGetFullPathName(wzPath, &sczFullPath, NULL, &cchWritten);
229 PathExitOnFailure(hr, "Failed to allocate space for full path."); 228 PathExitOnFailure(hr, "Failed to get full path for string: %ls", wzPath);
230
231 cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName);
232 if (0 == cch)
233 {
234 PathExitWithLastError(hr, "Failed to get full path for string: %ls", wzPath);
235 }
236 else if (cchFullPath < cch)
237 {
238 cchFullPath = cch < MAX_PATH ? cch : cch + 7; // ensure space for "\\?\UNC" prefix if needed
239 hr = StrAlloc(&sczFullPath, cchFullPath);
240 PathExitOnFailure(hr, "Failed to re-allocate more space for full path.");
241 229
242 cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName); 230 if (MAX_PATH < cchWritten)
243 if (0 == cch)
244 {
245 PathExitWithLastError(hr, "Failed to get full path for string: %ls", wzPath);
246 }
247 else if (cchFullPath < cch)
248 {
249 hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
250 PathExitOnRootFailure(hr, "Failed to allocate buffer for full path.");
251 }
252 }
253
254 if (MAX_PATH < cch)
255 { 231 {
256 hr = PathPrefix(&sczFullPath); 232 hr = PathPrefix(&sczFullPath);
257 PathExitOnFailure(hr, "Failed to prefix long path after expanding."); 233 PathExitOnFailure(hr, "Failed to prefix long path after expanding.");
@@ -263,7 +239,7 @@ DAPI_(HRESULT) PathExpand(
263 sczExpandedPath = NULL; 239 sczExpandedPath = NULL;
264 } 240 }
265 241
266 hr = StrAllocString(psczFullPath, sczFullPath? sczFullPath : wzRelativePath, 0); 242 hr = StrAllocString(psczFullPath, sczFullPath ? sczFullPath : wzRelativePath, 0);
267 PathExitOnFailure(hr, "Failed to copy relative path into full path."); 243 PathExitOnFailure(hr, "Failed to copy relative path into full path.");
268 244
269LExit: 245LExit:
@@ -274,6 +250,74 @@ LExit:
274} 250}
275 251
276 252
253DAPI_(HRESULT) PathGetFullPathName(
254 __in_z LPCWSTR wzPath,
255 __deref_out_z LPWSTR* psczFullPath,
256 __inout_z_opt LPCWSTR* pwzFileName,
257 __out_opt SIZE_T* pcch
258 )
259{
260 HRESULT hr = S_OK;
261 SIZE_T cchMax = 0;
262 DWORD cchBuffer = 0;
263 DWORD cch = 0;
264 DWORD dwAttempts = 0;
265 const DWORD dwMaxAttempts = 10;
266
267 if (!wzPath || !*wzPath)
268 {
269 hr = DirGetCurrent(psczFullPath, pcch);
270 PathExitOnFailure(hr, "Failed to get current directory.");
271
272 ExitFunction();
273 }
274
275 if (*psczFullPath)
276 {
277 hr = StrMaxLength(*psczFullPath, &cchMax);
278 PathExitOnFailure(hr, "Failed to get max length of input buffer.");
279
280 cchBuffer = (DWORD)min(DWORD_MAX, cchMax);
281 }
282 else
283 {
284 cchBuffer = MAX_PATH + 1;
285
286 hr = StrAlloc(psczFullPath, cchBuffer);
287 PathExitOnFailure(hr, "Failed to allocate space for full path.");
288 }
289
290 for (; dwAttempts < dwMaxAttempts; ++dwAttempts)
291 {
292 cch = ::GetFullPathNameW(wzPath, cchBuffer, *psczFullPath, const_cast<LPWSTR*>(pwzFileName));
293 PathExitOnNullWithLastError(cch, hr, "Failed to get full path for string: %ls", wzPath);
294
295 if (cch < cchBuffer)
296 {
297 break;
298 }
299
300 hr = StrAlloc(psczFullPath, cch);
301 PathExitOnFailure(hr, "Failed to reallocate space for full path.");
302
303 cchBuffer = cch;
304 }
305
306 if (dwMaxAttempts == dwAttempts)
307 {
308 PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "GetFullPathNameW results never converged.");
309 }
310
311 if (pcch)
312 {
313 *pcch = cch;
314 }
315
316LExit:
317 return hr;
318}
319
320
277DAPI_(HRESULT) PathPrefix( 321DAPI_(HRESULT) PathPrefix(
278 __inout LPWSTR *psczFullPath 322 __inout LPWSTR *psczFullPath
279 ) 323 )