4 * Copyright (C) 2001, 2002 Eric Kohl
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 static FRLDRHKEY RootKey
;
28 RegInitializeRegistry (VOID
)
31 RootKey
= (FRLDRHKEY
) MmHeapAlloc (sizeof(KEY
));
33 InitializeListHead (&RootKey
->SubKeyList
);
34 InitializeListHead (&RootKey
->ValueList
);
35 InitializeListHead (&RootKey
->KeyList
);
37 RootKey
->SubKeyCount
= 0;
38 RootKey
->ValueCount
= 0;
40 RootKey
->NameSize
= 4;
41 RootKey
->Name
= MmHeapAlloc (4);
42 wcscpy (RootKey
->Name
, L
"\\");
44 RootKey
->DataType
= 0;
45 RootKey
->DataSize
= 0;
48 /* Create 'SYSTEM' key */
49 RegCreateKey (RootKey
,
50 L
"Registry\\Machine\\SYSTEM",
56 RegInitCurrentControlSet(BOOLEAN LastKnownGood
)
58 WCHAR ControlSetKeyName
[80];
61 FRLDRHKEY ControlSetKey
;
65 ULONG LastKnownGoodSet
= 0;
69 Error
= RegOpenKey(NULL
,
70 L
"\\Registry\\Machine\\SYSTEM\\Select",
72 if (Error
!= ERROR_SUCCESS
)
74 DPRINTM(DPRINT_REGISTRY
, "RegOpenKey() failed (Error %u)\n", (int)Error
);
78 DataSize
= sizeof(ULONG
);
79 Error
= RegQueryValue(SelectKey
,
84 if (Error
!= ERROR_SUCCESS
)
86 DPRINTM(DPRINT_REGISTRY
, "RegQueryValue('Default') failed (Error %u)\n", (int)Error
);
90 DataSize
= sizeof(ULONG
);
91 Error
= RegQueryValue(SelectKey
,
94 (PUCHAR
)&LastKnownGoodSet
,
96 if (Error
!= ERROR_SUCCESS
)
98 DPRINTM(DPRINT_REGISTRY
, "RegQueryValue('Default') failed (Error %u)\n", (int)Error
);
102 CurrentSet
= (LastKnownGood
== TRUE
) ? LastKnownGoodSet
: DefaultSet
;
103 wcscpy(ControlSetKeyName
, L
"ControlSet");
107 wcscat(ControlSetKeyName
, L
"001");
110 wcscat(ControlSetKeyName
, L
"002");
113 wcscat(ControlSetKeyName
, L
"003");
116 wcscat(ControlSetKeyName
, L
"004");
119 wcscat(ControlSetKeyName
, L
"005");
123 Error
= RegOpenKey(NULL
,
124 L
"\\Registry\\Machine\\SYSTEM",
126 if (Error
!= ERROR_SUCCESS
)
128 DPRINTM(DPRINT_REGISTRY
, "RegOpenKey(SystemKey) failed (Error %u)\n", (int)Error
);
132 Error
= RegOpenKey(SystemKey
,
135 if (Error
!= ERROR_SUCCESS
)
137 DPRINTM(DPRINT_REGISTRY
, "RegOpenKey(ControlSetKey) failed (Error %u)\n", (int)Error
);
141 Error
= RegCreateKey(SystemKey
,
142 L
"CurrentControlSet",
144 if (Error
!= ERROR_SUCCESS
)
146 DPRINTM(DPRINT_REGISTRY
, "RegCreateKey(LinkKey) failed (Error %u)\n", (int)Error
);
150 Error
= RegSetValue(LinkKey
,
153 (PCHAR
)&ControlSetKey
,
155 if (Error
!= ERROR_SUCCESS
)
157 DPRINTM(DPRINT_REGISTRY
, "RegSetValue(LinkKey) failed (Error %u)\n", (int)Error
);
161 return(ERROR_SUCCESS
);
166 RegCreateKey(FRLDRHKEY ParentKey
,
171 FRLDRHKEY SearchKey
= NULL
;
172 FRLDRHKEY CurrentKey
;
181 DPRINTM(DPRINT_REGISTRY
, "KeyName '%S'\n", KeyName
);
183 if (*KeyName
== L
'\\')
186 CurrentKey
= RootKey
;
188 else if (ParentKey
== NULL
)
190 CurrentKey
= RootKey
;
194 CurrentKey
= ParentKey
;
197 /* Check whether current key is a link */
198 if (CurrentKey
->DataType
== REG_LINK
)
200 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
203 while (*KeyName
!= 0)
205 DPRINTM(DPRINT_REGISTRY
, "KeyName '%S'\n", KeyName
);
207 if (*KeyName
== L
'\\')
209 p
= wcschr(KeyName
, L
'\\');
210 if ((p
!= NULL
) && (p
!= KeyName
))
212 subkeyLength
= p
- KeyName
;
213 stringLength
= subkeyLength
+ 1;
218 subkeyLength
= wcslen(KeyName
);
219 stringLength
= subkeyLength
;
222 NameSize
= (subkeyLength
+ 1) * sizeof(WCHAR
);
224 Ptr
= CurrentKey
->SubKeyList
.Flink
;
226 while (Ptr
!= &CurrentKey
->SubKeyList
)
228 DPRINTM(DPRINT_REGISTRY
, "Ptr 0x%x\n", Ptr
);
230 SearchKey
= CONTAINING_RECORD(Ptr
,
233 DPRINTM(DPRINT_REGISTRY
, "SearchKey 0x%x\n", SearchKey
);
234 DPRINTM(DPRINT_REGISTRY
, "Searching '%S'\n", SearchKey
->Name
);
235 CmpResult
= _wcsnicmp(SearchKey
->Name
, name
, subkeyLength
);
236 if (CmpResult
== 0 && SearchKey
->NameSize
== NameSize
)
238 else if (CmpResult
== -1)
246 /* no key found -> create new subkey */
247 NewKey
= (FRLDRHKEY
)MmHeapAlloc(sizeof(KEY
));
249 return(ERROR_OUTOFMEMORY
);
251 InitializeListHead(&NewKey
->SubKeyList
);
252 InitializeListHead(&NewKey
->ValueList
);
254 NewKey
->SubKeyCount
= 0;
255 NewKey
->ValueCount
= 0;
257 NewKey
->DataType
= 0;
258 NewKey
->DataSize
= 0;
261 InsertTailList(Ptr
, &NewKey
->KeyList
);
262 CurrentKey
->SubKeyCount
++;
264 NewKey
->NameSize
= NameSize
;
265 NewKey
->Name
= (PWCHAR
)MmHeapAlloc(NewKey
->NameSize
);
266 if (NewKey
->Name
== NULL
)
267 return(ERROR_OUTOFMEMORY
);
268 memcpy(NewKey
->Name
, name
, NewKey
->NameSize
- sizeof(WCHAR
));
269 NewKey
->Name
[subkeyLength
] = 0;
271 DPRINTM(DPRINT_REGISTRY
, "NewKey 0x%x\n", NewKey
);
272 DPRINTM(DPRINT_REGISTRY
, "NewKey '%S' Length %d\n", NewKey
->Name
, NewKey
->NameSize
);
278 CurrentKey
= SearchKey
;
280 /* Check whether current key is a link */
281 if (CurrentKey
->DataType
== REG_LINK
)
283 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
287 KeyName
= KeyName
+ stringLength
;
293 return(ERROR_SUCCESS
);
298 RegDeleteKey(FRLDRHKEY Key
,
303 if (wcschr(Name
, L
'\\') != NULL
)
304 return(ERROR_INVALID_PARAMETER
);
308 return(ERROR_SUCCESS
);
313 RegEnumKey(FRLDRHKEY Key
,
323 Ptr
= Key
->SubKeyList
.Flink
;
324 while (Ptr
!= &Key
->SubKeyList
)
333 if (Ptr
== &Key
->SubKeyList
)
334 return(ERROR_NO_MORE_ITEMS
);
336 SearchKey
= CONTAINING_RECORD(Ptr
,
340 DPRINTM(DPRINT_REGISTRY
, "Name '%S' Length %d\n", SearchKey
->Name
, SearchKey
->NameSize
);
342 Size
= min(SearchKey
->NameSize
, *NameSize
);
344 memcpy(Name
, SearchKey
->Name
, Size
);
346 return(ERROR_SUCCESS
);
351 RegOpenKey(FRLDRHKEY ParentKey
,
356 FRLDRHKEY SearchKey
= NULL
;
357 FRLDRHKEY CurrentKey
;
364 DPRINTM(DPRINT_REGISTRY
, "KeyName '%S'\n", KeyName
);
368 if (*KeyName
== L
'\\')
371 CurrentKey
= RootKey
;
373 else if (ParentKey
== NULL
)
375 CurrentKey
= RootKey
;
379 CurrentKey
= ParentKey
;
382 /* Check whether current key is a link */
383 if (CurrentKey
->DataType
== REG_LINK
)
385 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
388 while (*KeyName
!= 0)
390 DPRINTM(DPRINT_REGISTRY
, "KeyName '%S'\n", KeyName
);
392 if (*KeyName
== L
'\\')
394 p
= wcschr(KeyName
, L
'\\');
395 if ((p
!= NULL
) && (p
!= KeyName
))
397 subkeyLength
= p
- KeyName
;
398 stringLength
= subkeyLength
+ 1;
403 subkeyLength
= wcslen(KeyName
);
404 stringLength
= subkeyLength
;
407 NameSize
= (subkeyLength
+ 1) * sizeof(WCHAR
);
409 Ptr
= CurrentKey
->SubKeyList
.Flink
;
410 while (Ptr
!= &CurrentKey
->SubKeyList
)
412 DPRINTM(DPRINT_REGISTRY
, "Ptr 0x%x\n", Ptr
);
414 SearchKey
= CONTAINING_RECORD(Ptr
,
418 DPRINTM(DPRINT_REGISTRY
, "SearchKey 0x%x\n", SearchKey
);
419 DPRINTM(DPRINT_REGISTRY
, "Searching '%S'\n", SearchKey
->Name
);
421 if (SearchKey
->NameSize
== NameSize
&&
422 _wcsnicmp(SearchKey
->Name
, name
, subkeyLength
) == 0)
428 if (Ptr
== &CurrentKey
->SubKeyList
)
430 return(ERROR_PATH_NOT_FOUND
);
434 CurrentKey
= SearchKey
;
436 /* Check whether current key is a link */
437 if (CurrentKey
->DataType
== REG_LINK
)
439 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
443 KeyName
= KeyName
+ stringLength
;
449 return(ERROR_SUCCESS
);
454 RegSetValue(FRLDRHKEY Key
,
463 DPRINTM(DPRINT_REGISTRY
, "Key 0x%p, ValueName '%S', Type %ld, Data 0x%p, DataSize %ld\n",
464 Key
, ValueName
, Type
, Data
, DataSize
);
466 if ((ValueName
== NULL
) || (*ValueName
== 0))
468 /* set default value */
469 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
471 MmHeapFree(Key
->Data
);
474 if (DataSize
<= sizeof(PUCHAR
))
476 Key
->DataSize
= DataSize
;
477 Key
->DataType
= Type
;
478 memcpy(&Key
->Data
, Data
, DataSize
);
482 Key
->Data
= MmHeapAlloc(DataSize
);
483 Key
->DataSize
= DataSize
;
484 Key
->DataType
= Type
;
485 memcpy(Key
->Data
, Data
, DataSize
);
490 /* set non-default value */
491 Ptr
= Key
->ValueList
.Flink
;
492 while (Ptr
!= &Key
->ValueList
)
494 Value
= CONTAINING_RECORD(Ptr
,
498 DPRINTM(DPRINT_REGISTRY
, "Value->Name '%S'\n", Value
->Name
);
500 if (_wcsicmp(Value
->Name
, ValueName
) == 0)
506 if (Ptr
== &Key
->ValueList
)
509 DPRINTM(DPRINT_REGISTRY
, "No value found - adding new value\n");
511 Value
= (PVALUE
)MmHeapAlloc(sizeof(VALUE
));
513 return(ERROR_OUTOFMEMORY
);
515 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
518 Value
->NameSize
= (wcslen(ValueName
)+1)*sizeof(WCHAR
);
519 Value
->Name
= (PWCHAR
)MmHeapAlloc(Value
->NameSize
);
520 if (Value
->Name
== NULL
)
521 return(ERROR_OUTOFMEMORY
);
522 wcscpy(Value
->Name
, ValueName
);
523 Value
->DataType
= REG_NONE
;
529 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
531 MmHeapFree(Value
->Data
);
534 if (DataSize
<= sizeof(PUCHAR
))
536 Value
->DataSize
= DataSize
;
537 Value
->DataType
= Type
;
538 memcpy(&Value
->Data
, Data
, DataSize
);
542 Value
->Data
= MmHeapAlloc(DataSize
);
543 if (Value
->Data
== NULL
)
544 return(ERROR_OUTOFMEMORY
);
545 Value
->DataType
= Type
;
546 Value
->DataSize
= DataSize
;
547 memcpy(Value
->Data
, Data
, DataSize
);
550 return(ERROR_SUCCESS
);
555 RegQueryValue(FRLDRHKEY Key
,
565 if ((ValueName
== NULL
) || (*ValueName
== 0))
567 /* query default value */
568 if (Key
->Data
== NULL
)
569 return(ERROR_INVALID_PARAMETER
);
572 *Type
= Key
->DataType
;
573 if ((Data
!= NULL
) && (DataSize
!= NULL
))
575 if (Key
->DataSize
<= sizeof(PUCHAR
))
577 Size
= min(Key
->DataSize
, *DataSize
);
578 memcpy(Data
, &Key
->Data
, Size
);
583 Size
= min(Key
->DataSize
, *DataSize
);
584 memcpy(Data
, Key
->Data
, Size
);
588 else if ((Data
== NULL
) && (DataSize
!= NULL
))
590 *DataSize
= Key
->DataSize
;
595 /* query non-default value */
596 Ptr
= Key
->ValueList
.Flink
;
597 while (Ptr
!= &Key
->ValueList
)
599 Value
= CONTAINING_RECORD(Ptr
,
603 DPRINTM(DPRINT_REGISTRY
, "Searching for '%S'. Value name '%S'\n", ValueName
, Value
->Name
);
605 if (_wcsicmp(Value
->Name
, ValueName
) == 0)
611 if (Ptr
== &Key
->ValueList
)
612 return(ERROR_INVALID_PARAMETER
);
615 *Type
= Value
->DataType
;
616 if ((Data
!= NULL
) && (DataSize
!= NULL
))
618 if (Value
->DataSize
<= sizeof(PUCHAR
))
620 Size
= min(Value
->DataSize
, *DataSize
);
621 memcpy(Data
, &Value
->Data
, Size
);
626 Size
= min(Value
->DataSize
, *DataSize
);
627 memcpy(Data
, Value
->Data
, Size
);
631 else if ((Data
== NULL
) && (DataSize
!= NULL
))
633 *DataSize
= Value
->DataSize
;
637 return(ERROR_SUCCESS
);
642 RegDeleteValue(FRLDRHKEY Key
,
648 if ((ValueName
== NULL
) || (*ValueName
== 0))
650 /* delete default value */
651 if (Key
->Data
!= NULL
)
652 MmFreeMemory(Key
->Data
);
659 /* delete non-default value */
660 Ptr
= Key
->ValueList
.Flink
;
661 while (Ptr
!= &Key
->ValueList
)
663 Value
= CONTAINING_RECORD(Ptr
,
666 if (_wcsicmp(Value
->Name
, ValueName
) == 0)
672 if (Ptr
== &Key
->ValueList
)
673 return(ERROR_INVALID_PARAMETER
);
677 if (Value
->Name
!= NULL
)
678 MmFreeMemory(Value
->Name
);
682 if (Value
->DataSize
> sizeof(PUCHAR
))
684 if (Value
->Data
!= NULL
)
685 MmFreeMemory(Value
->Data
);
691 RemoveEntryList(&Value
->ValueList
);
694 return(ERROR_SUCCESS
);
699 RegEnumValue(FRLDRHKEY Key
,
711 if (Key
->Data
!= NULL
)
719 /* enumerate default value */
720 if (ValueName
!= NULL
)
723 *Type
= Key
->DataType
;
726 if (Key
->DataSize
<= sizeof(PUCHAR
))
728 memcpy(Data
, &Key
->Data
, min(Key
->DataSize
, *DataSize
));
732 memcpy(Data
, Key
->Data
, min(Key
->DataSize
, *DataSize
));
735 if (DataSize
!= NULL
)
736 *DataSize
= min(Key
->DataSize
, *DataSize
);
738 return(ERROR_SUCCESS
);
742 Ptr
= Key
->ValueList
.Flink
;
743 while (Ptr
!= &Key
->ValueList
)
752 if (Ptr
== &Key
->ValueList
)
753 return(ERROR_NO_MORE_ITEMS
);
755 Value
= CONTAINING_RECORD(Ptr
,
759 /* enumerate non-default value */
760 if (ValueName
!= NULL
)
761 memcpy(ValueName
, Value
->Name
, min(Value
->NameSize
, *NameSize
));
763 *Type
= Value
->DataType
;
767 if (Value
->DataSize
<= sizeof(PUCHAR
))
769 memcpy(Data
, &Value
->Data
, min(Value
->DataSize
, *DataSize
));
773 memcpy(Data
, Value
->Data
, min(Value
->DataSize
, *DataSize
));
777 if (DataSize
!= NULL
)
778 *DataSize
= min(Value
->DataSize
, *DataSize
);
780 return(ERROR_SUCCESS
);
785 RegGetSubKeyCount (FRLDRHKEY Key
)
787 return Key
->SubKeyCount
;
792 RegGetValueCount (FRLDRHKEY Key
)
794 if (Key
->DataSize
!= 0)
795 return Key
->ValueCount
+ 1;
797 return Key
->ValueCount
;