diff options
Diffstat (limited to '')
| -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 | } |
