ReactOS 0.4.16-dev-340-g0540c21
registry.c File Reference
#include <freeldr.h>
#include <cmlib.h>
#include "registry.h"
#include <internal/cmboot.h>
#include <debug.h>
Include dependency graph for registry.c:

Go to the source code of this file.

Macros

#define HCI_TO_HKEY(CellIndex)   ((HKEY)(ULONG_PTR)(CellIndex))
 
#define GET_HHIVE(CmHive)   (&((CmHive)->Hive))
 
#define GET_HHIVE_FROM_HKEY(hKey)   GET_HHIVE(CmSystemHive)
 
#define GET_CM_KEY_NODE(hHive, hKey)   ((PCM_KEY_NODE)HvGetCell(hHive, HKEY_TO_HCI(hKey)))
 
#define GET_HBASE_BLOCK(ChunkBase)   ((PHBASE_BLOCK)ChunkBase)
 

Functions

 DBG_DEFAULT_CHANNEL (REGISTRY)
 
PVOID NTAPI CmpAllocate (IN SIZE_T Size, IN BOOLEAN Paged, IN ULONG Tag)
 
VOID NTAPI CmpFree (IN PVOID Ptr, IN ULONG Quota)
 
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 purged during this procedure for initialization.
 
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.
 
static BOOLEAN RegRecoverHeaderHive (_Inout_ PVOID ChunkBase, _In_ PCSTR DirectoryPath, _In_ PCSTR LogName)
 Recovers the header base block of a flat registry hive.
 
static BOOLEAN RegRecoverDataHive (_Inout_ PVOID ChunkBase, _In_ PCSTR DirectoryPath, _In_ PCSTR LogName)
 Recovers the corrupt data of a primary flat registry hive.
 
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.
 
BOOLEAN RegInitCurrentControlSet (_In_ BOOLEAN LastKnownGood)
 
static BOOLEAN GetNextPathElement (_Out_ PUNICODE_STRING NextElement, _Inout_ PUNICODE_STRING RemainingPath)
 
LONG RegOpenKey (_In_ HKEY ParentKey, _In_z_ PCWSTR KeyName, _Out_ PHKEY Key)
 
static VOID RepGetValueData (_In_ PHHIVE Hive, _In_ PCM_KEY_VALUE ValueCell, _Out_opt_ PULONG Type, _Out_opt_ PUCHAR Data, _Inout_opt_ PULONG DataSize)
 
LONG RegQueryValue (_In_ HKEY Key, _In_z_ PCWSTR ValueName, _Out_opt_ PULONG Type, _Out_opt_ PUCHAR Data, _Inout_opt_ PULONG DataSize)
 

Variables

static PCMHIVE CmSystemHive
 
static HCELL_INDEX SystemRootCell
 
PHHIVE SystemHive = NULL
 
HKEY CurrentControlSetKey = NULL
 

Macro Definition Documentation

◆ GET_CM_KEY_NODE

#define GET_CM_KEY_NODE (   hHive,
  hKey 
)    ((PCM_KEY_NODE)HvGetCell(hHive, HKEY_TO_HCI(hKey)))

Definition at line 43 of file registry.c.

◆ GET_HBASE_BLOCK

#define GET_HBASE_BLOCK (   ChunkBase)    ((PHBASE_BLOCK)ChunkBase)

Definition at line 45 of file registry.c.

◆ GET_HHIVE

#define GET_HHIVE (   CmHive)    (&((CmHive)->Hive))

Definition at line 41 of file registry.c.

◆ GET_HHIVE_FROM_HKEY

#define GET_HHIVE_FROM_HKEY (   hKey)    GET_HHIVE(CmSystemHive)

Definition at line 42 of file registry.c.

◆ HCI_TO_HKEY

#define HCI_TO_HKEY (   CellIndex)    ((HKEY)(ULONG_PTR)(CellIndex))

Definition at line 36 of file registry.c.

