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.7 2003/10/19 09:35: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 SOFTWARE key */
103 RegCreateKey(RootKey
,
104 "Registry\\Machine\\SOFTWARE",
107 /* Create DEFAULT key */
108 RegCreateKey(RootKey
,
109 "Registry\\User\\.DEFAULT",
115 RegCreateKey(HKEY ParentKey
,
120 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
128 DPRINT ("KeyName '%s'\n", KeyName
);
130 if (*KeyName
== '\\')
133 CurrentKey
= RootKey
;
135 else if (ParentKey
== NULL
)
137 CurrentKey
= RootKey
;
141 CurrentKey
= ParentKey
;
144 /* Check whether current key is a link */
145 if (CurrentKey
->DataType
== REG_LINK
)
147 CurrentKey
= (HKEY
)CurrentKey
->Data
;
150 while (*KeyName
!= 0)
152 DPRINT ("KeyName '%s'\n", KeyName
);
154 if (*KeyName
== '\\')
156 p
= strchr (KeyName
, '\\');
157 if ((p
!= NULL
) && (p
!= KeyName
))
159 subkeyLength
= p
- KeyName
;
160 stringLength
= subkeyLength
+ 1;
165 subkeyLength
= strlen (KeyName
);
166 stringLength
= subkeyLength
;
170 Ptr
= CurrentKey
->SubKeyList
.Flink
;
171 while (Ptr
!= &CurrentKey
->SubKeyList
)
173 DPRINT ("Ptr 0x%x\n", Ptr
);
175 SearchKey
= CONTAINING_RECORD(Ptr
,
178 DPRINT ("SearchKey 0x%x\n", SearchKey
);
179 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
180 if (strncasecmp (SearchKey
->Name
, name
, subkeyLength
) == 0)
186 if (Ptr
== &CurrentKey
->SubKeyList
)
188 /* no key found -> create new subkey */
189 NewKey
= (HKEY
)malloc (sizeof(KEY
));
191 return ERROR_OUTOFMEMORY
;
193 InitializeListHead (&NewKey
->SubKeyList
);
194 InitializeListHead (&NewKey
->ValueList
);
196 NewKey
->SubKeyCount
= 0;
197 NewKey
->ValueCount
= 0;
199 NewKey
->DataType
= 0;
200 NewKey
->DataSize
= 0;
203 InsertTailList (&CurrentKey
->SubKeyList
, &NewKey
->KeyList
);
204 CurrentKey
->SubKeyCount
++;
206 NewKey
->NameSize
= subkeyLength
+ 1;
207 NewKey
->Name
= (PCHAR
)malloc (NewKey
->NameSize
);
208 if (NewKey
->Name
== NULL
)
209 return(ERROR_OUTOFMEMORY
);
210 memcpy(NewKey
->Name
, name
, subkeyLength
);
211 NewKey
->Name
[subkeyLength
] = 0;
213 DPRINT ("NewKey 0x%x\n", NewKey
);
214 DPRINT ("NewKey '%s' Length %d\n", NewKey
->Name
, NewKey
->NameSize
);
220 CurrentKey
= SearchKey
;
222 /* Check whether current key is a link */
223 if (CurrentKey
->DataType
== REG_LINK
)
225 CurrentKey
= (HKEY
)CurrentKey
->Data
;
229 KeyName
= KeyName
+ stringLength
;
235 return ERROR_SUCCESS
;
240 RegDeleteKey(HKEY Key
,
244 if (strchr(Name
, '\\') != NULL
)
245 return(ERROR_INVALID_PARAMETER
);
249 return(ERROR_SUCCESS
);
264 Ptr
= Key
->SubKeyList
.Flink
;
265 while (Ptr
!= &Key
->SubKeyList
)
274 if (Ptr
== &Key
->SubKeyList
)
275 return(ERROR_NO_MORE_ITEMS
);
277 SearchKey
= CONTAINING_RECORD(Ptr
,
281 DPRINT ("Name '%s' Length %d\n", SearchKey
->Name
, SearchKey
->NameSize
);
283 Size
= min(SearchKey
->NameSize
, *NameSize
);
285 memcpy(Name
, SearchKey
->Name
, Size
);
287 return(ERROR_SUCCESS
);
292 RegOpenKey(HKEY ParentKey
,
297 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
304 DPRINT("KeyName '%s'\n", KeyName
);
308 if (*KeyName
== '\\')
311 CurrentKey
= RootKey
;
313 else if (ParentKey
== NULL
)
315 CurrentKey
= RootKey
;
319 CurrentKey
= ParentKey
;
322 /* Check whether current key is a link */
323 if (CurrentKey
->DataType
== REG_LINK
)
325 CurrentKey
= (HKEY
)CurrentKey
->Data
;
328 while (*KeyName
!= 0)
330 DPRINT ("KeyName '%s'\n", KeyName
);
332 if (*KeyName
== '\\')
334 p
= strchr(KeyName
, '\\');
335 if ((p
!= NULL
) && (p
!= KeyName
))
337 subkeyLength
= p
- KeyName
;
338 stringLength
= subkeyLength
+ 1;
343 subkeyLength
= strlen(KeyName
);
344 stringLength
= subkeyLength
;
348 Ptr
= CurrentKey
->SubKeyList
.Flink
;
349 while (Ptr
!= &CurrentKey
->SubKeyList
)
351 DPRINT ("Ptr 0x%x\n", Ptr
);
353 SearchKey
= CONTAINING_RECORD(Ptr
,
357 DPRINT ("SearchKey 0x%x\n", SearchKey
);
358 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
360 if (strncasecmp(SearchKey
->Name
, name
, subkeyLength
) == 0)
366 if (Ptr
== &CurrentKey
->SubKeyList
)
368 return(ERROR_PATH_NOT_FOUND
);
372 CurrentKey
= SearchKey
;
374 /* Check whether current key is a link */
375 if (CurrentKey
->DataType
== REG_LINK
)
377 CurrentKey
= (HKEY
)CurrentKey
->Data
;
381 KeyName
= KeyName
+ stringLength
;
387 return(ERROR_SUCCESS
);
392 RegSetValue(HKEY Key
,
401 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
402 (int)Key
, ValueName
, (int)Type
, (int)Data
, (int)DataSize
);
404 if ((ValueName
== NULL
) || (*ValueName
== 0))
406 /* set default value */
407 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
412 if (DataSize
<= sizeof(PUCHAR
))
414 Key
->DataSize
= DataSize
;
415 Key
->DataType
= Type
;
416 memcpy(&Key
->Data
, Data
, DataSize
);
420 Key
->Data
= (PUCHAR
)malloc(DataSize
);
421 Key
->DataSize
= DataSize
;
422 Key
->DataType
= Type
;
423 memcpy(Key
->Data
, Data
, DataSize
);
428 /* set non-default value */
429 Ptr
= Key
->ValueList
.Flink
;
430 while (Ptr
!= &Key
->ValueList
)
432 Value
= CONTAINING_RECORD(Ptr
,
436 DPRINT ("Value->Name '%s'\n", Value
->Name
);
438 if (strcasecmp(Value
->Name
, ValueName
) == 0)
444 if (Ptr
== &Key
->ValueList
)
447 DPRINT("No value found - adding new value\n");
449 Value
= (PVALUE
)malloc(sizeof(VALUE
));
451 return(ERROR_OUTOFMEMORY
);
452 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
454 Value
->NameSize
= strlen(ValueName
)+1;
455 Value
->Name
= (PCHAR
)malloc(Value
->NameSize
);
456 if (Value
->Name
== NULL
)
457 return(ERROR_OUTOFMEMORY
);
458 strcpy(Value
->Name
, ValueName
);
459 Value
->DataType
= REG_NONE
;
465 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
470 if (DataSize
<= sizeof(PUCHAR
))
472 Value
->DataSize
= DataSize
;
473 Value
->DataType
= Type
;
474 memcpy(&Value
->Data
, Data
, DataSize
);
478 Value
->Data
= (PUCHAR
)malloc(DataSize
);
479 if (Value
->Data
== NULL
)
480 return(ERROR_OUTOFMEMORY
);
481 Value
->DataType
= Type
;
482 Value
->DataSize
= DataSize
;
483 memcpy(Value
->Data
, Data
, DataSize
);
486 return(ERROR_SUCCESS
);
491 RegQueryValue(HKEY Key
,
501 if ((ValueName
== NULL
) || (*ValueName
== 0))
503 /* query default value */
504 if (Key
->Data
== NULL
)
505 return(ERROR_INVALID_PARAMETER
);
508 *Type
= Key
->DataType
;
509 if ((Data
!= NULL
) && (DataSize
!= NULL
))
511 if (Key
->DataSize
<= sizeof(PUCHAR
))
513 Size
= min(Key
->DataSize
, *DataSize
);
514 memcpy(Data
, &Key
->Data
, Size
);
519 Size
= min(Key
->DataSize
, *DataSize
);
520 memcpy(Data
, Key
->Data
, Size
);
524 else if ((Data
== NULL
) && (DataSize
!= NULL
))
526 *DataSize
= Key
->DataSize
;
531 /* query non-default value */
532 Ptr
= Key
->ValueList
.Flink
;
533 while (Ptr
!= &Key
->ValueList
)
535 Value
= CONTAINING_RECORD(Ptr
,
539 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName
, Value
->Name
);
541 if (strcasecmp(Value
->Name
, ValueName
) == 0)
547 if (Ptr
== &Key
->ValueList
)
548 return(ERROR_INVALID_PARAMETER
);
551 *Type
= Value
->DataType
;
552 if ((Data
!= NULL
) && (DataSize
!= NULL
))
554 if (Value
->DataSize
<= sizeof(PUCHAR
))
556 Size
= min(Value
->DataSize
, *DataSize
);
557 memcpy(Data
, &Value
->Data
, Size
);
562 Size
= min(Value
->DataSize
, *DataSize
);
563 memcpy(Data
, Value
->Data
, Size
);
567 else if ((Data
== NULL
) && (DataSize
!= NULL
))
569 *DataSize
= Value
->DataSize
;
573 return(ERROR_SUCCESS
);
578 RegDeleteValue(HKEY Key
,
584 if ((ValueName
== NULL
) || (*ValueName
== 0))
586 /* delete default value */
587 if (Key
->Data
!= NULL
)
595 /* delete non-default value */
596 Ptr
= Key
->ValueList
.Flink
;
597 while (Ptr
!= &Key
->ValueList
)
599 Value
= CONTAINING_RECORD(Ptr
,
602 if (strcasecmp(Value
->Name
, ValueName
) == 0)
608 if (Ptr
== &Key
->ValueList
)
609 return(ERROR_INVALID_PARAMETER
);
613 if (Value
->Name
!= NULL
)
618 if (Value
->DataSize
> sizeof(PUCHAR
))
620 if (Value
->Data
!= NULL
)
627 RemoveEntryList(&Value
->ValueList
);
630 return(ERROR_SUCCESS
);
635 RegEnumValue(HKEY Key
,
647 if (Key
->Data
!= NULL
)
655 /* enumerate default value */
656 if (ValueName
!= NULL
)
659 *Type
= Key
->DataType
;
660 if (DataSize
!= NULL
)
661 *DataSize
= Key
->DataSize
;
663 /* FIXME: return more values */
667 Ptr
= Key
->ValueList
.Flink
;
668 while (Ptr
!= &Key
->ValueList
)
677 if (Ptr
== &Key
->ValueList
)
678 return(ERROR_NO_MORE_ITEMS
);
680 Value
= CONTAINING_RECORD(Ptr
,
684 /* FIXME: return values */
686 return(ERROR_SUCCESS
);
691 RegGetSubKeyCount (HKEY Key
)
693 return Key
->SubKeyCount
;
698 RegGetValueCount (HKEY Key
)
700 if (Key
->DataSize
!= 0)
701 return Key
->ValueCount
+ 1;
703 return Key
->ValueCount
;