Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  LauncherRegistryInfo.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */


#include "LauncherRegistryInfo.h"

#include "commonupdatedir.h"
#include "mozilla/Assertions.h"
#include "mozilla/NativeNt.h"
#include "mozilla/UniquePtr.h"

#include <cwctype>
#include <shlobj.h>
#include <string>
#include <type_traits>

// This is how long to wait after the last crash to try using the launcher
// process again. (bug 1846830) 45 days in 100-nanosecond intervals (FILETIME
// units)
static constexpr uint64_t kCrashTimeoutInterval =
    45ULL * 24 * 60 * 60 * 10000000ULL;

#define EXPAND_STRING_MACRO2(t) t
#define EXPAND_STRING_MACRO(t) EXPAND_STRING_MACRO2(t)

// This function is copied from Chromium base/time/time_win.cc
// Returns the current value of the performance counter.
static uint64_t QPCNowRaw() {
  LARGE_INTEGER perf_counter_now = {};
  // According to the MSDN documentation for QueryPerformanceCounter(), this
  // will never fail on systems that run XP or later.
  // https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
  ::QueryPerformanceCounter(&perf_counter_now);
  return perf_counter_now.QuadPart;
}

static mozilla::LauncherResult<DWORD> GetCurrentImageTimestamp() {
  mozilla::nt::PEHeaders headers(::GetModuleHandleW(nullptr));
  if (!headers) {
    return LAUNCHER_ERROR_FROM_WIN32(ERROR_BAD_EXE_FORMAT);
  }

  DWORD timestamp;
  if (!headers.GetTimeStamp(timestamp)) {
    return LAUNCHER_ERROR_FROM_WIN32(ERROR_INVALID_DATA);
  }

  return timestamp;
}

template <typename T>
static mozilla::LauncherResult<mozilla::Maybe<T>> ReadRegistryValueData(
    const nsAutoRegKey& key, const std::wstring& name, DWORD expectedType) {
  static_assert(std::is_trivial_v<T> && std::is_standard_layout_v<T>,
                "Registry value type must be primitive.");
  T data;
  DWORD dataLen = sizeof(data);
  DWORD type;
  LSTATUS status = ::RegQueryValueExW(key.get(), name.c_str(), nullptr, &type,
                                      reinterpret_cast<PBYTE>(&data), &dataLen);
  if (status == ERROR_FILE_NOT_FOUND) {
    return mozilla::Maybe<T>();
  }

  if (status != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(status);
  }

  if (type != expectedType) {
    return LAUNCHER_ERROR_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
  }

  return mozilla::Some(data);
}

static mozilla::LauncherResult<mozilla::UniquePtr<wchar_t[]>>
ReadRegistryValueString(const nsAutoRegKey& aKey, const std::wstring& aName) {
  mozilla::UniquePtr<wchar_t[]> buf;
  DWORD dataLen;
  LSTATUS status = ::RegGetValueW(aKey.get(), nullptr, aName.c_str(),
                                  RRF_RT_REG_SZ, nullptr, nullptr, &dataLen);
  if (status == ERROR_FILE_NOT_FOUND) {
    return buf;
  }

  if (status != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(status);
  }

  buf = mozilla::MakeUnique<wchar_t[]>(dataLen / sizeof(wchar_t));

  status = ::RegGetValueW(aKey.get(), nullptr, aName.c_str(), RRF_RT_REG_SZ,
                          nullptr, buf.get(), &dataLen);
  if (status != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(status);
  }

  return buf;
}

static mozilla::LauncherVoidResult WriteRegistryValueString(
    const nsAutoRegKey& aKey, const std::wstring& aName,
    const std::wstring& aValue) {
  DWORD dataBytes = (aValue.size() + 1) * sizeof(wchar_t);
  LSTATUS status = ::RegSetValueExW(
      aKey.get(), aName.c_str(), /*Reserved*/ 0, REG_SZ,
      reinterpret_cast<const BYTE*>(aValue.c_str()), dataBytes);
  if (status != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(status);
  }

  return mozilla::Ok();
}

