aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-06-03 17:47:31 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-06-07 19:44:36 -0500
commit8a4d03207633e9fdc364aaed82bd167f844679f9 (patch)
tree9ca862bb51fd3507fc5867c292aef236e3411867 /src
parent5d35ff01e33b8ffdab04a49ddc5927185309391a (diff)
downloadwix-8a4d03207633e9fdc364aaed82bd167f844679f9.tar.gz
wix-8a4d03207633e9fdc364aaed82bd167f844679f9.tar.bz2
wix-8a4d03207633e9fdc364aaed82bd167f844679f9.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/burn/engine/core.cpp18
-rw-r--r--src/burn/engine/logging.cpp5
-rw-r--r--src/libs/dutil/WixToolset.DUtil/cabcutil.cpp8
-rw-r--r--src/libs/dutil/WixToolset.DUtil/cabutil.cpp4
-rw-r--r--src/libs/dutil/WixToolset.DUtil/dirutil.cpp55
-rw-r--r--src/libs/dutil/WixToolset.DUtil/fileutil.cpp118
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/dirutil.h3
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/fileutil.h7
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/pathutil.h10
-rw-r--r--src/libs/dutil/WixToolset.DUtil/logutil.cpp15
-rw-r--r--src/libs/dutil/WixToolset.DUtil/pathutil.cpp104
-rw-r--r--src/libs/dutil/WixToolset.DUtil/sceutil.cpp7
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp2
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp129
-rw-r--r--src/wix/WixToolset.Core.Native/WixNativeExe.cs1
-rw-r--r--src/wix/wixnative/smartcab.cpp25
16 files changed, 301 insertions, 210 deletions
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 4255fa6b..39836bce 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -1419,7 +1419,7 @@ extern "C" HRESULT CoreParseCommandLine(
1419 1419
1420 ++i; 1420 ++i;
1421 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."); 1423 ExitOnFailure(hr, "Failed to copy log file path.");
1424 } 1424 }
1425 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"?", -1) || 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 } 1516 }
1517 1517
1518 ++i; 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."); 1520 ExitOnFailure(hr, "Failed to copy last used source.");
1521 } 1521 }
1522 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PARENT, -1)) 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 1547
1548 ++i; 1548 ++i;
1549 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."); 1551 ExitOnFailure(hr, "Failed to copy append log file path.");
1552 1552
1553 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_APPEND; 1553 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_APPEND;
@@ -1638,7 +1638,7 @@ extern "C" HRESULT CoreParseCommandLine(
1638 } 1638 }
1639 else if (L'\0' != wzParam[1]) 1639 else if (L'\0' != wzParam[1])
1640 { 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."); 1642 ExitOnFailure(hr, "Failed to copy source process path.");
1643 } 1643 }
1644 } 1644 }
@@ -1807,16 +1807,10 @@ extern "C" HRESULT CoreParseCommandLine(
1807 fInvalidCommandLine = TRUE; 1807 fInvalidCommandLine = TRUE;
1808 TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]); 1808 TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]);
1809 } 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 }
1816 else 1810 else
1817 { 1811 {
1818 hr = StrAllocString(&pInternalCommand->sczEngineWorkingDirectory, wzParam + 1, 0); 1812 hr = PathExpand(&pInternalCommand->sczEngineWorkingDirectory, wzParam + 1, PATH_EXPAND_FULLPATH);
1819 ExitOnFailure(hr, "Failed to allocate the custom working directory."); 1813 ExitOnFailure(hr, "Failed to store the custom working directory.");
1820 } 1814 }
1821 } 1815 }
1822 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))) 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)))
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 8e89957b..3a403025 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -84,9 +84,6 @@ extern "C" HRESULT LoggingOpen(
84 { 84 {
85 DWORD cRetry = 0; 85 DWORD cRetry = 0;
86 86
87 hr = DirGetCurrent(&sczLoggingBaseFolder);
88 ExitOnFailure(hr, "Failed to get current directory.");
89
90 // Try pretty hard to open the log file when appending. 87 // Try pretty hard to open the log file when appending.
91 do 88 do
92 { 89 {
@@ -95,7 +92,7 @@ extern "C" HRESULT LoggingOpen(
95 ::Sleep(LOG_OPEN_RETRY_WAIT); 92 ::Sleep(LOG_OPEN_RETRY_WAIT);
96 } 93 }
97 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);
99 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND && HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == hr) 96 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND && HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == hr)
100 { 97 {
101 ++cRetry; 98 ++cRetry;
diff --git a/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp b/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp
index 9cc45a83..d1edc54d 100644
--- a/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp
@@ -503,7 +503,7 @@ extern "C" HRESULT DAPI CabCFinish(
503 } 503 }
504 else 504 else
505 { 505 {
506 LPCWSTR pwzTemp = FileFromPath(fileInfo.wzSourcePath); 506 LPCWSTR pwzTemp = PathFile(fileInfo.wzSourcePath);
507 hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP); 507 hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP);
508 CabcExitOnFailure(hr, "failed to convert file name to ANSI: %ls", pwzTemp); 508 CabcExitOnFailure(hr, "failed to convert file name to ANSI: %ls", pwzTemp);
509 } 509 }
@@ -538,7 +538,7 @@ extern "C" HRESULT DAPI CabCFinish(
538 } 538 }
539 else 539 else
540 { 540 {
541 LPCWSTR pwzTemp = FileFromPath(fileInfo.wzSourcePath); 541 LPCWSTR pwzTemp = PathFile(fileInfo.wzSourcePath);
542 hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP); 542 hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP);
543 CabcExitOnFailure(hr, "failed to convert duplicate file name to ANSI: %ls", pwzTemp); 543 CabcExitOnFailure(hr, "failed to convert duplicate file name to ANSI: %ls", pwzTemp);
544 } 544 }
@@ -1386,7 +1386,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet(
1386 if (pccab->iCab == 1) 1386 if (pccab->iCab == 1)
1387 { 1387 {
1388 pcd->wzFirstCabinetName[0] = '\0'; 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)); 1390 size_t len = wcsnlen(pwzCabinetName, sizeof(pwzCabinetName));
1391 if (len > 4) 1391 if (len > 4)
1392 { 1392 {
@@ -1439,7 +1439,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet(
1439 else 1439 else
1440 { 1440 {
1441 LPCWSTR wzSourcePath = pcd->prgFiles[0].pwzSourcePath; 1441 LPCWSTR wzSourcePath = pcd->prgFiles[0].pwzSourcePath;
1442 pwzFileToken = FileFromPath(wzSourcePath); 1442 pwzFileToken = PathFile(wzSourcePath);
1443 } 1443 }
1444 1444
1445 // The call back to Binder to Add File Transfer for new Cab and add new Cab to Media table 1445 // The call back to Binder to Add File Transfer for new Cab and add new Cab to Media table
diff --git a/src/libs/dutil/WixToolset.DUtil/cabutil.cpp b/src/libs/dutil/WixToolset.DUtil/cabutil.cpp
index 5d77e483..f3629d57 100644
--- a/src/libs/dutil/WixToolset.DUtil/cabutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/cabutil.cpp
@@ -106,7 +106,7 @@ static HANDLE OpenFileWithRetry(
106 __in LPCWSTR wzPath, 106 __in LPCWSTR wzPath,
107 __in DWORD dwDesiredAccess, 107 __in DWORD dwDesiredAccess,
108 __in DWORD dwCreationDisposition 108 __in DWORD dwCreationDisposition
109) 109 )
110{ 110{
111 HANDLE hFile = INVALID_HANDLE_VALUE; 111 HANDLE hFile = INVALID_HANDLE_VALUE;
112 112
@@ -286,7 +286,7 @@ static HRESULT DAPI CabOperation(
286 // 286 //
287 // split the cabinet full path into directory and filename and convert to multi-byte (ick!) 287 // split the cabinet full path into directory and filename and convert to multi-byte (ick!)
288 // 288 //
289 pwz = FileFromPath(sczCabinet); 289 pwz = PathFile(sczCabinet);
290 CabExitOnNull(pwz, hr, E_INVALIDARG, "failed to process cabinet path: %ls", wzCabinet); 290 CabExitOnNull(pwz, hr, E_INVALIDARG, "failed to process cabinet path: %ls", wzCabinet);
291 291
292 if (!::WideCharToMultiByte(CP_UTF8, 0, pwz, -1, szCabFile, countof(szCabFile), NULL, NULL)) 292 if (!::WideCharToMultiByte(CP_UTF8, 0, pwz, -1, szCabFile, countof(szCabFile), NULL, NULL))
diff --git a/src/libs/dutil/WixToolset.DUtil/dirutil.cpp b/src/libs/dutil/WixToolset.DUtil/dirutil.cpp
index ae2c5e1c..c106a467 100644
--- a/src/libs/dutil/WixToolset.DUtil/dirutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/dirutil.cpp
@@ -9,6 +9,7 @@
9#define DirExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__) 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__) 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__) 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__)
12#define DirExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__) 13#define DirExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__)
13#define DirExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DIRUTIL, p, x, e, s, __VA_ARGS__) 14#define DirExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DIRUTIL, p, x, e, s, __VA_ARGS__)
14#define DirExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, p, x, s, __VA_ARGS__) 15#define DirExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, p, x, s, __VA_ARGS__)
@@ -388,32 +389,58 @@ LExit:
388 389
389*******************************************************************/ 390*******************************************************************/
390extern "C" HRESULT DAPI DirGetCurrent( 391extern "C" HRESULT DAPI DirGetCurrent(
391 __deref_out_z LPWSTR* psczCurrentDirectory 392 __deref_out_z LPWSTR* psczCurrentDirectory,
393 __out_opt SIZE_T* pcch
392 ) 394 )
393{ 395{
396 Assert(psczCurrentDirectory);
397
394 HRESULT hr = S_OK; 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;
396 404
397 if (psczCurrentDirectory && *psczCurrentDirectory) 405 if (*psczCurrentDirectory)
398 { 406 {
399 hr = StrMaxLength(*psczCurrentDirectory, &cch); 407 hr = StrMaxLength(*psczCurrentDirectory, &cchMax);
400 DirExitOnFailure(hr, "Failed to determine size of current directory."); 408 DirExitOnFailure(hr, "Failed to get max length of input buffer.");
401 }
402 409
403 DWORD cchRequired = ::GetCurrentDirectoryW((DWORD)min(DWORD_MAX, cch), 0 == cch ? NULL : *psczCurrentDirectory); 410 cchBuffer = (DWORD)min(DWORD_MAX, cchMax);
404 if (0 == cchRequired) 411 }
412 else
405 { 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.");
407 } 418 }
408 else if (cch < cchRequired) 419
420 for (; dwAttempts < dwMaxAttempts; ++dwAttempts)
409 { 421 {
410 hr = StrAlloc(psczCurrentDirectory, cchRequired); 422 cch = ::GetCurrentDirectoryW(cchBuffer, *psczCurrentDirectory);
411 DirExitOnFailure(hr, "Failed to allocate string for current directory."); 423 DirExitOnNullWithLastError(cch, hr, "Failed to get current directory.");
412 424
413 if (!::GetCurrentDirectoryW(cchRequired, *psczCurrentDirectory)) 425 if (cch < cchBuffer)
414 { 426 {
415 DirExitWithLastError(hr, "Failed to get current directory using allocated string."); 427 break;
416 } 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;
417 } 444 }
418 445
419LExit: 446LExit:
diff --git a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp
index 1822727a..2fe04de1 100644
--- a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp
@@ -25,124 +25,6 @@ const BYTE UTF16BOM[] = {0xFF, 0xFE};
25const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager"; 25const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
26const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations"; 26const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations";
27 27
28/*******************************************************************
29 FileFromPath - returns a pointer to the file part of the path
30
31********************************************************************/
32extern "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********************************************************************/
59extern "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
139LExit:
140 ReleaseStr(pwzFullPath);
141 ReleaseStr(pwzExpandedPath);
142
143 return hr;
144}
145
146 28
147/******************************************************************* 29/*******************************************************************
148FileStripExtension - Strip extension from filename 30FileStripExtension - Strip extension from filename
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h b/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h
index 539b3a73..42268a16 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h
@@ -46,7 +46,8 @@ DWORD DAPI DirDeleteEmptyDirectoriesToRoot(
46 ); 46 );
47 47
48HRESULT DAPI DirGetCurrent( 48HRESULT DAPI DirGetCurrent(
49 __deref_out_z LPWSTR* psczCurrentDirectory 49 __deref_out_z LPWSTR* psczCurrentDirectory,
50 __out_opt SIZE_T* pcch
50 ); 51 );
51 52
52HRESULT DAPI DirSetCurrent( 53HRESULT DAPI DirSetCurrent(
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h b/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h
index d3e326f7..868312dc 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h
@@ -34,13 +34,6 @@ typedef enum FILE_ENCODING
34} FILE_ENCODING; 34} FILE_ENCODING;
35 35
36 36
37LPWSTR DAPI FileFromPath(
38 __in_z LPCWSTR wzPath
39 );
40HRESULT DAPI FileResolvePath(
41 __in_z LPCWSTR wzRelativePath,
42 __out LPWSTR *ppwzFullPath
43 );
44HRESULT DAPI FileStripExtension( 37HRESULT DAPI FileStripExtension(
45 __in_z LPCWSTR wzFileName, 38 __in_z LPCWSTR wzFileName,
46 __out LPWSTR *ppwzFileNameNoExtension 39 __out LPWSTR *ppwzFileNameNoExtension
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
index 941793f8..871e706b 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
@@ -68,6 +68,16 @@ DAPI_(HRESULT) PathExpand(
68 ); 68 );
69 69
70/******************************************************************* 70/*******************************************************************
71 PathGetFullPathName - wrapper around GetFullPathNameW.
72*******************************************************************/
73DAPI_(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/*******************************************************************
71 PathPrefix - prefixes a full path with \\?\ or \\?\UNC as 81 PathPrefix - prefixes a full path with \\?\ or \\?\UNC as
72 appropriate. 82 appropriate.
73********************************************************************/ 83********************************************************************/
diff --git a/src/libs/dutil/WixToolset.DUtil/logutil.cpp b/src/libs/dutil/WixToolset.DUtil/logutil.cpp
index bd21098c..94c21374 100644
--- a/src/libs/dutil/WixToolset.DUtil/logutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/logutil.cpp
@@ -117,6 +117,7 @@ extern "C" HRESULT DAPI LogOpen(
117{ 117{
118 HRESULT hr = S_OK; 118 HRESULT hr = S_OK;
119 BOOL fEnteredCriticalSection = FALSE; 119 BOOL fEnteredCriticalSection = FALSE;
120 LPWSTR sczCombined = NULL;
120 LPWSTR sczLogDirectory = NULL; 121 LPWSTR sczLogDirectory = NULL;
121 122
122 ::EnterCriticalSection(&LogUtil_csLog); 123 ::EnterCriticalSection(&LogUtil_csLog);
@@ -129,9 +130,20 @@ extern "C" HRESULT DAPI LogOpen(
129 } 130 }
130 else 131 else
131 { 132 {
132 hr = PathConcat(wzDirectory, wzLog, &LogUtil_sczLogPath); 133 hr = PathConcat(wzDirectory, wzLog, &sczCombined);
133 LoguExitOnFailure(hr, "Failed to combine the log path."); 134 LoguExitOnFailure(hr, "Failed to combine the log path.");
134 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
135 hr = PathGetDirectory(LogUtil_sczLogPath, &sczLogDirectory); 147 hr = PathGetDirectory(LogUtil_sczLogPath, &sczLogDirectory);
136 LoguExitOnFailure(hr, "Failed to get log directory."); 148 LoguExitOnFailure(hr, "Failed to get log directory.");
137 149
@@ -176,6 +188,7 @@ LExit:
176 ::LeaveCriticalSection(&LogUtil_csLog); 188 ::LeaveCriticalSection(&LogUtil_csLog);
177 } 189 }
178 190
191 ReleaseStr(sczCombined);
179 ReleaseStr(sczLogDirectory); 192 ReleaseStr(sczLogDirectory);
180 193
181 return hr; 194 return hr;
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 )
diff --git a/src/libs/dutil/WixToolset.DUtil/sceutil.cpp b/src/libs/dutil/WixToolset.DUtil/sceutil.cpp
index cdb1623b..4eede74f 100644
--- a/src/libs/dutil/WixToolset.DUtil/sceutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/sceutil.cpp
@@ -1491,11 +1491,8 @@ static HRESULT CreateSqlCe(
1491 // If that failed, fallback to loading from current path 1491 // If that failed, fallback to loading from current path
1492 if (NULL == *phSqlCeDll) 1492 if (NULL == *phSqlCeDll)
1493 { 1493 {
1494 hr = DirGetCurrent(&sczDirectory); 1494 hr = PathGetFullPathName(wzSqlCeDllPath, &sczDllFullPath, NULL, NULL);
1495 ExitOnFailure(hr, "Failed to get current directory"); 1495 ExitOnFailure(hr, "Failed to get full path for DLL");
1496
1497 hr = PathConcat(sczDirectory, wzSqlCeDllPath, &sczDllFullPath);
1498 ExitOnFailure(hr, "Failed to concatenate current directory and DLL filename");
1499 1496
1500 *phSqlCeDll = ::LoadLibraryW(sczDllFullPath); 1497 *phSqlCeDll = ::LoadLibraryW(sczDllFullPath);
1501 ExitOnNullWithLastError(*phSqlCeDll, hr, "Failed to open Sql CE DLL: %ls", sczDllFullPath); 1498 ExitOnNullWithLastError(*phSqlCeDll, hr, "Failed to open Sql CE DLL: %ls", sczDllFullPath);
diff --git a/src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp b/src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp
index 7643366f..14ed7807 100644
--- a/src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp
+++ b/src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp
@@ -25,7 +25,7 @@ namespace DutilTests
25 hr = GuidCreate(&sczGuid); 25 hr = GuidCreate(&sczGuid);
26 NativeAssert::Succeeded(hr, "Failed to create guid."); 26 NativeAssert::Succeeded(hr, "Failed to create guid.");
27 27
28 hr = DirGetCurrent(&sczCurrentDir); 28 hr = DirGetCurrent(&sczCurrentDir, NULL);
29 NativeAssert::Succeeded(hr, "Failed to get current directory."); 29 NativeAssert::Succeeded(hr, "Failed to get current directory.");
30 30
31 hr = PathConcat(sczCurrentDir, sczGuid, &sczFolder); 31 hr = PathConcat(sczCurrentDir, sczGuid, &sczFolder);
diff --git a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
index 52698b98..554c6f00 100644
--- a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
+++ b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
@@ -3,6 +3,7 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5using namespace System; 5using namespace System;
6using namespace System::IO;
6using namespace Xunit; 7using namespace Xunit;
7using namespace WixBuildTools::TestSupport; 8using namespace WixBuildTools::TestSupport;
8 9
@@ -403,6 +404,70 @@ namespace DutilTests
403 } 404 }
404 405
405 [Fact] 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]
406 void PathGetDirectoryTest() 471 void PathGetDirectoryTest()
407 { 472 {
408 HRESULT hr = S_OK; 473 HRESULT hr = S_OK;
@@ -436,6 +501,70 @@ namespace DutilTests
436 } 501 }
437 502
438 [Fact] 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]
439 void PathGetHierarchyArrayTest() 568 void PathGetHierarchyArrayTest()
440 { 569 {
441 HRESULT hr = S_OK; 570 HRESULT hr = S_OK;
diff --git a/src/wix/WixToolset.Core.Native/WixNativeExe.cs b/src/wix/WixToolset.Core.Native/WixNativeExe.cs
index f5ff8bf0..90439c5d 100644
--- a/src/wix/WixToolset.Core.Native/WixNativeExe.cs
+++ b/src/wix/WixToolset.Core.Native/WixNativeExe.cs
@@ -36,6 +36,7 @@ namespace WixToolset.Core.Native
36 36
37 var wixNativeInfo = new ProcessStartInfo(PathToWixNativeExe, this.commandLine) 37 var wixNativeInfo = new ProcessStartInfo(PathToWixNativeExe, this.commandLine)
38 { 38 {
39 WorkingDirectory = Environment.CurrentDirectory,
39 RedirectStandardInput = true, 40 RedirectStandardInput = true,
40 RedirectStandardOutput = true, 41 RedirectStandardOutput = true,
41 RedirectStandardError = true, 42 RedirectStandardError = true,
diff --git a/src/wix/wixnative/smartcab.cpp b/src/wix/wixnative/smartcab.cpp
index dedcbc2d..b5f20736 100644
--- a/src/wix/wixnative/smartcab.cpp
+++ b/src/wix/wixnative/smartcab.cpp
@@ -9,10 +9,10 @@ static void __stdcall CabNamesCallback(__in_z LPWSTR wzFirstCabName, __in_z LPWS
9HRESULT SmartCabCommand( 9HRESULT SmartCabCommand(
10 __in int argc, 10 __in int argc,
11 __in_ecount(argc) LPWSTR argv[] 11 __in_ecount(argc) LPWSTR argv[]
12) 12 )
13{ 13{
14 HRESULT hr = E_INVALIDARG; 14 HRESULT hr = E_INVALIDARG;
15 LPCWSTR wzCabPath = NULL; 15 LPWSTR sczCabPath = NULL;
16 LPCWSTR wzCabName = NULL; 16 LPCWSTR wzCabName = NULL;
17 LPWSTR sczCabDir = NULL; 17 LPWSTR sczCabDir = NULL;
18 UINT uiFileCount = 0; 18 UINT uiFileCount = 0;
@@ -27,11 +27,13 @@ HRESULT SmartCabCommand(
27 } 27 }
28 else 28 else
29 { 29 {
30 wzCabPath = argv[0]; 30 hr = PathExpand(&sczCabPath, argv[0], PATH_EXPAND_FULLPATH);
31 wzCabName = PathFile(wzCabPath); 31 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not expand path: %ls", argv[0]);
32 32
33 hr = PathGetDirectory(wzCabPath, &sczCabDir); 33 wzCabName = PathFile(sczCabPath);
34 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", wzCabPath); 34
35 hr = PathGetDirectory(sczCabPath, &sczCabDir);
36 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", sczCabPath);
35 37
36 if (argc > 1) 38 if (argc > 1)
37 { 39 {
@@ -62,7 +64,7 @@ HRESULT SmartCabCommand(
62 } 64 }
63 65
64 hr = CabCBegin(wzCabName, sczCabDir, uiFileCount, uiMaxSize, uiMaxThresh, ct, &hCab); 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);
66 68
67 if (uiFileCount > 0) 69 if (uiFileCount > 0)
68 { 70 {
@@ -70,12 +72,12 @@ HRESULT SmartCabCommand(
70 ExitOnFailure(hr, "failed to read stdin preamble before smartcabbing"); 72 ExitOnFailure(hr, "failed to read stdin preamble before smartcabbing");
71 73
72 hr = CompressFiles(hCab); 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);
74 } 76 }
75 77
76 hr = CabCFinish(hCab, CabNamesCallback); 78 hr = CabCFinish(hCab, CabNamesCallback);
77 hCab = NULL; // once finish is called, the handle is invalid. 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);
79 81
80 82
81LExit: 83LExit:
@@ -84,6 +86,7 @@ LExit:
84 CabCCancel(hCab); 86 CabCCancel(hCab);
85 } 87 }
86 ReleaseStr(sczCabDir); 88 ReleaseStr(sczCabDir);
89 ReleaseStr(sczCabPath);
87 90
88 return hr; 91 return hr;
89} 92}
@@ -91,7 +94,7 @@ LExit:
91 94
92static HRESULT CompressFiles( 95static HRESULT CompressFiles(
93 __in HANDLE hCab 96 __in HANDLE hCab
94) 97 )
95{ 98{
96 HRESULT hr = S_OK; 99 HRESULT hr = S_OK;
97 LPWSTR sczLine = NULL; 100 LPWSTR sczLine = NULL;
@@ -157,7 +160,7 @@ static void __stdcall CabNamesCallback(
157 __in_z LPWSTR wzFirstCabName, 160 __in_z LPWSTR wzFirstCabName,
158 __in_z LPWSTR wzNewCabName, 161 __in_z LPWSTR wzNewCabName,
159 __in_z LPWSTR wzFileToken 162 __in_z LPWSTR wzFileToken
160) 163 )
161{ 164{
162 ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken); 165 ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken);
163} 166}