1 /* $Id: RegistryKey.cpp,v 1.4 2001/01/13 23:54:40 narnaoud Exp $
3 * regexpl - Console Registry Explorer
5 * Copyright (C) 2000,2001 Nedko Arnaoudov <nedkohome@atia.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 // RegistryKey.cpp: implementation of the CRegistryKey class.
25 //////////////////////////////////////////////////////////////////////
28 #include "RegistryKey.h"
30 static TCHAR
*g_ppszHiveNames
[] =
32 _T("HKEY_CLASSES_ROOT"),
33 _T("HKEY_CURRENT_USER"),
34 _T("HKEY_LOCAL_MACHINE"),
36 _T("HKEY_PERFORMANCE_DATA"),
37 _T("HKEY_CURRENT_CONFIG"),
41 //////////////////////////////////////////////////////////////////////
42 // Construction/Destruction
43 //////////////////////////////////////////////////////////////////////
45 CRegistryKey::CRegistryKey()
48 m_pszMachineName
= NULL
;
53 HRESULT
CRegistryKey::InitRoot(const TCHAR
*pszMachineName
= NULL
)
55 if ((pszMachineName
)&&
56 ((_tcslen(pszMachineName
) < 3)||
57 (pszMachineName
[0] != _T('\\'))||
58 (pszMachineName
[1] != _T('\\'))
65 HRESULT hr
= Uninit();
70 { // copy machine name
71 size_t size
= _tcslen(pszMachineName
);
73 m_pszMachineName
= new TCHAR
[size
+2];
74 if (!m_pszMachineName
)
76 _tcscpy(m_pszMachineName
,pszMachineName
);
77 m_pszMachineName
[size
] = _T('\\');
78 m_pszMachineName
[size
+1] = 0;
82 m_pszMachineName
= NULL
; // local registry
85 ASSERT(m_pszKeyName
== NULL
);
87 ASSERT(m_hKey
== NULL
);
92 HRESULT
CRegistryKey::Init(HKEY hKey
, const TCHAR
*pszPath
, const TCHAR
*pszKeyName
, REGSAM CurrentAccess
)
94 HRESULT hr
= Uninit();
98 if (!pszKeyName
|| !hKey
)
101 // copy key name name
102 size_t size
= _tcslen(pszKeyName
);
104 size
+= _tcslen(pszPath
);
106 m_pszKeyName
= new TCHAR
[size
+2];
108 return E_OUTOFMEMORY
;
109 _stprintf(m_pszKeyName
,_T("%s%s\\"),pszPath
?pszPath
:_T(""),pszKeyName
);
111 m_CurrentAccess
= CurrentAccess
;
118 HRESULT
CRegistryKey::Uninit()
122 delete [] m_pszKeyName
;
126 if (m_pszMachineName
)
128 delete [] m_pszMachineName
;
129 m_pszMachineName
= NULL
;
132 LONG nError
= ERROR_SUCCESS
;
133 if((m_hKey
!= NULL
)&&(!IsHive(m_hKey
)))
134 nError
= RegCloseKey(m_hKey
);
138 return (nError
== ERROR_SUCCESS
)?S_OK
:E_FAIL
;
141 BOOL
CRegistryKey::IsHive(HKEY hKey
)
143 return ((hKey
== HKEY_CLASSES_ROOT
)||
144 (hKey
== HKEY_CURRENT_USER
)||
145 (hKey
== HKEY_LOCAL_MACHINE
)||
146 (hKey
== HKEY_USERS
)||
147 (hKey
== HKEY_PERFORMANCE_DATA
)||
148 (hKey
== HKEY_CURRENT_CONFIG
)||
149 (hKey
== HKEY_DYN_DATA
));
152 CRegistryKey::~CRegistryKey()
157 const TCHAR
* CRegistryKey::GetKeyName()
159 return m_pszKeyName
?m_pszKeyName
:(m_pszMachineName
?m_pszMachineName
:_T("\\"));
162 BOOL
CRegistryKey::IsRoot()
164 return m_hKey
== NULL
;
167 LONG
CRegistryKey::OpenSubkey(REGSAM samDesired
, const TCHAR
*pszSubkeyName
, HKEY
&rhKey
)
170 { // subkey of root key is hive root key.
171 if ((_tcsicmp(pszSubkeyName
,_T("HKCR")) == 0)||
172 (_tcsicmp(pszSubkeyName
,_T("HKEY_CLASSES_ROOT")) == 0))
174 rhKey
= HKEY_CLASSES_ROOT
;
176 if (m_pszMachineName
)
177 return ERROR_FILE_NOT_FOUND
;
179 return ERROR_SUCCESS
;
181 else if ((_tcsicmp(pszSubkeyName
,_T("HKCU")) == 0)||
182 (_tcsicmp(pszSubkeyName
,_T("HKEY_CURRENT_USER")) == 0))
184 rhKey
= HKEY_CURRENT_USER
;
186 if (m_pszMachineName
)
187 return ERROR_FILE_NOT_FOUND
;
189 return ERROR_SUCCESS
;
191 else if ((_tcsicmp(pszSubkeyName
,_T("HKLM")) == 0)||
192 (_tcsicmp(pszSubkeyName
,_T("HKEY_LOCAL_MACHINE")) == 0))
194 rhKey
= HKEY_LOCAL_MACHINE
;
196 if (m_pszMachineName
)
197 return RegConnectRegistry(m_pszMachineName
,rhKey
,&rhKey
);
199 return ERROR_SUCCESS
;
201 else if ((_tcsicmp(pszSubkeyName
,_T("HKU")) == 0)||
202 (_tcsicmp(pszSubkeyName
,_T("HKEY_USERS")) == 0))
206 if (m_pszMachineName
)
207 return RegConnectRegistry(m_pszMachineName
,rhKey
,&rhKey
);
209 return ERROR_SUCCESS
;
211 else if ((_tcsicmp(pszSubkeyName
,_T("HKPD")) == 0)||
212 (_tcsicmp(pszSubkeyName
,_T("HKEY_PERFORMANCE_DATA")) == 0))
214 rhKey
= HKEY_PERFORMANCE_DATA
;
216 if (m_pszMachineName
)
217 return RegConnectRegistry(m_pszMachineName
,rhKey
,&rhKey
);
219 return ERROR_SUCCESS
;
221 else if ((_tcsicmp(pszSubkeyName
,_T("HKDD")) == 0)||
222 (_tcsicmp(pszSubkeyName
,_T("HKEY_DYN_DATA")) == 0))
224 rhKey
= HKEY_DYN_DATA
;
226 if (m_pszMachineName
)
227 return RegConnectRegistry(m_pszMachineName
,rhKey
,&rhKey
);
229 return ERROR_SUCCESS
;
231 else if ((_tcsicmp(pszSubkeyName
,_T("HKCC")) == 0)||
232 (_tcsicmp(pszSubkeyName
,_T("HKEY_CURRENT_CONFIG")) == 0))
234 rhKey
= HKEY_CURRENT_CONFIG
;
236 if (m_pszMachineName
)
238 TCHAR
*pch
= m_pszMachineName
;
243 ASSERT(*pch
== _T('\\'));
244 if (*pch
!= _T('\\'))
245 return ERROR_INTERNAL_ERROR
;
249 LONG nError
= RegConnectRegistry(m_pszMachineName
,rhKey
,&rhKey
);
256 return ERROR_SUCCESS
;
260 return ERROR_FILE_NOT_FOUND
;
264 return RegOpenKeyEx(m_hKey
,pszSubkeyName
,0,samDesired
,&rhKey
);
267 LONG
CRegistryKey::OpenSubkey(REGSAM samDesired
, const TCHAR
*pszSubkeyName
, CRegistryKey
&rKey
)
270 LONG nError
= OpenSubkey(samDesired
, pszSubkeyName
, hKey
);
272 if (nError
== ERROR_SUCCESS
)
274 const TCHAR
*pszKeyName
= GetKeyName();
275 size_t size
= _tcslen(pszKeyName
) + _tcslen(pszSubkeyName
) + 1;
276 TCHAR
*pszSubkeyFullName
= new TCHAR
[size
];
277 if (!pszSubkeyFullName
)
279 nError
= RegCloseKey(hKey
);
280 ASSERT(nError
== ERROR_SUCCESS
);
281 return ERROR_OUTOFMEMORY
;
283 _tcscpy(pszSubkeyFullName
,pszKeyName
);
284 _tcscat(pszSubkeyFullName
,pszSubkeyName
);
285 HRESULT hr
= rKey
.Init(hKey
,GetKeyName(),pszSubkeyName
,samDesired
);
286 delete pszSubkeyName
;
289 nError
= RegCloseKey(hKey
);
290 ASSERT(nError
== ERROR_SUCCESS
);
291 if (hr
== (HRESULT
)E_OUTOFMEMORY
)
292 return ERROR_OUTOFMEMORY
;
294 return ERROR_INTERNAL_ERROR
;
301 LONG
CRegistryKey::GetSubkeyNameMaxLength(DWORD
&rdwMaxSubkeyNameLength
)
305 rdwMaxSubkeyNameLength
= 0;
306 for(int i
= 0; i
< 7 ; i
++)
308 size_t l
= _tcslen(g_ppszHiveNames
[i
]);
309 if (rdwMaxSubkeyNameLength
< l
)
310 rdwMaxSubkeyNameLength
= l
;
313 rdwMaxSubkeyNameLength
++; // terminating null
315 return ERROR_SUCCESS
;
320 nRet
= RegQueryInfoKey(m_hKey
,NULL
,NULL
,NULL
,NULL
,&rdwMaxSubkeyNameLength
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
);
322 rdwMaxSubkeyNameLength
= (nRet
== ERROR_SUCCESS
)?(rdwMaxSubkeyNameLength
+1):0;
327 void CRegistryKey::InitSubkeyEnumeration(TCHAR
*pszSubkeyNameBuffer
, DWORD dwBufferSize
)
329 m_pchSubkeyNameBuffer
= pszSubkeyNameBuffer
;
330 m_dwSubkeyNameBufferSize
= dwBufferSize
;
331 m_dwCurrentSubKeyIndex
= 0;
334 LONG
CRegistryKey::GetNextSubkeyName(DWORD
*pdwActualSize
)
340 if (m_dwCurrentSubKeyIndex
< (DWORD
)(m_pszMachineName
?5:7))
342 DWORD dwIndex
= m_pszMachineName
?m_dwCurrentSubKeyIndex
+2:m_dwCurrentSubKeyIndex
;
343 _tcsncpy(m_pchSubkeyNameBuffer
,g_ppszHiveNames
[dwIndex
],m_dwSubkeyNameBufferSize
);
344 nError
= ERROR_SUCCESS
;
346 *pdwActualSize
= strlen(m_pchSubkeyNameBuffer
);
350 nError
= ERROR_NO_MORE_ITEMS
;
355 DWORD dwActualSize
= m_dwSubkeyNameBufferSize
;
357 nError
= RegEnumKeyEx(m_hKey
,
358 m_dwCurrentSubKeyIndex
,
359 m_pchSubkeyNameBuffer
,
366 *pdwActualSize
= dwActualSize
;
369 m_dwCurrentSubKeyIndex
++;
372 *pdwActualSize
= strlen(m_pchSubkeyNameBuffer
);
376 LONG
CRegistryKey::GetSubkeyCount(DWORD
&rdwSubkeyCount
)
378 return RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,&rdwSubkeyCount
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
);
381 LONG
CRegistryKey::GetMaxValueDataSize(DWORD
& rdwMaxValueDataBuferSize
)
383 return RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&rdwMaxValueDataBuferSize
,NULL
,NULL
);
386 LONG
CRegistryKey::GetMaxValueNameLength(DWORD
& rdwMaxValueNameBuferSize
)
389 return 0; // the root key abstraction has only subkeys (hives)
391 LONG nError
= RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&rdwMaxValueNameBuferSize
,NULL
,NULL
,NULL
);
393 rdwMaxValueNameBuferSize
++;
397 void CRegistryKey::InitValueEnumeration(TCHAR
*pszValueNameBuffer
,
398 DWORD dwValueNameBufferSize
,
399 BYTE
*pbValueDataBuffer
,
400 DWORD dwValueDataBufferSize
,
403 m_pszValueNameBuffer
= pszValueNameBuffer
;
404 m_dwValueNameBufferSize
= dwValueNameBufferSize
;
405 m_pbValueDataBuffer
= pbValueDataBuffer
;
406 m_dwValueDataBufferSize
= dwValueDataBufferSize
;
409 m_dwCurrentValueIndex
= 0;
413 // On input dwValueNameSize is size in characters of buffer pointed by pchValueNameBuffer
414 // On output dwValueNameSize contains number of characters stored in buffer
415 LONG
CRegistryKey::GetNextValue(DWORD
*pdwNameActualSize
, DWORD
*pdwDataActualSize
)
418 return ERROR_NO_MORE_ITEMS
; // the root key abstraction has only subkeys (hives)
420 DWORD dwValueNameBufferSize
= m_dwValueNameBufferSize
;
421 DWORD dwValueDataBufferSize
= m_dwValueDataBufferSize
;
422 LONG nError
= RegEnumValue(m_hKey
,
423 m_dwCurrentValueIndex
,
424 m_pszValueNameBuffer
,
425 &dwValueNameBufferSize
,
429 &dwValueDataBufferSize
);
431 if (pdwNameActualSize
)
432 *pdwNameActualSize
= dwValueNameBufferSize
;
434 if (pdwDataActualSize
)
435 *pdwDataActualSize
= dwValueDataBufferSize
;
437 m_dwCurrentValueIndex
++;
441 LONG
CRegistryKey::GetValueCount(DWORD
& rdwValueCount
)
444 return 0; // the root key abstraction has only subkeys (hives)
446 return RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&rdwValueCount
,NULL
,NULL
,NULL
,NULL
);
449 LONG
CRegistryKey::GetDefaultValue(DWORD
*pdwType
,
450 BYTE
*pbValueDataBuffer
,
451 DWORD dwValueDataBufferSize
,
452 DWORD
*pdwValueDataActualSize
)
454 DWORD dwBufferSize
= dwValueDataBufferSize
;
456 LONG nError
= RegQueryValueEx(m_hKey
,NULL
,NULL
,pdwType
,pbValueDataBuffer
,&dwBufferSize
);
458 if (pdwValueDataActualSize
&& (nError
== ERROR_SUCCESS
))
459 *pdwValueDataActualSize
= dwBufferSize
;
464 const TCHAR
* CRegistryKey::GetValueTypeName(DWORD dwType
)
469 return _T("REG_NONE");
473 return _T("REG_EXPAND_SZ");
475 return _T("REG_BINARY");
476 case REG_DWORD_LITTLE_ENDIAN
:
477 return _T("REG_DWORD_LITTLE_ENDIAN");
478 case REG_DWORD_BIG_ENDIAN
:
479 return _T("REG_DWORD_BIG_ENDIAN");
481 return _T("REG_LINK");
483 return _T("REG_MULTI_SZ");
484 case REG_RESOURCE_LIST
:
485 return _T("REG_RESOURCE_LIST");
486 case REG_FULL_RESOURCE_DESCRIPTOR
:
487 return _T("REG_FULL_RESOURCE_DESCRIPTOR");
488 case REG_RESOURCE_REQUIREMENTS_LIST
:
489 return _T("REG_RESOURCE_REQUIREMENTS_LIST");
491 return _T("Unkown Type");
495 DWORD
CRegistryKey::GetValue(TCHAR
*pchValueName
, DWORD
*pdwType
, LPBYTE lpValueDataBuffer
, DWORD
*pdwValueDataSize
)
497 return RegQueryValueEx(m_hKey
,pchValueName
,NULL
,pdwType
,lpValueDataBuffer
,pdwValueDataSize
);
500 LONG
CRegistryKey::CreateSubkey(REGSAM samDesired
,
501 const TCHAR
*pszSubkeyName
,
508 LONG nError
= RegCreateKeyEx(
513 blnVolatile
?REG_OPTION_VOLATILE
:REG_OPTION_NON_VOLATILE
,
519 if ((nError
== ERROR_SUCCESS
)&&(pblnOpened
))
520 *pblnOpened
= dwDisposition
== REG_OPENED_EXISTING_KEY
;
525 LONG
CRegistryKey::GetLastWriteTime(SYSTEMTIME
&st
)
528 LONG nError
= RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&ft
);
530 if (nError
== ERROR_SUCCESS
)
532 FileTimeToLocalFileTime(&ft
,&ftLocal
);
533 FileTimeToSystemTime(&ftLocal
,&st
);
539 const TCHAR
* CRegistryKey::GetLastWriteTime()
542 if (GetLastWriteTime(st
) != ERROR_SUCCESS
)
543 return _T("(Cannot get time last write time)");
545 static TCHAR Buffer
[256];
546 _stprintf(Buffer
,_T("%d.%d.%d %02d:%02d:%02d"),st
.wDay
,st
.wMonth
,st
.wYear
,st
.wHour
,st
.wMinute
,st
.wSecond
);
550 LONG
CRegistryKey::GetSecurityDescriptorLength(DWORD
*pdwSecurityDescriptor
)
552 return RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,
553 NULL
,NULL
,pdwSecurityDescriptor
,NULL
);
556 LONG
CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
, PSECURITY_DESCRIPTOR pSecurityDescriptor
, LPDWORD lpcbSecurityDescriptor
)
558 return RegGetKeySecurity(m_hKey
,SecurityInformation
,pSecurityDescriptor
,lpcbSecurityDescriptor
);
561 LONG
CRegistryKey::DeleteSubkey(const TCHAR
*pszSubkeyName
)
563 return RegDeleteKey(m_hKey
,pszSubkeyName
);
566 LONG
CRegistryKey::SetValue(LPCTSTR pszValueName
, DWORD dwType
, BYTE
*lpData
, DWORD dwDataSize
)
568 return RegSetValueEx(m_hKey
,pszValueName
,0,dwType
,lpData
,dwDataSize
);
571 LONG
CRegistryKey::DeleteValue(const TCHAR
*pszValueName
)
573 return RegDeleteValue(m_hKey
,pszValueName
);