ReactOS 0.4.15-dev-7788-g1ad9096
hiveinit.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Configuration Manager Library - Registry Hive Loading & Initialization
5 * COPYRIGHT: Copyright 2001 - 2005 Eric Kohl
6 * Copyright 2005 Filip Navara <navaraf@reactos.org>
7 * Copyright 2021 Max Korostil
8 * Copyright 2022 George Bișoc <george.bisoc@reactos.org>
9 */
10
11#include "cmlib.h"
12#define NDEBUG
13#include <debug.h>
14
15/* ENUMERATIONS *************************************************************/
16
17typedef enum _RESULT
18{
27
28/* PRIVATE FUNCTIONS ********************************************************/
29
50 _In_ PHBASE_BLOCK BaseBlock,
52{
53 if (BaseBlock->Signature != HV_HBLOCK_SIGNATURE ||
54 BaseBlock->Major != HSYS_MAJOR ||
55 BaseBlock->Minor < HSYS_MINOR ||
56 BaseBlock->Type != FileType ||
57 BaseBlock->Format != HBASE_FORMAT_MEMORY ||
58 BaseBlock->Cluster != 1 ||
59 BaseBlock->Sequence1 != BaseBlock->Sequence2 ||
60 HvpHiveHeaderChecksum(BaseBlock) != BaseBlock->CheckSum)
61 {
62 DPRINT1("Verify Hive Header failed:\n");
63 DPRINT1(" Signature: 0x%x, expected 0x%x; Major: 0x%x, expected 0x%x\n",
64 BaseBlock->Signature, HV_HBLOCK_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
65 DPRINT1(" Minor: 0x%x expected to be >= 0x%x; Type: 0x%x, expected 0x%x\n",
66 BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, FileType);
67 DPRINT1(" Format: 0x%x, expected 0x%x; Cluster: 0x%x, expected 1\n",
68 BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
69 DPRINT1(" Sequence: 0x%x, expected 0x%x; Checksum: 0x%x, expected 0x%x\n",
70 BaseBlock->Sequence1, BaseBlock->Sequence2,
71 HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum);
72
73 return FALSE;
74 }
75
76 return TRUE;
77}
78
88VOID
91 _In_ PHHIVE Hive)
92{
93 ULONG i;
94 PHBIN Bin;
96
97 for (Storage = 0; Storage < Hive->StorageTypeCount; Storage++)
98 {
99 Bin = NULL;
100 for (i = 0; i < Hive->Storage[Storage].Length; i++)
101 {
102 if (Hive->Storage[Storage].BlockList[i].BinAddress == (ULONG_PTR)NULL)
103 continue;
104 if (Hive->Storage[Storage].BlockList[i].BinAddress != (ULONG_PTR)Bin)
105 {
106 Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress;
107 Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress, 0);
108 }
109 Hive->Storage[Storage].BlockList[i].BinAddress = (ULONG_PTR)NULL;
110 Hive->Storage[Storage].BlockList[i].BlockAddress = (ULONG_PTR)NULL;
111 }
112
113 if (Hive->Storage[Storage].Length)
114 Hive->Free(Hive->Storage[Storage].BlockList, 0);
115 }
116}
117
140static
141__inline
144 _In_ PHHIVE Hive,
145 _In_ BOOLEAN Paged,
146 _In_ ULONG Tag)
147{
148 PHBASE_BLOCK BaseBlock;
150
151 ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
152
153 /* Allocate the buffer */
154 BaseBlock = Hive->Allocate(Hive->BaseBlockAlloc, Paged, Tag);
155 if (!BaseBlock) return NULL;
156
157 /* Check for, and enforce, alignment */
158 Alignment = Hive->Cluster * HSECTOR_SIZE -1;
159 if ((ULONG_PTR)BaseBlock & Alignment)
160 {
161 /* Free the old header and reallocate a new one, always paged */
162 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
163 BaseBlock = Hive->Allocate(PAGE_SIZE, TRUE, Tag);
164 if (!BaseBlock) return NULL;
165
166 Hive->BaseBlockAlloc = PAGE_SIZE;
167 }
168
169 return BaseBlock;
170}
171
187static
188VOID
190 _Inout_ PHBASE_BLOCK BaseBlock,
192{
195
196 /* Always NULL-initialize */
197 RtlZeroMemory(BaseBlock->FileName, (HIVE_FILENAME_MAXLEN + 1) * sizeof(WCHAR));
198
199 /* Copy the 31 last characters of the hive file name if any */
200 if (!FileName) return;
201
202 if (FileName->Length / sizeof(WCHAR) <= HIVE_FILENAME_MAXLEN)
203 {
204 Offset = 0;
205 Length = FileName->Length;
206 }
207 else
208 {
209 Offset = FileName->Length / sizeof(WCHAR) - HIVE_FILENAME_MAXLEN;
211 }
212
213 RtlCopyMemory(BaseBlock->FileName, FileName->Buffer + Offset, Length);
214}
215
237CMAPI
239 _Inout_ PHHIVE RegistryHive,
241{
242 PHBASE_BLOCK BaseBlock;
243 ULONG Index;
244
245 /* Allocate the base block */
246 BaseBlock = HvpAllocBaseBlockAligned(RegistryHive, FALSE, TAG_CM);
247 if (BaseBlock == NULL)
248 return STATUS_NO_MEMORY;
249
250 /* Clear it */
251 RtlZeroMemory(BaseBlock, RegistryHive->BaseBlockAlloc);
252
253 BaseBlock->Signature = HV_HBLOCK_SIGNATURE;
254 BaseBlock->Major = HSYS_MAJOR;
255 BaseBlock->Minor = HSYS_MINOR;
256 BaseBlock->Type = HFILE_TYPE_PRIMARY;
257 BaseBlock->Format = HBASE_FORMAT_MEMORY;
258 BaseBlock->Cluster = 1;
259 BaseBlock->RootCell = HCELL_NIL;
260 BaseBlock->Length = 0;
261 BaseBlock->Sequence1 = 1;
262 BaseBlock->Sequence2 = 1;
263 BaseBlock->TimeStamp.QuadPart = 0ULL;
264
265 /*
266 * No need to compute the checksum since
267 * the hive resides only in memory so far.
268 */
269 BaseBlock->CheckSum = 0;
270
271 /* Set default boot type */
272 BaseBlock->BootType = HBOOT_TYPE_REGULAR;
273
274 /* Setup hive data */
275 RegistryHive->BaseBlock = BaseBlock;
276 RegistryHive->Version = BaseBlock->Minor; // == HSYS_MINOR
277
278 for (Index = 0; Index < 24; Index++)
279 {
280 RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
281 RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
282 }
283
284 HvpInitFileName(BaseBlock, FileName);
285
286 return STATUS_SUCCESS;
287}
288
317CMAPI
319 _In_ PHHIVE Hive,
320 _In_ PHBASE_BLOCK ChunkBase,
322{
323 SIZE_T BlockIndex;
324 PHBIN Bin, NewBin;
325 ULONG i;
326 ULONG BitmapSize;
329
330 ChunkSize = ChunkBase->Length;
331 DPRINT("ChunkSize: %zx\n", ChunkSize);
332
333 if (ChunkSize < sizeof(HBASE_BLOCK) ||
335 {
336 DPRINT1("Registry is corrupt: ChunkSize 0x%zx < sizeof(HBASE_BLOCK) 0x%zx, "
337 "or HvpVerifyHiveHeader() failed\n", ChunkSize, sizeof(HBASE_BLOCK));
339 }
340
341 /* Allocate the base block */
342 Hive->BaseBlock = HvpAllocBaseBlockAligned(Hive, FALSE, TAG_CM);
343 if (Hive->BaseBlock == NULL)
344 return STATUS_NO_MEMORY;
345
346 RtlCopyMemory(Hive->BaseBlock, ChunkBase, sizeof(HBASE_BLOCK));
347
348 /* Setup hive data */
349 Hive->Version = ChunkBase->Minor;
350
351 /*
352 * Build a block list from the in-memory chunk and copy the data as
353 * we go.
354 */
355
356 Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HBLOCK_SIZE);
357 Hive->Storage[Stable].BlockList =
358 Hive->Allocate(Hive->Storage[Stable].Length *
359 sizeof(HMAP_ENTRY), FALSE, TAG_CM);
360 if (Hive->Storage[Stable].BlockList == NULL)
361 {
362 DPRINT1("Allocating block list failed\n");
363 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
364 return STATUS_NO_MEMORY;
365 }
366
367 for (BlockIndex = 0; BlockIndex < Hive->Storage[Stable].Length; )
368 {
369 Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HBLOCK_SIZE);
370 if (Bin->Signature != HV_HBIN_SIGNATURE ||
371 (Bin->Size % HBLOCK_SIZE) != 0 ||
372 (Bin->FileOffset / HBLOCK_SIZE) != BlockIndex)
373 {
374 /*
375 * Bin is toast but luckily either the signature, size or offset
376 * is out of order. For the signature it is obvious what we are going
377 * to do, for the offset we are re-positioning the bin back to where it
378 * was and for the size we will set it up to a block size, since technically
379 * a hive bin is large as a block itself to accommodate cells.
380 */
382 {
383 DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x. Self-heal not possible!\n",
384 (unsigned long)BlockIndex, (unsigned)Bin->Signature, (unsigned)Bin->Size);
385 Hive->Free(Hive->Storage[Stable].BlockList, 0);
386 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
388 }
389
390 /* Fix this bin */
391 Bin->Signature = HV_HBIN_SIGNATURE;
392 Bin->Size = HBLOCK_SIZE;
393 Bin->FileOffset = BlockIndex * HBLOCK_SIZE;
394 ChunkBase->BootType |= HBOOT_TYPE_SELF_HEAL;
395 DPRINT1("Bin at index %lu is corrupt and it has been repaired!\n", (unsigned long)BlockIndex);
396 }
397
398 NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM);
399 if (NewBin == NULL)
400 {
401 Hive->Free(Hive->Storage[Stable].BlockList, 0);
402 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
403 return STATUS_NO_MEMORY;
404 }
405
406 Hive->Storage[Stable].BlockList[BlockIndex].BinAddress = (ULONG_PTR)NewBin;
407 Hive->Storage[Stable].BlockList[BlockIndex].BlockAddress = (ULONG_PTR)NewBin;
408
409 RtlCopyMemory(NewBin, Bin, Bin->Size);
410
411 if (Bin->Size > HBLOCK_SIZE)
412 {
413 for (i = 1; i < Bin->Size / HBLOCK_SIZE; i++)
414 {
415 Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin;
416 Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress =
417 ((ULONG_PTR)NewBin + (i * HBLOCK_SIZE));
418 }
419 }
420
421 BlockIndex += Bin->Size / HBLOCK_SIZE;
422 }
423
425 {
426 HvpFreeHiveBins(Hive);
427 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
428 return STATUS_NO_MEMORY;
429 }
430
431 BitmapSize = ROUND_UP(Hive->Storage[Stable].Length,
432 sizeof(ULONG) * 8) / 8;
433 BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE, TAG_CM);
434 if (BitmapBuffer == NULL)
435 {
436 HvpFreeHiveBins(Hive);
437 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
438 return STATUS_NO_MEMORY;
439 }
440
441 RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
442 RtlClearAllBits(&Hive->DirtyVector);
443
444 /*
445 * Mark the entire hive as dirty. Indeed we understand if we charged up
446 * the alternate variant of the primary hive (e.g. SYSTEM.ALT) because
447 * FreeLdr could not load the main SYSTEM hive, due to corruptions, and
448 * repairing it with a LOG did not help at all.
449 */
450 if (ChunkBase->BootRecover == HBOOT_BOOT_RECOVERED_BY_ALTERNATE_HIVE)
451 {
452 RtlSetAllBits(&Hive->DirtyVector);
453 Hive->DirtyCount = Hive->DirtyVector.SizeOfBitMap;
454 }
455
456 HvpInitFileName(Hive->BaseBlock, FileName);
457
458 return STATUS_SUCCESS;
459}
460
484CMAPI
486 _In_ PHHIVE Hive,
487 _In_ PHBASE_BLOCK ChunkBase)
488{
491
492 /* Setup hive data */
493 Hive->BaseBlock = ChunkBase;
494 Hive->Version = ChunkBase->Minor;
495 Hive->Flat = TRUE;
496 Hive->ReadOnly = TRUE;
497
498 Hive->StorageTypeCount = 1;
499
500 /* Set default boot type */
501 ChunkBase->BootType = HBOOT_TYPE_REGULAR;
502
503 return STATUS_SUCCESS;
504}
505
550RESULT
551CMAPI
553 _In_ PHHIVE Hive,
554 _Inout_ PHBASE_BLOCK *HiveBaseBlock,
556{
557 PHBASE_BLOCK BaseBlock;
560 PHBIN FirstBin;
561
562 ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
563
564 /* Assume failure and allocate the base block */
565 *HiveBaseBlock = NULL;
566 BaseBlock = HvpAllocBaseBlockAligned(Hive, TRUE, TAG_CM);
567 if (!BaseBlock)
568 {
569 DPRINT1("Failed to allocate an aligned base block buffer\n");
570 return NoMemory;
571 }
572
573 /* Clear it */
574 RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
575
576 /* Now read it from disk */
577 FileOffset = 0;
578 Result = Hive->FileRead(Hive,
580 &FileOffset,
581 BaseBlock,
582 Hive->Cluster * HSECTOR_SIZE);
583 if (!Result)
584 {
585 /*
586 * Don't assume the hive is ultimately destroyed
587 * but instead try to read the first block of
588 * the first bin hive. So that we're sure of
589 * ourselves we can somewhat recover this hive.
590 */
592 Result = Hive->FileRead(Hive,
594 &FileOffset,
595 (PVOID)BaseBlock,
596 Hive->Cluster * HSECTOR_SIZE);
597 if (!Result)
598 {
599 DPRINT1("Failed to read the first block of the first bin hive (hive too corrupt)\n");
600 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
601 return NotHive;
602 }
603
604 /*
605 * Deconstruct the casted buffer we got
606 * into a hive bin. Check if the offset
607 * position is in the right place (namely
608 * its offset must be 0 because it's the first
609 * bin) and it should have a sane signature.
610 */
611 FirstBin = (PHBIN)BaseBlock;
612 if (FirstBin->Signature != HV_HBIN_SIGNATURE ||
613 FirstBin->FileOffset != 0)
614 {
615 DPRINT1("Failed to read the first block of the first bin hive (hive too corrupt)\n");
616 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
617 return NotHive;
618 }
619
620 /*
621 * There's still hope for this hive so acknowledge the
622 * caller this hive needs a recoverable header.
623 */
624 *TimeStamp = BaseBlock->TimeStamp;
625 DPRINT1("The hive is not fully corrupt, the base block needs to be RECOVERED\n");
626 return RecoverHeader;
627 }
628
629 /*
630 * This hive has a base block that's not maimed
631 * but is the header data valid?
632 *
633 * FIXME: We must check if primary and secondary
634 * sequences mismatch separately and fire up RecoverData
635 * in that case but due to a hack in HvLoadHive, let
636 * HvpVerifyHiveHeader check the sequences for now.
637 */
639 {
640 DPRINT1("The hive base header block needs to be RECOVERED\n");
641 *TimeStamp = BaseBlock->TimeStamp;
642 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
643 return RecoverHeader;
644 }
645
646 /* Return information */
647 *HiveBaseBlock = BaseBlock;
648 *TimeStamp = BaseBlock->TimeStamp;
649 return HiveSuccess;
650}
651
652/*
653 * FIXME: Disable compilation for AMD64 for now since it makes
654 * the FreeLdr binary size so large it makes booting impossible.
655 */
656#if !defined(_M_AMD64)
669ULONG
670CMAPI
672 _In_ PHHIVE Hive)
673{
674#if !defined(CMLIB_HOST) && !defined(_BLDR_)
676 FILE_STANDARD_INFORMATION FileStandard;
678#endif
679 ULONG HiveSize = 0;
680
681 /*
682 * Query the file size of the physical hive
683 * file. We need that information in order
684 * to ensure how big the hive actually is.
685 */
686#if !defined(CMLIB_HOST) && !defined(_BLDR_)
687 Status = ZwQueryInformationFile(((PCMHIVE)Hive)->FileHandles[HFILE_TYPE_PRIMARY],
689 &FileStandard,
692 if (!NT_SUCCESS(Status))
693 {
694 DPRINT1("ZwQueryInformationFile returned 0x%lx\n", Status);
695 return HiveSize;
696 }
697
698 /* Now compute the hive size */
699 HiveSize = FileStandard.EndOfFile.u.LowPart - HBLOCK_SIZE;
700#endif
701 return HiveSize;
702}
703
741RESULT
742CMAPI
744 _In_ PHHIVE Hive,
746 _Inout_ PHBASE_BLOCK *BaseBlock)
747{
749 PHBASE_BLOCK LogHeader;
751 ULONG HiveSize;
752 BOOLEAN HeaderResuscitated;
753
754 /*
755 * The cluster must not be greater than what the
756 * base block can permit.
757 */
758 ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
759
760 /* Assume we haven't resuscitated the header */
761 HeaderResuscitated = FALSE;
762
763 /* Allocate an aligned buffer for the log header */
764 LogHeader = HvpAllocBaseBlockAligned(Hive, TRUE, TAG_CM);
765 if (!LogHeader)
766 {
767 DPRINT1("Failed to allocate memory for the log header\n");
768 return NoMemory;
769 }
770
771 /* Zero out our header buffer */
772 RtlZeroMemory(LogHeader, HSECTOR_SIZE);
773
774 /* Get the base header from the log */
775 FileOffset = 0;
776 Success = Hive->FileRead(Hive,
778 &FileOffset,
779 LogHeader,
780 Hive->Cluster * HSECTOR_SIZE);
781 if (!Success ||
782 !HvpVerifyHiveHeader(LogHeader, HFILE_TYPE_LOG) ||
783 TimeStamp->HighPart != LogHeader->TimeStamp.HighPart ||
784 TimeStamp->LowPart != LogHeader->TimeStamp.LowPart)
785 {
786 /*
787 * We failed to read the base block header from
788 * the log, or the header itself or timestamp is
789 * invalid. Check if self healing is enabled.
790 */
792 {
793 DPRINT1("The log couldn't be read and self-healing mode is disabled\n");
794 Hive->Free(LogHeader, Hive->BaseBlockAlloc);
795 return Fail;
796 }
797
798 /*
799 * Determine the size of this hive so that
800 * we can estabilish the length of the base
801 * block we are trying to resuscitate.
802 */
803 HiveSize = HvpQueryHiveSize(Hive);
804 if (HiveSize == 0)
805 {
806 DPRINT1("Failed to query the hive size\n");
807 Hive->Free(LogHeader, Hive->BaseBlockAlloc);
808 return Fail;
809 }
810
811 /*
812 * We can still resuscitate the base header if we
813 * could not grab one from the log by reconstructing
814 * the header internals by hand (this assumes the
815 * root cell is not NIL nor damaged). CmCheckRegistry
816 * does the ultimate judgement whether the root cell
817 * is fatally kaput or not after the hive has been
818 * initialized and loaded.
819 *
820 * For more information about base block header
821 * resuscitation, see https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md#notes-4.
822 */
823 LogHeader->Signature = HV_HBLOCK_SIGNATURE;
824 LogHeader->Sequence1 = 1;
825 LogHeader->Sequence2 = 1;
826 LogHeader->Cluster = 1;
827 LogHeader->Length = HiveSize;
828 LogHeader->CheckSum = HvpHiveHeaderChecksum(LogHeader);
829
830 /*
831 * Acknowledge that we have resuscitated
832 * the header.
833 */
834 HeaderResuscitated = TRUE;
835 DPRINT1("Header has been resuscitated, triggering self-heal mode\n");
836 }
837
838 /*
839 * Tag this log header as a primary hive before
840 * writing it to the hive.
841 */
842 LogHeader->Type = HFILE_TYPE_PRIMARY;
843
844 /*
845 * If we have not made attempts of recovering
846 * the header due to log corruption then we
847 * have to compute the checksum. This is
848 * already done when the header has been resuscitated
849 * so don't try to do it twice.
850 */
851 if (!HeaderResuscitated)
852 {
853 LogHeader->CheckSum = HvpHiveHeaderChecksum(LogHeader);
854 }
855
856 /* Write the header back to hive now */
857 Success = Hive->FileWrite(Hive,
859 &FileOffset,
860 LogHeader,
861 Hive->Cluster * HSECTOR_SIZE);
862 if (!Success)
863 {
864 DPRINT1("Couldn't write the base header to primary hive\n");
865 Hive->Free(LogHeader, Hive->BaseBlockAlloc);
866 return Fail;
867 }
868
869 *BaseBlock = LogHeader;
870 return HeaderResuscitated ? SelfHeal : HiveSuccess;
871}
872
897RESULT
898CMAPI
900 _In_ PHHIVE Hive,
901 _In_ PHBASE_BLOCK BaseBlock)
902{
905 ULONG BlockIndex;
906 ULONG LogIndex;
907 ULONG StorageLength;
908 UCHAR DirtyVector[HSECTOR_SIZE];
910
911 /* Read the dirty data from the log */
913 Success = Hive->FileRead(Hive,
915 &FileOffset,
916 DirtyVector,
918 if (!Success)
919 {
921 {
922 DPRINT1("The log couldn't be read and self-healing mode is disabled\n");
923 return Fail;
924 }
925
926 /*
927 * There's nothing we can do on a situation
928 * where dirty data could not be read from
929 * the log. It does not make much sense to
930 * behead the system on such scenario so
931 * trigger a self-heal and go on. The worst
932 * thing that can happen? Data loss, that's it.
933 */
934 DPRINT1("Triggering self-heal mode, DATA LOSS IS IMMINENT\n");
935 return SelfHeal;
936 }
937
938 /* Check the dirty vector */
939 if (*((PULONG)DirtyVector) != HV_LOG_DIRTY_SIGNATURE)
940 {
942 {
943 DPRINT1("The log's dirty vector signature is not valid\n");
944 return Fail;
945 }
946
947 /*
948 * Trigger a self-heal like above. If the
949 * vector signature is garbage then logically
950 * whatever comes after the signature is also
951 * garbage.
952 */
953 DPRINT1("Triggering self-heal mode, DATA LOSS IS IMMINENT\n");
954 return SelfHeal;
955 }
956
957 /* Now read each data individually and write it back to hive */
958 LogIndex = 0;
959 StorageLength = BaseBlock->Length / HBLOCK_SIZE;
960 for (BlockIndex = 0; BlockIndex < StorageLength; BlockIndex++)
961 {
962 /* Skip this block if it's not dirty and go to the next one */
963 if (DirtyVector[BlockIndex + sizeof(HV_LOG_DIRTY_SIGNATURE)] != HV_LOG_DIRTY_BLOCK)
964 {
965 continue;
966 }
967
969 Success = Hive->FileRead(Hive,
971 &FileOffset,
972 Buffer,
974 if (!Success)
975 {
976 DPRINT1("Failed to read the dirty block (index %lu)\n", BlockIndex);
977 return Fail;
978 }
979
980 FileOffset = HBLOCK_SIZE + BlockIndex * HBLOCK_SIZE;
981 Success = Hive->FileWrite(Hive,
983 &FileOffset,
984 Buffer,
986 if (!Success)
987 {
988 DPRINT1("Failed to write dirty block to hive (index %lu)\n", BlockIndex);
989 return Fail;
990 }
991
992 /* Increment the index in log as we continue further */
993 LogIndex++;
994 }
995
996 return HiveSuccess;
997}
998#endif
999
1029CMAPI
1031 _In_ PHHIVE Hive,
1033{
1036 PHBASE_BLOCK BaseBlock = NULL;
1037/* FIXME: See the comment above (near HvpQueryHiveSize) */
1038#if defined(_M_AMD64)
1039 ULONG Result;
1040#else
1041 ULONG Result, Result2;
1042#endif
1044 ULONG Offset = 0;
1045 PVOID HiveData;
1047 BOOLEAN HiveSelfHeal = FALSE;
1048
1049 /* Get the hive header */
1050 Result = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp);
1051 switch (Result)
1052 {
1053 /* Out of memory */
1054 case NoMemory:
1055 {
1056 /* Fail */
1057 DPRINT1("There's no enough memory to get the header\n");
1059 }
1060
1061 /* Not a hive */
1062 case NotHive:
1063 {
1064 /* Fail */
1065 DPRINT1("The hive is not an actual registry hive file\n");
1067 }
1068
1069 /* Hive data needs a repair */
1070 case RecoverData:
1071 {
1072 /*
1073 * FIXME: We must be handling this status
1074 * case if the header isn't corrupt but
1075 * the counter sequences do not match but
1076 * due to a hack in HvLoadHive we have
1077 * to do both a header + data recovery.
1078 * RecoverHeader also implies RecoverData
1079 * anyway. When HvLoadHive gets rid of
1080 * that hack, data recovery must be done
1081 * after we read the hive block by block.
1082 */
1083 break;
1084 }
1085
1086 /* Hive header needs a repair */
1087 case RecoverHeader:
1088/* FIXME: See the comment above (near HvpQueryHiveSize) */
1089#if defined(_M_AMD64)
1090 {
1092 }
1093#else
1094 {
1095 /* Check if this hive has a log at hand to begin with */
1096 #if (NTDDI_VERSION < NTDDI_VISTA)
1097 if (!Hive->Log)
1098 {
1099 DPRINT1("The hive has no log for header recovery\n");
1101 }
1102 #endif
1103
1104 /* The header needs to be recovered so do it */
1105 DPRINT1("Attempting to heal the header...\n");
1106 Result2 = HvpRecoverHeaderFromLog(Hive, &TimeStamp, &BaseBlock);
1107 if (Result2 == NoMemory)
1108 {
1109 DPRINT1("There's no enough memory to recover header from log\n");
1111 }
1112
1113 /* Did we fail? */
1114 if (Result2 == Fail)
1115 {
1116 DPRINT1("Failed to recover the hive header\n");
1118 }
1119
1120 /* Did we trigger the self-heal mode? */
1121 if (Result2 == SelfHeal)
1122 {
1123 HiveSelfHeal = TRUE;
1124 }
1125
1126 /* Now recover the data */
1127 Result2 = HvpRecoverDataFromLog(Hive, BaseBlock);
1128 if (Result2 == Fail)
1129 {
1130 DPRINT1("Failed to recover the hive data\n");
1132 }
1133
1134 /* Tag the boot as self heal if we haven't done it before */
1135 if ((Result2 == SelfHeal) && (!HiveSelfHeal))
1136 {
1137 HiveSelfHeal = TRUE;
1138 }
1139
1140 break;
1141 }
1142#endif
1143 }
1144
1145 /* Set the boot type */
1146 BaseBlock->BootType = HiveSelfHeal ? HBOOT_TYPE_SELF_HEAL : HBOOT_TYPE_REGULAR;
1147
1148 /* Setup hive data */
1149 Hive->BaseBlock = BaseBlock;
1150 Hive->Version = BaseBlock->Minor;
1151
1152 /* Allocate a buffer large enough to hold the hive */
1153 FileSize = HBLOCK_SIZE + BaseBlock->Length; // == sizeof(HBASE_BLOCK) + BaseBlock->Length;
1154 HiveData = Hive->Allocate(FileSize, TRUE, TAG_CM);
1155 if (!HiveData)
1156 {
1157 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
1158 DPRINT1("There's no enough memory to allocate hive data\n");
1160 }
1161
1162 /* HACK (see explanation below): Now read the whole hive */
1163 Success = Hive->FileRead(Hive,
1165 &Offset,
1166 HiveData,
1167 FileSize);
1168 if (!Success)
1169 {
1170 DPRINT1("Failed to read the whole hive\n");
1171 Hive->Free(HiveData, FileSize);
1172 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
1174 }
1175
1176 /*
1177 * HACK (FIXME): Free our base block... it's useless in
1178 * this implementation.
1179 *
1180 * And it's useless because while the idea of reading the
1181 * hive from physical file is correct, the implementation
1182 * is hacky and incorrect. Instead of reading the whole hive,
1183 * we should be instead reading the hive block by block,
1184 * deconstruct the block buffer and enlist the bins and
1185 * prepare the storage for the hive. What we currently do
1186 * is we try to initialize the hive storage and bins enlistment
1187 * by calling HvpInitializeMemoryHive below. This mixes
1188 * HINIT_FILE and HINIT_MEMORY together which is disgusting
1189 * because HINIT_FILE implementation shouldn't be calling
1190 * HvpInitializeMemoryHive.
1191 */
1192 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
1193 Status = HvpInitializeMemoryHive(Hive, HiveData, FileName);
1194 if (!NT_SUCCESS(Status))
1195 {
1196 DPRINT1("Failed to initialize hive from memory\n");
1197 Hive->Free(HiveData, FileSize);
1198 return Status;
1199 }
1200
1201 /*
1202 * If we have done some sort of recovery against
1203 * the hive we were going to load it from file,
1204 * tell the caller we did recover it. The caller
1205 * is responsible to flush the data later on.
1206 */
1208}
1209
1351CMAPI
1353 _Inout_ PHHIVE RegistryHive,
1354 _In_ ULONG OperationType,
1355 _In_ ULONG HiveFlags,
1357 _In_opt_ PVOID HiveData,
1360 _In_opt_ PFILE_SET_SIZE_ROUTINE FileSetSize,
1361 _In_opt_ PFILE_WRITE_ROUTINE FileWrite,
1363 _In_opt_ PFILE_FLUSH_ROUTINE FileFlush,
1364 _In_ ULONG Cluster,
1366{
1368 PHHIVE Hive = RegistryHive;
1369
1370 /*
1371 * Create a new hive structure that will hold all the maintenance data.
1372 */
1373
1374 RtlZeroMemory(Hive, sizeof(HHIVE));
1376
1377 Hive->Allocate = Allocate;
1378 Hive->Free = Free;
1379 Hive->FileSetSize = FileSetSize;
1380 Hive->FileWrite = FileWrite;
1381 Hive->FileRead = FileRead;
1382 Hive->FileFlush = FileFlush;
1383
1384 Hive->RefreshCount = 0;
1386 Hive->Cluster = Cluster;
1387 Hive->BaseBlockAlloc = sizeof(HBASE_BLOCK); // == HBLOCK_SIZE
1388
1389 Hive->Version = HSYS_MINOR;
1390#if (NTDDI_VERSION < NTDDI_VISTA)
1391 Hive->Log = (FileType == HFILE_TYPE_LOG);
1392 Hive->Alternate = (FileType == HFILE_TYPE_ALTERNATE);
1393#endif
1394 Hive->HiveFlags = HiveFlags & ~HIVE_NOLAZYFLUSH;
1395
1396 // TODO: The CellRoutines point to different callbacks
1397 // depending on the OperationType.
1399 Hive->ReleaseCellRoutine = NULL;
1400
1401 switch (OperationType)
1402 {
1403 case HINIT_CREATE:
1404 {
1405 /* Create a new fresh hive */
1406 Status = HvpCreateHive(Hive, FileName);
1407 break;
1408 }
1409
1410 case HINIT_MEMORY:
1411 {
1412 /* Initialize a hive from memory */
1413 Status = HvpInitializeMemoryHive(Hive, HiveData, FileName);
1414 break;
1415 }
1416
1417 case HINIT_FLAT:
1418 {
1419 /* Initialize a flat read-only hive */
1420 Status = HvpInitializeFlatHive(Hive, HiveData);
1421 break;
1422 }
1423
1424 case HINIT_FILE:
1425 {
1426 /* Initialize a hive by loading it from physical file in backing storage */
1427 Status = HvLoadHive(Hive, FileName);
1428 if ((Status != STATUS_SUCCESS) &&
1430 {
1431 /* Unrecoverable failure */
1432 DPRINT1("Registry hive couldn't be initialized, it's corrupt (hive 0x%p)\n", Hive);
1433 return Status;
1434 }
1435
1436/* FIXME: See the comment above (near HvpQueryHiveSize) */
1437#if !defined(_M_AMD64)
1438 /*
1439 * Check if we have recovered this hive. We are responsible to
1440 * flush the primary hive back to backing storage afterwards.
1441 */
1443 {
1444 if (!HvSyncHiveFromRecover(Hive))
1445 {
1446 DPRINT1("Fail to write healthy data back to hive\n");
1448 }
1449
1450 /*
1451 * We are saved from hell, now clear out the
1452 * dirty bits and dirty count.
1453 *
1454 * FIXME: We must as well clear out the log
1455 * and reset its size to 0 but we are lacking
1456 * in code that deals with log growing/shrinking
1457 * management. When the time comes to implement
1458 * this stuff we must set the LogSize and file size
1459 * to 0 here.
1460 */
1462 Hive->DirtyCount = 0;
1463
1464 /*
1465 * Masquerade the status code as success.
1466 * STATUS_REGISTRY_RECOVERED is not a failure
1467 * code but not STATUS_SUCCESS either so the caller
1468 * thinks we failed at our job.
1469 */
1471 }
1472#endif
1473 break;
1474 }
1475
1477 {
1478 // Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
1479 // break;
1480 DPRINT1("HINIT_MEMORY_INPLACE is UNIMPLEMENTED\n");
1482 }
1483
1484 case HINIT_MAPFILE:
1485 {
1486 DPRINT1("HINIT_MAPFILE is UNIMPLEMENTED\n");
1488 }
1489
1490 default:
1491 {
1492 DPRINT1("Invalid operation type (OperationType = %lu)\n", OperationType);
1494 }
1495 }
1496
1497 return Status;
1498}
1499
1510VOID
1511CMAPI
1513 _In_ PHHIVE RegistryHive)
1514{
1515 if (!RegistryHive->ReadOnly)
1516 {
1517 /* Release hive bitmap */
1518 if (RegistryHive->DirtyVector.Buffer)
1519 {
1520 RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
1521 }
1522
1523 HvpFreeHiveBins(RegistryHive);
1524
1525 /* Free the BaseBlock */
1526 if (RegistryHive->BaseBlock)
1527 {
1528 RegistryHive->Free(RegistryHive->BaseBlock, RegistryHive->BaseBlockAlloc);
1529 RegistryHive->BaseBlock = NULL;
1530 }
1531 }
1532}
1533
1534/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define CMAPI
Definition: cfgmgr32.h:41
Definition: bin.h:44
Definition: bufpool.h:45
BOOLEAN CMAPI CmIsSelfHealEnabled(_In_ BOOLEAN FixHive)
Checks if self healing is permitted by the kernel and/or bootloader. Self healing is also triggered i...
Definition: cmheal.c:369
BOOLEAN CMAPI HvSyncHiveFromRecover(_In_ PHHIVE RegistryHive)
Synchronizes a hive with recovered data during a healing/resuscitation operation of the registry.
Definition: hivewrt.c:672
ULONG CMAPI HvpHiveHeaderChecksum(PHBASE_BLOCK HiveHeader)
Definition: hivesum.c:17
PCELL_DATA CMAPI HvpGetCellData(_In_ PHHIVE Hive, _In_ HCELL_INDEX CellIndex)
Definition: hivecell.c:77
NTSTATUS CMAPI HvpCreateHiveFreeCellList(PHHIVE Hive)
Definition: hivecell.c:306
#define TAG_CM
Definition: cmlib.h:212
#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:32
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
@ Success
Definition: eventcreate.c:712
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
union Alignment_ Alignment
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static ULONG BitmapBuffer[(XMS_BLOCKS+31)/32]
Definition: himem.c:86
BOOLEAN(CMAPI * PFILE_READ_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, PULONG FileOffset, PVOID Buffer, SIZE_T BufferLength)
Definition: hivedata.h:248
#define HV_HBIN_SIGNATURE
Definition: hivedata.h:64
#define HBOOT_BOOT_RECOVERED_BY_ALTERNATE_HIVE
Definition: hivedata.h:96
#define HBOOT_TYPE_REGULAR
Definition: hivedata.h:88
#define HV_HHIVE_SIGNATURE
Definition: hivedata.h:62
#define HINIT_CREATE
Definition: hivedata.h:13
@ Volatile
Definition: hivedata.h:128
@ Stable
Definition: hivedata.h:127
#define HTYPE_COUNT
Definition: hivedata.h:83
#define HBLOCK_SIZE
Definition: hivedata.h:42
#define HINIT_FILE
Definition: hivedata.h:15
#define HV_LOG_HEADER_SIZE
Definition: hivedata.h:46
#define HINIT_MEMORY
Definition: hivedata.h:14
#define HFILE_TYPE_ALTERNATE
Definition: hivedata.h:36
#define HFILE_TYPE_LOG
Definition: hivedata.h:34
#define HV_HBLOCK_SIGNATURE
Definition: hivedata.h:63
BOOLEAN(CMAPI * PFILE_WRITE_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, PULONG FileOffset, PVOID Buffer, SIZE_T BufferLength)
Definition: hivedata.h:257
VOID(CMAPI * PFREE_ROUTINE)(PVOID Ptr, ULONG Quota)
Definition: hivedata.h:242
#define HINIT_FLAT
Definition: hivedata.h:17
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
struct _HBASE_BLOCK HBASE_BLOCK
#define HINIT_MAPFILE
Definition: hivedata.h:18
struct _HBIN * PHBIN
#define HCELL_NIL
Definition: hivedata.h:110
#define HSYS_MINOR
Definition: hivedata.h:70
#define HSYS_MAJOR
Definition: hivedata.h:69
#define HIVE_FILENAME_MAXLEN
Definition: hivedata.h:139
BOOLEAN(CMAPI * PFILE_FLUSH_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, PLARGE_INTEGER FileOffset, ULONG Length)
Definition: hivedata.h:274
#define HV_LOG_DIRTY_BLOCK
Definition: hivedata.h:56
PVOID(CMAPI * PALLOCATE_ROUTINE)(SIZE_T Size, BOOLEAN Paged, ULONG Tag)
Definition: hivedata.h:235
#define HINIT_MEMORY_INPLACE
Definition: hivedata.h:16
#define HBOOT_TYPE_SELF_HEAL
Definition: hivedata.h:89
#define HBASE_FORMAT_MEMORY
Definition: hivedata.h:78
BOOLEAN(CMAPI * PFILE_SET_SIZE_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, ULONG FileSize, ULONG OldfileSize)
Definition: hivedata.h:266
#define HV_LOG_DIRTY_SIGNATURE
Definition: hivedata.h:57
#define HSECTOR_SIZE
Definition: hivedata.h:43
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
static __inline PHBASE_BLOCK HvpAllocBaseBlockAligned(_In_ PHHIVE Hive, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Allocates a cluster-aligned hive base header block.
Definition: hiveinit.c:143
NTSTATUS CMAPI HvInitialize(_Inout_ PHHIVE RegistryHive, _In_ ULONG OperationType, _In_ ULONG HiveFlags, _In_ ULONG FileType, _In_opt_ PVOID HiveData, _In_opt_ PALLOCATE_ROUTINE Allocate, _In_opt_ PFREE_ROUTINE Free, _In_opt_ PFILE_SET_SIZE_ROUTINE FileSetSize, _In_opt_ PFILE_WRITE_ROUTINE FileWrite, _In_opt_ PFILE_READ_ROUTINE FileRead, _In_opt_ PFILE_FLUSH_ROUTINE FileFlush, _In_ ULONG Cluster, _In_opt_ PCUNICODE_STRING FileName)
Initializes a registry hive. It allocates a hive descriptor and sets up the hive type depending on th...
Definition: hiveinit.c:1352
VOID CMAPI HvFree(_In_ PHHIVE RegistryHive)
Frees all the bins within the storage, the dirty vector and the base block associated with the given ...
Definition: hiveinit.c:1512
ULONG CMAPI HvpQueryHiveSize(_In_ PHHIVE Hive)
Computes the hive space size by querying the file size of the associated hive file.
Definition: hiveinit.c:671
_RESULT
Definition: hiveinit.c:18
@ HiveSuccess
Definition: hiveinit.c:22
@ NotHive
Definition: hiveinit.c:19
@ Fail
Definition: hiveinit.c:20
@ SelfHeal
Definition: hiveinit.c:25
@ RecoverData
Definition: hiveinit.c:24
@ NoMemory
Definition: hiveinit.c:21
@ RecoverHeader
Definition: hiveinit.c:23
NTSTATUS CMAPI HvpInitializeMemoryHive(_In_ PHHIVE Hive, _In_ PHBASE_BLOCK ChunkBase, _In_opt_ PCUNICODE_STRING FileName)
Initializes a hive descriptor from an already loaded registry hive stored in memory....
Definition: hiveinit.c:318
NTSTATUS CMAPI HvLoadHive(_In_ PHHIVE Hive, _In_opt_ PCUNICODE_STRING FileName)
Loads a registry hive from a physical hive file within the physical backing storage....
Definition: hiveinit.c:1030
static VOID HvpInitFileName(_Inout_ PHBASE_BLOCK BaseBlock, _In_opt_ PCUNICODE_STRING FileName)
Initializes a NULL-terminated Unicode hive file name of a hive header by copying the last 31 characte...
Definition: hiveinit.c:189
NTSTATUS CMAPI HvpCreateHive(_Inout_ PHHIVE RegistryHive, _In_opt_ PCUNICODE_STRING FileName)
Initializes a hive descriptor structure for a newly created hive in memory.
Definition: hiveinit.c:238
enum _RESULT RESULT
NTSTATUS CMAPI HvpInitializeFlatHive(_In_ PHHIVE Hive, _In_ PHBASE_BLOCK ChunkBase)
Initializes a hive descriptor for an already loaded hive that is stored in memory....
Definition: hiveinit.c:485
RESULT CMAPI HvpGetHiveHeader(_In_ PHHIVE Hive, _Inout_ PHBASE_BLOCK *HiveBaseBlock, _Inout_ PLARGE_INTEGER TimeStamp)
Retrieves the base block hive header from the primary hive file stored in physical backing storage....
Definition: hiveinit.c:552
RESULT CMAPI HvpRecoverHeaderFromLog(_In_ PHHIVE Hive, _In_ PLARGE_INTEGER TimeStamp, _Inout_ PHBASE_BLOCK *BaseBlock)
Recovers the base block header by obtaining it from a log file associated with the hive.
Definition: hiveinit.c:743
RESULT CMAPI HvpRecoverDataFromLog(_In_ PHHIVE Hive, _In_ PHBASE_BLOCK BaseBlock)
Recovers the registry data by obtaining it from a log that is associated with the hive.
Definition: hiveinit.c:899
VOID CMAPI HvpFreeHiveBins(_In_ PHHIVE Hive)
Frees all the bins within storage space associated with a hive descriptor.
Definition: hiveinit.c:90
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
#define ASSERT(a)
Definition: mode.c:44
#define ULL(a, b)
Definition: format_msg.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static IStorage Storage
Definition: ole2.c:3548
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_REGISTRY_RECOVERED
Definition: ntstatus.h:123
#define STATUS_NOT_REGISTRY_FILE
Definition: ntstatus.h:584
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_REGISTRY_CORRUPT
Definition: ntstatus.h:568
#define STATUS_REGISTRY_IO_FAILED
Definition: ntstatus.h:569
#define FileStandardInformation
Definition: propsheet.cpp:61
SECURITY_INTEGER TimeStamp
Definition: sspi.h:78
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
Definition: cmlib.h:316
ULONG BootType
Definition: hivedata.h:186
ULONG Length
Definition: hivedata.h:171
HCELL_INDEX RootCell
Definition: hivedata.h:168
ULONG Sequence1
Definition: hivedata.h:147
ULONG Minor
Definition: hivedata.h:158
ULONG Type
Definition: hivedata.h:161
ULONG Major
Definition: hivedata.h:154
LARGE_INTEGER TimeStamp
Definition: hivedata.h:151
ULONG Signature
Definition: hivedata.h:144
ULONG Format
Definition: hivedata.h:164
ULONG CheckSum
Definition: hivedata.h:183
ULONG Sequence2
Definition: hivedata.h:148
ULONG Cluster
Definition: hivedata.h:174
HCELL_INDEX FileOffset
Definition: hivedata.h:198
ULONG Signature
Definition: hivedata.h:195
RTL_BITMAP DirtyVector
Definition: hivedata.h:329
PFILE_FLUSH_ROUTINE FileFlush
Definition: hivedata.h:323
PFILE_SET_SIZE_ROUTINE FileSetSize
Definition: hivedata.h:320
ULONG Signature
Definition: hivedata.h:313
ULONG HiveFlags
Definition: hivedata.h:347
PFILE_WRITE_ROUTINE FileWrite
Definition: hivedata.h:321
PALLOCATE_ROUTINE Allocate
Definition: hivedata.h:318
PFILE_READ_ROUTINE FileRead
Definition: hivedata.h:322
ULONG Cluster
Definition: hivedata.h:333
ULONG BaseBlockAlloc
Definition: hivedata.h:332
ULONG RefreshCount
Definition: hivedata.h:354
PGET_CELL_ROUTINE GetCellRoutine
Definition: hivedata.h:316
PFREE_ROUTINE Free
Definition: hivedata.h:319
ULONG DirtyCount
Definition: hivedata.h:330
ULONG Version
Definition: hivedata.h:356
PRELEASE_CELL_ROUTINE ReleaseCellRoutine
Definition: hivedata.h:317
ULONG StorageTypeCount
Definition: hivedata.h:355
Definition: hivedata.h:282
ULONG LowPart
Definition: sspi.h:75
LONG HighPart
Definition: sspi.h:76
uint32_t * PULONG
Definition: typedefs.h:59
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2290 u
ULONG LowPart
Definition: typedefs.h:106
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_In_ WDFDEVICE _In_ WDF_SPECIAL_FILE_TYPE FileType
Definition: wdfdevice.h:2741
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_In_opt_ PALLOCATE_FUNCTION Allocate
Definition: exfuncs.h:814
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:815
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2277
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180