 09b0c10eed
			
		
	
	09b0c10eed
	
	
	
		
			
			BUG=N/A R=mallinath@webrtc.org Review URL: https://webrtc-codereview.appspot.com/11249004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5848 4adac7df-926f-26a2-2b94-8c16560cd09d
		
			
				
	
	
		
			1120 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1120 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * libjingle
 | |
|  * Copyright 2003-2008, Google Inc.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions are met:
 | |
|  *
 | |
|  *  1. Redistributions of source code must retain the above copyright notice,
 | |
|  *     this list of conditions and the following disclaimer.
 | |
|  *  2. Redistributions in binary form must reproduce the above copyright notice,
 | |
|  *     this list of conditions and the following disclaimer in the documentation
 | |
|  *     and/or other materials provided with the distribution.
 | |
|  *  3. The name of the author may not be used to endorse or promote products
 | |
|  *     derived from this software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | |
|  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | |
|  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | |
|  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | |
|  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 | |
|  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | |
|  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | |
|  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | |
|  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| // Registry configuration wrapers class implementation
 | |
| //
 | |
| // Change made by S. Ganesh - ganesh@google.com:
 | |
| //   Use SHQueryValueEx instead of RegQueryValueEx throughout.
 | |
| //   A call to the SHLWAPI function is essentially a call to the standard
 | |
| //   function but with post-processing:
 | |
| //   * to fix REG_SZ or REG_EXPAND_SZ data that is not properly null-terminated;
 | |
| //   * to expand REG_EXPAND_SZ data.
 | |
| 
 | |
| #include "talk/base/win32regkey.h"
 | |
| 
 | |
| #include <shlwapi.h>
 | |
| 
 | |
| #include "talk/base/common.h"
 | |
| #include "talk/base/logging.h"
 | |
| #include "talk/base/scoped_ptr.h"
 | |
| 
 | |
| namespace talk_base {
 | |
| 
 | |
| RegKey::RegKey() {
 | |
|   h_key_ = NULL;
 | |
| }
 | |
| 
 | |
| RegKey::~RegKey() {
 | |
|   Close();
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::Create(HKEY parent_key, const wchar_t* key_name) {
 | |
|   return Create(parent_key,
 | |
|                 key_name,
 | |
|                 REG_NONE,
 | |
|                 REG_OPTION_NON_VOLATILE,
 | |
|                 KEY_ALL_ACCESS,
 | |
|                 NULL,
 | |
|                 NULL);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::Open(HKEY parent_key, const wchar_t* key_name) {
 | |
|   return Open(parent_key, key_name, KEY_ALL_ACCESS);
 | |
| }
 | |
| 
 | |
| bool RegKey::HasValue(const TCHAR* value_name) const {
 | |
|   return (ERROR_SUCCESS == ::RegQueryValueEx(h_key_, value_name, NULL,
 | |
|                                              NULL, NULL, NULL));
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          DWORD value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name, REG_DWORD, &value);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          DWORD64 value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name, REG_QWORD, &value);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          float value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name,
 | |
|                               REG_BINARY, &value, sizeof(value));
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          double value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name,
 | |
|                               REG_BINARY, &value, sizeof(value));
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          const TCHAR* value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name,
 | |
|                               REG_SZ, const_cast<wchar_t*>(value));
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          const uint8* value,
 | |
|                          DWORD byte_count) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name, REG_BINARY,
 | |
|                               const_cast<uint8*>(value), byte_count);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::SetValueMultiSZ(const wchar_t* full_key_name,
 | |
|                                 const wchar_t* value_name,
 | |
|                                 const uint8* value,
 | |
|                                 DWORD byte_count) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return SetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ,
 | |
|                               const_cast<uint8*>(value), byte_count);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          DWORD* value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   return GetValueStaticHelper(full_key_name, value_name, REG_DWORD, value);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          DWORD64* value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   return GetValueStaticHelper(full_key_name, value_name, REG_QWORD, value);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          float* value) {
 | |
|   ASSERT(value != NULL);
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   DWORD byte_count = 0;
 | |
|   scoped_ptr<byte[]> buffer;
 | |
|   HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
 | |
|                                     REG_BINARY, buffer.accept(), &byte_count);
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     ASSERT(byte_count == sizeof(*value));
 | |
|     if (byte_count == sizeof(*value)) {
 | |
|       *value = *reinterpret_cast<float*>(buffer.get());
 | |
|     }
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          double* value) {
 | |
|   ASSERT(value != NULL);
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   DWORD byte_count = 0;
 | |
|   scoped_ptr<byte[]> buffer;
 | |
|   HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
 | |
|                                     REG_BINARY, buffer.accept(), &byte_count);
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     ASSERT(byte_count == sizeof(*value));
 | |
