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;
47 UNICODE_STRING LinkPath;
48 UNICODE_STRING TargetPath;
50 ParsedKey = ParsedObject;
52 VERIFY_KEY_OBJECT(ParsedKey);
58 DPRINT("*Path is NULL\n");
59 return STATUS_UNSUCCESSFUL;
62 DPRINT("Path '%S'\n", *Path);
64 /* Extract relevant path name */
66 if (*StartPtr == L'\\')
69 EndPtr = wcschr(StartPtr, L'\\');
71 Length = ((PCHAR)EndPtr - (PCHAR)StartPtr) / sizeof(WCHAR);
73 Length = wcslen(StartPtr);
75 wcstombs(cPath, StartPtr, Length);
79 FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes);
80 if (FoundObject == NULL)
82 Status = CmiScanForSubKey(ParsedKey->RegistryHive,
89 if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
91 return(STATUS_UNSUCCESSFUL);
94 if ((SubKeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
95 !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL) /*(end == NULL)*/))
97 RtlInitUnicodeString(&LinkPath, NULL);
98 Status = CmiGetLinkTarget(ParsedKey->RegistryHive,
101 if (NT_SUCCESS(Status))
103 DPRINT("LinkPath '%wZ'\n", &LinkPath);
105 /* build new FullPath for reparsing */
106 TargetPath.MaximumLength = LinkPath.MaximumLength;
109 TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR));
111 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
112 TargetPath.Buffer = ExAllocatePool(NonPagedPool,
113 TargetPath.MaximumLength);
114 wcscpy(TargetPath.Buffer, LinkPath.Buffer);
117 wcscat(TargetPath.Buffer, EndPtr);
120 RtlFreeUnicodeString(FullPath);
121 RtlFreeUnicodeString(&LinkPath);
122 FullPath->Length = TargetPath.Length;
123 FullPath->MaximumLength = TargetPath.MaximumLength;
124 FullPath->Buffer = TargetPath.Buffer;
126 DPRINT("FullPath '%wZ'\n", FullPath);
128 /* reinitialize Path for reparsing */
129 *Path = FullPath->Buffer;
132 return(STATUS_REPARSE);
136 /* Create new key object and put into linked list */
137 DPRINT("CmiObjectParse: %s\n", cPath);
138 Status = ObCreateObject(NULL,
139 STANDARD_RIGHTS_REQUIRED,
142 (PVOID*)&FoundObject);
143 if (!NT_SUCCESS(Status))
148 FoundObject->Flags = 0;
149 FoundObject->Name = SubKeyCell->Name;
150 FoundObject->NameSize = SubKeyCell->NameSize;
151 FoundObject->KeyCell = SubKeyCell;
152 FoundObject->BlockOffset = BlockOffset;
153 FoundObject->RegistryHive = ParsedKey->RegistryHive;
154 CmiAddKeyToList(ParsedKey, FoundObject);
155 DPRINT("Created object 0x%x\n", FoundObject);
159 if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
160 !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)/*(end == NULL)*/))
162 DPRINT("Found link\n");
164 RtlInitUnicodeString(&LinkPath, NULL);
165 Status = CmiGetLinkTarget(FoundObject->RegistryHive,
166 FoundObject->KeyCell,
168 if (NT_SUCCESS(Status))
170 DPRINT("LinkPath '%wZ'\n", &LinkPath);
172 /* build new FullPath for reparsing */
173 TargetPath.MaximumLength = LinkPath.MaximumLength;
176 TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR));
178 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
179 TargetPath.Buffer = ExAllocatePool(NonPagedPool,
180 TargetPath.MaximumLength);
181 wcscpy(TargetPath.Buffer, LinkPath.Buffer);
184 wcscat(TargetPath.Buffer, EndPtr);
187 RtlFreeUnicodeString(FullPath);
188 RtlFreeUnicodeString(&LinkPath);
189 FullPath->Length = TargetPath.Length;
190 FullPath->MaximumLength = TargetPath.MaximumLength;
191 FullPath->Buffer = TargetPath.Buffer;
193 DPRINT("FullPath '%wZ'\n", FullPath);
195 /* reinitialize Path for reparsing */
196 *Path = FullPath->Buffer;
199 return(STATUS_REPARSE);
203 ObReferenceObjectByPointer(FoundObject,
204 STANDARD_RIGHTS_REQUIRED,
209 DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
213 VERIFY_KEY_OBJECT(FoundObject);
215 *NextObject = FoundObject;
217 return(STATUS_SUCCESS);
222 CmiObjectCreate(PVOID ObjectBody,
225 POBJECT_ATTRIBUTES ObjectAttributes)
227 PKEY_OBJECT pKey = ObjectBody;
229 pKey->ParentKey = Parent;
232 if(RemainingPath[0]== L'\\')
234 pKey->Name = (PCHAR)(&RemainingPath[1]);
235 pKey->NameSize = wcslen(RemainingPath) - 1;
239 pKey->Name = (PCHAR)RemainingPath;
240 pKey->NameSize = wcslen(RemainingPath);
248 return STATUS_SUCCESS;
253 CmiObjectDelete(PVOID DeletedObject)
255 PKEY_OBJECT KeyObject;
257 DPRINT("Delete object key\n");
259 KeyObject = (PKEY_OBJECT) DeletedObject;
261 if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
263 DPRINT1("Key not found in parent list ???\n");
266 if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
268 DPRINT("delete really key\n");
270 CmiRemoveSubKey(KeyObject->RegistryHive,
271 KeyObject->ParentKey,
274 if (!IsVolatileHive(KeyObject->RegistryHive))
283 CmiObjectSecurity(PVOID ObjectBody,
284 SECURITY_OPERATION_CODE OperationCode,
285 SECURITY_INFORMATION SecurityInformation,
286 PSECURITY_DESCRIPTOR SecurityDescriptor,
289 DPRINT1("CmiObjectSecurity() called\n");
291 return(STATUS_SUCCESS);
296 CmiAddKeyToList(PKEY_OBJECT ParentKey,
301 DPRINT("ParentKey %.08x\n", ParentKey);
303 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
305 if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
307 PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
308 (ParentKey->NumberOfSubKeys + 1) * sizeof(ULONG));
310 if (ParentKey->NumberOfSubKeys > 0)
312 RtlCopyMemory (tmpSubKeys,
314 ParentKey->NumberOfSubKeys * sizeof(ULONG));
317 if (ParentKey->SubKeys)
318 ExFreePool(ParentKey->SubKeys);
320 ParentKey->SubKeys = tmpSubKeys;
321 ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1;
324 /* FIXME: Please maintain the list in alphabetic order */
325 /* to allow a dichotomic search */
326 ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
328 DPRINT("Reference parent key: 0x%x\n", ParentKey);
330 ObReferenceObjectByPointer(ParentKey,
331 STANDARD_RIGHTS_REQUIRED,
334 NewKey->ParentKey = ParentKey;
335 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
340 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
342 PKEY_OBJECT ParentKey;
346 ParentKey = KeyToRemove->ParentKey;
347 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
348 /* FIXME: If list maintained in alphabetic order, use dichotomic search */
349 for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
351 if (ParentKey->SubKeys[Index] == KeyToRemove)
353 if (Index < ParentKey->NumberOfSubKeys-1)
354 RtlMoveMemory(&ParentKey->SubKeys[Index],
355 &ParentKey->SubKeys[Index + 1],
356 (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
357 ParentKey->NumberOfSubKeys--;
358 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
360 DPRINT("Dereference parent key: 0x%x\n", ParentKey);
362 ObDereferenceObject(ParentKey);
363 return STATUS_SUCCESS;
366 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
368 return STATUS_UNSUCCESSFUL;
373 CmiScanKeyList(PKEY_OBJECT Parent,
382 DPRINT("Scanning key list for: %s (Parent: %s)\n",
383 KeyName, Parent->Name);
385 NameSize = strlen(KeyName);
386 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
387 /* FIXME: if list maintained in alphabetic order, use dichotomic search */
388 for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
390 CurKey = Parent->SubKeys[Index];
391 if (Attributes & OBJ_CASE_INSENSITIVE)
393 if ((NameSize == CurKey->NameSize)
394 && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0))
396 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
402 if ((NameSize == CurKey->NameSize)
403 && (strncmp(KeyName,CurKey->Name,NameSize) == 0))
405 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
410 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
417 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
419 PUNICODE_STRING TargetPath)
421 UNICODE_STRING LinkName = UNICODE_STRING_INITIALIZER(L"SymbolicLinkValue");
422 PVALUE_CELL ValueCell;
426 DPRINT("CmiGetLinkTarget() called\n");
428 /* Get Value block of interest */
429 Status = CmiScanKeyForValue(RegistryHive,
434 if (!NT_SUCCESS(Status))
436 DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status);
440 if (ValueCell->DataType != REG_LINK)
442 DPRINT1("Type != REG_LINK\n!");
443 return(STATUS_UNSUCCESSFUL);
446 if (TargetPath->Buffer == NULL && TargetPath->MaximumLength == 0)
448 TargetPath->Length = 0;
449 TargetPath->MaximumLength = ValueCell->DataSize + sizeof(WCHAR);
450 TargetPath->Buffer = ExAllocatePool(NonPagedPool,
451 TargetPath->MaximumLength);
454 TargetPath->Length = min(TargetPath->MaximumLength - sizeof(WCHAR),
455 (ULONG) ValueCell->DataSize);
457 if (ValueCell->DataSize > 0)
459 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
460 RtlCopyMemory(TargetPath->Buffer,
463 TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
467 RtlCopyMemory(TargetPath->Buffer,
468 &ValueCell->DataOffset,
470 TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
473 DPRINT("TargetPath '%wZ'\n", TargetPath);
475 return(STATUS_SUCCESS);