diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/path2utl.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/path2utl.cpp | 145 |
1 files changed, 133 insertions, 12 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp index 3c4b2f88..862a743d 100644 --- a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp +++ b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp | |||
@@ -19,6 +19,65 @@ | |||
19 | #define PathExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_PATHUTIL, g, x, s, __VA_ARGS__) | 19 | #define PathExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_PATHUTIL, g, x, s, __VA_ARGS__) |
20 | 20 | ||
21 | 21 | ||
22 | typedef HRESULT(WINAPI* PFN_PATH_ALLOC_CANONICALIZE)( | ||
23 | __in LPCWSTR wzSource, | ||
24 | __in DWORD dwFlags, | ||
25 | __out_z LPWSTR* psczPathOut | ||
26 | ); | ||
27 | |||
28 | static BOOL vfInitialized = FALSE; | ||
29 | static HMODULE vhPathApiSet_1_1_0 = NULL; | ||
30 | static PFN_PATH_ALLOC_CANONICALIZE vpfnPathAllocCanonicalize = NULL; | ||
31 | static BOOL vfForceFallback = FALSE; | ||
32 | |||
33 | // from PathCch.h | ||
34 | #ifndef PATHCCH_ALLOW_LONG_PATHS | ||
35 | #define PATHCCH_ALLOW_LONG_PATHS 0x01 | ||
36 | #endif | ||
37 | |||
38 | static HRESULT Initialize() | ||
39 | { | ||
40 | HRESULT hr = S_OK; | ||
41 | DWORD er = ERROR_SUCCESS; | ||
42 | |||
43 | if (vfInitialized) | ||
44 | { | ||
45 | ExitFunction(); | ||
46 | } | ||
47 | |||
48 | hr = LoadSystemApiSet(L"api-ms-win-core-path-l1-1-0.dll", &vhPathApiSet_1_1_0); | ||
49 | if (E_MODNOTFOUND == hr) | ||
50 | { | ||
51 | hr = E_NOTIMPL; | ||
52 | } | ||
53 | PathExitOnFailure(hr, "Failed to load api-ms-win-core-path-l1-1-0.dll"); | ||
54 | |||
55 | vpfnPathAllocCanonicalize = reinterpret_cast<PFN_PATH_ALLOC_CANONICALIZE>(::GetProcAddress(vhPathApiSet_1_1_0, "PathAllocCanonicalize")); | ||
56 | if (!vpfnPathAllocCanonicalize) | ||
57 | { | ||
58 | er = ::GetLastError(); | ||
59 | PathExitWithRootFailure(hr, ERROR_PROC_NOT_FOUND == er ? E_NOTIMPL : HRESULT_FROM_WIN32(er), "Failed to get address of PathAllocCanonicalize."); | ||
60 | } | ||
61 | |||
62 | vfInitialized = TRUE; | ||
63 | |||
64 | LExit: | ||
65 | return hr; | ||
66 | } | ||
67 | |||
68 | |||
69 | DAPI_(void) Path2FunctionAllowFallback() | ||
70 | { | ||
71 | vfForceFallback = FALSE; | ||
72 | } | ||
73 | |||
74 | |||
75 | DAPI_(void) Path2FunctionForceFallback() | ||
76 | { | ||
77 | vfForceFallback = TRUE; | ||
78 | } | ||
79 | |||
80 | |||
22 | DAPI_(HRESULT) PathCanonicalizePath( | 81 | DAPI_(HRESULT) PathCanonicalizePath( |
23 | __in_z LPCWSTR wzPath, | 82 | __in_z LPCWSTR wzPath, |
24 | __deref_out_z LPWSTR* psczCanonicalized | 83 | __deref_out_z LPWSTR* psczCanonicalized |
@@ -43,6 +102,37 @@ LExit: | |||
43 | return hr; | 102 | return hr; |
44 | } | 103 | } |
45 | 104 | ||
105 | DAPI_(HRESULT) PathAllocCanonicalizePath( | ||
106 | __in_z LPCWSTR wzPath, | ||
107 | __in DWORD dwFlags, | ||
108 | __deref_out_z LPWSTR* psczCanonicalized | ||
109 | ) | ||
110 | { | ||
111 | HRESULT hr = S_OK; | ||
112 | LPWSTR sczCanonicalizedPath = NULL; | ||
113 | |||
114 | hr = Initialize(); | ||
115 | if (E_NOTIMPL == hr || SUCCEEDED(hr) && !vpfnPathAllocCanonicalize) | ||
116 | { | ||
117 | ExitFunction1(hr = E_NOTIMPL); | ||
118 | } | ||
119 | PathExitOnFailure(hr, "Failed to initialize path2utl."); | ||
120 | |||
121 | hr = vpfnPathAllocCanonicalize(wzPath, dwFlags, &sczCanonicalizedPath); | ||
122 | PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzPath); | ||
123 | |||
124 | hr = StrAllocString(psczCanonicalized, sczCanonicalizedPath, 0); | ||
125 | PathExitOnFailure(hr, "Failed to copy the canonicalized path."); | ||
126 | |||
127 | LExit: | ||
128 | if (sczCanonicalizedPath) | ||
129 | { | ||
130 | ::LocalFree(sczCanonicalizedPath); | ||
131 | } | ||
132 | |||
133 | return hr; | ||
134 | } | ||
135 | |||
46 | DAPI_(HRESULT) PathCanonicalizeForComparison( | 136 | DAPI_(HRESULT) PathCanonicalizeForComparison( |
47 | __in_z LPCWSTR wzPath, | 137 | __in_z LPCWSTR wzPath, |
48 | __in DWORD dwCanonicalizeFlags, | 138 | __in DWORD dwCanonicalizeFlags, |
@@ -75,7 +165,19 @@ DAPI_(HRESULT) PathCanonicalizeForComparison( | |||
75 | 165 | ||
76 | if (*wzNormalizedPath) | 166 | if (*wzNormalizedPath) |
77 | { | 167 | { |
78 | hr = PathCanonicalizePath(wzNormalizedPath, psczCanonicalized); | 168 | if (!vfForceFallback) |
169 | { | ||
170 | hr = PathAllocCanonicalizePath(wzNormalizedPath, PATHCCH_ALLOW_LONG_PATHS, psczCanonicalized); | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | hr = E_NOTIMPL; | ||
175 | } | ||
176 | |||
177 | if (E_NOTIMPL == hr) | ||
178 | { | ||
179 | hr = PathCanonicalizePath(wzNormalizedPath, psczCanonicalized); | ||
180 | } | ||
79 | PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzNormalizedPath); | 181 | PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzNormalizedPath); |
80 | } | 182 | } |
81 | else | 183 | else |
@@ -273,33 +375,52 @@ DAPI_(HRESULT) PathSystemWindowsSubdirectory( | |||
273 | ) | 375 | ) |
274 | { | 376 | { |
275 | HRESULT hr = S_OK; | 377 | HRESULT hr = S_OK; |
276 | WCHAR wzTempPath[MAX_PATH + 1] = { }; | 378 | LPWSTR sczWindowsPath = NULL; |
379 | DWORD cchBuffer = MAX_PATH + 1; | ||
277 | DWORD cch = 0; | 380 | DWORD cch = 0; |
278 | 381 | ||
279 | cch = ::GetSystemWindowsDirectoryW(wzTempPath, countof(wzTempPath)); | 382 | hr = StrAlloc(&sczWindowsPath, cchBuffer); |
280 | if (!cch) | 383 | PathExitOnFailure(hr, "Failed to alloc Windows directory path."); |
281 | { | 384 | |
282 | PathExitWithLastError(hr, "Failed to get Windows directory path."); | 385 | cch = ::GetSystemWindowsDirectoryW(sczWindowsPath, cchBuffer); |
283 | } | 386 | PathExitOnNullWithLastError(cch, hr, "Failed to get Windows directory path with default size."); |
284 | else if (cch >= countof(wzTempPath)) | 387 | |
388 | cch += 1; // add 1 for null terminator. | ||
389 | |||
390 | if (cch > cchBuffer) | ||
285 | { | 391 | { |
286 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Windows directory path too long."); | 392 | hr = StrAlloc(&sczWindowsPath, cch); |
393 | PathExitOnFailure(hr, "Failed to realloc Windows directory path."); | ||
394 | |||
395 | cchBuffer = cch; | ||
396 | |||
397 | cch = ::GetSystemWindowsDirectoryW(sczWindowsPath, cchBuffer); | ||
398 | PathExitOnNullWithLastError(cch, hr, "Failed to get Windows directory path with returned size."); | ||
399 | |||
400 | cch += 1; // add 1 for null terminator. | ||
401 | |||
402 | if (cch > cchBuffer) | ||
403 | { | ||
404 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Failed to get Windows directory path with returned size."); | ||
405 | } | ||
287 | } | 406 | } |
288 | 407 | ||
289 | if (wzSubdirectory) | 408 | if (wzSubdirectory) |
290 | { | 409 | { |
291 | hr = PathConcatRelativeToBase(wzTempPath, wzSubdirectory, psczFullPath); | 410 | hr = PathConcatRelativeToBase(sczWindowsPath, wzSubdirectory, psczFullPath); |
292 | PathExitOnFailure(hr, "Failed to concat subdirectory on Windows directory path."); | 411 | PathExitOnFailure(hr, "Failed to concat subdirectory on Windows directory path."); |
293 | } | 412 | } |
294 | else | 413 | else |
295 | { | 414 | { |
296 | hr = StrAllocString(psczFullPath, wzTempPath, 0); | 415 | *psczFullPath = sczWindowsPath; |
297 | PathExitOnFailure(hr, "Failed to copy Windows directory path."); | 416 | sczWindowsPath = NULL; |
298 | } | 417 | } |
299 | 418 | ||
300 | hr = PathBackslashTerminate(psczFullPath); | 419 | hr = PathBackslashTerminate(psczFullPath); |
301 | PathExitOnFailure(hr, "Failed to terminate Windows directory path with backslash."); | 420 | PathExitOnFailure(hr, "Failed to terminate Windows directory path with backslash."); |
302 | 421 | ||
303 | LExit: | 422 | LExit: |
423 | ReleaseStr(sczWindowsPath); | ||
424 | |||
304 | return hr; | 425 | return hr; |
305 | } | 426 | } |