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 DBG_DEFAULT_CHANNEL(REGISTRY
);
26 static FRLDRHKEY RootKey
;
29 RegInitializeRegistry (VOID
)
32 RootKey
= MmHeapAlloc(sizeof(KEY
));
34 InitializeListHead(&RootKey
->SubKeyList
);
35 InitializeListHead(&RootKey
->ValueList
);
36 InitializeListHead(&RootKey
->KeyList
);
38 RootKey
->SubKeyCount
= 0;
39 RootKey
->ValueCount
= 0;
41 RootKey
->NameSize
= 4;
42 RootKey
->Name
= MmHeapAlloc(4);
43 wcscpy (RootKey
->Name
, L
"\\");
45 RootKey
->DataType
= 0;
46 RootKey
->DataSize
= 0;
49 /* Create 'SYSTEM' key */
50 RegCreateKey (RootKey
,
51 L
"Registry\\Machine\\SYSTEM",
57 RegInitCurrentControlSet(BOOLEAN LastKnownGood
)
59 WCHAR ControlSetKeyName
[80];
62 FRLDRHKEY ControlSetKey
;
66 ULONG LastKnownGoodSet
= 0;
70 Error
= RegOpenKey(NULL
,
71 L
"\\Registry\\Machine\\SYSTEM\\Select",
73 if (Error
!= ERROR_SUCCESS
)
75 ERR("RegOpenKey() failed (Error %u)\n", (int)Error
);
79 DataSize
= sizeof(ULONG
);
80 Error
= RegQueryValue(SelectKey
,
85 if (Error
!= ERROR_SUCCESS
)
87 ERR("RegQueryValue('Default') failed (Error %u)\n", (int)Error
);
91 DataSize
= sizeof(ULONG
);
92 Error
= RegQueryValue(SelectKey
,
95 (PUCHAR
)&LastKnownGoodSet
,
97 if (Error
!= ERROR_SUCCESS
)
99 ERR("RegQueryValue('Default') failed (Error %u)\n", (int)Error
);
103 CurrentSet
= (LastKnownGood
== TRUE
) ? LastKnownGoodSet
: DefaultSet
;
104 wcscpy(ControlSetKeyName
, L
"ControlSet");
108 wcscat(ControlSetKeyName
, L
"001");
111 wcscat(ControlSetKeyName
, L
"002");
114 wcscat(ControlSetKeyName
, L
"003");
117 wcscat(ControlSetKeyName
, L
"004");
120 wcscat(ControlSetKeyName
, L
"005");
124 Error
= RegOpenKey(NULL
,
125 L
"\\Registry\\Machine\\SYSTEM",
127 if (Error
!= ERROR_SUCCESS
)
129 ERR("RegOpenKey(SystemKey) failed (Error %lu)\n", Error
);
133 Error
= RegOpenKey(SystemKey
,
136 if (Error
!= ERROR_SUCCESS
)
138 ERR("RegOpenKey(ControlSetKey) failed (Error %lu)\n", Error
);
142 Error
= RegCreateKey(SystemKey
,
143 L
"CurrentControlSet",
145 if (Error
!= ERROR_SUCCESS
)
147 ERR("RegCreateKey(LinkKey) failed (Error %lu)\n", Error
);
151 Error
= RegSetValue(LinkKey
,
154 (PCHAR
)&ControlSetKey
,
156 if (Error
!= ERROR_SUCCESS
)
158 ERR("RegSetValue(LinkKey) failed (Error %lu)\n", Error
);
162 return ERROR_SUCCESS
;
167 RegCreateKey(FRLDRHKEY ParentKey
,
172 FRLDRHKEY SearchKey
= NULL
;
173 FRLDRHKEY CurrentKey
;
182 TRACE("KeyName '%S'\n", KeyName
);
184 if (*KeyName
== L
'\\')
187 CurrentKey
= RootKey
;
189 else if (ParentKey
== NULL
)
191 CurrentKey
= RootKey
;
195 CurrentKey
= ParentKey
;
198 /* Check whether current key is a link */
199 if (CurrentKey
->DataType
== REG_LINK
)
201 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
204 while (*KeyName
!= 0)
206 TRACE("KeyName '%S'\n", KeyName
);
208 if (*KeyName
== L
'\\')
210 p
= wcschr(KeyName
, L
'\\');
211 if ((p
!= NULL
) && (p
!= KeyName
))
213 subkeyLength
= p
- KeyName
;
214 stringLength
= subkeyLength
+ 1;
219 subkeyLength
= wcslen(KeyName
);
220 stringLength
= subkeyLength
;
223 NameSize
= (subkeyLength
+ 1) * sizeof(WCHAR
);
225 Ptr
= CurrentKey
->SubKeyList
.Flink
;
227 while (Ptr
!= &CurrentKey
->SubKeyList
)
229 TRACE("Ptr 0x%x\n", Ptr
);
231 SearchKey
= CONTAINING_RECORD(Ptr
, KEY
, KeyList
);
232 TRACE("SearchKey 0x%x\n", SearchKey
);
233 TRACE("Searching '%S'\n", SearchKey
->Name
);
234 CmpResult
= _wcsnicmp(SearchKey
->Name
, name
, subkeyLength
);
236 if (CmpResult
== 0 && SearchKey
->NameSize
== NameSize
) break;
237 else if (CmpResult
== -1) break;
244 /* no key found -> create new subkey */
245 NewKey
= MmHeapAlloc(sizeof(KEY
));
246 if (NewKey
== NULL
) return ERROR_OUTOFMEMORY
;
248 InitializeListHead(&NewKey
->SubKeyList
);
249 InitializeListHead(&NewKey
->ValueList
);
251 NewKey
->SubKeyCount
= 0;
252 NewKey
->ValueCount
= 0;
254 NewKey
->DataType
= 0;
255 NewKey
->DataSize
= 0;
258 InsertTailList(Ptr
, &NewKey
->KeyList
);
259 CurrentKey
->SubKeyCount
++;
261 NewKey
->NameSize
= NameSize
;
262 NewKey
->Name
= (PWCHAR
)MmHeapAlloc(NewKey
->NameSize
);
263 if (NewKey
->Name
== NULL
) return ERROR_OUTOFMEMORY
;
265 memcpy(NewKey
->Name
, name
, NewKey
->NameSize
- sizeof(WCHAR
));
266 NewKey
->Name
[subkeyLength
] = 0;
268 TRACE("NewKey 0x%x\n", NewKey
);
269 TRACE("NewKey '%S' Length %d\n", NewKey
->Name
, NewKey
->NameSize
);
275 CurrentKey
= SearchKey
;
277 /* Check whether current key is a link */
278 if (CurrentKey
->DataType
== REG_LINK
)
280 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
284 KeyName
= KeyName
+ stringLength
;
287 if (Key
!= NULL
) *Key
= CurrentKey
;
289 return ERROR_SUCCESS
;
294 RegDeleteKey(FRLDRHKEY Key
,
298 if (wcschr(Name
, L
'\\') != NULL
) return ERROR_INVALID_PARAMETER
;
300 return ERROR_SUCCESS
;
305 RegEnumKey(FRLDRHKEY Key
,
315 Ptr
= Key
->SubKeyList
.Flink
;
316 while (Ptr
!= &Key
->SubKeyList
)
318 if (Index
== Count
) break;
324 if (Ptr
== &Key
->SubKeyList
) return ERROR_NO_MORE_ITEMS
;
326 SearchKey
= CONTAINING_RECORD(Ptr
, KEY
, KeyList
);
328 TRACE("Name '%S' Length %d\n", SearchKey
->Name
, SearchKey
->NameSize
);
330 Size
= min(SearchKey
->NameSize
, *NameSize
);
332 memcpy(Name
, SearchKey
->Name
, Size
);
334 return ERROR_SUCCESS
;
339 RegOpenKey(FRLDRHKEY ParentKey
,
344 FRLDRHKEY SearchKey
= NULL
;
345 FRLDRHKEY CurrentKey
;
352 TRACE("KeyName '%S'\n", KeyName
);
356 if (*KeyName
== L
'\\')
359 CurrentKey
= RootKey
;
361 else if (ParentKey
== NULL
)
363 CurrentKey
= RootKey
;
367 CurrentKey
= ParentKey
;
370 /* Check whether current key is a link */
371 if (CurrentKey
->DataType
== REG_LINK
)
373 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
376 while (*KeyName
!= 0)
378 TRACE("KeyName '%S'\n", KeyName
);
380 if (*KeyName
== L
'\\') KeyName
++;
381 p
= wcschr(KeyName
, L
'\\');
382 if ((p
!= NULL
) && (p
!= KeyName
))
384 subkeyLength
= p
- KeyName
;
385 stringLength
= subkeyLength
+ 1;
390 subkeyLength
= wcslen(KeyName
);
391 stringLength
= subkeyLength
;
394 NameSize
= (subkeyLength
+ 1) * sizeof(WCHAR
);
396 Ptr
= CurrentKey
->SubKeyList
.Flink
;
397 while (Ptr
!= &CurrentKey
->SubKeyList
)
399 TRACE("Ptr 0x%x\n", Ptr
);
401 SearchKey
= CONTAINING_RECORD(Ptr
, KEY
, KeyList
);
403 TRACE("SearchKey 0x%x\n", SearchKey
);
404 TRACE("Searching '%S'\n", SearchKey
->Name
);
406 if (SearchKey
->NameSize
== NameSize
&&
407 _wcsnicmp(SearchKey
->Name
, name
, subkeyLength
) == 0) break;
412 if (Ptr
== &CurrentKey
->SubKeyList
)
414 return ERROR_PATH_NOT_FOUND
;
418 CurrentKey
= SearchKey
;
420 /* Check whether current key is a link */
421 if (CurrentKey
->DataType
== REG_LINK
)
423 CurrentKey
= (FRLDRHKEY
)CurrentKey
->Data
;
427 KeyName
= KeyName
+ stringLength
;
433 return ERROR_SUCCESS
;
438 RegSetValue(FRLDRHKEY Key
,
447 TRACE("Key 0x%p, ValueName '%S', Type %ld, Data 0x%p, DataSize %ld\n",
448 Key
, ValueName
, Type
, Data
, DataSize
);
450 if ((ValueName
== NULL
) || (*ValueName
== 0))
452 /* set default value */
453 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
455 MmHeapFree(Key
->Data
);
458 if (DataSize
<= sizeof(PUCHAR
))
460 Key
->DataSize
= DataSize
;
461 Key
->DataType
= Type
;
462 memcpy(&Key
->Data
, Data
, DataSize
);
466 Key
->Data
= MmHeapAlloc(DataSize
);
467 Key
->DataSize
= DataSize
;
468 Key
->DataType
= Type
;
469 memcpy(Key
->Data
, Data
, DataSize
);
474 /* set non-default value */
475 Ptr
= Key
->ValueList
.Flink
;
476 while (Ptr
!= &Key
->ValueList
)
478 Value
= CONTAINING_RECORD(Ptr
, VALUE
, ValueList
);
480 TRACE("Value->Name '%S'\n", Value
->Name
);
482 if (_wcsicmp(Value
->Name
, ValueName
) == 0) break;
487 if (Ptr
== &Key
->ValueList
)
490 TRACE("No value found - adding new value\n");
492 Value
= (PVALUE
)MmHeapAlloc(sizeof(VALUE
));
493 if (Value
== NULL
) return ERROR_OUTOFMEMORY
;
495 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
498 Value
->NameSize
= (wcslen(ValueName
)+1) * sizeof(WCHAR
);
499 Value
->Name
= MmHeapAlloc(Value
->NameSize
);
500 if (Value
->Name
== NULL
) return ERROR_OUTOFMEMORY
;
501 wcscpy(Value
->Name
, ValueName
);
502 Value
->DataType
= REG_NONE
;
508 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
510 MmHeapFree(Value
->Data
);
513 if (DataSize
<= sizeof(PUCHAR
))
515 Value
->DataSize
= DataSize
;
516 Value
->DataType
= Type
;
517 memcpy(&Value
->Data
, Data
, DataSize
);
521 Value
->Data
= MmHeapAlloc(DataSize
);
522 if (Value
->Data
== NULL
) return ERROR_OUTOFMEMORY
;
523 Value
->DataType
= Type
;
524 Value
->DataSize
= DataSize
;
525 memcpy(Value
->Data
, Data
, DataSize
);
528 return(ERROR_SUCCESS
);
533 RegQueryValue(FRLDRHKEY Key
,
543 if ((ValueName
== NULL
) || (*ValueName
== 0))
545 /* query default value */
546 if (Key
->Data
== NULL
) return ERROR_INVALID_PARAMETER
;
549 *Type
= Key
->DataType
;
550 if ((Data
!= NULL
) && (DataSize
!= NULL
))
552 if (Key
->DataSize
<= sizeof(PUCHAR
))
554 Size
= min(Key
->DataSize
, *DataSize
);
555 memcpy(Data
, &Key
->Data
, Size
);
560 Size
= min(Key
->DataSize
, *DataSize
);
561 memcpy(Data
, Key
->Data
, Size
);
565 else if ((Data
== NULL
) && (DataSize
!= NULL
))
567 *DataSize
= Key
->DataSize
;
572 /* query non-default value */
573 Ptr
= Key
->ValueList
.Flink
;
574 while (Ptr
!= &Key
->ValueList
)
576 Value
= CONTAINING_RECORD(Ptr
, VALUE
, ValueList
);
578 TRACE("Searching for '%S'. Value name '%S'\n", ValueName
, Value
->Name
);
580 if (_wcsicmp(Value
->Name
, ValueName
) == 0) break;
585 if (Ptr
== &Key
->ValueList
) return ERROR_INVALID_PARAMETER
;
587 if (Type
!= NULL
) *Type
= Value
->DataType
;
588 if ((Data
!= NULL
) && (DataSize
!= NULL
))
590 if (Value
->DataSize
<= sizeof(PUCHAR
))
592 Size
= min(Value
->DataSize
, *DataSize
);
593 memcpy(Data
, &Value
->Data
, Size
);
598 Size
= min(Value
->DataSize
, *DataSize
);
599 memcpy(Data
, Value
->Data
, Size
);
603 else if ((Data
== NULL
) && (DataSize
!= NULL
))
605 *DataSize
= Value
->DataSize
;
609 return ERROR_SUCCESS
;
614 RegDeleteValue(FRLDRHKEY Key
,
620 if ((ValueName
== NULL
) || (*ValueName
== 0))
622 /* delete default value */
623 if (Key
->Data
!= NULL
) MmFreeMemory(Key
->Data
);
630 /* delete non-default value */
631 Ptr
= Key
->ValueList
.Flink
;
632 while (Ptr
!= &Key
->ValueList
)
634 Value
= CONTAINING_RECORD(Ptr
, VALUE
, ValueList
);
635 if (_wcsicmp(Value
->Name
, ValueName
) == 0) break;
640 if (Ptr
== &Key
->ValueList
) return ERROR_INVALID_PARAMETER
;
644 if (Value
->Name
!= NULL
) MmFreeMemory(Value
->Name
);
648 if (Value
->DataSize
> sizeof(PUCHAR
))
650 if (Value
->Data
!= NULL
) MmFreeMemory(Value
->Data
);
656 RemoveEntryList(&Value
->ValueList
);
659 return ERROR_SUCCESS
;
664 RegEnumValue(FRLDRHKEY Key
,
676 if (Key
->Data
!= NULL
)
684 /* enumerate default value */
685 if (ValueName
!= NULL
) *ValueName
= 0;
686 if (Type
!= NULL
) *Type
= Key
->DataType
;
689 if (Key
->DataSize
<= sizeof(PUCHAR
))
691 memcpy(Data
, &Key
->Data
, min(Key
->DataSize
, *DataSize
));
695 memcpy(Data
, Key
->Data
, min(Key
->DataSize
, *DataSize
));
699 if (DataSize
!= NULL
) *DataSize
= min(Key
->DataSize
, *DataSize
);
701 return ERROR_SUCCESS
;
705 Ptr
= Key
->ValueList
.Flink
;
706 while (Ptr
!= &Key
->ValueList
)
708 if (Index
== Count
) break;
714 if (Ptr
== &Key
->ValueList
) return ERROR_NO_MORE_ITEMS
;
716 Value
= CONTAINING_RECORD(Ptr
, VALUE
, ValueList
);
718 /* enumerate non-default value */
719 if (ValueName
!= NULL
)
721 memcpy(ValueName
, Value
->Name
, min(Value
->NameSize
, *NameSize
));
723 if (Type
!= NULL
) *Type
= Value
->DataType
;
727 if (Value
->DataSize
<= sizeof(PUCHAR
))
729 memcpy(Data
, &Value
->Data
, min(Value
->DataSize
, *DataSize
));
733 memcpy(Data
, Value
->Data
, min(Value
->DataSize
, *DataSize
));
737 if (DataSize
!= NULL
) *DataSize
= min(Value
->DataSize
, *DataSize
);
739 return ERROR_SUCCESS
;
744 RegGetSubKeyCount (FRLDRHKEY Key
)
746 return Key
->SubKeyCount
;
751 RegGetValueCount (FRLDRHKEY Key
)
753 if (Key
->DataSize
!= 0) return Key
->ValueCount
+ 1;
755 return Key
->ValueCount
;