diff options
Diffstat (limited to 'src/engine/cache.cpp')
| -rw-r--r-- | src/engine/cache.cpp | 203 |
1 files changed, 126 insertions, 77 deletions
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp index 6ac313e0..84b7f131 100644 --- a/src/engine/cache.cpp +++ b/src/engine/cache.cpp | |||
| @@ -11,7 +11,7 @@ static const DWORD FILE_OPERATION_RETRY_WAIT = 2000; | |||
| 11 | 11 | ||
| 12 | static BOOL vfInitializedCache = FALSE; | 12 | static BOOL vfInitializedCache = FALSE; |
| 13 | static BOOL vfRunningFromCache = FALSE; | 13 | static BOOL vfRunningFromCache = FALSE; |
| 14 | static LPWSTR vsczSourceProcessPath = NULL; | 14 | static LPWSTR vsczSourceProcessFolder = NULL; |
| 15 | static LPWSTR vsczWorkingFolder = NULL; | 15 | static LPWSTR vsczWorkingFolder = NULL; |
| 16 | static LPWSTR vsczDefaultUserPackageCache = NULL; | 16 | static LPWSTR vsczDefaultUserPackageCache = NULL; |
| 17 | static LPWSTR vsczDefaultMachinePackageCache = NULL; | 17 | static LPWSTR vsczDefaultMachinePackageCache = NULL; |
| @@ -140,8 +140,8 @@ extern "C" HRESULT CacheInitialize( | |||
| 140 | wzSourceProcessPath = sczCurrentPath; | 140 | wzSourceProcessPath = sczCurrentPath; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | hr = StrAllocString(&vsczSourceProcessPath, wzSourceProcessPath, 0); | 143 | hr = PathGetDirectory(wzSourceProcessPath, &vsczSourceProcessFolder); |
| 144 | ExitOnFailure(hr, "Failed to initialize cache source path."); | 144 | ExitOnFailure(hr, "Failed to initialize cache source folder."); |
| 145 | 145 | ||
| 146 | // If we're not running from the cache, ensure the original source is set. | 146 | // If we're not running from the cache, ensure the original source is set. |
| 147 | if (!vfRunningFromCache) | 147 | if (!vfRunningFromCache) |
| @@ -393,112 +393,166 @@ LExit: | |||
| 393 | return hr; | 393 | return hr; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | extern "C" HRESULT CacheFindLocalSource( | 396 | extern "C" HRESULT CacheGetLocalSourcePaths( |
| 397 | __in_z LPCWSTR wzRelativePath, | ||
| 397 | __in_z LPCWSTR wzSourcePath, | 398 | __in_z LPCWSTR wzSourcePath, |
| 398 | __in_z LPCWSTR wzDestinationPath, | 399 | __in_z LPCWSTR wzDestinationPath, |
| 400 | __in_z_opt LPCWSTR wzLayoutDirectory, | ||
| 399 | __in BURN_VARIABLES* pVariables, | 401 | __in BURN_VARIABLES* pVariables, |
| 400 | __out BOOL* pfFound, | 402 | __inout LPWSTR** prgSearchPaths, |
| 401 | __out_z LPWSTR* psczSourceFullPath | 403 | __out DWORD* pcSearchPaths |
| 402 | ) | 404 | ) |
| 403 | { | 405 | { |
| 404 | HRESULT hr = S_OK; | 406 | HRESULT hr = S_OK; |
| 405 | LPWSTR sczSourceProcessFolder = NULL; | ||
| 406 | LPWSTR sczCurrentPath = NULL; | 407 | LPWSTR sczCurrentPath = NULL; |
| 407 | LPWSTR sczLastSourcePath = NULL; | ||
| 408 | LPWSTR sczLastSourceFolder = NULL; | 408 | LPWSTR sczLastSourceFolder = NULL; |
| 409 | LPWSTR sczLayoutPath = NULL; | 409 | LPWSTR* psczPath = NULL; |
| 410 | LPWSTR sczLayoutFolder = NULL; | 410 | BOOL fPreferSourcePathLocation = FALSE; |
| 411 | LPCWSTR rgwzSearchPaths[4] = { }; | 411 | BOOL fTryLastFolder = FALSE; |
| 412 | BOOL fTryRelativePath = FALSE; | ||
| 413 | BOOL fSourceIsAbsolute = FALSE; | ||
| 412 | DWORD cSearchPaths = 0; | 414 | DWORD cSearchPaths = 0; |
| 413 | 415 | ||
| 414 | // If the source path provided is a full path, obviously that is where we should be looking. | 416 | AssertSz(vfInitializedCache, "Cache wasn't initialized"); |
| 415 | if (PathIsAbsolute(wzSourcePath)) | 417 | |
| 418 | hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder); | ||
| 419 | fPreferSourcePathLocation = !vfRunningFromCache || FAILED(hr); | ||
| 420 | fTryLastFolder = SUCCEEDED(hr) && sczLastSourceFolder && *sczLastSourceFolder && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, vsczSourceProcessFolder, -1, sczLastSourceFolder, -1); | ||
| 421 | fTryRelativePath = CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzSourcePath, -1, wzRelativePath, -1); | ||
| 422 | fSourceIsAbsolute = PathIsAbsolute(wzSourcePath); | ||
| 423 | |||
| 424 | // If the source path provided is a full path, try that first. | ||
| 425 | if (fSourceIsAbsolute) | ||
| 416 | { | 426 | { |
| 417 | rgwzSearchPaths[0] = wzSourcePath; | 427 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 418 | cSearchPaths = 1; | 428 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 429 | |||
| 430 | psczPath = *prgSearchPaths + cSearchPaths; | ||
| 431 | ++cSearchPaths; | ||
| 432 | |||
| 433 | hr = StrAllocString(psczPath, wzSourcePath, 0); | ||
| 434 | ExitOnFailure(hr, "Failed to copy absolute source path."); | ||
| 419 | } | 435 | } |
| 420 | else | 436 | |
| 437 | // Try the destination path next. | ||
| 438 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 439 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 440 | |||
| 441 | psczPath = *prgSearchPaths + cSearchPaths; | ||
| 442 | ++cSearchPaths; | ||
| 443 | |||
| 444 | hr = StrAllocString(psczPath, wzDestinationPath, 0); | ||
| 445 | ExitOnFailure(hr, "Failed to copy absolute source path."); | ||
| 446 | |||
| 447 | if (!fSourceIsAbsolute) | ||
| 421 | { | 448 | { |
| 422 | // Use the destination path first. | 449 | // Calculate the source path location. |
| 423 | rgwzSearchPaths[0] = wzDestinationPath; | 450 | // In the case where we are in the bundle's package cache and |
| 424 | cSearchPaths = 1; | 451 | // couldn't find a last used source that will be the package cache path |
| 425 | 452 | // which isn't likely to have what we are looking for. | |
| 426 | // If we're not running from cache or we couldn't get the last source, use | 453 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 427 | // the source path location. In the case where we are in the bundle's | 454 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 428 | // package cache and couldn't find a last used source we unfortunately will | 455 | |
| 429 | // be picking the package cache path which isn't likely to have what we are | 456 | hr = PathConcat(vsczSourceProcessFolder, wzSourcePath, &sczCurrentPath); |
| 430 | // looking for. | 457 | ExitOnFailure(hr, "Failed to combine source process folder with source."); |
| 431 | hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder); | 458 | |
| 432 | if (!vfRunningFromCache || FAILED(hr)) | 459 | // If we're not running from cache or we couldn't get the last source, |
| 460 | // try the source path location next. | ||
| 461 | if (fPreferSourcePathLocation) | ||
| 433 | { | 462 | { |
| 434 | hr = PathGetDirectory(vsczSourceProcessPath, &sczSourceProcessFolder); | 463 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; |
| 435 | ExitOnFailure(hr, "Failed to get current process directory."); | 464 | ++cSearchPaths; |
| 465 | sczCurrentPath = NULL; | ||
| 466 | } | ||
| 436 | 467 | ||
| 437 | hr = PathConcat(sczSourceProcessFolder, wzSourcePath, &sczCurrentPath); | 468 | // If we have a last used source and it is not the source path location, |
| 469 | // add the last used source to the search path next. | ||
| 470 | if (fTryLastFolder) | ||
| 471 | { | ||
| 472 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 473 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 474 | |||
| 475 | psczPath = *prgSearchPaths + cSearchPaths; | ||
| 476 | ++cSearchPaths; | ||
| 477 | |||
| 478 | hr = PathConcat(sczLastSourceFolder, wzSourcePath, psczPath); | ||
| 438 | ExitOnFailure(hr, "Failed to combine last source with source."); | 479 | ExitOnFailure(hr, "Failed to combine last source with source."); |
| 480 | } | ||
| 439 | 481 | ||
| 440 | rgwzSearchPaths[cSearchPaths] = sczCurrentPath; | 482 | if (!fPreferSourcePathLocation) |
| 483 | { | ||
| 484 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; | ||
| 441 | ++cSearchPaths; | 485 | ++cSearchPaths; |
| 486 | sczCurrentPath = NULL; | ||
| 442 | } | 487 | } |
| 443 | 488 | ||
| 444 | // If we have a last used source and it does not duplicate the existing search path, | 489 | // Also consider the layout directory if doing Layout. |
| 445 | // add the last used source to the search path second. | 490 | if (wzLayoutDirectory) |
| 446 | if (sczLastSourceFolder && *sczLastSourceFolder) | ||
| 447 | { | 491 | { |
| 448 | hr = PathConcat(sczLastSourceFolder, wzSourcePath, &sczLastSourcePath); | 492 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 449 | ExitOnFailure(hr, "Failed to combine last source with source."); | 493 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 450 | 494 | ||
| 451 | if (1 == cSearchPaths || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, rgwzSearchPaths[1], -1, sczLastSourcePath, -1)) | 495 | psczPath = *prgSearchPaths + cSearchPaths; |
| 452 | { | 496 | ++cSearchPaths; |
| 453 | rgwzSearchPaths[cSearchPaths] = sczLastSourcePath; | 497 | |
| 454 | ++cSearchPaths; | 498 | hr = PathConcat(wzLayoutDirectory, wzSourcePath, psczPath); |
| 455 | } | 499 | ExitOnFailure(hr, "Failed to combine layout source with source."); |
| 456 | } | 500 | } |
| 501 | } | ||
| 457 | 502 | ||
| 458 | // Also consider the layout directory if set on the command line or by the BA. | 503 | if (fTryRelativePath) |
| 459 | hr = VariableGetString(pVariables, BURN_BUNDLE_LAYOUT_DIRECTORY, &sczLayoutFolder); | 504 | { |
| 460 | if (E_NOTFOUND != hr) | 505 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 506 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 507 | |||
| 508 | hr = PathConcat(vsczSourceProcessFolder, wzRelativePath, &sczCurrentPath); | ||
| 509 | ExitOnFailure(hr, "Failed to combine source process folder with relative."); | ||
| 510 | |||
| 511 | if (fPreferSourcePathLocation) | ||
| 461 | { | 512 | { |
| 462 | ExitOnFailure(hr, "Failed to get bundle layout directory property."); | 513 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; |
| 514 | ++cSearchPaths; | ||
| 515 | sczCurrentPath = NULL; | ||
| 516 | } | ||
| 463 | 517 | ||
| 464 | hr = PathConcat(sczLayoutFolder, wzSourcePath, &sczLayoutPath); | 518 | if (fTryLastFolder) |
| 465 | ExitOnFailure(hr, "Failed to combine layout source with source."); | 519 | { |
| 520 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 521 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 466 | 522 | ||
| 467 | rgwzSearchPaths[cSearchPaths] = sczLayoutPath; | 523 | psczPath = *prgSearchPaths + cSearchPaths; |
| 468 | ++cSearchPaths; | 524 | ++cSearchPaths; |
| 525 | |||
| 526 | hr = PathConcat(sczLastSourceFolder, wzRelativePath, psczPath); | ||
| 527 | ExitOnFailure(hr, "Failed to combine last source with relative."); | ||
| 469 | } | 528 | } |
| 470 | } | ||
| 471 | 529 | ||
| 472 | *pfFound = FALSE; // assume we won't find the file locally. | 530 | if (!fPreferSourcePathLocation) |
| 531 | { | ||
| 532 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; | ||
| 533 | ++cSearchPaths; | ||
| 534 | sczCurrentPath = NULL; | ||
| 535 | } | ||
| 473 | 536 | ||
| 474 | for (DWORD i = 0; i < cSearchPaths; ++i) | 537 | if (wzLayoutDirectory) |
| 475 | { | ||
| 476 | // If the file exists locally, copy its path. | ||
| 477 | if (FileExistsEx(rgwzSearchPaths[i], NULL)) | ||
| 478 | { | 538 | { |
| 479 | hr = StrAllocString(psczSourceFullPath, rgwzSearchPaths[i], 0); | 539 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 480 | ExitOnFailure(hr, "Failed to copy source path."); | 540 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 481 | 541 | ||
| 482 | *pfFound = TRUE; | 542 | psczPath = *prgSearchPaths + cSearchPaths; |
| 483 | break; | 543 | ++cSearchPaths; |
| 484 | } | ||
| 485 | } | ||
| 486 | 544 | ||
| 487 | // If nothing was found, return the first thing in our search path as the | 545 | hr = PathConcat(wzLayoutDirectory, wzSourcePath, psczPath); |
| 488 | // best path where we thought we should have found the file. | 546 | ExitOnFailure(hr, "Failed to combine layout source with relative."); |
| 489 | if (!*pfFound) | 547 | } |
| 490 | { | ||
| 491 | hr = StrAllocString(psczSourceFullPath, rgwzSearchPaths[0], 0); | ||
| 492 | ExitOnFailure(hr, "Failed to copy source path."); | ||
| 493 | } | 548 | } |
| 494 | 549 | ||
| 495 | LExit: | 550 | LExit: |
| 496 | ReleaseStr(sczCurrentPath); | 551 | ReleaseStr(sczCurrentPath); |
| 497 | ReleaseStr(sczSourceProcessFolder); | ||
| 498 | ReleaseStr(sczLastSourceFolder); | 552 | ReleaseStr(sczLastSourceFolder); |
| 499 | ReleaseStr(sczLastSourcePath); | 553 | |
| 500 | ReleaseStr(sczLayoutFolder); | 554 | AssertSz(cSearchPaths <= BURN_CACHE_MAX_SEARCH_PATHS, "Got more than BURN_CACHE_MAX_SEARCH_PATHS search paths"); |
| 501 | ReleaseStr(sczLayoutPath); | 555 | *pcSearchPaths = cSearchPaths; |
| 502 | 556 | ||
| 503 | return hr; | 557 | return hr; |
| 504 | } | 558 | } |
| @@ -1079,7 +1133,7 @@ extern "C" void CacheUninitialize() | |||
| 1079 | ReleaseNullStr(vsczDefaultMachinePackageCache); | 1133 | ReleaseNullStr(vsczDefaultMachinePackageCache); |
| 1080 | ReleaseNullStr(vsczDefaultUserPackageCache); | 1134 | ReleaseNullStr(vsczDefaultUserPackageCache); |
| 1081 | ReleaseNullStr(vsczWorkingFolder); | 1135 | ReleaseNullStr(vsczWorkingFolder); |
| 1082 | ReleaseNullStr(vsczSourceProcessPath); | 1136 | ReleaseNullStr(vsczSourceProcessFolder); |
| 1083 | 1137 | ||
| 1084 | vfRunningFromCache = FALSE; | 1138 | vfRunningFromCache = FALSE; |
| 1085 | vfInitializedCache = FALSE; | 1139 | vfInitializedCache = FALSE; |
| @@ -1224,17 +1278,12 @@ static HRESULT GetLastUsedSourceFolder( | |||
| 1224 | ) | 1278 | ) |
| 1225 | { | 1279 | { |
| 1226 | HRESULT hr = S_OK; | 1280 | HRESULT hr = S_OK; |
| 1227 | LPWSTR sczOriginalSource = NULL; | ||
| 1228 | 1281 | ||
| 1229 | hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, psczLastSource); | 1282 | hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, psczLastSource); |
| 1230 | if (E_NOTFOUND == hr) | 1283 | if (E_NOTFOUND == hr) |
| 1231 | { | 1284 | { |
| 1232 | // Try the original source folder. | 1285 | // Try the original source folder. |
| 1233 | hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, &sczOriginalSource); | 1286 | hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, psczLastSource); |
| 1234 | if (SUCCEEDED(hr)) | ||
| 1235 | { | ||
| 1236 | hr = PathGetDirectory(sczOriginalSource, psczLastSource); | ||
| 1237 | } | ||
| 1238 | } | 1287 | } |
| 1239 | 1288 | ||
| 1240 | return hr; | 1289 | return hr; |
