winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Registry.h (9722B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include <wil/resource.h>
      5 
      6 #include <optional>
      7 #include <string>
      8 #include <string_view>
      9 #include <vector>
     10 
     11 #define AICLI_REGISTRY_UTF16_FLAG 0x08000000
     12 
     13 namespace AppInstaller::Registry
     14 {
     15     namespace details
     16     {
     17         template<DWORD>
     18         constexpr bool dependent_false = false;
     19 
     20         template <DWORD Type>
     21         struct ValueTypeSpecifics
     22         {
     23             using value_t = void;
     24 
     25             static value_t Convert(const std::vector<BYTE>& data)
     26             {
     27                 static_assert(dependent_false<Type>, "No Type specific override has been supplied");
     28             }
     29         };
     30 
     31         template <>
     32         struct ValueTypeSpecifics<REG_NONE>
     33         {
     34             using value_t = std::vector<BYTE>;
     35             static value_t Convert(const std::vector<BYTE>& data);
     36         };
     37 
     38         template <>
     39         struct ValueTypeSpecifics<REG_SZ>
     40         {
     41             using value_t = std::string;
     42             static value_t Convert(const std::vector<BYTE>& data);
     43         };
     44 
     45         template <>
     46         struct ValueTypeSpecifics<REG_SZ | AICLI_REGISTRY_UTF16_FLAG>
     47         {
     48             using value_t = std::wstring;
     49             static value_t Convert(const std::vector<BYTE>& data);
     50         };
     51 
     52         template <>
     53         struct ValueTypeSpecifics<REG_EXPAND_SZ>
     54         {
     55             using value_t = std::string;
     56             static value_t Convert(const std::vector<BYTE>& data);
     57         };
     58 
     59         template <>
     60         struct ValueTypeSpecifics<REG_EXPAND_SZ | AICLI_REGISTRY_UTF16_FLAG>
     61         {
     62             using value_t = std::wstring;
     63             static value_t Convert(const std::vector<BYTE>& data);
     64         };
     65 
     66         template <>
     67         struct ValueTypeSpecifics<REG_BINARY>
     68         {
     69             using value_t = std::vector<BYTE>;
     70             static value_t Convert(const std::vector<BYTE>& data);
     71         };
     72 
     73         template <>
     74         struct ValueTypeSpecifics<REG_DWORD_LITTLE_ENDIAN>
     75         {
     76             using value_t = uint32_t;
     77             static value_t Convert(const std::vector<BYTE>& data);
     78         };
     79     }
     80 
     81     struct Key;
     82     struct ValueList;
     83 
     84     // A registry value.
     85     struct Value
     86     {
     87         friend Key;
     88         friend ValueList;
     89 
     90         // The type of data stored in the Value.
     91         enum class Type : DWORD
     92         {
     93             None = REG_NONE,
     94             String = REG_SZ,
     95             UTF16Flag = AICLI_REGISTRY_UTF16_FLAG,
     96             UTF16String = REG_SZ | UTF16Flag,
     97             ExpandString = REG_EXPAND_SZ,
     98             UTF16ExpandString = REG_EXPAND_SZ | UTF16Flag,
     99             Binary = REG_BINARY,
    100             DWord = REG_DWORD,
    101             DWordLittleEndian = REG_DWORD_LITTLE_ENDIAN,
    102             DWordBigEndian = REG_DWORD_BIG_ENDIAN,
    103             MultiString = REG_MULTI_SZ,
    104             QWord = REG_QWORD,
    105             QWordLittleEndian = REG_QWORD_LITTLE_ENDIAN,
    106         };
    107 
    108         Type GetType() const { return m_type; }
    109 
    110         template <Type T>
    111         typename details::ValueTypeSpecifics<static_cast<DWORD>(T)>::value_t GetValue() const
    112         {
    113             auto value = TryGetValue<T>();
    114             if (!value.has_value())
    115             {
    116                 THROW_HR(E_INVALIDARG);
    117             }
    118 
    119             return std::move(value.value());
    120         }
    121 
    122         template <Type T>
    123         typename std::optional<typename details::ValueTypeSpecifics<static_cast<DWORD>(T)>::value_t> TryGetValue() const
    124         {
    125             if (HasCompatibleType(T))
    126             {
    127                 return details::ValueTypeSpecifics<static_cast<DWORD>(T)>::Convert(m_data);
    128             }
    129             else
    130             {
    131                 return std::nullopt;
    132             }
    133         }
    134 
    135     private:
    136         Value(DWORD type, std::vector<BYTE>&& data);
    137 
    138         bool HasCompatibleType(Type type) const;
    139 
    140         Type m_type;
    141         std::vector<BYTE> m_data;
    142     };
    143 
    144     // Value iteration
    145     struct ValueList
    146     {
    147         friend Key;
    148 
    149         struct const_iterator;
    150 
    151         struct ValueRef
    152         {
    153             friend const_iterator;
    154 
    155             // Gets the name of the value.
    156             std::string Name() const;
    157 
    158             // Gets the actual value of the value.
    159             // The optional allows for the potential race with the value being removed.
    160             std::optional<Value> Value() const;
    161 
    162         private:
    163             ValueRef(wil::shared_hkey key, std::wstring&& valueName);
    164 
    165             wil::shared_hkey m_key;
    166             std::wstring m_valueName;
    167         };
    168 
    169         struct const_iterator
    170         {
    171             friend ValueList;
    172 
    173             const_iterator& operator++();
    174             const_iterator operator++(int);
    175 
    176             bool operator==(const const_iterator& other) const;
    177             bool operator!=(const const_iterator& other) const;
    178 
    179             const ValueRef& operator*() const;
    180             const ValueRef* operator->() const;
    181 
    182         private:
    183             // Create an iterator
    184             const_iterator(const wil::shared_hkey& key, DWORD index = 0);
    185 
    186             // Create an iterator for end
    187             const_iterator() = default;
    188 
    189             void GetValue();
    190 
    191             // An empty handle represents the end iterator.
    192             wil::shared_hkey m_key;
    193             DWORD m_index = 0;
    194             std::optional<ValueRef> m_value;
    195         };
    196 
    197         const_iterator begin() const;
    198         const_iterator end() const;
    199 
    200     private:
    201         ValueList(wil::shared_hkey key);
    202 
    203         wil::shared_hkey m_key;
    204     };
    205 
    206     // A registry key.
    207     struct Key
    208     {
    209         Key() = default;
    210         Key(HKEY key);
    211         Key(HKEY key, std::string_view subKey, DWORD options = 0, REGSAM access = KEY_READ);
    212         Key(HKEY key, const std::wstring& subKey, DWORD options = 0, REGSAM access = KEY_READ);
    213 
    214         // --== Sub-Key iteration ==--
    215         struct const_iterator;
    216 
    217         struct SubKeyRef
    218         {
    219             friend const_iterator;
    220 
    221             // Gets the name of the subkey.
    222             std::string Name() const;
    223 
    224             // Opens the subkey.
    225             Key Open() const;
    226 
    227             operator bool() const { return m_parentKey.operator bool(); }
    228 
    229         private:
    230             // For a valid iterator
    231             SubKeyRef(const wil::shared_hkey& key, REGSAM access);
    232 
    233             // For the end iterator
    234             SubKeyRef() = default;
    235 
    236             // Enumerates the subkey of m_parentKey at the given index.
    237             void Enum(DWORD index);
    238 
    239             wil::shared_hkey m_parentKey;
    240             REGSAM m_access = KEY_READ;
    241             std::wstring m_subKeyName;
    242         };
    243 
    244         struct const_iterator
    245         {
    246             friend Key;
    247 
    248             const_iterator& operator++();
    249             const_iterator operator++(int);
    250 
    251             bool operator==(const const_iterator& other) const;
    252             bool operator!=(const const_iterator& other) const;
    253 
    254             const SubKeyRef& operator*() const;
    255             const SubKeyRef* operator->() const;
    256 
    257         private:
    258             // Create an iterator for begin
    259             const_iterator(const wil::shared_hkey& key, REGSAM access);
    260 
    261             // Create an iterator for end
    262             const_iterator() = default;
    263 
    264             DWORD m_index = 0;
    265             SubKeyRef m_subkey;
    266         };
    267 
    268         const_iterator begin() const;
    269         const_iterator end() const;
    270 
    271         std::optional<Value> operator[](std::string_view name) const;
    272         std::optional<Value> operator[](const std::wstring& name) const;
    273 
    274         std::optional<Key> SubKey(std::string_view name, DWORD options = 0) const;
    275         std::optional<Key> SubKey(const std::wstring& name, DWORD options = 0) const;
    276 
    277         // Set registry values.
    278         void SetValue(const std::wstring& name, const std::wstring& value, DWORD type = REG_SZ) const;
    279         void SetValue(const std::wstring& name, const std::vector<BYTE>& value, DWORD type = REG_BINARY) const;
    280         void SetValue(const std::wstring& name, DWORD value) const;
    281 
    282         ValueList Values() const;
    283 
    284         operator bool() const { return m_key.operator bool(); }
    285         operator HKEY() const { return m_key.get(); }
    286 
    287         // Open a Key; will return an empty Key if the subkey does not exist.
    288         static Key OpenIfExists(HKEY key, std::string_view subKey = {}, DWORD options = 0, REGSAM access = KEY_READ);
    289         static Key OpenIfExists(HKEY key, const std::wstring& subKey = {}, DWORD options = 0, REGSAM access = KEY_READ);
    290 
    291         // Creates a new Key or returns one if it already existed. 
    292         static Key Create(HKEY key, std::string_view subkey = {}, DWORD options = REG_OPTION_NON_VOLATILE, REGSAM access = KEY_ALL_ACCESS);
    293         static Key Create(HKEY key, const std::wstring& subKey = {}, DWORD options = REG_OPTION_NON_VOLATILE, REGSAM access = KEY_ALL_ACCESS);
    294 
    295         // Delete a key
    296         static bool Delete(HKEY key, std::string_view subkey, DWORD samDesired);
    297         static bool Delete(HKEY key, const std::wstring& subKey, DWORD samDesired);
    298 
    299     private:
    300         // When ignoring error, returns whether the key existed
    301         bool Initialize(HKEY key, const std::wstring& subKey, DWORD options, REGSAM access, bool ignoreErrorIfDoesNotExist);
    302 
    303         // Returns whether the key was created successfully.
    304         bool CreateAndOpen(HKEY key, const std::wstring& subKey, DWORD options, REGSAM access);
    305 
    306         wil::shared_hkey m_key;
    307         REGSAM m_access = KEY_READ;
    308     };
    309 }