3 * regexpl - Console Registry Explorer
5 * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
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
)
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
)
388 rdwMaxValueNameBuferSize
= 0;
391 return 0; // the root key abstraction has only subkeys (hives)
393 LONG nError
= RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&rdwMaxValueNameBuferSize
,NULL
,NULL
,NULL
);
395 rdwMaxValueNameBuferSize
++;
399 void CRegistryKey::InitValueEnumeration(TCHAR
*pszValueNameBuffer
,
400 DWORD dwValueNameBufferSize
,
401 BYTE
*pbValueDataBuffer
,
402 DWORD dwValueDataBufferSize
,
405 m_pszValueNameBuffer
= pszValueNameBuffer
;
406 m_dwValueNameBufferSize
= dwValueNameBufferSize
;
407 m_pbValueDataBuffer
= pbValueDataBuffer
;
408 m_dwValueDataBufferSize
= dwValueDataBufferSize
;
411 m_dwCurrentValueIndex
= 0;
415 // On input dwValueNameSize is size in characters of buffer pointed by pchValueNameBuffer
416 // On output dwValueNameSize contains number of characters stored in buffer
417 LONG
CRegistryKey::GetNextValue(DWORD
*pdwNameActualSize
, DWORD
*pdwDataActualSize
)
420 return ERROR_NO_MORE_ITEMS
; // the root key abstraction has only subkeys (hives)
422 DWORD dwValueNameBufferSize
= m_dwValueNameBufferSize
;
423 DWORD dwValueDataBufferSize
= m_dwValueDataBufferSize
;
424 LONG nError
= RegEnumValue(m_hKey
,
425 m_dwCurrentValueIndex
,
426 m_pszValueNameBuffer
,
427 &dwValueNameBufferSize
,
431 &dwValueDataBufferSize
);
433 if (pdwNameActualSize
)
434 *pdwNameActualSize
= dwValueNameBufferSize
;
436 if (pdwDataActualSize
)
437 *pdwDataActualSize
= dwValueDataBufferSize
;
439 m_dwCurrentValueIndex
++;
443 LONG
CRegistryKey::GetValueCount(DWORD
& rdwValueCount
)
446 return 0; // the root key abstraction has only subkeys (hives)
448 return RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&rdwValueCount
,NULL
,NULL
,NULL
,NULL
);
451 LONG
CRegistryKey::GetDefaultValue(DWORD
*pdwType
,
452 BYTE
*pbValueDataBuffer
,
453 DWORD dwValueDataBufferSize
,
454 DWORD
*pdwValueDataActualSize
)
456 DWORD dwBufferSize
= dwValueDataBufferSize
;
458 LONG nError
= RegQueryValueEx(m_hKey
,NULL
,NULL
,pdwType
,pbValueDataBuffer
,&dwBufferSize
);
460 if (pdwValueDataActualSize
&& (nError
== ERROR_SUCCESS
))
461 *pdwValueDataActualSize
= dwBufferSize
;
466 const TCHAR
* CRegistryKey::GetValueTypeName(DWORD dwType
)
471 return _T("REG_NONE");
475 return _T("REG_EXPAND_SZ");
477 return _T("REG_BINARY");
478 case REG_DWORD_LITTLE_ENDIAN
:
479 return _T("REG_DWORD_LITTLE_ENDIAN");
480 case REG_DWORD_BIG_ENDIAN
:
481 return _T("REG_DWORD_BIG_ENDIAN");
483 return _T("REG_LINK");
485 return _T("REG_MULTI_SZ");
486 case REG_RESOURCE_LIST
:
487 return _T("REG_RESOURCE_LIST");
488 case REG_FULL_RESOURCE_DESCRIPTOR
:
489 return _T("REG_FULL_RESOURCE_DESCRIPTOR");
490 case REG_RESOURCE_REQUIREMENTS_LIST
:
491 return _T("REG_RESOURCE_REQUIREMENTS_LIST");
493 return _T("Unkown Type");
497 DWORD
CRegistryKey::GetValue(TCHAR
*pchValueName
, DWORD
*pdwType
, LPBYTE lpValueDataBuffer
, DWORD
*pdwValueDataSize
)
499 return RegQueryValueEx(m_hKey
,pchValueName
,NULL
,pdwType
,lpValueDataBuffer
,pdwValueDataSize
);
502 LONG
CRegistryKey::CreateSubkey(REGSAM samDesired
,
503 const TCHAR
*pszSubkeyName
,
510 LONG nError
= RegCreateKeyEx(
515 blnVolatile
?REG_OPTION_VOLATILE
:REG_OPTION_NON_VOLATILE
,
521 if ((nError
== ERROR_SUCCESS
)&&(pblnOpened
))
522 *pblnOpened
= dwDisposition
== REG_OPENED_EXISTING_KEY
;
527 LONG
CRegistryKey::GetLastWriteTime(SYSTEMTIME
&st
)
530 LONG nError
= RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,&ft
);
532 if (nError
== ERROR_SUCCESS
)
534 FileTimeToLocalFileTime(&ft
,&ftLocal
);
535 FileTimeToSystemTime(&ftLocal
,&st
);
541 const TCHAR
* CRegistryKey::GetLastWriteTime()
544 if (GetLastWriteTime(st
) != ERROR_SUCCESS
)
545 return _T("(Cannot get time last write time)");
547 static TCHAR Buffer
[256];
548 _stprintf(Buffer
,_T("%d.%d.%d %02d:%02d:%02d"),st
.wDay
,st
.wMonth
,st
.wYear
,st
.wHour
,st
.wMinute
,st
.wSecond
);
552 LONG
CRegistryKey::GetSecurityDescriptorLength(DWORD
*pdwSecurityDescriptor
)
554 return RegQueryInfoKeyW(m_hKey
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,
555 NULL
,NULL
,pdwSecurityDescriptor
,NULL
);
558 LONG
CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
, PSECURITY_DESCRIPTOR pSecurityDescriptor
, LPDWORD lpcbSecurityDescriptor
)
560 return RegGetKeySecurity(m_hKey
,SecurityInformation
,pSecurityDescriptor
,lpcbSecurityDescriptor
);
563 LONG
CRegistryKey::DeleteSubkey(const TCHAR
*pszSubkeyName
)
565 return RegDeleteKey(m_hKey
,pszSubkeyName
);
568 LONG
CRegistryKey::SetValue(LPCTSTR pszValueName
, DWORD dwType
, BYTE
*lpData
, DWORD dwDataSize
)
570 return RegSetValueEx(m_hKey
,pszValueName
,0,dwType
,lpData
,dwDataSize
);
573 LONG
CRegistryKey::DeleteValue(const TCHAR
*pszValueName
)
575 return RegDeleteValue(m_hKey
,pszValueName
);