template <typename T>
static mozilla::LauncherVoidResult WriteRegistryValueData(
    const nsAutoRegKey& key, const std::wstring& name, DWORD type, T data) {
  static_assert(std::is_trivial_v<T> && std::is_standard_layout_v<T>,
                "Registry value type must be primitive.");
  LSTATUS status =
      ::RegSetValueExW(key.get(), name.c_str(), 0, type,
                       reinterpret_cast<PBYTE>(&data), sizeof(data));
  if (status != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(status);
  }

  return mozilla::Ok();
}

static mozilla::LauncherResult<bool> DeleteRegistryValueData(
    const nsAutoRegKey& key, const std::wstring& name) {
  LSTATUS status = ::RegDeleteValueW(key, name.c_str());
  if (status == ERROR_FILE_NOT_FOUND) {
    return false;
  }

  if (status != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(status);
  }

  return true;
}

namespace mozilla {

const wchar_t LauncherRegistryInfo::kLauncherSubKeyPath[] =
    L"SOFTWARE\\" EXPAND_STRING_MACRO(MOZ_APP_VENDOR) L"\\" EXPAND_STRING_MACRO(
        MOZ_APP_BASENAME) L"\\Launcher";
const wchar_t LauncherRegistryInfo::kLauncherSuffix[] = L"|Launcher";
const wchar_t LauncherRegistryInfo::kBrowserSuffix[] = L"|Browser";
const wchar_t LauncherRegistryInfo::kImageTimestampSuffix[] = L"|Image";
const wchar_t LauncherRegistryInfo::kTelemetrySuffix[] = L"|Telemetry";
const wchar_t LauncherRegistryInfo::kBlocklistSuffix[] = L"|Blocklist";
const wchar_t LauncherRegistryInfo::kLauncherCrashTimestampSuffix[] =
    L"|LauncherCrashTime";

bool LauncherRegistryInfo::sAllowCommit = true;

LauncherResult<LauncherRegistryInfo::Disposition> LauncherRegistryInfo::Open() {
  if (!!mRegKey) {
    return Disposition::OpenedExisting;
  }

  DWORD disposition;
  HKEY rawKey;
  LSTATUS result = ::RegCreateKeyExW(
      HKEY_CURRENT_USER, kLauncherSubKeyPath, 0, nullptr,
      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &rawKey, &disposition);
  if (result != ERROR_SUCCESS) {
    return LAUNCHER_ERROR_FROM_WIN32(result);
  }

  mRegKey.own(rawKey);

  switch (disposition) {
    case REG_CREATED_NEW_KEY:
      return Disposition::CreatedNew;
    case REG_OPENED_EXISTING_KEY:
      return Disposition::OpenedExisting;
    default:
      break;
  }

  MOZ_ASSERT_UNREACHABLE("Invalid disposition from RegCreateKeyExW");
  return LAUNCHER_ERROR_GENERIC();
}

LauncherVoidResult LauncherRegistryInfo::ReflectPrefToRegistry(
    const bool aEnable) {
  LauncherResult<EnabledState> curEnabledState = IsEnabled();
  if (curEnabledState.isErr()) {
    return curEnabledState.propagateErr();
  }

  bool isCurrentlyEnabled =
      curEnabledState.inspect() != EnabledState::ForceDisabled;
  if (isCurrentlyEnabled == aEnable) {
    // Don't reflect to the registry unless the new enabled state is actually
    // changing with respect to the current enabled state.
    return Ok();
  }

  // Always delete the launcher timestamp
  LauncherResult<bool> clearedLauncherTimestamp = ClearLauncherStartTimestamp();
  MOZ_ASSERT(clearedLauncherTimestamp.isOk());
  if (clearedLauncherTimestamp.isErr()) {
    return clearedLauncherTimestamp.propagateErr();
  }

  // Allow commit when we enable the launcher, otherwise block.
  sAllowCommit = aEnable;

  if (!aEnable) {
    // Set the browser timestamp to 0 to indicate force-disabled
    return WriteBrowserStartTimestamp(0ULL);
  }

  // Otherwise we delete the browser timestamp to start over fresh
  LauncherResult<bool> clearedBrowserTimestamp = ClearBrowserStartTimestamp();
  MOZ_ASSERT(clearedBrowserTimestamp.isOk());
  if (clearedBrowserTimestamp.isErr()) {
    return clearedBrowserTimestamp.propagateErr();
  }

  return Ok();
}

LauncherVoidResult LauncherRegistryInfo::ReflectTelemetryPrefToRegistry(
    const bool aEnable) {
  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  return WriteRegistryValueData(mRegKey, ResolveTelemetryValueName(), REG_DWORD,
                                aEnable ? 1UL : 0UL);
}

LauncherResult<LauncherRegistryInfo::ProcessType> LauncherRegistryInfo::Check(
    const ProcessType aDesiredType, const CheckOption aOption) {
  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  LauncherResult<DWORD> ourImageTimestamp = GetCurrentImageTimestamp();
  if (ourImageTimestamp.isErr()) {
    return ourImageTimestamp.propagateErr();
  }

  LauncherResult<Maybe<DWORD>> savedImageTimestamp = GetSavedImageTimestamp();
  if (savedImageTimestamp.isErr()) {
    return savedImageTimestamp.propagateErr();
  }

  // If we don't have a saved timestamp, or we do but it doesn't match with
  // our current timestamp, clear previous values unless we're force-disabled.
  if (savedImageTimestamp.inspect().isNothing() ||
      savedImageTimestamp.inspect().value() != ourImageTimestamp.inspect()) {
    LauncherVoidResult clearResult = ClearStartTimestamps();
    if (clearResult.isErr()) {
      return clearResult.propagateErr();
    }

    LauncherVoidResult writeResult =
        WriteImageTimestamp(ourImageTimestamp.inspect());
    if (writeResult.isErr()) {
      return writeResult.propagateErr();
    }
  }

  // If we're going to be running as the browser process, or there is no
  // existing values to check, just write our timestamp and return.
  if (aDesiredType == ProcessType::Browser) {
    mBrowserTimestampToWrite = Some(QPCNowRaw());
    return ProcessType::Browser;
  }

  if (disposition.inspect() == Disposition::CreatedNew) {
    mLauncherTimestampToWrite = Some(QPCNowRaw());
    return ProcessType::Launcher;
  }

  if (disposition.inspect() != Disposition::OpenedExisting) {
    MOZ_ASSERT_UNREACHABLE("Invalid |disposition|");
    return LAUNCHER_ERROR_GENERIC();
  }

  LauncherResult<Maybe<uint64_t>> lastLauncherTimestampResult =
      GetLauncherStartTimestamp();
  if (lastLauncherTimestampResult.isErr()) {
    return lastLauncherTimestampResult.propagateErr();
  }

  LauncherResult<Maybe<uint64_t>> lastBrowserTimestampResult =
      GetBrowserStartTimestamp();
  if (lastBrowserTimestampResult.isErr()) {
    return lastBrowserTimestampResult.propagateErr();
  }

  const Maybe<uint64_t>& lastLauncherTimestamp =
      lastLauncherTimestampResult.inspect();
  const Maybe<uint64_t>& lastBrowserTimestamp =
      lastBrowserTimestampResult.inspect();

  ProcessType typeToRunAs = aDesiredType;

  // Check for force-disabled state first (browser timestamp = 0)
  if (lastBrowserTimestamp.isSome() && lastBrowserTimestamp.value() == 0ULL) {
    // By default, disable the launcher process.
    typeToRunAs = ProcessType::Browser;
    LauncherResult<Maybe<uint64_t>> crashTimestampResult =
        GetLauncherCrashTimestamp();
    if (crashTimestampResult.isOk() &&
        crashTimestampResult.inspect().isSome()) {
      uint64_t crashTimestamp = crashTimestampResult.inspect().value();

      FILETIME currentTime;
      ::GetSystemTimeAsFileTime(¤tTime);
      uint64_t currentTimestamp =
          (static_cast<uint64_t>(currentTime.dwHighDateTime) << 32) |
          currentTime.dwLowDateTime;

      bool clearForceDisabled =
          // This is nonsensical, either the clock is messed up or
          // something messed with the registry value. Clear the force-disabled
          // state.
          (crashTimestamp > currentTimestamp) ||
          // Check if 45 days have elapsed since crash.
          (currentTimestamp - crashTimestamp >= kCrashTimeoutInterval);
      if (clearForceDisabled) {
        // Clear the force-disabled state and crash timestamp
        LauncherResult<bool> clearedBrowserTimestamp =
            ClearBrowserStartTimestamp();
        LauncherResult<bool> clearedCrashTimestamp =
            ClearLauncherCrashTimestamp();

        if (clearedBrowserTimestamp.isOk() && clearedCrashTimestamp.isOk()) {
          // Re-enable launcher process
          sAllowCommit = true;
          typeToRunAs =
              aDesiredType;  // Allow the desired type (likely Launcher)
        }
      }
    }
  } else if (lastLauncherTimestamp.isSome() != lastBrowserTimestamp.isSome()) {
    // If we have a launcher timestamp but no browser timestamp (or vice versa),
    // that's bad because it is indicating that the browser can't run with
    // the launcher process.
    typeToRunAs = ProcessType::Browser;
  } else if (lastLauncherTimestamp.isSome()) {
    // if we have both timestamps, we want to ensure that the launcher timestamp
    // is earlier than the browser timestamp.
    if (aDesiredType == ProcessType::Launcher) {
      bool areTimestampsOk =
          lastLauncherTimestamp.value() < lastBrowserTimestamp.value();
      if (!areTimestampsOk) {
        typeToRunAs = ProcessType::Browser;
      }
    }
  } else {
    // If we have neither timestamp, then we should try running as suggested
    // by |aDesiredType|.
    // We shouldn't really have this scenario unless we're going to be running
    // as the launcher process.
    MOZ_ASSERT(typeToRunAs == ProcessType::Launcher);
    // No change to typeToRunAs
  }

  // Debugging setting that forces the desired type regardless of the various
  // tests that have been performed.
  if (aOption == CheckOption::Force) {
    typeToRunAs = aDesiredType;
  }

  switch (typeToRunAs) {
    case ProcessType::Browser:
      if (aDesiredType != typeToRunAs) {
        // We were hoping to run as the launcher, but some failure has caused
        // us to run as the browser. Set the browser timestamp to zero as an
        // indicator.
        mBrowserTimestampToWrite = Some(0ULL);
      } else {
        mBrowserTimestampToWrite = Some(QPCNowRaw());
      }
      break;
    case ProcessType::Launcher:
      mLauncherTimestampToWrite = Some(QPCNowRaw());
      break;
    default:
      MOZ_ASSERT_UNREACHABLE("Invalid |typeToRunAs|");
      return LAUNCHER_ERROR_GENERIC();
  }

  return typeToRunAs;
}

LauncherVoidResult LauncherRegistryInfo::DisableDueToFailure() {
  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  // Store the current time as crash timestamp
  FILETIME currentTime;
  ::GetSystemTimeAsFileTime(¤tTime);
  uint64_t crashTime =
      (static_cast<uint64_t>(currentTime.dwHighDateTime) << 32) |
      currentTime.dwLowDateTime;

  LauncherVoidResult crashTimestampResult =
      WriteLauncherCrashTimestamp(crashTime);
  if (crashTimestampResult.isErr()) {
    return crashTimestampResult.propagateErr();
  }

  LauncherVoidResult result = WriteBrowserStartTimestamp(0ULL);
  if (result.isOk()) {
    // Block commit when we disable the launcher.  It could be allowed
    // when the image timestamp is updated.
    sAllowCommit = false;
  }
  return result;
}

LauncherVoidResult LauncherRegistryInfo::Commit() {
  if (!sAllowCommit) {
    Abort();
    return Ok();
  }

  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  if (mLauncherTimestampToWrite.isSome()) {
    LauncherVoidResult writeResult =
        WriteLauncherStartTimestamp(mLauncherTimestampToWrite.value());
    if (writeResult.isErr()) {
      return writeResult.propagateErr();
    }
    mLauncherTimestampToWrite = Nothing();
  }

  if (mBrowserTimestampToWrite.isSome()) {
    LauncherVoidResult writeResult =
        WriteBrowserStartTimestamp(mBrowserTimestampToWrite.value());
    if (writeResult.isErr()) {
      return writeResult.propagateErr();
    }
    mBrowserTimestampToWrite = Nothing();
  }

  return Ok();
}

void LauncherRegistryInfo::Abort() {
  mLauncherTimestampToWrite = mBrowserTimestampToWrite = Nothing();
}

LauncherRegistryInfo::EnabledState LauncherRegistryInfo::GetEnabledState(
    const Maybe<uint64_t>& aLauncherTs, const Maybe<uint64_t>& aBrowserTs) {
  if (aBrowserTs.isSome()) {
    if (aLauncherTs.isSome()) {
      if (aLauncherTs.value() < aBrowserTs.value()) {
        // Both timestamps exist and the browser's timestamp is later.
        return EnabledState::Enabled;
      }
    } else if (aBrowserTs.value() == 0ULL) {
      // Only browser's timestamp exists and its value is 0.
      return EnabledState::ForceDisabled;
    }
  } else if (aLauncherTs.isNothing()) {
    // Neither timestamps exist.
    return EnabledState::Enabled;
  }

  // Everything else is FailDisabled.
  return EnabledState::FailDisabled;
}

LauncherResult<LauncherRegistryInfo::EnabledState>
LauncherRegistryInfo::IsEnabled() {
  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  LauncherResult<Maybe<uint64_t>> lastLauncherTimestamp =
      GetLauncherStartTimestamp();
  if (lastLauncherTimestamp.isErr()) {
    return lastLauncherTimestamp.propagateErr();
  }

  LauncherResult<Maybe<uint64_t>> lastBrowserTimestamp =
      GetBrowserStartTimestamp();
  if (lastBrowserTimestamp.isErr()) {
    return lastBrowserTimestamp.propagateErr();
  }

  return GetEnabledState(lastLauncherTimestamp.inspect(),
                         lastBrowserTimestamp.inspect());
}

LauncherResult<bool> LauncherRegistryInfo::IsTelemetryEnabled() {
  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  LauncherResult<Maybe<DWORD>> result = ReadRegistryValueData<DWORD>(
      mRegKey, ResolveTelemetryValueName(), REG_DWORD);
  if (result.isErr()) {
    return result.propagateErr();
  }

  if (result.inspect().isNothing()) {
    // Value does not exist, treat as false
    return false;
  }

  return result.inspect().value() != 0;
}

const std::wstring& LauncherRegistryInfo::ResolveLauncherValueName() {
  if (mLauncherValueName.empty()) {
    mLauncherValueName.assign(mBinPath);
    mLauncherValueName.append(kLauncherSuffix, std::size(kLauncherSuffix) - 1);
  }

  return mLauncherValueName;
}

const std::wstring& LauncherRegistryInfo::ResolveBrowserValueName() {
  if (mBrowserValueName.empty()) {
    mBrowserValueName.assign(mBinPath);
    mBrowserValueName.append(kBrowserSuffix, std::size(kBrowserSuffix) - 1);
  }

  return mBrowserValueName;
}

const std::wstring& LauncherRegistryInfo::ResolveImageTimestampValueName() {
  if (mImageValueName.empty()) {
    mImageValueName.assign(mBinPath);
    mImageValueName.append(kImageTimestampSuffix,
                           std::size(kImageTimestampSuffix) - 1);
  }

  return mImageValueName;
}

const std::wstring& LauncherRegistryInfo::ResolveTelemetryValueName() {
  if (mTelemetryValueName.empty()) {
    mTelemetryValueName.assign(mBinPath);
    mTelemetryValueName.append(kTelemetrySuffix,
                               std::size(kTelemetrySuffix) - 1);
  }

  return mTelemetryValueName;
}

const std::wstring& LauncherRegistryInfo::ResolveBlocklistValueName() {
  if (mBlocklistValueName.empty()) {
    mBlocklistValueName.assign(mBinPath);
    mBlocklistValueName.append(kBlocklistSuffix,
                               std::size(kBlocklistSuffix) - 1);
  }

  return mBlocklistValueName;
}

const std::wstring&
LauncherRegistryInfo::ResolveLauncherCrashTimestampValueName() {
  if (mLauncherCrashTimestampValueName.empty()) {
    mLauncherCrashTimestampValueName.assign(mBinPath);
    mLauncherCrashTimestampValueName.append(
        kLauncherCrashTimestampSuffix,
        std::size(kLauncherCrashTimestampSuffix) - 1);
  }

  return mLauncherCrashTimestampValueName;
}

LauncherVoidResult LauncherRegistryInfo::WriteLauncherStartTimestamp(
    uint64_t aValue) {
  return WriteRegistryValueData(mRegKey, ResolveLauncherValueName(), REG_QWORD,
                                aValue);
}

LauncherVoidResult LauncherRegistryInfo::WriteBrowserStartTimestamp(
    uint64_t aValue) {
  return WriteRegistryValueData(mRegKey, ResolveBrowserValueName(), REG_QWORD,
                                aValue);
}

LauncherVoidResult LauncherRegistryInfo::WriteImageTimestamp(DWORD aTimestamp) {
  return WriteRegistryValueData(mRegKey, ResolveImageTimestampValueName(),
                                REG_DWORD, aTimestamp);
}

LauncherResult<bool> LauncherRegistryInfo::ClearLauncherStartTimestamp() {
  return DeleteRegistryValueData(mRegKey, ResolveLauncherValueName());
}

LauncherResult<bool> LauncherRegistryInfo::ClearBrowserStartTimestamp() {
  return DeleteRegistryValueData(mRegKey, ResolveBrowserValueName());
}

LauncherVoidResult LauncherRegistryInfo::ClearStartTimestamps() {
  LauncherResult<EnabledState> enabled = IsEnabled();
  if (enabled.isOk() && enabled.inspect() == EnabledState::ForceDisabled) {
    // We don't clear anything when we're force disabled - we need to maintain
    // the current registry state in this case.
    return Ok();
  }

  LauncherResult<bool> clearedLauncherTimestamp = ClearLauncherStartTimestamp();
  if (clearedLauncherTimestamp.isErr()) {
    return clearedLauncherTimestamp.propagateErr();
  }

  LauncherResult<bool> clearedBrowserTimestamp = ClearBrowserStartTimestamp();
  if (clearedBrowserTimestamp.isErr()) {
    return clearedBrowserTimestamp.propagateErr();
  }

  // Also clear crash timestamp when resetting
  LauncherResult<bool> clearedCrashTimestamp = ClearLauncherCrashTimestamp();
  if (clearedCrashTimestamp.isErr()) {
    return clearedCrashTimestamp.propagateErr();
  }

  // Reset both timestamps to align with registry deletion
  mLauncherTimestampToWrite = mBrowserTimestampToWrite = Nothing();

  // Disablement is gone.  Let's allow commit.
  sAllowCommit = true;

  return Ok();
}

LauncherResult<Maybe<DWORD>> LauncherRegistryInfo::GetSavedImageTimestamp() {
  return ReadRegistryValueData<DWORD>(mRegKey, ResolveImageTimestampValueName(),
                                      REG_DWORD);
}

LauncherResult<Maybe<uint64_t>>
LauncherRegistryInfo::GetLauncherStartTimestamp() {
  return ReadRegistryValueData<uint64_t>(mRegKey, ResolveLauncherValueName(),
                                         REG_QWORD);
}

LauncherResult<Maybe<uint64_t>>
LauncherRegistryInfo::GetBrowserStartTimestamp() {
  return ReadRegistryValueData<uint64_t>(mRegKey, ResolveBrowserValueName(),
                                         REG_QWORD);
}

LauncherVoidResult LauncherRegistryInfo::WriteLauncherCrashTimestamp(
    uint64_t aValue) {
  return WriteRegistryValueData(
      mRegKey, ResolveLauncherCrashTimestampValueName(), REG_QWORD, aValue);
}

LauncherResult<Maybe<uint64_t>>
LauncherRegistryInfo::GetLauncherCrashTimestamp() {
  return ReadRegistryValueData<uint64_t>(
      mRegKey, ResolveLauncherCrashTimestampValueName(), REG_QWORD);
}

LauncherResult<bool> LauncherRegistryInfo::ClearLauncherCrashTimestamp() {
  return DeleteRegistryValueData(mRegKey,
                                 ResolveLauncherCrashTimestampValueName());
}

LauncherResult<std::wstring>
LauncherRegistryInfo::BuildDefaultBlocklistFilename() {
  // These flags are chosen to avoid I/O, see bug 1363398.
  const DWORD flags =
      KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_ALIAS;
  PWSTR rawPath = nullptr;
  HRESULT hr =
      ::SHGetKnownFolderPath(FOLDERID_RoamingAppData, flags, nullptr, &rawPath);
  if (FAILED(hr)) {
    ::CoTaskMemFree(rawPath);
    return LAUNCHER_ERROR_FROM_HRESULT(hr);
  }

  UniquePtr<wchar_t, CoTaskMemFreeDeleter> appDataPath(rawPath);
  std::wstring defaultBlocklistPath(appDataPath.get());

  UniquePtr<NS_tchar[]> hash;
  std::wstring binPathLower;
  binPathLower.reserve(mBinPath.size());
  std::transform(mBinPath.begin(), mBinPath.end(),
                 std::back_inserter(binPathLower), std::towlower);
  if (!::GetInstallHash(reinterpret_cast<const char16_t*>(binPathLower.c_str()),
                        hash)) {
    return LAUNCHER_ERROR_FROM_WIN32(ERROR_INVALID_DATA);
  }

  defaultBlocklistPath.append(
      L"\\" MOZ_APP_VENDOR L"\\" MOZ_APP_BASENAME L"\\blocklist-");
  defaultBlocklistPath.append(hash.get());

  return defaultBlocklistPath;
}

LauncherResult<std::wstring> LauncherRegistryInfo::GetBlocklistFileName() {
  LauncherResult<Disposition> disposition = Open();
  if (disposition.isErr()) {
    return disposition.propagateErr();
  }

  LauncherResult<UniquePtr<wchar_t[]>> readResult =
      ReadRegistryValueString(mRegKey, ResolveBlocklistValueName());
  if (readResult.isErr()) {
    return readResult.propagateErr();
  }

  if (readResult.inspect()) {
    UniquePtr<wchar_t[]> buf = readResult.unwrap();
    return std::wstring(buf.get());
  }

  LauncherResult<std::wstring> defaultBlocklistPath =
      BuildDefaultBlocklistFilename();
  if (defaultBlocklistPath.isErr()) {
    return defaultBlocklistPath.propagateErr();
  }

  LauncherVoidResult writeResult = WriteRegistryValueString(
      mRegKey, ResolveBlocklistValueName(), defaultBlocklistPath.inspect());
  if (writeResult.isErr()) {
    return writeResult.propagateErr();
  }

  return defaultBlocklistPath;
}

}  // namespace mozilla

Messung V0.5 in Prozent
C=93 H=100 G=96

¤ Dauer der Verarbeitung: 0.8 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142