Function Documentation

◆ CmpAllocate()

PVOID NTAPI CmpAllocate ( IN SIZE_T  Size,
IN BOOLEAN  Paged,
IN ULONG  Tag 
)

Definition at line 49 of file registry.c.

53{
55 return FrLdrHeapAlloc(Size, Tag);
56}
FORCEINLINE PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: mm.h:174
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
_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

Referenced by RegInitializeHive().

◆ CmpFree()

VOID NTAPI CmpFree ( IN PVOID  Ptr,
IN ULONG  Quota 
)

Definition at line 60 of file registry.c.

63{
66}
FORCEINLINE VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: mm.h:181
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898

Referenced by RegInitializeHive().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( REGISTRY  )

◆ GetNextPathElement()

static BOOLEAN GetNextPathElement ( _Out_ PUNICODE_STRING  NextElement,
_Inout_ PUNICODE_STRING  RemainingPath 
)
static

Definition at line 563 of file registry.c.

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}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ASSERT(a)
Definition: mode.c:44
unsigned short USHORT
Definition: pedump.c:61
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by RegOpenKey().

◆ RegImportBinaryHive()

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.

Parameters
[in]ChunkBaseA pointer to the registry base chunk that serves for SYSTEM hive initialization.
[in]ChunkSizeThe size of the registry base chunk. This parameter refers to the actual size of the SYSTEM hive. This parameter is currently unused.
[in]LoadAlternateIf set to TRUE, the function will initialize the hive as an alternate hive, otherwise FALSE to initialize it as primary.
Returns
Returns TRUE if hive importing and initialization have succeeded, FALSE otherwise.

Definition at line 449 of file registry.c.

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}
unsigned char BOOLEAN
#define ERR(fmt,...)
Definition: precomp.h:57
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
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_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
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
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
struct _CM_KEY_NODE * PCM_KEY_NODE
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:460
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:457
#define NULL
Definition: types.h:112
@ Success
Definition: eventcreate.c:712
#define HCELL_NIL
Definition: hivedata.h:110
#define HBOOT_BOOT_RECOVERED_BY_HIVE_LOG
Definition: hivedata.h:95
#define HBOOT_NO_BOOT_RECOVER
Definition: hivedata.h:94
struct _HBASE_BLOCK * PHBASE_BLOCK
#define TRACE(s)
Definition: solgame.cpp:4
Definition: cmlib.h:316
USHORT Signature
Definition: cmdata.h:92
HCELL_INDEX RootCell
Definition: hivedata.h:168
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:328
#define SearchPath
Definition: winbase.h:3925
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2294

Referenced by WinLdrInitSystemHive().

◆ RegInitCurrentControlSet()

BOOLEAN RegInitCurrentControlSet ( _In_ BOOLEAN  LastKnownGood)

Definition at line 525 of file registry.c.

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}
HKEY CurrentControlSetKey
Definition: registry.c:34
#define HCI_TO_HKEY(CellIndex)
Definition: registry.c:36
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
ULONG HCELL_INDEX
Definition: hivedata.h:105
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define L(x)
Definition: ntvdm.h:50

Referenced by WinLdrInitSystemHive().

◆ RegInitializeHive()

static BOOLEAN RegInitializeHive ( _In_ PCMHIVE  CmHive,
_In_ PVOID  ChunkBase,
_In_ BOOLEAN  LoadAlternate 
)
static

Initializes a flat hive descriptor for the hive and validates the registry hive. Volatile data is purged during this procedure for initialization.

Parameters
[in]CmHiveA pointer to a CM (in-memory) hive descriptor containing the hive descriptor to be initialized.
[in]ChunkBaseAn arbitrary pointer that points to the registry chunk base. This pointer serves as the base block containing the hive file header data.
[in]LoadAlternateIf set to TRUE, the function will initialize the hive as an alternate hive, otherwise FALSE to initialize it as primary.
Returns
Returns TRUE if the hive has been initialized and registry data inside the hive is valid, FALSE otherwise.

