2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmapi.c
5 * PURPOSE: Configuration Manager - Internal Registry APIs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
20 NtDeleteKey(IN HANDLE KeyHandle
)
22 PKEY_OBJECT KeyObject
;
24 REG_DELETE_KEY_INFORMATION DeleteKeyInfo
;
25 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
28 DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle
);
30 /* Verify that the handle is valid and is a registry key */
31 Status
= ObReferenceObjectByHandle(KeyHandle
,
37 if (!NT_SUCCESS(Status
))
39 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
43 /* Setup the callback */
44 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
45 DeleteKeyInfo
.Object
= (PVOID
)KeyObject
;
46 Status
= CmiCallRegisteredCallbacks(RegNtPreDeleteKey
, &DeleteKeyInfo
);
47 if (NT_SUCCESS(Status
))
49 /* Call the internal API */
50 Status
= CmDeleteKey(KeyObject
->KeyControlBlock
);
52 /* Remove the keep-alive reference */
53 ObDereferenceObject(KeyObject
);
54 if (KeyObject
->KeyControlBlock
->KeyHive
!=
55 KeyObject
->KeyControlBlock
->ParentKcb
->KeyHive
)
57 /* Dereference again */
58 ObDereferenceObject(KeyObject
);
61 /* Do post callback */
62 PostOperationInfo
.Status
= Status
;
63 CmiCallRegisteredCallbacks(RegNtPostDeleteKey
, &PostOperationInfo
);
66 /* Dereference the object */
67 ObDereferenceObject(KeyObject
);
73 NtEnumerateKey(IN HANDLE KeyHandle
,
75 IN KEY_INFORMATION_CLASS KeyInformationClass
,
76 OUT PVOID KeyInformation
,
78 OUT PULONG ResultLength
)
81 PKEY_OBJECT KeyObject
;
82 REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo
;
83 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
86 DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
87 KeyHandle
, Index
, KeyInformationClass
, Length
);
89 /* Verify that the handle is valid and is a registry key */
90 Status
= ObReferenceObjectByHandle(KeyHandle
,
91 KEY_ENUMERATE_SUB_KEYS
,
96 if (!NT_SUCCESS(Status
))
98 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
102 /* Setup the callback */
103 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
104 EnumerateKeyInfo
.Object
= (PVOID
)KeyObject
;
105 EnumerateKeyInfo
.Index
= Index
;
106 EnumerateKeyInfo
.KeyInformationClass
= KeyInformationClass
;
107 EnumerateKeyInfo
.Length
= Length
;
108 EnumerateKeyInfo
.ResultLength
= ResultLength
;
110 /* Do the callback */
111 Status
= CmiCallRegisteredCallbacks(RegNtPreEnumerateKey
, &EnumerateKeyInfo
);
112 if (NT_SUCCESS(Status
))
114 /* Call the internal API */
115 Status
= CmEnumerateKey(KeyObject
->KeyControlBlock
,
122 /* Do the post callback */
123 PostOperationInfo
.Status
= Status
;
124 CmiCallRegisteredCallbacks(RegNtPostEnumerateKey
, &PostOperationInfo
);
127 /* Dereference and return status */
128 ObDereferenceObject(KeyObject
);
134 NtEnumerateValueKey(IN HANDLE KeyHandle
,
136 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
137 OUT PVOID KeyValueInformation
,
139 OUT PULONG ResultLength
)
142 PKEY_OBJECT KeyObject
;
143 REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo
;
144 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
147 DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
148 KeyHandle
, Index
, KeyValueInformationClass
, Length
);
150 /* Verify that the handle is valid and is a registry key */
151 Status
= ObReferenceObjectByHandle(KeyHandle
,
157 if (!NT_SUCCESS(Status
))
159 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
163 /* Setup the callback */
164 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
165 EnumerateValueKeyInfo
.Object
= (PVOID
)KeyObject
;
166 EnumerateValueKeyInfo
.Index
= Index
;
167 EnumerateValueKeyInfo
.KeyValueInformationClass
= KeyValueInformationClass
;
168 EnumerateValueKeyInfo
.KeyValueInformation
= KeyValueInformation
;
169 EnumerateValueKeyInfo
.Length
= Length
;
170 EnumerateValueKeyInfo
.ResultLength
= ResultLength
;
172 /* Do the callback */
173 Status
= CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey
,
174 &EnumerateValueKeyInfo
);
175 if (NT_SUCCESS(Status
))
177 /* Call the internal API */
178 Status
= CmEnumerateValueKey(KeyObject
->KeyControlBlock
,
180 KeyValueInformationClass
,
185 /* Do the post callback */
186 PostOperationInfo
.Status
= Status
;
187 CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey
, &PostOperationInfo
);
190 ObDereferenceObject(KeyObject
);
196 NtQueryKey(IN HANDLE KeyHandle
,
197 IN KEY_INFORMATION_CLASS KeyInformationClass
,
198 OUT PVOID KeyInformation
,
200 OUT PULONG ResultLength
)
203 PKEY_OBJECT KeyObject
;
204 REG_QUERY_KEY_INFORMATION QueryKeyInfo
;
205 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
208 DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
209 KeyHandle
, KeyInformationClass
, Length
);
211 /* Verify that the handle is valid and is a registry key */
212 Status
= ObReferenceObjectByHandle(KeyHandle
,
213 (KeyInformationClass
!=
214 KeyNameInformation
) ?
220 if (!NT_SUCCESS(Status
))
222 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
226 /* Setup the callback */
227 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
228 QueryKeyInfo
.Object
= (PVOID
)KeyObject
;
229 QueryKeyInfo
.KeyInformationClass
= KeyInformationClass
;
230 QueryKeyInfo
.KeyInformation
= KeyInformation
;
231 QueryKeyInfo
.Length
= Length
;
232 QueryKeyInfo
.ResultLength
= ResultLength
;
234 /* Do the callback */
235 Status
= CmiCallRegisteredCallbacks(RegNtPreQueryKey
, &QueryKeyInfo
);
236 if (NT_SUCCESS(Status
))
238 /* Call the internal API */
239 Status
= CmQueryKey(KeyObject
->KeyControlBlock
,
245 /* Do the post callback */
246 PostOperationInfo
.Status
= Status
;
247 CmiCallRegisteredCallbacks(RegNtPostQueryKey
, &PostOperationInfo
);
250 /* Dereference and return status */
251 ObDereferenceObject(KeyObject
);
257 NtQueryValueKey(IN HANDLE KeyHandle
,
258 IN PUNICODE_STRING ValueName
,
259 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
260 OUT PVOID KeyValueInformation
,
262 OUT PULONG ResultLength
)
265 PKEY_OBJECT KeyObject
;
266 REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo
;
267 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
270 DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
271 KeyHandle
, ValueName
, KeyValueInformationClass
, Length
);
273 /* Verify that the handle is valid and is a registry key */
274 Status
= ObReferenceObjectByHandle(KeyHandle
,
280 if (!NT_SUCCESS(Status
))
282 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
286 /* Setup the callback */
287 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
288 QueryValueKeyInfo
.Object
= (PVOID
)KeyObject
;
289 QueryValueKeyInfo
.ValueName
= ValueName
;
290 QueryValueKeyInfo
.KeyValueInformationClass
= KeyValueInformationClass
;
291 QueryValueKeyInfo
.Length
= Length
;
292 QueryValueKeyInfo
.ResultLength
= ResultLength
;
294 /* Do the callback */
295 Status
= CmiCallRegisteredCallbacks(RegNtPreQueryValueKey
, &QueryValueKeyInfo
);
296 if (NT_SUCCESS(Status
))
298 /* Call the internal API */
299 Status
= CmQueryValueKey(KeyObject
->KeyControlBlock
,
301 KeyValueInformationClass
,
306 /* Do the post callback */
307 PostOperationInfo
.Status
= Status
;
308 CmiCallRegisteredCallbacks(RegNtPostQueryValueKey
, &PostOperationInfo
);
311 DPRINT("NtQueryValueKey() returning 0x%08X\n", Status
);
313 /* Dereference and return status */
314 ObDereferenceObject(KeyObject
);
320 NtSetValueKey(IN HANDLE KeyHandle
,
321 IN PUNICODE_STRING ValueName
,
328 PKEY_OBJECT KeyObject
;
329 REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo
;
330 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
333 DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
334 KeyHandle
, ValueName
, TitleIndex
, Type
, DataSize
);
336 /* Verify that the handle is valid and is a registry key */
337 Status
= ObReferenceObjectByHandle(KeyHandle
,
343 if (!NT_SUCCESS(Status
))
345 DPRINT1("ObReferenceObjectByHandle() failed with Status = 0x%08X\n", Status
);
350 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
351 SetValueKeyInfo
.Object
= (PVOID
)KeyObject
;
352 SetValueKeyInfo
.ValueName
= ValueName
;
353 SetValueKeyInfo
.TitleIndex
= TitleIndex
;
354 SetValueKeyInfo
.Type
= Type
;
355 SetValueKeyInfo
.Data
= Data
;
356 SetValueKeyInfo
.DataSize
= DataSize
;
358 /* Do the callback */
359 Status
= CmiCallRegisteredCallbacks(RegNtPreSetValueKey
, &SetValueKeyInfo
);
360 if (NT_SUCCESS(Status
))
362 /* Call the internal API */
363 Status
= CmSetValueKey(KeyObject
->KeyControlBlock
,
370 /* Do the post-callback and de-reference the key object */
371 PostOperationInfo
.Status
= Status
;
372 CmiCallRegisteredCallbacks(RegNtPostSetValueKey
, &PostOperationInfo
);
373 ObDereferenceObject(KeyObject
);
375 /* Synchronize the hives and return */
382 NtDeleteValueKey(IN HANDLE KeyHandle
,
383 IN PUNICODE_STRING ValueName
)
385 PKEY_OBJECT KeyObject
;
387 REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo
;
388 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
389 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
392 /* Verify that the handle is valid and is a registry key */
393 Status
= ObReferenceObjectByHandle(KeyHandle
,
399 if (!NT_SUCCESS(Status
))
401 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
405 /* Do the callback */
406 DeleteValueKeyInfo
.Object
= (PVOID
)KeyObject
;
407 DeleteValueKeyInfo
.ValueName
= ValueName
;
408 Status
= CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey
,
409 &DeleteValueKeyInfo
);
410 if (NT_SUCCESS(Status
))
412 /* Call the internal API */
413 Status
= CmDeleteValueKey(KeyObject
->KeyControlBlock
, *ValueName
);
415 /* Do the post callback */
416 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
417 PostOperationInfo
.Status
= Status
;
418 CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey
,
422 /* Dereference the key body and synchronize the hives */
423 ObDereferenceObject(KeyObject
);
430 NtFlushKey(IN HANDLE KeyHandle
)
433 PKEY_OBJECT KeyObject
;
436 /* Get the key object */
437 Status
= ObReferenceObjectByHandle(KeyHandle
,
443 if (!NT_SUCCESS(Status
)) return Status
;
445 /* Lock the registry */
446 KeEnterCriticalRegion();
447 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
449 /* Make sure KCB isn't deleted */
450 if (KeyObject
->KeyControlBlock
->Delete
)
453 Status
= STATUS_KEY_DELETED
;
457 /* Call the internal API */
458 Status
= CmFlushKey(KeyObject
->KeyControlBlock
, FALSE
);
461 /* Release the lock */
462 ExReleaseResourceLite(&CmpRegistryLock
);
463 KeLeaveCriticalRegion();
465 /* Dereference the object and return status */
466 ObDereferenceObject(KeyObject
);
472 NtCompactKeys(IN ULONG Count
,
476 return STATUS_NOT_IMPLEMENTED
;
481 NtCompressKey(IN HANDLE Key
)
484 return STATUS_NOT_IMPLEMENTED
;
489 NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
490 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
492 return NtLoadKey2(KeyObjectAttributes
, FileObjectAttributes
, 0);
497 NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
498 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
501 return NtLoadKeyEx(KeyObjectAttributes
, FileObjectAttributes
, Flags
, NULL
);
506 CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey
,
507 IN POBJECT_ATTRIBUTES SourceFile
,
509 IN PKEY_OBJECT KeyBody
);
513 NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey
,
514 IN POBJECT_ATTRIBUTES SourceFile
,
516 IN HANDLE TrustClassKey
)
519 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
520 PKEY_OBJECT KeyBody
= NULL
;
524 if (Flags
& ~REG_NO_LAZY_FLUSH
) return STATUS_INVALID_PARAMETER
;
526 /* Validate privilege */
527 if (!SeSinglePrivilegeCheck(SeRestorePrivilege
, PreviousMode
))
530 DPRINT1("Restore Privilege missing!\n");
531 //return STATUS_PRIVILEGE_NOT_HELD;
535 KeEnterCriticalRegion();
537 /* Check if we have a trust class */
541 Status
= ObReferenceObjectByHandle(TrustClassKey
,
549 /* Call the internal API */
550 Status
= CmLoadKey(TargetKey
, SourceFile
, Flags
, KeyBody
);
552 /* Dereference the trust key, if any */
553 if (KeyBody
) ObDereferenceObject(KeyBody
);
555 /* Bring back APCs */
556 KeLeaveCriticalRegion();
564 NtLockProductActivationKeys(IN PULONG pPrivateVer
,
568 return STATUS_NOT_IMPLEMENTED
;
573 NtLockRegistryKey(IN HANDLE KeyHandle
)
576 return STATUS_NOT_IMPLEMENTED
;
581 NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle
,
583 IN POBJECT_ATTRIBUTES SlaveObjects
,
585 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
586 IN PVOID ApcContext OPTIONAL
,
587 OUT PIO_STATUS_BLOCK IoStatusBlock
,
588 IN ULONG CompletionFilter
,
589 IN BOOLEAN WatchTree
,
592 IN BOOLEAN Asynchronous
)
595 return STATUS_NOT_IMPLEMENTED
;
600 NtNotifyChangeKey(IN HANDLE KeyHandle
,
602 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
603 IN PVOID ApcContext OPTIONAL
,
604 OUT PIO_STATUS_BLOCK IoStatusBlock
,
605 IN ULONG CompletionFilter
,
606 IN BOOLEAN WatchTree
,
609 IN BOOLEAN Asynchronous
)
611 return NtNotifyChangeMultipleKeys(KeyHandle
,
627 NtQueryMultipleValueKey(IN HANDLE KeyHandle
,
628 IN OUT PKEY_VALUE_ENTRY ValueList
,
629 IN ULONG NumberOfValues
,
631 IN OUT PULONG Length
,
632 OUT PULONG ReturnLength
)
635 return STATUS_NOT_IMPLEMENTED
;
640 NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey
,
641 IN ULONG HandleCount
)
644 return STATUS_NOT_IMPLEMENTED
;
649 NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey
,
650 IN ULONG BufferLength
,
652 IN PULONG RequiredSize
)
655 return STATUS_NOT_IMPLEMENTED
;
660 NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes
,
662 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
665 return STATUS_NOT_IMPLEMENTED
;
670 NtRestoreKey(IN HANDLE KeyHandle
,
671 IN HANDLE FileHandle
,
672 IN ULONG RestoreFlags
)
675 return STATUS_NOT_IMPLEMENTED
;
680 NtSaveKey(IN HANDLE KeyHandle
,
681 IN HANDLE FileHandle
)
684 return STATUS_NOT_IMPLEMENTED
;
689 NtSaveKeyEx(IN HANDLE KeyHandle
,
690 IN HANDLE FileHandle
,
694 return STATUS_NOT_IMPLEMENTED
;
699 NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle
,
700 IN HANDLE LowPrecedenceKeyHandle
,
701 IN HANDLE FileHandle
)
704 return STATUS_NOT_IMPLEMENTED
;
709 NtSetInformationKey(IN HANDLE KeyHandle
,
710 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
711 IN PVOID KeyInformation
,
712 IN ULONG KeyInformationLength
)
715 return STATUS_NOT_IMPLEMENTED
;
720 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
723 return STATUS_NOT_IMPLEMENTED
;
728 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey
,
732 return STATUS_NOT_IMPLEMENTED
;
737 NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey
,
741 return STATUS_NOT_IMPLEMENTED
;