From 8a4d03207633e9fdc364aaed82bd167f844679f9 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 3 Jun 2022 17:47:31 -0500 Subject: 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. --- src/burn/engine/core.cpp | 18 +-- src/burn/engine/logging.cpp | 5 +- src/libs/dutil/WixToolset.DUtil/cabcutil.cpp | 8 +- src/libs/dutil/WixToolset.DUtil/cabutil.cpp | 4 +- src/libs/dutil/WixToolset.DUtil/dirutil.cpp | 55 ++++++--- src/libs/dutil/WixToolset.DUtil/fileutil.cpp | 118 ------------------- src/libs/dutil/WixToolset.DUtil/inc/dirutil.h | 3 +- src/libs/dutil/WixToolset.DUtil/inc/fileutil.h | 7 -- src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | 10 ++ src/libs/dutil/WixToolset.DUtil/logutil.cpp | 15 ++- src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 104 ++++++++++++----- src/libs/dutil/WixToolset.DUtil/sceutil.cpp | 7 +- src/libs/dutil/test/DUtilUnitTest/DirUtilTests.cpp | 2 +- src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | 129 +++++++++++++++++++++ src/wix/WixToolset.Core.Native/WixNativeExe.cs | 1 + src/wix/wixnative/smartcab.cpp | 25 ++-- 16 files changed, 301 insertions(+), 210 deletions(-) (limited to 'src') 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( ++i; - hr = StrAllocString(&pInternalCommand->sczLogFile, argv[i], 0); + hr = PathExpand(&pInternalCommand->sczLogFile, argv[i], PATH_EXPAND_FULLPATH); ExitOnFailure(hr, "Failed to copy log file path."); } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"?", -1) || @@ -1516,7 +1516,7 @@ extern "C" HRESULT CoreParseCommandLine( } ++i; - hr = StrAllocString(&pInternalCommand->sczOriginalSource, argv[i], 0); + hr = PathExpand(&pInternalCommand->sczOriginalSource, argv[i], PATH_EXPAND_FULLPATH); ExitOnFailure(hr, "Failed to copy last used source."); } 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( ++i; - hr = StrAllocString(&pInternalCommand->sczLogFile, argv[i], 0); + hr = PathExpand(&pInternalCommand->sczLogFile, argv[i], PATH_EXPAND_FULLPATH); ExitOnFailure(hr, "Failed to copy append log file path."); pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_APPEND; @@ -1638,7 +1638,7 @@ extern "C" HRESULT CoreParseCommandLine( } else if (L'\0' != wzParam[1]) { - hr = StrAllocString(&pInternalCommand->sczSourceProcessPath, wzParam + 1, 0); + hr = PathExpand(&pInternalCommand->sczSourceProcessPath, wzParam + 1, PATH_EXPAND_FULLPATH); ExitOnFailure(hr, "Failed to copy source process path."); } } @@ -1807,16 +1807,10 @@ extern "C" HRESULT CoreParseCommandLine( fInvalidCommandLine = TRUE; TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]); } - else if (L'\0' == wzParam[1]) - { - // Need to grab the current directory here since this is passed on to other processes. - hr = DirGetCurrent(&pInternalCommand->sczEngineWorkingDirectory); - ExitOnFailure(hr, "Failed to get current directory for custom working directory."); - } else { - hr = StrAllocString(&pInternalCommand->sczEngineWorkingDirectory, wzParam + 1, 0); - ExitOnFailure(hr, "Failed to allocate the custom working directory."); + hr = PathExpand(&pInternalCommand->sczEngineWorkingDirectory, wzParam + 1, PATH_EXPAND_FULLPATH); + ExitOnFailure(hr, "Failed to store the custom working directory."); } } 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( { DWORD cRetry = 0; - hr = DirGetCurrent(&sczLoggingBaseFolder); - ExitOnFailure(hr, "Failed to get current directory."); - // Try pretty hard to open the log file when appending. do { @@ -95,7 +92,7 @@ extern "C" HRESULT LoggingOpen( ::Sleep(LOG_OPEN_RETRY_WAIT); } - hr = LogOpen(sczLoggingBaseFolder, pLog->sczPath, NULL, NULL, pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND, FALSE, &pLog->sczPath); + hr = LogOpen(NULL, pLog->sczPath, NULL, NULL, pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND, FALSE, &pLog->sczPath); if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND && HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == hr) { ++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( } else { - LPCWSTR pwzTemp = FileFromPath(fileInfo.wzSourcePath); + LPCWSTR pwzTemp = PathFile(fileInfo.wzSourcePath); hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP); CabcExitOnFailure(hr, "failed to convert file name to ANSI: %ls", pwzTemp); } @@ -538,7 +538,7 @@ extern "C" HRESULT DAPI CabCFinish( } else { - LPCWSTR pwzTemp = FileFromPath(fileInfo.wzSourcePath); + LPCWSTR pwzTemp = PathFile(fileInfo.wzSourcePath); hr = StrAnsiAllocString(&pszFileToken, pwzTemp, 0, CP_ACP); CabcExitOnFailure(hr, "failed to convert duplicate file name to ANSI: %ls", pwzTemp); } @@ -1386,7 +1386,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet( if (pccab->iCab == 1) { pcd->wzFirstCabinetName[0] = '\0'; - LPCWSTR pwzCabinetName = FileFromPath(pcd->wzCabinetPath); + LPCWSTR pwzCabinetName = PathFile(pcd->wzCabinetPath); size_t len = wcsnlen(pwzCabinetName, sizeof(pwzCabinetName)); if (len > 4) { @@ -1439,7 +1439,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet( else { LPCWSTR wzSourcePath = pcd->prgFiles[0].pwzSourcePath; - pwzFileToken = FileFromPath(wzSourcePath); + pwzFileToken = PathFile(wzSourcePath); } // 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( __in LPCWSTR wzPath, __in DWORD dwDesiredAccess, __in DWORD dwCreationDisposition -) + ) { HANDLE hFile = INVALID_HANDLE_VALUE; @@ -286,7 +286,7 @@ static HRESULT DAPI CabOperation( // // split the cabinet full path into directory and filename and convert to multi-byte (ick!) // - pwz = FileFromPath(sczCabinet); + pwz = PathFile(sczCabinet); CabExitOnNull(pwz, hr, E_INVALIDARG, "failed to process cabinet path: %ls", wzCabinet); 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 @@ #define DirExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__) #define DirExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__) #define DirExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__) +#define DirExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_DIRUTIL, x, e, s, __VA_ARGS__) #define DirExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DIRUTIL, x, s, __VA_ARGS__) #define DirExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DIRUTIL, p, x, e, s, __VA_ARGS__) #define DirExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DIRUTIL, p, x, s, __VA_ARGS__) @@ -388,32 +389,58 @@ LExit: *******************************************************************/ extern "C" HRESULT DAPI DirGetCurrent( - __deref_out_z LPWSTR* psczCurrentDirectory + __deref_out_z LPWSTR* psczCurrentDirectory, + __out_opt SIZE_T* pcch ) { + Assert(psczCurrentDirectory); + HRESULT hr = S_OK; - SIZE_T cch = 0; + SIZE_T cchMax = 0; + DWORD cch = 0; + DWORD cchBuffer = 0; + DWORD dwAttempts = 0; + const DWORD dwMaxAttempts = 10; - if (psczCurrentDirectory && *psczCurrentDirectory) + if (*psczCurrentDirectory) { - hr = StrMaxLength(*psczCurrentDirectory, &cch); - DirExitOnFailure(hr, "Failed to determine size of current directory."); - } + hr = StrMaxLength(*psczCurrentDirectory, &cchMax); + DirExitOnFailure(hr, "Failed to get max length of input buffer."); - DWORD cchRequired = ::GetCurrentDirectoryW((DWORD)min(DWORD_MAX, cch), 0 == cch ? NULL : *psczCurrentDirectory); - if (0 == cchRequired) + cchBuffer = (DWORD)min(DWORD_MAX, cchMax); + } + else { - DirExitWithLastError(hr, "Failed to get current directory."); + cchBuffer = MAX_PATH + 1; + + hr = StrAlloc(psczCurrentDirectory, cchBuffer); + DirExitOnFailure(hr, "Failed to allocate space for current directory."); } - else if (cch < cchRequired) + + for (; dwAttempts < dwMaxAttempts; ++dwAttempts) { - hr = StrAlloc(psczCurrentDirectory, cchRequired); - DirExitOnFailure(hr, "Failed to allocate string for current directory."); + cch = ::GetCurrentDirectoryW(cchBuffer, *psczCurrentDirectory); + DirExitOnNullWithLastError(cch, hr, "Failed to get current directory."); - if (!::GetCurrentDirectoryW(cchRequired, *psczCurrentDirectory)) + if (cch < cchBuffer) { - DirExitWithLastError(hr, "Failed to get current directory using allocated string."); + break; } + + hr = StrAlloc(psczCurrentDirectory, cch); + DirExitOnFailure(hr, "Failed to reallocate space for current directory."); + + cchBuffer = cch; + } + + if (dwMaxAttempts == dwAttempts) + { + DirExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "GetCurrentDirectoryW results never converged."); + } + + if (pcch) + { + *pcch = cch; } LExit: 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}; const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager"; const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations"; -/******************************************************************* - FileFromPath - returns a pointer to the file part of the path - -********************************************************************/ -extern "C" LPWSTR DAPI FileFromPath( - __in_z LPCWSTR wzPath - ) -{ - if (!wzPath) - return NULL; - - LPWSTR wzFile = const_cast(wzPath); - for (LPWSTR wz = wzFile; *wz; ++wz) - { - // valid delineators - // \ => Windows path - // / => unix and URL path - // : => relative path from mapped root - if (L'\\' == *wz || L'/' == *wz || L':' == *wz) - wzFile = wz + 1; - } - - return wzFile; -} - - -/******************************************************************* - FileResolvePath - gets the full path to a file resolving environment - variables along the way. - -********************************************************************/ -extern "C" HRESULT DAPI FileResolvePath( - __in_z LPCWSTR wzRelativePath, - __out LPWSTR *ppwzFullPath - ) -{ - Assert(wzRelativePath && *wzRelativePath); - - HRESULT hr = S_OK; - DWORD cch = 0; - LPWSTR pwzExpandedPath = NULL; - DWORD cchExpandedPath = 0; - - LPWSTR pwzFullPath = NULL; - DWORD cchFullPath = 0; - - LPWSTR wzFileName = NULL; - - // - // First, expand any environment variables. - // - cchExpandedPath = MAX_PATH; - hr = StrAlloc(&pwzExpandedPath, cchExpandedPath); - FileExitOnFailure(hr, "Failed to allocate space for expanded path."); - - cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath); - if (0 == cch) - { - FileExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath); - } - else if (cchExpandedPath < cch) - { - cchExpandedPath = cch; - hr = StrAlloc(&pwzExpandedPath, cchExpandedPath); - FileExitOnFailure(hr, "Failed to re-allocate more space for expanded path."); - - cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath); - if (0 == cch) - { - FileExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath); - } - else if (cchExpandedPath < cch) - { - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - FileExitOnRootFailure(hr, "Failed to allocate buffer for expanded path."); - } - } - - // - // Second, get the full path. - // - cchFullPath = MAX_PATH; - hr = StrAlloc(&pwzFullPath, cchFullPath); - FileExitOnFailure(hr, "Failed to allocate space for full path."); - - cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName); - if (0 == cch) - { - FileExitWithLastError(hr, "Failed to get full path for string: %ls", pwzExpandedPath); - } - else if (cchFullPath < cch) - { - cchFullPath = cch; - hr = StrAlloc(&pwzFullPath, cchFullPath); - FileExitOnFailure(hr, "Failed to re-allocate more space for full path."); - - cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName); - if (0 == cch) - { - FileExitWithLastError(hr, "Failed to get full path for string: %ls", pwzExpandedPath); - } - else if (cchFullPath < cch) - { - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - FileExitOnRootFailure(hr, "Failed to allocate buffer for full path."); - } - } - - *ppwzFullPath = pwzFullPath; - pwzFullPath = NULL; - -LExit: - ReleaseStr(pwzFullPath); - ReleaseStr(pwzExpandedPath); - - return hr; -} - /******************************************************************* FileStripExtension - 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( ); HRESULT DAPI DirGetCurrent( - __deref_out_z LPWSTR* psczCurrentDirectory + __deref_out_z LPWSTR* psczCurrentDirectory, + __out_opt SIZE_T* pcch ); HRESULT 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 } FILE_ENCODING; -LPWSTR DAPI FileFromPath( - __in_z LPCWSTR wzPath - ); -HRESULT DAPI FileResolvePath( - __in_z LPCWSTR wzRelativePath, - __out LPWSTR *ppwzFullPath - ); HRESULT DAPI FileStripExtension( __in_z LPCWSTR wzFileName, __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 @@ -67,6 +67,16 @@ DAPI_(HRESULT) PathExpand( __in DWORD dwResolveFlags ); +/******************************************************************* + PathGetFullPathName - wrapper around GetFullPathNameW. +*******************************************************************/ +DAPI_(HRESULT) PathGetFullPathName( + __in_z LPCWSTR wzPath, + __deref_out_z LPWSTR* psczFullPath, + __inout_z_opt LPCWSTR* pwzFileName, + __out_opt SIZE_T* pcch + ); + /******************************************************************* PathPrefix - prefixes a full path with \\?\ or \\?\UNC as appropriate. 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( { HRESULT hr = S_OK; BOOL fEnteredCriticalSection = FALSE; + LPWSTR sczCombined = NULL; LPWSTR sczLogDirectory = NULL; ::EnterCriticalSection(&LogUtil_csLog); @@ -129,9 +130,20 @@ extern "C" HRESULT DAPI LogOpen( } else { - hr = PathConcat(wzDirectory, wzLog, &LogUtil_sczLogPath); + hr = PathConcat(wzDirectory, wzLog, &sczCombined); LoguExitOnFailure(hr, "Failed to combine the log path."); + if (!PathIsFullyQualified(sczCombined, NULL)) + { + hr = PathExpand(&LogUtil_sczLogPath, sczCombined, PATH_EXPAND_FULLPATH); + LoguExitOnFailure(hr, "Failed to expand the log path."); + } + else + { + LogUtil_sczLogPath = sczCombined; + sczCombined = NULL; + } + hr = PathGetDirectory(LogUtil_sczLogPath, &sczLogDirectory); LoguExitOnFailure(hr, "Failed to get log directory."); @@ -176,6 +188,7 @@ LExit: ::LeaveCriticalSection(&LogUtil_csLog); } + ReleaseStr(sczCombined); ReleaseStr(sczLogDirectory); 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( __in DWORD dwResolveFlags ) { - Assert(wzRelativePath && *wzRelativePath); + Assert(wzRelativePath); HRESULT hr = S_OK; DWORD cch = 0; LPWSTR sczExpandedPath = NULL; + SIZE_T cchWritten = 0; DWORD cchExpandedPath = 0; SIZE_T cbSize = 0; @@ -221,37 +222,12 @@ DAPI_(HRESULT) PathExpand( // if (dwResolveFlags & PATH_EXPAND_FULLPATH) { - LPWSTR wzFileName = NULL; LPCWSTR wzPath = sczExpandedPath ? sczExpandedPath : wzRelativePath; - DWORD cchFullPath = max(PATH_GOOD_ENOUGH, cchExpandedPath); - hr = StrAlloc(&sczFullPath, cchFullPath); - PathExitOnFailure(hr, "Failed to allocate space for full path."); - - cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName); - if (0 == cch) - { - PathExitWithLastError(hr, "Failed to get full path for string: %ls", wzPath); - } - else if (cchFullPath < cch) - { - cchFullPath = cch < MAX_PATH ? cch : cch + 7; // ensure space for "\\?\UNC" prefix if needed - hr = StrAlloc(&sczFullPath, cchFullPath); - PathExitOnFailure(hr, "Failed to re-allocate more space for full path."); + hr = PathGetFullPathName(wzPath, &sczFullPath, NULL, &cchWritten); + PathExitOnFailure(hr, "Failed to get full path for string: %ls", wzPath); - cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName); - if (0 == cch) - { - PathExitWithLastError(hr, "Failed to get full path for string: %ls", wzPath); - } - else if (cchFullPath < cch) - { - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - PathExitOnRootFailure(hr, "Failed to allocate buffer for full path."); - } - } - - if (MAX_PATH < cch) + if (MAX_PATH < cchWritten) { hr = PathPrefix(&sczFullPath); PathExitOnFailure(hr, "Failed to prefix long path after expanding."); @@ -263,7 +239,7 @@ DAPI_(HRESULT) PathExpand( sczExpandedPath = NULL; } - hr = StrAllocString(psczFullPath, sczFullPath? sczFullPath : wzRelativePath, 0); + hr = StrAllocString(psczFullPath, sczFullPath ? sczFullPath : wzRelativePath, 0); PathExitOnFailure(hr, "Failed to copy relative path into full path."); LExit: @@ -274,6 +250,74 @@ LExit: } +DAPI_(HRESULT) PathGetFullPathName( + __in_z LPCWSTR wzPath, + __deref_out_z LPWSTR* psczFullPath, + __inout_z_opt LPCWSTR* pwzFileName, + __out_opt SIZE_T* pcch + ) +{ + HRESULT hr = S_OK; + SIZE_T cchMax = 0; + DWORD cchBuffer = 0; + DWORD cch = 0; + DWORD dwAttempts = 0; + const DWORD dwMaxAttempts = 10; + + if (!wzPath || !*wzPath) + { + hr = DirGetCurrent(psczFullPath, pcch); + PathExitOnFailure(hr, "Failed to get current directory."); + + ExitFunction(); + } + + if (*psczFullPath) + { + hr = StrMaxLength(*psczFullPath, &cchMax); + PathExitOnFailure(hr, "Failed to get max length of input buffer."); + + cchBuffer = (DWORD)min(DWORD_MAX, cchMax); + } + else + { + cchBuffer = MAX_PATH + 1; + + hr = StrAlloc(psczFullPath, cchBuffer); + PathExitOnFailure(hr, "Failed to allocate space for full path."); + } + + for (; dwAttempts < dwMaxAttempts; ++dwAttempts) + { + cch = ::GetFullPathNameW(wzPath, cchBuffer, *psczFullPath, const_cast(pwzFileName)); + PathExitOnNullWithLastError(cch, hr, "Failed to get full path for string: %ls", wzPath); + + if (cch < cchBuffer) + { + break; + } + + hr = StrAlloc(psczFullPath, cch); + PathExitOnFailure(hr, "Failed to reallocate space for full path."); + + cchBuffer = cch; + } + + if (dwMaxAttempts == dwAttempts) + { + PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "GetFullPathNameW results never converged."); + } + + if (pcch) + { + *pcch = cch; + } + +LExit: + return hr; +} + + DAPI_(HRESULT) PathPrefix( __inout LPWSTR *psczFullPath ) 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( // If that failed, fallback to loading from current path if (NULL == *phSqlCeDll) { - hr = DirGetCurrent(&sczDirectory); - ExitOnFailure(hr, "Failed to get current directory"); - - hr = PathConcat(sczDirectory, wzSqlCeDllPath, &sczDllFullPath); - ExitOnFailure(hr, "Failed to concatenate current directory and DLL filename"); + hr = PathGetFullPathName(wzSqlCeDllPath, &sczDllFullPath, NULL, NULL); + ExitOnFailure(hr, "Failed to get full path for DLL"); *phSqlCeDll = ::LoadLibraryW(sczDllFullPath); 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 hr = GuidCreate(&sczGuid); NativeAssert::Succeeded(hr, "Failed to create guid."); - hr = DirGetCurrent(&sczCurrentDir); + hr = DirGetCurrent(&sczCurrentDir, NULL); NativeAssert::Succeeded(hr, "Failed to get current directory."); 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 @@ #include "precomp.h" using namespace System; +using namespace System::IO; using namespace Xunit; using namespace WixBuildTools::TestSupport; @@ -402,6 +403,70 @@ namespace DutilTests Assert::Equal(S_OK, hr); } + [Fact] + void PathExpandEnvironmentVariablesTest() + { + HRESULT hr = S_OK; + LPWSTR sczExpanded = NULL; + LPCWSTR rgwzPaths[4] = + { + L"", L"", + L"\\\\?\\", L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", + }; + + try + { + for (DWORD i = 0; i < countof(rgwzPaths); i += 2) + { + hr = PathExpand(&sczExpanded, rgwzPaths[i + 1], PATH_EXPAND_ENVIRONMENT); + NativeAssert::Succeeded(hr, "PathExpand: {0}", rgwzPaths[i + 1]); + WixAssert::StringEqual((gcnew String(rgwzPaths[i])) + Environment::ExpandEnvironmentVariables(gcnew String(rgwzPaths[i + 1])), gcnew String(sczExpanded), false); + } + } + finally + { + ReleaseStr(sczExpanded); + } + } + + [Fact] + void PathExpandFullPathTest() + { + HRESULT hr = S_OK; + LPWSTR sczExpanded = NULL; + LPCWSTR wzGreaterThanMaxPathString = L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt"; + + try + { + hr = PathExpand(&sczExpanded, wzGreaterThanMaxPathString, PATH_EXPAND_FULLPATH); + NativeAssert::Succeeded(hr, "Failed to expand greater than MAX_PATH string."); + WixAssert::StringEqual((gcnew String("\\\\?\\")) + Path::Combine(Environment::CurrentDirectory, gcnew String(wzGreaterThanMaxPathString)), gcnew String(sczExpanded), false); + } + finally + { + ReleaseStr(sczExpanded); + } + } + + [Fact] + void PathExpandAllTest() + { + HRESULT hr = S_OK; + LPWSTR sczExpanded = NULL; + LPCWSTR wzRelativeEnvironmentVariableString = L"%USERNAME%\\abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt"; + + try + { + hr = PathExpand(&sczExpanded, wzRelativeEnvironmentVariableString, PATH_EXPAND_ENVIRONMENT | PATH_EXPAND_FULLPATH); + NativeAssert::Succeeded(hr, "Failed to expand path."); + WixAssert::StringEqual((gcnew String("\\\\?\\")) + Path::Combine(Environment::CurrentDirectory, Environment::ExpandEnvironmentVariables(gcnew String(wzRelativeEnvironmentVariableString))), gcnew String(sczExpanded), false); + } + finally + { + ReleaseStr(sczExpanded); + } + } + [Fact] void PathGetDirectoryTest() { @@ -435,6 +500,70 @@ namespace DutilTests } } + [Fact] + void PathGetFullPathNameTest() + { + HRESULT hr = S_OK; + LPWSTR sczPath = NULL; + LPCWSTR wzFileName = NULL; + LPCWSTR rgwzPaths[33] = + { + L"C:\\", L"C:\\", NULL, + L"C:\\file", L"C:\\file", L"file", + L"C:\\..\\file", L"C:\\file", L"file", + L"C:\\dir\\..\\file.txt", L"C:\\file.txt", L"file.txt", + L"C:\\dir\\\\file.txt.txt", L"C:\\dir\\file.txt.txt", L"file.txt.txt", + L"C:\\dir/.file", L"C:\\dir\\.file", L".file", + L"\\\\?\\C:\\file", L"\\\\?\\C:\\file", L"file", + L"\\\\server\\share\\file", L"\\\\server\\share\\file", L"file", + L"\\\\server\\share\\..\\file", L"\\\\server\\share\\file", L"file", + L"\\\\?\\UNC\\server\\share\\file", L"\\\\?\\UNC\\server\\share\\file", L"file", + L"C:\\abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt", L"C:\\abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt", L"a.txt", + }; + + try + { + for (DWORD i = 0; i < countof(rgwzPaths); i += 3) + { + hr = PathGetFullPathName(rgwzPaths[i], &sczPath, &wzFileName, NULL); + NativeAssert::Succeeded(hr, "PathGetFullPathName: {0}", rgwzPaths[i]); + NativeAssert::StringEqual(rgwzPaths[i + 1], sczPath); + NativeAssert::StringEqual(rgwzPaths[i + 2], wzFileName); + } + } + finally + { + ReleaseStr(sczPath); + } + } + + [Fact] + void PathGetFullPathNameRelativeTest() + { + HRESULT hr = S_OK; + LPWSTR sczPath = NULL; + LPCWSTR rgwzPaths[4] = + { + L"", + L"a.txt", + L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\\a.txt", + }; + + try + { + for (DWORD i = 0; i < countof(rgwzPaths); ++i) + { + hr = PathGetFullPathName(rgwzPaths[i], &sczPath, NULL, NULL); + NativeAssert::Succeeded(hr, "PathGetFullPathName: {0}", rgwzPaths[i]); + WixAssert::StringEqual(Path::Combine(Environment::CurrentDirectory, gcnew String(rgwzPaths[i])), gcnew String(sczPath), false); + } + } + finally + { + ReleaseStr(sczPath); + } + } + [Fact] void PathGetHierarchyArrayTest() { 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 var wixNativeInfo = new ProcessStartInfo(PathToWixNativeExe, this.commandLine) { + WorkingDirectory = Environment.CurrentDirectory, RedirectStandardInput = true, RedirectStandardOutput = true, 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 HRESULT SmartCabCommand( __in int argc, __in_ecount(argc) LPWSTR argv[] -) + ) { HRESULT hr = E_INVALIDARG; - LPCWSTR wzCabPath = NULL; + LPWSTR sczCabPath = NULL; LPCWSTR wzCabName = NULL; LPWSTR sczCabDir = NULL; UINT uiFileCount = 0; @@ -27,11 +27,13 @@ HRESULT SmartCabCommand( } else { - wzCabPath = argv[0]; - wzCabName = PathFile(wzCabPath); + hr = PathExpand(&sczCabPath, argv[0], PATH_EXPAND_FULLPATH); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not expand path: %ls", argv[0]); - hr = PathGetDirectory(wzCabPath, &sczCabDir); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", wzCabPath); + wzCabName = PathFile(sczCabPath); + + hr = PathGetDirectory(sczCabPath, &sczCabDir); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", sczCabPath); if (argc > 1) { @@ -62,7 +64,7 @@ HRESULT SmartCabCommand( } hr = CabCBegin(wzCabName, sczCabDir, uiFileCount, uiMaxSize, uiMaxThresh, ct, &hCab); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to initialize cabinet: %ls", wzCabPath); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to initialize cabinet: %ls", sczCabPath); if (uiFileCount > 0) { @@ -70,12 +72,12 @@ HRESULT SmartCabCommand( ExitOnFailure(hr, "failed to read stdin preamble before smartcabbing"); hr = CompressFiles(hCab); - ExitOnFailure(hr, "failed to compress files into cabinet: %ls", wzCabPath); + ExitOnFailure(hr, "failed to compress files into cabinet: %ls", sczCabPath); } hr = CabCFinish(hCab, CabNamesCallback); hCab = NULL; // once finish is called, the handle is invalid. - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to compress cabinet: %ls", wzCabPath); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to compress cabinet: %ls", sczCabPath); LExit: @@ -84,6 +86,7 @@ LExit: CabCCancel(hCab); } ReleaseStr(sczCabDir); + ReleaseStr(sczCabPath); return hr; } @@ -91,7 +94,7 @@ LExit: static HRESULT CompressFiles( __in HANDLE hCab -) + ) { HRESULT hr = S_OK; LPWSTR sczLine = NULL; @@ -157,7 +160,7 @@ static void __stdcall CabNamesCallback( __in_z LPWSTR wzFirstCabName, __in_z LPWSTR wzNewCabName, __in_z LPWSTR wzFileToken -) + ) { ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken); } -- cgit v1.2.3-55-g6feb