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
}