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 44 CRegistryKey::CRegistryKey() 45 { 46 m_pszKeyName = NULL; 47 m_pszMachineName = NULL; 48 m_CurrentAccess = 0; 49 m_hKey = NULL; 50 } 51 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 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 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 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 151 CRegistryKey::~CRegistryKey() 152 { 153 Uninit(); 154 } 155 156 const TCHAR * CRegistryKey::GetKeyName() 157 { 158 return m_pszKeyName?m_pszKeyName:(m_pszMachineName?m_pszMachineName:_T("\\")); 159 } 160 161 BOOL CRegistryKey::IsRoot() 162 { 163 return m_hKey == NULL; 164 } 165 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 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 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 326 void CRegistryKey::InitSubkeyEnumeration(TCHAR *pszSubkeyNameBuffer, DWORD dwBufferSize) 327 { 328 m_pchSubkeyNameBuffer = pszSubkeyNameBuffer; 329 m_dwSubkeyNameBufferSize = dwBufferSize; 330 m_dwCurrentSubKeyIndex = 0; 331 } 332 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 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 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 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 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 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 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 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 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("Unkown Type"); 493 } 494 } 495 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 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 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 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 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 557 LONG CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor) 558 { 559 return RegGetKeySecurity(m_hKey,SecurityInformation,pSecurityDescriptor,lpcbSecurityDescriptor); 560 } 561 562 LONG CRegistryKey::DeleteSubkey(const TCHAR *pszSubkeyName) 563 { 564 return RegDeleteKey(m_hKey,pszSubkeyName); 565 } 566 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 572 LONG CRegistryKey::DeleteValue(const TCHAR *pszValueName) 573 { 574 return RegDeleteValue(m_hKey,pszValueName); 575 } 576