diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2022-06-03 17:47:54 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2022-06-07 19:44:36 -0500 |
| commit | b652e93a460b4b822a01382e5992f96f1d805ffe (patch) | |
| tree | 0c8ec0f0eba23d65fd404eb3f510944b244de65b | |
| parent | 8a4d03207633e9fdc364aaed82bd167f844679f9 (diff) | |
| download | wix-b652e93a460b4b822a01382e5992f96f1d805ffe.tar.gz wix-b652e93a460b4b822a01382e5992f96f1d805ffe.tar.bz2 wix-b652e93a460b4b822a01382e5992f96f1d805ffe.zip | |
Replace PathCompare with PathCompareCanonicalized.
| -rw-r--r-- | src/burn/engine/apply.cpp | 12 | ||||
| -rw-r--r-- | src/burn/engine/cache.cpp | 18 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/dutil.vcxproj | 1 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters | 3 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/file2utl.cpp | 164 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/fileutil.cpp | 156 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | 9 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/path2utl.cpp | 46 | ||||
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 26 | ||||
| -rw-r--r-- | src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | 69 |
10 files changed, 301 insertions, 203 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index f9b33333..4ebed191 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp | |||
| @@ -1350,7 +1350,7 @@ static HRESULT LayoutBundle( | |||
| 1350 | LPWSTR sczBundlePath = NULL; | 1350 | LPWSTR sczBundlePath = NULL; |
| 1351 | LPWSTR sczBundleDownloadUrl = NULL; | 1351 | LPWSTR sczBundleDownloadUrl = NULL; |
| 1352 | LPWSTR sczDestinationPath = NULL; | 1352 | LPWSTR sczDestinationPath = NULL; |
| 1353 | int nEquivalentPaths = 0; | 1353 | BOOL fPathEqual = FALSE; |
| 1354 | BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; | 1354 | BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; |
| 1355 | BURN_CACHE_PROGRESS_CONTEXT progress = { }; | 1355 | BURN_CACHE_PROGRESS_CONTEXT progress = { }; |
| 1356 | BOOL fRetry = FALSE; | 1356 | BOOL fRetry = FALSE; |
| @@ -1375,10 +1375,10 @@ static HRESULT LayoutBundle( | |||
| 1375 | ExitOnFailure(hr, "Failed to concat layout path for bundle."); | 1375 | ExitOnFailure(hr, "Failed to concat layout path for bundle."); |
| 1376 | 1376 | ||
| 1377 | // If the destination path is the currently running bundle, bail. | 1377 | // If the destination path is the currently running bundle, bail. |
| 1378 | hr = PathCompare(sczBundlePath, sczDestinationPath, &nEquivalentPaths); | 1378 | hr = PathCompareCanonicalized(sczBundlePath, sczDestinationPath, &fPathEqual); |
| 1379 | ExitOnFailure(hr, "Failed to determine if layout bundle path was equivalent with current process path."); | 1379 | ExitOnFailure(hr, "Failed to determine if layout bundle path was equivalent with current process path."); |
| 1380 | 1380 | ||
| 1381 | if (CSTR_EQUAL == nEquivalentPaths && FileExistsEx(sczDestinationPath, NULL)) | 1381 | if (fPathEqual && FileExistsEx(sczDestinationPath, NULL)) |
| 1382 | { | 1382 | { |
| 1383 | hr = UserExperienceOnCacheContainerOrPayloadVerifyBegin(pContext->pUX, NULL, NULL); | 1383 | hr = UserExperienceOnCacheContainerOrPayloadVerifyBegin(pContext->pUX, NULL, NULL); |
| 1384 | if (FAILED(hr)) | 1384 | if (FAILED(hr)) |
| @@ -1533,7 +1533,7 @@ static HRESULT AcquireContainerOrPayload( | |||
| 1533 | AssertSz(pContainer || pPayload, "Must provide a container or a payload."); | 1533 | AssertSz(pContainer || pPayload, "Must provide a container or a payload."); |
| 1534 | 1534 | ||
| 1535 | HRESULT hr = S_OK; | 1535 | HRESULT hr = S_OK; |
| 1536 | int nEquivalentPaths = 0; | 1536 | BOOL fPathEqual = FALSE; |
| 1537 | LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL; | 1537 | LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL; |
| 1538 | LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL; | 1538 | LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL; |
| 1539 | LPCWSTR wzPayloadContainerId = pPayload && pPayload->pContainer ? pPayload->pContainer->sczId : NULL; | 1539 | LPCWSTR wzPayloadContainerId = pPayload && pPayload->pContainer ? pPayload->pContainer->sczId : NULL; |
| @@ -1673,10 +1673,10 @@ static HRESULT AcquireContainerOrPayload( | |||
| 1673 | { | 1673 | { |
| 1674 | case BOOTSTRAPPER_CACHE_OPERATION_COPY: | 1674 | case BOOTSTRAPPER_CACHE_OPERATION_COPY: |
| 1675 | // If the source path and destination path are different, do the copy (otherwise there's no point). | 1675 | // If the source path and destination path are different, do the copy (otherwise there's no point). |
| 1676 | hr = PathCompare(pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath, &nEquivalentPaths); | 1676 | hr = PathCompareCanonicalized(pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath, &fPathEqual); |
| 1677 | ExitOnFailure(hr, "Failed to determine if payload paths were equivalent, source: %ls, destination: %ls.", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); | 1677 | ExitOnFailure(hr, "Failed to determine if payload paths were equivalent, source: %ls, destination: %ls.", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); |
| 1678 | 1678 | ||
| 1679 | if (CSTR_EQUAL != nEquivalentPaths) | 1679 | if (!fPathEqual) |
| 1680 | { | 1680 | { |
| 1681 | hr = CopyPayload(pProgress, INVALID_HANDLE_VALUE, pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); | 1681 | hr = CopyPayload(pProgress, INVALID_HANDLE_VALUE, pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); |
| 1682 | ExitOnFailure(hr, "Failed to copy payload: %ls", wzPayloadId); | 1682 | ExitOnFailure(hr, "Failed to copy payload: %ls", wzPayloadId); |
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index 04b2f0ca..b311a195 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp | |||
| @@ -170,7 +170,7 @@ extern "C" HRESULT CacheInitialize( | |||
| 170 | 170 | ||
| 171 | HRESULT hr = S_OK; | 171 | HRESULT hr = S_OK; |
| 172 | LPWSTR sczAppData = NULL; | 172 | LPWSTR sczAppData = NULL; |
| 173 | int nCompare = 0; | 173 | BOOL fPathEqual = FALSE; |
| 174 | 174 | ||
| 175 | // Cache paths are initialized once so they cannot be changed while the engine is caching payloads. | 175 | // Cache paths are initialized once so they cannot be changed while the engine is caching payloads. |
| 176 | // Always construct the default machine package cache path so we can determine if we're redirected. | 176 | // Always construct the default machine package cache path so we can determine if we're redirected. |
| @@ -199,10 +199,10 @@ extern "C" HRESULT CacheInitialize( | |||
| 199 | ExitOnFailure(hr, "Failed to copy default package cache directory to current package cache directory."); | 199 | ExitOnFailure(hr, "Failed to copy default package cache directory to current package cache directory."); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | hr = PathCompare(pCache->sczDefaultMachinePackageCache, pCache->sczCurrentMachinePackageCache, &nCompare); | 202 | hr = PathCompareCanonicalized(pCache->sczDefaultMachinePackageCache, pCache->sczCurrentMachinePackageCache, &fPathEqual); |
| 203 | ExitOnFailure(hr, "Failed to compare default and current package cache directories."); | 203 | ExitOnFailure(hr, "Failed to compare default and current package cache directories."); |
| 204 | 204 | ||
| 205 | pCache->fCustomMachinePackageCache = CSTR_EQUAL != nCompare; | 205 | pCache->fCustomMachinePackageCache = !fPathEqual; |
| 206 | 206 | ||
| 207 | 207 | ||
| 208 | hr = PathGetKnownFolder(CSIDL_LOCAL_APPDATA, &sczAppData); | 208 | hr = PathGetKnownFolder(CSIDL_LOCAL_APPDATA, &sczAppData); |
| @@ -241,7 +241,7 @@ extern "C" HRESULT CacheInitializeSources( | |||
| 241 | LPWSTR sczCompletedPath = NULL; | 241 | LPWSTR sczCompletedPath = NULL; |
| 242 | LPWSTR sczOriginalSource = NULL; | 242 | LPWSTR sczOriginalSource = NULL; |
| 243 | LPWSTR sczOriginalSourceFolder = NULL; | 243 | LPWSTR sczOriginalSourceFolder = NULL; |
| 244 | int nCompare = 0; | 244 | BOOL fPathEqual = FALSE; |
| 245 | LPCWSTR wzSourceProcessPath = pInternalCommand->sczSourceProcessPath; | 245 | LPCWSTR wzSourceProcessPath = pInternalCommand->sczSourceProcessPath; |
| 246 | 246 | ||
| 247 | hr = PathForCurrentProcess(&sczCurrentPath, NULL); | 247 | hr = PathForCurrentProcess(&sczCurrentPath, NULL); |
| @@ -254,10 +254,10 @@ extern "C" HRESULT CacheInitializeSources( | |||
| 254 | hr = PathConcatRelativeToBase(sczCompletedFolder, pRegistration->sczExecutableName, &sczCompletedPath); | 254 | hr = PathConcatRelativeToBase(sczCompletedFolder, pRegistration->sczExecutableName, &sczCompletedPath); |
| 255 | ExitOnFailure(hr, "Failed to combine working path with engine file name."); | 255 | ExitOnFailure(hr, "Failed to combine working path with engine file name."); |
| 256 | 256 | ||
| 257 | hr = PathCompare(sczCurrentPath, sczCompletedPath, &nCompare); | 257 | hr = PathCompareCanonicalized(sczCurrentPath, sczCompletedPath, &fPathEqual); |
| 258 | ExitOnFailure(hr, "Failed to compare current path for bundle: %ls", sczCurrentPath); | 258 | ExitOnFailure(hr, "Failed to compare current path for bundle: %ls", sczCurrentPath); |
| 259 | 259 | ||
| 260 | pCache->fRunningFromCache = (CSTR_EQUAL == nCompare); | 260 | pCache->fRunningFromCache = fPathEqual; |
| 261 | 261 | ||
| 262 | // If a source process path was not provided (e.g. we are not being | 262 | // If a source process path was not provided (e.g. we are not being |
| 263 | // run in a clean room) then use the current process path as the | 263 | // run in a clean room) then use the current process path as the |
| @@ -959,7 +959,7 @@ extern "C" HRESULT CacheCompleteBundle( | |||
| 959 | ) | 959 | ) |
| 960 | { | 960 | { |
| 961 | HRESULT hr = S_OK; | 961 | HRESULT hr = S_OK; |
| 962 | int nCompare = 0; | 962 | BOOL fPathEqual = FALSE; |
| 963 | LPWSTR sczTargetDirectory = NULL; | 963 | LPWSTR sczTargetDirectory = NULL; |
| 964 | LPWSTR sczTargetPath = NULL; | 964 | LPWSTR sczTargetPath = NULL; |
| 965 | LPWSTR sczSourceDirectory = NULL; | 965 | LPWSTR sczSourceDirectory = NULL; |
| @@ -976,10 +976,10 @@ extern "C" HRESULT CacheCompleteBundle( | |||
| 976 | 976 | ||
| 977 | // If the bundle is running out of the package cache then we don't need to copy it there | 977 | // If the bundle is running out of the package cache then we don't need to copy it there |
| 978 | // (and don't want to since it'll be in use) so bail. | 978 | // (and don't want to since it'll be in use) so bail. |
| 979 | hr = PathCompare(wzSourceBundlePath, sczTargetPath, &nCompare); | 979 | hr = PathCompareCanonicalized(wzSourceBundlePath, sczTargetPath, &fPathEqual); |
| 980 | ExitOnFailure(hr, "Failed to compare completed cache path for bundle: %ls", wzSourceBundlePath); | 980 | ExitOnFailure(hr, "Failed to compare completed cache path for bundle: %ls", wzSourceBundlePath); |
| 981 | 981 | ||
| 982 | if (CSTR_EQUAL == nCompare) | 982 | if (fPathEqual) |
| 983 | { | 983 | { |
| 984 | ExitFunction(); | 984 | ExitFunction(); |
| 985 | } | 985 | } |
diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj index ba9e801e..8a6f3b13 100644 --- a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj +++ b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings> | 66 | <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings> |
| 67 | </ClCompile> | 67 | </ClCompile> |
| 68 | <ClCompile Include="eseutil.cpp" /> | 68 | <ClCompile Include="eseutil.cpp" /> |
| 69 | <ClCompile Include="file2utl.cpp" /> | ||
| 69 | <ClCompile Include="fileutil.cpp" /> | 70 | <ClCompile Include="fileutil.cpp" /> |
| 70 | <ClCompile Include="gdiputil.cpp" /> | 71 | <ClCompile Include="gdiputil.cpp" /> |
| 71 | <ClCompile Include="guidutil.cpp" /> | 72 | <ClCompile Include="guidutil.cpp" /> |
diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters index 6444b19c..dbbe68f4 100644 --- a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters +++ b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters | |||
| @@ -69,6 +69,9 @@ | |||
| 69 | <ClCompile Include="eseutil.cpp"> | 69 | <ClCompile Include="eseutil.cpp"> |
| 70 | <Filter>Source Files</Filter> | 70 | <Filter>Source Files</Filter> |
| 71 | </ClCompile> | 71 | </ClCompile> |
| 72 | <ClCompile Include="file2utl.cpp"> | ||
| 73 | <Filter>Source Files</Filter> | ||
| 74 | </ClCompile> | ||
| 72 | <ClCompile Include="fileutil.cpp"> | 75 | <ClCompile Include="fileutil.cpp"> |
| 73 | <Filter>Source Files</Filter> | 76 | <Filter>Source Files</Filter> |
| 74 | </ClCompile> | 77 | </ClCompile> |
diff --git a/src/libs/dutil/WixToolset.DUtil/file2utl.cpp b/src/libs/dutil/WixToolset.DUtil/file2utl.cpp new file mode 100644 index 00000000..88f8377c --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/file2utl.cpp | |||
| @@ -0,0 +1,164 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // Exit macros | ||
| 7 | #define FileExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__) | ||
| 8 | #define FileExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__) | ||
| 9 | #define FileExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__) | ||
| 10 | #define FileExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__) | ||
| 11 | #define FileExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__) | ||
| 12 | #define FileExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__) | ||
| 13 | #define FileExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_FILEUTIL, p, x, e, s, __VA_ARGS__) | ||
| 14 | #define FileExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_FILEUTIL, p, x, s, __VA_ARGS__) | ||
| 15 | #define FileExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_FILEUTIL, p, x, e, s, __VA_ARGS__) | ||
| 16 | #define FileExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_FILEUTIL, p, x, s, __VA_ARGS__) | ||
| 17 | #define FileExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_FILEUTIL, e, x, s, __VA_ARGS__) | ||
| 18 | #define FileExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_FILEUTIL, g, x, s, __VA_ARGS__) | ||
| 19 | |||
| 20 | // constants | ||
| 21 | |||
| 22 | const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager"; | ||
| 23 | const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations"; | ||
| 24 | |||
| 25 | |||
| 26 | /******************************************************************* | ||
| 27 | FileExistsAfterRestart - checks that a file exists and will continue | ||
| 28 | to exist after restart. | ||
| 29 | |||
| 30 | ********************************************************************/ | ||
| 31 | extern "C" BOOL DAPI FileExistsAfterRestart( | ||
| 32 | __in_z LPCWSTR wzPath, | ||
| 33 | __out_opt DWORD *pdwAttributes | ||
| 34 | ) | ||
| 35 | { | ||
| 36 | HRESULT hr = S_OK; | ||
| 37 | BOOL fExists = FALSE; | ||
| 38 | HKEY hkPendingFileRename = NULL; | ||
| 39 | LPWSTR* rgsczRenames = NULL; | ||
| 40 | DWORD cRenames = 0; | ||
| 41 | BOOL fPathEqual = FALSE; | ||
| 42 | |||
| 43 | fExists = FileExistsEx(wzPath, pdwAttributes); | ||
| 44 | if (fExists) | ||
| 45 | { | ||
| 46 | hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE, &hkPendingFileRename); | ||
| 47 | if (E_FILENOTFOUND == hr) | ||
| 48 | { | ||
| 49 | ExitFunction1(hr = S_OK); | ||
| 50 | } | ||
| 51 | FileExitOnFailure(hr, "Failed to open pending file rename registry key."); | ||
| 52 | |||
| 53 | hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames); | ||
| 54 | if (E_FILENOTFOUND == hr) | ||
| 55 | { | ||
| 56 | ExitFunction1(hr = S_OK); | ||
| 57 | } | ||
| 58 | FileExitOnFailure(hr, "Failed to read pending file renames."); | ||
| 59 | |||
| 60 | // The pending file renames array is pairs of source and target paths. We only care | ||
| 61 | // about checking the source paths so skip the target paths (i += 2). | ||
| 62 | for (DWORD i = 0; i < cRenames; i += 2) | ||
| 63 | { | ||
| 64 | LPWSTR wzRename = rgsczRenames[i]; | ||
| 65 | if (wzRename && *wzRename) | ||
| 66 | { | ||
| 67 | hr = PathCompareCanonicalized(wzPath, wzRename, &fPathEqual); | ||
| 68 | FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path."); | ||
| 69 | |||
| 70 | if (fPathEqual) | ||
| 71 | { | ||
| 72 | fExists = FALSE; | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | LExit: | ||
| 80 | ReleaseStrArray(rgsczRenames, cRenames); | ||
| 81 | ReleaseRegKey(hkPendingFileRename); | ||
| 82 | |||
| 83 | return fExists; | ||
| 84 | } | ||
| 85 | |||
| 86 | |||
| 87 | /******************************************************************* | ||
| 88 | FileRemoveFromPendingRename - removes the file path from the pending | ||
| 89 | file rename list. | ||
| 90 | |||
| 91 | ********************************************************************/ | ||
| 92 | extern "C" HRESULT DAPI FileRemoveFromPendingRename( | ||
| 93 | __in_z LPCWSTR wzPath | ||
| 94 | ) | ||
| 95 | { | ||
| 96 | HRESULT hr = S_OK; | ||
| 97 | HKEY hkPendingFileRename = NULL; | ||
| 98 | LPWSTR* rgsczRenames = NULL; | ||
| 99 | DWORD cRenames = 0; | ||
| 100 | BOOL fPathEqual = FALSE; | ||
| 101 | BOOL fRemoved = FALSE; | ||
| 102 | DWORD cNewRenames = 0; | ||
| 103 | |||
| 104 | hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkPendingFileRename); | ||
| 105 | if (E_FILENOTFOUND == hr) | ||
| 106 | { | ||
| 107 | ExitFunction1(hr = S_OK); | ||
| 108 | } | ||
| 109 | FileExitOnFailure(hr, "Failed to open pending file rename registry key."); | ||
| 110 | |||
| 111 | hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames); | ||
| 112 | if (E_FILENOTFOUND == hr) | ||
| 113 | { | ||
| 114 | ExitFunction1(hr = S_OK); | ||
| 115 | } | ||
| 116 | FileExitOnFailure(hr, "Failed to read pending file renames."); | ||
| 117 | |||
| 118 | // The pending file renames array is pairs of source and target paths. We only care | ||
| 119 | // about checking the source paths so skip the target paths (i += 2). | ||
| 120 | for (DWORD i = 0; i < cRenames; i += 2) | ||
| 121 | { | ||
| 122 | LPWSTR wzRename = rgsczRenames[i]; | ||
| 123 | if (wzRename && *wzRename) | ||
| 124 | { | ||
| 125 | hr = PathCompareCanonicalized(wzPath, wzRename, &fPathEqual); | ||
| 126 | FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path."); | ||
| 127 | |||
| 128 | // If we find our path in the list, null out the source and target slot and | ||
| 129 | // we'll compact the array next. | ||
| 130 | if (fPathEqual) | ||
| 131 | { | ||
| 132 | ReleaseNullStr(rgsczRenames[i]); | ||
| 133 | ReleaseNullStr(rgsczRenames[i + 1]); | ||
| 134 | fRemoved = TRUE; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | if (fRemoved) | ||
| 140 | { | ||
| 141 | // Compact the array by removing any nulls. | ||
| 142 | for (DWORD i = 0; i < cRenames; ++i) | ||
| 143 | { | ||
| 144 | LPWSTR wzRename = rgsczRenames[i]; | ||
| 145 | if (wzRename) | ||
| 146 | { | ||
| 147 | rgsczRenames[cNewRenames] = wzRename; | ||
| 148 | ++cNewRenames; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | cRenames = cNewRenames; // ignore the pointers on the end of the array since an early index points to them already. | ||
| 153 | |||
| 154 | // Write the new array back to the pending file rename key. | ||
| 155 | hr = RegWriteStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, rgsczRenames, cRenames); | ||
| 156 | FileExitOnFailure(hr, "Failed to update pending file renames."); | ||
| 157 | } | ||
| 158 | |||
| 159 | LExit: | ||
| 160 | ReleaseStrArray(rgsczRenames, cRenames); | ||
| 161 | ReleaseRegKey(hkPendingFileRename); | ||
| 162 | |||
| 163 | return hr; | ||
| 164 | } | ||
diff --git a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp index 2fe04de1..9f68ee52 100644 --- a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp | |||
| @@ -22,9 +22,6 @@ | |||
| 22 | const BYTE UTF8BOM[] = {0xEF, 0xBB, 0xBF}; | 22 | const BYTE UTF8BOM[] = {0xEF, 0xBB, 0xBF}; |
| 23 | const BYTE UTF16BOM[] = {0xFF, 0xFE}; | 23 | const BYTE UTF16BOM[] = {0xFF, 0xFE}; |
| 24 | 24 | ||
| 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 | 25 | ||
| 29 | /******************************************************************* | 26 | /******************************************************************* |
| 30 | FileStripExtension - Strip extension from filename | 27 | FileStripExtension - Strip extension from filename |
| @@ -527,159 +524,6 @@ extern "C" BOOL DAPI FileExistsEx( | |||
| 527 | 524 | ||
| 528 | 525 | ||
| 529 | /******************************************************************* | 526 | /******************************************************************* |
| 530 | FileExistsAfterRestart - checks that a file exists and will continue | ||
| 531 | to exist after restart. | ||
| 532 | |||
| 533 | ********************************************************************/ | ||
| 534 | extern "C" BOOL DAPI FileExistsAfterRestart( | ||
| 535 | __in_z LPCWSTR wzPath, | ||
| 536 | __out_opt DWORD *pdwAttributes | ||
| 537 | ) | ||
| 538 | { | ||
| 539 | HRESULT hr = S_OK; | ||
| 540 | BOOL fExists = FALSE; | ||
| 541 | HKEY hkPendingFileRename = NULL; | ||
| 542 | LPWSTR* rgsczRenames = NULL; | ||
| 543 | DWORD cRenames = 0; | ||
| 544 | int nCompare = 0; | ||
| 545 | |||
| 546 | fExists = FileExistsEx(wzPath, pdwAttributes); | ||
| 547 | if (fExists) | ||
| 548 | { | ||
| 549 | hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE, &hkPendingFileRename); | ||
| 550 | if (E_FILENOTFOUND == hr) | ||
| 551 | { | ||
| 552 | ExitFunction1(hr = S_OK); | ||
| 553 | } | ||
| 554 | FileExitOnFailure(hr, "Failed to open pending file rename registry key."); | ||
| 555 | |||
| 556 | hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames); | ||
| 557 | if (E_FILENOTFOUND == hr) | ||
| 558 | { | ||
| 559 | ExitFunction1(hr = S_OK); | ||
| 560 | } | ||
| 561 | FileExitOnFailure(hr, "Failed to read pending file renames."); | ||
| 562 | |||
| 563 | // The pending file renames array is pairs of source and target paths. We only care | ||
| 564 | // about checking the source paths so skip the target paths (i += 2). | ||
| 565 | for (DWORD i = 0; i < cRenames; i += 2) | ||
| 566 | { | ||
| 567 | LPWSTR wzRename = rgsczRenames[i]; | ||
| 568 | if (wzRename && *wzRename) | ||
| 569 | { | ||
| 570 | // Skip the long path designator if present. | ||
| 571 | if (L'\\' == wzRename[0] && L'?' == wzRename[1] && L'?' == wzRename[2] && L'\\' == wzRename[3]) | ||
| 572 | { | ||
| 573 | wzRename += 4; | ||
| 574 | } | ||
| 575 | |||
| 576 | hr = PathCompare(wzPath, wzRename, &nCompare); | ||
| 577 | FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path."); | ||
| 578 | |||
| 579 | if (CSTR_EQUAL == nCompare) | ||
| 580 | { | ||
| 581 | fExists = FALSE; | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | } | ||
| 586 | } | ||
| 587 | |||
| 588 | LExit: | ||
| 589 | ReleaseStrArray(rgsczRenames, cRenames); | ||
| 590 | ReleaseRegKey(hkPendingFileRename); | ||
| 591 | |||
| 592 | return fExists; | ||
| 593 | } | ||
| 594 | |||
| 595 | |||
| 596 | /******************************************************************* | ||
| 597 | FileRemoveFromPendingRename - removes the file path from the pending | ||
| 598 | file rename list. | ||
| 599 | |||
| 600 | ********************************************************************/ | ||
| 601 | extern "C" HRESULT DAPI FileRemoveFromPendingRename( | ||
| 602 | __in_z LPCWSTR wzPath | ||
| 603 | ) | ||
| 604 | { | ||
| 605 | HRESULT hr = S_OK; | ||
| 606 | HKEY hkPendingFileRename = NULL; | ||
| 607 | LPWSTR* rgsczRenames = NULL; | ||
| 608 | DWORD cRenames = 0; | ||
| 609 | int nCompare = 0; | ||
| 610 | BOOL fRemoved = FALSE; | ||
| 611 | DWORD cNewRenames = 0; | ||
| 612 | |||
| 613 | hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkPendingFileRename); | ||
| 614 | if (E_FILENOTFOUND == hr) | ||
| 615 | { | ||
| 616 | ExitFunction1(hr = S_OK); | ||
| 617 | } | ||
| 618 | FileExitOnFailure(hr, "Failed to open pending file rename registry key."); | ||
| 619 | |||
| 620 | hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames); | ||
| 621 | if (E_FILENOTFOUND == hr) | ||
| 622 | { | ||
| 623 | ExitFunction1(hr = S_OK); | ||
| 624 | } | ||
| 625 | FileExitOnFailure(hr, "Failed to read pending file renames."); | ||
| 626 | |||
| 627 | // The pending file renames array is pairs of source and target paths. We only care | ||
| 628 | // about checking the source paths so skip the target paths (i += 2). | ||
| 629 | for (DWORD i = 0; i < cRenames; i += 2) | ||
| 630 | { | ||
| 631 | LPWSTR wzRename = rgsczRenames[i]; | ||
| 632 | if (wzRename && *wzRename) | ||
| 633 | { | ||
| 634 | // Skip the long path designator if present. | ||
| 635 | if (L'\\' == wzRename[0] && L'?' == wzRename[1] && L'?' == wzRename[2] && L'\\' == wzRename[3]) | ||
| 636 | { | ||
| 637 | wzRename += 4; | ||
| 638 | } | ||
| 639 | |||
| 640 | hr = PathCompare(wzPath, wzRename, &nCompare); | ||
| 641 | FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path."); | ||
| 642 | |||
| 643 | // If we find our path in the list, null out the source and target slot and | ||
| 644 | // we'll compact the array next. | ||
| 645 | if (CSTR_EQUAL == nCompare) | ||
| 646 | { | ||
| 647 | ReleaseNullStr(rgsczRenames[i]); | ||
| 648 | ReleaseNullStr(rgsczRenames[i + 1]); | ||
| 649 | fRemoved = TRUE; | ||
| 650 | } | ||
| 651 | } | ||
| 652 | } | ||
| 653 | |||
| 654 | if (fRemoved) | ||
| 655 | { | ||
| 656 | // Compact the array by removing any nulls. | ||
| 657 | for (DWORD i = 0; i < cRenames; ++i) | ||
| 658 | { | ||
| 659 | LPWSTR wzRename = rgsczRenames[i]; | ||
| 660 | if (wzRename) | ||
| 661 | { | ||
| 662 | rgsczRenames[cNewRenames] = wzRename; | ||
| 663 | ++cNewRenames; | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | cRenames = cNewRenames; // ignore the pointers on the end of the array since an early index points to them already. | ||
| 668 | |||
| 669 | // Write the new array back to the pending file rename key. | ||
| 670 | hr = RegWriteStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, rgsczRenames, cRenames); | ||
| 671 | FileExitOnFailure(hr, "Failed to update pending file renames."); | ||
| 672 | } | ||
| 673 | |||
| 674 | LExit: | ||
| 675 | ReleaseStrArray(rgsczRenames, cRenames); | ||
| 676 | ReleaseRegKey(hkPendingFileRename); | ||
| 677 | |||
| 678 | return hr; | ||
| 679 | } | ||
| 680 | |||
| 681 | |||
| 682 | /******************************************************************* | ||
| 683 | FileRead - read a file into memory | 527 | FileRead - read a file into memory |
| 684 | 528 | ||
| 685 | ********************************************************************/ | 529 | ********************************************************************/ |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h index 871e706b..e64c8ef3 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | |||
| @@ -258,13 +258,14 @@ DAPI_(HRESULT) PathConcatRelativeToBase( | |||
| 258 | ); | 258 | ); |
| 259 | 259 | ||
| 260 | /******************************************************************* | 260 | /******************************************************************* |
| 261 | PathCompare - compares the fully expanded path of the two paths using | 261 | PathCompareCanonicalized - canonicalizes the two paths using PathCanonicalizeForComparison |
| 262 | ::CompareStringW(). | 262 | which does not resolve relative paths into fully qualified paths. |
| 263 | The strings are then compared using ::CompareStringW(). | ||
| 263 | *******************************************************************/ | 264 | *******************************************************************/ |
| 264 | DAPI_(HRESULT) PathCompare( | 265 | DAPI_(HRESULT) PathCompareCanonicalized( |
| 265 | __in_z LPCWSTR wzPath1, | 266 | __in_z LPCWSTR wzPath1, |
| 266 | __in_z LPCWSTR wzPath2, | 267 | __in_z LPCWSTR wzPath2, |
| 267 | __out int* pnResult | 268 | __out BOOL* pfEqual |
| 268 | ); | 269 | ); |
| 269 | 270 | ||
| 270 | /******************************************************************* | 271 | /******************************************************************* |
diff --git a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp index 61c1803a..1957a8c5 100644 --- a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp +++ b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp | |||
| @@ -118,11 +118,19 @@ DAPI_(HRESULT) PathCanonicalizeForComparison( | |||
| 118 | PathExitOnFailure(hr, "Failed to backslash terminate the canonicalized path"); | 118 | PathExitOnFailure(hr, "Failed to backslash terminate the canonicalized path"); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | if ((PATH_CANONICALIZE_APPEND_LONG_PATH_PREFIX & dwCanonicalizeFlags) && | 121 | if (PathIsFullyQualified(*psczCanonicalized, &fHasPrefix) && !fHasPrefix && |
| 122 | PathIsFullyQualified(*psczCanonicalized, &fHasPrefix) && !fHasPrefix) | 122 | (PATH_CANONICALIZE_APPEND_LONG_PATH_PREFIX & dwCanonicalizeFlags)) |
| 123 | { | 123 | { |
| 124 | hr = PathPrefix(psczCanonicalized); | 124 | hr = PathPrefix(psczCanonicalized); |
| 125 | PathExitOnFailure(hr, "Failed to ensure the long path prefix on the canonicalized path"); | 125 | PathExitOnFailure(hr, "Failed to ensure the long path prefix on the canonicalized path"); |
| 126 | |||
| 127 | fHasPrefix = TRUE; | ||
| 128 | } | ||
| 129 | |||
| 130 | if (fHasPrefix) | ||
| 131 | { | ||
| 132 | // Canonicalize \??\ into \\?\. | ||
| 133 | (*psczCanonicalized)[1] = L'\\'; | ||
| 126 | } | 134 | } |
| 127 | 135 | ||
| 128 | LExit: | 136 | LExit: |
| @@ -171,6 +179,40 @@ LExit: | |||
| 171 | return hr; | 179 | return hr; |
| 172 | } | 180 | } |
| 173 | 181 | ||
| 182 | DAPI_(HRESULT) PathCompareCanonicalized( | ||
| 183 | __in_z LPCWSTR wzPath1, | ||
| 184 | __in_z LPCWSTR wzPath2, | ||
| 185 | __out BOOL* pfEqual | ||
| 186 | ) | ||
| 187 | { | ||
| 188 | HRESULT hr = S_OK; | ||
| 189 | LPWSTR sczCanonicalized1 = NULL; | ||
| 190 | LPWSTR sczCanonicalized2 = NULL; | ||
| 191 | DWORD dwDefaultFlags = PATH_CANONICALIZE_APPEND_LONG_PATH_PREFIX | PATH_CANONICALIZE_KEEP_UNC_ROOT; | ||
| 192 | int nResult = 0; | ||
| 193 | |||
| 194 | if (!wzPath1 || !wzPath2) | ||
| 195 | { | ||
| 196 | PathExitWithRootFailure(hr, E_INVALIDARG, "Both paths are required."); | ||
| 197 | } | ||
| 198 | |||
| 199 | hr = PathCanonicalizeForComparison(wzPath1, dwDefaultFlags, &sczCanonicalized1); | ||
| 200 | PathExitOnFailure(hr, "Failed to canonicalize wzPath1."); | ||
| 201 | |||
| 202 | hr = PathCanonicalizeForComparison(wzPath2, dwDefaultFlags, &sczCanonicalized2); | ||
| 203 | PathExitOnFailure(hr, "Failed to canonicalize wzPath2."); | ||
| 204 | |||
| 205 | nResult = ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczCanonicalized1, -1, sczCanonicalized2, -1); | ||
| 206 | PathExitOnNullWithLastError(nResult, hr, "Failed to compare canonicalized paths."); | ||
| 207 | |||
| 208 | *pfEqual = CSTR_EQUAL == nResult; | ||
| 209 | |||
| 210 | LExit: | ||
| 211 | ReleaseStr(sczCanonicalized1); | ||
| 212 | ReleaseStr(sczCanonicalized2); | ||
| 213 | return hr; | ||
| 214 | } | ||
| 215 | |||
| 174 | DAPI_(HRESULT) PathDirectoryContainsPath( | 216 | DAPI_(HRESULT) PathDirectoryContainsPath( |
| 175 | __in_z LPCWSTR wzDirectory, | 217 | __in_z LPCWSTR wzDirectory, |
| 176 | __in_z LPCWSTR wzPath | 218 | __in_z LPCWSTR wzPath |
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp index a9a19b9f..abbf4d4b 100644 --- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp | |||
| @@ -1080,32 +1080,6 @@ LExit: | |||
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | 1082 | ||
| 1083 | DAPI_(HRESULT) PathCompare( | ||
| 1084 | __in_z LPCWSTR wzPath1, | ||
| 1085 | __in_z LPCWSTR wzPath2, | ||
| 1086 | __out int* pnResult | ||
| 1087 | ) | ||
| 1088 | { | ||
| 1089 | HRESULT hr = S_OK; | ||
| 1090 | LPWSTR sczPath1 = NULL; | ||
| 1091 | LPWSTR sczPath2 = NULL; | ||
| 1092 | |||
| 1093 | hr = PathExpand(&sczPath1, wzPath1, PATH_EXPAND_ENVIRONMENT | PATH_EXPAND_FULLPATH); | ||
| 1094 | PathExitOnFailure(hr, "Failed to expand path1."); | ||
| 1095 | |||
| 1096 | hr = PathExpand(&sczPath2, wzPath2, PATH_EXPAND_ENVIRONMENT | PATH_EXPAND_FULLPATH); | ||
| 1097 | PathExitOnFailure(hr, "Failed to expand path2."); | ||
| 1098 | |||
| 1099 | *pnResult = ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczPath1, -1, sczPath2, -1); | ||
| 1100 | |||
| 1101 | LExit: | ||
| 1102 | ReleaseStr(sczPath2); | ||
| 1103 | ReleaseStr(sczPath1); | ||
| 1104 | |||
| 1105 | return hr; | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | |||
| 1109 | DAPI_(HRESULT) PathCompress( | 1083 | DAPI_(HRESULT) PathCompress( |
| 1110 | __in_z LPCWSTR wzPath | 1084 | __in_z LPCWSTR wzPath |
| 1111 | ) | 1085 | ) |
diff --git a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp index 554c6f00..2505c6bf 100644 --- a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp +++ b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | |||
| @@ -151,6 +151,10 @@ namespace DutilTests | |||
| 151 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | 151 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); |
| 152 | NativeAssert::StringEqual(L"\\\\otherdir\\unc.exe", sczCanonicalized); | 152 | NativeAssert::StringEqual(L"\\\\otherdir\\unc.exe", sczCanonicalized); |
| 153 | 153 | ||
| 154 | hr = PathCanonicalizeForComparison(L"\\??\\UNC\\server\\share\\dir", PATH_CANONICALIZE_KEEP_UNC_ROOT, &sczCanonicalized); | ||
| 155 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
| 156 | NativeAssert::StringEqual(L"\\\\?\\UNC\\server\\share\\dir", sczCanonicalized); | ||
| 157 | |||
| 154 | hr = PathCanonicalizeForComparison(L"\\\\?\\UNC\\server\\share\\..\\..\\otherdir\\unc.exe", PATH_CANONICALIZE_KEEP_UNC_ROOT, &sczCanonicalized); | 158 | hr = PathCanonicalizeForComparison(L"\\\\?\\UNC\\server\\share\\..\\..\\otherdir\\unc.exe", PATH_CANONICALIZE_KEEP_UNC_ROOT, &sczCanonicalized); |
| 155 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | 159 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); |
| 156 | NativeAssert::StringEqual(L"\\\\?\\UNC\\server\\share\\otherdir\\unc.exe", sczCanonicalized); | 160 | NativeAssert::StringEqual(L"\\\\?\\UNC\\server\\share\\otherdir\\unc.exe", sczCanonicalized); |
| @@ -203,6 +207,10 @@ namespace DutilTests | |||
| 203 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | 207 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); |
| 204 | NativeAssert::StringEqual(L"\\\\?\\invalidlongpath.exe", sczCanonicalized); | 208 | NativeAssert::StringEqual(L"\\\\?\\invalidlongpath.exe", sczCanonicalized); |
| 205 | 209 | ||
| 210 | hr = PathCanonicalizeForComparison(L"\\??\\test\\..\\invalidlongpath.exe", 0, &sczCanonicalized); | ||
| 211 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
| 212 | NativeAssert::StringEqual(L"\\\\?\\invalidlongpath.exe", sczCanonicalized); | ||
| 213 | |||
| 206 | hr = PathCanonicalizeForComparison(L"C:\\.\\invalid:pathchars?.exe", 0, &sczCanonicalized); | 214 | hr = PathCanonicalizeForComparison(L"C:\\.\\invalid:pathchars?.exe", 0, &sczCanonicalized); |
| 207 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | 215 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); |
| 208 | NativeAssert::StringEqual(L"C:\\invalid:pathchars?.exe", sczCanonicalized); | 216 | NativeAssert::StringEqual(L"C:\\invalid:pathchars?.exe", sczCanonicalized); |
| @@ -264,6 +272,67 @@ namespace DutilTests | |||
| 264 | } | 272 | } |
| 265 | 273 | ||
| 266 | [Fact] | 274 | [Fact] |
| 275 | void PathCompareCanonicalizeEqualTest() | ||
| 276 | { | ||
| 277 | HRESULT hr = S_OK; | ||
| 278 | LPWSTR sczPath = NULL; | ||
| 279 | BOOL fEqual = FALSE; | ||
| 280 | LPCWSTR rgwzPaths[14] = | ||
| 281 | { | ||
| 282 | L"C:\\simplepath", L"C:\\simplepath", | ||
| 283 | L"\\\\server\\share\\dir\\dir2\\..\\otherdir\\unc.exe", L"\\\\server\\share\\dir\\otherdir\\unc.exe", | ||
| 284 | L"\\\\server\\share\\..\\..\\otherdir\\unc.exe", L"\\\\server\\share\\otherdir\\unc.exe", | ||
| 285 | L"\\\\?\\UNC\\server\\share\\..\\..\\otherdir\\unc.exe", L"\\\\?\\UNC\\server\\share\\otherdir\\unc.exe", | ||
| 286 | L"C:\\dir\\subdir\\..\\..\\..\\otherdir\\pastroot.exe", L"C:\\otherdir\\pastroot.exe", | ||
| 287 | L"\\\\?\\C:\\dir\\subdir\\..\\..\\..\\otherdir\\pastroot.exe", L"C:\\..\\otherdir\\pastroot.exe", | ||
| 288 | L"\\??\\C:\\dir", L"\\\\?\\C:\\dir", | ||
| 289 | }; | ||
| 290 | |||
| 291 | try | ||
| 292 | { | ||
| 293 | for (DWORD i = 0; i < countof(rgwzPaths); i += 2) | ||
| 294 | { | ||
| 295 | hr = PathCompareCanonicalized(rgwzPaths[i], rgwzPaths[i + 1], &fEqual); | ||
| 296 | NativeAssert::Succeeded(hr, "PathCompareCanonicalized: {0}, {1}", rgwzPaths[i], rgwzPaths[i + 1]); | ||
| 297 | Assert::True(fEqual, String::Format("PathCompareCanonicalized: {0}, {1}", gcnew String(rgwzPaths[i]), gcnew String(rgwzPaths[i + 1]))); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | finally | ||
| 301 | { | ||
| 302 | ReleaseStr(sczPath); | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | [Fact] | ||
| 307 | void PathCompareCanonicalizeNotEqualTest() | ||
| 308 | { | ||
| 309 | HRESULT hr = S_OK; | ||
| 310 | LPWSTR sczPath = NULL; | ||
| 311 | BOOL fEqual = FALSE; | ||
| 312 | LPCWSTR rgwzPaths[8] = | ||
| 313 | { | ||
| 314 | L"C:\\simplepath", L"D:\\simplepath", | ||
| 315 | L"\\\\.\\share\\otherdir\\unc.exe", L"\\\\share\\otherdir\\unc.exe", | ||
| 316 | L"\\\\server\\.\\otherdir\\unc.exe", L"\\\\server\\otherdir\\unc.exe", | ||
| 317 | L"\\\\server\\\\otherdir\\unc.exe", L"\\\\server\\otherdir\\unc.exe", | ||
| 318 | }; | ||
| 319 | |||
| 320 | try | ||
| 321 | { | ||
| 322 | for (DWORD i = 0; i < countof(rgwzPaths); i += 2) | ||
| 323 | { | ||
| 324 | hr = PathCompareCanonicalized(rgwzPaths[i], rgwzPaths[i + 1], &fEqual); | ||
| 325 | NativeAssert::Succeeded(hr, "PathCompareCanonicalized: {0}, {1}", rgwzPaths[i], rgwzPaths[i + 1]); | ||
| 326 | Assert::False(fEqual, String::Format("PathCompareCanonicalized: {0}, {1}", gcnew String(rgwzPaths[i]), gcnew String(rgwzPaths[i + 1]))); | ||
| 327 | } | ||
| 328 | } | ||
| 329 | finally | ||
| 330 | { | ||
| 331 | ReleaseStr(sczPath); | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | [Fact] | ||
| 267 | void PathConcatRelativeToBaseTest() | 336 | void PathConcatRelativeToBaseTest() |
| 268 | { | 337 | { |
| 269 | HRESULT hr = S_OK; | 338 | HRESULT hr = S_OK; |
