@joebigelow / wix / commits / 8a4d0320

Resolve paths while parsing them from the command line.

The current directory is a process wide setting that can potentially be changed by any thread. Remove fileutil methods that had equivalent pathutil methods.

Sean Hall committed Jun 3, 2022 at 17:47 UTC 8a4d03207633e9fdc364aaed82bd167f844679f9
16 files changed +301 -210
src/burn/engine/core.cpp
+6 -12
@@ -1419,7 +1419,7 @@ extern "C" HRESULT CoreParseCommandLine(
1419
1420 ++i;
1421
1422 - hr = StrAllocString(&pInternalCommand->sczLogFile, argv[i], 0);
1422 + hr = PathExpand(&pInternalCommand->sczLogFile, argv[i], PATH_EXPAND_FULLPATH);
1423 ExitOnFailure(hr, "Failed to copy log file path.");
1424 }
1425 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"?", -1) ||
@@ -1516,7 +1516,7 @@ extern "C" HRESULT CoreParseCommandLine(
1516 }
1517
1518 ++i;
1519 - hr = StrAllocString(&pInternalCommand->sczOriginalSource, argv[i], 0);
1519 + hr = PathExpand(&pInternalCommand->sczOriginalSource, argv[i], PATH_EXPAND_FULLPATH);
1520 ExitOnFailure(hr, "Failed to copy last used source.");
1521 }
1522 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PARENT, -1))
@@ -1547,7 +1547,7 @@ extern "C" HRESULT CoreParseCommandLine(
1547
1548 ++i;
1549
1550 - hr = StrAllocString(&pInternalCommand->sczLogFile, argv[i], 0);
1550 + hr = PathExpand(&pInternalCommand->sczLogFile, argv[i], PATH_EXPAND_FULLPATH);
1551 ExitOnFailure(hr, "Failed to copy append log file path.");
1552
1553 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_APPEND;
@@ -1638,7 +1638,7 @@ extern "C" HRESULT CoreParseCommandLine(
1638 }
1639 else if (L'\0' != wzParam[1])
1640 {
1641 - hr = StrAllocString(&pInternalCommand->sczSourceProcessPath, wzParam + 1, 0);
1641 + hr = PathExpand(&pInternalCommand->sczSourceProcessPath, wzParam + 1, PATH_EXPAND_FULLPATH);
1642 ExitOnFailure(hr, "Failed to copy source process path.");
1643 }
1644 }
@@ -1807,16 +1807,10 @@ extern "C" HRESULT CoreParseCommandLine(
1807 fInvalidCommandLine = TRUE;
1808 TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]);
1809 }
1810 - else if (L'\0' == wzParam[1])
1811 - {
1812 - // Need to grab the current directory here since this is passed on to other processes.
1813 - hr = DirGetCurrent(&pInternalCommand->sczEngineWorkingDirectory);
1814 - ExitOnFailure(hr, "Failed to get current directory for custom working directory.");
1815 - }
1810 else
1811 {
1818 - hr = StrAllocString(&pInternalCommand->sczEngineWorkingDirectory, wzParam + 1, 0);
1819 - ExitOnFailure(hr, "Failed to allocate the custom working directory.");
1812 + hr = PathExpand(&pInternalCommand->sczEngineWorkingDirectory, wzParam + 1, PATH_EXPAND_FULLPATH);
1813 + ExitOnFailure(hr, "Failed to store the custom working directory.");
1814 }
1815 }
1816 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED), BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED)))
src/burn/engine/logging.cpp
+1 -4
@@ -84,9 +84,6 @@ extern "C" HRESULT LoggingOpen(
84 {
85 DWORD cRetry = 0;
86
87 - hr = DirGetCurrent(&sczLoggingBaseFolder);
88 - ExitOnFailure(hr, "Failed to get current directory.");
89 -
87 // Try pretty hard to open the log file when appending.
88 do
89 {
@@ -95,7 +92,7 @@ extern "C" HRESULT LoggingOpen(
92 ::Sleep(LOG_OPEN_RETRY_WAIT);
93 }
94
98 - hr = LogOpen(sczLoggingBaseFolder, pLog->sczPath, NULL, NULL, pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND, FALSE, &pLog->sczPath);
95 + hr = LogOpen(NULL, pLog->sczPath, NULL, NULL, pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND, FALSE, &pLog->sczPath);
96 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND && HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == hr)
97 {
98 ++cRetry;
src/libs/dutil/WixToolset.DUtil/cabcutil.cpp
+4 -4
@@ -503,7 +503,7 @@ extern "C" HRESULT DAPI CabCFinish(
503 }
504 else
505 {
506 - LPCWSTR pwzTemp = FileFromPath(fileInfo.wzSourcePath);
506 + LPCWSTR pwzTemp = PathFile(fileInfo.wzSourcePath);
507 hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP);
508 CabcExitOnFailure(hr, "failed to convert file name to ANSI: %ls", pwzTemp);
509 }
@@ -538,7 +538,7 @@ extern "C" HRESULT DAPI CabCFinish(
538 }
539 else
540 {
541 - LPCWSTR pwzTemp = FileFromPath(fileInfo.wzSourcePath);
541 + LPCWSTR pwzTemp = PathFile(fileInfo.wzSourcePath);
542 hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP);
543 CabcExitOnFailure(hr, "failed to convert duplicate file name to ANSI: %ls", pwzTemp);
544 }
@@ -1386,7 +1386,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet(
1386 if (pccab->iCab == 1)
1387 {
1388 pcd->wzFirstCabinetName[0] = '\0';
1389 - LPCWSTR pwzCabinetName = FileFromPath(pcd->wzCabinetPath);
1389 + LPCWSTR pwzCabinetName = PathFile(pcd->wzCabinetPath);
1390 size_t len = wcsnlen(pwzCabinetName, sizeof(pwzCabinetName));
1391 if (len > 4)
1392 {
@@ -1439,7 +1439,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet(
1439 else
1440 {
1441 LPCWSTR wzSourcePath = pcd->prgFiles[0].pwzSourcePath;
1442 - pwzFileToken = FileFromPath(wzSourcePath);
1442 + pwzFileToken = PathFile(wzSourcePath);
1443 }
1444
1445 // The call back to Binder to Add File Transfer for new Cab and add new Cab to Media table
src/libs/dutil/WixToolset.DUtil/cabutil.cpp
+2 -2
@@ -106,7 +106,7 @@ static HANDLE OpenFileWithRetry(
106 __in LPCWSTR wzPath,
107 __in DWORD dwDesiredAccess,
108 __in DWORD dwCreationDisposition
109 -)
109 + )
110 {
111 HANDLE hFile = INVALID_HANDLE_VALUE;
112
@@ -286,7 +286,7 @@ static HRESULT DAPI CabOperation(
286 //
287 // split the cabinet full path into directory and filename and convert to multi-byte (ick!)
288 //
289 - pwz = FileFromPath(sczCabinet);
289 + pwz = PathFile(sczCabinet);
290 CabExitOnNull(pwz, hr, E_INVALIDARG, "failed to process cabinet path: %ls", wzCabinet);
291
292 if (!::WideCharToMultiByte(CP_UTF8, 0, pwz, -1, szCabFile, countof(szCabFile), NULL, NULL))
src/libs/dutil/WixToolset.DUtil/dirutil.cpp
+41 -14
@@ -9,6 +9,7 @@
9 #define DirExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__)
10 #define DirExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__)
11 #define DirExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__)
12 +#define DirExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_DIRUTIL, x, e, s, __VA_ARGS__)
13 #define DirExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__)
14 #define DirExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DIRUTIL, p, x, e, s, __VA_ARGS__)
15 #define DirExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, p, x, s, __VA_ARGS__)
@@ -388,32 +389,58 @@ LExit:
389
390 *******************************************************************/
391 extern "C" HRESULT DAPI DirGetCurrent(
391 - __deref_out_z LPWSTR* psczCurrentDirectory
392 + __deref_out_z LPWSTR* psczCurrentDirectory,
393 + __out_opt SIZE_T* pcch
394 )
395 {
396 + Assert(psczCurrentDirectory);
397 +
398 HRESULT hr = S_OK;
395 - SIZE_T cch = 0;
399 + SIZE_T cchMax = 0;
400 + DWORD cch = 0;
401 + DWORD cchBuffer = 0;
402 + DWORD dwAttempts = 0;
403 + const DWORD dwMaxAttempts = 10;
404
397 - if (psczCurrentDirectory && *psczCurrentDirectory)
405 + if (*psczCurrentDirectory)
406 {
399 - hr = StrMaxLength(*psczCurrentDirectory, &cch);
400 - DirExitOnFailure(hr, "Failed to determine size of current directory.");
401 - }
407 + hr = StrMaxLength(*psczCurrentDirectory, &cchMax);
408 + DirExitOnFailure(hr, "Failed to get max length of input buffer.");
409
403 - DWORD cchRequired = ::GetCurrentDirectoryW((DWORD)min(DWORD_MAX, cch), 0 == cch ? NULL : *psczCurrentDirectory);
404 - if (0 == cchRequired)
410 + cchBuffer = (DWORD)min(DWORD_MAX, cchMax);
411 + }
412 + else
413 {
406 - DirExitWithLastError(hr, "Failed to get current directory.");
414 + cchBuffer = MAX_PATH + 1;
415 +
416 + hr = StrAlloc(psczCurrentDirectory, cchBuffer);
417 + DirExitOnFailure(hr, "Failed to allocate space for current directory.");
418 }
408 - else if (cch < cchRequired)
419 +
420 + for (; dwAttempts < dwMaxAttempts; ++dwAttempts)
421 {
410 - hr = StrAlloc(psczCurrentDirectory, cchRequired);
411 - DirExitOnFailure(hr, "Failed to allocate string for current directory.");
422 + cch = ::GetCurrentDirectoryW(cchBuffer, *psczCurrentDirectory);
423 + DirExitOnNullWithLastError(cch, hr, "Failed to get current directory.");
424
413 - if (!::GetCurrentDirectoryW(cchRequired, *psczCurrentDirectory))
425 + if (cch < cchBuffer)
426 {
415 - DirExitWithLastError(hr, "Failed to get current directory using allocated string.");
427 + break;
428 }
429 +
430 + hr = StrAlloc(psczCurrentDirectory, cch);
431 + DirExitOnFailure(hr, "Failed to reallocate space for current directory.");
432 +
433 + cchBuffer = cch;
434 + }
435 +
436 + if (dwMaxAttempts == dwAttempts)
437 + {
438 + DirExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "GetCurrentDirectoryW results never converged.");
439 + }
440 +
441 + if (pcch)
442 + {
443 + *pcch = cch;
444 }
445
446 LExit:
src/libs/dutil/WixToolset.DUtil/fileutil.cpp
-118
@@ -25,124 +25,6 @@ const BYTE UTF16BOM[] = {0xFF, 0xFE};
25 const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
26 const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations";
27
28 -/*******************************************************************
29 - FileFromPath - returns a pointer to the file part of the path
30 -
31 -********************************************************************/
32 -extern "C" LPWSTR DAPI FileFromPath(
33 - __in_z LPCWSTR wzPath
34 - )
35 -{
36 - if (!wzPath)
37 - return NULL;
38 -
39 - LPWSTR wzFile = const_cast<LPWSTR>(wzPath);
40 - for (LPWSTR wz = wzFile; *wz; ++wz)
41 - {
42 - // valid delineators
43 - // \ => Windows path
44 - // / => unix and URL path
45 - // : => relative path from mapped root
46 - if (L'\\' == *wz || L'/' == *wz || L':' == *wz)
47 - wzFile = wz + 1;
48 - }
49 -
50 - return wzFile;
51 -}
52 -
53 -
54 -/*******************************************************************
55 - FileResolvePath - gets the full path to a file resolving environment
56 - variables along the way.
57 -
58 -********************************************************************/
59 -extern "C" HRESULT DAPI FileResolvePath(
60 - __in_z LPCWSTR wzRelativePath,
61 - __out LPWSTR *ppwzFullPath
62 - )
63 -{
64 - Assert(wzRelativePath && *wzRelativePath);
65 -
66 - HRESULT hr = S_OK;
67 - DWORD cch = 0;
68 - LPWSTR pwzExpandedPath = NULL;
69 - DWORD cchExpandedPath = 0;
70 -
71 - LPWSTR pwzFullPath = NULL;
72 - DWORD cchFullPath = 0;
73 -
74 - LPWSTR wzFileName = NULL;
75 -
76 - //
77 - // First, expand any environment variables.
78 - //
79 - cchExpandedPath = MAX_PATH;
80 - hr = StrAlloc(&pwzExpandedPath, cchExpandedPath);
81 - FileExitOnFailure(hr, "Failed to allocate space for expanded path.");
82 -
83 - cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath);
84 - if (0 == cch)
85 - {
86 - FileExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
87 - }
88 - else if (cchExpandedPath < cch)
89 - {
90 - cchExpandedPath = cch;
91 - hr = StrAlloc(&pwzExpandedPath, cchExpandedPath);
92 - FileExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
93 -
94 - cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath);
95 - if (0 == cch)
96 - {
97 - FileExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
98 - }
99 - else if (cchExpandedPath < cch)
100 - {
101 - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
102 - FileExitOnRootFailure(hr, "Failed to allocate buffer for expanded path.");
103 - }
104 - }
105 -
106 - //
107 - // Second, get the full path.
108 - //
109 - cchFullPath = MAX_PATH;
110 - hr = StrAlloc(&pwzFullPath, cchFullPath);
111 - FileExitOnFailure(hr, "Failed to allocate space for full path.");
112 -
113 - cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName);
114 - if (0 == cch)
115 - {
116 - FileExitWithLastError(hr, "Failed to get full path for string: %ls", pwzExpandedPath);
117 - }
118 - else if (cchFullPath < cch)
119 - {
120 - cchFullPath = cch;
121 - hr = StrAlloc(&pwzFullPath, cchFullPath);
122 - FileExitOnFailure(hr, "Failed to re-allocate more space for full path.");
123 -
124 - cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName);
125 - if (0 == cch)
126 - {
127 - FileExitWithLastError(hr, "Failed to get full path for string: %ls", pwzExpandedPath);
128 - }
129 - else if (cchFullPath < cch)
130 - {
131 - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
132 - FileExitOnRootFailure(hr, "Failed to allocate buffer for full path.");
133 - }
134 - }
135 -
136 - *ppwzFullPath = pwzFullPath;
137 - pwzFullPath = NULL;
138 -
139 -LExit:
140 - ReleaseStr(pwzFullPath);
141 - ReleaseStr(pwzExpandedPath);
142 -
143 - return hr;
144 -}
145 -
28
29 /*******************************************************************
30 FileStripExtension - Strip extension from filename
src/libs/dutil/WixToolset.DUtil/inc/dirutil.h
+2 -1
@@ -46,7 +46,8 @@ DWORD DAPI DirDeleteEmptyDirectoriesToRoot(
46 );
47
48 HRESULT DAPI DirGetCurrent(
49 - __deref_out_z LPWSTR* psczCurrentDirectory
49 + __deref_out_z LPWSTR* psczCurrentDirectory,
50 + __out_opt SIZE_T* pcch
51 );
52
53 HRESULT DAPI DirSetCurrent(
src/libs/dutil/WixToolset.DUtil/inc/fileutil.h
-7
@@ -34,13 +34,6 @@ typedef enum FILE_ENCODING
34 } FILE_ENCODING;
35
36
37 -LPWSTR DAPI FileFromPath(
38 - __in_z LPCWSTR wzPath
39 - );
40 -HRESULT DAPI FileResolvePath(
41 - __in_z LPCWSTR wzRelativePath,
42 - __out LPWSTR *ppwzFullPath
43 - );
37 HRESULT DAPI FileStripExtension(
38 __in_z LPCWSTR wzFileName,
39 __out LPWSTR *ppwzFileNameNoExtension
src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
+10
@@ -67,6 +67,16 @@ DAPI_(HRESULT) PathExpand(
67 __in DWORD dwResolveFlags
68 );
69
70 +/*******************************************************************
71 + PathGetFullPathName - wrapper around GetFullPathNameW.
72 +*******************************************************************/
73 +DAPI_(HRESULT) PathGetFullPathName(
74 + __in_z LPCWSTR wzPath,
75 + __deref_out_z LPWSTR* psczFullPath,
76 + __inout_z_opt LPCWSTR* pwzFileName,
77 + __out_opt SIZE_T* pcch
78 + );
79 +
80 /*******************************************************************
81 PathPrefix - prefixes a full path with \\?\ or \\?\UNC as
82 appropriate.
src/libs/dutil/WixToolset.DUtil/logutil.cpp
+14 -1
@@ -117,6 +117,7 @@ extern "C" HRESULT DAPI LogOpen(
117 {
118 HRESULT hr = S_OK;
119 BOOL fEnteredCriticalSection = FALSE;
120 + LPWSTR sczCombined = NULL;
121 LPWSTR sczLogDirectory = NULL;
122
123 ::EnterCriticalSection(&LogUtil_csLog);
@@ -129,9 +130,20 @@ extern "C" HRESULT DAPI LogOpen(
130 }
131 else
132 {
132 - hr = PathConcat(wzDirectory, wzLog, &LogUtil_sczLogPath);
133 + hr = PathConcat(wzDirectory, wzLog, &sczCombined);
134 LoguExitOnFailure(hr, "Failed to combine the log path.");
135
136 + if (!PathIsFullyQualified(sczCombined, NULL))
137 + {
138 + hr = PathExpand(&LogUtil_sczLogPath, sczCombined, PATH_EXPAND_FULLPATH);
139 + LoguExitOnFailure(hr, "Failed to expand the log path.");
140 + }
141 + else
142 + {
143 + LogUtil_sczLogPath = sczCombined;
144 + sczCombined = NULL;
145 + }
146 +
147 hr = PathGetDirectory(LogUtil_sczLogPath, &sczLogDirectory);
148 LoguExitOnFailure(hr, "Failed to get log directory.");
149
@@ -176,6 +188,7 @@ LExit:
188 ::LeaveCriticalSection(&LogUtil_csLog);
189 }
190
191 + ReleaseStr(sczCombined);
192 ReleaseStr(sczLogDirectory);
193
194 return hr;
src/libs/dutil/WixToolset.DUtil/pathutil.cpp
+74 -30
@@ -157,11 +157,12 @@ DAPI_(HRESULT) PathExpand(
157 __in DWORD dwResolveFlags
158 )
159 {
160 - Assert(wzRelativePath && *wzRelativePath);
160 + Assert(wzRelativePath);
161
162 HRESULT hr = S_OK;
163 DWORD cch = 0;
164 LPWSTR sczExpandedPath = NULL;
165 + SIZE_T cchWritten = 0;
166 DWORD cchExpandedPath = 0;
167 SIZE_T cbSize = 0;
168
@@ -221,37 +222,12 @@ DAPI_(HRESULT) PathExpand(
222 //
223 if (dwResolveFlags & PATH_EXPAND_FULLPATH)
224 {
224 - LPWSTR wzFileName = NULL;
225 LPCWSTR wzPath = sczExpandedPath ? sczExpandedPath : wzRelativePath;
226 - DWORD cchFullPath = max(PATH_GOOD_ENOUGH, cchExpandedPath);
226
228 - hr = StrAlloc(&sczFullPath, cchFullPath);
229 - PathExitOnFailure(hr, "Failed to allocate space for full path.");
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.");
227 + hr = PathGetFullPathName(wzPath, &sczFullPath, NULL, &cchWritten);
228 + PathExitOnFailure(hr, "Failed to get full path for string: %ls", wzPath);
229
242 - cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName);
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)
230 + if (MAX_PATH < cchWritten)
231 {
232 hr = PathPrefix(&sczFullPath);
233 PathExitOnFailure(hr, "Failed to prefix long path after expanding.");
@@ -263,7 +239,7 @@ DAPI_(HRESULT) PathExpand(
239 sczExpandedPath = NULL;
240 }
241
266 - hr = StrAllocString(psczFullPath, sczFullPath? sczFullPath : wzRelativePath, 0);
242 + hr = StrAllocString(psczFullPath, sczFullPath ? sczFullPath : wzRelativePath, 0);
243 PathExitOnFailure(hr, "Failed to copy relative path into full path.");
244
245 LExit:
@@ -274,6 +250,74 @@ LExit:
250 }
251
252
253 +DAPI_(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 +
316 +LExit:
317 + return hr;
318 +}
319 +
320 +
321 DAPI_(HRESULT) PathPrefix(
322 __inout LPWSTR *psczFullPath
323 )
src/libs/dutil/WixToolset.DUtil/sceutil.cpp
+2 -5
@@ -1491,11 +1491,8 @@ static HRESULT CreateSqlCe(
1491 // If that failed, fallback to loading from current path
1492 if (NULL == *phSqlCeDll)
1493 {
1494 - hr = DirGetCurrent(&sczDirectory);
1495 - ExitOnFailure(hr, "Failed to get current directory");
1496 -
1497 - hr = PathConcat(sczDirectory, wzSqlCeDllPath, &sczDllFullPath);
1498 - ExitOnFailure(hr, "Failed to concatenate current directory and DLL filename");
1494 + hr = PathGetFullPathName(wzSqlCeDllPath, &sczDllFullPath, NULL, NULL);
1495 + ExitOnFailure(hr, "Failed to get full path for DLL");
1496
1497 *phSqlCeDll = ::LoadLibraryW(sczDllFullPath);
1498 ExitOnNullWithLastError(*phSqlCeDll, hr, "Failed to open Sql CE DLL: %ls", sczDllFullPath);
src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp
+1 -1
@@ -25,7 +25,7 @@ namespace DutilTests
25 hr = GuidCreate(&sczGuid);
26 NativeAssert::Succeeded(hr, "Failed to create guid.");
27
28 - hr = DirGetCurrent(&sczCurrentDir);
28 + hr = DirGetCurrent(&sczCurrentDir, NULL);
29 NativeAssert::Succeeded(hr, "Failed to get current directory.");
30
31 hr = PathConcat(sczCurrentDir, sczGuid, &sczFolder);
src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
+129
@@ -3,6 +3,7 @@
3 #include "precomp.h"
4
5 using namespace System;
6 +using namespace System::IO;
7 using namespace Xunit;
8 using namespace WixBuildTools::TestSupport;
9
@@ -402,6 +403,70 @@ namespace DutilTests
403 Assert::Equal<HRESULT>(S_OK, hr);
404 }
405
406 + [Fact]
407 + void PathExpandEnvironmentVariablesTest()
408 + {
409 + HRESULT hr = S_OK;
410 + LPWSTR sczExpanded = NULL;
411 + LPCWSTR rgwzPaths[4] =
412 + {
413 + L"", L"",
414 + L"\\\\?\\", L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789",
415 + };
416 +
417 + try
418 + {
419 + for (DWORD i = 0; i < countof(rgwzPaths); i += 2)
420 + {
421 + hr = PathExpand(&sczExpanded, rgwzPaths[i + 1], PATH_EXPAND_ENVIRONMENT);
422 + NativeAssert::Succeeded(hr, "PathExpand: {0}", rgwzPaths[i + 1]);
423 + WixAssert::StringEqual((gcnew String(rgwzPaths[i])) + Environment::ExpandEnvironmentVariables(gcnew String(rgwzPaths[i + 1])), gcnew String(sczExpanded), false);
424 + }
425 + }
426 + finally
427 + {
428 + ReleaseStr(sczExpanded);
429 + }
430 + }
431 +
432 + [Fact]
433 + void PathExpandFullPathTest()
434 + {
435 + HRESULT hr = S_OK;
436 + LPWSTR sczExpanded = NULL;
437 + LPCWSTR wzGreaterThanMaxPathString = L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt";
438 +
439 + try
440 + {
441 + hr = PathExpand(&sczExpanded, wzGreaterThanMaxPathString, PATH_EXPAND_FULLPATH);
442 + NativeAssert::Succeeded(hr, "Failed to expand greater than MAX_PATH string.");
443 + WixAssert::StringEqual((gcnew String("\\\\?\\")) + Path::Combine(Environment::CurrentDirectory, gcnew String(wzGreaterThanMaxPathString)), gcnew String(sczExpanded), false);
444 + }
445 + finally
446 + {
447 + ReleaseStr(sczExpanded);
448 + }
449 + }
450 +
451 + [Fact]
452 + void PathExpandAllTest()
453 + {
454 + HRESULT hr = S_OK;
455 + LPWSTR sczExpanded = NULL;
456 + LPCWSTR wzRelativeEnvironmentVariableString = L"%USERNAME%\\abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt";
457 +
458 + try
459 + {
460 + hr = PathExpand(&sczExpanded, wzRelativeEnvironmentVariableString, PATH_EXPAND_ENVIRONMENT | PATH_EXPAND_FULLPATH);
461 + NativeAssert::Succeeded(hr, "Failed to expand path.");
462 + WixAssert::StringEqual((gcnew String("\\\\?\\")) + Path::Combine(Environment::CurrentDirectory, Environment::ExpandEnvironmentVariables(gcnew String(wzRelativeEnvironmentVariableString))), gcnew String(sczExpanded), false);
463 + }
464 + finally
465 + {
466 + ReleaseStr(sczExpanded);
467 + }
468 + }
469 +
470 [Fact]
471 void PathGetDirectoryTest()
472 {
@@ -435,6 +500,70 @@ namespace DutilTests
500 }
501 }
502
503 + [Fact]
504 + void PathGetFullPathNameTest()
505 + {
506 + HRESULT hr = S_OK;
507 + LPWSTR sczPath = NULL;
508 + LPCWSTR wzFileName = NULL;
509 + LPCWSTR rgwzPaths[33] =
510 + {
511 + L"C:\\", L"C:\\", NULL,
512 + L"C:\\file", L"C:\\file", L"file",
513 + L"C:\\..\\file", L"C:\\file", L"file",
514 + L"C:\\dir\\..\\file.txt", L"C:\\file.txt", L"file.txt",
515 + L"C:\\dir\\\\file.txt.txt", L"C:\\dir\\file.txt.txt", L"file.txt.txt",
516 + L"C:\\dir/.file", L"C:\\dir\\.file", L".file",
517 + L"\\\\?\\C:\\file", L"\\\\?\\C:\\file", L"file",
518 + L"\\\\server\\share\\file", L"\\\\server\\share\\file", L"file",
519 + L"\\\\server\\share\\..\\file", L"\\\\server\\share\\file", L"file",
520 + L"\\\\?\\UNC\\server\\share\\file", L"\\\\?\\UNC\\server\\share\\file", L"file",
521 + L"C:\\abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt", L"C:\\abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt", L"a.txt",
522 + };
523 +
524 + try
525 + {
526 + for (DWORD i = 0; i < countof(rgwzPaths); i += 3)
527 + {
528 + hr = PathGetFullPathName(rgwzPaths[i], &sczPath, &wzFileName, NULL);
529 + NativeAssert::Succeeded(hr, "PathGetFullPathName: {0}", rgwzPaths[i]);
530 + NativeAssert::StringEqual(rgwzPaths[i + 1], sczPath);
531 + NativeAssert::StringEqual(rgwzPaths[i + 2], wzFileName);
532 + }
533 + }
534 + finally
535 + {
536 + ReleaseStr(sczPath);
537 + }
538 + }
539 +
540 + [Fact]
541 + void PathGetFullPathNameRelativeTest()
542 + {
543 + HRESULT hr = S_OK;
544 + LPWSTR sczPath = NULL;
545 + LPCWSTR rgwzPaths[4] =
546 + {
547 + L"",
548 + L"a.txt",
549 + L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt",
550 + };
551 +
552 + try
553 + {
554 + for (DWORD i = 0; i < countof(rgwzPaths); ++i)
555 + {
556 + hr = PathGetFullPathName(rgwzPaths[i], &sczPath, NULL, NULL);
557 + NativeAssert::Succeeded(hr, "PathGetFullPathName: {0}", rgwzPaths[i]);
558 + WixAssert::StringEqual(Path::Combine(Environment::CurrentDirectory, gcnew String(rgwzPaths[i])), gcnew String(sczPath), false);
559 + }
560 + }
561 + finally
562 + {
563 + ReleaseStr(sczPath);
564 + }
565 + }
566 +
567 [Fact]
568 void PathGetHierarchyArrayTest()
569 {
src/wix/WixToolset.Core.Native/WixNativeExe.cs
+1
@@ -36,6 +36,7 @@ namespace WixToolset.Core.Native
36
37 var wixNativeInfo = new ProcessStartInfo(PathToWixNativeExe, this.commandLine)
38 {
39 + WorkingDirectory = Environment.CurrentDirectory,
40 RedirectStandardInput = true,
41 RedirectStandardOutput = true,
42 RedirectStandardError = true,
src/wix/wixnative/smartcab.cpp
+14 -11
@@ -9,10 +9,10 @@ static void __stdcall CabNamesCallback(__in_z LPWSTR wzFirstCabName, __in_z LPWS
9 HRESULT SmartCabCommand(
10 __in int argc,
11 __in_ecount(argc) LPWSTR argv[]
12 -)
12 + )
13 {
14 HRESULT hr = E_INVALIDARG;
15 - LPCWSTR wzCabPath = NULL;
15 + LPWSTR sczCabPath = NULL;
16 LPCWSTR wzCabName = NULL;
17 LPWSTR sczCabDir = NULL;
18 UINT uiFileCount = 0;
@@ -27,11 +27,13 @@ HRESULT SmartCabCommand(
27 }
28 else
29 {
30 - wzCabPath = argv[0];
31 - wzCabName = PathFile(wzCabPath);
30 + hr = PathExpand(&sczCabPath, argv[0], PATH_EXPAND_FULLPATH);
31 + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not expand path: %ls", argv[0]);
32
33 - hr = PathGetDirectory(wzCabPath, &sczCabDir);
34 - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", wzCabPath);
33 + wzCabName = PathFile(sczCabPath);
34 +
35 + hr = PathGetDirectory(sczCabPath, &sczCabDir);
36 + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", sczCabPath);
37
38 if (argc > 1)
39 {
@@ -62,7 +64,7 @@ HRESULT SmartCabCommand(
64 }
65
66 hr = CabCBegin(wzCabName, sczCabDir, uiFileCount, uiMaxSize, uiMaxThresh, ct, &hCab);
65 - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to initialize cabinet: %ls", wzCabPath);
67 + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to initialize cabinet: %ls", sczCabPath);
68
69 if (uiFileCount > 0)
70 {
@@ -70,12 +72,12 @@ HRESULT SmartCabCommand(
72 ExitOnFailure(hr, "failed to read stdin preamble before smartcabbing");
73
74 hr = CompressFiles(hCab);
73 - ExitOnFailure(hr, "failed to compress files into cabinet: %ls", wzCabPath);
75 + ExitOnFailure(hr, "failed to compress files into cabinet: %ls", sczCabPath);
76 }
77
78 hr = CabCFinish(hCab, CabNamesCallback);
79 hCab = NULL; // once finish is called, the handle is invalid.
78 - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to compress cabinet: %ls", wzCabPath);
80 + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to compress cabinet: %ls", sczCabPath);
81
82
83 LExit:
@@ -84,6 +86,7 @@ LExit:
86 CabCCancel(hCab);
87 }
88 ReleaseStr(sczCabDir);
89 + ReleaseStr(sczCabPath);
90
91 return hr;
92 }
@@ -91,7 +94,7 @@ LExit:
94
95 static HRESULT CompressFiles(
96 __in HANDLE hCab
94 -)
97 + )
98 {
99 HRESULT hr = S_OK;
100 LPWSTR sczLine = NULL;
@@ -157,7 +160,7 @@ static void __stdcall CabNamesCallback(
160 __in_z LPWSTR wzFirstCabName,
161 __in_z LPWSTR wzNewCabName,
162 __in_z LPWSTR wzFileToken
160 -)
163 + )
164 {
165 ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken);
166 }