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.3 2003/04/17 10:41:02 chorns 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 * - Implement RegQueryMultipleValue().
31 * - Fix RegEnumValue().
45 RegInitializeRegistry(VOID
)
51 RootKey
= (HKEY
)malloc(sizeof(KEY
));
53 InitializeListHead(&RootKey
->SubKeyList
);
54 InitializeListHead(&RootKey
->ValueList
);
55 InitializeListHead(&RootKey
->KeyList
);
57 RootKey
->SubKeyCount
= 0;
58 RootKey
->ValueCount
= 0;
60 RootKey
->NameSize
= 2;
61 RootKey
->Name
= (PUCHAR
)malloc(2);
62 strcpy(RootKey
->Name
, "\\");
64 RootKey
->DataType
= 0;
65 RootKey
->DataSize
= 0;
68 /* Create SYSTEM key */
70 "Registry\\Machine\\SYSTEM",
73 /* Create link 'CurrentControlSet' --> 'ControlSet001' */
75 "Registry\\Machine\\SYSTEM\\ControlSet001",
79 "Registry\\Machine\\SYSTEM\\CurrentControlSet",
85 (PUCHAR
)&ControlSetKey
,
88 /* Create HARDWARE key */
90 "Registry\\Machine\\HARDWARE",
95 "Registry\\Machine\\SAM",
98 /* Create SECURITY key */
100 "Registry\\Machine\\SECURITY",
103 /* Create DEFAULT key */
104 RegCreateKey(RootKey
,
105 "Registry\\User\\.DEFAULT",
111 RegCreateKey(HKEY ParentKey
,
116 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
124 DPRINT ("KeyName '%s'\n", KeyName
);
126 if (*KeyName
== '\\')
129 CurrentKey
= RootKey
;
131 else if (ParentKey
== NULL
)
133 CurrentKey
= RootKey
;
137 CurrentKey
= ParentKey
;
140 /* Check whether current key is a link */
141 if (CurrentKey
->DataType
== REG_LINK
)
143 CurrentKey
= (HKEY
)CurrentKey
->Data
;
146 while (*KeyName
!= 0)
148 DPRINT ("KeyName '%s'\n", KeyName
);
150 if (*KeyName
== '\\')
152 p
= strchr (KeyName
, '\\');
153 if ((p
!= NULL
) && (p
!= KeyName
))
155 subkeyLength
= p
- KeyName
;
156 stringLength
= subkeyLength
+ 1;
161 subkeyLength
= strlen (KeyName
);
162 stringLength
= subkeyLength
;
166 Ptr
= CurrentKey
->SubKeyList
.Flink
;
167 while (Ptr
!= &CurrentKey
->SubKeyList
)
169 DPRINT ("Ptr 0x%x\n", Ptr
);
171 SearchKey
= CONTAINING_RECORD(Ptr
,
174 DPRINT ("SearchKey 0x%x\n", SearchKey
);
175 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
176 if (strncmp (SearchKey
->Name
, name
, subkeyLength
) == 0)
182 if (Ptr
== &CurrentKey
->SubKeyList
)
184 /* no key found -> create new subkey */
185 NewKey
= (HKEY
)malloc (sizeof(KEY
));
187 return ERROR_OUTOFMEMORY
;
189 InitializeListHead (&NewKey
->SubKeyList
);
190 InitializeListHead (&NewKey
->ValueList
);
192 NewKey
->SubKeyCount
= 0;
193 NewKey
->ValueCount
= 0;
195 NewKey
->DataType
= 0;
196 NewKey
->DataSize
= 0;
199 InsertTailList (&CurrentKey
->SubKeyList
, &NewKey
->KeyList
);
200 CurrentKey
->SubKeyCount
++;
202 NewKey
->NameSize
= subkeyLength
+ 1;
203 NewKey
->Name
= (PCHAR
)malloc (NewKey
->NameSize
);
204 if (NewKey
->Name
== NULL
)
205 return(ERROR_OUTOFMEMORY
);
206 memcpy(NewKey
->Name
, name
, subkeyLength
);
207 NewKey
->Name
[subkeyLength
] = 0;
209 DPRINT ("NewKey 0x%x\n", NewKey
);
210 DPRINT ("NewKey '%s' Length %d\n", NewKey
->Name
, NewKey
->NameSize
);
216 CurrentKey
= SearchKey
;
218 /* Check whether current key is a link */
219 if (CurrentKey
->DataType
== REG_LINK
)
221 CurrentKey
= (HKEY
)CurrentKey
->Data
;
225 KeyName
= KeyName
+ stringLength
;
231 return ERROR_SUCCESS
;
236 RegDeleteKey(HKEY Key
,
241 if (strchr(Name
, '\\') != NULL
)
242 return(ERROR_INVALID_PARAMETER
);
246 return(ERROR_SUCCESS
);
261 Ptr
= Key
->SubKeyList
.Flink
;
262 while (Ptr
!= &Key
->SubKeyList
)
271 if (Ptr
== &Key
->SubKeyList
)
272 return(ERROR_NO_MORE_ITEMS
);
274 SearchKey
= CONTAINING_RECORD(Ptr
,
278 DPRINT ("Name '%s' Length %d\n", SearchKey
->Name
, SearchKey
->NameSize
);
280 Size
= min(SearchKey
->NameSize
, *NameSize
);
282 memcpy(Name
, SearchKey
->Name
, Size
);
284 return(ERROR_SUCCESS
);
289 RegOpenKey(HKEY ParentKey
,
294 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
301 DPRINT("KeyName '%s'\n", KeyName
);
305 if (*KeyName
== '\\')
308 CurrentKey
= RootKey
;
310 else if (ParentKey
== NULL
)
312 CurrentKey
= RootKey
;
316 CurrentKey
= ParentKey
;
319 /* Check whether current key is a link */
320 if (CurrentKey
->DataType
== REG_LINK
)
322 CurrentKey
= (HKEY
)CurrentKey
->Data
;
325 while (*KeyName
!= 0)
327 DPRINT ("KeyName '%s'\n", KeyName
);
329 if (*KeyName
== '\\')
331 p
= strchr(KeyName
, '\\');
332 if ((p
!= NULL
) && (p
!= KeyName
))
334 subkeyLength
= p
- KeyName
;
335 stringLength
= subkeyLength
+ 1;
340 subkeyLength
= strlen(KeyName
);
341 stringLength
= subkeyLength
;
345 Ptr
= CurrentKey
->SubKeyList
.Flink
;
346 while (Ptr
!= &CurrentKey
->SubKeyList
)
348 DPRINT ("Ptr 0x%x\n", Ptr
);
350 SearchKey
= CONTAINING_RECORD(Ptr
,
354 DPRINT ("SearchKey 0x%x\n", SearchKey
);
355 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
357 if (strncmp(SearchKey
->Name
, name
, subkeyLength
) == 0)
363 if (Ptr
== &CurrentKey
->SubKeyList
)
365 return(ERROR_PATH_NOT_FOUND
);
369 CurrentKey
= SearchKey
;
371 /* Check whether current key is a link */
372 if (CurrentKey
->DataType
== REG_LINK
)
374 CurrentKey
= (HKEY
)CurrentKey
->Data
;
378 KeyName
= KeyName
+ stringLength
;
384 return(ERROR_SUCCESS
);
389 RegSetValue(HKEY Key
,
398 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
399 (int)Key
, ValueName
, (int)Type
, (int)Data
, (int)DataSize
);
401 if ((ValueName
== NULL
) || (*ValueName
== 0))
403 /* set default value */
404 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
409 if (DataSize
<= sizeof(PUCHAR
))
411 Key
->DataSize
= DataSize
;
412 Key
->DataType
= Type
;
413 memcpy(&Key
->Data
, Data
, DataSize
);
417 Key
->Data
= (PUCHAR
)malloc(DataSize
);
418 Key
->DataSize
= DataSize
;
419 Key
->DataType
= Type
;
420 memcpy(Key
->Data
, Data
, DataSize
);
425 /* set non-default value */
426 Ptr
= Key
->ValueList
.Flink
;
427 while (Ptr
!= &Key
->ValueList
)
429 Value
= CONTAINING_RECORD(Ptr
,
433 DPRINT ("Value->Name '%s'\n", Value
->Name
);
435 if (strcasecmp(Value
->Name
, ValueName
) == 0)
441 if (Ptr
== &Key
->ValueList
)
444 DPRINT("No value found - adding new value\n");
446 Value
= (PVALUE
)malloc(sizeof(VALUE
));
448 return(ERROR_OUTOFMEMORY
);
449 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
451 Value
->NameSize
= strlen(ValueName
)+1;
452 Value
->Name
= (PCHAR
)malloc(Value
->NameSize
);
453 if (Value
->Name
== NULL
)
454 return(ERROR_OUTOFMEMORY
);
455 strcpy(Value
->Name
, ValueName
);
456 Value
->DataType
= REG_NONE
;
462 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
467 if (DataSize
<= sizeof(PUCHAR
))
469 Value
->DataSize
= DataSize
;
470 Value
->DataType
= Type
;
471 memcpy(&Value
->Data
, Data
, DataSize
);
475 Value
->Data
= (PUCHAR
)malloc(DataSize
);
476 if (Value
->Data
== NULL
)
477 return(ERROR_OUTOFMEMORY
);
478 Value
->DataType
= Type
;
479 Value
->DataSize
= DataSize
;
480 memcpy(Value
->Data
, Data
, DataSize
);
483 return(ERROR_SUCCESS
);
488 RegQueryValue(HKEY Key
,
498 if ((ValueName
== NULL
) || (*ValueName
== 0))
500 /* query default value */
501 if (Key
->Data
== NULL
)
502 return(ERROR_INVALID_PARAMETER
);
505 *Type
= Key
->DataType
;
506 if ((Data
!= NULL
) && (DataSize
!= NULL
))
508 if (Key
->DataSize
<= sizeof(PUCHAR
))
510 Size
= min(Key
->DataSize
, *DataSize
);
511 memcpy(Data
, &Key
->Data
, Size
);
516 Size
= min(Key
->DataSize
, *DataSize
);
517 memcpy(Data
, Key
->Data
, Size
);
521 else if ((Data
== NULL
) && (DataSize
!= NULL
))
523 *DataSize
= Key
->DataSize
;
528 /* query non-default value */
529 Ptr
= Key
->ValueList
.Flink
;
530 while (Ptr
!= &Key
->ValueList
)
532 Value
= CONTAINING_RECORD(Ptr
,
536 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName
, Value
->Name
);
538 if (strcasecmp(Value
->Name
, ValueName
) == 0)
544 if (Ptr
== &Key
->ValueList
)
545 return(ERROR_INVALID_PARAMETER
);
548 *Type
= Value
->DataType
;
549 if ((Data
!= NULL
) && (DataSize
!= NULL
))
551 if (Value
->DataSize
<= sizeof(PUCHAR
))
553 Size
= min(Value
->DataSize
, *DataSize
);
554 memcpy(Data
, &Value
->Data
, Size
);
559 Size
= min(Value
->DataSize
, *DataSize
);
560 memcpy(Data
, Value
->Data
, Size
);
564 else if ((Data
== NULL
) && (DataSize
!= NULL
))
566 *DataSize
= Value
->DataSize
;
570 return(ERROR_SUCCESS
);
575 RegDeleteValue(HKEY Key
,
581 if ((ValueName
== NULL
) || (*ValueName
== 0))
583 /* delete default value */
584 if (Key
->Data
!= NULL
)
592 /* delete non-default value */
593 Ptr
= Key
->ValueList
.Flink
;
594 while (Ptr
!= &Key
->ValueList
)
596 Value
= CONTAINING_RECORD(Ptr
,
599 if (strcmp(Value
->Name
, ValueName
) == 0)
605 if (Ptr
== &Key
->ValueList
)
606 return(ERROR_INVALID_PARAMETER
);
610 if (Value
->Name
!= NULL
)
615 if (Value
->DataSize
> sizeof(PUCHAR
))
617 if (Value
->Data
!= NULL
)
624 RemoveEntryList(&Value
->ValueList
);
627 return(ERROR_SUCCESS
);
632 RegEnumValue(HKEY Key
,
644 if (Key
->Data
!= NULL
)
652 /* enumerate default value */
653 if (ValueName
!= NULL
)
656 *Type
= Key
->DataType
;
657 if (DataSize
!= NULL
)
658 *DataSize
= Key
->DataSize
;
660 /* FIXME: return more values */
664 Ptr
= Key
->ValueList
.Flink
;
665 while (Ptr
!= &Key
->ValueList
)
674 if (Ptr
== &Key
->ValueList
)
675 return(ERROR_NO_MORE_ITEMS
);
677 Value
= CONTAINING_RECORD(Ptr
,
681 /* FIXME: return values */
683 return(ERROR_SUCCESS
);
688 RegGetSubKeyCount (HKEY Key
)
690 return Key
->SubKeyCount
;
695 RegGetValueCount (HKEY Key
)
697 if (Key
->DataSize
!= 0)
698 return Key
->ValueCount
+ 1;
700 return Key
->ValueCount
;
707 RegQueryMultipleValue(HKEY Key
,
710 return(ERROR_SUCCESS
);