ReactOS 0.4.16-dev-819-g75c0dc0
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}
PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: heap.c:533
#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}
VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: heap.c:539
_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 541 of file registry.c.

544{
545 /* Check if there are any characters left */
546 if (RemainingPath->Length < sizeof(WCHAR))
547 {
548 /* Nothing left, bail out early */
549 return FALSE;
550 }
551
552 /* The next path elements starts with the remaining path */
553 NextElement->Buffer = RemainingPath->Buffer;
554
555 /* Loop until the path element ends */
556 while ((RemainingPath->Length >= sizeof(WCHAR)) &&
557 (RemainingPath->Buffer[0] != '\\'))
558 {
559 /* Skip this character */
560 RemainingPath->Buffer++;
561 RemainingPath->Length -= sizeof(WCHAR);
562 }
563
564 NextElement->Length = (USHORT)(RemainingPath->Buffer - NextElement->Buffer) * sizeof(WCHAR);
565 NextElement->MaximumLength = NextElement->Length;
566
567 /* Check if the path element ended with a path separator */
568 if (RemainingPath->Length >= sizeof(WCHAR))
569 {
570 /* Skip the path separator */
571 ASSERT(RemainingPath->Buffer[0] == '\\');
572 RemainingPath->Buffer++;
573 RemainingPath->Length -= sizeof(WCHAR);
574 }
575
576 /* Return whether we got any characters */
577 return TRUE;
578}
#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 436 of file registry.c.

441{
443 PCM_KEY_NODE KeyNode;
444
445 TRACE("RegImportBinaryHive(%p, 0x%lx)\n", ChunkBase, ChunkSize);
446
447 /* Assume that we don't need boot recover, unless we have to */
448 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_NO_BOOT_RECOVER;
449
450 /* Allocate and initialize the hive */
451 CmSystemHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
452 Success = RegInitializeHive(CmSystemHive, ChunkBase, LoadAlternate);
453 if (!Success)
454 {
455 /* Free the buffer and retry again */
458
459 if (!RegRecoverHeaderHive(ChunkBase, SearchPath, "SYSTEM"))
460 {
461 ERR("Failed to recover the hive header block\n");
462 return FALSE;
463 }
464
465 if (!RegRecoverDataHive(ChunkBase, SearchPath, "SYSTEM"))
466 {
467 ERR("Failed to recover the hive data\n");
468 return FALSE;
469 }
470
471 /* Now retry initializing the hive again */
472 CmSystemHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
473 Success = RegInitializeHive(CmSystemHive, ChunkBase, LoadAlternate);
474 if (!Success)
475 {
476 ERR("Corrupted hive (despite recovery) %p\n", ChunkBase);
478 return FALSE;
479 }
480
481 /*
482 * Acknowledge the kernel we recovered the SYSTEM hive
483 * on our side by applying log data.
484 */
485 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_BOOT_RECOVERED_BY_HIVE_LOG;
486 }
487
488 /* Save the root key node */
492
493 /* Verify it is accessible */
495 ASSERT(KeyNode);
498
499 return TRUE;
500}
unsigned char BOOLEAN
#define ERR(fmt,...)
Definition: precomp.h:57
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
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:277
#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:350
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 503 of file registry.c.

505{
506 UNICODE_STRING ControlSetName;
507 HCELL_INDEX ControlCell;
508 PCM_KEY_NODE KeyNode;
509 BOOLEAN AutoSelect;
510
511 TRACE("RegInitCurrentControlSet\n");
512
513 /* Choose which control set to open and set it as the new "Current" */
514 RtlInitUnicodeString(&ControlSetName,
515 LastKnownGood ? L"LastKnownGood"
516 : L"Default");
517
518 ControlCell = CmpFindControlSet(SystemHive,
520 &ControlSetName,
521 &AutoSelect);
522 if (ControlCell == HCELL_NIL)
523 {
524 ERR("CmpFindControlSet('%wZ') failed\n", &ControlSetName);
525 return FALSE;
526 }
527
528 CurrentControlSetKey = HCI_TO_HKEY(ControlCell);
529
530 /* Verify it is accessible */
531 KeyNode = (PCM_KEY_NODE)HvGetCell(SystemHive, ControlCell);
532 ASSERT(KeyNode);
534 HvReleaseCell(SystemHive, ControlCell);
535
536 return TRUE;
537}
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 CM_CHECK_REGISTRY_STATUS CmStatusCode;
103
104 /* Initialize the hive */
105 Status = HvInitialize(GET_HHIVE(CmHive),
106 HINIT_FLAT, // HINIT_MEMORY_INPLACE
107 0,
109 ChunkBase,
111 CmpFree,
112 NULL,
113 NULL,
114 NULL,
115 NULL,
116 1,
117 NULL);
118 if (!NT_SUCCESS(Status))
119 {
120 ERR("Failed to initialize the flat hive (Status 0x%lx)\n", Status);
121 return FALSE;
122 }
123
124 /* Now check the hive and purge volatile data */
126 if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode))
127 {
128 ERR("CmCheckRegistry detected problems with the loaded flat hive (check code %lu)\n", CmStatusCode);
129 return FALSE;
130 }
131
132 return TRUE;
133}
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 170 of file registry.c.

