Remove ole32 from api status
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / registry.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2001, 2002 Eric Kohl
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; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <freeldr.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 static FRLDRHKEY RootKey;
27
28
29 VOID
30 RegInitializeRegistry (VOID)
31 {
32 #if 0
33 FRLDRHKEY TestKey;
34 #endif
35
36 /* Create root key */
37 RootKey = (FRLDRHKEY) MmAllocateMemory (sizeof(KEY));
38
39 InitializeListHead (&RootKey->SubKeyList);
40 InitializeListHead (&RootKey->ValueList);
41 InitializeListHead (&RootKey->KeyList);
42
43 RootKey->SubKeyCount = 0;
44 RootKey->ValueCount = 0;
45
46 RootKey->NameSize = 4;
47 RootKey->Name = MmAllocateMemory (4);
48 wcscpy (RootKey->Name, L"\\");
49
50 RootKey->DataType = 0;
51 RootKey->DataSize = 0;
52 RootKey->Data = NULL;
53
54 /* Create 'SYSTEM' key */
55 RegCreateKey (RootKey,
56 L"Registry\\Machine\\SYSTEM",
57 NULL);
58
59 /* Create 'HARDWARE' key */
60 RegCreateKey (RootKey,
61 L"Registry\\Machine\\HARDWARE",
62 NULL);
63
64 /* Create 'HARDWARE\DESCRIPTION' key */
65 RegCreateKey (RootKey,
66 L"Registry\\Machine\\HARDWARE\\DESCRIPTION",
67 NULL);
68
69 /* Create 'HARDWARE\DEVICEMAP' key */
70 RegCreateKey (RootKey,
71 L"Registry\\Machine\\HARDWARE\\DEVICEMAP",
72 NULL);
73
74 /* Create 'HARDWARE\RESOURCEMAP' key */
75 RegCreateKey (RootKey,
76 L"Registry\\Machine\\HARDWARE\\RESOURCEMAP",
77 NULL);
78
79 /* Testcode */
80 #if 0
81 RegCreateKey (RootKey,
82 L"Registry\\Machine\\HARDWARE\\DESCRIPTION\\TestKey",
83 &TestKey);
84
85 RegSetValue (TestKey,
86 L"TestValue",
87 REG_SZ,
88 (PUCHAR)"TestString",
89 11);
90 #endif
91 }
92
93
94 LONG
95 RegInitCurrentControlSet(BOOL LastKnownGood)
96 {
97 WCHAR ControlSetKeyName[80];
98 FRLDRHKEY SelectKey;
99 FRLDRHKEY SystemKey;
100 FRLDRHKEY ControlSetKey;
101 FRLDRHKEY LinkKey;
102 ULONG CurrentSet = 0;
103 ULONG DefaultSet = 0;
104 ULONG LastKnownGoodSet = 0;
105 ULONG DataSize;
106 LONG Error;
107
108 Error = RegOpenKey(NULL,
109 L"\\Registry\\Machine\\SYSTEM\\Select",
110 &SelectKey);
111 if (Error != ERROR_SUCCESS)
112 {
113 DbgPrint((DPRINT_REGISTRY, "RegOpenKey() failed (Error %u)\n", (int)Error));
114 return(Error);
115 }
116
117 DataSize = sizeof(ULONG);
118 Error = RegQueryValue(SelectKey,
119 L"Default",
120 NULL,
121 (PUCHAR)&DefaultSet,
122 &DataSize);
123 if (Error != ERROR_SUCCESS)
124 {
125 DbgPrint((DPRINT_REGISTRY, "RegQueryValue('Default') failed (Error %u)\n", (int)Error));
126 return(Error);
127 }
128
129 DataSize = sizeof(ULONG);
130 Error = RegQueryValue(SelectKey,
131 L"LastKnownGood",
132 NULL,
133 (PUCHAR)&LastKnownGoodSet,
134 &DataSize);
135 if (Error != ERROR_SUCCESS)
136 {
137 DbgPrint((DPRINT_REGISTRY, "RegQueryValue('Default') failed (Error %u)\n", (int)Error));
138 return(Error);
139 }
140
141 CurrentSet = (LastKnownGood == TRUE) ? LastKnownGoodSet : DefaultSet;
142 wcscpy(ControlSetKeyName, L"ControlSet");
143 switch(CurrentSet)
144 {
145 case 1:
146 wcscat(ControlSetKeyName, L"001");
147 break;
148 case 2:
149 wcscat(ControlSetKeyName, L"002");
150 break;
151 case 3:
152 wcscat(ControlSetKeyName, L"003");
153 break;
154 case 4:
155 wcscat(ControlSetKeyName, L"004");
156 break;
157 case 5:
158 wcscat(ControlSetKeyName, L"005");
159 break;
160 }
161
162 Error = RegOpenKey(NULL,
163 L"\\Registry\\Machine\\SYSTEM",
164 &SystemKey);
165 if (Error != ERROR_SUCCESS)
166 {
167 DbgPrint((DPRINT_REGISTRY, "RegOpenKey(SystemKey) failed (Error %u)\n", (int)Error));
168 return(Error);
169 }
170
171 Error = RegOpenKey(SystemKey,
172 ControlSetKeyName,
173 &ControlSetKey);
174 if (Error != ERROR_SUCCESS)
175 {
176 DbgPrint((DPRINT_REGISTRY, "RegOpenKey(ControlSetKey) failed (Error %u)\n", (int)Error));
177 return(Error);
178 }
179
180 Error = RegCreateKey(SystemKey,
181 L"CurrentControlSet",
182 &LinkKey);
183 if (Error != ERROR_SUCCESS)
184 {
185 DbgPrint((DPRINT_REGISTRY, "RegCreateKey(LinkKey) failed (Error %u)\n", (int)Error));
186 return(Error);
187 }
188
189 Error = RegSetValue(LinkKey,
190 NULL,
191 REG_LINK,
192 (PCHAR)&ControlSetKey,
193 sizeof(PVOID));
194 if (Error != ERROR_SUCCESS)
195 {
196 DbgPrint((DPRINT_REGISTRY, "RegSetValue(LinkKey) failed (Error %u)\n", (int)Error));
197 return(Error);
198 }
199
200 return(ERROR_SUCCESS);
201 }
202
203
204 LONG
205 RegCreateKey(FRLDRHKEY ParentKey,
206 PCWSTR KeyName,
207 PFRLDRHKEY Key)
208 {
209 PLIST_ENTRY Ptr;
210 FRLDRHKEY SearchKey = NULL;
211 FRLDRHKEY CurrentKey;
212 FRLDRHKEY NewKey;
213 PWCHAR p;
214 PCWSTR name;
215 int subkeyLength;
216 int stringLength;
217 ULONG NameSize;
218
219 DbgPrint((DPRINT_REGISTRY, "KeyName '%S'\n", KeyName));
220
221 if (*KeyName == L'\\')
222 {
223 KeyName++;
224 CurrentKey = RootKey;
225 }
226 else if (ParentKey == NULL)
227 {
228 CurrentKey = RootKey;
229 }
230 else
231 {
232 CurrentKey = ParentKey;
233 }
234
235 /* Check whether current key is a link */
236 if (CurrentKey->DataType == REG_LINK)
237 {
238 CurrentKey = (FRLDRHKEY)CurrentKey->Data;
239 }
240
241 while (*KeyName != 0)
242 {
243 DbgPrint((DPRINT_REGISTRY, "KeyName '%S'\n", KeyName));
244
245 if (*KeyName == L'\\')
246 KeyName++;
247 p = wcschr(KeyName, L'\\');
248 if ((p != NULL) && (p != KeyName))
249 {
250 subkeyLength = p - KeyName;
251 stringLength = subkeyLength + 1;
252 name = KeyName;
253 }
254 else
255 {
256 subkeyLength = wcslen(KeyName);
257 stringLength = subkeyLength;
258 name = KeyName;
259 }
260 NameSize = (subkeyLength + 1) * sizeof(WCHAR);
261
262 Ptr = CurrentKey->SubKeyList.Flink;
263 while (Ptr != &CurrentKey->SubKeyList)
264 {
265 DbgPrint((DPRINT_REGISTRY, "Ptr 0x%x\n", Ptr));
266
267 SearchKey = CONTAINING_RECORD(Ptr,
268 KEY,
269 KeyList);
270 DbgPrint((DPRINT_REGISTRY, "SearchKey 0x%x\n", SearchKey));
271 DbgPrint((DPRINT_REGISTRY, "Searching '%S'\n", SearchKey->Name));
272 if (SearchKey->NameSize == NameSize &&
273 _wcsnicmp(SearchKey->Name, name, subkeyLength) == 0)
274 break;
275
276 Ptr = Ptr->Flink;
277 }
278
279 if (Ptr == &CurrentKey->SubKeyList)
280 {
281 /* no key found -> create new subkey */
282 NewKey = (FRLDRHKEY)MmAllocateMemory(sizeof(KEY));
283 if (NewKey == NULL)
284 return(ERROR_OUTOFMEMORY);
285
286 InitializeListHead(&NewKey->SubKeyList);
287 InitializeListHead(&NewKey->ValueList);
288
289 NewKey->SubKeyCount = 0;
290 NewKey->ValueCount = 0;
291
292 NewKey->DataType = 0;
293 NewKey->DataSize = 0;
294 NewKey->Data = NULL;
295
296 InsertTailList(&CurrentKey->SubKeyList, &NewKey->KeyList);
297 CurrentKey->SubKeyCount++;
298
299 NewKey->NameSize = NameSize;
300 NewKey->Name = (PWCHAR)MmAllocateMemory(NewKey->NameSize);
301 if (NewKey->Name == NULL)
302 return(ERROR_OUTOFMEMORY);
303 memcpy(NewKey->Name, name, NewKey->NameSize - sizeof(WCHAR));
304 NewKey->Name[subkeyLength] = 0;
305
306 DbgPrint((DPRINT_REGISTRY, "NewKey 0x%x\n", NewKey));
307 DbgPrint((DPRINT_REGISTRY, "NewKey '%S' Length %d\n", NewKey->Name, NewKey->NameSize));
308
309 CurrentKey = NewKey;
310 }
311 else
312 {
313 CurrentKey = SearchKey;
314
315 /* Check whether current key is a link */
316 if (CurrentKey->DataType == REG_LINK)
317 {
318 CurrentKey = (FRLDRHKEY)CurrentKey->Data;
319 }
320 }
321
322 KeyName = KeyName + stringLength;
323 }
324
325 if (Key != NULL)
326 *Key = CurrentKey;
327
328 return(ERROR_SUCCESS);
329 }
330
331
332 LONG
333 RegDeleteKey(FRLDRHKEY Key,
334 PCWSTR Name)
335 {
336
337
338 if (wcschr(Name, L'\\') != NULL)
339 return(ERROR_INVALID_PARAMETER);
340
341
342
343 return(ERROR_SUCCESS);
344 }
345
346
347 LONG
348 RegEnumKey(FRLDRHKEY Key,
349 ULONG Index,
350 PWCHAR Name,
351 ULONG* NameSize)
352 {
353 PLIST_ENTRY Ptr;
354 FRLDRHKEY SearchKey;
355 ULONG Count = 0;
356 ULONG Size;
357
358 Ptr = Key->SubKeyList.Flink;
359 while (Ptr != &Key->SubKeyList)
360 {
361 if (Index == Count)
362 break;
363
364 Count++;
365 Ptr = Ptr->Flink;
366 }
367
368 if (Ptr == &Key->SubKeyList)
369 return(ERROR_NO_MORE_ITEMS);
370
371 SearchKey = CONTAINING_RECORD(Ptr,
372 KEY,
373 KeyList);
374
375 DbgPrint((DPRINT_REGISTRY, "Name '%S' Length %d\n", SearchKey->Name, SearchKey->NameSize));
376
377 Size = min(SearchKey->NameSize, *NameSize);
378 *NameSize = Size;
379 memcpy(Name, SearchKey->Name, Size);
380
381 return(ERROR_SUCCESS);
382 }
383
384
385 LONG
386 RegOpenKey(FRLDRHKEY ParentKey,
387 PCWSTR KeyName,
388 PFRLDRHKEY Key)
389 {
390 PLIST_ENTRY Ptr;
391 FRLDRHKEY SearchKey = NULL;
392 FRLDRHKEY CurrentKey;
393 PWCHAR p;
394 PCWSTR name;
395 int subkeyLength;
396 int stringLength;
397 ULONG NameSize;
398
399 DbgPrint((DPRINT_REGISTRY, "KeyName '%S'\n", KeyName));
400
401 *Key = NULL;
402
403 if (*KeyName == L'\\')
404 {
405 KeyName++;
406 CurrentKey = RootKey;
407 }
408 else if (ParentKey == NULL)
409 {
410 CurrentKey = RootKey;
411 }
412 else
413 {
414 CurrentKey = ParentKey;
415 }
416
417 /* Check whether current key is a link */
418 if (CurrentKey->DataType == REG_LINK)
419 {
420 CurrentKey = (FRLDRHKEY)CurrentKey->Data;
421 }
422
423 while (*KeyName != 0)
424 {
425 DbgPrint((DPRINT_REGISTRY, "KeyName '%S'\n", KeyName));
426
427 if (*KeyName == L'\\')
428 KeyName++;
429 p = wcschr(KeyName, L'\\');
430 if ((p != NULL) && (p != KeyName))
431 {
432 subkeyLength = p - KeyName;
433 stringLength = subkeyLength + 1;
434 name = KeyName;
435 }
436 else
437 {
438 subkeyLength = wcslen(KeyName);
439 stringLength = subkeyLength;
440 name = KeyName;
441 }
442 NameSize = (subkeyLength + 1) * sizeof(WCHAR);
443
444 Ptr = CurrentKey->SubKeyList.Flink;
445 while (Ptr != &CurrentKey->SubKeyList)
446 {
447 DbgPrint((DPRINT_REGISTRY, "Ptr 0x%x\n", Ptr));
448
449 SearchKey = CONTAINING_RECORD(Ptr,
450 KEY,
451 KeyList);
452
453 DbgPrint((DPRINT_REGISTRY, "SearchKey 0x%x\n", SearchKey));
454 DbgPrint((DPRINT_REGISTRY, "Searching '%S'\n", SearchKey->Name));
455
456 if (SearchKey->NameSize == NameSize &&
457 _wcsnicmp(SearchKey->Name, name, subkeyLength) == 0)
458 break;
459
460 Ptr = Ptr->Flink;
461 }
462
463 if (Ptr == &CurrentKey->SubKeyList)
464 {
465 return(ERROR_PATH_NOT_FOUND);
466 }
467 else
468 {
469 CurrentKey = SearchKey;
470
471 /* Check whether current key is a link */
472 if (CurrentKey->DataType == REG_LINK)
473 {
474 CurrentKey = (FRLDRHKEY)CurrentKey->Data;
475 }
476 }
477
478 KeyName = KeyName + stringLength;
479 }
480
481 if (Key != NULL)
482 *Key = CurrentKey;
483
484 return(ERROR_SUCCESS);
485 }
486
487
488 LONG
489 RegSetValue(FRLDRHKEY Key,
490 PCWSTR ValueName,
491 ULONG Type,
492 PCSTR Data,
493 ULONG DataSize)
494 {
495 PLIST_ENTRY Ptr;
496 PVALUE Value = NULL;
497
498 DbgPrint((DPRINT_REGISTRY, "Key 0x%x, ValueName '%S', Type %d, Data 0x%x, DataSize %d\n",
499 (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize));
500
501 if ((ValueName == NULL) || (*ValueName == 0))
502 {
503 /* set default value */
504 if ((Key->Data != NULL) && (Key->DataSize > sizeof(PUCHAR)))
505 {
506 MmFreeMemory(Key->Data);
507 }
508
509 if (DataSize <= sizeof(PUCHAR))
510 {
511 Key->DataSize = DataSize;
512 Key->DataType = Type;
513 memcpy(&Key->Data, Data, DataSize);
514 }
515 else
516 {
517 Key->Data = MmAllocateMemory(DataSize);
518 Key->DataSize = DataSize;
519 Key->DataType = Type;
520 memcpy(Key->Data, Data, DataSize);
521 }
522 }
523 else
524 {
525 /* set non-default value */
526 Ptr = Key->ValueList.Flink;
527 while (Ptr != &Key->ValueList)
528 {
529 Value = CONTAINING_RECORD(Ptr,
530 VALUE,
531 ValueList);
532
533 DbgPrint((DPRINT_REGISTRY, "Value->Name '%S'\n", Value->Name));
534
535 if (_wcsicmp(Value->Name, ValueName) == 0)
536 break;
537
538 Ptr = Ptr->Flink;
539 }
540
541 if (Ptr == &Key->ValueList)
542 {
543 /* add new value */
544 DbgPrint((DPRINT_REGISTRY, "No value found - adding new value\n"));
545
546 Value = (PVALUE)MmAllocateMemory(sizeof(VALUE));
547 if (Value == NULL)
548 return(ERROR_OUTOFMEMORY);
549
550 InsertTailList(&Key->ValueList, &Value->ValueList);
551 Key->ValueCount++;
552
553 Value->NameSize = (wcslen(ValueName)+1)*sizeof(WCHAR);
554 Value->Name = (PWCHAR)MmAllocateMemory(Value->NameSize);
555 if (Value->Name == NULL)
556 return(ERROR_OUTOFMEMORY);
557 wcscpy(Value->Name, ValueName);
558 Value->DataType = REG_NONE;
559 Value->DataSize = 0;
560 Value->Data = NULL;
561 }
562
563 /* set new value */
564 if ((Value->Data != NULL) && (Value->DataSize > sizeof(PUCHAR)))
565 {
566 MmFreeMemory(Value->Data);
567 }
568
569 if (DataSize <= sizeof(PUCHAR))
570 {
571 Value->DataSize = DataSize;
572 Value->DataType = Type;
573 memcpy(&Value->Data, Data, DataSize);
574 }
575 else
576 {
577 Value->Data = MmAllocateMemory(DataSize);
578 if (Value->Data == NULL)
579 return(ERROR_OUTOFMEMORY);
580 Value->DataType = Type;
581 Value->DataSize = DataSize;
582 memcpy(Value->Data, Data, DataSize);
583 }
584 }
585 return(ERROR_SUCCESS);
586 }
587
588
589 LONG
590 RegQueryValue(FRLDRHKEY Key,
591 PCWSTR ValueName,
592 ULONG* Type,
593 PUCHAR Data,
594 ULONG* DataSize)
595 {
596 ULONG Size;
597 PLIST_ENTRY Ptr;
598 PVALUE Value = NULL;
599
600 if ((ValueName == NULL) || (*ValueName == 0))
601 {
602 /* query default value */
603 if (Key->Data == NULL)
604 return(ERROR_INVALID_PARAMETER);
605
606 if (Type != NULL)
607 *Type = Key->DataType;
608 if ((Data != NULL) && (DataSize != NULL))
609 {
610 if (Key->DataSize <= sizeof(PUCHAR))
611 {
612 Size = min(Key->DataSize, *DataSize);
613 memcpy(Data, &Key->Data, Size);
614 *DataSize = Size;
615 }
616 else
617 {
618 Size = min(Key->DataSize, *DataSize);
619 memcpy(Data, Key->Data, Size);
620 *DataSize = Size;
621 }
622 }
623 else if ((Data == NULL) && (DataSize != NULL))
624 {
625 *DataSize = Key->DataSize;
626 }
627 }
628 else
629 {
630 /* query non-default value */
631 Ptr = Key->ValueList.Flink;
632 while (Ptr != &Key->ValueList)
633 {
634 Value = CONTAINING_RECORD(Ptr,
635 VALUE,
636 ValueList);
637
638 DbgPrint((DPRINT_REGISTRY, "Searching for '%S'. Value name '%S'\n", ValueName, Value->Name));
639
640 if (_wcsicmp(Value->Name, ValueName) == 0)
641 break;
642
643 Ptr = Ptr->Flink;
644 }
645
646 if (Ptr == &Key->ValueList)
647 return(ERROR_INVALID_PARAMETER);
648
649 if (Type != NULL)
650 *Type = Value->DataType;
651 if ((Data != NULL) && (DataSize != NULL))
652 {
653 if (Value->DataSize <= sizeof(PUCHAR))
654 {
655 Size = min(Value->DataSize, *DataSize);
656 memcpy(Data, &Value->Data, Size);
657 *DataSize = Size;
658 }
659 else
660 {
661 Size = min(Value->DataSize, *DataSize);
662 memcpy(Data, Value->Data, Size);
663 *DataSize = Size;
664 }
665 }
666 else if ((Data == NULL) && (DataSize != NULL))
667 {
668 *DataSize = Value->DataSize;
669 }
670 }
671
672 return(ERROR_SUCCESS);
673 }
674
675
676 LONG
677 RegDeleteValue(FRLDRHKEY Key,
678 PCWSTR ValueName)
679 {
680 PLIST_ENTRY Ptr;
681 PVALUE Value = NULL;
682
683 if ((ValueName == NULL) || (*ValueName == 0))
684 {
685 /* delete default value */
686 if (Key->Data != NULL)
687 MmFreeMemory(Key->Data);
688 Key->Data = NULL;
689 Key->DataSize = 0;
690 Key->DataType = 0;
691 }
692 else
693 {
694 /* delete non-default value */
695 Ptr = Key->ValueList.Flink;
696 while (Ptr != &Key->ValueList)
697 {
698 Value = CONTAINING_RECORD(Ptr,
699 VALUE,
700 ValueList);
701 if (_wcsicmp(Value->Name, ValueName) == 0)
702 break;
703
704 Ptr = Ptr->Flink;
705 }
706
707 if (Ptr == &Key->ValueList)
708 return(ERROR_INVALID_PARAMETER);
709
710 /* delete value */
711 Key->ValueCount--;
712 if (Value->Name != NULL)
713 MmFreeMemory(Value->Name);
714 Value->Name = NULL;
715 Value->NameSize = 0;
716
717 if (Value->DataSize > sizeof(PUCHAR))
718 {
719 if (Value->Data != NULL)
720 MmFreeMemory(Value->Data);
721 }
722 Value->Data = NULL;
723 Value->DataSize = 0;
724 Value->DataType = 0;
725
726 RemoveEntryList(&Value->ValueList);
727 MmFreeMemory(Value);
728 }
729 return(ERROR_SUCCESS);
730 }
731
732
733 LONG
734 RegEnumValue(FRLDRHKEY Key,
735 ULONG Index,
736 PWCHAR ValueName,
737 ULONG* NameSize,
738 ULONG* Type,
739 PUCHAR Data,
740 ULONG* DataSize)
741 {
742 PLIST_ENTRY Ptr;
743 PVALUE Value;
744 ULONG Count = 0;
745
746 if (Key->Data != NULL)
747 {
748 if (Index > 0)
749 {
750 Index--;
751 }
752 else
753 {
754 /* enumerate default value */
755 if (ValueName != NULL)
756 *ValueName = 0;
757 if (Type != NULL)
758 *Type = Key->DataType;
759 if (Data != NULL)
760 {
761 if (Key->DataSize <= sizeof(PUCHAR))
762 {
763 memcpy(Data, &Key->Data, min(Key->DataSize, *DataSize));
764 }
765 else
766 {
767 memcpy(Data, Key->Data, min(Key->DataSize, *DataSize));
768 }
769 }
770 if (DataSize != NULL)
771 *DataSize = min(Key->DataSize, *DataSize);
772
773 return(ERROR_SUCCESS);
774 }
775 }
776
777 Ptr = Key->ValueList.Flink;
778 while (Ptr != &Key->ValueList)
779 {
780 if (Index == Count)
781 break;
782
783 Count++;
784 Ptr = Ptr->Flink;
785 }
786
787 if (Ptr == &Key->ValueList)
788 return(ERROR_NO_MORE_ITEMS);
789
790 Value = CONTAINING_RECORD(Ptr,
791 VALUE,
792 ValueList);
793
794 /* enumerate non-default value */
795 if (ValueName != NULL)
796 memcpy(ValueName, Value->Name, min(Value->NameSize, *NameSize));
797 if (Type != NULL)
798 *Type = Value->DataType;
799
800 if (Data != NULL)
801 {
802 if (Value->DataSize <= sizeof(PUCHAR))
803 {
804 memcpy(Data, &Value->Data, min(Value->DataSize, *DataSize));
805 }
806 else
807 {
808 memcpy(Data, Value->Data, min(Value->DataSize, *DataSize));
809 }
810 }
811
812 if (DataSize != NULL)
813 *DataSize = min(Value->DataSize, *DataSize);
814
815 return(ERROR_SUCCESS);
816 }
817
818
819 ULONG
820 RegGetSubKeyCount (FRLDRHKEY Key)
821 {
822 return Key->SubKeyCount;
823 }
824
825
826 ULONG
827 RegGetValueCount (FRLDRHKEY Key)
828 {
829 if (Key->DataSize != 0)
830 return Key->ValueCount + 1;
831
832 return Key->ValueCount;
833 }
834
835 /* EOF */