| ... | ... | @@ -17,6 +17,9 @@ | 
| 17 | 17 |  #include <string>
 | 
| 18 | 18 |  #include <type_traits>
 | 
| 19 | 19 |  
 | 
|  | 20 | +// tor-browser#42163
 | 
|  | 21 | +#include <filesystem>
 | 
|  | 22 | +
 | 
| 20 | 23 |  #define EXPAND_STRING_MACRO2(t) t
 | 
| 21 | 24 |  #define EXPAND_STRING_MACRO(t) EXPAND_STRING_MACRO2(t)
 | 
| 22 | 25 |  
 | 
| ... | ... | @@ -586,6 +589,45 @@ LauncherRegistryInfo::GetBrowserStartTimestamp() { | 
| 586 | 589 |  
 | 
| 587 | 590 |  LauncherResult<std::wstring>
 | 
| 588 | 591 |  LauncherRegistryInfo::BuildDefaultBlocklistFilename() {
 | 
|  | 592 | +  // tor-browser#42163: Make the DLL blocklist obey portable mode
 | 
|  | 593 | +  {
 | 
|  | 594 | +    std::filesystem::path appDir;
 | 
|  | 595 | +    {
 | 
|  | 596 | +      mozilla::UniquePtr<wchar_t[]> appDirStr = GetFullBinaryPath();
 | 
|  | 597 | +      if (!appDirStr) {
 | 
|  | 598 | +        return LAUNCHER_ERROR_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
 | 
|  | 599 | +      }
 | 
|  | 600 | +      appDir = std::filesystem::path(appDirStr.get()).parent_path();
 | 
|  | 601 | +    }
 | 
|  | 602 | +    std::error_code ec;
 | 
|  | 603 | +    const bool isPortable =
 | 
|  | 604 | +        !std::filesystem::exists(appDir / L"system-install", ec);
 | 
|  | 605 | +    if (ec) {
 | 
|  | 606 | +      // exists is supposed not to set an error when a file does not exist
 | 
|  | 607 | +      // (whereas other functions such as is_regular_file sets it).
 | 
|  | 608 | +      // The standard is quite opaque about the meaning of the numeric codes.
 | 
|  | 609 | +      // Moreover, we use libcxx on Windows, and it seems they created a sort of
 | 
|  | 610 | +      // POSIX compatibility layer (e.g., for stat), see
 | 
|  | 611 | +      // libcxx/src/filesystem/posix_compat.h.
 | 
|  | 612 | +      // std::error_code has a message function, but all the various macro are
 | 
|  | 613 | +      // specific to handle Windows errors, so we have to use the generic error.
 | 
|  | 614 | +      // At least, at the moment the error is dropped eventually.
 | 
|  | 615 | +      return LAUNCHER_ERROR_GENERIC();
 | 
|  | 616 | +    }
 | 
|  | 617 | +    if (isPortable) {
 | 
|  | 618 | +      // RELATIVE_DATA_DIR must have forward slashes, but weakly_canonical
 | 
|  | 619 | +      // already changes them to backslashes.
 | 
|  | 620 | +      const std::filesystem::path blocklistPath =
 | 
|  | 621 | +          std::filesystem::weakly_canonical(
 | 
|  | 622 | +              appDir / L"" RELATIVE_DATA_DIR / L"blocklist", ec);
 | 
|  | 623 | +      if (ec) {
 | 
|  | 624 | +        return LAUNCHER_ERROR_GENERIC();
 | 
|  | 625 | +      }
 | 
|  | 626 | +      return blocklistPath.wstring();
 | 
|  | 627 | +    }
 | 
|  | 628 | +    // Normal installation, continue on Mozilla's path
 | 
|  | 629 | +  }
 | 
|  | 630 | +
 | 
| 589 | 631 |    // These flags are chosen to avoid I/O, see bug 1363398.
 | 
| 590 | 632 |    const DWORD flags =
 | 
| 591 | 633 |        KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_ALIAS;
 | 
| ... | ... | @@ -618,6 +660,8 @@ LauncherRegistryInfo::BuildDefaultBlocklistFilename() { | 
| 618 | 660 |  }
 | 
| 619 | 661 |  
 | 
| 620 | 662 |  LauncherResult<std::wstring> LauncherRegistryInfo::GetBlocklistFileName() {
 | 
|  | 663 | +  // tor-browser#42163: Make the DLL blocklist obey portable mode
 | 
|  | 664 | +#ifndef BASE_BROWSER_VERSION
 | 
| 621 | 665 |    LauncherResult<Disposition> disposition = Open();
 | 
| 622 | 666 |    if (disposition.isErr()) {
 | 
| 623 | 667 |      return disposition.propagateErr();
 | 
| ... | ... | @@ -633,19 +677,19 @@ LauncherResult<std::wstring> LauncherRegistryInfo::GetBlocklistFileName() { | 
| 633 | 677 |      UniquePtr<wchar_t[]> buf = readResult.unwrap();
 | 
| 634 | 678 |      return std::wstring(buf.get());
 | 
| 635 | 679 |    }
 | 
| 636 |  | -
 | 
|  | 680 | +#endif
 | 
| 637 | 681 |    LauncherResult<std::wstring> defaultBlocklistPath =
 | 
| 638 | 682 |        BuildDefaultBlocklistFilename();
 | 
| 639 | 683 |    if (defaultBlocklistPath.isErr()) {
 | 
| 640 | 684 |      return defaultBlocklistPath.propagateErr();
 | 
| 641 | 685 |    }
 | 
| 642 |  | -
 | 
|  | 686 | +#ifndef BASE_BROWSER_VERSION
 | 
| 643 | 687 |    LauncherVoidResult writeResult = WriteRegistryValueString(
 | 
| 644 | 688 |        mRegKey, ResolveBlocklistValueName(), defaultBlocklistPath.inspect());
 | 
| 645 | 689 |    if (writeResult.isErr()) {
 | 
| 646 | 690 |      return writeResult.propagateErr();
 | 
| 647 | 691 |    }
 | 
| 648 |  | -
 | 
|  | 692 | +#endif
 | 
| 649 | 693 |    return defaultBlocklistPath;
 | 
| 650 | 694 |  }
 | 
| 651 | 695 |  
 |