175{
177 ULONG LogId;
178 CHAR LogPath[MAX_PATH];
179 ULONG LogFileSize;
183 PVOID LogDataVirtual;
184 PVOID LogDataPhysical;
185
186 /* Build the full path to the hive log */
187 RtlStringCbCopyA(LogPath, sizeof(LogPath), DirectoryPath);
188 RtlStringCbCatA(LogPath, sizeof(LogPath), LogName);
189
190 /* Open the file */
191 Status = ArcOpen(LogPath, OpenReadOnly, &LogId);
192 if (Status != ESUCCESS)
193 {
194 ERR("Failed to open %s (ARC code %lu)\n", LogName, Status);
195 return FALSE;
196 }
197
198 /* Get the file length */
200 if (Status != ESUCCESS)
201 {
202 ERR("Failed to get file information from %s (ARC code %lu)\n", LogName, Status);
203 ArcClose(LogId);
204 return FALSE;
205 }
206
207 /* Capture the size of the hive log file */
208 LogFileSize = FileInfo.EndingAddress.LowPart;
209 if (LogFileSize == 0)
210 {
211 ERR("LogFileSize is 0, %s is corrupt\n", LogName);
212 ArcClose(LogId);
213 return FALSE;
214 }
215
216 /* Allocate memory blocks for our log data */
217 LogDataPhysical = MmAllocateMemoryWithType(
218 MM_SIZE_TO_PAGES(LogFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT,
220 if (LogDataPhysical == NULL)
221 {
222 ERR("Failed to allocate memory for log data\n");
223 ArcClose(LogId);
224 return FALSE;
225 }
226
227 /* Convert the address to virtual so that it can be useable */
228 LogDataVirtual = PaToVa(LogDataPhysical);
229
230 /* Seek within the log file at desired position */
231 Position.QuadPart = LogFileOffset;
233 if (Status != ESUCCESS)
234 {
235 ERR("Failed to seek at %s (ARC code %lu)\n", LogName, Status);
236 ArcClose(LogId);
237 return FALSE;
238 }
239
240 /* And read the actual data from the log */
241 Status = ArcRead(LogId, LogDataPhysical, LogFileSize, &BytesRead);
242 if (Status != ESUCCESS)
243 {
244 ERR("Failed to read %s (ARC code %lu)\n", LogName, Status);
245 ArcClose(LogId);
246 return FALSE;
247 }
248
249 *LogData = LogDataVirtual;
250 ArcClose(LogId);
251 return TRUE;
252}
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 654 of file registry.c.

658{
659 UNICODE_STRING RemainingPath, SubKeyName;
660 UNICODE_STRING CurrentControlSet = RTL_CONSTANT_STRING(L"CurrentControlSet");
662 PCM_KEY_NODE KeyNode;
663 HCELL_INDEX CellIndex;
664
665 TRACE("RegOpenKey(%p, '%S', %p)\n", ParentKey, KeyName, Key);
666
667 /* Initialize the remaining path name */
668 RtlInitUnicodeString(&RemainingPath, KeyName);
669
670 /* Check if we have a parent key */
671 if (ParentKey == NULL)
672 {
673 UNICODE_STRING SubKeyName1, SubKeyName2, SubKeyName3;
675 UNICODE_STRING MachinePath = RTL_CONSTANT_STRING(L"MACHINE");
676 UNICODE_STRING SystemPath = RTL_CONSTANT_STRING(L"SYSTEM");
677
678 TRACE("RegOpenKey: absolute path\n");
679
680 if ((RemainingPath.Length < sizeof(WCHAR)) ||
681 RemainingPath.Buffer[0] != '\\')
682 {
683 /* The key path is not absolute */
684 ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
686 }
687
688 /* Skip initial path separator */
689 RemainingPath.Buffer++;
690 RemainingPath.Length -= sizeof(WCHAR);
691
692 /* Get the first 3 path elements */
693 GetNextPathElement(&SubKeyName1, &RemainingPath);
694 GetNextPathElement(&SubKeyName2, &RemainingPath);
695 GetNextPathElement(&SubKeyName3, &RemainingPath);
696 TRACE("RegOpenKey: %wZ / %wZ / %wZ\n", &SubKeyName1, &SubKeyName2, &SubKeyName3);
697
698 /* Check if we have the correct path */
699 if (!RtlEqualUnicodeString(&SubKeyName1, &RegistryPath, TRUE) ||
700 !RtlEqualUnicodeString(&SubKeyName2, &MachinePath, TRUE) ||
701 !RtlEqualUnicodeString(&SubKeyName3, &SystemPath, TRUE))
702 {
703 /* The key path is not inside HKLM\Machine\System */
704 ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
706 }
707
708 /* Use the root key */
709 CellIndex = SystemRootCell;
710 }
711 else
712 {
713 /* Use the parent key */
714 CellIndex = HKEY_TO_HCI(ParentKey);
715 }
716
717 /* Check if this is the root key */
718 if (CellIndex == SystemRootCell)
719 {
720 UNICODE_STRING TempPath = RemainingPath;
721
722 /* Get the first path element */
723 GetNextPathElement(&SubKeyName, &TempPath);
724
725 /* Check if this is CurrentControlSet */
726 if (RtlEqualUnicodeString(&SubKeyName, &CurrentControlSet, TRUE))
727 {
728 /* Use the CurrentControlSetKey and update the remaining path */
730 RemainingPath = TempPath;
731 }
732 }
733
734 /* Get the key node */
735 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
736 ASSERT(KeyNode);
738
739 TRACE("RegOpenKey: RemainingPath '%wZ'\n", &RemainingPath);
740
741 /* Loop while there are path elements */
742 while (GetNextPathElement(&SubKeyName, &RemainingPath))
743 {
744 HCELL_INDEX NextCellIndex;
745
746 TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName);
747
748 /* Get the next sub key */
749 NextCellIndex = CmpFindSubKeyByName(Hive, KeyNode, &SubKeyName);
750 HvReleaseCell(Hive, CellIndex);
751 CellIndex = NextCellIndex;
752 if (CellIndex == HCELL_NIL)
753 {
754 WARN("Did not find sub key '%wZ' (full: %S)\n", &SubKeyName, KeyName);
756 }
757
758 /* Get the found key */
759 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
760 ASSERT(KeyNode);
762 }
763
764 HvReleaseCell(Hive, CellIndex);
765 *Key = HCI_TO_HKEY(CellIndex);
766
767 return ERROR_SUCCESS;
768}
#define WARN(fmt,...)
Definition: precomp.h:61
static BOOLEAN GetNextPathElement(_Out_ PUNICODE_STRING NextElement, _Inout_ PUNICODE_STRING RemainingPath)
Definition: registry.c:541
#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 809 of file registry.c.

815{
817 PCM_KEY_NODE KeyNode;
818 PCM_KEY_VALUE ValueCell;
819 HCELL_INDEX CellIndex;
820 UNICODE_STRING ValueNameString;
821
822 TRACE("RegQueryValue(%p, '%S', %p, %p, %p)\n",
824
825 /* Get the key node */
826 KeyNode = GET_CM_KEY_NODE(Hive, Key);
827 ASSERT(KeyNode);
829
830 /* Initialize value name string */
831 RtlInitUnicodeString(&ValueNameString, ValueName);
832 CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
833 if (CellIndex == HCELL_NIL)
834 {
835 TRACE("RegQueryValue value not found in key (%.*s)\n",
836 KeyNode->NameLength, KeyNode->Name);
839 }
841
842 /* Get the value cell */
843 ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
844 ASSERT(ValueCell != NULL);
845
846 RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
847
848 HvReleaseCell(Hive, CellIndex);
849
850 return ERROR_SUCCESS;
851}
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 350 of file registry.c.

354{
356 ULONG StorageLength;
357 ULONG BlockIndex, LogIndex;
358 PUCHAR BlockPtr, BlockDest;
359 CHAR FullLogFileName[MAX_PATH];
360 PVOID LogData;
361 PUCHAR LogDataPhysical;
362 PHBASE_BLOCK HiveBaseBlock;
363
364 /* Build the complete path of the hive log */
365 RtlStringCbCopyA(FullLogFileName, sizeof(FullLogFileName), LogName);
366 RtlStringCbCatA(FullLogFileName, sizeof(FullLogFileName), ".LOG");
367 Success = RegLoadHiveLog(DirectoryPath, HV_LOG_HEADER_SIZE, FullLogFileName, &LogData);
368 if (!Success)
369 {
370 ERR("Failed to read the hive log\n");
371 return FALSE;
372 }
373
374 /* Make sure the dirty vector signature is there otherwise the hive log is corrupt */
375 LogDataPhysical = (PUCHAR)VaToPa(LogData);
376 if (*((PULONG)LogDataPhysical) != HV_LOG_DIRTY_SIGNATURE)
377 {
378 ERR("The hive log dirty signature could not be found\n");
379 return FALSE;
380 }
381
382 /* Copy the dirty data into the primary hive */
383 LogIndex = 0;
384 BlockIndex = 0;
385 HiveBaseBlock = GET_HBASE_BLOCK(ChunkBase);
386 StorageLength = HiveBaseBlock->Length / HBLOCK_SIZE;
387 for (; BlockIndex < StorageLength; ++BlockIndex)
388 {
389 /* Skip this block if it's not dirty and go to the next one */
390 if (LogDataPhysical[BlockIndex + sizeof(HV_LOG_DIRTY_SIGNATURE)] != HV_LOG_DIRTY_BLOCK)
391 {
392 continue;
393 }
394
395 /* Read the dirty block and copy it at right offsets */
396 BlockPtr = (PUCHAR)((ULONG_PTR)LogDataPhysical + 2 * HSECTOR_SIZE + LogIndex * HBLOCK_SIZE);
397 BlockDest = (PUCHAR)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HBLOCK_SIZE);
398 RtlCopyMemory(BlockDest, BlockPtr, HBLOCK_SIZE);
399
400 /* Increment the index in log as we continue further */
401 LogIndex++;
402 }
403
404 /* Fix the secondary sequence of the primary hive and compute a new checksum */
405 HiveBaseBlock->Sequence2 = HiveBaseBlock->Sequence1;
406 HiveBaseBlock->CheckSum = HvpHiveHeaderChecksum(HiveBaseBlock);
407 return TRUE;
408}
#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:170
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 277 of file registry.c.

281{
283 CHAR FullLogFileName[MAX_PATH];
284 PVOID LogData;
285 PHBASE_BLOCK HiveBaseBlock;
286 PHBASE_BLOCK LogBaseBlock;
287
288 /* Build the complete path of the hive log */
289 RtlStringCbCopyA(FullLogFileName, sizeof(FullLogFileName), LogName);
290 RtlStringCbCatA(FullLogFileName, sizeof(FullLogFileName), ".LOG");
291 Success = RegLoadHiveLog(DirectoryPath, 0, FullLogFileName, &LogData);
292 if (!Success)
293 {
294 ERR("Failed to read the hive log\n");
295 return FALSE;
296 }
297
298 /* Make sure the header from the hive log is actually sane */
299 LogData = VaToPa(LogData);
300 LogBaseBlock = GET_HBASE_BLOCK(LogData);
301 if (!HvpVerifyHiveHeader(LogBaseBlock, HFILE_TYPE_LOG))
302 {
303 ERR("The hive log has corrupt base block\n");
304 return FALSE;
305 }
306
307 /* Copy the healthy header base block into the primary hive */
308 HiveBaseBlock = GET_HBASE_BLOCK(ChunkBase);
309 WARN("Recovering the hive base block...\n");
310 RtlCopyMemory(HiveBaseBlock,
311 LogBaseBlock,
312 LogBaseBlock->Cluster * HSECTOR_SIZE);
313 HiveBaseBlock->Type = HFILE_TYPE_PRIMARY;
314 return TRUE;
315}
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 772 of file registry.c.

778{
780 PVOID DataCell;
781
782 /* Does the caller want the type? */
783 if (Type != NULL)
784 *Type = ValueCell->Type;
785
786 /* Does the caller provide DataSize? */
787 if (DataSize != NULL)
788 {
789 // NOTE: CmpValueToData doesn't support big data (the function will
790 // bugcheck if so), FreeLdr is not supposed to read such data.
791 // If big data is needed, use instead CmpGetValueData.
792 // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...);
793 DataCell = CmpValueToData(Hive, ValueCell, &DataLength);
794
795 /* Does the caller want the data? */
796 if ((Data != NULL) && (*DataSize != 0))
797 {
799 DataCell,
801 }
802
803 /* Return the actual data length */
805 }
806}
_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().