Home | History | Annotate | Download | only in Windows
      1 // Windows/Registry.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include <wchar.h>
      6 
      7 #ifndef _UNICODE
      8 #include "../Common/StringConvert.h"
      9 #endif
     10 #include "Registry.h"
     11 
     12 #ifndef _UNICODE
     13 extern bool g_IsNT;
     14 #endif
     15 
     16 namespace NWindows {
     17 namespace NRegistry {
     18 
     19 #define MYASSERT(expr) // _ASSERTE(expr)
     20 
     21 LONG CKey::Create(HKEY parentKey, LPCTSTR keyName,
     22     LPTSTR keyClass, DWORD options, REGSAM accessMask,
     23     LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw()
     24 {
     25   MYASSERT(parentKey != NULL);
     26   DWORD dispositionReal;
     27   HKEY key = NULL;
     28   LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass,
     29       options, accessMask, securityAttributes, &key, &dispositionReal);
     30   if (disposition != NULL)
     31     *disposition = dispositionReal;
     32   if (res == ERROR_SUCCESS)
     33   {
     34     res = Close();
     35     _object = key;
     36   }
     37   return res;
     38 }
     39 
     40 LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw()
     41 {
     42   MYASSERT(parentKey != NULL);
     43   HKEY key = NULL;
     44   LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key);
     45   if (res == ERROR_SUCCESS)
     46   {
     47     res = Close();
     48     MYASSERT(res == ERROR_SUCCESS);
     49     _object = key;
     50   }
     51   return res;
     52 }
     53 
     54 LONG CKey::Close() throw()
     55 {
     56   LONG res = ERROR_SUCCESS;
     57   if (_object != NULL)
     58   {
     59     res = RegCloseKey(_object);
     60     _object = NULL;
     61   }
     62   return res;
     63 }
     64 
     65 // win95, win98: deletes sunkey and all its subkeys
     66 // winNT to be deleted must not have subkeys
     67 LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()
     68 {
     69   MYASSERT(_object != NULL);
     70   return RegDeleteKey(_object, subKeyName);
     71 }
     72 
     73 LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw()
     74 {
     75   CKey key;
     76   LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);
     77   if (res != ERROR_SUCCESS)
     78     return res;
     79   FILETIME fileTime;
     80   const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL
     81   DWORD size = kBufSize;
     82   TCHAR buffer[kBufSize];
     83   while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)
     84   {
     85     res = key.RecurseDeleteKey(buffer);
     86     if (res != ERROR_SUCCESS)
     87       return res;
     88     size = kBufSize;
     89   }
     90   key.Close();
     91   return DeleteSubKey(subKeyName);
     92 }
     93 
     94 
     95 /////////////////////////
     96 // Value Functions
     97 
     98 static inline UInt32 BoolToUINT32(bool value) {  return (value ? 1: 0); }
     99 static inline bool UINT32ToBool(UInt32 value) {  return (value != 0); }
    100 
    101 
    102 LONG CKey::DeleteValue(LPCTSTR name) throw()
    103 {
    104   MYASSERT(_object != NULL);
    105   return ::RegDeleteValue(_object, name);
    106 }
    107 
    108 #ifndef _UNICODE
    109 LONG CKey::DeleteValue(LPCWSTR name)
    110 {
    111   MYASSERT(_object != NULL);
    112   if (g_IsNT)
    113     return ::RegDeleteValueW(_object, name);
    114   return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name));
    115 }
    116 #endif
    117 
    118 LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw()
    119 {
    120   MYASSERT(_object != NULL);
    121   return RegSetValueEx(_object, name, 0, REG_DWORD,
    122       (BYTE * const)&value, sizeof(UInt32));
    123 }
    124 
    125 LONG CKey::SetValue(LPCTSTR name, bool value) throw()
    126 {
    127   return SetValue(name, BoolToUINT32(value));
    128 }
    129 
    130 LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw()
    131 {
    132   MYASSERT(value != NULL);
    133   MYASSERT(_object != NULL);
    134   return RegSetValueEx(_object, name, 0, REG_SZ,
    135       (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR));
    136 }
    137 
    138 /*
    139 LONG CKey::SetValue(LPCTSTR name, const CSysString &value)
    140 {
    141   MYASSERT(value != NULL);
    142   MYASSERT(_object != NULL);
    143   return RegSetValueEx(_object, name, NULL, REG_SZ,
    144       (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR));
    145 }
    146 */
    147 
    148 #ifndef _UNICODE
    149 
    150 LONG CKey::SetValue(LPCWSTR name, LPCWSTR value)
    151 {
    152   MYASSERT(value != NULL);
    153   MYASSERT(_object != NULL);
    154   if (g_IsNT)
    155     return RegSetValueExW(_object, name, NULL, REG_SZ,
    156       (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t)));
    157   return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name),
    158     value == 0 ? 0 : (LPCSTR)GetSystemString(value));
    159 }
    160 
    161 #endif
    162 
    163 
    164 LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw()
    165 {
    166   MYASSERT(value != NULL);
    167   MYASSERT(_object != NULL);
    168   return RegSetValueEx(_object, name, 0, REG_BINARY,
    169       (const BYTE *)value, size);
    170 }
    171 
    172 LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)
    173 {
    174   MYASSERT(value != NULL);
    175   CKey key;
    176   LONG res = key.Create(parentKey, keyName);
    177   if (res == ERROR_SUCCESS)
    178     res = key.SetValue(valueName, value);
    179   return res;
    180 }
    181 
    182 LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw()
    183 {
    184   MYASSERT(value != NULL);
    185   CKey key;
    186   LONG res = key.Create(_object, keyName);
    187   if (res == ERROR_SUCCESS)
    188     res = key.SetValue(valueName, value);
    189   return res;
    190 }
    191 
    192 LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw()
    193 {
    194   DWORD type = 0;
    195   DWORD count = sizeof(DWORD);
    196   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type,
    197     (LPBYTE)&value, &count);
    198   MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD));
    199   MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32)));
    200   return res;
    201 }
    202 
    203 LONG CKey::QueryValue(LPCTSTR name, bool &value) throw()
    204 {
    205   UInt32 uintValue = BoolToUINT32(value);
    206   LONG res = QueryValue(name, uintValue);
    207   value = UINT32ToBool(uintValue);
    208   return res;
    209 }
    210 
    211 LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw()
    212 {
    213   UInt32 newVal;
    214   LONG res = QueryValue(name, newVal);
    215   if (res == ERROR_SUCCESS)
    216     value = newVal;
    217   return res;
    218 }
    219 
    220 LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()
    221 {
    222   bool newVal;
    223   LONG res = QueryValue(name, newVal);
    224   if (res == ERROR_SUCCESS)
    225     value = newVal;
    226   return res;
    227 }
    228 
    229 LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()
    230 {
    231   DWORD type = 0;
    232   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
    233   MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
    234   return res;
    235 }
    236 
    237 LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
    238 {
    239   value.Empty();
    240   DWORD type = 0;
    241   UInt32 curSize = 0;
    242   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize);
    243   if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
    244     return res;
    245   UInt32 curSize2 = curSize;
    246   res = QueryValue(name, value.GetBuf(curSize), curSize2);
    247   if (curSize > curSize2)
    248     curSize = curSize2;
    249   value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR));
    250   return res;
    251 }
    252 
    253 
    254 #ifndef _UNICODE
    255 
    256 LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)
    257 {
    258   DWORD type = 0;
    259   LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
    260   MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
    261   return res;
    262 }
    263 
    264 LONG CKey::QueryValue(LPCWSTR name, UString &value)
    265 {
    266   value.Empty();
    267   DWORD type = 0;
    268   UInt32 curSize = 0;
    269 
    270   LONG res;
    271 
    272   if (g_IsNT)
    273   {
    274     res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize);
    275     if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
    276       return res;
    277     UInt32 curSize2 = curSize;
    278     res = QueryValue(name, value.GetBuf(curSize), curSize2);
    279     if (curSize > curSize2)
    280       curSize = curSize2;
    281     value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t));
    282   }
    283   else
    284   {
    285     AString vTemp;
    286     res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);
    287     value = GetUnicodeString(vTemp);
    288   }
    289 
    290   return res;
    291 }
    292 
    293 #endif
    294 
    295 
    296 LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()
    297 {
    298   DWORD type = 0;
    299   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
    300   MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY));
    301   return res;
    302 }
    303 
    304 
    305 LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)
    306 {
    307   DWORD type = 0;
    308   dataSize = 0;
    309   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize);
    310   if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
    311     return res;
    312   value.Alloc(dataSize);
    313   return QueryValue(name, (BYTE *)value, dataSize);
    314 }
    315 
    316 LONG CKey::EnumKeys(CSysStringVector &keyNames)
    317 {
    318   keyNames.Clear();
    319   CSysString keyName;
    320   for (DWORD index = 0; ; index++)
    321   {
    322     const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL
    323     FILETIME lastWriteTime;
    324     UInt32 nameSize = kBufSize;
    325     LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize),
    326         (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);
    327     keyName.ReleaseBuf_CalcLen(kBufSize);
    328     if (result == ERROR_NO_MORE_ITEMS)
    329       break;
    330     if (result != ERROR_SUCCESS)
    331       return result;
    332     keyNames.Add(keyName);
    333   }
    334   return ERROR_SUCCESS;
    335 }
    336 
    337 LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)
    338 {
    339   size_t numChars = 0;
    340 
    341   unsigned i;
    342 
    343   for (i = 0; i < strings.Size(); i++)
    344     numChars += strings[i].Len() + 1;
    345 
    346   CObjArray<wchar_t> buffer(numChars);
    347   size_t pos = 0;
    348 
    349   for (i = 0; i < strings.Size(); i++)
    350   {
    351     const UString &s = strings[i];
    352     size_t size = s.Len() + 1;
    353     wmemcpy(buffer + pos, s, size);
    354     pos += size;
    355   }
    356   return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t));
    357 }
    358 
    359 LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
    360 {
    361   strings.Clear();
    362   CByteBuffer buffer;
    363   UInt32 dataSize = 0;
    364   LONG res = QueryValue(valueName, buffer, dataSize);
    365   if (res != ERROR_SUCCESS)
    366     return res;
    367   if (dataSize > buffer.Size())
    368     return E_FAIL;
    369   if (dataSize % sizeof(wchar_t) != 0)
    370     return E_FAIL;
    371 
    372   const wchar_t *data = (const wchar_t *)(const Byte  *)buffer;
    373   size_t numChars = dataSize / sizeof(wchar_t);
    374   size_t prev = 0;
    375   UString s;
    376 
    377   for (size_t i = 0; i < numChars; i++)
    378   {
    379     if (data[i] == 0)
    380     {
    381       s = data + prev;
    382       strings.Add(s);
    383       prev = i + 1;
    384     }
    385   }
    386 
    387   return res;
    388 }
    389 
    390 }}
    391