DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d1ed7de67f5a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// All Rights Reserved.

#ifndef BASE_REGISTRY_H__
#define BASE_REGISTRY_H__

#include <windows.h>
#include <tchar.h>
#include <shlwapi.h>
#include <string>

// The shared file uses a bunch of header files that define types that we don't.
// To avoid changing much code from the standard version, and also to avoid
// polluting our namespace with extra types we don't want, we define these types
// here with the preprocessor and undefine them at the end of the file.
#define tchar TCHAR
#define CTP const tchar*
#define tstr std::basic_string<tchar>

// RegKey
// Utility class to read from and manipulate the registry.
// Registry vocabulary primer: a "key" is like a folder, in which there
// are "values", which are <name,data> pairs, with an associated data type.

class RegKey {
 public:
  RegKey(HKEY rootkey = NULL, CTP subkey = NULL, REGSAM access = KEY_READ);
    // start there

  ~RegKey() { this->Close(); }

  bool Create(HKEY rootkey, CTP subkey, REGSAM access = KEY_READ);

  bool CreateWithDisposition(HKEY rootkey, CTP subkey, DWORD* disposition,
                             REGSAM access = KEY_READ);

  bool Open(HKEY rootkey, CTP subkey, REGSAM access = KEY_READ);

  // Create a subkey (or open if exists)
  bool CreateKey(CTP name, REGSAM access);

  // Open a subkey
  bool OpenKey(CTP name, REGSAM access);

  // all done, eh?
  void Close();

  DWORD ValueCount();  // Count of the number of value extant

  bool ReadName(int index, tstr* name);  // Determine the Nth value's name

  // True while the key is valid
  bool Valid() const { return NULL != key_; }

  // Kill key and everything that liveth below it; please be careful out there
  bool DeleteKey(CTP name);

  // Delete a single value within the key
  bool DeleteValue(CTP name);

  bool ValueExists(CTP name);
  bool ReadValue(CTP name, void * data, DWORD * dsize, DWORD * dtype = NULL);
  bool ReadValue(CTP name, tstr * value);
  bool ReadValueDW(CTP name, DWORD * value);  // Named to differ from tstr*

  bool WriteValue(CTP name, const void * data, DWORD dsize,
                  DWORD dtype = REG_BINARY);
  bool WriteValue(CTP name, CTP value);
  bool WriteValue(CTP name, DWORD value);

  // StartWatching()
  //   Start watching the key to see if any of its values have changed.
  //   The key must have been opened with the KEY_NOTIFY access
  //   privelege.
  bool StartWatching();

  // HasChanged()
  //   If StartWatching hasn't been called, always returns false.
  //   Otherwise, returns true if anything under the key has changed.
  //   This can't be const because the watch_event_ may be refreshed.
  bool HasChanged();

  // StopWatching()
  //   Will automatically be called by destructor if not manually called
  //   beforehand.  Returns true if it was watching, false otherwise.
  bool StopWatching();

  inline bool IsWatching() const { return watch_event_ != 0; }
  HANDLE watch_event() const { return watch_event_; }
  HKEY Handle() const { return key_; }

 private:
  HKEY  key_;    // the registry key being iterated
  HANDLE watch_event_;
};


// Standalone registry functions -- sorta deprecated, they now map to
// using RegKey


// Add a raw data to the registry -- you can pass NULL for the data if
// you just want to create a key
inline bool AddToRegistry(HKEY root_key, CTP key, CTP value_name,
                          void const * data, DWORD dsize,
                          DWORD dtype = REG_BINARY) {
  return RegKey(root_key, key, KEY_WRITE).WriteValue(value_name, data, dsize,
                                                     dtype);
}

// Convenience routine to add a string value to the registry
inline bool AddToRegistry(HKEY root_key, CTP key, CTP value_name, CTP value) {
  return AddToRegistry(root_key, key, value_name, value,
                       sizeof(*value) * (lstrlen(value) + 1), REG_SZ);
}

// Read raw data from the registry -- pass something as the dtype
// parameter if you care to learn what type the value was stored as
inline bool ReadFromRegistry(HKEY root_key, CTP key, CTP value_name,
                             void* data, DWORD* dsize, DWORD* dtype = NULL) {
  return RegKey(root_key, key).ReadValue(value_name, data, dsize, dtype);
}


// Delete a value or a key from the registry
inline bool DeleteFromRegistry(HKEY root_key, CTP subkey, CTP value_name) {
  if (value_name)
    return ERROR_SUCCESS == ::SHDeleteValue(root_key, subkey, value_name);
  else
    return ERROR_SUCCESS == ::SHDeleteKey(root_key, subkey);
}



// delete a key and all subkeys from the registry
inline bool DeleteKeyFromRegistry(HKEY root_key, CTP key_path, CTP key_name) {
  RegKey key;
  return key.Open(root_key, key_path, KEY_WRITE)
      && key.DeleteKey(key_name);
}


// Iterates the entries found in a particular folder on the registry.
// For this application I happen to know I wont need data size larger
// than MAX_PATH, but in real life this wouldn't neccessarily be
// adequate.
class RegistryValueIterator {
 public:
  // Specify a key in construction
  RegistryValueIterator(HKEY root_key, LPCTSTR folder_key);

  ~RegistryValueIterator();

  DWORD ValueCount() const;  // count of the number of subkeys extant

  bool Valid() const;  // true while the iterator is valid

  void operator++();  // advance to the next entry in the folder

  // The pointers returned by these functions are statics owned by the
  // Name and Value functions
  CTP Name() const { return name_; }
  CTP Value() const { return value_; }
  DWORD ValueSize() const { return value_size_; }
  DWORD Type() const { return type_; }

  int Index() const { return index_; }

 private:
  bool Read();   // read in the current values

  HKEY  key_;    // the registry key being iterated
  int   index_;  // current index of the iteration

  // Current values
  TCHAR name_[MAX_PATH];
  TCHAR value_[MAX_PATH];
  DWORD value_size_;
  DWORD type_;
};


class RegistryKeyIterator {
 public:
  // Specify a parent key in construction
  RegistryKeyIterator(HKEY root_key, LPCTSTR folder_key);

  ~RegistryKeyIterator();

  DWORD SubkeyCount() const;  // count of the number of subkeys extant

  bool Valid() const;  // true while the iterator is valid

  void operator++();  // advance to the next entry in the folder

  // The pointer returned by Name() is a static owned by the function
  CTP Name() const { return name_; }

  int Index() const { return index_; }

 private:
  bool Read();   // read in the current values

  HKEY  key_;    // the registry key being iterated
  int   index_;  // current index of the iteration

  // Current values
  TCHAR name_[MAX_PATH];
};


// Register a COM object with the most usual properties.
bool RegisterCOMServer(const tchar* guid, const tchar* name,
                       const tchar* modulepath);
bool RegisterCOMServer(const tchar* guid, const tchar* name, HINSTANCE module);
bool UnregisterCOMServer(const tchar* guid);

// undo the local types defined above
#undef tchar
#undef CTP
#undef tstr

#endif  // BASE_REGISTRY_H__