ReactOS 0.4.16-dev-334-g4d9f67c
registry.c
Go to the documentation of this file.
1/*
2 * FreeLoader
3 *
4 * Copyright (C) 2014 Timo Kreuzer <timo.kreuzer@reactos.org>
5 * 2022 George Bișoc <george.bisoc@reactos.org>
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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#include <freeldr.h>
23#include <cmlib.h>
24#include "registry.h"
25#include <internal/cmboot.h>
26
27#include <debug.h>
29
32
35
36#define HCI_TO_HKEY(CellIndex) ((HKEY)(ULONG_PTR)(CellIndex))
37#ifndef HKEY_TO_HCI // See also registry.h
38#define HKEY_TO_HCI(hKey) ((HCELL_INDEX)(ULONG_PTR)(hKey))
39#endif
40
41#define GET_HHIVE(CmHive) (&((CmHive)->Hive))
42#define GET_HHIVE_FROM_HKEY(hKey) GET_HHIVE(CmSystemHive)
43#define GET_CM_KEY_NODE(hHive, hKey) ((PCM_KEY_NODE)HvGetCell(hHive, HKEY_TO_HCI(hKey)))
44
45#define GET_HBASE_BLOCK(ChunkBase) ((PHBASE_BLOCK)ChunkBase)
46
51 IN BOOLEAN Paged,
52 IN ULONG Tag)
53{
55 return FrLdrHeapAlloc(Size, Tag);
56}
57
58VOID
61 IN PVOID Ptr,
62 IN ULONG Quota)
63{
66}
67
94static
97 _In_ PCMHIVE CmHive,
98 _In_ PVOID ChunkBase,
99 _In_ BOOLEAN LoadAlternate)
100{
102/*
103 * FIXME: Disable compilation of some parts of code for AMD64 for now,
104 * since it makes the FreeLdr binary size so large that it prevents
105 * x64 ROS from booting.
106 */
107#if !defined(_M_AMD64)
108 CM_CHECK_REGISTRY_STATUS CmStatusCode;
109#endif
110
111 /* Initialize the hive */
112 Status = HvInitialize(GET_HHIVE(CmHive),
113 HINIT_FLAT, // HINIT_MEMORY_INPLACE
114 0,
116 ChunkBase,
118 CmpFree,
119 NULL,
120 NULL,
121 NULL,
122 NULL,
123 1,
124 NULL);
125 if (!NT_SUCCESS(Status))
126 {
127 ERR("Failed to initialize the flat hive (Status 0x%lx)\n", Status);
128 return FALSE;
129 }
130
131/* FIXME: See the comment above */
132#if !defined(_M_AMD64)
133 /* Now check the hive and purge volatile data */
135 if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode))
136 {
137 ERR("CmCheckRegistry detected problems with the loaded flat hive (check code %lu)\n", CmStatusCode);
138 return FALSE;
139 }
140#endif
141
142 return TRUE;
143}
144
145/* FIXME: See the comment above */
146#if !defined(_M_AMD64)
180static
183 _In_ PCSTR DirectoryPath,
184 _In_ ULONG LogFileOffset,
185 _In_ PCSTR LogName,
186 _Out_ PVOID *LogData)
187{
189 ULONG LogId;
190 CHAR LogPath[MAX_PATH];
191 ULONG LogFileSize;
195 PVOID LogDataVirtual;
196 PVOID LogDataPhysical;
197
198 /* Build the full path to the hive log */
199 RtlStringCbCopyA(LogPath, sizeof(LogPath), DirectoryPath);
200 RtlStringCbCatA(LogPath, sizeof(LogPath), LogName);
201
202 /* Open the file */
203 Status = ArcOpen(LogPath, OpenReadOnly, &LogId);
204 if (Status != ESUCCESS)
205 {
206 ERR("Failed to open %s (ARC code %lu)\n", LogName, Status);
207 return FALSE;
208 }
209
210 /* Get the file length */
212 if (Status != ESUCCESS)
213 {
214 ERR("Failed to get file information from %s (ARC code %lu)\n", LogName, Status);
215 ArcClose(LogId);
216 return FALSE;
217 }
218
219 /* Capture the size of the hive log file */
220 LogFileSize = FileInfo.EndingAddress.LowPart;
221 if (LogFileSize == 0)
222 {
223 ERR("LogFileSize is 0, %s is corrupt\n", LogName);
224 ArcClose(LogId);
225 return FALSE;
226 }
227
228 /* Allocate memory blocks for our log data */
229 LogDataPhysical = MmAllocateMemoryWithType(
230 MM_SIZE_TO_PAGES(LogFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT,
232 if (LogDataPhysical == NULL)
233 {
234 ERR("Failed to allocate memory for log data\n");
235 ArcClose(LogId);
236 return FALSE;
237 }
238
239 /* Convert the address to virtual so that it can be useable */
240 LogDataVirtual = PaToVa(LogDataPhysical);
241
242 /* Seek within the log file at desired position */
243 Position.QuadPart = LogFileOffset;
245 if (Status != ESUCCESS)
246 {
247 ERR("Failed to seek at %s (ARC code %lu)\n", LogName, Status);
248 ArcClose(LogId);
249 return FALSE;
250 }
251
252 /* And read the actual data from the log */
253 Status = ArcRead(LogId, LogDataPhysical, LogFileSize, &BytesRead);
254 if (Status != ESUCCESS)
255 {
256 ERR("Failed to read %s (ARC code %lu)\n", LogName, Status);
257 ArcClose(LogId);
258 return FALSE;
259 }
260
261 *LogData = LogDataVirtual;
262 ArcClose(LogId);
263 return TRUE;
264}
265
287static
290 _Inout_ PVOID ChunkBase,
291 _In_ PCSTR DirectoryPath,
292 _In_ PCSTR LogName)
293{
295 CHAR FullLogFileName[MAX_PATH];
296 PVOID LogData;
297 PHBASE_BLOCK HiveBaseBlock;
298 PHBASE_BLOCK LogBaseBlock;
299
300 /* Build the complete path of the hive log */
301 RtlStringCbCopyA(FullLogFileName, sizeof(FullLogFileName), LogName);
302 RtlStringCbCatA(FullLogFileName, sizeof(FullLogFileName), ".LOG");
303 Success = RegLoadHiveLog(DirectoryPath, 0, FullLogFileName, &LogData);
304 if (!Success)
305 {
306 ERR("Failed to read the hive log\n");
307 return FALSE;
308 }
309
310 /* Make sure the header from the hive log is actually sane */
311 LogData = VaToPa(LogData);
312 LogBaseBlock = GET_HBASE_BLOCK(LogData);
313 if (!HvpVerifyHiveHeader(LogBaseBlock, HFILE_TYPE_LOG))
314 {
315 ERR("The hive log has corrupt base block\n");
316 return FALSE;
317 }
318
319 /* Copy the healthy header base block into the primary hive */
320 HiveBaseBlock = GET_HBASE_BLOCK(ChunkBase);
321 WARN("Recovering the hive base block...\n");
322 RtlCopyMemory(HiveBaseBlock,
323 LogBaseBlock,
324 LogBaseBlock->Cluster * HSECTOR_SIZE);
325 HiveBaseBlock->Type = HFILE_TYPE_PRIMARY;
326 return TRUE;
327}
328
360static
363 _Inout_ PVOID ChunkBase,
364 _In_ PCSTR DirectoryPath,
365 _In_ PCSTR LogName)
366{
368 ULONG StorageLength;
369 ULONG BlockIndex, LogIndex;
370 PUCHAR BlockPtr, BlockDest;
371 CHAR FullLogFileName[MAX_PATH];
372 PVOID LogData;
373 PUCHAR LogDataPhysical;
374 PHBASE_BLOCK HiveBaseBlock;
375
376 /* Build the complete path of the hive log */
377 RtlStringCbCopyA(FullLogFileName, sizeof(FullLogFileName), LogName);
378 RtlStringCbCatA(FullLogFileName, sizeof(FullLogFileName), ".LOG");
379 Success = RegLoadHiveLog(DirectoryPath, HV_LOG_HEADER_SIZE, FullLogFileName, &LogData);
380 if (!Success)
381 {
382 ERR("Failed to read the hive log\n");
383 return FALSE;
384 }
385
386 /* Make sure the dirty vector signature is there otherwise the hive log is corrupt */
387 LogDataPhysical = (PUCHAR)VaToPa(LogData);
388 if (*((PULONG)LogDataPhysical) != HV_LOG_DIRTY_SIGNATURE)
389 {
390 ERR("The hive log dirty signature could not be found\n");
391 return FALSE;
392 }
393
394 /* Copy the dirty data into the primary hive */
395 LogIndex = 0;
396 BlockIndex = 0;
397 HiveBaseBlock = GET_HBASE_BLOCK(ChunkBase);
398 StorageLength = HiveBaseBlock->Length / HBLOCK_SIZE;
399 for (; BlockIndex < StorageLength; ++BlockIndex)
400 {
401 /* Skip this block if it's not dirty and go to the next one */
402 if (LogDataPhysical[BlockIndex + sizeof(HV_LOG_DIRTY_SIGNATURE)] != HV_LOG_DIRTY_BLOCK)
403 {
404 continue;
405 }
406
407 /* Read the dirty block and copy it at right offsets */
408 BlockPtr = (PUCHAR)((ULONG_PTR)LogDataPhysical + 2 * HSECTOR_SIZE + LogIndex * HBLOCK_SIZE);
409 BlockDest = (PUCHAR)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HBLOCK_SIZE);
410 RtlCopyMemory(BlockDest, BlockPtr, HBLOCK_SIZE);
411
412 /* Increment the index in log as we continue further */
413 LogIndex++;
414 }
415
416 /* Fix the secondary sequence of the primary hive and compute a new checksum */
417 HiveBaseBlock->Sequence2 = HiveBaseBlock->Sequence1;
418 HiveBaseBlock->CheckSum = HvpHiveHeaderChecksum(HiveBaseBlock);
419 return TRUE;
420}
421#endif
422
450 _In_ PVOID ChunkBase,
453 _In_ BOOLEAN LoadAlternate)
454{
456 PCM_KEY_NODE KeyNode;
457
458 TRACE("RegImportBinaryHive(%p, 0x%lx)\n", ChunkBase, ChunkSize);
459
460 /* Assume that we don't need boot recover, unless we have to */
461 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_NO_BOOT_RECOVER;
462
463 /* Allocate and initialize the hive */
464 CmSystemHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
465 Success = RegInitializeHive(CmSystemHive, ChunkBase, LoadAlternate);
466 if (!Success)
467/* FIXME: See the comment above */
468#if defined(_M_AMD64)
469 {
470 ERR("Corrupted hive %p!\n", ChunkBase);
472 return FALSE;
473 }
474#else
475 {
476 /* Free the buffer and retry again */
479
480 if (!RegRecoverHeaderHive(ChunkBase, SearchPath, "SYSTEM"))
481 {
482 ERR("Failed to recover the hive header block\n");
483 return FALSE;
484 }
485
486 if (!RegRecoverDataHive(ChunkBase, SearchPath, "SYSTEM"))
487 {
488 ERR("Failed to recover the hive data\n");
489 return FALSE;
490 }
491
492 /* Now retry initializing the hive again */
493 CmSystemHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
494 Success = RegInitializeHive(CmSystemHive, ChunkBase, LoadAlternate);
495 if (!Success)
496 {
497 ERR("Corrupted hive (despite recovery) %p\n", ChunkBase);
499 return FALSE;
500 }
501
502 /*
503 * Acknowledge the kernel we recovered the SYSTEM hive
504 * on our side by applying log data.
505 */
506 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_BOOT_RECOVERED_BY_HIVE_LOG;
507 }
508#endif
509
510 /* Save the root key node */
514
515 /* Verify it is accessible */
517 ASSERT(KeyNode);
520
521 return TRUE;
522}
523
526 _In_ BOOLEAN LastKnownGood)
527{
528 UNICODE_STRING ControlSetName;
529 HCELL_INDEX ControlCell;
530 PCM_KEY_NODE KeyNode;
531 BOOLEAN AutoSelect;
532
533 TRACE("RegInitCurrentControlSet\n");
534
535 /* Choose which control set to open and set it as the new "Current" */
536 RtlInitUnicodeString(&ControlSetName,
537 LastKnownGood ? L"LastKnownGood"
538 : L"Default");
539
540 ControlCell = CmpFindControlSet(SystemHive,
542 &ControlSetName,
543 &AutoSelect);
544 if (ControlCell == HCELL_NIL)
545 {
546 ERR("CmpFindControlSet('%wZ') failed\n", &ControlSetName);
547 return FALSE;
548 }
549
550 CurrentControlSetKey = HCI_TO_HKEY(ControlCell);
551
552 /* Verify it is accessible */
553 KeyNode = (PCM_KEY_NODE)HvGetCell(SystemHive, ControlCell);
554 ASSERT(KeyNode);
556 HvReleaseCell(SystemHive, ControlCell);
557
558 return TRUE;
559}
560
561static
564 _Out_ PUNICODE_STRING NextElement,
565 _Inout_ PUNICODE_STRING RemainingPath)
566{
567 /* Check if there are any characters left */
568 if (RemainingPath->Length < sizeof(WCHAR))
569 {
570 /* Nothing left, bail out early */
571 return FALSE;
572 }
573
574 /* The next path elements starts with the remaining path */
575 NextElement->Buffer = RemainingPath->Buffer;
576
577 /* Loop until the path element ends */
578 while ((RemainingPath->Length >= sizeof(WCHAR)) &&
579 (RemainingPath->Buffer[0] != '\\'))
580 {
581 /* Skip this character */
582 RemainingPath->Buffer++;
583 RemainingPath->Length -= sizeof(WCHAR);
584 }
585
586 NextElement->Length = (USHORT)(RemainingPath->Buffer - NextElement->Buffer) * sizeof(WCHAR);
587 NextElement->MaximumLength = NextElement->Length;
588
589 /* Check if the path element ended with a path separator */
590 if (RemainingPath->Length >= sizeof(WCHAR))
591 {
592 /* Skip the path separator */
593 ASSERT(RemainingPath->Buffer[0] == '\\');
594 RemainingPath->Buffer++;
595 RemainingPath->Length -= sizeof(WCHAR);
596 }
597
598 /* Return whether we got any characters */
599 return TRUE;
600}
601
602#if 0
603LONG
605 _In_ HKEY Key,
608 _Inout_ PULONG NameSize,
609 _Out_opt_ PHKEY SubKey)
610{
612 PCM_KEY_NODE KeyNode, SubKeyNode;
613 HCELL_INDEX CellIndex;
614 USHORT NameLength;
615
616 TRACE("RegEnumKey(%p, %lu, %p, %p->%u)\n",
617 Key, Index, Name, NameSize, NameSize ? *NameSize : 0);
618
619 /* Get the key node */
620 KeyNode = GET_CM_KEY_NODE(Hive, Key);
621 ASSERT(KeyNode);
623
624 CellIndex = CmpFindSubKeyByNumber(Hive, KeyNode, Index);
625 if (CellIndex == HCELL_NIL)
626 {
627 TRACE("RegEnumKey index out of bounds (%d) in key (%.*s)\n",
628 Index, KeyNode->NameLength, KeyNode->Name);
630 return ERROR_NO_MORE_ITEMS;
631 }
633
634 /* Get the value cell */
635 SubKeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
636 ASSERT(SubKeyNode != NULL);
637 ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE);
638
639 if (SubKeyNode->Flags & KEY_COMP_NAME)
640 {
641 NameLength = CmpCompressedNameSize(SubKeyNode->Name, SubKeyNode->NameLength);
642
643 /* Compressed name */
645 *NameSize,
646 SubKeyNode->Name,
647 SubKeyNode->NameLength);
648 }
649 else
650 {
651 NameLength = SubKeyNode->NameLength;
652
653 /* Normal name */
654 RtlCopyMemory(Name, SubKeyNode->Name,
655 min(*NameSize, SubKeyNode->NameLength));
656 }
657
658 if (*NameSize >= NameLength + sizeof(WCHAR))
659 {
660 Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
661 }
662
663 *NameSize = NameLength + sizeof(WCHAR);
664
665 HvReleaseCell(Hive, CellIndex);
666
667 if (SubKey != NULL)
668 *SubKey = HCI_TO_HKEY(CellIndex);
669
670 TRACE("RegEnumKey done -> %u, '%.*S'\n", *NameSize, *NameSize, Name);
671 return ERROR_SUCCESS;
672}
673#endif
674
675LONG
680{
681 UNICODE_STRING RemainingPath, SubKeyName;
682 UNICODE_STRING CurrentControlSet = RTL_CONSTANT_STRING(L"CurrentControlSet");
684 PCM_KEY_NODE KeyNode;
685 HCELL_INDEX CellIndex;
686
687 TRACE("RegOpenKey(%p, '%S', %p)\n", ParentKey, KeyName, Key);
688
689 /* Initialize the remaining path name */
690 RtlInitUnicodeString(&RemainingPath, KeyName);
691
692 /* Check if we have a parent key */
693 if (ParentKey == NULL)
694 {
695 UNICODE_STRING SubKeyName1, SubKeyName2, SubKeyName3;
697 UNICODE_STRING MachinePath = RTL_CONSTANT_STRING(L"MACHINE");
698 UNICODE_STRING SystemPath = RTL_CONSTANT_STRING(L"SYSTEM");
699
700 TRACE("RegOpenKey: absolute path\n");
701
702 if ((RemainingPath.Length < sizeof(WCHAR)) ||
703 RemainingPath.Buffer[0] != '\\')
704 {
705 /* The key path is not absolute */
706 ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
708 }
709
710 /* Skip initial path separator */
711 RemainingPath.Buffer++;
712 RemainingPath.Length -= sizeof(WCHAR);
713
714 /* Get the first 3 path elements */
715 GetNextPathElement(&SubKeyName1, &RemainingPath);
716 GetNextPathElement(&SubKeyName2, &RemainingPath);
717 GetNextPathElement(&SubKeyName3, &RemainingPath);
718 TRACE("RegOpenKey: %wZ / %wZ / %wZ\n", &SubKeyName1, &SubKeyName2, &SubKeyName3);
719
720 /* Check if we have the correct path */
721 if (!RtlEqualUnicodeString(&SubKeyName1, &RegistryPath, TRUE) ||
722 !RtlEqualUnicodeString(&SubKeyName2, &MachinePath, TRUE) ||
723 !RtlEqualUnicodeString(&SubKeyName3, &SystemPath, TRUE))
724 {
725 /* The key path is not inside HKLM\Machine\System */
726 ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
728 }
729
730 /* Use the root key */
731 CellIndex = SystemRootCell;
732 }
733 else
734 {
735 /* Use the parent key */
736 CellIndex = HKEY_TO_HCI(ParentKey);
737 }
738
739 /* Check if this is the root key */
740 if (CellIndex == SystemRootCell)
741 {
742 UNICODE_STRING TempPath = RemainingPath;
743
744 /* Get the first path element */
745 GetNextPathElement(&SubKeyName, &TempPath);
746
747 /* Check if this is CurrentControlSet */
748 if (RtlEqualUnicodeString(&SubKeyName, &CurrentControlSet, TRUE))
749 {
750 /* Use the CurrentControlSetKey and update the remaining path */
752 RemainingPath = TempPath;
753 }
754 }
755
756 /* Get the key node */
757 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
758 ASSERT(KeyNode);
760
761 TRACE("RegOpenKey: RemainingPath '%wZ'\n", &RemainingPath);
762
763 /* Loop while there are path elements */
764 while (GetNextPathElement(&SubKeyName, &RemainingPath))
765 {
766 HCELL_INDEX NextCellIndex;
767
768 TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName);
769
770 /* Get the next sub key */
771 NextCellIndex = CmpFindSubKeyByName(Hive, KeyNode, &SubKeyName);
772 HvReleaseCell(Hive, CellIndex);
773 CellIndex = NextCellIndex;
774 if (CellIndex == HCELL_NIL)
775 {
776 WARN("Did not find sub key '%wZ' (full: %S)\n", &SubKeyName, KeyName);
778 }
779
780 /* Get the found key */
781 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
782 ASSERT(KeyNode);
784 }
785
786 HvReleaseCell(Hive, CellIndex);
787 *Key = HCI_TO_HKEY(CellIndex);
788
789 return ERROR_SUCCESS;
790}
791
792static
793VOID
795 _In_ PHHIVE Hive,
796 _In_ PCM_KEY_VALUE ValueCell,
800{
802 PVOID DataCell;
803
804 /* Does the caller want the type? */
805 if (Type != NULL)
806 *Type = ValueCell->Type;
807
808 /* Does the caller provide DataSize? */
809 if (DataSize != NULL)
810 {
811 // NOTE: CmpValueToData doesn't support big data (the function will
812 // bugcheck if so), FreeLdr is not supposed to read such data.
813 // If big data is needed, use instead CmpGetValueData.
814 // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...);
815 DataCell = CmpValueToData(Hive, ValueCell, &DataLength);
816
817 /* Does the caller want the data? */
818 if ((Data != NULL) && (*DataSize != 0))
819 {
821 DataCell,
823 }
824
825 /* Return the actual data length */
827 }
828}
829
830LONG
832 _In_ HKEY Key,
837{
839 PCM_KEY_NODE KeyNode;
840 PCM_KEY_VALUE ValueCell;
841 HCELL_INDEX CellIndex;
842 UNICODE_STRING ValueNameString;
843
844 TRACE("RegQueryValue(%p, '%S', %p, %p, %p)\n",
846
847 /* Get the key node */
848 KeyNode = GET_CM_KEY_NODE(Hive, Key);
849 ASSERT(KeyNode);
851
852 /* Initialize value name string */
853 RtlInitUnicodeString(&ValueNameString, ValueName);
854 CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
855 if (CellIndex == HCELL_NIL)
856 {
857 TRACE("RegQueryValue value not found in key (%.*s)\n",
858 KeyNode->NameLength, KeyNode->Name);
861 }
863
864 /* Get the value cell */
865 ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
866 ASSERT(ValueCell != NULL);
867
868 RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
869
870 HvReleaseCell(Hive, CellIndex);
871
872 return ERROR_SUCCESS;
873}
874
875/*
876 * NOTE: This function is currently unused in FreeLdr; however it is kept here
877 * as an implementation reference of RegEnumValue using CMLIB that may be used
878 * elsewhere in ReactOS.
879 */
880#if 0
881LONG
883 _In_ HKEY Key,
886 _Inout_ PULONG NameSize,
890{
892 PCM_KEY_NODE KeyNode;
893 PCELL_DATA ValueListCell;
894 PCM_KEY_VALUE ValueCell;
895 USHORT NameLength;
896
897 TRACE("RegEnumValue(%p, %lu, %S, %p, %p, %p, %p (%lu))\n",
898 Key, Index, ValueName, NameSize, Type, Data, DataSize, *DataSize);
899
900 /* Get the key node */
901 KeyNode = GET_CM_KEY_NODE(Hive, Key);
902 ASSERT(KeyNode);
904
905 /* Check if the index is valid */
906 if ((KeyNode->ValueList.Count == 0) ||
907 (KeyNode->ValueList.List == HCELL_NIL) ||
908 (Index >= KeyNode->ValueList.Count))
909 {
910 ERR("RegEnumValue: index invalid\n");
912 return ERROR_NO_MORE_ITEMS;
913 }
914
915 ValueListCell = (PCELL_DATA)HvGetCell(Hive, KeyNode->ValueList.List);
916 ASSERT(ValueListCell != NULL);
917
918 /* Get the value cell */
919 ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, ValueListCell->KeyList[Index]);
920 ASSERT(ValueCell != NULL);
922
923 if (ValueCell->Flags & VALUE_COMP_NAME)
924 {
925 NameLength = CmpCompressedNameSize(ValueCell->Name, ValueCell->NameLength);
926
927 /* Compressed name */
929 *NameSize,
930 ValueCell->Name,
931 ValueCell->NameLength);
932 }
933 else
934 {
935 NameLength = ValueCell->NameLength;
936
937 /* Normal name */
938 RtlCopyMemory(ValueName, ValueCell->Name,
939 min(*NameSize, ValueCell->NameLength));
940 }
941
942 if (*NameSize >= NameLength + sizeof(WCHAR))
943 {
944 ValueName[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
945 }
946
947 *NameSize = NameLength + sizeof(WCHAR);
948
949 RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
950
951 HvReleaseCell(Hive, ValueListCell->KeyList[Index]);
952 HvReleaseCell(Hive, KeyNode->ValueList.List);
954
955 TRACE("RegEnumValue done -> %u, '%.*S'\n", *NameSize, *NameSize, ValueName);
956 return ERROR_SUCCESS;
957}
958#endif
959
960/* EOF */
unsigned char BOOLEAN
Type
Definition: Type.h:7
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:462
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
ARC_STATUS ArcOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fs.c:219
ARC_STATUS ArcClose(_In_ ULONG FileId)
Definition: fs.c:409
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
FORCEINLINE VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: mm.h:181
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:188
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:197
FORCEINLINE PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: mm.h:174
static BOOLEAN RegRecoverHeaderHive(_Inout_ PVOID ChunkBase, _In_ PCSTR DirectoryPath, _In_ PCSTR LogName)
Recovers the header base block of a flat registry hive.
Definition: registry.c:289
#define GET_CM_KEY_NODE(hHive, hKey)
Definition: registry.c:43
static BOOLEAN GetNextPathElement(_Out_ PUNICODE_STRING NextElement, _Inout_ PUNICODE_STRING RemainingPath)
Definition: registry.c:563
BOOLEAN RegInitCurrentControlSet(_In_ BOOLEAN LastKnownGood)
Definition: registry.c:525
static VOID RepGetValueData(_In_ PHHIVE Hive, _In_ PCM_KEY_VALUE ValueCell, _Out_opt_ PULONG Type, _Out_opt_ PUCHAR Data, _Inout_opt_ PULONG DataSize)
Definition: registry.c:794
#define GET_HBASE_BLOCK(ChunkBase)
Definition: registry.c:45
VOID NTAPI CmpFree(IN PVOID Ptr, IN ULONG Quota)
Definition: registry.c:60
static BOOLEAN RegLoadHiveLog(_In_ PCSTR DirectoryPath, _In_ ULONG LogFileOffset, _In_ PCSTR LogName, _Out_ PVOID *LogData)
Loads and reads a hive log at specified file offset.
Definition: registry.c:182
#define GET_HHIVE(CmHive)
Definition: registry.c:41
static PCMHIVE CmSystemHive
Definition: registry.c:30
PHHIVE SystemHive
Definition: registry.c:33
static HCELL_INDEX SystemRootCell
Definition: registry.c:31
BOOLEAN RegImportBinaryHive(_In_ PVOID ChunkBase, _In_ ULONG ChunkSize, _In_ PCSTR SearchPath, _In_ BOOLEAN LoadAlternate)
Imports the SYSTEM binary hive from the registry base chunk that's been provided by the loader block.
Definition: registry.c:449
HKEY CurrentControlSetKey
Definition: registry.c:34
#define HCI_TO_HKEY(CellIndex)
Definition: registry.c:36
PVOID NTAPI CmpAllocate(IN SIZE_T Size, IN BOOLEAN Paged, IN ULONG Tag)
Definition: registry.c:49
static BOOLEAN RegInitializeHive(_In_ PCMHIVE CmHive, _In_ PVOID ChunkBase, _In_ BOOLEAN LoadAlternate)
Initializes a flat hive descriptor for the hive and validates the registry hive. Volatile data is pur...
Definition: registry.c:96
#define GET_HHIVE_FROM_HKEY(hKey)
Definition: registry.c:42
static BOOLEAN RegRecoverDataHive(_Inout_ PVOID ChunkBase, _In_ PCSTR DirectoryPath, _In_ PCSTR LogName)
Recovers the corrupt data of a primary flat registry hive.
Definition: registry.c:362
#define HKEY_TO_HCI(hKey)
Definition: registry.h:28
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
HCELL_INDEX NTAPI CmpFindControlSet(_In_ PHHIVE SystemHive, _In_ HCELL_INDEX RootCell, _In_ PCUNICODE_STRING SelectKeyName, _Out_ PBOOLEAN AutoSelect)
Finds the corresponding "HKLM\SYSTEM\ControlSetXXX" system control set registry key,...
Definition: cmboot.c:84
CM_CHECK_REGISTRY_STATUS NTAPI CmCheckRegistry(_In_ PCMHIVE RegistryHive, _In_ ULONG Flags)
Checks the registry that is consistent and its contents valid and not corrupted. More specifically th...
Definition: cmcheck.c:1634
struct _CELL_DATA * PCELL_DATA
struct _CM_KEY_NODE * PCM_KEY_NODE
#define KEY_COMP_NAME
Definition: cmdata.h:35
struct _CM_KEY_VALUE * PCM_KEY_VALUE
#define CM_KEY_VALUE_SIGNATURE
Definition: cmdata.h:24
#define VALUE_COMP_NAME
Definition: cmdata.h:44
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:460
BOOLEAN CMAPI HvpVerifyHiveHeader(_In_ PHBASE_BLOCK BaseBlock, _In_ ULONG FileType)
Validates the base block header of a registry file (hive or log).
Definition: hiveinit.c:49
ULONG CMAPI HvpHiveHeaderChecksum(PHBASE_BLOCK HiveHeader)
Definition: hivesum.c:17
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
NTSTATUS CMAPI HvInitialize(PHHIVE RegistryHive, ULONG OperationType, ULONG HiveFlags, ULONG FileType, PVOID HiveData OPTIONAL, PALLOCATE_ROUTINE Allocate, PFREE_ROUTINE Free, PFILE_SET_SIZE_ROUTINE FileSetSize, PFILE_WRITE_ROUTINE FileWrite, PFILE_READ_ROUTINE FileRead, PFILE_FLUSH_ROUTINE FileFlush, ULONG Cluster OPTIONAL, PCUNICODE_STRING FileName OPTIONAL)
#define CM_CHECK_REGISTRY_VALIDATE_HIVE
Definition: cmlib.h:231
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
Definition: cmvalue.c:99
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
Definition: cmlib.h:281
ULONG CM_CHECK_REGISTRY_STATUS
Definition: cmlib.h:223
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES
Definition: cmlib.h:230
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:457
FORCEINLINE PVOID VaToPa(PVOID Va)
Definition: conversion.h:15
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
@ Success
Definition: eventcreate.c:712
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
#define HBLOCK_SIZE
Definition: hivedata.h:42
#define HV_LOG_HEADER_SIZE
Definition: hivedata.h:46
#define HFILE_TYPE_ALTERNATE
Definition: hivedata.h:36
#define HFILE_TYPE_LOG
Definition: hivedata.h:34
#define HINIT_FLAT
Definition: hivedata.h:17
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
#define HCELL_NIL
Definition: hivedata.h:110
#define HBOOT_BOOT_RECOVERED_BY_HIVE_LOG
Definition: hivedata.h:95
#define HV_LOG_DIRTY_BLOCK
Definition: hivedata.h:56
ULONG HCELL_INDEX
Definition: hivedata.h:105
#define HBOOT_NO_BOOT_RECOVER
Definition: hivedata.h:94
struct _HBASE_BLOCK * PHBASE_BLOCK
#define HV_LOG_DIRTY_SIGNATURE
Definition: hivedata.h:57
#define HSECTOR_SIZE
Definition: hivedata.h:43
#define ASSERT(a)
Definition: mode.c:44
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define min(a, b)
Definition: monoChain.cc:55
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _In_z_
Definition: no_sal2.h:164
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
@ ESUCCESS
Definition: arc.h:32
@ LoaderRegistryData
Definition: arc.h:193
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekAbsolute
Definition: arc.h:59
@ OpenReadOnly
Definition: arc.h:65
#define TRACE(s)
Definition: solgame.cpp:4
HCELL_INDEX KeyList[ANYSIZE_ARRAY]
Definition: cmdata.h:205
HCELL_INDEX List
Definition: cmdata.h:75
ULONG Count
Definition: cmdata.h:74
Definition: cmlib.h:316
USHORT Signature
Definition: cmdata.h:92
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
USHORT NameLength
Definition: cmdata.h:114
CHILD_LIST ValueList
Definition: cmdata.h:103
USHORT Flags
Definition: cmdata.h:93
USHORT Signature
Definition: cmdata.h:124
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:131
USHORT NameLength
Definition: cmdata.h:125
USHORT Flags
Definition: cmdata.h:129
ULONG Length
Definition: hivedata.h:171
HCELL_INDEX RootCell
Definition: hivedata.h:168
ULONG Sequence1
Definition: hivedata.h:147
ULONG Type
Definition: hivedata.h:161
ULONG CheckSum
Definition: hivedata.h:183
ULONG Sequence2
Definition: hivedata.h:148
ULONG Cluster
Definition: hivedata.h:174
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:328
static COORD Position
Definition: mouse.c:34
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_Must_inspect_result_ _In_opt_ WDFKEY ParentKey
Definition: wdfregistry.h:69
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
#define SearchPath
Definition: winbase.h:3925
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define RegOpenKey
Definition: winreg.h:519
#define RegEnumValue
Definition: winreg.h:511
#define RegQueryValue
Definition: winreg.h:523
#define RegEnumKey
Definition: winreg.h:509
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2294
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175