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.11 2004/12/30 16:02:12 royce 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().
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 SOFTWARE key */
104 RegCreateKey(RootKey
,
105 "Registry\\Machine\\SOFTWARE",
108 /* Create DEFAULT key */
109 RegCreateKey(RootKey
,
110 "Registry\\User\\.DEFAULT",
116 RegCreateKey(HKEY ParentKey
,
121 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
129 DPRINT ("RegCreateKey('%s')\n", KeyName
);
131 if (*KeyName
== '\\')
134 CurrentKey
= RootKey
;
136 else if (ParentKey
== NULL
)
138 CurrentKey
= RootKey
;
142 CurrentKey
= ParentKey
;
145 /* Check whether current key is a link */
146 if (CurrentKey
->DataType
== REG_LINK
)
148 CurrentKey
= (HKEY
)CurrentKey
->Data
;
151 while (*KeyName
!= 0)
153 DPRINT ("KeyName '%s'\n", KeyName
);
155 if (*KeyName
== '\\')
157 p
= strchr (KeyName
, '\\');
158 if ((p
!= NULL
) && (p
!= KeyName
))
160 subkeyLength
= p
- KeyName
;
161 stringLength
= subkeyLength
+ 1;
166 subkeyLength
= strlen (KeyName
);
167 stringLength
= subkeyLength
;
171 Ptr
= CurrentKey
->SubKeyList
.Flink
;
172 while (Ptr
!= &CurrentKey
->SubKeyList
)
174 DPRINT ("Ptr 0x%p\n", Ptr
);
176 SearchKey
= CONTAINING_RECORD(Ptr
,
179 DPRINT ("SearchKey 0x%p\n", SearchKey
);
180 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
181 if (strncasecmp (SearchKey
->Name
, name
, subkeyLength
) == 0)
187 if (Ptr
== &CurrentKey
->SubKeyList
)
189 /* no key found -> create new subkey */
190 NewKey
= (HKEY
)malloc (sizeof(KEY
));
192 return ERROR_OUTOFMEMORY
;
194 InitializeListHead (&NewKey
->SubKeyList
);
195 InitializeListHead (&NewKey
->ValueList
);
197 NewKey
->SubKeyCount
= 0;
198 NewKey
->ValueCount
= 0;
200 NewKey
->DataType
= 0;
201 NewKey
->DataSize
= 0;
204 InsertTailList (&CurrentKey
->SubKeyList
, &NewKey
->KeyList
);
205 CurrentKey
->SubKeyCount
++;
207 NewKey
->NameSize
= subkeyLength
+ 1;
208 NewKey
->Name
= (PCHAR
)malloc (NewKey
->NameSize
);
209 if (NewKey
->Name
== NULL
)
210 return(ERROR_OUTOFMEMORY
);
211 memcpy(NewKey
->Name
, name
, subkeyLength
);
212 NewKey
->Name
[subkeyLength
] = 0;
214 DPRINT ("NewKey 0x%p\n", NewKey
);
215 DPRINT ("NewKey '%s' Length %ld\n", NewKey
->Name
, NewKey
->NameSize
);
221 CurrentKey
= SearchKey
;
223 /* Check whether current key is a link */
224 if (CurrentKey
->DataType
== REG_LINK
)
226 CurrentKey
= (HKEY
)CurrentKey
->Data
;
230 KeyName
= KeyName
+ stringLength
;
236 return ERROR_SUCCESS
;
241 RegDeleteKey(HKEY Key
,
244 if (Name
!= NULL
&& 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 %ld\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%p\n", Ptr
);
353 SearchKey
= CONTAINING_RECORD(Ptr
,
357 DPRINT ("SearchKey 0x%p\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
;