Fixes to compile the whole set of ROS applications.
[reactos.git] / rosapps / sysutils / regexpl / RegistryKey.cpp
1 /* $Id: RegistryKey.cpp,v 1.4 2001/01/13 23:54:40 narnaoud Exp $
2 *
3 * regexpl - Console Registry Explorer
4 *
5 * Copyright (C) 2000,2001 Nedko Arnaoudov <nedkohome@atia.com>
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 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 = NULL)
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 if (!m_hKey)
389 return 0; // the root key abstraction has only subkeys (hives)
390
391 LONG nError = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&rdwMaxValueNameBuferSize,NULL,NULL,NULL);
392
393 rdwMaxValueNameBuferSize++;
394 return nError;
395 }
396
397 void CRegistryKey::InitValueEnumeration(TCHAR *pszValueNameBuffer,
398 DWORD dwValueNameBufferSize,
399 BYTE *pbValueDataBuffer,
400 DWORD dwValueDataBufferSize,
401 DWORD *pdwType)
402 {
403 m_pszValueNameBuffer = pszValueNameBuffer;
404 m_dwValueNameBufferSize = dwValueNameBufferSize;
405 m_pbValueDataBuffer = pbValueDataBuffer;
406 m_dwValueDataBufferSize = dwValueDataBufferSize;
407 m_pdwType = pdwType;
408
409 m_dwCurrentValueIndex = 0;
410 }
411
412
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)
416 {
417 if (!m_hKey)
418 return ERROR_NO_MORE_ITEMS; // the root key abstraction has only subkeys (hives)
419
420 DWORD dwValueNameBufferSize = m_dwValueNameBufferSize;
421 DWORD dwValueDataBufferSize = m_dwValueDataBufferSize;
422 LONG nError = RegEnumValue(m_hKey,
423 m_dwCurrentValueIndex,
424 m_pszValueNameBuffer,
425 &dwValueNameBufferSize,
426 NULL,
427 m_pdwType,
428 m_pbValueDataBuffer,
429 &dwValueDataBufferSize);
430
431 if (pdwNameActualSize)
432 *pdwNameActualSize = dwValueNameBufferSize;
433
434 if (pdwDataActualSize)
435 *pdwDataActualSize = dwValueDataBufferSize;
436
437 m_dwCurrentValueIndex++;
438 return nError;
439 }
440
441 LONG CRegistryKey::GetValueCount(DWORD& rdwValueCount)
442 {
443 if (!m_hKey)
444 return 0; // the root key abstraction has only subkeys (hives)
445
446 return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,&rdwValueCount,NULL,NULL,NULL,NULL);
447 }
448
449 LONG CRegistryKey::GetDefaultValue(DWORD *pdwType,
450 BYTE *pbValueDataBuffer,
451 DWORD dwValueDataBufferSize,
452 DWORD *pdwValueDataActualSize)
453 {
454 DWORD dwBufferSize = dwValueDataBufferSize;
455
456 LONG nError = RegQueryValueEx(m_hKey,NULL,NULL,pdwType,pbValueDataBuffer,&dwBufferSize);
457
458 if (pdwValueDataActualSize && (nError == ERROR_SUCCESS))
459 *pdwValueDataActualSize = dwBufferSize;
460
461 return nError;
462 }
463
464 const TCHAR * CRegistryKey::GetValueTypeName(DWORD dwType)
465 {
466 switch(dwType)
467 {
468 case REG_NONE:
469 return _T("REG_NONE");
470 case REG_SZ:
471 return _T("REG_SZ");
472 case REG_EXPAND_SZ:
473 return _T("REG_EXPAND_SZ");
474 case REG_BINARY:
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");
480 case REG_LINK:
481 return _T("REG_LINK");
482 case REG_MULTI_SZ:
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");
490 default:
491 return _T("Unkown Type");
492 }
493 }
494
495 DWORD CRegistryKey::GetValue(TCHAR *pchValueName, DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize)
496 {
497 return RegQueryValueEx(m_hKey,pchValueName,NULL,pdwType,lpValueDataBuffer,pdwValueDataSize);
498 }
499
500 LONG CRegistryKey::CreateSubkey(REGSAM samDesired,
501 const TCHAR *pszSubkeyName,
502 HKEY &rhKey,
503 BOOL *pblnOpened,
504 BOOL blnVolatile)
505 {
506 DWORD dwDisposition;
507
508 LONG nError = RegCreateKeyEx(
509 m_hKey,
510 pszSubkeyName,
511 0,
512 NULL,
513 blnVolatile?REG_OPTION_VOLATILE:REG_OPTION_NON_VOLATILE,
514 samDesired,
515 NULL,
516 &rhKey,
517 &dwDisposition);
518
519 if ((nError == ERROR_SUCCESS)&&(pblnOpened))
520 *pblnOpened = dwDisposition == REG_OPENED_EXISTING_KEY;
521
522 return nError;
523 }
524
525 LONG CRegistryKey::GetLastWriteTime(SYSTEMTIME &st)
526 {
527 FILETIME ftLocal,ft;
528 LONG nError = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&ft);
529
530 if (nError == ERROR_SUCCESS)
531 {
532 FileTimeToLocalFileTime(&ft,&ftLocal);
533 FileTimeToSystemTime(&ftLocal,&st);
534 }
535
536 return nError;
537 }
538
539 const TCHAR * CRegistryKey::GetLastWriteTime()
540 {
541 SYSTEMTIME st;
542 if (GetLastWriteTime(st) != ERROR_SUCCESS)
543 return _T("(Cannot get time last write time)");
544
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);
547 return Buffer;
548 }
549
550 LONG CRegistryKey::GetSecurityDescriptorLength(DWORD *pdwSecurityDescriptor)
551 {
552 return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
553 NULL,NULL,pdwSecurityDescriptor,NULL);
554 }
555
556 LONG CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
557 {
558 return RegGetKeySecurity(m_hKey,SecurityInformation,pSecurityDescriptor,lpcbSecurityDescriptor);
559 }
560
561 LONG CRegistryKey::DeleteSubkey(const TCHAR *pszSubkeyName)
562 {
563 return RegDeleteKey(m_hKey,pszSubkeyName);
564 }
565
566 LONG CRegistryKey::SetValue(LPCTSTR pszValueName, DWORD dwType, BYTE *lpData, DWORD dwDataSize)
567 {
568 return RegSetValueEx(m_hKey,pszValueName,0,dwType,lpData,dwDataSize);
569 }
570
571 LONG CRegistryKey::DeleteValue(const TCHAR *pszValueName)
572 {
573 return RegDeleteValue(m_hKey,pszValueName);
574 }