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.5 2003/07/27 22:27:36 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
,
239 if (strchr(Name
, '\\') != NULL
)
240 return(ERROR_INVALID_PARAMETER
);
244 return(ERROR_SUCCESS
);
259 Ptr
= Key
->SubKeyList
.Flink
;
260 while (Ptr
!= &Key
->SubKeyList
)
269 if (Ptr
== &Key
->SubKeyList
)
270 return(ERROR_NO_MORE_ITEMS
);
272 SearchKey
= CONTAINING_RECORD(Ptr
,
276 DPRINT ("Name '%s' Length %d\n", SearchKey
->Name
, SearchKey
->NameSize
);
278 Size
= min(SearchKey
->NameSize
, *NameSize
);
280 memcpy(Name
, SearchKey
->Name
, Size
);
282 return(ERROR_SUCCESS
);
287 RegOpenKey(HKEY ParentKey
,
292 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
299 DPRINT("KeyName '%s'\n", KeyName
);
303 if (*KeyName
== '\\')
306 CurrentKey
= RootKey
;
308 else if (ParentKey
== NULL
)
310 CurrentKey
= RootKey
;
314 CurrentKey
= ParentKey
;
317 /* Check whether current key is a link */
318 if (CurrentKey
->DataType
== REG_LINK
)
320 CurrentKey
= (HKEY
)CurrentKey
->Data
;
323 while (*KeyName
!= 0)
325 DPRINT ("KeyName '%s'\n", KeyName
);
327 if (*KeyName
== '\\')
329 p
= strchr(KeyName
, '\\');
330 if ((p
!= NULL
) && (p
!= KeyName
))
332 subkeyLength
= p
- KeyName
;
333 stringLength
= subkeyLength
+ 1;
338 subkeyLength
= strlen(KeyName
);
339 stringLength
= subkeyLength
;
343 Ptr
= CurrentKey
->SubKeyList
.Flink
;
344 while (Ptr
!= &CurrentKey
->SubKeyList
)
346 DPRINT ("Ptr 0x%x\n", Ptr
);
348 SearchKey
= CONTAINING_RECORD(Ptr
,
352 DPRINT ("SearchKey 0x%x\n", SearchKey
);
353 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
355 if (strncmp(SearchKey
->Name
, name
, subkeyLength
) == 0)
361 if (Ptr
== &CurrentKey
->SubKeyList
)
363 return(ERROR_PATH_NOT_FOUND
);
367 CurrentKey
= SearchKey
;
369 /* Check whether current key is a link */
370 if (CurrentKey
->DataType
== REG_LINK
)
372 CurrentKey
= (HKEY
)CurrentKey
->Data
;
376 KeyName
= KeyName
+ stringLength
;
382 return(ERROR_SUCCESS
);
387 RegSetValue(HKEY Key
,
396 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
397 (int)Key
, ValueName
, (int)Type
, (int)Data
, (int)DataSize
);
399 if ((ValueName
== NULL
) || (*ValueName
== 0))
401 /* set default value */
402 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
407 if (DataSize
<= sizeof(PUCHAR
))
409 Key
->DataSize
= DataSize
;
410 Key
->DataType
= Type
;
411 memcpy(&Key
->Data
, Data
, DataSize
);
415 Key
->Data
= (PUCHAR
)malloc(DataSize
);
416 Key
->DataSize
= DataSize
;
417 Key
->DataType
= Type
;
418 memcpy(Key
->Data
, Data
, DataSize
);
423 /* set non-default value */
424 Ptr
= Key
->ValueList
.Flink
;
425 while (Ptr
!= &Key
->ValueList
)
427 Value
= CONTAINING_RECORD(Ptr
,
431 DPRINT ("Value->Name '%s'\n", Value
->Name
);
433 if (strcasecmp(Value
->Name
, ValueName
) == 0)
439 if (Ptr
== &Key
->ValueList
)
442 DPRINT("No value found - adding new value\n");
444 Value
= (PVALUE
)malloc(sizeof(VALUE
));
446 return(ERROR_OUTOFMEMORY
);
447 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
449 Value
->NameSize
= strlen(ValueName
)+1;
450 Value
->Name
= (PCHAR
)malloc(Value
->NameSize
);
451 if (Value
->Name
== NULL
)
452 return(ERROR_OUTOFMEMORY
);
453 strcpy(Value
->Name
, ValueName
);
454 Value
->DataType
= REG_NONE
;
460 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
465 if (DataSize
<= sizeof(PUCHAR
))
467 Value
->DataSize
= DataSize
;
468 Value
->DataType
= Type
;
469 memcpy(&Value
->Data
, Data
, DataSize
);
473 Value
->Data
= (PUCHAR
)malloc(DataSize
);
474 if (Value
->Data
== NULL
)
475 return(ERROR_OUTOFMEMORY
);
476 Value
->DataType
= Type
;
477 Value
->DataSize
= DataSize
;
478 memcpy(Value
->Data
, Data
, DataSize
);
481 return(ERROR_SUCCESS
);
486 RegQueryValue(HKEY Key
,
496 if ((ValueName
== NULL
) || (*ValueName
== 0))
498 /* query default value */
499 if (Key
->Data
== NULL
)
500 return(ERROR_INVALID_PARAMETER
);
503 *Type
= Key
->DataType
;
504 if ((Data
!= NULL
) && (DataSize
!= NULL
))
506 if (Key
->DataSize
<= sizeof(PUCHAR
))
508 Size
= min(Key
->DataSize
, *DataSize
);
509 memcpy(Data
, &Key
->Data
, Size
);
514 Size
= min(Key
->DataSize
, *DataSize
);
515 memcpy(Data
, Key
->Data
, Size
);
519 else if ((Data
== NULL
) && (DataSize
!= NULL
))
521 *DataSize
= Key
->DataSize
;
526 /* query non-default value */
527 Ptr
= Key
->ValueList
.Flink
;
528 while (Ptr
!= &Key
->ValueList
)
530 Value
= CONTAINING_RECORD(Ptr
,
534 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName
, Value
->Name
);
536 if (strcasecmp(Value
->Name
, ValueName
) == 0)
542 if (Ptr
== &Key
->ValueList
)
543 return(ERROR_INVALID_PARAMETER
);
546 *Type
= Value
->DataType
;
547 if ((Data
!= NULL
) && (DataSize
!= NULL
))
549 if (Value
->DataSize
<= sizeof(PUCHAR
))
551 Size
= min(Value
->DataSize
, *DataSize
);
552 memcpy(Data
, &Value
->Data
, Size
);
557 Size
= min(Value
->DataSize
, *DataSize
);
558 memcpy(Data
, Value
->Data
, Size
);
562 else if ((Data
== NULL
) && (DataSize
!= NULL
))
564 *DataSize
= Value
->DataSize
;
568 return(ERROR_SUCCESS
);
573 RegDeleteValue(HKEY Key
,
579 if ((ValueName
== NULL
) || (*ValueName
== 0))
581 /* delete default value */
582 if (Key
->Data
!= NULL
)
590 /* delete non-default value */
591 Ptr
= Key
->ValueList
.Flink
;
592 while (Ptr
!= &Key
->ValueList
)
594 Value
= CONTAINING_RECORD(Ptr
,
597 if (strcmp(Value
->Name
, ValueName
) == 0)
603 if (Ptr
== &Key
->ValueList
)
604 return(ERROR_INVALID_PARAMETER
);
608 if (Value
->Name
!= NULL
)
613 if (Value
->DataSize
> sizeof(PUCHAR
))
615 if (Value
->Data
!= NULL
)
622 RemoveEntryList(&Value
->ValueList
);
625 return(ERROR_SUCCESS
);
630 RegEnumValue(HKEY Key
,
642 if (Key
->Data
!= NULL
)
650 /* enumerate default value */
651 if (ValueName
!= NULL
)
654 *Type
= Key
->DataType
;
655 if (DataSize
!= NULL
)
656 *DataSize
= Key
->DataSize
;
658 /* FIXME: return more values */
662 Ptr
= Key
->ValueList
.Flink
;
663 while (Ptr
!= &Key
->ValueList
)
672 if (Ptr
== &Key
->ValueList
)
673 return(ERROR_NO_MORE_ITEMS
);
675 Value
= CONTAINING_RECORD(Ptr
,
679 /* FIXME: return values */
681 return(ERROR_SUCCESS
);
686 RegGetSubKeyCount (HKEY Key
)
688 return Key
->SubKeyCount
;
693 RegGetValueCount (HKEY Key
)
695 if (Key
->DataSize
!= 0)
696 return Key
->ValueCount
+ 1;
698 return Key
->ValueCount
;