michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // All Rights Reserved. michael@0: michael@0: #ifndef BASE_REGISTRY_H__ michael@0: #define BASE_REGISTRY_H__ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: // The shared file uses a bunch of header files that define types that we don't. michael@0: // To avoid changing much code from the standard version, and also to avoid michael@0: // polluting our namespace with extra types we don't want, we define these types michael@0: // here with the preprocessor and undefine them at the end of the file. michael@0: #define tchar TCHAR michael@0: #define CTP const tchar* michael@0: #define tstr std::basic_string michael@0: michael@0: // RegKey michael@0: // Utility class to read from and manipulate the registry. michael@0: // Registry vocabulary primer: a "key" is like a folder, in which there michael@0: // are "values", which are pairs, with an associated data type. michael@0: michael@0: class RegKey { michael@0: public: michael@0: RegKey(HKEY rootkey = NULL, CTP subkey = NULL, REGSAM access = KEY_READ); michael@0: // start there michael@0: michael@0: ~RegKey() { this->Close(); } michael@0: michael@0: bool Create(HKEY rootkey, CTP subkey, REGSAM access = KEY_READ); michael@0: michael@0: bool CreateWithDisposition(HKEY rootkey, CTP subkey, DWORD* disposition, michael@0: REGSAM access = KEY_READ); michael@0: michael@0: bool Open(HKEY rootkey, CTP subkey, REGSAM access = KEY_READ); michael@0: michael@0: // Create a subkey (or open if exists) michael@0: bool CreateKey(CTP name, REGSAM access); michael@0: michael@0: // Open a subkey michael@0: bool OpenKey(CTP name, REGSAM access); michael@0: michael@0: // all done, eh? michael@0: void Close(); michael@0: michael@0: DWORD ValueCount(); // Count of the number of value extant michael@0: michael@0: bool ReadName(int index, tstr* name); // Determine the Nth value's name michael@0: michael@0: // True while the key is valid michael@0: bool Valid() const { return NULL != key_; } michael@0: michael@0: // Kill key and everything that liveth below it; please be careful out there michael@0: bool DeleteKey(CTP name); michael@0: michael@0: // Delete a single value within the key michael@0: bool DeleteValue(CTP name); michael@0: michael@0: bool ValueExists(CTP name); michael@0: bool ReadValue(CTP name, void * data, DWORD * dsize, DWORD * dtype = NULL); michael@0: bool ReadValue(CTP name, tstr * value); michael@0: bool ReadValueDW(CTP name, DWORD * value); // Named to differ from tstr* michael@0: michael@0: bool WriteValue(CTP name, const void * data, DWORD dsize, michael@0: DWORD dtype = REG_BINARY); michael@0: bool WriteValue(CTP name, CTP value); michael@0: bool WriteValue(CTP name, DWORD value); michael@0: michael@0: // StartWatching() michael@0: // Start watching the key to see if any of its values have changed. michael@0: // The key must have been opened with the KEY_NOTIFY access michael@0: // privelege. michael@0: bool StartWatching(); michael@0: michael@0: // HasChanged() michael@0: // If StartWatching hasn't been called, always returns false. michael@0: // Otherwise, returns true if anything under the key has changed. michael@0: // This can't be const because the watch_event_ may be refreshed. michael@0: bool HasChanged(); michael@0: michael@0: // StopWatching() michael@0: // Will automatically be called by destructor if not manually called michael@0: // beforehand. Returns true if it was watching, false otherwise. michael@0: bool StopWatching(); michael@0: michael@0: inline bool IsWatching() const { return watch_event_ != 0; } michael@0: HANDLE watch_event() const { return watch_event_; } michael@0: HKEY Handle() const { return key_; } michael@0: michael@0: private: michael@0: HKEY key_; // the registry key being iterated michael@0: HANDLE watch_event_; michael@0: }; michael@0: michael@0: michael@0: // Standalone registry functions -- sorta deprecated, they now map to michael@0: // using RegKey michael@0: michael@0: michael@0: // Add a raw data to the registry -- you can pass NULL for the data if michael@0: // you just want to create a key michael@0: inline bool AddToRegistry(HKEY root_key, CTP key, CTP value_name, michael@0: void const * data, DWORD dsize, michael@0: DWORD dtype = REG_BINARY) { michael@0: return RegKey(root_key, key, KEY_WRITE).WriteValue(value_name, data, dsize, michael@0: dtype); michael@0: } michael@0: michael@0: // Convenience routine to add a string value to the registry michael@0: inline bool AddToRegistry(HKEY root_key, CTP key, CTP value_name, CTP value) { michael@0: return AddToRegistry(root_key, key, value_name, value, michael@0: sizeof(*value) * (lstrlen(value) + 1), REG_SZ); michael@0: } michael@0: michael@0: // Read raw data from the registry -- pass something as the dtype michael@0: // parameter if you care to learn what type the value was stored as michael@0: inline bool ReadFromRegistry(HKEY root_key, CTP key, CTP value_name, michael@0: void* data, DWORD* dsize, DWORD* dtype = NULL) { michael@0: return RegKey(root_key, key).ReadValue(value_name, data, dsize, dtype); michael@0: } michael@0: michael@0: michael@0: // Delete a value or a key from the registry michael@0: inline bool DeleteFromRegistry(HKEY root_key, CTP subkey, CTP value_name) { michael@0: if (value_name) michael@0: return ERROR_SUCCESS == ::SHDeleteValue(root_key, subkey, value_name); michael@0: else michael@0: return ERROR_SUCCESS == ::SHDeleteKey(root_key, subkey); michael@0: } michael@0: michael@0: michael@0: michael@0: // delete a key and all subkeys from the registry michael@0: inline bool DeleteKeyFromRegistry(HKEY root_key, CTP key_path, CTP key_name) { michael@0: RegKey key; michael@0: return key.Open(root_key, key_path, KEY_WRITE) michael@0: && key.DeleteKey(key_name); michael@0: } michael@0: michael@0: michael@0: // Iterates the entries found in a particular folder on the registry. michael@0: // For this application I happen to know I wont need data size larger michael@0: // than MAX_PATH, but in real life this wouldn't neccessarily be michael@0: // adequate. michael@0: class RegistryValueIterator { michael@0: public: michael@0: // Specify a key in construction michael@0: RegistryValueIterator(HKEY root_key, LPCTSTR folder_key); michael@0: michael@0: ~RegistryValueIterator(); michael@0: michael@0: DWORD ValueCount() const; // count of the number of subkeys extant michael@0: michael@0: bool Valid() const; // true while the iterator is valid michael@0: michael@0: void operator++(); // advance to the next entry in the folder michael@0: michael@0: // The pointers returned by these functions are statics owned by the michael@0: // Name and Value functions michael@0: CTP Name() const { return name_; } michael@0: CTP Value() const { return value_; } michael@0: DWORD ValueSize() const { return value_size_; } michael@0: DWORD Type() const { return type_; } michael@0: michael@0: int Index() const { return index_; } michael@0: michael@0: private: michael@0: bool Read(); // read in the current values michael@0: michael@0: HKEY key_; // the registry key being iterated michael@0: int index_; // current index of the iteration michael@0: michael@0: // Current values michael@0: TCHAR name_[MAX_PATH]; michael@0: TCHAR value_[MAX_PATH]; michael@0: DWORD value_size_; michael@0: DWORD type_; michael@0: }; michael@0: michael@0: michael@0: class RegistryKeyIterator { michael@0: public: michael@0: // Specify a parent key in construction michael@0: RegistryKeyIterator(HKEY root_key, LPCTSTR folder_key); michael@0: michael@0: ~RegistryKeyIterator(); michael@0: michael@0: DWORD SubkeyCount() const; // count of the number of subkeys extant michael@0: michael@0: bool Valid() const; // true while the iterator is valid michael@0: michael@0: void operator++(); // advance to the next entry in the folder michael@0: michael@0: // The pointer returned by Name() is a static owned by the function michael@0: CTP Name() const { return name_; } michael@0: michael@0: int Index() const { return index_; } michael@0: michael@0: private: michael@0: bool Read(); // read in the current values michael@0: michael@0: HKEY key_; // the registry key being iterated michael@0: int index_; // current index of the iteration michael@0: michael@0: // Current values michael@0: TCHAR name_[MAX_PATH]; michael@0: }; michael@0: michael@0: michael@0: // Register a COM object with the most usual properties. michael@0: bool RegisterCOMServer(const tchar* guid, const tchar* name, michael@0: const tchar* modulepath); michael@0: bool RegisterCOMServer(const tchar* guid, const tchar* name, HINSTANCE module); michael@0: bool UnregisterCOMServer(const tchar* guid); michael@0: michael@0: // undo the local types defined above michael@0: #undef tchar michael@0: #undef CTP michael@0: #undef tstr michael@0: michael@0: #endif // BASE_REGISTRY_H__