Definition at line 96 of file registry.c.

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}
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CmpFree(IN PVOID Ptr, IN ULONG Quota)
Definition: registry.c:60
PVOID NTAPI CmpAllocate(IN SIZE_T Size, IN BOOLEAN Paged, IN ULONG Tag)
Definition: registry.c:49
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
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
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
Definition: cmlib.h:281
ULONG CM_CHECK_REGISTRY_STATUS
Definition: cmlib.h:223
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES
Definition: cmlib.h:230
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
#define HFILE_TYPE_ALTERNATE
Definition: hivedata.h:36
#define HINIT_FLAT
Definition: hivedata.h:17
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33

Referenced by RegImportBinaryHive().

◆ RegLoadHiveLog()

static BOOLEAN RegLoadHiveLog ( _In_ PCSTR  DirectoryPath,
_In_ ULONG  LogFileOffset,
_In_ PCSTR  LogName,
_Out_ PVOID LogData 
)
static

Loads and reads a hive log at specified file offset.

Parameters
[in]DirectoryPathA pointer to a string that denotes the directory path of the hives and logs location.
[in]LogFileOffsetThe file offset of which this function uses to seek at specific position during read.
[in]LogNameA pointer to a string that denotes the name of the desired hive log (e.g. "SYSTEM").
[out]LogDataA pointer to the returned hive log data that was read. The following data varies depending on the specified offset set up by the caller, that is used to where to start reading from the hive log.
Returns
Returns TRUE if the hive log was loaded and read successfully, FALSE otherwise.
Remarks
The returned log data pointer to the caller is a virtual address. You must use VaToPa that converts the address to a physical one in order to actually use it!

Definition at line 182 of file registry.c.

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}
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 PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
#define MAX_PATH
Definition: compat.h:34
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
@ 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
static COORD Position
Definition: mouse.c:34
uint32_t ULONG
Definition: typedefs.h:59
_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
char CHAR
Definition: xmlstorage.h:175

Referenced by RegRecoverDataHive(), and RegRecoverHeaderHive().

◆ RegOpenKey()

LONG RegOpenKey ( _In_ HKEY  ParentKey,
_In_z_ PCWSTR  KeyName,
_Out_ PHKEY  Key 
)

Definition at line 676 of file registry.c.

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}
#define WARN(fmt,...)
Definition: precomp.h:61
static BOOLEAN GetNextPathElement(_Out_ PUNICODE_STRING NextElement, _Inout_ PUNICODE_STRING RemainingPath)
Definition: registry.c:563
#define GET_HHIVE_FROM_HKEY(hKey)
Definition: registry.c:42
#define HKEY_TO_HCI(hKey)
Definition: registry.h:28
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
#define ERROR_SUCCESS
Definition: deptool.c:10
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
_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_opt_ WDFKEY ParentKey
Definition: wdfregistry.h:69
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106

◆ RegQueryValue()

LONG RegQueryValue ( _In_ HKEY  Key,
_In_z_ PCWSTR  ValueName,
_Out_opt_ PULONG  Type,
_Out_opt_ PUCHAR  Data,
_Inout_opt_ PULONG  DataSize 
)

Definition at line 831 of file registry.c.

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}
Type
Definition: Type.h:7
#define GET_CM_KEY_NODE(hHive, hKey)
Definition: registry.c:43
struct _CM_KEY_VALUE * PCM_KEY_VALUE
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
Definition: cmvalue.c:99
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
static VOID RepGetValueData(IN PHHIVE Hive, IN PCM_KEY_VALUE ValueCell, OUT PULONG Type OPTIONAL, OUT PUCHAR Data OPTIONAL, IN OUT PULONG DataSize OPTIONAL)
Definition: registry.c:824
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
USHORT NameLength
Definition: cmdata.h:114
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243

◆ RegRecoverDataHive()

