summaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/path2utl.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/path2utl.cpp149
1 files changed, 114 insertions, 35 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
index ff3a946d..45157d0b 100644
--- a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
@@ -9,6 +9,7 @@
9#define PathExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__) 9#define PathExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
10#define PathExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__) 10#define PathExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
11#define PathExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__) 11#define PathExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
12#define PathExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, e, s, __VA_ARGS__)
12#define PathExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__) 13#define PathExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
13#define PathExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_PATHUTIL, p, x, e, s, __VA_ARGS__) 14#define PathExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_PATHUTIL, p, x, e, s, __VA_ARGS__)
14#define PathExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, p, x, s, __VA_ARGS__) 15#define PathExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, p, x, s, __VA_ARGS__)
@@ -42,63 +43,141 @@ LExit:
42 return hr; 43 return hr;
43} 44}
44 45
45DAPI_(HRESULT) PathDirectoryContainsPath( 46DAPI_(HRESULT) PathCanonicalizeForComparison(
46 __in_z LPCWSTR wzDirectory, 47 __in_z LPCWSTR wzPath,
47 __in_z LPCWSTR wzPath 48 __in DWORD dwCanonicalizeFlags,
49 __deref_out_z LPWSTR* psczCanonicalized
48 ) 50 )
49{ 51{
50 HRESULT hr = S_OK; 52 HRESULT hr = S_OK;
51 LPWSTR sczPath = NULL; 53 LPWSTR sczNormalizedPath = NULL;
52 LPWSTR sczDirectory = NULL; 54 LPCWSTR wzNormalizedPath = NULL;
53 LPWSTR sczOriginalPath = NULL; 55 SIZE_T cchUncRootLength = 0;
54 LPWSTR sczOriginalDirectory = NULL; 56 BOOL fHasPrefix = FALSE;
55 57
56 hr = PathCanonicalizePath(wzPath, &sczOriginalPath); 58 hr = StrAllocString(&sczNormalizedPath, wzPath, 0);
57 PathExitOnFailure(hr, "Failed to canonicalize the path."); 59 PathExitOnFailure(hr, "Failed to allocate string for the normalized path.");
58 60
59 hr = PathCanonicalizePath(wzDirectory, &sczOriginalDirectory); 61 PathFixedNormalizeSlashes(sczNormalizedPath);
60 PathExitOnFailure(hr, "Failed to canonicalize the directory."); 62
63 wzNormalizedPath = sczNormalizedPath;
61 64
62 if (!sczOriginalPath || !*sczOriginalPath) 65 if (PATH_CANONICALIZE_KEEP_UNC_ROOT & dwCanonicalizeFlags)
63 { 66 {
64 ExitFunction1(hr = S_FALSE); 67 if (L'\\' == sczNormalizedPath[0] && (L'\\' == sczNormalizedPath[1] || L'?' == sczNormalizedPath[1]) && L'?' == sczNormalizedPath[2] && L'\\' == sczNormalizedPath[3])
68 {
69 if (L'U' == sczNormalizedPath[4] && L'N' == sczNormalizedPath[5] && L'C' == sczNormalizedPath[6] && L'\\' == sczNormalizedPath[7])
70 {
71 cchUncRootLength = 8;
72 }
73 }
74 else if (L'\\' == sczNormalizedPath[0] && L'\\' == sczNormalizedPath[1])
75 {
76 cchUncRootLength = 2;
77 }
78
79 if (cchUncRootLength)
80 {
81 DWORD dwRemainingSlashes = 2;
82
83 for (wzNormalizedPath += cchUncRootLength; *wzNormalizedPath && dwRemainingSlashes; ++wzNormalizedPath)
84 {
85 ++cchUncRootLength;
86
87 if (L'\\' == *wzNormalizedPath)
88 {
89 --dwRemainingSlashes;
90 }
91 }
92 }
93 }
94
95 if (*wzNormalizedPath)
96 {
97 hr = PathCanonicalizePath(wzNormalizedPath, psczCanonicalized);
98 PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzNormalizedPath);
65 } 99 }
66 if (!sczOriginalDirectory || !*sczOriginalDirectory) 100 else
67 { 101 {
68 ExitFunction1(hr = S_FALSE); 102 Assert(cchUncRootLength);
103 ReleaseStr(*psczCanonicalized);
104 *psczCanonicalized = sczNormalizedPath;
105 sczNormalizedPath = NULL;
106 cchUncRootLength = 0;
69 } 107 }
70 108
71 sczPath = sczOriginalPath; 109 if (cchUncRootLength)
72 sczDirectory = sczOriginalDirectory; 110 {
111 hr = StrAllocPrefix(psczCanonicalized, sczNormalizedPath, cchUncRootLength);
112 PathExitOnFailure(hr, "Failed to prefix the UNC root to the canonicalized path.");
113 }
73 114
74 for (; *sczDirectory;) 115 if (PATH_CANONICALIZE_BACKSLASH_TERMINATE & dwCanonicalizeFlags)
75 { 116 {
76 if (!*sczPath) 117 hr = PathBackslashTerminate(psczCanonicalized);
77 { 118 PathExitOnFailure(hr, "Failed to backslash terminate the canonicalized path");
78 ExitFunction1(hr = S_FALSE); 119 }
79 }
80 120
81 if (CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczDirectory, 1, sczPath, 1)) 121 if ((PATH_CANONICALIZE_APPEND_LONG_PATH_PREFIX & dwCanonicalizeFlags) &&
82 { 122 PathIsFullyQualified(*psczCanonicalized, &fHasPrefix) && !fHasPrefix)
83 ExitFunction1(hr = S_FALSE); 123 {
84 } 124 hr = PathPrefix(psczCanonicalized);
125 PathExitOnFailure(hr, "Failed to ensure the long path prefix on the canonicalized path");
126 }
127
128LExit:
129 ReleaseStr(sczNormalizedPath);
85 130
86 ++sczDirectory; 131 return hr;
87 ++sczPath; 132}
133
134DAPI_(HRESULT) PathDirectoryContainsPath(
135 __in_z LPCWSTR wzDirectory,
136 __in_z LPCWSTR wzPath
137 )
138{
139 HRESULT hr = S_OK;
140 LPWSTR sczCanonicalizedDirectory = NULL;
141 LPWSTR sczCanonicalizedPath = NULL;
142 DWORD dwDefaultFlags = PATH_CANONICALIZE_APPEND_LONG_PATH_PREFIX | PATH_CANONICALIZE_KEEP_UNC_ROOT;
143 size_t cchDirectory = 0;
144
145 if (!wzDirectory || !*wzDirectory)
146 {
147 PathExitWithRootFailure(hr, E_INVALIDARG, "wzDirectory is required.");
88 } 148 }
149 if (!wzPath || !*wzPath)
150 {
151 PathExitWithRootFailure(hr, E_INVALIDARG, "wzPath is required.");
152 }
153
154 hr = PathCanonicalizeForComparison(wzDirectory, dwDefaultFlags | PATH_CANONICALIZE_BACKSLASH_TERMINATE, &sczCanonicalizedDirectory);
155 PathExitOnFailure(hr, "Failed to canonicalize the directory.");
89 156
90 --sczDirectory; 157 hr = PathCanonicalizeForComparison(wzPath, dwDefaultFlags, &sczCanonicalizedPath);
91 if (('\\' == *sczDirectory && *sczPath) || '\\' == *sczPath) 158 PathExitOnFailure(hr, "Failed to canonicalize the path.");
159
160 if (!PathIsFullyQualified(sczCanonicalizedDirectory, NULL))
92 { 161 {
93 hr = S_OK; 162 PathExitWithRootFailure(hr, E_INVALIDARG, "wzDirectory must be a fully qualified path.");
94 } 163 }
95 else 164 if (!sczCanonicalizedPath || !*sczCanonicalizedPath)
96 { 165 {
97 hr = S_FALSE; 166 ExitFunction1(hr = S_FALSE);
98 } 167 }
99 168
169 hr = ::StringCchLengthW(sczCanonicalizedDirectory, STRSAFE_MAX_CCH, &cchDirectory);
170 PathExitOnFailure(hr, "Failed to get length of canonicalized directory.");
171
172 if (CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczCanonicalizedDirectory, (DWORD)cchDirectory, sczCanonicalizedPath, (DWORD)cchDirectory))
173 {
174 ExitFunction1(hr = S_FALSE);
175 }
176
177 hr = sczCanonicalizedPath[cchDirectory] ? S_OK : S_FALSE;
178
100LExit: 179LExit:
101 ReleaseStr(sczOriginalPath); 180 ReleaseStr(sczCanonicalizedPath);
102 ReleaseStr(sczOriginalDirectory); 181 ReleaseStr(sczCanonicalizedDirectory);
103 return hr; 182 return hr;
104} 183}