Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/widget/windows/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  WinRegistry.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sts=2 sw=2 et cin: */
/* 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 http://mozilla.org/MPL/2.0/. */


#include "WinRegistry.h"
#include "nsThreadUtils.h"

namespace mozilla::widget::WinRegistry {

Key::Key(HKEY aParent, const nsString& aPath, KeyMode aMode, CreateFlag) {
  MOZ_ASSERT(aParent);
  DWORD disposition;
  ::RegCreateKeyExW(aParent, aPath.get(), 0, nullptr, REG_OPTION_NON_VOLATILE,
                    (REGSAM)aMode, nullptr, &mKey, &disposition);
}

Key::Key(HKEY aParent, const nsString& aPath, KeyMode aMode) {
  MOZ_ASSERT(aParent);
  ::RegOpenKeyExW(aParent, aPath.get(), 0, (REGSAM)aMode, &mKey);
}

uint32_t Key::GetChildCount() const {
  MOZ_ASSERT(mKey);
  DWORD result = 0;
  ::RegQueryInfoKeyW(mKey, nullptr, nullptr, nullptr, &result, nullptr, nullptr,
                     nullptr, nullptr, nullptr, nullptr, nullptr);
  return result;
}

bool Key::GetChildName(uint32_t aIndex, nsAString& aResult) const {
  MOZ_ASSERT(mKey);
  FILETIME lastWritten;

  wchar_t nameBuf[kMaxKeyNameLen + 1];
  DWORD nameLen = std::size(nameBuf);

  LONG rv = RegEnumKeyExW(mKey, aIndex, nameBuf, &nameLen, nullptr, nullptr,
                          nullptr, &lastWritten);
  if (rv != ERROR_SUCCESS) {
    return false;
  }
  aResult.Assign(nameBuf, nameLen);
  return true;
}

bool Key::RemoveChildKey(const nsString& aName) const {
  MOZ_ASSERT(mKey);
  return SUCCEEDED(RegDeleteKeyW(mKey, aName.get()));
}

uint32_t Key::GetValueCount() const {
  MOZ_ASSERT(mKey);
  DWORD result = 0;
  ::RegQueryInfoKeyW(mKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                     &result, nullptr, nullptr, nullptr, nullptr);
  return result;
}

bool Key::GetValueName(uint32_t aIndex, nsAString& aResult) const {
  MOZ_ASSERT(mKey);
  wchar_t nameBuf[kMaxValueNameLen + 1];
  DWORD nameLen = std::size(nameBuf);

  LONG rv = RegEnumValueW(mKey, aIndex, nameBuf, &nameLen, nullptr, nullptr,
                          nullptr, nullptr);
  if (rv != ERROR_SUCCESS) {
    return false;
  }
  aResult.Assign(nameBuf, nameLen);
  return true;
}

ValueType Key::GetValueType(const nsString& aName) const {
  MOZ_ASSERT(mKey);
  DWORD result;
  LONG rv =
      RegQueryValueExW(mKey, aName.get(), nullptr, &result, nullptr, nullptr);
  return SUCCEEDED(rv) ? ValueType(result) : ValueType::None;
}

bool Key::RemoveValue(const nsString& aName) const {
  MOZ_ASSERT(mKey);
  return SUCCEEDED(RegDeleteValueW(mKey, aName.get()));
}

Maybe<uint32_t> Key::GetValueAsDword(const nsString& aName) const {
  MOZ_ASSERT(mKey);
  DWORD type;
  DWORD value = 0;
  DWORD size = sizeof(DWORD);
  HRESULT rv = RegQueryValueExW(mKey, aName.get(), nullptr, &type,
                                (LPBYTE)&value, &size);
  if (FAILED(rv) || type != REG_DWORD) {
    return Nothing();
  }
  return Some(value);
}

bool Key::WriteValueAsDword(const nsString& aName, uint32_t aValue) {
  MOZ_ASSERT(mKey);
  return SUCCEEDED(RegSetValueExW(mKey, aName.get(), 0, REG_DWORD,
                                  (const BYTE*)&aValue, sizeof(aValue)));
}

Maybe<uint64_t> Key::GetValueAsQword(const nsString& aName) const {
  MOZ_ASSERT(mKey);
  DWORD type;
  uint64_t value = 0;
  DWORD size = sizeof(uint64_t);
  HRESULT rv = RegQueryValueExW(mKey, aName.get(), nullptr, &type,
                                (LPBYTE)&value, &size);
  if (FAILED(rv) || type != REG_QWORD) {
    return Nothing();
  }
  return Some(value);
}

bool Key::WriteValueAsQword(const nsString& aName, uint64_t aValue) {
  MOZ_ASSERT(mKey);
  return SUCCEEDED(RegSetValueExW(mKey, aName.get(), 0, REG_QWORD,
                                  (const BYTE*)&aValue, sizeof(aValue)));
}

bool Key::GetValueAsBinary(const nsString& aName,
                           nsTArray<uint8_t>& aResult) const {
  MOZ_ASSERT(mKey);
  DWORD type;
  DWORD size;
  LONG rv = RegQueryValueExW(mKey, aName.get(), nullptr, &type, nullptr, &size);
  if (FAILED(rv) || type != REG_BINARY) {
    return false;
  }
  if (!aResult.SetLength(size, fallible)) {
    return false;
  }
  rv = RegQueryValueExW(mKey, aName.get(), nullptr, nullptr, aResult.Elements(),
                        &size);
  return SUCCEEDED(rv);
}

Maybe<nsTArray<uint8_t>> Key::GetValueAsBinary(const nsString& aName) const {
  nsTArray<uint8_t> value;
  Maybe<nsTArray<uint8_t>> result;
  if (GetValueAsBinary(aName, value)) {
    result.emplace(std::move(value));
  }
  return result;
}

bool Key::WriteValueAsBinary(const nsString& aName,
                             Span<const uint8_t> aValue) {
  MOZ_ASSERT(mKey);
  return SUCCEEDED(RegSetValueExW(mKey, aName.get(), 0, REG_BINARY,
                                  (const BYTE*)aValue.data(), aValue.size()));
}

static bool IsStringType(DWORD aType, StringFlags aFlags) {
  switch (aType) {
    case REG_SZ:
      return bool(aFlags & StringFlags::Sz);
    case REG_EXPAND_SZ:
      return bool(aFlags & StringFlags::ExpandSz);
    case REG_MULTI_SZ:
      return bool(aFlags & StringFlags::LegacyMultiSz);
    default:
      return false;
  }
}

bool Key::GetValueAsString(const nsString& aName, nsString& aResult,
                           StringFlags aFlags) const {
  MOZ_ASSERT(mKey);
  DWORD type;
  DWORD size;
  LONG rv = RegQueryValueExW(mKey, aName.get(), nullptr, &type, nullptr, &size);
  if (FAILED(rv) || !IsStringType(type, aFlags)) {
    return false;
  }
  if (!size) {
    aResult.Truncate();
    return true;
  }
  // The buffer size must be a multiple of 2.
  if (NS_WARN_IF(size % 2 != 0)) {
    return false;
  }
  size_t resultLen = size / 2;
  {
    auto handleOrError =
        aResult.BulkWrite(resultLen, 0, /* aAllowShrinking = */ false);
    if (NS_WARN_IF(handleOrError.isErr())) {
      return false;
    }
    auto handle = handleOrError.unwrap();
    auto len = GetValueAsString(aName, {handle.Elements(), handle.Length() + 1},
                                aFlags & ~StringFlags::ExpandEnvironment);
    if (NS_WARN_IF(!len)) {
      return false;
    }
    handle.Finish(*len, /* aAllowShrinking = */ false);
    if (*len && !aResult.CharAt(*len - 1)) {
      // The string passed to us had a null terminator in the final
      // position.
      aResult.Truncate(*len - 1);
    }
  }
  if (type == REG_EXPAND_SZ && (aFlags & StringFlags::ExpandEnvironment)) {
    resultLen = ExpandEnvironmentStringsW(aResult.get(), nullptr, 0);
    if (resultLen > 1) {
      nsString expandedResult;
      // |resultLen| includes the terminating null character
      resultLen--;
      if (!expandedResult.SetLength(resultLen, fallible)) {
        return false;
      }
      resultLen = ExpandEnvironmentStringsW(aResult.get(), expandedResult.get(),
                                            resultLen + 1);
      if (resultLen <= 0) {
        return false;
      }
      aResult = std::move(expandedResult);
    } else if (resultLen == 1) {
      // It apparently expands to nothing (just a null terminator).
      resultLen = 0;
      aResult.Truncate();
    }
  }
  return true;
}

Maybe<nsString> Key::GetValueAsString(const nsString& aName,
                                      StringFlags aFlags) const {
  nsString value;
  Maybe<nsString> result;
  if (GetValueAsString(aName, value, aFlags)) {
    result.emplace(std::move(value));
  }
  return result;
}

Maybe<uint32_t> Key::GetValueAsString(const nsString& aName,
                                      Span<char16_t> aBuffer,
                                      StringFlags aFlags) const {
  MOZ_ASSERT(mKey);
  MOZ_ASSERT(aBuffer.Length(), "Empty buffer?");
  MOZ_ASSERT(!(aFlags & StringFlags::ExpandEnvironment),
             "Environment expansion not performed on a single buffer");

  DWORD size = aBuffer.LengthBytes();
  DWORD type;
  HRESULT rv = RegQueryValueExW(mKey, aName.get(), nullptr, &type,
                                (LPBYTE)aBuffer.data(), &size);
  if (FAILED(rv)) {
    return Nothing();
  }
  if (!IsStringType(type, aFlags)) {
    return Nothing();
  }
  uint32_t len = size ? size / sizeof(char16_t) - 1 : 0;
  aBuffer[len] = 0;
  return Some(len);
}

KeyWatcher::KeyWatcher(Key&& aKey,
                       nsISerialEventTarget* aTargetSerialEventTarget,
                       Callback&& aCallback)
    : mKey(std::move(aKey)),
      mEventTarget(aTargetSerialEventTarget),
      mCallback(std::move(aCallback)) {
  MOZ_ASSERT(mKey);
  MOZ_ASSERT(mEventTarget);
  MOZ_ASSERT(mCallback);
  mEvent = CreateEvent(nullptr, /* bManualReset = */ FALSE,
                       /* bInitialState = */ FALSE, nullptr);
  if (NS_WARN_IF(!mEvent)) {
    return;
  }

  if (NS_WARN_IF(!Register())) {
    return;
  }

  // The callback only dispatches to the relevant event target, so we can use
  // WT_EXECUTEINWAITTHREAD.
  RegisterWaitForSingleObject(&mWaitObject, mEvent, WatchCallback, this,
                              INFINITE, WT_EXECUTEINWAITTHREAD);
}

void KeyWatcher::WatchCallback(void* aContext, BOOLEAN) {
  auto* watcher = static_cast<KeyWatcher*>(aContext);
  watcher->Register();
  watcher->mEventTarget->Dispatch(
      NS_NewRunnableFunction("KeyWatcher callback", watcher->mCallback));
}

// As per the documentation in:
// https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regnotifychangekeyvalue
//
// This function detects a single change. After the caller receives a
// notification event, it should call the function again to receive the next
// notification.
bool KeyWatcher::Register() {
  MOZ_ASSERT(mEvent);
  DWORD flags = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES |
                REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY |
                REG_NOTIFY_THREAD_AGNOSTIC;
  HRESULT rv =
      RegNotifyChangeKeyValue(mKey.RawKey(), /* bWatchSubtree = */ TRUE, flags,
                              mEvent, /* fAsynchronous = */ TRUE);
  return !NS_WARN_IF(FAILED(rv));
}

KeyWatcher::~KeyWatcher() {
  if (mWaitObject) {
    UnregisterWait(mWaitObject);
    CloseHandle(mWaitObject);
  }
  if (mEvent) {
    CloseHandle(mEvent);
  }
}

}  // namespace mozilla::widget::WinRegistry

100%


¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

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 ist noch experimentell.