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