2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/regobj.c
5 * PURPOSE: Registry object manipulation routines.
13 #include <internal/debug.h>
18 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive
,
20 PUNICODE_STRING TargetPath
);
22 /* FUNCTONS *****************************************************************/
25 CmiObjectParse(PVOID ParsedObject
,
27 PUNICODE_STRING FullPath
,
31 BLOCK_OFFSET BlockOffset
;
32 PKEY_OBJECT FoundObject
;
33 PKEY_OBJECT ParsedKey
;
38 UNICODE_STRING LinkPath
;
39 UNICODE_STRING TargetPath
;
41 ParsedKey
= ParsedObject
;
43 VERIFY_KEY_OBJECT(ParsedKey
);
49 DPRINT("*Path is NULL\n");
50 return STATUS_UNSUCCESSFUL
;
53 DPRINT("Path '%S'\n", *Path
);
55 if ((*Path
[0]) == '\\')
57 end
= wcschr((*Path
) + 1, '\\');
60 wcstombs(cPath
, (*Path
) + 1, wcslen((*Path
) + 1));
61 cPath
[wcslen((*Path
) + 1)] = 0;
65 end
= wcschr((*Path
), '\\');
68 wcstombs(cPath
, (*Path
), wcslen((*Path
)));
69 cPath
[wcslen((*Path
))] = 0;
72 FoundObject
= CmiScanKeyList(ParsedKey
, cPath
, Attributes
);
73 if (FoundObject
== NULL
)
75 Status
= CmiScanForSubKey(ParsedKey
->RegistryHive
,
82 if (!NT_SUCCESS(Status
) || (SubKeyCell
== NULL
))
88 return(STATUS_UNSUCCESSFUL
);
91 if ((SubKeyCell
->Type
== REG_LINK_KEY_CELL_TYPE
) &&
92 !((Attributes
& OBJ_OPENLINK
) && (end
== NULL
)))
94 RtlInitUnicodeString(&LinkPath
, NULL
);
95 Status
= CmiGetLinkTarget(ParsedKey
->RegistryHive
,
98 if (NT_SUCCESS(Status
))
100 DPRINT("LinkPath '%wZ'\n", &LinkPath
);
102 /* build new FullPath for reparsing */
103 TargetPath
.MaximumLength
= LinkPath
.MaximumLength
;
107 TargetPath
.MaximumLength
+= (wcslen(end
) * sizeof(WCHAR
));
109 TargetPath
.Length
= TargetPath
.MaximumLength
- sizeof(WCHAR
);
110 TargetPath
.Buffer
= ExAllocatePool(NonPagedPool
,
111 TargetPath
.MaximumLength
);
112 wcscpy(TargetPath
.Buffer
, LinkPath
.Buffer
);
115 wcscat(TargetPath
.Buffer
, end
);
118 RtlFreeUnicodeString(FullPath
);
119 RtlFreeUnicodeString(&LinkPath
);
120 FullPath
->Length
= TargetPath
.Length
;
121 FullPath
->MaximumLength
= TargetPath
.MaximumLength
;
122 FullPath
->Buffer
= TargetPath
.Buffer
;
124 DPRINT("FullPath '%wZ'\n", FullPath
);
126 /* reinitialize Path for reparsing */
127 *Path
= FullPath
->Buffer
;
130 return(STATUS_REPARSE
);
134 /* Create new key object and put into linked list */
135 DPRINT("CmiObjectParse %s\n", cPath
);
136 Status
= ObRosCreateObject(NULL
,
137 STANDARD_RIGHTS_REQUIRED
,
140 (PVOID
*)&FoundObject
);
141 if (!NT_SUCCESS(Status
))
146 FoundObject
->Flags
= 0;
147 FoundObject
->Name
= SubKeyCell
->Name
;
148 FoundObject
->NameSize
= SubKeyCell
->NameSize
;
149 FoundObject
->KeyCell
= SubKeyCell
;
150 FoundObject
->BlockOffset
= BlockOffset
;
151 FoundObject
->RegistryHive
= ParsedKey
->RegistryHive
;
152 CmiAddKeyToList(ParsedKey
, FoundObject
);
153 DPRINT("Created object 0x%x\n", FoundObject
);
157 if ((FoundObject
->KeyCell
->Type
== REG_LINK_KEY_CELL_TYPE
) &&
158 !((Attributes
& OBJ_OPENLINK
) && (end
== NULL
)))
160 RtlInitUnicodeString(&LinkPath
, NULL
);
161 Status
= CmiGetLinkTarget(FoundObject
->RegistryHive
,
162 FoundObject
->KeyCell
,
164 if (NT_SUCCESS(Status
))
166 DPRINT("LinkPath '%wZ'\n", &LinkPath
);
168 /* build new FullPath for reparsing */
169 TargetPath
.MaximumLength
= LinkPath
.MaximumLength
;
173 TargetPath
.MaximumLength
+= (wcslen(end
) * sizeof(WCHAR
));
175 TargetPath
.Length
= TargetPath
.MaximumLength
- sizeof(WCHAR
);
176 TargetPath
.Buffer
= ExAllocatePool(NonPagedPool
,
177 TargetPath
.MaximumLength
);
178 wcscpy(TargetPath
.Buffer
, LinkPath
.Buffer
);
181 wcscat(TargetPath
.Buffer
, end
);
184 RtlFreeUnicodeString(FullPath
);
185 RtlFreeUnicodeString(&LinkPath
);
186 FullPath
->Length
= TargetPath
.Length
;
187 FullPath
->MaximumLength
= TargetPath
.MaximumLength
;
188 FullPath
->Buffer
= TargetPath
.Buffer
;
190 DPRINT("FullPath '%wZ'\n", FullPath
);
192 /* reinitialize Path for reparsing */
193 *Path
= FullPath
->Buffer
;
196 return(STATUS_REPARSE
);
200 ObReferenceObjectByPointer(FoundObject
,
201 STANDARD_RIGHTS_REQUIRED
,
206 DPRINT("CmiObjectParse %s\n", FoundObject
->Name
);
218 VERIFY_KEY_OBJECT(FoundObject
);
220 *NextObject
= FoundObject
;
222 return(STATUS_SUCCESS
);
227 CmiObjectCreate(PVOID ObjectBody
,
230 struct _OBJECT_ATTRIBUTES
* ObjectAttributes
)
232 PKEY_OBJECT pKey
= ObjectBody
;
234 pKey
->ParentKey
= Parent
;
237 if(RemainingPath
[0]== L
'\\')
239 pKey
->Name
= (PCHAR
)(&RemainingPath
[1]);
240 pKey
->NameSize
= wcslen(RemainingPath
) - 1;
244 pKey
->Name
= (PCHAR
)RemainingPath
;
245 pKey
->NameSize
= wcslen(RemainingPath
);
253 return STATUS_SUCCESS
;
258 CmiObjectDelete(PVOID DeletedObject
)
260 PKEY_OBJECT KeyObject
;
262 DPRINT("Delete object key\n");
264 KeyObject
= (PKEY_OBJECT
) DeletedObject
;
266 if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject
)))
268 DPRINT1("Key not found in parent list ???\n");
271 if (KeyObject
->Flags
& KO_MARKED_FOR_DELETE
)
273 DPRINT("delete really key\n");
274 CmiDestroyBlock(KeyObject
->RegistryHive
,
276 KeyObject
->BlockOffset
);
280 CmiReleaseBlock(KeyObject
->RegistryHive
, KeyObject
->KeyCell
);
286 CmiAddKeyToList(PKEY_OBJECT ParentKey
,
291 DPRINT("ParentKey %.08x\n", ParentKey
);
293 KeAcquireSpinLock(&CmiKeyListLock
, &OldIrql
);
295 if (ParentKey
->SizeOfSubKeys
<= ParentKey
->NumberOfSubKeys
)
297 PKEY_OBJECT
*tmpSubKeys
= ExAllocatePool(NonPagedPool
,
298 (ParentKey
->NumberOfSubKeys
+ 1) * sizeof(DWORD
));
300 if (ParentKey
->NumberOfSubKeys
> 0)
304 ParentKey
->NumberOfSubKeys
* sizeof(DWORD
));
307 if (ParentKey
->SubKeys
)
308 ExFreePool(ParentKey
->SubKeys
);
310 ParentKey
->SubKeys
= tmpSubKeys
;
311 ParentKey
->SizeOfSubKeys
= ParentKey
->NumberOfSubKeys
+ 1;
314 /* FIXME: Please maintain the list in alphabetic order */
315 /* to allow a dichotomic search */
316 ParentKey
->SubKeys
[ParentKey
->NumberOfSubKeys
++] = NewKey
;
318 DPRINT("Reference parent key: 0x%x\n", ParentKey
);
320 ObReferenceObjectByPointer(ParentKey
,
321 STANDARD_RIGHTS_REQUIRED
,
324 NewKey
->ParentKey
= ParentKey
;
325 KeReleaseSpinLock(&CmiKeyListLock
, OldIrql
);
330 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove
)
332 PKEY_OBJECT ParentKey
;
336 ParentKey
= KeyToRemove
->ParentKey
;
337 KeAcquireSpinLock(&CmiKeyListLock
, &OldIrql
);
338 /* FIXME: If list maintained in alphabetic order, use dichotomic search */
339 for (Index
= 0; Index
< ParentKey
->NumberOfSubKeys
; Index
++)
341 if (ParentKey
->SubKeys
[Index
] == KeyToRemove
)
343 if (Index
< ParentKey
->NumberOfSubKeys
-1)
344 RtlMoveMemory(&ParentKey
->SubKeys
[Index
],
345 &ParentKey
->SubKeys
[Index
+ 1],
346 (ParentKey
->NumberOfSubKeys
- Index
- 1) * sizeof(PKEY_OBJECT
));
347 ParentKey
->NumberOfSubKeys
--;
348 KeReleaseSpinLock(&CmiKeyListLock
, OldIrql
);
350 DPRINT("Dereference parent key: 0x%x\n", ParentKey
);
352 ObDereferenceObject(ParentKey
);
353 return STATUS_SUCCESS
;
356 KeReleaseSpinLock(&CmiKeyListLock
, OldIrql
);
358 return STATUS_UNSUCCESSFUL
;
363 CmiScanKeyList(PKEY_OBJECT Parent
,
372 DPRINT("Scanning key list for %s (Parent %s)\n",
373 KeyName
, Parent
->Name
);
375 NameSize
= strlen(KeyName
);
376 KeAcquireSpinLock(&CmiKeyListLock
, &OldIrql
);
377 /* FIXME: if list maintained in alphabetic order, use dichotomic search */
378 for (Index
=0; Index
< Parent
->NumberOfSubKeys
; Index
++)
380 CurKey
= Parent
->SubKeys
[Index
];
381 if (Attributes
& OBJ_CASE_INSENSITIVE
)
383 if ((NameSize
== CurKey
->NameSize
)
384 && (_strnicmp(KeyName
, CurKey
->Name
, NameSize
) == 0))
386 KeReleaseSpinLock(&CmiKeyListLock
, OldIrql
);
392 if ((NameSize
== CurKey
->NameSize
)
393 && (strncmp(KeyName
,CurKey
->Name
,NameSize
) == 0))
395 KeReleaseSpinLock(&CmiKeyListLock
, OldIrql
);
400 KeReleaseSpinLock(&CmiKeyListLock
, OldIrql
);
407 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive
,
409 PUNICODE_STRING TargetPath
)
411 PVALUE_CELL ValueCell
;
415 /* Get Value block of interest */
416 Status
= CmiScanKeyForValue(RegistryHive
,
421 if (!NT_SUCCESS(Status
))
426 if (ValueCell
->DataType
!= REG_LINK
)
428 DPRINT1("Type != REG_LINK\n!");
429 return(STATUS_UNSUCCESSFUL
);
432 if (TargetPath
->Buffer
== NULL
&& TargetPath
->MaximumLength
== 0)
434 TargetPath
->Length
= 0;
435 TargetPath
->MaximumLength
= ValueCell
->DataSize
+ sizeof(WCHAR
);
436 TargetPath
->Buffer
= ExAllocatePool(NonPagedPool
,
437 TargetPath
->MaximumLength
);
440 TargetPath
->Length
= min(TargetPath
->MaximumLength
- sizeof(WCHAR
),
441 ValueCell
->DataSize
);
443 if (ValueCell
->DataSize
> 0)
445 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
446 RtlCopyMemory(TargetPath
->Buffer
,
449 TargetPath
->Buffer
[TargetPath
->Length
/ sizeof(WCHAR
)] = 0;
450 CmiReleaseBlock(RegistryHive
, DataCell
);
454 RtlCopyMemory(TargetPath
->Buffer
,
455 &ValueCell
->DataOffset
,
457 TargetPath
->Buffer
[TargetPath
->Length
/ sizeof(WCHAR
)] = 0;
460 return(STATUS_SUCCESS
);