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.
11 #include <internal/ob.h>
14 #include <internal/pool.h>
15 #include <internal/registry.h>
16 #include <ntos/minmax.h>
19 #include <internal/debug.h>
25 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
27 PUNICODE_STRING TargetPath);
29 /* FUNCTONS *****************************************************************/
32 CmiObjectParse(PVOID ParsedObject,
34 PUNICODE_STRING FullPath,
38 BLOCK_OFFSET BlockOffset;
39 PKEY_OBJECT FoundObject;
40 PKEY_OBJECT ParsedKey;
45 UNICODE_STRING LinkPath;
46 UNICODE_STRING TargetPath;
48 ParsedKey = ParsedObject;
50 VERIFY_KEY_OBJECT(ParsedKey);
56 DPRINT("*Path is NULL\n");
57 return STATUS_UNSUCCESSFUL;
60 DPRINT("Path '%S'\n", *Path);
62 if ((*Path[0]) == '\\')
64 end = wcschr((*Path) + 1, '\\');
67 wcstombs(cPath, (*Path) + 1, wcslen((*Path) + 1));
68 cPath[wcslen((*Path) + 1)] = 0;
72 end = wcschr((*Path), '\\');
75 wcstombs(cPath, (*Path), wcslen((*Path)));
76 cPath[wcslen((*Path))] = 0;
79 FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes);
80 if (FoundObject == NULL)
82 Status = CmiScanForSubKey(ParsedKey->RegistryHive,
89 if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
95 return(STATUS_UNSUCCESSFUL);
98 if ((SubKeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
99 !((Attributes & OBJ_OPENLINK) && (end == NULL)))
101 RtlInitUnicodeString(&LinkPath, NULL);
102 Status = CmiGetLinkTarget(ParsedKey->RegistryHive,
105 if (NT_SUCCESS(Status))
107 DPRINT("LinkPath '%wZ'\n", &LinkPath);
109 /* build new FullPath for reparsing */
110 TargetPath.MaximumLength = LinkPath.MaximumLength;
114 TargetPath.MaximumLength += (wcslen(end) * sizeof(WCHAR));
116 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
117 TargetPath.Buffer = ExAllocatePool(NonPagedPool,
118 TargetPath.MaximumLength);
119 wcscpy(TargetPath.Buffer, LinkPath.Buffer);
122 wcscat(TargetPath.Buffer, end);
125 RtlFreeUnicodeString(FullPath);
126 RtlFreeUnicodeString(&LinkPath);
127 FullPath->Length = TargetPath.Length;
128 FullPath->MaximumLength = TargetPath.MaximumLength;
129 FullPath->Buffer = TargetPath.Buffer;
131 DPRINT("FullPath '%wZ'\n", FullPath);
133 /* reinitialize Path for reparsing */
134 *Path = FullPath->Buffer;
137 return(STATUS_REPARSE);
141 /* Create new key object and put into linked list */
142 DPRINT("CmiObjectParse %s\n", cPath);
143 Status = ObCreateObject(NULL,
144 STANDARD_RIGHTS_REQUIRED,
147 (PVOID*)&FoundObject);
148 if (!NT_SUCCESS(Status))
153 FoundObject->Flags = 0;
154 FoundObject->Name = SubKeyCell->Name;
155 FoundObject->NameSize = SubKeyCell->NameSize;
156 FoundObject->KeyCell = SubKeyCell;
157 FoundObject->BlockOffset = BlockOffset;
158 FoundObject->RegistryHive = ParsedKey->RegistryHive;
159 CmiAddKeyToList(ParsedKey, FoundObject);
160 DPRINT("Created object 0x%x\n", FoundObject);
164 if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
165 !((Attributes & OBJ_OPENLINK) && (end == NULL)))
167 RtlInitUnicodeString(&LinkPath, NULL);
168 Status = CmiGetLinkTarget(FoundObject->RegistryHive,
169 FoundObject->KeyCell,
171 if (NT_SUCCESS(Status))
173 DPRINT("LinkPath '%wZ'\n", &LinkPath);
175 /* build new FullPath for reparsing */
176 TargetPath.MaximumLength = LinkPath.MaximumLength;
180 TargetPath.MaximumLength += (wcslen(end) * sizeof(WCHAR));
182 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
183 TargetPath.Buffer = ExAllocatePool(NonPagedPool,
184 TargetPath.MaximumLength);
185 wcscpy(TargetPath.Buffer, LinkPath.Buffer);
188 wcscat(TargetPath.Buffer, end);
191 RtlFreeUnicodeString(FullPath);
192 RtlFreeUnicodeString(&LinkPath);
193 FullPath->Length = TargetPath.Length;
194 FullPath->MaximumLength = TargetPath.MaximumLength;
195 FullPath->Buffer = TargetPath.Buffer;
197 DPRINT("FullPath '%wZ'\n", FullPath);
199 /* reinitialize Path for reparsing */
200 *Path = FullPath->Buffer;
203 return(STATUS_REPARSE);
207 ObReferenceObjectByPointer(FoundObject,
208 STANDARD_RIGHTS_REQUIRED,
213 DPRINT("CmiObjectParse %s\n", FoundObject->Name);
225 VERIFY_KEY_OBJECT(FoundObject);
227 *NextObject = FoundObject;
229 return(STATUS_SUCCESS);
234 CmiObjectCreate(PVOID ObjectBody,
237 struct _OBJECT_ATTRIBUTES* ObjectAttributes)
239 PKEY_OBJECT pKey = ObjectBody;
241 pKey->ParentKey = Parent;
244 if(RemainingPath[0]== L'\\')
246 pKey->Name = (PCHAR)(&RemainingPath[1]);
247 pKey->NameSize = wcslen(RemainingPath) - 1;
251 pKey->Name = (PCHAR)RemainingPath;
252 pKey->NameSize = wcslen(RemainingPath);
260 return STATUS_SUCCESS;
265 CmiObjectDelete(PVOID DeletedObject)
267 PKEY_OBJECT KeyObject;
269 DPRINT("Delete object key\n");
271 KeyObject = (PKEY_OBJECT) DeletedObject;
273 if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
275 DPRINT1("Key not found in parent list ???\n");
278 if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
280 DPRINT("delete really key\n");
281 CmiDestroyBlock(KeyObject->RegistryHive,
283 KeyObject->BlockOffset);
287 CmiReleaseBlock(KeyObject->RegistryHive, KeyObject->KeyCell);
293 CmiAddKeyToList(PKEY_OBJECT ParentKey,
298 DPRINT("ParentKey %.08x\n", ParentKey);
300 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
302 if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
304 PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
305 (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD));
307 if (ParentKey->NumberOfSubKeys > 0)
311 ParentKey->NumberOfSubKeys * sizeof(DWORD));
314 if (ParentKey->SubKeys)
315 ExFreePool(ParentKey->SubKeys);
317 ParentKey->SubKeys = tmpSubKeys;
318 ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1;
321 /* FIXME: Please maintain the list in alphabetic order */
322 /* to allow a dichotomic search */
323 ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
325 DPRINT("Reference parent key: 0x%x\n", ParentKey);
327 ObReferenceObjectByPointer(ParentKey,
328 STANDARD_RIGHTS_REQUIRED,
331 NewKey->ParentKey = ParentKey;
332 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
337 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
339 PKEY_OBJECT ParentKey;
343 ParentKey = KeyToRemove->ParentKey;
344 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
345 /* FIXME: If list maintained in alphabetic order, use dichotomic search */
346 for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
348 if (ParentKey->SubKeys[Index] == KeyToRemove)
350 if (Index < ParentKey->NumberOfSubKeys-1)
351 RtlMoveMemory(&ParentKey->SubKeys[Index],
352 &ParentKey->SubKeys[Index + 1],
353 (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
354 ParentKey->NumberOfSubKeys--;
355 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
357 DPRINT("Dereference parent key: 0x%x\n", ParentKey);
359 ObDereferenceObject(ParentKey);
360 return STATUS_SUCCESS;
363 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
365 return STATUS_UNSUCCESSFUL;
370 CmiScanKeyList(PKEY_OBJECT Parent,
379 DPRINT("Scanning key list for %s (Parent %s)\n",
380 KeyName, Parent->Name);
382 NameSize = strlen(KeyName);
383 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
384 /* FIXME: if list maintained in alphabetic order, use dichotomic search */
385 for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
387 CurKey = Parent->SubKeys[Index];
388 if (Attributes & OBJ_CASE_INSENSITIVE)
390 if ((NameSize == CurKey->NameSize)
391 && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0))
393 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
399 if ((NameSize == CurKey->NameSize)
400 && (strncmp(KeyName,CurKey->Name,NameSize) == 0))
402 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
407 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
414 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
416 PUNICODE_STRING TargetPath)
418 PVALUE_CELL ValueCell;
422 /* Get Value block of interest */
423 Status = CmiScanKeyForValue(RegistryHive,
428 if (!NT_SUCCESS(Status))
433 if (ValueCell->DataType != REG_LINK)
435 DPRINT1("Type != REG_LINK\n!");
436 return(STATUS_UNSUCCESSFUL);
439 if (TargetPath->Buffer == NULL && TargetPath->MaximumLength == 0)
441 TargetPath->Length = 0;
442 TargetPath->MaximumLength = ValueCell->DataSize + sizeof(WCHAR);
443 TargetPath->Buffer = ExAllocatePool(NonPagedPool,
444 TargetPath->MaximumLength);
447 TargetPath->Length = min(TargetPath->MaximumLength - sizeof(WCHAR),
448 ValueCell->DataSize);
450 if (ValueCell->DataSize > 0)
452 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
453 RtlCopyMemory(TargetPath->Buffer,
456 TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
457 CmiReleaseBlock(RegistryHive, DataCell);
461 RtlCopyMemory(TargetPath->Buffer,
462 &ValueCell->DataOffset,
464 TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
467 return(STATUS_SUCCESS);