Bring back ext2 code from branch
[reactos.git] / reactos / ntoskrnl / config / ntapi.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14
15 BOOLEAN CmBootAcceptFirstTime = TRUE;
16 BOOLEAN CmFirstTime = TRUE;
17
18 /* FUNCTIONS *****************************************************************/
19
20 NTSTATUS
21 NTAPI
22 NtCreateKey(OUT PHANDLE KeyHandle,
23 IN ACCESS_MASK DesiredAccess,
24 IN POBJECT_ATTRIBUTES ObjectAttributes,
25 IN ULONG TitleIndex,
26 IN PUNICODE_STRING Class,
27 IN ULONG CreateOptions,
28 OUT PULONG Disposition)
29 {
30 NTSTATUS Status;
31 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
32 CM_PARSE_CONTEXT ParseContext = {0};
33 HANDLE Handle;
34 PAGED_CODE();
35 DPRINT("NtCreateKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
36
37 /* Setup the parse context */
38 ParseContext.CreateOperation = TRUE;
39 ParseContext.CreateOptions = CreateOptions;
40 if (Class) ParseContext.Class = *Class;
41
42 /* Do the create */
43 Status = ObOpenObjectByName(ObjectAttributes,
44 CmpKeyObjectType,
45 PreviousMode,
46 NULL,
47 DesiredAccess,
48 &ParseContext,
49 &Handle);
50 if (NT_SUCCESS(Status)) *KeyHandle = Handle;
51
52 /* Return data to user */
53 if (Disposition) *Disposition = ParseContext.Disposition;
54 return Status;
55 }
56
57 NTSTATUS
58 NTAPI
59 NtOpenKey(OUT PHANDLE KeyHandle,
60 IN ACCESS_MASK DesiredAccess,
61 IN POBJECT_ATTRIBUTES ObjectAttributes)
62 {
63 CM_PARSE_CONTEXT ParseContext = {0};
64 HANDLE Handle;
65 NTSTATUS Status;
66 PAGED_CODE();
67 DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
68
69 /* Just let the object manager handle this */
70 Status = ObOpenObjectByName(ObjectAttributes,
71 CmpKeyObjectType,
72 ExGetPreviousMode(),
73 NULL,
74 DesiredAccess,
75 &ParseContext,
76 &Handle);
77 if (NT_SUCCESS(Status)) *KeyHandle = Handle;
78
79 /* Return status */
80 return Status;
81 }
82
83
84 NTSTATUS
85 NTAPI
86 NtDeleteKey(IN HANDLE KeyHandle)
87 {
88 PCM_KEY_BODY KeyObject;
89 NTSTATUS Status;
90 REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
91 REG_POST_OPERATION_INFORMATION PostOperationInfo;
92 PAGED_CODE();
93 DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle);
94
95 /* Verify that the handle is valid and is a registry key */
96 Status = ObReferenceObjectByHandle(KeyHandle,
97 DELETE,
98 CmpKeyObjectType,
99 ExGetPreviousMode(),
100 (PVOID*)&KeyObject,
101 NULL);
102 if (!NT_SUCCESS(Status)) return Status;
103
104 /* Setup the callback */
105 PostOperationInfo.Object = (PVOID)KeyObject;
106 DeleteKeyInfo.Object = (PVOID)KeyObject;
107 Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo);
108 if (NT_SUCCESS(Status))
109 {
110 /* Check if we are read-only */
111 if ((KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY) ||
112 (KeyObject->KeyControlBlock->ParentKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
113 {
114 /* Fail */
115 Status = STATUS_ACCESS_DENIED;
116 }
117 else
118 {
119 /* Call the internal API */
120 Status = CmDeleteKey(KeyObject);
121 }
122
123 /* Do post callback */
124 PostOperationInfo.Status = Status;
125 CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
126 }
127
128 /* Dereference the object */
129 ObDereferenceObject(KeyObject);
130 return Status;
131 }
132
133 NTSTATUS
134 NTAPI
135 NtEnumerateKey(IN HANDLE KeyHandle,
136 IN ULONG Index,
137 IN KEY_INFORMATION_CLASS KeyInformationClass,
138 OUT PVOID KeyInformation,
139 IN ULONG Length,
140 OUT PULONG ResultLength)
141 {
142 NTSTATUS Status;
143 PCM_KEY_BODY KeyObject;
144 REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
145 REG_POST_OPERATION_INFORMATION PostOperationInfo;
146 PAGED_CODE();
147 DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
148 KeyHandle, Index, KeyInformationClass, Length);
149
150 /* Reject classes we don't know about */
151 if ((KeyInformationClass != KeyBasicInformation) &&
152 (KeyInformationClass != KeyNodeInformation) &&
153 (KeyInformationClass != KeyFullInformation))
154 {
155 /* Fail */
156 return STATUS_INVALID_PARAMETER;
157 }
158
159 /* Verify that the handle is valid and is a registry key */
160 Status = ObReferenceObjectByHandle(KeyHandle,
161 KEY_ENUMERATE_SUB_KEYS,
162 CmpKeyObjectType,
163 ExGetPreviousMode(),
164 (PVOID*)&KeyObject,
165 NULL);
166 if (!NT_SUCCESS(Status)) return Status;
167
168 /* Setup the callback */
169 PostOperationInfo.Object = (PVOID)KeyObject;
170 EnumerateKeyInfo.Object = (PVOID)KeyObject;
171 EnumerateKeyInfo.Index = Index;
172 EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
173 EnumerateKeyInfo.Length = Length;
174 EnumerateKeyInfo.ResultLength = ResultLength;
175
176 /* Do the callback */
177 Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
178 if (NT_SUCCESS(Status))
179 {
180 /* Call the internal API */
181 Status = CmEnumerateKey(KeyObject->KeyControlBlock,
182 Index,
183 KeyInformationClass,
184 KeyInformation,
185 Length,
186 ResultLength);
187
188 /* Do the post callback */
189 PostOperationInfo.Status = Status;
190 CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
191 }
192
193 /* Dereference and return status */
194 ObDereferenceObject(KeyObject);
195 return Status;
196 }
197
198 NTSTATUS
199 NTAPI
200 NtEnumerateValueKey(IN HANDLE KeyHandle,
201 IN ULONG Index,
202 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
203 OUT PVOID KeyValueInformation,
204 IN ULONG Length,
205 OUT PULONG ResultLength)
206 {
207 NTSTATUS Status;
208 PCM_KEY_BODY KeyObject;
209 REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo;
210 REG_POST_OPERATION_INFORMATION PostOperationInfo;
211 PAGED_CODE();
212 DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
213 KeyHandle, Index, KeyValueInformationClass, Length);
214
215 /* Reject classes we don't know about */
216 if ((KeyValueInformationClass != KeyValueBasicInformation) &&
217 (KeyValueInformationClass != KeyValueFullInformation) &&
218 (KeyValueInformationClass != KeyValuePartialInformation))
219 {
220 /* Fail */
221 return STATUS_INVALID_PARAMETER;
222 }
223
224 /* Verify that the handle is valid and is a registry key */
225 Status = ObReferenceObjectByHandle(KeyHandle,
226 KEY_QUERY_VALUE,
227 CmpKeyObjectType,
228 ExGetPreviousMode(),
229 (PVOID*)&KeyObject,
230 NULL);
231 if (!NT_SUCCESS(Status)) return Status;
232
233 /* Setup the callback */
234 PostOperationInfo.Object = (PVOID)KeyObject;
235 EnumerateValueKeyInfo.Object = (PVOID)KeyObject;
236 EnumerateValueKeyInfo.Index = Index;
237 EnumerateValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass;
238 EnumerateValueKeyInfo.KeyValueInformation = KeyValueInformation;
239 EnumerateValueKeyInfo.Length = Length;
240 EnumerateValueKeyInfo.ResultLength = ResultLength;
241
242 /* Do the callback */
243 Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey,
244 &EnumerateValueKeyInfo);
245 if (NT_SUCCESS(Status))
246 {
247 /* Call the internal API */
248 Status = CmEnumerateValueKey(KeyObject->KeyControlBlock,
249 Index,
250 KeyValueInformationClass,
251 KeyValueInformation,
252 Length,
253 ResultLength);
254
255 /* Do the post callback */
256 PostOperationInfo.Status = Status;
257 CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo);
258 }
259
260 ObDereferenceObject(KeyObject);
261 return Status;
262 }
263
264 NTSTATUS
265 NTAPI
266 NtQueryKey(IN HANDLE KeyHandle,
267 IN KEY_INFORMATION_CLASS KeyInformationClass,
268 OUT PVOID KeyInformation,
269 IN ULONG Length,
270 OUT PULONG ResultLength)
271 {
272 NTSTATUS Status;
273 PCM_KEY_BODY KeyObject;
274 REG_QUERY_KEY_INFORMATION QueryKeyInfo;
275 REG_POST_OPERATION_INFORMATION PostOperationInfo;
276 OBJECT_HANDLE_INFORMATION HandleInfo;
277 PAGED_CODE();
278 DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
279 KeyHandle, KeyInformationClass, Length);
280
281 /* Reject invalid classes */
282 if ((KeyInformationClass != KeyBasicInformation) &&
283 (KeyInformationClass != KeyNodeInformation) &&
284 (KeyInformationClass != KeyFullInformation) &&
285 (KeyInformationClass != KeyNameInformation) &&
286 (KeyInformationClass != KeyCachedInformation) &&
287 (KeyInformationClass != KeyFlagsInformation))
288 {
289 /* Fail */
290 return STATUS_INVALID_PARAMETER;
291 }
292
293 /* Check if just the name is required */
294 if (KeyInformationClass == KeyNameInformation)
295 {
296 /* Ignore access level */
297 Status = ObReferenceObjectByHandle(KeyHandle,
298 0,
299 CmpKeyObjectType,
300 ExGetPreviousMode(),
301 (PVOID*)&KeyObject,
302 &HandleInfo);
303 if (NT_SUCCESS(Status))
304 {
305 /* At least a single bit of access is required */
306 if (!HandleInfo.GrantedAccess)
307 {
308 /* No such luck */
309 ObDereferenceObject(KeyObject);
310 Status = STATUS_ACCESS_DENIED;
311 }
312 }
313 }
314 else
315 {
316 /* Get a reference */
317 Status = ObReferenceObjectByHandle(KeyHandle,
318 KEY_QUERY_VALUE,
319 CmpKeyObjectType,
320 ExGetPreviousMode(),
321 (PVOID*)&KeyObject,
322 NULL);
323 }
324
325 /* Quit on failure */
326 if (!NT_SUCCESS(Status)) return Status;
327
328 /* Setup the callback */
329 PostOperationInfo.Object = (PVOID)KeyObject;
330 QueryKeyInfo.Object = (PVOID)KeyObject;
331 QueryKeyInfo.KeyInformationClass = KeyInformationClass;
332 QueryKeyInfo.KeyInformation = KeyInformation;
333 QueryKeyInfo.Length = Length;
334 QueryKeyInfo.ResultLength = ResultLength;
335
336 /* Do the callback */
337 Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo);
338 if (NT_SUCCESS(Status))
339 {
340 /* Call the internal API */
341 Status = CmQueryKey(KeyObject->KeyControlBlock,
342 KeyInformationClass,
343 KeyInformation,
344 Length,
345 ResultLength);
346
347 /* Do the post callback */
348 PostOperationInfo.Status = Status;
349 CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
350 }
351
352 /* Dereference and return status */
353 ObDereferenceObject(KeyObject);
354 return Status;
355 }
356
357 NTSTATUS
358 NTAPI
359 NtQueryValueKey(IN HANDLE KeyHandle,
360 IN PUNICODE_STRING ValueName,
361 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
362 OUT PVOID KeyValueInformation,
363 IN ULONG Length,
364 OUT PULONG ResultLength)
365 {
366 NTSTATUS Status;
367 PCM_KEY_BODY KeyObject;
368 REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo;
369 REG_POST_OPERATION_INFORMATION PostOperationInfo;
370 UNICODE_STRING ValueNameCopy = *ValueName;
371 PAGED_CODE();
372 DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
373 KeyHandle, ValueName, KeyValueInformationClass, Length);
374
375 /* Verify that the handle is valid and is a registry key */
376 Status = ObReferenceObjectByHandle(KeyHandle,
377 KEY_QUERY_VALUE,
378 CmpKeyObjectType,
379 ExGetPreviousMode(),
380 (PVOID*)&KeyObject,
381 NULL);
382 if (!NT_SUCCESS(Status)) return Status;
383
384 /* Make sure the name is aligned properly */
385 if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1)))
386 {
387 /* It isn't, so we'll fail */
388 ObDereferenceObject(KeyObject);
389 return STATUS_INVALID_PARAMETER;
390 }
391 else
392 {
393 /* Ignore any null characters at the end */
394 while ((ValueNameCopy.Length) &&
395 !(ValueNameCopy.Buffer[ValueNameCopy.Length / sizeof(WCHAR) - 1]))
396 {
397 /* Skip it */
398 ValueNameCopy.Length -= sizeof(WCHAR);
399 }
400 }
401
402 /* Setup the callback */
403 PostOperationInfo.Object = (PVOID)KeyObject;
404 QueryValueKeyInfo.Object = (PVOID)KeyObject;
405 QueryValueKeyInfo.ValueName = &ValueNameCopy;
406 QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass;
407 QueryValueKeyInfo.Length = Length;
408 QueryValueKeyInfo.ResultLength = ResultLength;
409
410 /* Do the callback */
411 Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo);
412 if (NT_SUCCESS(Status))
413 {
414 /* Call the internal API */
415 Status = CmQueryValueKey(KeyObject->KeyControlBlock,
416 ValueNameCopy,
417 KeyValueInformationClass,
418 KeyValueInformation,
419 Length,
420 ResultLength);
421
422 /* Do the post callback */
423 PostOperationInfo.Status = Status;
424 CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
425 }
426
427 /* Dereference and return status */
428 ObDereferenceObject(KeyObject);
429 return Status;
430 }
431
432 NTSTATUS
433 NTAPI
434 NtSetValueKey(IN HANDLE KeyHandle,
435 IN PUNICODE_STRING ValueName,
436 IN ULONG TitleIndex,
437 IN ULONG Type,
438 IN PVOID Data,
439 IN ULONG DataSize)
440 {
441 NTSTATUS Status;
442 PCM_KEY_BODY KeyObject;
443 REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
444 REG_POST_OPERATION_INFORMATION PostOperationInfo;
445 UNICODE_STRING ValueNameCopy = *ValueName;
446 PAGED_CODE();
447 DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
448 KeyHandle, ValueName, TitleIndex, Type, DataSize);
449
450 /* Verify that the handle is valid and is a registry key */
451 Status = ObReferenceObjectByHandle(KeyHandle,
452 KEY_SET_VALUE,
453 CmpKeyObjectType,
454 ExGetPreviousMode(),
455 (PVOID*)&KeyObject,
456 NULL);
457 if (!NT_SUCCESS(Status)) return Status;
458
459 /* Make sure the name is aligned, not too long, and the data under 4GB */
460 if ( (ValueNameCopy.Length > 32767) ||
461 ((ValueNameCopy.Length & (sizeof(WCHAR) - 1))) ||
462 (DataSize > 0x80000000))
463 {
464 /* Fail */
465 ObDereferenceObject(KeyObject);
466 return STATUS_INVALID_PARAMETER;
467 }
468
469 /* Ignore any null characters at the end */
470 while ((ValueNameCopy.Length) &&
471 !(ValueNameCopy.Buffer[ValueNameCopy.Length / sizeof(WCHAR) - 1]))
472 {
473 /* Skip it */
474 ValueNameCopy.Length -= sizeof(WCHAR);
475 }
476
477 /* Don't touch read-only keys */
478 if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
479 {
480 /* Fail */
481 ObDereferenceObject(KeyObject);
482 return STATUS_ACCESS_DENIED;
483 }
484
485 /* Setup callback */
486 PostOperationInfo.Object = (PVOID)KeyObject;
487 SetValueKeyInfo.Object = (PVOID)KeyObject;
488 SetValueKeyInfo.ValueName = ValueName;
489 SetValueKeyInfo.TitleIndex = TitleIndex;
490 SetValueKeyInfo.Type = Type;
491 SetValueKeyInfo.Data = Data;
492 SetValueKeyInfo.DataSize = DataSize;
493
494 /* Do the callback */
495 Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
496 if (NT_SUCCESS(Status))
497 {
498 /* Call the internal API */
499 Status = CmSetValueKey(KeyObject->KeyControlBlock,
500 &ValueNameCopy,
501 Type,
502 Data,
503 DataSize);
504 }
505
506 /* Do the post-callback */
507 PostOperationInfo.Status = Status;
508 CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
509
510 /* Dereference and return status */
511 ObDereferenceObject(KeyObject);
512 return Status;
513 }
514
515 NTSTATUS
516 NTAPI
517 NtDeleteValueKey(IN HANDLE KeyHandle,
518 IN PUNICODE_STRING ValueName)
519 {
520 PCM_KEY_BODY KeyObject;
521 NTSTATUS Status;
522 REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
523 REG_POST_OPERATION_INFORMATION PostOperationInfo;
524 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
525 UNICODE_STRING ValueNameCopy = *ValueName;
526 PAGED_CODE();
527
528 /* Verify that the handle is valid and is a registry key */
529 Status = ObReferenceObjectByHandle(KeyHandle,
530 KEY_SET_VALUE,
531 CmpKeyObjectType,
532 PreviousMode,
533 (PVOID *)&KeyObject,
534 NULL);
535 if (!NT_SUCCESS(Status)) return Status;
536
537 /* Don't touch read-only keys */
538 if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
539 {
540 /* Fail */
541 ObDereferenceObject(KeyObject);
542 return STATUS_ACCESS_DENIED;
543 }
544
545 /* Make sure the name is aligned properly */
546 if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1)))
547 {
548 /* It isn't, so we'll fail */
549 ObDereferenceObject(KeyObject);
550 return STATUS_INVALID_PARAMETER;
551 }
552
553 /* Do the callback */
554 DeleteValueKeyInfo.Object = (PVOID)KeyObject;
555 DeleteValueKeyInfo.ValueName = ValueName;
556 Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey,
557 &DeleteValueKeyInfo);
558 if (NT_SUCCESS(Status))
559 {
560 /* Call the internal API */
561 Status = CmDeleteValueKey(KeyObject->KeyControlBlock, ValueNameCopy);
562
563 /* Do the post callback */
564 PostOperationInfo.Object = (PVOID)KeyObject;
565 PostOperationInfo.Status = Status;
566 CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey,
567 &PostOperationInfo);
568 }
569
570 /* Dereference the key body */
571 ObDereferenceObject(KeyObject);
572 return Status;
573 }
574
575 NTSTATUS
576 NTAPI
577 NtFlushKey(IN HANDLE KeyHandle)
578 {
579 NTSTATUS Status;
580 PCM_KEY_BODY KeyObject;
581 PAGED_CODE();
582
583 /* Get the key object */
584 Status = ObReferenceObjectByHandle(KeyHandle,
585 0,
586 CmpKeyObjectType,
587 ExGetPreviousMode(),
588 (PVOID*)&KeyObject,
589 NULL);
590 if (!NT_SUCCESS(Status)) return Status;
591
592 /* Lock the registry */
593 CmpLockRegistry();
594
595 /* Lock the KCB */
596 CmpAcquireKcbLockShared(KeyObject->KeyControlBlock);
597
598 /* Make sure KCB isn't deleted */
599 if (KeyObject->KeyControlBlock->Delete)
600 {
601 /* Fail */
602 Status = STATUS_KEY_DELETED;
603 }
604 else
605 {
606 /* Call the internal API */
607 Status = CmFlushKey(KeyObject->KeyControlBlock, FALSE);
608 }
609
610 /* Release the locks */
611 CmpReleaseKcbLock(KeyObject->KeyControlBlock);
612 CmpUnlockRegistry();
613
614 /* Dereference the object and return status */
615 ObDereferenceObject(KeyObject);
616 return Status;
617 }
618
619 NTSTATUS
620 NTAPI
621 NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
622 IN POBJECT_ATTRIBUTES FileObjectAttributes)
623 {
624 /* Call the newer API */
625 return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
626 }
627
628 NTSTATUS
629 NTAPI
630 NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
631 IN POBJECT_ATTRIBUTES FileObjectAttributes,
632 IN ULONG Flags)
633 {
634 /* Call the newer API */
635 return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL);
636 }
637
638 NTSTATUS
639 NTAPI
640 NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
641 IN POBJECT_ATTRIBUTES SourceFile,
642 IN ULONG Flags,
643 IN HANDLE TrustClassKey)
644 {
645 NTSTATUS Status;
646 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
647 PCM_KEY_BODY KeyBody = NULL;
648 PAGED_CODE();
649
650 /* Validate flags */
651 if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
652
653 /* Validate privilege */
654 if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
655 {
656 /* Fail */
657 DPRINT1("Restore Privilege missing!\n");
658 return STATUS_PRIVILEGE_NOT_HELD;
659 }
660
661 /* Block APCs */
662 KeEnterCriticalRegion();
663
664 /* Check if we have a trust class */
665 if (TrustClassKey)
666 {
667 /* Reference it */
668 Status = ObReferenceObjectByHandle(TrustClassKey,
669 0,
670 CmpKeyObjectType,
671 PreviousMode,
672 (PVOID *)&KeyBody,
673 NULL);
674 }
675
676 /* Call the internal API */
677 Status = CmLoadKey(TargetKey, SourceFile, Flags, KeyBody);
678
679 /* Dereference the trust key, if any */
680 if (KeyBody) ObDereferenceObject(KeyBody);
681
682 /* Bring back APCs */
683 KeLeaveCriticalRegion();
684
685 /* Return status */
686 return Status;
687 }
688
689 NTSTATUS
690 NTAPI
691 NtNotifyChangeKey(IN HANDLE KeyHandle,
692 IN HANDLE Event,
693 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
694 IN PVOID ApcContext OPTIONAL,
695 OUT PIO_STATUS_BLOCK IoStatusBlock,
696 IN ULONG CompletionFilter,
697 IN BOOLEAN WatchTree,
698 OUT PVOID Buffer,
699 IN ULONG Length,
700 IN BOOLEAN Asynchronous)
701 {
702 /* Call the newer API */
703 return NtNotifyChangeMultipleKeys(KeyHandle,
704 0,
705 NULL,
706 Event,
707 ApcRoutine,
708 ApcContext,
709 IoStatusBlock,
710 CompletionFilter,
711 WatchTree,
712 Buffer,
713 Length,
714 Asynchronous);
715 }
716
717 NTSTATUS
718 NTAPI
719 NtInitializeRegistry(IN USHORT Flag)
720 {
721 BOOLEAN SetupBoot;
722 NTSTATUS Status = STATUS_SUCCESS;
723 PAGED_CODE();
724
725 /* Always do this as kernel mode */
726 if (KeGetPreviousMode() == UserMode) return ZwInitializeRegistry(Flag);
727
728 /* Validate flag */
729 if (Flag > CM_BOOT_FLAG_MAX) return STATUS_INVALID_PARAMETER;
730
731 /* Check if boot was accepted */
732 if ((Flag >= CM_BOOT_FLAG_ACCEPTED) && (Flag <= CM_BOOT_FLAG_MAX))
733 {
734 /* Only allow once */
735 if (!CmBootAcceptFirstTime) return STATUS_ACCESS_DENIED;
736 CmBootAcceptFirstTime = FALSE;
737
738 /* Get the control set accepted */
739 Flag -= CM_BOOT_FLAG_ACCEPTED;
740 if (Flag)
741 {
742 /* FIXME: Save the last known good boot */
743 //Status = CmpSaveBootControlSet(Flag);
744
745 /* Notify HAL */
746 HalEndOfBoot();
747
748 /* Enable lazy flush */
749 CmpHoldLazyFlush = FALSE;
750 CmpLazyFlush();
751 return Status;
752 }
753
754 /* Otherwise, invalid boot */
755 return STATUS_INVALID_PARAMETER;
756 }
757
758 /* Check if this was a setup boot */
759 SetupBoot = (Flag == CM_BOOT_FLAG_SETUP ? TRUE : FALSE);
760
761 /* Make sure we're only called once */
762 if (!CmFirstTime) return STATUS_ACCESS_DENIED;
763 CmFirstTime = FALSE;
764
765 /* Acquire registry lock */
766 //CmpLockRegistryExclusive();
767
768 /* Initialize the hives and lazy flusher */
769 CmpCmdInit(SetupBoot);
770
771 /* FIXME: Save version data */
772 //CmpSetVersionData();
773
774 /* Release the registry lock */
775 //CmpUnlockRegistry();
776 return STATUS_SUCCESS;
777 }
778
779 NTSTATUS
780 NTAPI
781 NtCompactKeys(IN ULONG Count,
782 IN PHANDLE KeyArray)
783 {
784 UNIMPLEMENTED;
785 return STATUS_NOT_IMPLEMENTED;
786 }
787
788 NTSTATUS
789 NTAPI
790 NtCompressKey(IN HANDLE Key)
791 {
792 UNIMPLEMENTED;
793 return STATUS_NOT_IMPLEMENTED;
794 }
795
796 NTSTATUS
797 NTAPI
798 NtLockProductActivationKeys(IN PULONG pPrivateVer,
799 IN PULONG pSafeMode)
800 {
801 UNIMPLEMENTED;
802 return STATUS_NOT_IMPLEMENTED;
803 }
804
805 NTSTATUS
806 NTAPI
807 NtLockRegistryKey(IN HANDLE KeyHandle)
808 {
809 UNIMPLEMENTED;
810 return STATUS_NOT_IMPLEMENTED;
811 }
812
813 NTSTATUS
814 NTAPI
815 NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle,
816 IN ULONG Count,
817 IN POBJECT_ATTRIBUTES SlaveObjects,
818 IN HANDLE Event,
819 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
820 IN PVOID ApcContext OPTIONAL,
821 OUT PIO_STATUS_BLOCK IoStatusBlock,
822 IN ULONG CompletionFilter,
823 IN BOOLEAN WatchTree,
824 OUT PVOID Buffer,
825 IN ULONG Length,
826 IN BOOLEAN Asynchronous)
827 {
828 UNIMPLEMENTED;
829 return STATUS_NOT_IMPLEMENTED;
830 }
831
832 NTSTATUS
833 NTAPI
834 NtQueryMultipleValueKey(IN HANDLE KeyHandle,
835 IN OUT PKEY_VALUE_ENTRY ValueList,
836 IN ULONG NumberOfValues,
837 OUT PVOID Buffer,
838 IN OUT PULONG Length,
839 OUT PULONG ReturnLength)
840 {
841 UNIMPLEMENTED;
842 return STATUS_NOT_IMPLEMENTED;
843 }
844
845 NTSTATUS
846 NTAPI
847 NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
848 IN ULONG HandleCount)
849 {
850 UNIMPLEMENTED;
851 return STATUS_NOT_IMPLEMENTED;
852 }
853
854 NTSTATUS
855 NTAPI
856 NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey,
857 IN ULONG BufferLength,
858 IN PVOID Buffer,
859 IN PULONG RequiredSize)
860 {
861 UNIMPLEMENTED;
862 return STATUS_NOT_IMPLEMENTED;
863 }
864
865 NTSTATUS
866 NTAPI
867 NtRenameKey(IN HANDLE KeyHandle,
868 IN PUNICODE_STRING ReplacementName)
869 {
870 UNIMPLEMENTED;
871 return STATUS_NOT_IMPLEMENTED;
872 }
873
874 NTSTATUS
875 NTAPI
876 NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes,
877 IN HANDLE Key,
878 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
879 {
880 UNIMPLEMENTED;
881 return STATUS_NOT_IMPLEMENTED;
882 }
883
884 NTSTATUS
885 NTAPI
886 NtRestoreKey(IN HANDLE KeyHandle,
887 IN HANDLE FileHandle,
888 IN ULONG RestoreFlags)
889 {
890 UNIMPLEMENTED;
891 return STATUS_NOT_IMPLEMENTED;
892 }
893
894 NTSTATUS
895 NTAPI
896 NtSaveKey(IN HANDLE KeyHandle,
897 IN HANDLE FileHandle)
898 {
899 UNIMPLEMENTED;
900 return STATUS_NOT_IMPLEMENTED;
901 }
902
903 NTSTATUS
904 NTAPI
905 NtSaveKeyEx(IN HANDLE KeyHandle,
906 IN HANDLE FileHandle,
907 IN ULONG Flags)
908 {
909 UNIMPLEMENTED;
910 return STATUS_NOT_IMPLEMENTED;
911 }
912
913 NTSTATUS
914 NTAPI
915 NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle,
916 IN HANDLE LowPrecedenceKeyHandle,
917 IN HANDLE FileHandle)
918 {
919 UNIMPLEMENTED;
920 return STATUS_NOT_IMPLEMENTED;
921 }
922
923 NTSTATUS
924 NTAPI
925 NtSetInformationKey(IN HANDLE KeyHandle,
926 IN KEY_SET_INFORMATION_CLASS KeyInformationClass,
927 IN PVOID KeyInformation,
928 IN ULONG KeyInformationLength)
929 {
930 UNIMPLEMENTED;
931 return STATUS_NOT_IMPLEMENTED;
932 }
933
934 NTSTATUS
935 NTAPI
936 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes)
937 {
938 UNIMPLEMENTED;
939 return STATUS_NOT_IMPLEMENTED;
940 }
941
942 NTSTATUS
943 NTAPI
944 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
945 IN ULONG Flags)
946 {
947 UNIMPLEMENTED;
948 return STATUS_NOT_IMPLEMENTED;
949 }
950
951 NTSTATUS
952 NTAPI
953 NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
954 IN HANDLE Event)
955 {
956 UNIMPLEMENTED;
957 return STATUS_NOT_IMPLEMENTED;
958 }
959
960 /* EOF */