3 * Copyright (C) 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: registry.c,v 1.4 2003/05/18 12:12:07 ekohl Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS hive maker
22 * FILE: tools/mkhive/registry.c
23 * PURPOSE: Registry code
24 * PROGRAMMER: Eric Kohl
29 * - Implement RegDeleteKey().
30 * - Fix RegEnumValue().
44 RegInitializeRegistry(VOID
)
50 RootKey
= (HKEY
)malloc(sizeof(KEY
));
52 InitializeListHead(&RootKey
->SubKeyList
);
53 InitializeListHead(&RootKey
->ValueList
);
54 InitializeListHead(&RootKey
->KeyList
);
56 RootKey
->SubKeyCount
= 0;
57 RootKey
->ValueCount
= 0;
59 RootKey
->NameSize
= 2;
60 RootKey
->Name
= (PUCHAR
)malloc(2);
61 strcpy(RootKey
->Name
, "\\");
63 RootKey
->DataType
= 0;
64 RootKey
->DataSize
= 0;
67 /* Create SYSTEM key */
69 "Registry\\Machine\\SYSTEM",
72 /* Create link 'CurrentControlSet' --> 'ControlSet001' */
74 "Registry\\Machine\\SYSTEM\\ControlSet001",
78 "Registry\\Machine\\SYSTEM\\CurrentControlSet",
84 (PUCHAR
)&ControlSetKey
,
87 /* Create HARDWARE key */
89 "Registry\\Machine\\HARDWARE",
94 "Registry\\Machine\\SAM",
97 /* Create SECURITY key */
99 "Registry\\Machine\\SECURITY",
102 /* Create DEFAULT key */
103 RegCreateKey(RootKey
,
104 "Registry\\User\\.DEFAULT",
110 RegCreateKey(HKEY ParentKey
,
115 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
123 DPRINT ("KeyName '%s'\n", KeyName
);
125 if (*KeyName
== '\\')
128 CurrentKey
= RootKey
;
130 else if (ParentKey
== NULL
)
132 CurrentKey
= RootKey
;
136 CurrentKey
= ParentKey
;
139 /* Check whether current key is a link */
140 if (CurrentKey
->DataType
== REG_LINK
)
142 CurrentKey
= (HKEY
)CurrentKey
->Data
;
145 while (*KeyName
!= 0)
147 DPRINT ("KeyName '%s'\n", KeyName
);
149 if (*KeyName
== '\\')
151 p
= strchr (KeyName
, '\\');
152 if ((p
!= NULL
) && (p
!= KeyName
))
154 subkeyLength
= p
- KeyName
;
155 stringLength
= subkeyLength
+ 1;
160 subkeyLength
= strlen (KeyName
);
161 stringLength
= subkeyLength
;
165 Ptr
= CurrentKey
->SubKeyList
.Flink
;
166 while (Ptr
!= &CurrentKey
->SubKeyList
)
168 DPRINT ("Ptr 0x%x\n", Ptr
);
170 SearchKey
= CONTAINING_RECORD(Ptr
,
173 DPRINT ("SearchKey 0x%x\n", SearchKey
);
174 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
175 if (strncmp (SearchKey
->Name
, name
, subkeyLength
) == 0)
181 if (Ptr
== &CurrentKey
->SubKeyList
)
183 /* no key found -> create new subkey */
184 NewKey
= (HKEY
)malloc (sizeof(KEY
));
186 return ERROR_OUTOFMEMORY
;
188 InitializeListHead (&NewKey
->SubKeyList
);
189 InitializeListHead (&NewKey
->ValueList
);
191 NewKey
->SubKeyCount
= 0;
192 NewKey
->ValueCount
= 0;
194 NewKey
->DataType
= 0;
195 NewKey
->DataSize
= 0;
198 InsertTailList (&CurrentKey
->SubKeyList
, &NewKey
->KeyList
);
199 CurrentKey
->SubKeyCount
++;
201 NewKey
->NameSize
= subkeyLength
+ 1;
202 NewKey
->Name
= (PCHAR
)malloc (NewKey
->NameSize
);
203 if (NewKey
->Name
== NULL
)
204 return(ERROR_OUTOFMEMORY
);
205 memcpy(NewKey
->Name
, name
, subkeyLength
);
206 NewKey
->Name
[subkeyLength
] = 0;
208 DPRINT ("NewKey 0x%x\n", NewKey
);
209 DPRINT ("NewKey '%s' Length %d\n", NewKey
->Name
, NewKey
->NameSize
);
215 CurrentKey
= SearchKey
;
217 /* Check whether current key is a link */
218 if (CurrentKey
->DataType
== REG_LINK
)
220 CurrentKey
= (HKEY
)CurrentKey
->Data
;
224 KeyName
= KeyName
+ stringLength
;
230 return ERROR_SUCCESS
;
235 RegDeleteKey(HKEY Key
,
240 if (strchr(Name
, '\\') != NULL
)
241 return(ERROR_INVALID_PARAMETER
);
245 return(ERROR_SUCCESS
);
260 Ptr
= Key
->SubKeyList
.Flink
;
261 while (Ptr
!= &Key
->SubKeyList
)
270 if (Ptr
== &Key
->SubKeyList
)
271 return(ERROR_NO_MORE_ITEMS
);
273 SearchKey
= CONTAINING_RECORD(Ptr
,
277 DPRINT ("Name '%s' Length %d\n", SearchKey
->Name
, SearchKey
->NameSize
);
279 Size
= min(SearchKey
->NameSize
, *NameSize
);
281 memcpy(Name
, SearchKey
->Name
, Size
);
283 return(ERROR_SUCCESS
);
288 RegOpenKey(HKEY ParentKey
,
293 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
300 DPRINT("KeyName '%s'\n", KeyName
);
304 if (*KeyName
== '\\')
307 CurrentKey
= RootKey
;
309 else if (ParentKey
== NULL
)
311 CurrentKey
= RootKey
;
315 CurrentKey
= ParentKey
;
318 /* Check whether current key is a link */
319 if (CurrentKey
->DataType
== REG_LINK
)
321 CurrentKey
= (HKEY
)CurrentKey
->Data
;
324 while (*KeyName
!= 0)
326 DPRINT ("KeyName '%s'\n", KeyName
);
328 if (*KeyName
== '\\')
330 p
= strchr(KeyName
, '\\');
331 if ((p
!= NULL
) && (p
!= KeyName
))
333 subkeyLength
= p
- KeyName
;
334 stringLength
= subkeyLength
+ 1;
339 subkeyLength
= strlen(KeyName
);
340 stringLength
= subkeyLength
;
344 Ptr
= CurrentKey
->SubKeyList
.Flink
;
345 while (Ptr
!= &CurrentKey
->SubKeyList
)
347 DPRINT ("Ptr 0x%x\n", Ptr
);
349 SearchKey
= CONTAINING_RECORD(Ptr
,
353 DPRINT ("SearchKey 0x%x\n", SearchKey
);
354 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
356 if (strncmp(SearchKey
->Name
, name
, subkeyLength
) == 0)
362 if (Ptr
== &CurrentKey
->SubKeyList
)
364 return(ERROR_PATH_NOT_FOUND
);
368 CurrentKey
= SearchKey
;
370 /* Check whether current key is a link */
371 if (CurrentKey
->DataType
== REG_LINK
)
373 CurrentKey
= (HKEY
)CurrentKey
->Data
;
377 KeyName
= KeyName
+ stringLength
;
383 return(ERROR_SUCCESS
);
388 RegSetValue(HKEY Key
,
397 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
398 (int)Key
, ValueName
, (int)Type
, (int)Data
, (int)DataSize
);
400 if ((ValueName
== NULL
) || (*ValueName
== 0))
402 /* set default value */
403 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
408 if (DataSize
<= sizeof(PUCHAR
))
410 Key
->DataSize
= DataSize
;
411 Key
->DataType
= Type
;
412 memcpy(&Key
->Data
, Data
, DataSize
);
416 Key
->Data
= (PUCHAR
)malloc(DataSize
);
417 Key
->DataSize
= DataSize
;
418 Key
->DataType
= Type
;
419 memcpy(Key
->Data
, Data
, DataSize
);
424 /* set non-default value */
425 Ptr
= Key
->ValueList
.Flink
;
426 while (Ptr
!= &Key
->ValueList
)
428 Value
= CONTAINING_RECORD(Ptr
,
432 DPRINT ("Value->Name '%s'\n", Value
->Name
);
434 if (strcasecmp(Value
->Name
, ValueName
) == 0)
440 if (Ptr
== &Key
->ValueList
)
443 DPRINT("No value found - adding new value\n");
445 Value
= (PVALUE
)malloc(sizeof(VALUE
));
447 return(ERROR_OUTOFMEMORY
);
448 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
450 Value
->NameSize
= strlen(ValueName
)+1;
451 Value
->Name
= (PCHAR
)malloc(Value
->NameSize
);
452 if (Value
->Name
== NULL
)
453 return(ERROR_OUTOFMEMORY
);
454 strcpy(Value
->Name
, ValueName
);
455 Value
->DataType
= REG_NONE
;
461 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
466 if (DataSize
<= sizeof(PUCHAR
))
468 Value
->DataSize
= DataSize
;
469 Value
->DataType
= Type
;
470 memcpy(&Value
->Data
, Data
, DataSize
);
474 Value
->Data
= (PUCHAR
)malloc(DataSize
);
475 if (Value
->Data
== NULL
)
476 return(ERROR_OUTOFMEMORY
);
477 Value
->DataType
= Type
;
478 Value
->DataSize
= DataSize
;
479 memcpy(Value
->Data
, Data
, DataSize
);
482 return(ERROR_SUCCESS
);
487 RegQueryValue(HKEY Key
,
497 if ((ValueName
== NULL
) || (*ValueName
== 0))
499 /* query default value */
500 if (Key
->Data
== NULL
)
501 return(ERROR_INVALID_PARAMETER
);
504 *Type
= Key
->DataType
;
505 if ((Data
!= NULL
) && (DataSize
!= NULL
))
507 if (Key
->DataSize
<= sizeof(PUCHAR
))
509 Size
= min(Key
->DataSize
, *DataSize
);
510 memcpy(Data
, &Key
->Data
, Size
);
515 Size
= min(Key
->DataSize
, *DataSize
);
516 memcpy(Data
, Key
->Data
, Size
);
520 else if ((Data
== NULL
) && (DataSize
!= NULL
))
522 *DataSize
= Key
->DataSize
;
527 /* query non-default value */
528 Ptr
= Key
->ValueList
.Flink
;
529 while (Ptr
!= &Key
->ValueList
)
531 Value
= CONTAINING_RECORD(Ptr
,
535 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName
, Value
->Name
);
537 if (strcasecmp(Value
->Name
, ValueName
) == 0)
543 if (Ptr
== &Key
->ValueList
)
544 return(ERROR_INVALID_PARAMETER
);
547 *Type
= Value
->DataType
;
548 if ((Data
!= NULL
) && (DataSize
!= NULL
))
550 if (Value
->DataSize
<= sizeof(PUCHAR
))
552 Size
= min(Value
->DataSize
, *DataSize
);
553 memcpy(Data
, &Value
->Data
, Size
);
558 Size
= min(Value
->DataSize
, *DataSize
);
559 memcpy(Data
, Value
->Data
, Size
);
563 else if ((Data
== NULL
) && (DataSize
!= NULL
))
565 *DataSize
= Value
->DataSize
;
569 return(ERROR_SUCCESS
);
574 RegDeleteValue(HKEY Key
,
580 if ((ValueName
== NULL
) || (*ValueName
== 0))
582 /* delete default value */
583 if (Key
->Data
!= NULL
)
591 /* delete non-default value */
592 Ptr
= Key
->ValueList
.Flink
;
593 while (Ptr
!= &Key
->ValueList
)
595 Value
= CONTAINING_RECORD(Ptr
,
598 if (strcmp(Value
->Name
, ValueName
) == 0)
604 if (Ptr
== &Key
->ValueList
)
605 return(ERROR_INVALID_PARAMETER
);
609 if (Value
->Name
!= NULL
)
614 if (Value
->DataSize
> sizeof(PUCHAR
))
616 if (Value
->Data
!= NULL
)
623 RemoveEntryList(&Value
->ValueList
);
626 return(ERROR_SUCCESS
);
631 RegEnumValue(HKEY Key
,
643 if (Key
->Data
!= NULL
)
651 /* enumerate default value */
652 if (ValueName
!= NULL
)
655 *Type
= Key
->DataType
;
656 if (DataSize
!= NULL
)
657 *DataSize
= Key
->DataSize
;
659 /* FIXME: return more values */
663 Ptr
= Key
->ValueList
.Flink
;
664 while (Ptr
!= &Key
->ValueList
)
673 if (Ptr
== &Key
->ValueList
)
674 return(ERROR_NO_MORE_ITEMS
);
676 Value
= CONTAINING_RECORD(Ptr
,
680 /* FIXME: return values */
682 return(ERROR_SUCCESS
);
687 RegGetSubKeyCount (HKEY Key
)
689 return Key
->SubKeyCount
;
694 RegGetValueCount (HKEY Key
)
696 if (Key
->DataSize
!= 0)
697 return Key
->ValueCount
+ 1;
699 return Key
->ValueCount
;