|     if (byte_count == sizeof(*value)) {
 | |
|       *value = *reinterpret_cast<double*>(buffer.get());
 | |
|     }
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          wchar_t** value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   return GetValueStaticHelper(full_key_name, value_name, REG_SZ, value);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          std::wstring* value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   scoped_ptr<wchar_t[]> buffer;
 | |
|   HRESULT hr = RegKey::GetValue(full_key_name, value_name, buffer.accept());
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     value->assign(buffer.get());
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          std::vector<std::wstring>* value) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   return GetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ, value);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValue(const wchar_t* full_key_name,
 | |
|                          const wchar_t* value_name,
 | |
|                          uint8** value,
 | |
|                          DWORD* byte_count) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value != NULL);
 | |
|   ASSERT(byte_count != NULL);
 | |
| 
 | |
|   return GetValueStaticHelper(full_key_name, value_name,
 | |
|                               REG_BINARY, value, byte_count);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::DeleteSubKey(const wchar_t* key_name) {
 | |
|   ASSERT(key_name != NULL);
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   LONG res = ::RegDeleteKey(h_key_, key_name);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
|   if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
 | |
|       hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
 | |
|     hr = S_FALSE;
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::DeleteValue(const wchar_t* value_name) {
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   LONG res = ::RegDeleteValue(h_key_, value_name);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
|   if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
 | |
|       hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
 | |
|     hr = S_FALSE;
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::Close() {
 | |
|   HRESULT hr = S_OK;
 | |
|   if (h_key_ != NULL) {
 | |
|     LONG res = ::RegCloseKey(h_key_);
 | |
|     hr = HRESULT_FROM_WIN32(res);
 | |
|     h_key_ = NULL;
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::Create(HKEY parent_key,
 | |
|                        const wchar_t* key_name,
 | |
|                        wchar_t* lpszClass,
 | |
|                        DWORD options,
 | |
|                        REGSAM sam_desired,
 | |
|                        LPSECURITY_ATTRIBUTES lpSecAttr,
 | |
|                        LPDWORD lpdwDisposition) {
 | |
|   ASSERT(key_name != NULL);
 | |
|   ASSERT(parent_key != NULL);
 | |
| 
 | |
|   DWORD dw = 0;
 | |
|   HKEY h_key = NULL;
 | |
|   LONG res = ::RegCreateKeyEx(parent_key, key_name, 0, lpszClass, options,
 | |
|                               sam_desired, lpSecAttr, &h_key, &dw);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
| 
 | |
|   if (lpdwDisposition) {
 | |
|     *lpdwDisposition = dw;
 | |
|   }
 | |
| 
 | |
|   // we have to close the currently opened key
 | |
|   // before replacing it with the new one
 | |
|   if (hr == S_OK) {
 | |
|     hr = Close();
 | |
|     ASSERT(hr == S_OK);
 | |
|     h_key_ = h_key;
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::Open(HKEY parent_key,
 | |
|                      const wchar_t* key_name,
 | |
|                      REGSAM sam_desired) {
 | |
|   ASSERT(key_name != NULL);
 | |
|   ASSERT(parent_key != NULL);
 | |
| 
 | |
|   HKEY h_key = NULL;
 | |
|   LONG res = ::RegOpenKeyEx(parent_key, key_name, 0, sam_desired, &h_key);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
| 
 | |
|   // we have to close the currently opened key
 | |
|   // before replacing it with the new one
 | |
|   if (hr == S_OK) {
 | |
|     // close the currently opened key if any
 | |
|     hr = Close();
 | |
|     ASSERT(hr == S_OK);
 | |
|     h_key_ = h_key;
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // save the key and all of its subkeys and values to a file
 | |
| HRESULT RegKey::Save(const wchar_t* full_key_name, const wchar_t* file_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(file_name != NULL);
 | |
| 
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
|   if (!h_key) {
 | |
|     return E_FAIL;
 | |
|   }
 | |
| 
 | |
|   RegKey key;
 | |
|   HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ);
 | |
|   if (FAILED(hr)) {
 | |
|     return hr;
 | |
|   }
 | |
| 
 | |
|   AdjustCurrentProcessPrivilege(SE_BACKUP_NAME, true);
 | |
|   LONG res = ::RegSaveKey(key.h_key_, file_name, NULL);
 | |
|   AdjustCurrentProcessPrivilege(SE_BACKUP_NAME, false);
 | |
| 
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // restore the key and all of its subkeys and values which are saved into a file
 | |
| HRESULT RegKey::Restore(const wchar_t* full_key_name,
 | |
|                         const wchar_t* file_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(file_name != NULL);
 | |
| 
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
|   if (!h_key) {
 | |
|     return E_FAIL;
 | |
|   }
 | |
| 
 | |
|   RegKey key;
 | |
|   HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_WRITE);
 | |
|   if (FAILED(hr)) {
 | |
|     return hr;
 | |
|   }
 | |
| 
 | |
|   AdjustCurrentProcessPrivilege(SE_RESTORE_NAME, true);
 | |
|   LONG res = ::RegRestoreKey(key.h_key_, file_name, REG_FORCE_RESTORE);
 | |
|   AdjustCurrentProcessPrivilege(SE_RESTORE_NAME, false);
 | |
| 
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // check if the current key has the specified subkey
 | |
| bool RegKey::HasSubkey(const wchar_t* key_name) const {
 | |
|   ASSERT(key_name != NULL);
 | |
| 
 | |
|   RegKey key;
 | |
|   HRESULT hr = key.Open(h_key_, key_name, KEY_READ);
 | |
|   key.Close();
 | |
|   return hr == S_OK;
 | |
| }
 | |
| 
 | |
| // static flush key
 | |
| HRESULT RegKey::FlushKey(const wchar_t* full_key_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   if (h_key != NULL) {
 | |
|     LONG res = ::RegFlushKey(h_key);
 | |
|     hr = HRESULT_FROM_WIN32(res);
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // static SET helper
 | |
| HRESULT RegKey::SetValueStaticHelper(const wchar_t* full_key_name,
 | |
|                                      const wchar_t* value_name,
 | |
|                                      DWORD type,
 | |
|                                      LPVOID value,
 | |
|                                      DWORD byte_count) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   if (h_key != NULL) {
 | |
|     RegKey key;
 | |
|     hr = key.Create(h_key, key_name.c_str());
 | |
|     if (hr == S_OK) {
 | |
|       switch (type) {
 | |
|         case REG_DWORD:
 | |
|           hr = key.SetValue(value_name, *(static_cast<DWORD*>(value)));
 | |
|           break;
 | |
|         case REG_QWORD:
 | |
|           hr = key.SetValue(value_name, *(static_cast<DWORD64*>(value)));
 | |
|           break;
 | |
|         case REG_SZ:
 | |
|           hr = key.SetValue(value_name, static_cast<const wchar_t*>(value));
 | |
|           break;
 | |
|         case REG_BINARY:
 | |
|           hr = key.SetValue(value_name, static_cast<const uint8*>(value),
 | |
|                             byte_count);
 | |
|           break;
 | |
|         case REG_MULTI_SZ:
 | |
|           hr = key.SetValue(value_name, static_cast<const uint8*>(value),
 | |
|                             byte_count, type);
 | |
|           break;
 | |
|         default:
 | |
|           ASSERT(false);
 | |
|           hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
 | |
|           break;
 | |
|       }
 | |
|       // close the key after writing
 | |
|       HRESULT temp_hr = key.Close();
 | |
|       if (hr == S_OK) {
 | |
|         hr = temp_hr;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // static GET helper
 | |
| HRESULT RegKey::GetValueStaticHelper(const wchar_t* full_key_name,
 | |
|                                      const wchar_t* value_name,
 | |
|                                      DWORD type,
 | |
|                                      LPVOID value,
 | |
|                                      DWORD* byte_count) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   if (h_key != NULL) {
 | |
|     RegKey key;
 | |
|     hr = key.Open(h_key, key_name.c_str(), KEY_READ);
 | |
|     if (hr == S_OK) {
 | |
|       switch (type) {
 | |
|         case REG_DWORD:
 | |
|           hr = key.GetValue(value_name, reinterpret_cast<DWORD*>(value));
 | |
|           break;
 | |
|         case REG_QWORD:
 | |
|           hr = key.GetValue(value_name, reinterpret_cast<DWORD64*>(value));
 | |
|           break;
 | |
|         case REG_SZ:
 | |
|           hr = key.GetValue(value_name, reinterpret_cast<wchar_t**>(value));
 | |
|           break;
 | |
|         case REG_MULTI_SZ:
 | |
|           hr = key.GetValue(value_name, reinterpret_cast<
 | |
|                                             std::vector<std::wstring>*>(value));
 | |
|           break;
 | |
|         case REG_BINARY:
 | |
|           hr = key.GetValue(value_name, reinterpret_cast<uint8**>(value),
 | |
|                             byte_count);
 | |
|           break;
 | |
|         default:
 | |
|           ASSERT(false);
 | |
|           hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
 | |
|           break;
 | |
|       }
 | |
|       // close the key after writing
 | |
|       HRESULT temp_hr = key.Close();
 | |
|       if (hr == S_OK) {
 | |
|         hr = temp_hr;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // GET helper
 | |
| HRESULT RegKey::GetValueHelper(const wchar_t* value_name,
 | |
|                                DWORD* type,
 | |
|                                uint8** value,
 | |
|                                DWORD* byte_count) const {
 | |
|   ASSERT(byte_count != NULL);
 | |
|   ASSERT(value != NULL);
 | |
|   ASSERT(type != NULL);
 | |
| 
 | |
|   // init return buffer
 | |
|   *value = NULL;
 | |
| 
 | |
|   // get the size of the return data buffer
 | |
|   LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, type, NULL, byte_count);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
| 
 | |
|   if (hr == S_OK) {
 | |
|     // if the value length is 0, nothing to do
 | |
|     if (*byte_count != 0) {
 | |
|       // allocate the buffer
 | |
|       *value = new byte[*byte_count];
 | |
|       ASSERT(*value != NULL);
 | |
| 
 | |
|       // make the call again to get the data
 | |
|       res = ::SHQueryValueEx(h_key_, value_name, NULL,
 | |
|                              type, *value, byte_count);
 | |
|       hr = HRESULT_FROM_WIN32(res);
 | |
|       ASSERT(hr == S_OK);
 | |
|     }
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // Int32 Get
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name, DWORD* value) const {
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   DWORD type = 0;
 | |
|   DWORD byte_count = sizeof(DWORD);
 | |
|   LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
 | |
|                               value, &byte_count);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
|   ASSERT((hr != S_OK) || (type == REG_DWORD));
 | |
|   ASSERT((hr != S_OK) || (byte_count == sizeof(DWORD)));
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // Int64 Get
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name, DWORD64* value) const {
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   DWORD type = 0;
 | |
|   DWORD byte_count = sizeof(DWORD64);
 | |
|   LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
 | |
|                               value, &byte_count);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
|   ASSERT((hr != S_OK) || (type == REG_QWORD));
 | |
|   ASSERT((hr != S_OK) || (byte_count == sizeof(DWORD64)));
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // String Get
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name, wchar_t** value) const {
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   DWORD byte_count = 0;
 | |
|   DWORD type = 0;
 | |
| 
 | |
|   // first get the size of the string buffer
 | |
|   LONG res = ::SHQueryValueEx(h_key_, value_name, NULL,
 | |
|                               &type, NULL, &byte_count);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
| 
 | |
|   if (hr == S_OK) {
 | |
|     // allocate room for the string and a terminating \0
 | |
|     *value = new wchar_t[(byte_count / sizeof(wchar_t)) + 1];
 | |
| 
 | |
|     if ((*value) != NULL) {
 | |
|       if (byte_count != 0) {
 | |
|         // make the call again
 | |
|         res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
 | |
|                                *value, &byte_count);
 | |
|         hr = HRESULT_FROM_WIN32(res);
 | |
|       } else {
 | |
|         (*value)[0] = L'\0';
 | |
|       }
 | |
| 
 | |
|       ASSERT((hr != S_OK) || (type == REG_SZ) ||
 | |
|              (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
 | |
|     } else {
 | |
|       hr = E_OUTOFMEMORY;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // get a string value
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name, std::wstring* value) const {
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   DWORD byte_count = 0;
 | |
|   DWORD type = 0;
 | |
| 
 | |
|   // first get the size of the string buffer
 | |
|   LONG res = ::SHQueryValueEx(h_key_, value_name, NULL,
 | |
|                               &type, NULL, &byte_count);
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(res);
 | |
| 
 | |
|   if (hr == S_OK) {
 | |
|     if (byte_count != 0) {
 | |
|       // Allocate some memory and make the call again
 | |
|       value->resize(byte_count / sizeof(wchar_t) + 1);
 | |
|       res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
 | |
|                              &value->at(0), &byte_count);
 | |
|       hr = HRESULT_FROM_WIN32(res);
 | |
|       value->resize(wcslen(value->data()));
 | |
|     } else {
 | |
|       value->clear();
 | |
|     }
 | |
| 
 | |
|     ASSERT((hr != S_OK) || (type == REG_SZ) ||
 | |
|            (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
 | |
|   }
 | |
| 
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // convert REG_MULTI_SZ bytes to string array
 | |
| HRESULT RegKey::MultiSZBytesToStringArray(const uint8* buffer,
 | |
|                                           DWORD byte_count,
 | |
|                                           std::vector<std::wstring>* value) {
 | |
|   ASSERT(buffer != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   const wchar_t* data = reinterpret_cast<const wchar_t*>(buffer);
 | |
|   DWORD data_len = byte_count / sizeof(wchar_t);
 | |
|   value->clear();
 | |
|   if (data_len > 1) {
 | |
|     // must be terminated by two null characters
 | |
|     if (data[data_len - 1] != 0 || data[data_len - 2] != 0) {
 | |
|       return E_INVALIDARG;
 | |
|     }
 | |
| 
 | |
|     // put null-terminated strings into arrays
 | |
|     while (*data) {
 | |
|       std::wstring str(data);
 | |
|       value->push_back(str);
 | |
|       data += str.length() + 1;
 | |
|     }
 | |
|   }
 | |
|   return S_OK;
 | |
| }
 | |
| 
 | |
| // get a std::vector<std::wstring> value from REG_MULTI_SZ type
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name,
 | |
|                          std::vector<std::wstring>* value) const {
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   DWORD byte_count = 0;
 | |
|   DWORD type = 0;
 | |
|   uint8* buffer = 0;
 | |
| 
 | |
|   // first get the size of the buffer
 | |
|   HRESULT hr = GetValueHelper(value_name, &type, &buffer, &byte_count);
 | |
|   ASSERT((hr != S_OK) || (type == REG_MULTI_SZ));
 | |
| 
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     hr = MultiSZBytesToStringArray(buffer, byte_count, value);
 | |
|   }
 | |
| 
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // Binary data Get
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name,
 | |
|                          uint8** value,
 | |
|                          DWORD* byte_count) const {
 | |
|   ASSERT(byte_count != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   DWORD type = 0;
 | |
|   HRESULT hr = GetValueHelper(value_name, &type, value, byte_count);
 | |
|   ASSERT((hr != S_OK) || (type == REG_MULTI_SZ) || (type == REG_BINARY));
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| // Raw data get
 | |
| HRESULT RegKey::GetValue(const wchar_t* value_name,
 | |
|                          uint8** value,
 | |
|                          DWORD* byte_count,
 | |
|                          DWORD*type) const {
 | |
|   ASSERT(type != NULL);
 | |
|   ASSERT(byte_count != NULL);
 | |
|   ASSERT(value != NULL);
 | |
| 
 | |
|   return GetValueHelper(value_name, type, value, byte_count);
 | |
| }
 | |
| 
 | |
| // Int32 set
 | |
| HRESULT RegKey::SetValue(const wchar_t* value_name, DWORD value) const {
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_DWORD,
 | |
|                              reinterpret_cast<const uint8*>(&value),
 | |
|                              sizeof(DWORD));
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // Int64 set
 | |
| HRESULT RegKey::SetValue(const wchar_t* value_name, DWORD64 value) const {
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_QWORD,
 | |
|                              reinterpret_cast<const uint8*>(&value),
 | |
|                              sizeof(DWORD64));
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // String set
 | |
| HRESULT RegKey::SetValue(const wchar_t* value_name,
 | |
|                          const wchar_t* value) const {
 | |
|   ASSERT(value != NULL);
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_SZ,
 | |
|                              reinterpret_cast<const uint8*>(value),
 | |
|                              (lstrlen(value) + 1) * sizeof(wchar_t));
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // Binary data set
 | |
| HRESULT RegKey::SetValue(const wchar_t* value_name,
 | |
|                          const uint8* value,
 | |
|                          DWORD byte_count) const {
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   // special case - if 'value' is NULL make sure byte_count is zero
 | |
|   if (value == NULL) {
 | |
|     byte_count = 0;
 | |
|   }
 | |
| 
 | |
|   LONG res = ::RegSetValueEx(h_key_, value_name, NULL,
 | |
|                              REG_BINARY, value, byte_count);
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // Raw data set
 | |
| HRESULT RegKey::SetValue(const wchar_t* value_name,
 | |
|                          const uint8* value,
 | |
|                          DWORD byte_count,
 | |
|                          DWORD type) const {
 | |
|   ASSERT(value != NULL);
 | |
|   ASSERT(h_key_ != NULL);
 | |
| 
 | |
|   LONG res = ::RegSetValueEx(h_key_, value_name, NULL, type, value, byte_count);
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| bool RegKey::HasKey(const wchar_t* full_key_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   if (h_key != NULL) {
 | |
|     RegKey key;
 | |
|     HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ);
 | |
|     key.Close();
 | |
|     return S_OK == hr;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| // static version of HasValue
 | |
| bool RegKey::HasValue(const wchar_t* full_key_name, const wchar_t* value_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   bool has_value = false;
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   if (h_key != NULL) {
 | |
|     RegKey key;
 | |
|     if (key.Open(h_key, key_name.c_str(), KEY_READ) == S_OK) {
 | |
|       has_value = key.HasValue(value_name);
 | |
|       key.Close();
 | |
|     }
 | |
|   }
 | |
|   return has_value;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetValueType(const wchar_t* full_key_name,
 | |
|                              const wchar_t* value_name,
 | |
|                              DWORD* value_type) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
|   ASSERT(value_type != NULL);
 | |
| 
 | |
|   *value_type = REG_NONE;
 | |
| 
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   RegKey key;
 | |
|   HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ);
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     LONG res = ::SHQueryValueEx(key.h_key_, value_name, NULL, value_type,
 | |
|                                 NULL, NULL);
 | |
|     if (res != ERROR_SUCCESS) {
 | |
|       hr = HRESULT_FROM_WIN32(res);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::DeleteKey(const wchar_t* full_key_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   return DeleteKey(full_key_name, true);
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::DeleteKey(const wchar_t* full_key_name, bool recursively) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   // need to open the parent key first
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   // get the parent key
 | |
|   std::wstring parent_key(GetParentKeyInfo(&key_name));
 | |
| 
 | |
|   RegKey key;
 | |
|   HRESULT hr = key.Open(h_key, parent_key.c_str());
 | |
| 
 | |
|   if (hr == S_OK) {
 | |
|     hr = recursively ? key.RecurseDeleteSubKey(key_name.c_str())
 | |
|                      : key.DeleteSubKey(key_name.c_str());
 | |
|   } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
 | |
|              hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
 | |
|     hr = S_FALSE;
 | |
|   }
 | |
| 
 | |
|   key.Close();
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::DeleteValue(const wchar_t* full_key_name,
 | |
|                             const wchar_t* value_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
 | |
|   // get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   if (h_key != NULL) {
 | |
|     RegKey key;
 | |
|     hr = key.Open(h_key, key_name.c_str());
 | |
|     if (hr == S_OK) {
 | |
|       hr = key.DeleteValue(value_name);
 | |
|       key.Close();
 | |
|     }
 | |
|   }
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::RecurseDeleteSubKey(const wchar_t* key_name) {
 | |
|   ASSERT(key_name != NULL);
 | |
| 
 | |
|   RegKey key;
 | |
|   HRESULT hr = key.Open(h_key_, key_name);
 | |
| 
 | |
|   if (hr == S_OK) {
 | |
|     // enumerate all subkeys of this key and recursivelly delete them
 | |
|     FILETIME time = {0};
 | |
|     wchar_t key_name_buf[kMaxKeyNameChars] = {0};
 | |
|     DWORD key_name_buf_size = kMaxKeyNameChars;
 | |
|     while (hr == S_OK &&
 | |
|         ::RegEnumKeyEx(key.h_key_, 0, key_name_buf, &key_name_buf_size,
 | |
|                        NULL, NULL, NULL,  &time) == ERROR_SUCCESS) {
 | |
|       hr = key.RecurseDeleteSubKey(key_name_buf);
 | |
| 
 | |
|       // restore the buffer size
 | |
|       key_name_buf_size = kMaxKeyNameChars;
 | |
|     }
 | |
|     // close the top key
 | |
|     key.Close();
 | |
|   }
 | |
| 
 | |
|   if (hr == S_OK) {
 | |
|     // the key has no more children keys
 | |
|     // delete the key and all of its values
 | |
|     hr = DeleteSubKey(key_name);
 | |
|   }
 | |
| 
 | |
|   return hr;
 | |
| }
 | |
| 
 | |
| HKEY RegKey::GetRootKeyInfo(std::wstring* full_key_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   HKEY h_key = NULL;
 | |
|   // get the root HKEY
 | |
|   size_t index = full_key_name->find(L'\\');
 | |
|   std::wstring root_key;
 | |
| 
 | |
|   if (index == -1) {
 | |
|     root_key = *full_key_name;
 | |
|     *full_key_name = L"";
 | |
|   } else {
 | |
|     root_key = full_key_name->substr(0, index);
 | |
|     *full_key_name = full_key_name->substr(index + 1,
 | |
|                                            full_key_name->length() - index - 1);
 | |
|   }
 | |
| 
 | |
|   for (std::wstring::iterator iter = root_key.begin();
 | |
|        iter != root_key.end(); ++iter) {
 | |
|     *iter = toupper(*iter);
 | |
|   }
 | |
| 
 | |
|   if (!root_key.compare(L"HKLM") ||
 | |
|       !root_key.compare(L"HKEY_LOCAL_MACHINE")) {
 | |
|     h_key = HKEY_LOCAL_MACHINE;
 | |
|   } else if (!root_key.compare(L"HKCU") ||
 | |
|              !root_key.compare(L"HKEY_CURRENT_USER")) {
 | |
|     h_key = HKEY_CURRENT_USER;
 | |
|   } else if (!root_key.compare(L"HKU") ||
 | |
|              !root_key.compare(L"HKEY_USERS")) {
 | |
|     h_key = HKEY_USERS;
 | |
|   } else if (!root_key.compare(L"HKCR") ||
 | |
|              !root_key.compare(L"HKEY_CLASSES_ROOT")) {
 | |
|     h_key = HKEY_CLASSES_ROOT;
 | |
|   }
 | |
| 
 | |
|   return h_key;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Returns true if this key name is 'safe' for deletion
 | |
| // (doesn't specify a key root)
 | |
| bool RegKey::SafeKeyNameForDeletion(const wchar_t* key_name) {
 | |
|   ASSERT(key_name != NULL);
 | |
|   std::wstring key(key_name);
 | |
| 
 | |
|   HKEY root_key = GetRootKeyInfo(&key);
 | |
| 
 | |
|   if (!root_key) {
 | |
|     key = key_name;
 | |
|   }
 | |
|   if (key.empty()) {
 | |
|     return false;
 | |
|   }
 | |
|   bool found_subkey = false, backslash_found = false;
 | |
|   for (size_t i = 0 ; i < key.length() ; ++i) {
 | |
|     if (key[i] == L'\\') {
 | |
|       backslash_found = true;
 | |
|     } else if (backslash_found) {
 | |
|       found_subkey = true;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   return (root_key == HKEY_USERS) ? found_subkey : true;
 | |
| }
 | |
| 
 | |
| std::wstring RegKey::GetParentKeyInfo(std::wstring* key_name) {
 | |
|   ASSERT(key_name != NULL);
 | |
| 
 | |
|   // get the parent key
 | |
|   size_t index = key_name->rfind(L'\\');
 | |
|   std::wstring parent_key;
 | |
|   if (index == -1) {
 | |
|     parent_key = L"";
 | |
|   } else {
 | |
|     parent_key = key_name->substr(0, index);
 | |
|     *key_name = key_name->substr(index + 1, key_name->length() - index - 1);
 | |
|   }
 | |
| 
 | |
|   return parent_key;
 | |
| }
 | |
| 
 | |
| // get the number of values for this key
 | |
| uint32 RegKey::GetValueCount() {
 | |
|   DWORD num_values = 0;
 | |
| 
 | |
|   if (ERROR_SUCCESS != ::RegQueryInfoKey(
 | |
|         h_key_,  // key handle
 | |
|         NULL,  // buffer for class name
 | |
|         NULL,  // size of class string
 | |
|         NULL,  // reserved
 | |
|         NULL,  // number of subkeys
 | |
|         NULL,  // longest subkey size
 | |
|         NULL,  // longest class string
 | |
|         &num_values,  // number of values for this key
 | |
|         NULL,  // longest value name
 | |
|         NULL,  // longest value data
 | |
|         NULL,  // security descriptor
 | |
|         NULL)) {  // last write time
 | |
|     ASSERT(false);
 | |
|   }
 | |
|   return num_values;
 | |
| }
 | |
| 
 | |
| // Enumerators for the value_names for this key
 | |
| 
 | |
| // Called to get the value name for the given value name index
 | |
| // Use GetValueCount() to get the total value_name count for this key
 | |
| // Returns failure if no key at the specified index
 | |
| HRESULT RegKey::GetValueNameAt(int index, std::wstring* value_name,
 | |
|                                DWORD* type) {
 | |
|   ASSERT(value_name != NULL);
 | |
| 
 | |
|   LONG res = ERROR_SUCCESS;
 | |
|   wchar_t value_name_buf[kMaxValueNameChars] = {0};
 | |
|   DWORD value_name_buf_size = kMaxValueNameChars;
 | |
|   res = ::RegEnumValue(h_key_, index, value_name_buf, &value_name_buf_size,
 | |
|                        NULL, type, NULL, NULL);
 | |
| 
 | |
|   if (res == ERROR_SUCCESS) {
 | |
|     value_name->assign(value_name_buf);
 | |
|   }
 | |
| 
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| uint32 RegKey::GetSubkeyCount() {
 | |
|   // number of values for key
 | |
|   DWORD num_subkeys = 0;
 | |
| 
 | |
|   if (ERROR_SUCCESS != ::RegQueryInfoKey(
 | |
|           h_key_,  // key handle
 | |
|           NULL,  // buffer for class name
 | |
|           NULL,  // size of class string
 | |
|           NULL,  // reserved
 | |
|           &num_subkeys,  // number of subkeys
 | |
|           NULL,  // longest subkey size
 | |
|           NULL,  // longest class string
 | |
|           NULL,  // number of values for this key
 | |
|           NULL,  // longest value name
 | |
|           NULL,  // longest value data
 | |
|           NULL,  // security descriptor
 | |
|           NULL)) { // last write time
 | |
|     ASSERT(false);
 | |
|   }
 | |
|   return num_subkeys;
 | |
| }
 | |
| 
 | |
| HRESULT RegKey::GetSubkeyNameAt(int index, std::wstring* key_name) {
 | |
|   ASSERT(key_name != NULL);
 | |
| 
 | |
|   LONG res = ERROR_SUCCESS;
 | |
|   wchar_t key_name_buf[kMaxKeyNameChars] = {0};
 | |
|   DWORD key_name_buf_size = kMaxKeyNameChars;
 | |
| 
 | |
|   res = ::RegEnumKeyEx(h_key_, index, key_name_buf, &key_name_buf_size,
 | |
|                        NULL, NULL, NULL, NULL);
 | |
| 
 | |
|   if (res == ERROR_SUCCESS) {
 | |
|     key_name->assign(key_name_buf);
 | |
|   }
 | |
| 
 | |
|   return HRESULT_FROM_WIN32(res);
 | |
| }
 | |
| 
 | |
| // Is the key empty: having no sub-keys and values
 | |
| bool RegKey::IsKeyEmpty(const wchar_t* full_key_name) {
 | |
|   ASSERT(full_key_name != NULL);
 | |
| 
 | |
|   bool is_empty = true;
 | |
| 
 | |
|   // Get the root HKEY
 | |
|   std::wstring key_name(full_key_name);
 | |
|   HKEY h_key = GetRootKeyInfo(&key_name);
 | |
| 
 | |
|   // Open the key to check
 | |
|   if (h_key != NULL) {
 | |
|     RegKey key;
 | |
|     HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ);
 | |
|     if (SUCCEEDED(hr)) {
 | |
|       is_empty = key.GetSubkeyCount() == 0 && key.GetValueCount() == 0;
 | |
|       key.Close();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return is_empty;
 | |
| }
 | |
| 
 | |
| bool AdjustCurrentProcessPrivilege(const TCHAR* privilege, bool to_enable) {
 | |
|   ASSERT(privilege != NULL);
 | |
| 
 | |
|   bool ret = false;
 | |
|   HANDLE token;
 | |
|   if (::OpenProcessToken(::GetCurrentProcess(),
 | |
|                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
 | |
|     LUID luid;
 | |
|     memset(&luid, 0, sizeof(luid));
 | |
|     if (::LookupPrivilegeValue(NULL, privilege, &luid)) {
 | |
|       TOKEN_PRIVILEGES privs;
 | |
|       privs.PrivilegeCount = 1;
 | |
|       privs.Privileges[0].Luid = luid;
 | |
|       privs.Privileges[0].Attributes = to_enable ? SE_PRIVILEGE_ENABLED : 0;
 | |
|       if (::AdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, 0)) {
 | |
|         ret = true;
 | |
|       } else {
 | |
|         LOG_GLE(LS_ERROR) << "AdjustTokenPrivileges failed";
 | |
|       }
 | |
|     } else {
 | |
|       LOG_GLE(LS_ERROR) << "LookupPrivilegeValue failed";
 | |
|     }
 | |
|     CloseHandle(token);
 | |
|   } else {
 | |
|     LOG_GLE(LS_ERROR) << "OpenProcessToken(GetCurrentProcess) failed";
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| }  // namespace talk_base
 |