diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/path2utl.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/path2utl.cpp | 149 |
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 | ||
45 | DAPI_(HRESULT) PathDirectoryContainsPath( | 46 | DAPI_(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 | |||
128 | LExit: | ||
129 | ReleaseStr(sczNormalizedPath); | ||
85 | 130 | ||
86 | ++sczDirectory; | 131 | return hr; |
87 | ++sczPath; | 132 | } |
133 | |||
134 | DAPI_(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 | |||
100 | LExit: | 179 | LExit: |
101 | ReleaseStr(sczOriginalPath); | 180 | ReleaseStr(sczCanonicalizedPath); |
102 | ReleaseStr(sczOriginalDirectory); | 181 | ReleaseStr(sczCanonicalizedDirectory); |
103 | return hr; | 182 | return hr; |
104 | } | 183 | } |