Merge freeldr from amd64 branch:
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / binhive.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2001 Rex Jolliff
5 * Copyright (C) 2001 Eric Kohl
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <freeldr.h>
23 #include <cmlib.h>
24 #include <debug.h>
25
26 #define REG_DATA_SIZE_MASK 0x7FFFFFFF
27 #define REG_DATA_IN_OFFSET 0x80000000
28
29 /* FUNCTIONS ****************************************************************/
30
31 static PVOID
32 NTAPI
33 CmpAllocate (SIZE_T Size, BOOLEAN Paged, ULONG Tag)
34 {
35 return MmHeapAlloc(Size);
36 }
37
38
39 static VOID
40 NTAPI
41 CmpFree (PVOID Ptr, IN ULONG Quota)
42 {
43 return MmHeapFree(Ptr);
44 }
45
46 static BOOLEAN
47 RegImportValue (PHHIVE Hive,
48 PCM_KEY_VALUE ValueCell,
49 FRLDRHKEY Key)
50 {
51 PVOID DataCell;
52 PWCHAR wName;
53 LONG Error;
54 ULONG DataLength;
55 ULONG i;
56
57 if (ValueCell->Signature != CM_KEY_VALUE_SIGNATURE)
58 {
59 DPRINTM(DPRINT_REGISTRY, "Invalid key cell!\n");
60 return FALSE;
61 }
62
63 if (ValueCell->Flags & VALUE_COMP_NAME)
64 {
65 wName = MmHeapAlloc ((ValueCell->NameLength + 1)*sizeof(WCHAR));
66 for (i = 0; i < ValueCell->NameLength; i++)
67 {
68 wName[i] = ((PCHAR)ValueCell->Name)[i];
69 }
70 wName[ValueCell->NameLength] = 0;
71 }
72 else
73 {
74 wName = MmHeapAlloc (ValueCell->NameLength + sizeof(WCHAR));
75 memcpy (wName,
76 ValueCell->Name,
77 ValueCell->NameLength);
78 wName[ValueCell->NameLength / sizeof(WCHAR)] = 0;
79 }
80
81 DataLength = ValueCell->DataLength & REG_DATA_SIZE_MASK;
82
83 DPRINTM(DPRINT_REGISTRY, "ValueName: '%S'\n", wName);
84 DPRINTM(DPRINT_REGISTRY, "DataLength: %u\n", DataLength);
85
86 if (DataLength <= sizeof(HCELL_INDEX) && (ValueCell->DataLength & REG_DATA_IN_OFFSET))
87 {
88 Error = RegSetValue(Key,
89 wName,
90 ValueCell->Type,
91 (PCHAR)&ValueCell->Data,
92 DataLength);
93 if (Error != ERROR_SUCCESS)
94 {
95 DPRINTM(DPRINT_REGISTRY, "RegSetValue() failed!\n");
96 MmHeapFree (wName);
97 return FALSE;
98 }
99 }
100 else
101 {
102 DataCell = (PVOID)HvGetCell (Hive, ValueCell->Data);
103 DPRINTM(DPRINT_REGISTRY, "DataCell: %x\n", DataCell);
104
105 Error = RegSetValue (Key,
106 wName,
107 ValueCell->Type,
108 DataCell,
109 DataLength);
110
111 if (Error != ERROR_SUCCESS)
112 {
113 DPRINTM(DPRINT_REGISTRY, "RegSetValue() failed!\n");
114 MmHeapFree (wName);
115 return FALSE;
116 }
117 }
118
119 MmHeapFree (wName);
120
121 return TRUE;
122 }
123
124 static BOOLEAN
125 RegImportSubKey(PHHIVE Hive,
126 PCM_KEY_NODE KeyCell,
127 FRLDRHKEY ParentKey);
128
129 static BOOLEAN
130 RegImportIndexSubKey(PHHIVE Hive,
131 PCM_KEY_INDEX IndexCell,
132 FRLDRHKEY ParentKey)
133 {
134 ULONG i;
135
136 DPRINTM(DPRINT_REGISTRY, "IndexCell: %x\n", IndexCell);
137
138 /* Enumerate and add subkeys */
139 if (IndexCell->Signature == CM_KEY_INDEX_ROOT ||
140 IndexCell->Signature == CM_KEY_INDEX_LEAF)
141 {
142 for (i = 0; i < IndexCell->Count; i++)
143 {
144 PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]);
145 if (!RegImportIndexSubKey(Hive, SubIndexCell, ParentKey))
146 return FALSE;
147 }
148 }
149 else if (IndexCell->Signature == CM_KEY_FAST_LEAF ||
150 IndexCell->Signature == CM_KEY_HASH_LEAF)
151 {
152 PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
153 for (i = 0; i < HashCell->Count; i++)
154 {
155 PCM_KEY_NODE SubKeyCell = HvGetCell(Hive, HashCell->List[i].Cell);
156 if (!RegImportSubKey(Hive, SubKeyCell, ParentKey))
157 return FALSE;
158 }
159 }
160 else
161 {
162 ASSERT(FALSE);
163 }
164
165 return TRUE;
166 }
167
168
169 static BOOLEAN
170 RegImportSubKey(PHHIVE Hive,
171 PCM_KEY_NODE KeyCell,
172 FRLDRHKEY ParentKey)
173 {
174 PCM_KEY_INDEX IndexCell;
175 PVALUE_LIST_CELL ValueListCell;
176 PCM_KEY_VALUE ValueCell = NULL;
177 PWCHAR wName;
178 FRLDRHKEY SubKey;
179 LONG Error;
180 ULONG i;
181
182
183 DPRINTM(DPRINT_REGISTRY, "KeyCell: %x\n", KeyCell);
184 DPRINTM(DPRINT_REGISTRY, "KeyCell->Signature: %x\n", KeyCell->Signature);
185 if (KeyCell->Signature != CM_KEY_NODE_SIGNATURE)
186 {
187 DPRINTM(DPRINT_REGISTRY, "Invalid key cell Signature!\n");
188 return FALSE;
189 }
190
191 if (KeyCell->Flags & KEY_COMP_NAME)
192 {
193 wName = MmHeapAlloc ((KeyCell->NameLength + 1) * sizeof(WCHAR));
194 for (i = 0; i < KeyCell->NameLength; i++)
195 {
196 wName[i] = ((PCHAR)KeyCell->Name)[i];
197 }
198 wName[KeyCell->NameLength] = 0;
199 }
200 else
201 {
202 wName = MmHeapAlloc (KeyCell->NameLength + sizeof(WCHAR));
203 memcpy (wName,
204 KeyCell->Name,
205 KeyCell->NameLength);
206 wName[KeyCell->NameLength/sizeof(WCHAR)] = 0;
207 }
208
209 DPRINTM(DPRINT_REGISTRY, "KeyName: '%S'\n", wName);
210
211 /* Create new sub key */
212 Error = RegCreateKey (ParentKey,
213 wName,
214 &SubKey);
215 MmHeapFree (wName);
216 if (Error != ERROR_SUCCESS)
217 {
218 DPRINTM(DPRINT_REGISTRY, "RegCreateKey() failed!\n");
219 return FALSE;
220 }
221 DPRINTM(DPRINT_REGISTRY, "Subkeys: %u\n", KeyCell->SubKeyCounts);
222 DPRINTM(DPRINT_REGISTRY, "Values: %u\n", KeyCell->ValueList.Count);
223
224 /* Enumerate and add values */
225 if (KeyCell->ValueList.Count > 0)
226 {
227 ValueListCell = (PVALUE_LIST_CELL) HvGetCell (Hive, KeyCell->ValueList.List);
228 DPRINTM(DPRINT_REGISTRY, "ValueListCell: %x\n", ValueListCell);
229
230 for (i = 0; i < KeyCell->ValueList.Count; i++)
231 {
232 DPRINTM(DPRINT_REGISTRY, "ValueOffset[%d]: %x\n", i, ValueListCell->ValueOffset[i]);
233
234 ValueCell = (PCM_KEY_VALUE) HvGetCell (Hive, ValueListCell->ValueOffset[i]);
235
236 DPRINTM(DPRINT_REGISTRY, "ValueCell[%d]: %x\n", i, ValueCell);
237
238 if (!RegImportValue(Hive, ValueCell, SubKey))
239 return FALSE;
240 }
241 }
242
243 /* Enumerate and add subkeys */
244 if (KeyCell->SubKeyCounts[Stable] > 0)
245 {
246 IndexCell = HvGetCell (Hive, KeyCell->SubKeyLists[Stable]);
247
248 if (!RegImportIndexSubKey(Hive, IndexCell, SubKey))
249 return FALSE;
250 }
251
252 return TRUE;
253 }
254
255
256 BOOLEAN
257 RegImportBinaryHive(PCHAR ChunkBase,
258 ULONG ChunkSize)
259 {
260 PCM_KEY_NODE KeyCell;
261 PCM_KEY_FAST_INDEX HashCell;
262 PCM_KEY_NODE SubKeyCell;
263 FRLDRHKEY SystemKey;
264 ULONG i;
265 LONG Error;
266 PCMHIVE CmHive;
267 PHHIVE Hive;
268 NTSTATUS Status;
269
270 DPRINTM(DPRINT_REGISTRY, "RegImportBinaryHive(%x, %u) called\n",ChunkBase,ChunkSize);
271
272 CmHive = CmpAllocate(sizeof(CMHIVE), TRUE, 0);
273 Status = HvInitialize (&CmHive->Hive,
274 HINIT_FLAT,
275 0,
276 0,
277 ChunkBase,
278 CmpAllocate,
279 CmpFree,
280 NULL,
281 NULL,
282 NULL,
283 NULL,
284 1,
285 NULL);
286 if (!NT_SUCCESS(Status))
287 {
288 CmpFree(CmHive, 0);
289 DPRINTM(DPRINT_REGISTRY, "Invalid hive Signature!\n");
290 return FALSE;
291 }
292
293 Hive = &CmHive->Hive;
294 KeyCell = (PCM_KEY_NODE)HvGetCell (Hive, Hive->BaseBlock->RootCell);
295 DPRINTM(DPRINT_REGISTRY, "KeyCell: %x\n", KeyCell);
296 DPRINTM(DPRINT_REGISTRY, "KeyCell->Signature: %x\n", KeyCell->Signature);
297 if (KeyCell->Signature != CM_KEY_NODE_SIGNATURE)
298 {
299 DPRINTM(DPRINT_REGISTRY, "Invalid key cell Signature!\n");
300 return FALSE;
301 }
302
303 DPRINTM(DPRINT_REGISTRY, "Subkeys: %u\n", KeyCell->SubKeyCounts);
304 DPRINTM(DPRINT_REGISTRY, "Values: %u\n", KeyCell->ValueList.Count);
305
306 /* Open 'System' key */
307 Error = RegOpenKey(NULL,
308 L"\\Registry\\Machine\\SYSTEM",
309 &SystemKey);
310 if (Error != ERROR_SUCCESS)
311 {
312 DPRINTM(DPRINT_REGISTRY, "Failed to open 'system' key!\n");
313 return FALSE;
314 }
315
316 /* Enumerate and add subkeys */
317 if (KeyCell->SubKeyCounts[Stable] > 0)
318 {
319 HashCell = (PCM_KEY_FAST_INDEX)HvGetCell (Hive, KeyCell->SubKeyLists[Stable]);
320 DPRINTM(DPRINT_REGISTRY, "HashCell: %x\n", HashCell);
321 DPRINTM(DPRINT_REGISTRY, "SubKeyCounts: %x\n", KeyCell->SubKeyCounts[Stable]);
322
323 for (i = 0; i < KeyCell->SubKeyCounts[Stable]; i++)
324 {
325 DPRINTM(DPRINT_REGISTRY, "Cell[%d]: %x\n", i, HashCell->List[i].Cell);
326
327 SubKeyCell = (PCM_KEY_NODE)HvGetCell (Hive, HashCell->List[i].Cell);
328
329 DPRINTM(DPRINT_REGISTRY, "SubKeyCell[%d]: %x\n", i, SubKeyCell);
330
331 if (!RegImportSubKey(Hive, SubKeyCell, SystemKey))
332 return FALSE;
333 }
334 }
335
336 return TRUE;
337 }
338
339 /* EOF */