- Fix prototype of NtLoadKeyEx.
[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 #include "cm.h"
13 #define NDEBUG
14 #include "debug.h"
15
16 /* FUNCTIONS *****************************************************************/
17
18 NTSTATUS
19 NTAPI
20 NtDeleteKey(IN HANDLE KeyHandle)
21 {
22 PKEY_OBJECT KeyObject;
23 NTSTATUS Status;
24 REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
25 REG_POST_OPERATION_INFORMATION PostOperationInfo;
26 PAGED_CODE();
27
28 DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle);
29
30 /* Verify that the handle is valid and is a registry key */
31 Status = ObReferenceObjectByHandle(KeyHandle,
32 DELETE,
33 CmpKeyObjectType,
34 ExGetPreviousMode(),
35 (PVOID *)&KeyObject,
36 NULL);
37 if (!NT_SUCCESS(Status))
38 {
39 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
40 return Status;
41 }
42
43 /* Setup the callback */
44 PostOperationInfo.Object = (PVOID)KeyObject;
45 DeleteKeyInfo.Object = (PVOID)KeyObject;
46 Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo);
47 if (NT_SUCCESS(Status))
48 {
49 /* Call the internal API */
50 Status = CmDeleteKey(KeyObject->KeyControlBlock);
51
52 /* Remove the keep-alive reference */
53 ObDereferenceObject(KeyObject);
54 if (KeyObject->KeyControlBlock->KeyHive !=
55 KeyObject->KeyControlBlock->ParentKcb->KeyHive)
56 {
57 /* Dereference again */
58 ObDereferenceObject(KeyObject);
59 }
60
61 /* Do post callback */
62 PostOperationInfo.Status = Status;
63 CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
64 }
65
66 /* Dereference the object */
67 ObDereferenceObject(KeyObject);
68 return Status;
69 }
70
71 NTSTATUS
72 NTAPI
73 NtEnumerateKey(IN HANDLE KeyHandle,
74 IN ULONG Index,
75 IN KEY_INFORMATION_CLASS KeyInformationClass,
76 OUT PVOID KeyInformation,
77 IN ULONG Length,
78 OUT PULONG ResultLength)
79 {
80 NTSTATUS Status;
81 PKEY_OBJECT KeyObject;
82 REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
83 REG_POST_OPERATION_INFORMATION PostOperationInfo;
84 PAGED_CODE();
85
86 DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
87 KeyHandle, Index, KeyInformationClass, Length);
88
89 /* Verify that the handle is valid and is a registry key */
90 Status = ObReferenceObjectByHandle(KeyHandle,
91 KEY_ENUMERATE_SUB_KEYS,
92 CmpKeyObjectType,
93 ExGetPreviousMode(),
94 (PVOID *)&KeyObject,
95 NULL);
96 if (!NT_SUCCESS(Status))
97 {
98 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
99 return Status;
100 }
101
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;
109
110 /* Do the callback */
111 Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
112 if (NT_SUCCESS(Status))
113 {
114 /* Call the internal API */
115 Status = CmEnumerateKey(KeyObject->KeyControlBlock,
116 Index,
117 KeyInformationClass,
118 KeyInformation,
119 Length,
120 ResultLength);
121
122 /* Do the post callback */
123 PostOperationInfo.Status = Status;
124 CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
125 }
126
127 /* Dereference and return status */
128 ObDereferenceObject(KeyObject);
129 return Status;
130 }
131
132 NTSTATUS
133 NTAPI
134 NtEnumerateValueKey(IN HANDLE KeyHandle,
135 IN ULONG Index,
136 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
137 OUT PVOID KeyValueInformation,
138 IN ULONG Length,
139 OUT PULONG ResultLength)
140 {
141 NTSTATUS Status;
142 PKEY_OBJECT KeyObject;
143 REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo;
144 REG_POST_OPERATION_INFORMATION PostOperationInfo;
145 PAGED_CODE();
146
147 DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
148 KeyHandle, Index, KeyValueInformationClass, Length);
149
150 /* Verify that the handle is valid and is a registry key */
151 Status = ObReferenceObjectByHandle(KeyHandle,
152 KEY_QUERY_VALUE,
153 CmpKeyObjectType,
154 ExGetPreviousMode(),
155 (PVOID *)&KeyObject,
156 NULL);
157 if (!NT_SUCCESS(Status))
158 {
159 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
160 return Status;
161 }
162
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;
171
172 /* Do the callback */
173 Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey,
174 &EnumerateValueKeyInfo);
175 if (NT_SUCCESS(Status))
176 {
177 /* Call the internal API */
178 Status = CmEnumerateValueKey(KeyObject->KeyControlBlock,
179 Index,
180 KeyValueInformationClass,
181 KeyValueInformation,
182 Length,
183 ResultLength);
184
185 /* Do the post callback */
186 PostOperationInfo.Status = Status;
187 CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo);
188 }
189
190 ObDereferenceObject(KeyObject);
191 return Status;
192 }
193
194 NTSTATUS
195 NTAPI
196 NtQueryKey(IN HANDLE KeyHandle,
197 IN KEY_INFORMATION_CLASS KeyInformationClass,
198 OUT PVOID KeyInformation,
199 IN ULONG Length,
200 OUT PULONG ResultLength)
201 {
202 NTSTATUS Status;
203 PKEY_OBJECT KeyObject;
204 REG_QUERY_KEY_INFORMATION QueryKeyInfo;
205 REG_POST_OPERATION_INFORMATION PostOperationInfo;
206 PAGED_CODE();
207
208 DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
209 KeyHandle, KeyInformationClass, Length);
210
211 /* Verify that the handle is valid and is a registry key */
212 Status = ObReferenceObjectByHandle(KeyHandle,
213 (KeyInformationClass !=
214 KeyNameInformation) ?
215 KEY_QUERY_VALUE : 0,
216 CmpKeyObjectType,
217 ExGetPreviousMode(),
218 (PVOID *)&KeyObject,
219 NULL);
220 if (!NT_SUCCESS(Status))
221 {
222 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
223 return Status;
224 }
225
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;
233
234 /* Do the callback */
235 Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo);
236 if (NT_SUCCESS(Status))
237 {
238 /* Call the internal API */
239 Status = CmQueryKey(KeyObject->KeyControlBlock,
240 KeyInformationClass,
241 KeyInformation,
242 Length,
243 ResultLength);
244
245 /* Do the post callback */
246 PostOperationInfo.Status = Status;
247 CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
248 }
249
250 /* Dereference and return status */
251 ObDereferenceObject(KeyObject);
252 return Status;
253 }
254
255 NTSTATUS
256 NTAPI
257 NtQueryValueKey(IN HANDLE KeyHandle,
258 IN PUNICODE_STRING ValueName,
259 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
260 OUT PVOID KeyValueInformation,
261 IN ULONG Length,
262 OUT PULONG ResultLength)
263 {
264 NTSTATUS Status;
265 PKEY_OBJECT KeyObject;
266 REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo;
267 REG_POST_OPERATION_INFORMATION PostOperationInfo;
268 PAGED_CODE();
269
270 DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
271 KeyHandle, ValueName, KeyValueInformationClass, Length);
272
273 /* Verify that the handle is valid and is a registry key */
274 Status = ObReferenceObjectByHandle(KeyHandle,
275 KEY_QUERY_VALUE,
276 CmpKeyObjectType,
277 ExGetPreviousMode(),
278 (PVOID *)&KeyObject,
279 NULL);
280 if (!NT_SUCCESS(Status))
281 {
282 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
283 return Status;
284 }
285
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;
293
294 /* Do the callback */
295 Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo);
296 if (NT_SUCCESS(Status))
297 {
298 /* Call the internal API */
299 Status = CmQueryValueKey(KeyObject->KeyControlBlock,
300 *ValueName,
301 KeyValueInformationClass,
302 KeyValueInformation,
303 Length,
304 ResultLength);
305
306 /* Do the post callback */
307 PostOperationInfo.Status = Status;
308 CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
309 }
310
311 DPRINT("NtQueryValueKey() returning 0x%08X\n", Status);
312
313 /* Dereference and return status */
314 ObDereferenceObject(KeyObject);
315 return Status;
316 }
317
318 NTSTATUS
319 NTAPI
320 NtSetValueKey(IN HANDLE KeyHandle,
321 IN PUNICODE_STRING ValueName,
322 IN ULONG TitleIndex,
323 IN ULONG Type,
324 IN PVOID Data,
325 IN ULONG DataSize)
326 {
327 NTSTATUS Status;
328 PKEY_OBJECT KeyObject;
329 REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
330 REG_POST_OPERATION_INFORMATION PostOperationInfo;
331 PAGED_CODE();
332
333 DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
334 KeyHandle, ValueName, TitleIndex, Type, DataSize);
335
336 /* Verify that the handle is valid and is a registry key */
337 Status = ObReferenceObjectByHandle(KeyHandle,
338 KEY_SET_VALUE,
339 CmpKeyObjectType,
340 ExGetPreviousMode(),
341 (PVOID *)&KeyObject,
342 NULL);
343 if (!NT_SUCCESS(Status))
344 {
345 DPRINT1("ObReferenceObjectByHandle() failed with Status = 0x%08X\n", Status);
346 return Status;
347 }
348
349 /* Setup callback */
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;
357
358 /* Do the callback */
359 Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
360 if (NT_SUCCESS(Status))
361 {
362 /* Call the internal API */
363 Status = CmSetValueKey(KeyObject->KeyControlBlock,
364 ValueName,
365 Type,
366 Data,
367 DataSize);
368 }
369
370 /* Do the post-callback and de-reference the key object */
371 PostOperationInfo.Status = Status;
372 CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
373 ObDereferenceObject(KeyObject);
374
375 /* Synchronize the hives and return */
376 CmpLazyFlush();
377 return Status;
378 }
379
380 NTSTATUS
381 NTAPI
382 NtDeleteValueKey(IN HANDLE KeyHandle,
383 IN PUNICODE_STRING ValueName)
384 {
385 PKEY_OBJECT KeyObject;
386 NTSTATUS Status;
387 REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
388 REG_POST_OPERATION_INFORMATION PostOperationInfo;
389 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
390 PAGED_CODE();
391
392 /* Verify that the handle is valid and is a registry key */
393 Status = ObReferenceObjectByHandle(KeyHandle,
394 KEY_SET_VALUE,
395 CmpKeyObjectType,
396 PreviousMode,
397 (PVOID *)&KeyObject,
398 NULL);
399 if (!NT_SUCCESS(Status))
400 {
401 DPRINT("ObReferenceObjectByHandle() failed with Status = 0x%08X\n");
402 return Status;
403 }
404
405 /* Do the callback */
406 DeleteValueKeyInfo.Object = (PVOID)KeyObject;
407 DeleteValueKeyInfo.ValueName = ValueName;
408 Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey,
409 &DeleteValueKeyInfo);
410 if (NT_SUCCESS(Status))
411 {
412 /* Call the internal API */
413 Status = CmDeleteValueKey(KeyObject->KeyControlBlock, *ValueName);
414
415 /* Do the post callback */
416 PostOperationInfo.Object = (PVOID)KeyObject;
417 PostOperationInfo.Status = Status;
418 CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey,
419 &PostOperationInfo);
420 }
421
422 /* Dereference the key body and synchronize the hives */
423 ObDereferenceObject(KeyObject);
424 CmpLazyFlush();
425 return Status;
426 }
427
428 NTSTATUS
429 NTAPI
430 NtFlushKey(IN HANDLE KeyHandle)
431 {
432 NTSTATUS Status;
433 PKEY_OBJECT KeyObject;
434 PAGED_CODE();
435
436 /* Get the key object */
437 Status = ObReferenceObjectByHandle(KeyHandle,
438 0,
439 CmpKeyObjectType,
440 ExGetPreviousMode(),
441 (PVOID*)&KeyObject,
442 NULL);
443 if (!NT_SUCCESS(Status)) return Status;
444
445 /* Lock the registry */
446 KeEnterCriticalRegion();
447 ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
448
449 /* Make sure KCB isn't deleted */
450 if (KeyObject->KeyControlBlock->Delete)
451 {
452 /* Fail */
453 Status = STATUS_KEY_DELETED;
454 }
455 else
456 {
457 /* Call the internal API */
458 Status = CmFlushKey(KeyObject->KeyControlBlock, FALSE);
459 }
460
461 /* Release the lock */
462 ExReleaseResourceLite(&CmpRegistryLock);
463 KeLeaveCriticalRegion();
464
465 /* Dereference the object and return status */
466 ObDereferenceObject(KeyObject);
467 return Status;
468 }
469
470 NTSTATUS
471 NTAPI
472 NtCompactKeys(IN ULONG Count,
473 IN PHANDLE KeyArray)
474 {
475 UNIMPLEMENTED;
476 return STATUS_NOT_IMPLEMENTED;
477 }
478
479 NTSTATUS
480 NTAPI
481 NtCompressKey(IN HANDLE Key)
482 {
483 UNIMPLEMENTED;
484 return STATUS_NOT_IMPLEMENTED;
485 }
486
487 NTSTATUS
488 NTAPI
489 NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
490 IN POBJECT_ATTRIBUTES FileObjectAttributes)
491 {
492 return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
493 }
494
495 NTSTATUS
496 NTAPI
497 NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
498 IN POBJECT_ATTRIBUTES FileObjectAttributes,
499 IN ULONG Flags)
500 {
501 return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL);
502 }
503
504 NTSTATUS
505 NTAPI
506 CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
507 IN POBJECT_ATTRIBUTES SourceFile,
508 IN ULONG Flags,
509 IN PKEY_OBJECT KeyBody);
510
511 NTSTATUS
512 NTAPI
513 NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
514 IN POBJECT_ATTRIBUTES SourceFile,
515 IN ULONG Flags,
516 IN HANDLE TrustClassKey)
517 {
518 NTSTATUS Status;
519 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
520 PKEY_OBJECT KeyBody = NULL;
521 PAGED_CODE();
522
523 /* Validate flags */
524 if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
525
526 /* Validate privilege */
527 if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
528 {
529 /* Fail */
530 DPRINT1("Restore Privilege missing!\n");
531 //return STATUS_PRIVILEGE_NOT_HELD;
532 }
533
534 /* Block APCs */
535 KeEnterCriticalRegion();
536
537 /* Check if we have a trust class */
538 if (TrustClassKey)
539 {
540 /* Reference it */
541 Status = ObReferenceObjectByHandle(TrustClassKey,
542 0,
543 CmpKeyObjectType,
544 PreviousMode,
545 (PVOID *)&KeyBody,
546 NULL);
547 }
548
549 /* Call the internal API */
550 Status = CmLoadKey(TargetKey, SourceFile, Flags, KeyBody);
551
552 /* Dereference the trust key, if any */
553 if (KeyBody) ObDereferenceObject(KeyBody);
554
555 /* Bring back APCs */
556 KeLeaveCriticalRegion();
557
558 /* Return status */
559 return Status;
560 }
561
562 NTSTATUS
563 NTAPI
564 NtLockProductActivationKeys(IN PULONG pPrivateVer,
565 IN PULONG pSafeMode)
566 {
567 UNIMPLEMENTED;
568 return STATUS_NOT_IMPLEMENTED;
569 }
570
571 NTSTATUS
572 NTAPI
573 NtLockRegistryKey(IN HANDLE KeyHandle)
574 {
575 UNIMPLEMENTED;
576 return STATUS_NOT_IMPLEMENTED;
577 }
578
579 NTSTATUS
580 NTAPI
581 NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle,
582 IN ULONG Count,
583 IN POBJECT_ATTRIBUTES SlaveObjects,
584 IN HANDLE Event,
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,
590 OUT PVOID Buffer,
591 IN ULONG Length,
592 IN BOOLEAN Asynchronous)
593 {
594 UNIMPLEMENTED;
595 return STATUS_NOT_IMPLEMENTED;
596 }
597
598 NTSTATUS
599 NTAPI
600 NtNotifyChangeKey(IN HANDLE KeyHandle,
601 IN HANDLE Event,
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,
607 OUT PVOID Buffer,
608 IN ULONG Length,
609 IN BOOLEAN Asynchronous)
610 {
611 return NtNotifyChangeMultipleKeys(KeyHandle,
612 0,
613 NULL,
614 Event,
615 ApcRoutine,
616 ApcContext,
617 IoStatusBlock,
618 CompletionFilter,
619 WatchTree,
620 Buffer,
621 Length,
622 Asynchronous);
623 }
624
625 NTSTATUS
626 NTAPI
627 NtQueryMultipleValueKey(IN HANDLE KeyHandle,
628 IN OUT PKEY_VALUE_ENTRY ValueList,
629 IN ULONG NumberOfValues,
630 OUT PVOID Buffer,
631 IN OUT PULONG Length,
632 OUT PULONG ReturnLength)
633 {
634 UNIMPLEMENTED;
635 return STATUS_NOT_IMPLEMENTED;
636 }
637
638 NTSTATUS
639 NTAPI
640 NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
641 IN ULONG HandleCount)
642 {
643 UNIMPLEMENTED;
644 return STATUS_NOT_IMPLEMENTED;
645 }
646
647 NTSTATUS
648 NTAPI
649 NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey,
650 IN ULONG BufferLength,
651 IN PVOID Buffer,
652 IN PULONG RequiredSize)
653 {
654 UNIMPLEMENTED;
655 return STATUS_NOT_IMPLEMENTED;
656 }
657
658 NTSTATUS
659 NTAPI
660 NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes,
661 IN HANDLE Key,
662 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
663 {
664 UNIMPLEMENTED;
665 return STATUS_NOT_IMPLEMENTED;
666 }
667
668 NTSTATUS
669 NTAPI
670 NtRestoreKey(IN HANDLE KeyHandle,
671 IN HANDLE FileHandle,
672 IN ULONG RestoreFlags)
673 {
674 UNIMPLEMENTED;
675 return STATUS_NOT_IMPLEMENTED;
676 }
677
678 NTSTATUS
679 NTAPI
680 NtSaveKey(IN HANDLE KeyHandle,
681 IN HANDLE FileHandle)
682 {
683 UNIMPLEMENTED;
684 return STATUS_NOT_IMPLEMENTED;
685 }
686
687 NTSTATUS
688 NTAPI
689 NtSaveKeyEx(IN HANDLE KeyHandle,
690 IN HANDLE FileHandle,
691 IN ULONG Flags)
692 {
693 UNIMPLEMENTED;
694 return STATUS_NOT_IMPLEMENTED;
695 }
696
697 NTSTATUS
698 NTAPI
699 NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle,
700 IN HANDLE LowPrecedenceKeyHandle,
701 IN HANDLE FileHandle)
702 {
703 UNIMPLEMENTED;
704 return STATUS_NOT_IMPLEMENTED;
705 }
706
707 NTSTATUS
708 NTAPI
709 NtSetInformationKey(IN HANDLE KeyHandle,
710 IN KEY_SET_INFORMATION_CLASS KeyInformationClass,
711 IN PVOID KeyInformation,
712 IN ULONG KeyInformationLength)
713 {
714 UNIMPLEMENTED;
715 return STATUS_NOT_IMPLEMENTED;
716 }
717
718 NTSTATUS
719 NTAPI
720 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes)
721 {
722 UNIMPLEMENTED;
723 return STATUS_NOT_IMPLEMENTED;
724 }
725
726 NTSTATUS
727 NTAPI
728 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
729 IN ULONG Flags)
730 {
731 UNIMPLEMENTED;
732 return STATUS_NOT_IMPLEMENTED;
733 }
734
735 NTSTATUS
736 NTAPI
737 NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
738 IN HANDLE Event)
739 {
740 UNIMPLEMENTED;
741 return STATUS_NOT_IMPLEMENTED;
742 }
743
744 /* EOF */