1 /*
2  * regexpl - Console Registry Explorer
3  *
4  * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 // RegistryKey.cpp: implementation of the CRegistryKey class.
23 //
24 //////////////////////////////////////////////////////////////////////
25 
26 #include "ph.h"
27 #include "RegistryKey.h"
28 
29 static const TCHAR *g_ppszHiveNames[] =
30 {
31   _T("HKEY_CLASSES_ROOT"),
32   _T("HKEY_CURRENT_USER"),
33   _T("HKEY_LOCAL_MACHINE"),
34   _T("HKEY_USERS"),
35   _T("HKEY_PERFORMANCE_DATA"),
36   _T("HKEY_CURRENT_CONFIG"),
37   _T("HKEY_DYN_DATA")
38 };
39 
40 //////////////////////////////////////////////////////////////////////
41 // Construction/Destruction
42 //////////////////////////////////////////////////////////////////////
43 
CRegistryKey()44 CRegistryKey::CRegistryKey()
45 {
46   m_pszKeyName = NULL;
47   m_pszMachineName = NULL;
48 	m_CurrentAccess = 0;
49 	m_hKey = NULL;
50 }
51 
InitRoot(const TCHAR * pszMachineName)52 HRESULT CRegistryKey::InitRoot(const TCHAR *pszMachineName)
53 {
54   if ((pszMachineName)&&
55       ((_tcslen(pszMachineName) < 3)||
56        (pszMachineName[0] != _T('\\'))||
57        (pszMachineName[1] != _T('\\'))
58       )
59     )
60   {
61     return E_INVALIDARG;
62   }
63 
64   HRESULT hr = Uninit();
65   if (FAILED(hr))
66     return hr;
67 
68   if (pszMachineName)
69   { // copy machine name
70     size_t size = _tcslen(pszMachineName);
71 
72     m_pszMachineName = new (std::nothrow) TCHAR [size+2];
73     if (!m_pszMachineName)
74       return E_OUTOFMEMORY;
75     _tcscpy(m_pszMachineName,pszMachineName);
76     m_pszMachineName[size] = _T('\\');
77     m_pszMachineName[size+1] = 0;
78   }
79   else
80   {
81     m_pszMachineName = NULL; // local registry
82   }
83 
84   ASSERT(m_pszKeyName == NULL);
85 	m_CurrentAccess = 0;
86 	ASSERT(m_hKey == NULL);
87 
88   return S_OK;
89 }
90 
Init(HKEY hKey,const TCHAR * pszPath,const TCHAR * pszKeyName,REGSAM CurrentAccess)91 HRESULT CRegistryKey::Init(HKEY hKey, const TCHAR *pszPath, const TCHAR *pszKeyName, REGSAM CurrentAccess)
92 {
93   HRESULT hr = Uninit();
94   if (FAILED(hr))
95     return hr;
96 
97   if (!pszKeyName || !hKey)
98     return E_INVALIDARG;
99 
100   // copy key name name
101   size_t size = _tcslen(pszKeyName);
102   if (pszPath)
103     size += _tcslen(pszPath);
104 
105   m_pszKeyName = new (std::nothrow) TCHAR [size+2];
106   if (!m_pszKeyName)
107     return E_OUTOFMEMORY;
108   _stprintf(m_pszKeyName,_T("%s%s\\"),pszPath?pszPath:_T(""),pszKeyName);
109 
110 	m_CurrentAccess = CurrentAccess;
111 	m_hKey = hKey;
112   ASSERT(m_hKey);
113 
114   return S_OK;
115 }
116 
Uninit()117 HRESULT CRegistryKey::Uninit()
118 {
119 	if (m_pszKeyName)
120   {
121     delete [] m_pszKeyName;
122     m_pszKeyName = NULL;
123   }
124 
125 	if (m_pszMachineName)
126   {
127     delete [] m_pszMachineName;
128     m_pszMachineName = NULL;
129   }
130 
131   LONG nError = ERROR_SUCCESS;
132 	if((m_hKey != NULL)&&(!IsHive(m_hKey)))
133 		nError = RegCloseKey(m_hKey);
134 
135   m_hKey = NULL;
136 
137   return (nError == ERROR_SUCCESS)?S_OK:E_FAIL;
138 }
139 
IsHive(HKEY hKey)140 BOOL CRegistryKey::IsHive(HKEY hKey)
141 {
142 	return ((hKey == HKEY_CLASSES_ROOT)||
143           (hKey == HKEY_CURRENT_USER)||
144           (hKey == HKEY_LOCAL_MACHINE)||
145           (hKey == HKEY_USERS)||
146           (hKey == HKEY_PERFORMANCE_DATA)||
147           (hKey == HKEY_CURRENT_CONFIG)||
148           (hKey == HKEY_DYN_DATA));
149 }
150 
~CRegistryKey()151 CRegistryKey::~CRegistryKey()
152 {
153   Uninit();
154 }
155 
GetKeyName()156 const TCHAR * CRegistryKey::GetKeyName()
157 {
158 	return m_pszKeyName?m_pszKeyName:(m_pszMachineName?m_pszMachineName:_T("\\"));
159 }
160 
IsRoot()161 BOOL CRegistryKey::IsRoot()
162 {
163   return m_hKey == NULL;
164 }
165 
OpenSubkey(REGSAM samDesired,const TCHAR * pszSubkeyName,HKEY & rhKey)166 LONG CRegistryKey::OpenSubkey(REGSAM samDesired, const TCHAR *pszSubkeyName, HKEY &rhKey)
167 {
168 	if (m_hKey == NULL)
169   { // subkey of root key is hive root key.
170     if ((_tcsicmp(pszSubkeyName,_T("HKCR")) == 0)||
171 				(_tcsicmp(pszSubkeyName,_T("HKEY_CLASSES_ROOT")) == 0))
172     {
173       rhKey = HKEY_CLASSES_ROOT;
174 
175       if (m_pszMachineName)
176         return ERROR_FILE_NOT_FOUND;
177 
178       return ERROR_SUCCESS;
179     }
180     else if ((_tcsicmp(pszSubkeyName,_T("HKCU")) == 0)||
181              (_tcsicmp(pszSubkeyName,_T("HKEY_CURRENT_USER")) == 0))
182     {
183       rhKey = HKEY_CURRENT_USER;
184 
185       if (m_pszMachineName)
186         return ERROR_FILE_NOT_FOUND;
187 
188       return ERROR_SUCCESS;
189     }
190     else if ((_tcsicmp(pszSubkeyName,_T("HKLM")) == 0)||
191              (_tcsicmp(pszSubkeyName,_T("HKEY_LOCAL_MACHINE")) == 0))
192     {
193       rhKey = HKEY_LOCAL_MACHINE;
194 
195       if (m_pszMachineName)
196         return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
197 
198       return ERROR_SUCCESS;
199     }
200     else if ((_tcsicmp(pszSubkeyName,_T("HKU")) == 0)||
201              (_tcsicmp(pszSubkeyName,_T("HKEY_USERS")) == 0))
202     {
203       rhKey = HKEY_USERS;
204 
205       if (m_pszMachineName)
206         return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
207 
208       return ERROR_SUCCESS;
209     }
210     else if ((_tcsicmp(pszSubkeyName,_T("HKPD")) == 0)||
211              (_tcsicmp(pszSubkeyName,_T("HKEY_PERFORMANCE_DATA")) == 0))
212     {
213       rhKey = HKEY_PERFORMANCE_DATA;
214 
215       if (m_pszMachineName)
216         return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
217 
218       return ERROR_SUCCESS;
219     }
220     else if ((_tcsicmp(pszSubkeyName,_T("HKDD")) == 0)||
221              (_tcsicmp(pszSubkeyName,_T("HKEY_DYN_DATA")) == 0))
222     {
223       rhKey = HKEY_DYN_DATA;
224 
225       if (m_pszMachineName)
226         return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
227 
228       return ERROR_SUCCESS;
229     }
230     else if ((_tcsicmp(pszSubkeyName,_T("HKCC")) == 0)||
231              (_tcsicmp(pszSubkeyName,_T("HKEY_CURRENT_CONFIG")) == 0))
232     {
233       rhKey = HKEY_CURRENT_CONFIG;
234 
235       if (m_pszMachineName)
236       {
237         TCHAR *pch = m_pszMachineName;
238         while (*pch)
239           pch++;
240         pch--;
241 
242         ASSERT(*pch == _T('\\'));
243         if (*pch != _T('\\'))
244           return ERROR_INTERNAL_ERROR;
245 
246         *pch = 0;
247 
248         LONG nError = RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
249 
250         *pch = _T('\\');
251 
252         return nError;
253       }
254 
255       return ERROR_SUCCESS;
256     }
257     else
258     {
259       return ERROR_FILE_NOT_FOUND;
260     }
261   }
262 
263 	return RegOpenKeyEx(m_hKey,pszSubkeyName,0,samDesired,&rhKey);
264 }
265 
OpenSubkey(REGSAM samDesired,const TCHAR * pszSubkeyName,CRegistryKey & rKey)266 LONG CRegistryKey::OpenSubkey(REGSAM samDesired, const TCHAR *pszSubkeyName, CRegistryKey &rKey)
267 {
268   HKEY hKey;
269   LONG nError = OpenSubkey(samDesired, pszSubkeyName, hKey);
270 
271   if (nError == ERROR_SUCCESS)
272   {
273     const TCHAR *pszKeyName = GetKeyName();
274     size_t size = _tcslen(pszKeyName) + _tcslen(pszSubkeyName) + 1;
275     TCHAR *pszSubkeyFullName = new (std::nothrow) TCHAR [size];
276     if (!pszSubkeyFullName)
277     {
278       nError = RegCloseKey(hKey);
279       ASSERT(nError == ERROR_SUCCESS);
280       return ERROR_OUTOFMEMORY;
281     }
282     _tcscpy(pszSubkeyFullName,pszKeyName);
283     _tcscat(pszSubkeyFullName,pszSubkeyName);
284     HRESULT hr = rKey.Init(hKey,GetKeyName(),pszSubkeyName,samDesired);
285     delete[] pszSubkeyName;
286     if (FAILED(hr))
287     {
288       nError = RegCloseKey(hKey);
289       ASSERT(nError == ERROR_SUCCESS);
290       if (hr == (HRESULT)E_OUTOFMEMORY)
291         return ERROR_OUTOFMEMORY;
292       else
293         return ERROR_INTERNAL_ERROR;
294     }
295   }
296 
297   return nError;
298 }
299 
GetSubkeyNameMaxLength(DWORD & rdwMaxSubkeyNameLength)300 LONG CRegistryKey::GetSubkeyNameMaxLength(DWORD &rdwMaxSubkeyNameLength)
301 {
302   if (m_hKey == NULL)
303   { // root key
304     rdwMaxSubkeyNameLength = 0;
305     for(int i = 0; i < 7 ; i++)
306     {
307       size_t l = _tcslen(g_ppszHiveNames[i]);
308       if (rdwMaxSubkeyNameLength < l)
309         rdwMaxSubkeyNameLength = l;
310     }
311 
312     rdwMaxSubkeyNameLength++; // terminating null
313 
314     return ERROR_SUCCESS;
315   }
316 
317   LONG nRet;
318 
319   nRet = RegQueryInfoKey(m_hKey,NULL,NULL,NULL,NULL,&rdwMaxSubkeyNameLength,NULL,NULL,NULL,NULL,NULL,NULL);
320 
321   rdwMaxSubkeyNameLength = (nRet == ERROR_SUCCESS)?(rdwMaxSubkeyNameLength+1):0;
322 
323   return nRet;
324 }
325 
InitSubkeyEnumeration(TCHAR * pszSubkeyNameBuffer,DWORD dwBufferSize)326 void CRegistryKey::InitSubkeyEnumeration(TCHAR *pszSubkeyNameBuffer, DWORD dwBufferSize)
327 {
328   m_pchSubkeyNameBuffer = pszSubkeyNameBuffer;
329   m_dwSubkeyNameBufferSize = dwBufferSize;
330   m_dwCurrentSubKeyIndex = 0;
331 }
332 
GetNextSubkeyName(DWORD * pdwActualSize)333 LONG CRegistryKey::GetNextSubkeyName(DWORD *pdwActualSize)
334 {
335   LONG nError;
336 
337   if (m_hKey == NULL)
338   {
339     if (m_dwCurrentSubKeyIndex < (DWORD)(m_pszMachineName?5:7))
340     {
341       DWORD dwIndex = m_pszMachineName?m_dwCurrentSubKeyIndex+2:m_dwCurrentSubKeyIndex;
342       _tcsncpy(m_pchSubkeyNameBuffer,g_ppszHiveNames[dwIndex],m_dwSubkeyNameBufferSize);
343       nError = ERROR_SUCCESS;
344       if (pdwActualSize)
345         *pdwActualSize = strlen(m_pchSubkeyNameBuffer);
346     }
347     else
348     {
349       nError = ERROR_NO_MORE_ITEMS;
350     }
351   }
352   else
353   {
354     DWORD dwActualSize = m_dwSubkeyNameBufferSize;
355     FILETIME ft;
356     nError = RegEnumKeyEx(m_hKey,
357                           m_dwCurrentSubKeyIndex,
358                           m_pchSubkeyNameBuffer,
359                           &dwActualSize,
360                           NULL,
361                           NULL,
362                           NULL,
363                           &ft);
364     if (pdwActualSize)
365       *pdwActualSize = dwActualSize;
366   }
367 
368 	m_dwCurrentSubKeyIndex++;
369 
370   if (pdwActualSize)
371     *pdwActualSize = strlen(m_pchSubkeyNameBuffer);
372   return nError;
373 }
374 
GetSubkeyCount(DWORD & rdwSubkeyCount)375 LONG CRegistryKey::GetSubkeyCount(DWORD &rdwSubkeyCount)
376 {
377 	return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,&rdwSubkeyCount,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
378 }
379 
GetMaxValueDataSize(DWORD & rdwMaxValueDataBuferSize)380 LONG CRegistryKey::GetMaxValueDataSize(DWORD& rdwMaxValueDataBuferSize)
381 {
382 	return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&rdwMaxValueDataBuferSize,NULL,NULL);
383 }
384 
GetMaxValueNameLength(DWORD & rdwMaxValueNameBuferSize)385 LONG CRegistryKey::GetMaxValueNameLength(DWORD& rdwMaxValueNameBuferSize)
386 {
387   rdwMaxValueNameBuferSize = 0;
388 
389   if (!m_hKey)
390     return 0; // the root key abstraction has only subkeys (hives)
391 
392 	LONG nError = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&rdwMaxValueNameBuferSize,NULL,NULL,NULL);
393 
394   rdwMaxValueNameBuferSize++;
395   return nError;
396 }
397 
InitValueEnumeration(TCHAR * pszValueNameBuffer,DWORD dwValueNameBufferSize,BYTE * pbValueDataBuffer,DWORD dwValueDataBufferSize,DWORD * pdwType)398 void CRegistryKey::InitValueEnumeration(TCHAR *pszValueNameBuffer,
399                                         DWORD dwValueNameBufferSize,
400                                         BYTE *pbValueDataBuffer,
401                                         DWORD dwValueDataBufferSize,
402                                         DWORD *pdwType)
403 {
404   m_pszValueNameBuffer = pszValueNameBuffer;
405   m_dwValueNameBufferSize = dwValueNameBufferSize;
406   m_pbValueDataBuffer = pbValueDataBuffer;
407   m_dwValueDataBufferSize = dwValueDataBufferSize;
408   m_pdwType = pdwType;
409 
410 	m_dwCurrentValueIndex = 0;
411 }
412 
413 
414 // On input dwValueNameSize is size in characters of buffer pointed by pchValueNameBuffer
415 // On output dwValueNameSize contains number of characters stored in buffer
GetNextValue(DWORD * pdwNameActualSize,DWORD * pdwDataActualSize)416 LONG CRegistryKey::GetNextValue(DWORD *pdwNameActualSize, DWORD *pdwDataActualSize)
417 {
418   if (!m_hKey)
419     return ERROR_NO_MORE_ITEMS; // the root key abstraction has only subkeys (hives)
420 
421 	DWORD dwValueNameBufferSize = m_dwValueNameBufferSize;
422 	DWORD dwValueDataBufferSize = m_dwValueDataBufferSize;
423   LONG nError = RegEnumValue(m_hKey,
424                             m_dwCurrentValueIndex,
425                             m_pszValueNameBuffer,
426                             &dwValueNameBufferSize,
427                             NULL,
428                             m_pdwType,
429                             m_pbValueDataBuffer,
430                             &dwValueDataBufferSize);
431 
432   if (pdwNameActualSize)
433     *pdwNameActualSize = dwValueNameBufferSize;
434 
435   if (pdwDataActualSize)
436     *pdwDataActualSize = dwValueDataBufferSize;
437 
438 	m_dwCurrentValueIndex++;
439 	return nError;
440 }
441 
GetValueCount(DWORD & rdwValueCount)442 LONG CRegistryKey::GetValueCount(DWORD& rdwValueCount)
443 {
444   if (!m_hKey)
445     return 0; // the root key abstraction has only subkeys (hives)
446 
447   return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,&rdwValueCount,NULL,NULL,NULL,NULL);
448 }
449 
GetDefaultValue(DWORD * pdwType,BYTE * pbValueDataBuffer,DWORD dwValueDataBufferSize,DWORD * pdwValueDataActualSize)450 LONG CRegistryKey::GetDefaultValue(DWORD *pdwType,
451                                    BYTE *pbValueDataBuffer,
452                                    DWORD dwValueDataBufferSize,
453                                    DWORD *pdwValueDataActualSize)
454 {
455   DWORD dwBufferSize = dwValueDataBufferSize;
456 
457 	LONG nError = RegQueryValueEx(m_hKey,NULL,NULL,pdwType,pbValueDataBuffer,&dwBufferSize);
458 
459   if (pdwValueDataActualSize && (nError == ERROR_SUCCESS))
460     *pdwValueDataActualSize = dwBufferSize;
461 
462   return nError;
463 }
464 
GetValueTypeName(DWORD dwType)465 const TCHAR * CRegistryKey::GetValueTypeName(DWORD dwType)
466 {
467 	switch(dwType)
468 	{
469 	case REG_NONE:
470 		return _T("REG_NONE");
471 	case REG_SZ:
472 		return _T("REG_SZ");
473 	case REG_EXPAND_SZ:
474 		return _T("REG_EXPAND_SZ");
475 	case REG_BINARY:
476 		return _T("REG_BINARY");
477 	case REG_DWORD_LITTLE_ENDIAN:
478 		return _T("REG_DWORD_LITTLE_ENDIAN");
479 	case REG_DWORD_BIG_ENDIAN:
480 		return _T("REG_DWORD_BIG_ENDIAN");
481 	case REG_LINK:
482 		return _T("REG_LINK");
483 	case REG_MULTI_SZ:
484 		return _T("REG_MULTI_SZ");
485 	case REG_RESOURCE_LIST:
486 		return _T("REG_RESOURCE_LIST");
487 	case REG_FULL_RESOURCE_DESCRIPTOR:
488 		return _T("REG_FULL_RESOURCE_DESCRIPTOR");
489 	case REG_RESOURCE_REQUIREMENTS_LIST:
490 		return _T("REG_RESOURCE_REQUIREMENTS_LIST");
491 	default:
492 		return _T("Unknown Type");
493 	}
494 }
495 
GetValue(TCHAR * pchValueName,DWORD * pdwType,LPBYTE lpValueDataBuffer,DWORD * pdwValueDataSize)496 DWORD CRegistryKey::GetValue(TCHAR *pchValueName, DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize)
497 {
498 	return RegQueryValueEx(m_hKey,pchValueName,NULL,pdwType,lpValueDataBuffer,pdwValueDataSize);
499 }
500 
CreateSubkey(REGSAM samDesired,const TCHAR * pszSubkeyName,HKEY & rhKey,BOOL * pblnOpened,BOOL blnVolatile)501 LONG CRegistryKey::CreateSubkey(REGSAM samDesired,
502                                 const TCHAR *pszSubkeyName,
503                                 HKEY &rhKey,
504                                 BOOL *pblnOpened,
505                                 BOOL blnVolatile)
506 {
507   DWORD dwDisposition;
508 
509 	LONG nError = RegCreateKeyEx(
510       m_hKey,
511       pszSubkeyName,
512       0,
513       NULL,
514       blnVolatile?REG_OPTION_VOLATILE:REG_OPTION_NON_VOLATILE,
515       samDesired,
516       NULL,
517       &rhKey,
518       &dwDisposition);
519 
520   if ((nError == ERROR_SUCCESS)&&(pblnOpened))
521     *pblnOpened = dwDisposition == REG_OPENED_EXISTING_KEY;
522 
523 	return nError;
524 }
525 
GetLastWriteTime(SYSTEMTIME & st)526 LONG CRegistryKey::GetLastWriteTime(SYSTEMTIME &st)
527 {
528 	FILETIME ftLocal,ft;
529 	LONG nError = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&ft);
530 
531   if (nError == ERROR_SUCCESS)
532   {
533     FileTimeToLocalFileTime(&ft,&ftLocal);
534     FileTimeToSystemTime(&ftLocal,&st);
535   }
536 
537   return nError;
538 }
539 
GetLastWriteTime()540 const TCHAR * CRegistryKey::GetLastWriteTime()
541 {
542 	SYSTEMTIME st;
543 	if (GetLastWriteTime(st) != ERROR_SUCCESS)
544     return _T("(Cannot get time last write time)");
545 
546 	static TCHAR Buffer[256];
547 	_stprintf(Buffer,_T("%d.%d.%d %02d:%02d:%02d"),st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute,st.wSecond);
548 	return Buffer;
549 }
550 
GetSecurityDescriptorLength(DWORD * pdwSecurityDescriptor)551 LONG CRegistryKey::GetSecurityDescriptorLength(DWORD *pdwSecurityDescriptor)
552 {
553 	return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
554 		NULL,NULL,pdwSecurityDescriptor,NULL);
555 }
556 
GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,PSECURITY_DESCRIPTOR pSecurityDescriptor,LPDWORD lpcbSecurityDescriptor)557 LONG CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
558 {
559 	return RegGetKeySecurity(m_hKey,SecurityInformation,pSecurityDescriptor,lpcbSecurityDescriptor);
560 }
561 
DeleteSubkey(const TCHAR * pszSubkeyName)562 LONG CRegistryKey::DeleteSubkey(const TCHAR *pszSubkeyName)
563 {
564   return RegDeleteKey(m_hKey,pszSubkeyName);
565 }
566 
SetValue(LPCTSTR pszValueName,DWORD dwType,BYTE * lpData,DWORD dwDataSize)567 LONG CRegistryKey::SetValue(LPCTSTR pszValueName, DWORD dwType, BYTE *lpData, DWORD dwDataSize)
568 {
569 	return RegSetValueEx(m_hKey,pszValueName,0,dwType,lpData,dwDataSize);
570 }
571 
DeleteValue(const TCHAR * pszValueName)572 LONG CRegistryKey::DeleteValue(const TCHAR *pszValueName)
573 {
574 	return RegDeleteValue(m_hKey,pszValueName);
575 }
576