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; |