static BOOLEAN RegRecoverDataHive ( _Inout_ PVOID  ChunkBase,
_In_ PCSTR  DirectoryPath,
_In_ PCSTR  LogName 
)
static

Recovers the corrupt data of a primary flat registry hive.

Parameters
[in]ChunkBaseA pointer to the registry hive chunk base of which the damaged hive data is to be replaced with healthy data from the corresponding hive log.
[in]DirectoryPathA pointer to a string that denotes the directory path of the hives and logs location.
[in]LogNameA pointer to a string that denotes the name of the desired hive log (e.g. "SYSTEM").
Returns
Returns TRUE if the hive data was successfully recovered, FALSE otherwise.
Remarks
Data recovery of the target hive does not always guarantee the primary hive is fully recovered. It could happen a block from a hive log is not marked dirty (pending to be written to disk) that has healthy data therefore the following bad block would still remain in corrupt state in the main primary hive. In such scenarios an alternate hive must be replayed.

Definition at line 362 of file registry.c.

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}
#define GET_HBASE_BLOCK(ChunkBase)
Definition: registry.c:45
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
ULONG CMAPI HvpHiveHeaderChecksum(PHBASE_BLOCK HiveHeader)
Definition: hivesum.c:17
FORCEINLINE PVOID VaToPa(PVOID Va)
Definition: conversion.h:15
#define HBLOCK_SIZE
Definition: hivedata.h:42
#define HV_LOG_HEADER_SIZE
Definition: hivedata.h:46
#define HV_LOG_DIRTY_BLOCK
Definition: hivedata.h:56
#define HV_LOG_DIRTY_SIGNATURE
Definition: hivedata.h:57
#define HSECTOR_SIZE
Definition: hivedata.h:43
ULONG Length
Definition: hivedata.h:171
ULONG Sequence1
Definition: hivedata.h:147
ULONG CheckSum
Definition: hivedata.h:183
ULONG Sequence2
Definition: hivedata.h:148
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by RegImportBinaryHive().

◆ RegRecoverHeaderHive()

static BOOLEAN RegRecoverHeaderHive ( _Inout_ PVOID  ChunkBase,
_In_ PCSTR  DirectoryPath,
_In_ PCSTR  LogName 
)
static

Recovers the header base block of a flat registry hive.

Parameters
[in]ChunkBaseA pointer to the registry hive chunk base of which the damaged header block is to be recovered.
[in]DirectoryPathA pointer to a string that denotes the directory path of the hives and logs location.
[in]LogNameA pointer to a string that denotes the name of the desired hive log (e.g. "SYSTEM").
Returns
Returns TRUE if the header base block was successfully recovered, FALSE otherwise.

Definition at line 289 of file registry.c.

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}
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
#define HFILE_TYPE_LOG
Definition: hivedata.h:34
ULONG Type
Definition: hivedata.h:161
ULONG Cluster
Definition: hivedata.h:174

Referenced by RegImportBinaryHive().

◆ RepGetValueData()

static VOID RepGetValueData ( _In_ PHHIVE  Hive,
_In_ PCM_KEY_VALUE  ValueCell,
_Out_opt_ PULONG  Type,
_Out_opt_ PUCHAR  Data,
_Inout_opt_ PULONG  DataSize 
)
static

Definition at line 794 of file registry.c.

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}
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define min(a, b)
Definition: monoChain.cc:55

Referenced by RegQueryValue(), and RegQueryValueExW().

Variable Documentation

◆ CmSystemHive

PCMHIVE CmSystemHive
static

Definition at line 30 of file registry.c.

Referenced by RegImportBinaryHive(), and RegOpenKey().

◆ CurrentControlSetKey

◆ SystemHive

◆ SystemRootCell

HCELL_INDEX SystemRootCell
static

Definition at line 31 of file registry.c.

Referenced by RegImportBinaryHive(), RegInitCurrentControlSet(), and RegOpenKey().