ReactOS 0.4.17-dev-966-gf06eace
cmhvlist.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 - Hives file list management
5 * COPYRIGHT: Copyright 2012-2026 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "ntoskrnl.h"
11#define NDEBUG
12#include "debug.h"
13
14/* GLOBALS ********************************************************************/
15
17 RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\hivelist");
18
19/* FUNCTIONS ******************************************************************/
20
21/* Note: the caller is expected to free the HiveName string buffer */
22static
25 _In_ PCMHIVE Hive,
26 _Out_ PUNICODE_STRING HiveName)
27{
28 HCELL_INDEX RootCell, LinkCell;
29 PCELL_DATA RootData, LinkData, ParentData;
30 ULONG ParentNameSize, LinkNameSize;
31 SIZE_T NameSize;
32 PWCHAR p;
33 UNICODE_STRING RegistryName = RTL_CONSTANT_STRING(L"\\REGISTRY\\");
34
35 /* Get the root cell of this hive */
36 RootCell = Hive->Hive.BaseBlock->RootCell;
37 RootData = HvGetCell(&Hive->Hive, RootCell);
38 if (!RootData) return FALSE;
39
40 /* Get the cell index at which this hive is linked to, and its parent */
41 LinkCell = RootData->u.KeyNode.Parent;
42 HvReleaseCell(&Hive->Hive, RootCell);
43
44 /* Sanity check */
45 ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL);
46
47 /* Get the cell data for link and parent */
48 LinkData = HvGetCell(&CmiVolatileHive->Hive, LinkCell);
49 if (!LinkData) return FALSE;
50 ParentData = HvGetCell(&CmiVolatileHive->Hive, LinkData->u.KeyNode.Parent);
51 if (!ParentData) return FALSE;
52
53 /* Get the size of the parent name */
54 if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME)
55 {
56 ParentNameSize = CmpCompressedNameSize(ParentData->u.KeyNode.Name,
57 ParentData->u.KeyNode.NameLength);
58 }
59 else
60 {
61 ParentNameSize = ParentData->u.KeyNode.NameLength;
62 }
63
64 /* Get the size of the link name */
65 if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME)
66 {
67 LinkNameSize = CmpCompressedNameSize(LinkData->u.KeyNode.Name,
68 LinkData->u.KeyNode.NameLength);
69 }
70 else
71 {
72 LinkNameSize = LinkData->u.KeyNode.NameLength;
73 }
74
75 /* No need to account for terminal NULL character since we deal with counted UNICODE strings */
76 NameSize = RegistryName.Length + ParentNameSize + sizeof(WCHAR) + LinkNameSize;
77
78 /* Allocate the memory */
79 HiveName->Buffer = ExAllocatePoolWithTag(PagedPool, NameSize, TAG_CM);
80 if (!HiveName->Buffer)
81 {
82 DPRINT1("CmpGetHiveName: Unable to allocate memory\n");
83 return FALSE;
84 }
85
86 /* Build the string for it */
87 HiveName->Length = HiveName->MaximumLength = (USHORT)NameSize;
88 p = HiveName->Buffer;
89
90 /* Copy the parent name */
91 RtlCopyMemory(p, RegistryName.Buffer, RegistryName.Length);
92 p += RegistryName.Length / sizeof(WCHAR);
93 if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME)
94 {
96 ParentNameSize,
97 ParentData->u.KeyNode.Name,
98 ParentData->u.KeyNode.NameLength);
99 }
100 else
101 {
102 RtlCopyMemory(p, ParentData->u.KeyNode.Name, ParentNameSize);
103 }
104
105 /* Add a path separator between parent and link */
106 p += ParentNameSize / sizeof(WCHAR);
108 ++p;
109
110 /* Now copy the link name */
111 if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME)
112 {
114 LinkNameSize,
115 LinkData->u.KeyNode.Name,
116 LinkData->u.KeyNode.NameLength);
117
118 }
119 else
120 {
121 RtlCopyMemory(p, LinkData->u.KeyNode.Name, LinkNameSize);
122 }
123
124 /* All done */
125 return TRUE;
126}
127
129NTAPI
131 _Inout_ PCMHIVE Hive)
132{
136 UNICODE_STRING HivePath;
140
141 HivePath.Buffer = NULL;
143
144 /* Create or open the hive list key */
148 NULL,
149 NULL);
150 Status = ZwCreateKey(&KeyHandle,
153 0,
154 NULL,
156 NULL);
157 if (!NT_SUCCESS(Status))
158 {
159 DPRINT1("CmpAddToHiveFileList: Failed to create or open the hive list (Status: 0x%08lx)\n", Status);
160 return Status;
161 }
162
163 /* Retrieve the hive path.
164 * NOTE: On Vista+, the hive path is constructed in CmpLinkHiveToMaster().
165 * In ReactOS, its construction is instead deferred to this point, when
166 * the hive is added to the hive file list. */
167 if (!CmpGetHiveName(Hive, &HivePath))
168 {
169 DPRINT1("CmpAddToHiveFileList: Unable to retrieve the hive path\n");
171 goto Quit;
172 }
173
174 /* Get the name of the corresponding file */
175 if (!(Hive->Hive.HiveFlags & HIVE_VOLATILE))
176 {
177 /* Determine the right buffer size and allocate */
178 OBJECT_NAME_INFORMATION DummyNameInfo;
179 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
181 &DummyNameInfo,
182 sizeof(DummyNameInfo),
183 &Length);
185 {
186 DPRINT1("CmpAddToHiveFileList: Hive file name size query failed (Status: 0x%08lx)\n", Status);
187 goto Quit;
188 }
189
191 Length + sizeof(UNICODE_NULL),
192 TAG_CM);
193 if (FileNameInfo == NULL)
194 {
196 goto Quit;
197 }
198
199 /* Try to get the value */
200 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
203 Length,
204 &Length);
205 if (NT_SUCCESS(Status))
206 {
207 /* Null-terminate and add the length of the terminator */
209 FilePath = FileNameInfo->Name.Buffer;
210 FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL;
211 Length += sizeof(UNICODE_NULL);
212 }
213 else
214 {
215 DPRINT1("CmpAddToHiveFileList: Hive file name query failed (Status: 0x%08lx)\n", Status);
216 goto Quit;
217 }
218 }
219 else
220 {
221 /* No name */
222 FilePath = L"";
223 Length = sizeof(UNICODE_NULL);
224 }
225
226 /* Set the entry in the hive list */
227 Status = ZwSetValueKey(KeyHandle,
228 &HivePath,
229 0,
230 REG_SZ,
231 FilePath,
232 Length);
233 if (!NT_SUCCESS(Status))
234 {
235 DPRINT1("CmpAddToHiveFileList: Failed to add an entry in the hive list (Status: 0x%08lx)\n", Status);
236 }
237
238 /* Capture the hive path and reset the local buffer so it doesn't get freed */
239 Hive->HiveRootPath = HivePath;
240 HivePath.Buffer = NULL;
241
242Quit:
243 /* Cleanup and return status */
244 if (HivePath.Buffer)
246 if (FileNameInfo)
248
250 return Status;
251}
252
253VOID
254NTAPI
256 _Inout_ PCMHIVE Hive)
257{
261
262 /* Do nothing if no hive path was captured, e.g. CmpAddToHiveFileList() failed */
263 if (Hive->HiveRootPath.Buffer == NULL)
264 return;
265
266 /* Open the hive list key */
270 NULL,
271 NULL);
272 Status = ZwOpenKey(&KeyHandle,
275 if (!NT_SUCCESS(Status))
276 {
277 DPRINT1("CmpRemoveFromHiveFileList: Failed to open the hive list (Status: 0x%08lx)\n", Status);
278 return;
279 }
280
281 /* Delete the hive path from the list */
282 ZwDeleteValueKey(KeyHandle, &Hive->HiveRootPath);
283
284 /* Free the captured hive path */
285 ExFreePoolWithTag(Hive->HiveRootPath.Buffer, TAG_CM);
286 RtlInitEmptyUnicodeString(&Hive->HiveRootPath, NULL, 0);
287
288 /* Close the key and exit */
290}
291
292/* EOF */
@ ObjectNameInformation
Definition: DriverTester.h:55
PCWSTR FilePath
unsigned char BOOLEAN
Definition: actypes.h:127
#define REG_SZ
Definition: layer.c:22
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define KEY_COMP_NAME
Definition: cmdata.h:35
static UNICODE_STRING HiveListKeyName
Definition: cmhvlist.c:16
static BOOLEAN CmpGetHiveName(_In_ PCMHIVE Hive, _Out_ PUNICODE_STRING HiveName)
Definition: cmhvlist.c:24
NTSTATUS NTAPI CmpAddToHiveFileList(_Inout_ PCMHIVE Hive)
Definition: cmhvlist.c:130
VOID NTAPI CmpRemoveFromHiveFileList(_Inout_ PCMHIVE Hive)
Definition: cmhvlist.c:255
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:476
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:473
#define TAG_CM
Definition: cmlib.h:219
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:16
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define L(x)
Definition: resources.c:13
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
NTSYSAPI NTSTATUS NTAPI ZwDeleteValueKey(__in IN HANDLE Key, __in IN PUNICODE_STRING ValueName)
Status
Definition: gdiplustypes.h:24
GLfloat GLfloat p
Definition: glext.h:8902
#define HIVE_VOLATILE
Definition: hivedata.h:23
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
ULONG HCELL_INDEX
Definition: hivedata.h:105
@ FileNameInfo
Definition: minwinbase.h:306
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KernelMode
Definition: asm.h:38
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1063
#define KEY_SET_VALUE
Definition: nt_native.h:1020
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3406
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
union _CELL_DATA::@5243 u
CM_KEY_NODE KeyNode
Definition: cmdata.h:200
Definition: cmlib.h:323
HHIVE Hive
Definition: cmlib.h:324
HCELL_INDEX Parent
Definition: cmdata.h:96
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
USHORT NameLength
Definition: cmdata.h:114
USHORT Flags
Definition: cmdata.h:93
uint16_t * PWSTR
Definition: typedefs.h:56
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158