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.
12 #include <ddk/ntddk.h>
14 #include <internal/ob.h>
17 #include <internal/pool.h>
18 #include <internal/registry.h>
19 #include <ntos/minmax.h>
22 #include <internal/debug.h>
29 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
31 PUNICODE_STRING TargetPath);
33 /* FUNCTONS *****************************************************************/
36 CmiObjectParse(PVOID ParsedObject,
38 PUNICODE_STRING FullPath,
42 BLOCK_OFFSET BlockOffset;
43 PKEY_OBJECT FoundObject;
44 PKEY_OBJECT ParsedKey;
51 UNICODE_STRING LinkPath;
52 UNICODE_STRING TargetPath;
54 ParsedKey = ParsedObject;
56 VERIFY_KEY_OBJECT(ParsedKey);
62 DPRINT("*Path is NULL\n");
63 return STATUS_UNSUCCESSFUL;
66 DPRINT("Path '%S'\n", *Path);
68 /* Extract relevant path name */
70 if (*StartPtr == L'\\')
73 EndPtr = wcschr(StartPtr, L'\\');
75 Length = ((PCHAR)EndPtr - (PCHAR)StartPtr) / sizeof(WCHAR);
77 Length = wcslen(StartPtr);
79 wcstombs(cPath, StartPtr, Length);
83 FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes);
84 if (FoundObject == NULL)
86 Status = CmiScanForSubKey(ParsedKey->RegistryHive,
93 if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
95 return(STATUS_UNSUCCESSFUL);
98 if ((SubKeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
99 !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL) /*(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;
113 TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR));
115 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
116 TargetPath.Buffer = ExAllocatePool(NonPagedPool,
117 TargetPath.MaximumLength);
118 wcscpy(TargetPath.Buffer, LinkPath.Buffer);
121 wcscat(TargetPath.Buffer, EndPtr);
124 RtlFreeUnicodeString(FullPath);
125 RtlFreeUnicodeString(&LinkPath);
126 FullPath->Length = TargetPath.Length;
127 FullPath->MaximumLength = TargetPath.MaximumLength;
128 FullPath->Buffer = TargetPath.Buffer;
130 DPRINT("FullPath '%wZ'\n", FullPath);
132 /* reinitialize Path for reparsing */
133 *Path = FullPath->Buffer;
136 return(STATUS_REPARSE);
140 /* Create new key object and put into linked list */
141 DPRINT("CmiObjectParse: %s\n", cPath);
142 Status = ObCreateObject(NULL,
143 STANDARD_RIGHTS_REQUIRED,
146 (PVOID*)&FoundObject);
147 if (!NT_SUCCESS(Status))
152 FoundObject->Flags = 0;
153 FoundObject->Name = SubKeyCell->Name;
154 FoundObject->NameSize = SubKeyCell->NameSize;
155 FoundObject->KeyCell = SubKeyCell;
156 FoundObject->BlockOffset = BlockOffset;
157 FoundObject->RegistryHive = ParsedKey->RegistryHive;
158 CmiAddKeyToList(ParsedKey, FoundObject);
159 DPRINT("Created object 0x%x\n", FoundObject);
163 if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
164 !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)/*(end == NULL)*/))
166 DPRINT("Found link\n");
168 RtlInitUnicodeString(&LinkPath, NULL);
169 Status = CmiGetLinkTarget(FoundObject->RegistryHive,
170 FoundObject->KeyCell,
172 if (NT_SUCCESS(Status))
174 DPRINT("LinkPath '%wZ'\n", &LinkPath);
176 /* build new FullPath for reparsing */
177 TargetPath.MaximumLength = LinkPath.MaximumLength;
180 TargetPath.MaximumLength += (wcslen(EndPtr) * 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, EndPtr);
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);
216 char buffer[_BUFFER_LEN];
217 memset(buffer, 0, _BUFFER_LEN);
218 strncpy(buffer, FoundObject->Name, min(FoundObject->NameSize, _BUFFER_LEN - 1));
219 DPRINT("CmiObjectParse: %s\n", buffer);
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");
282 CmiRemoveSubKey(KeyObject->RegistryHive,
283 KeyObject->ParentKey,
286 if (IsPermanentHive(KeyObject->RegistryHive))
291 CmiReleaseBlock(KeyObject->RegistryHive, KeyObject->KeyCell);
297 CmiAddKeyToList(PKEY_OBJECT ParentKey,
302 DPRINT("ParentKey %.08x\n", ParentKey);
304 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
306 if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
308 PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
309 (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD));
311 if (ParentKey->NumberOfSubKeys > 0)
315 ParentKey->NumberOfSubKeys * sizeof(DWORD));
318 if (ParentKey->SubKeys)
319 ExFreePool(ParentKey->SubKeys);
321 ParentKey->SubKeys = tmpSubKeys;
322 ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1;
325 /* FIXME: Please maintain the list in alphabetic order */
326 /* to allow a dichotomic search */
327 ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
329 DPRINT("Reference parent key: 0x%x\n", ParentKey);
331 ObReferenceObjectByPointer(ParentKey,
332 STANDARD_RIGHTS_REQUIRED,
335 NewKey->ParentKey = ParentKey;
336 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
341 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
343 PKEY_OBJECT ParentKey;
347 ParentKey = KeyToRemove->ParentKey;
348 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
349 /* FIXME: If list maintained in alphabetic order, use dichotomic search */
350 for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
352 if (ParentKey->SubKeys[Index] == KeyToRemove)
354 if (Index < ParentKey->NumberOfSubKeys-1)
355 RtlMoveMemory(&ParentKey->SubKeys[Index],
356 &ParentKey->SubKeys[Index + 1],
357 (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
358 ParentKey->NumberOfSubKeys--;
359 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
361 DPRINT("Dereference parent key: 0x%x\n", ParentKey);
363 ObDereferenceObject(ParentKey);
364 return STATUS_SUCCESS;
367 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
369 return STATUS_UNSUCCESSFUL;
374 CmiScanKeyList(PKEY_OBJECT Parent,
384 DPRINT("Scanning key list for: %s (Parent: %s)\n",
385 KeyName, Parent->Name);
388 char buffer[_BUFFER_LEN];
389 memset(buffer, 0, _BUFFER_LEN);
390 strncpy(buffer, Parent->Name, min(Parent->NameSize, _BUFFER_LEN - 1));
391 DPRINT("Scanning key list for: %s (Parent: %s)\n", KeyName, buffer);
395 NameSize = strlen(KeyName);
396 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
397 /* FIXME: if list maintained in alphabetic order, use dichotomic search */
398 for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
400 CurKey = Parent->SubKeys[Index];
401 if (Attributes & OBJ_CASE_INSENSITIVE)
403 if ((NameSize == CurKey->NameSize)
404 && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0))
406 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
412 if ((NameSize == CurKey->NameSize)
413 && (strncmp(KeyName,CurKey->Name,NameSize) == 0))
415 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
420 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
427 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
429 PUNICODE_STRING TargetPath)
431 UNICODE_STRING LinkName = UNICODE_STRING_INITIALIZER(L"SymbolicLinkValue");
432 PVALUE_CELL ValueCell;
436 DPRINT("CmiGetLinkTarget() called\n");
438 /* Get Value block of interest */
439 Status = CmiScanKeyForValue(RegistryHive,
444 if (!NT_SUCCESS(Status))
446 DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status);
450 if (ValueCell->DataType != REG_LINK)
452 DPRINT1("Type != REG_LINK\n!");
453 return(STATUS_UNSUCCESSFUL);
456 if (TargetPath->Buffer == NULL && TargetPath->MaximumLength == 0)
458 TargetPath->Length = 0;
459 TargetPath->MaximumLength = ValueCell->DataSize + sizeof(WCHAR);
460 TargetPath->Buffer = ExAllocatePool(NonPagedPool,
461 TargetPath->MaximumLength);
464 TargetPath->Length = min(TargetPath->MaximumLength - sizeof(WCHAR),
465 (ULONG) ValueCell->DataSize);
467 if (ValueCell->DataSize > 0)
469 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
470 RtlCopyMemory(TargetPath->Buffer,
473 TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
474 CmiReleaseBlock(RegistryHive, DataCell);
478 RtlCopyMemory(TargetPath->Buffer,
479 &ValueCell->DataOffset,
481 TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
484 DPRINT("TargetPath '%wZ'\n", TargetPath);
486 return(STATUS_SUCCESS);