ReactOS 0.4.15-dev-7788-g1ad9096
cmapi.c
Go to the documentation of this file.
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 * Eric Kohl
8 * Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 */
10
11/* INCLUDES ******************************************************************/
12
13#include "ntoskrnl.h"
14#define NDEBUG
15#include "debug.h"
16
17/* FUNCTIONS *****************************************************************/
18
22 IN POBJECT_ATTRIBUTES SourceFile,
23 OUT PCMHIVE *CmHive)
24{
26 PCM_KEY_BODY KeyBody;
27 PCMHIVE Hive;
29 PAGED_CODE();
30
31 /* Sanity check */
33
34 /* Reference the handle */
36 0,
39 (PVOID)&KeyBody,
40 NULL);
41 if (!NT_SUCCESS(Status)) return Loaded;
42
43 /* Don't touch deleted KCBs */
44 if (KeyBody->KeyControlBlock->Delete) return Loaded;
45
46 Hive = CONTAINING_RECORD(KeyBody->KeyControlBlock->KeyHive, CMHIVE, Hive);
47
48 /* Must be the root key */
49 if (!(KeyBody->KeyControlBlock->Flags & KEY_HIVE_ENTRY) ||
50 !(Hive->FileUserName.Buffer))
51 {
52 /* It isn't */
53 ObDereferenceObject(KeyBody);
54 return Loaded;
55 }
56
57 /* Now compare the name of the file */
59 SourceFile->ObjectName,
60 TRUE))
61 {
62 /* Same file found */
63 Loaded = TRUE;
64 *CmHive = Hive;
65
66 /* If the hive is frozen, not sure what to do */
67 if (Hive->Frozen)
68 {
69 /* FIXME: TODO */
70 UNIMPLEMENTED_DBGBREAK("ERROR: Hive is frozen\n");
71 }
72 }
73
74 /* Dereference and return result */
75 ObDereferenceObject(KeyBody);
76 return Loaded;
77 }
78
82{
83 PLIST_ENTRY NextEntry;
84 PCMHIVE Hive;
87
88 /* Make sure that the registry isn't read-only now */
89 if (CmpNoWrite) return TRUE;
90
91 /* Otherwise, acquire the hive list lock and disable force flush */
94
95 /* Loop the hive list */
96 NextEntry = CmpHiveListHead.Flink;
97 while (NextEntry != &CmpHiveListHead)
98 {
99 /* Get the hive */
100 Hive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList);
101 if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))
102 {
103 /* Acquire the flusher lock */
105
106 /* Check for illegal state */
107 if (ForceFlush && Hive->UseCount)
108 {
109 /* Registry needs to be locked down */
111 UNIMPLEMENTED_DBGBREAK("FIXME: Hive is damaged and needs fixup\n");
112 }
113
114 /* Only sync if we are forced to or if it won't cause a hive shrink */
115 if (ForceFlush || !HvHiveWillShrink(&Hive->Hive))
116 {
117 /* Do the sync */
118 Status = HvSyncHive(&Hive->Hive);
119
120 /* If something failed - set the flag and continue looping */
121 if (!NT_SUCCESS(Status))
122 Result = FALSE;
123 }
124 else
125 {
126 /* We won't flush if the hive might shrink */
127 Result = FALSE;
129 }
130
131 /* Release the flusher lock */
133 }
134
135 /* Try the next entry */
136 NextEntry = NextEntry->Flink;
137 }
138
139 /* Release lock and return */
141 return Result;
142}
143
145NTAPI
149 IN ULONG Index,
150 IN ULONG Type,
151 IN PVOID Data,
153 IN ULONG StorageType,
154 IN ULONG SmallData)
155{
156 PCELL_DATA CellData;
157 HCELL_INDEX ValueCell;
159
160 /* Check if we already have a value list */
161 if (Parent->ValueList.Count)
162 {
163 /* Then make sure it's valid and dirty it */
164 ASSERT(Parent->ValueList.List != HCELL_NIL);
165 if (!HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE))
166 {
167 /* Fail if we're out of space for log changes */
168 return STATUS_NO_LOG_SPACE;
169 }
170 }
171
172 /* Allocate a value cell */
173 ValueCell = HvAllocateCell(Hive,
175 CmpNameSize(Hive, ValueName),
176 StorageType,
177 HCELL_NIL);
178 if (ValueCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
179
180 /* Get the actual data for it */
181 CellData = HvGetCell(Hive, ValueCell);
182 ASSERT(CellData);
183
184 /* Now we can release it, make sure it's also dirty */
185 HvReleaseCell(Hive, ValueCell);
186 ASSERT(HvIsCellDirty(Hive, ValueCell));
187
188 /* Set it up and copy the name */
191 {
192 /* This can crash since the name is coming from user-mode */
193 CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
194 CellData->u.KeyValue.Name,
195 ValueName);
196 }
198 {
199 /* Fail */
200 DPRINT1("Invalid user data!\n");
201 HvFreeCell(Hive, ValueCell);
203 }
204 _SEH2_END;
205
206 /* Check for compressed name */
207 if (CellData->u.KeyValue.NameLength < ValueName->Length)
208 {
209 /* This is a compressed name */
210 CellData->u.KeyValue.Flags = VALUE_COMP_NAME;
211 }
212 else
213 {
214 /* No flags to set */
215 CellData->u.KeyValue.Flags = 0;
216 }
217
218 /* Check if this is a normal key */
220 {
221 /* Build a data cell for it */
223 Data,
224 DataSize,
225 StorageType,
226 ValueCell,
227 &CellData->u.KeyValue.Data);
228 if (!NT_SUCCESS(Status))
229 {
230 /* We failed, free the cell */
231 HvFreeCell(Hive, ValueCell);
232 return Status;
233 }
234
235 /* Otherwise, set the data length, and make sure the data is dirty */
236 CellData->u.KeyValue.DataLength = DataSize;
237 ASSERT(HvIsCellDirty(Hive, CellData->u.KeyValue.Data));
238 }
239 else
240 {
241 /* This is a small key, set the data directly inside */
243 CellData->u.KeyValue.Data = SmallData;
244 }
245
246 /* Set the type now */
247 CellData->u.KeyValue.Type = Type;
248
249 /* Add this value cell to the child list */
251 ValueCell,
252 Index,
253 StorageType,
254 &Parent->ValueList);
255
256 /* If we failed, free the entire cell, including the data */
257 if (!NT_SUCCESS(Status))
258 {
259 /* Overwrite the status with a known one */
260 CmpFreeValue(Hive, ValueCell);
262 }
263
264 /* Return Status */
265 return Status;
266}
267
269NTAPI
271 IN HCELL_INDEX OldChild,
273 IN ULONG Type,
274 IN PVOID Data,
276 IN ULONG StorageType,
277 IN ULONG TempData)
278{
279 HCELL_INDEX DataCell, NewCell;
280 PCELL_DATA CellData;
282 BOOLEAN WasSmall, IsSmall;
283
284 /* Registry writes must be blocked */
286
287 /* Mark the old child cell dirty */
288 if (!HvMarkCellDirty(Hive, OldChild, FALSE)) return STATUS_NO_LOG_SPACE;
289
290 /* See if this is a small or normal key */
291 WasSmall = CmpIsKeyValueSmall(&Length, Value->DataLength);
292
293 /* See if our new data can fit in a small key */
294 IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
295
296 /* Big keys are unsupported */
299
300 /* Mark the old value dirty */
302
303 /* Check if we have a small key */
304 if (IsSmall)
305 {
306 /* Check if we had a normal key with some data in it */
307 if (!(WasSmall) && (Length > 0))
308 {
309 /* Free the previous data */
310 CmpFreeValueData(Hive, Value->Data, Length);
311 }
312
313 /* Write our data directly */
315 Value->Data = TempData;
316 Value->Type = Type;
317 return STATUS_SUCCESS;
318 }
319
320 /* We have a normal key. Was the old cell also normal and had data? */
321 if (!(WasSmall) && (Length > 0))
322 {
323 /* Get the current data cell and actual data inside it */
324 DataCell = Value->Data;
325 ASSERT(DataCell != HCELL_NIL);
326 CellData = HvGetCell(Hive, DataCell);
327 if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
328
329 /* Immediately release the cell */
330 HvReleaseCell(Hive, DataCell);
331
332 /* Make sure that the data cell actually has a size */
333 ASSERT(HvGetCellSize(Hive, CellData) > 0);
334
335 /* Check if the previous data cell could fit our new data */
336 if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData)))
337 {
338 /* Re-use it then */
339 NewCell = DataCell;
340 }
341 else
342 {
343 /* Otherwise, re-allocate the current data cell */
344 NewCell = HvReallocateCell(Hive, DataCell, DataSize);
345 if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
346 }
347 }
348 else
349 {
350 /* This was a small key, or a key with no data, allocate a cell */
351 NewCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
352 if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
353 }
354
355 /* Now get the actual data for our data cell */
356 CellData = HvGetCell(Hive, NewCell);
357 ASSERT(CellData);
358
359 /* Release it immediately */
360 HvReleaseCell(Hive, NewCell);
361
362 /* Copy our data into the data cell's buffer, and set up the value */
363 RtlCopyMemory(CellData, Data, DataSize);
364 Value->Data = NewCell;
365 Value->DataLength = DataSize;
366 Value->Type = Type;
367
368 /* Return success */
369 ASSERT(HvIsCellDirty(Hive, NewCell));
370 return STATUS_SUCCESS;
371}
372
374NTAPI
378 IN OUT PVOID KeyInformation,
381{
383 ULONG Size, SizeLeft, MinimumSize, Offset;
384 PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
385 USHORT NameLength;
387
388 /* Check if the value is compressed */
389 if (Node->Flags & KEY_COMP_NAME)
390 {
391 /* Get the compressed name size */
392 NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
393 }
394 else
395 {
396 /* Get the real size */
397 NameLength = Node->NameLength;
398 }
399
400 /* Check what kind of information is being requested */
401 switch (KeyInformationClass)
402 {
403 /* Basic information */
405
406 /* This is the size we need */
408
409 /* And this is the minimum we can work with */
411
412 /* Let the caller know and assume success */
415
416 /* Check if the bufer we got is too small */
417 if (Length < MinimumSize)
418 {
419 /* Let the caller know and fail */
421 break;
422 }
423
424 /* Copy the basic information */
425 Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
426 Info->KeyBasicInformation.TitleIndex = 0;
427 Info->KeyBasicInformation.NameLength = NameLength;
428
429 /* Only the name is left */
430 SizeLeft = Length - MinimumSize;
431 Size = NameLength;
432
433 /* Check if we don't have enough space for the name */
434 if (SizeLeft < Size)
435 {
436 /* Truncate the name we'll return, and tell the caller */
437 Size = SizeLeft;
439 }
440
441 /* Check if this is a compressed key */
442 if (Node->Flags & KEY_COMP_NAME)
443 {
444 /* Copy the compressed name */
445 CmpCopyCompressedName(Info->KeyBasicInformation.Name,
446 SizeLeft,
447 Node->Name,
448 Node->NameLength);
449 }
450 else
451 {
452 /* Otherwise, copy the raw name */
453 RtlCopyMemory(Info->KeyBasicInformation.Name,
454 Node->Name,
455 Size);
456 }
457 break;
458
459 /* Node information */
461
462 /* Calculate the size we need */
464 NameLength +
465 Node->ClassLength;
466
467 /* And the minimum size we can support */
468 MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
469
470 /* Return the size to the caller and assume succes */
473
474 /* Check if the caller's buffer is too small */
475 if (Length < MinimumSize)
476 {
477 /* Let them know, and fail */
479 break;
480 }
481
482 /* Copy the basic information */
483 Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
484 Info->KeyNodeInformation.TitleIndex = 0;
485 Info->KeyNodeInformation.ClassLength = Node->ClassLength;
486 Info->KeyNodeInformation.NameLength = NameLength;
487
488 /* Now the name is left */
489 SizeLeft = Length - MinimumSize;
490 Size = NameLength;
491
492 /* Check if the name can fit entirely */
493 if (SizeLeft < Size)
494 {
495 /* It can't, we'll have to truncate. Tell the caller */
496 Size = SizeLeft;
498 }
499
500 /* Check if the key node name is compressed */
501 if (Node->Flags & KEY_COMP_NAME)
502 {
503 /* Copy the compressed name */
504 CmpCopyCompressedName(Info->KeyNodeInformation.Name,
505 SizeLeft,
506 Node->Name,
507 Node->NameLength);
508 }
509 else
510 {
511 /* It isn't, so copy the raw name */
512 RtlCopyMemory(Info->KeyNodeInformation.Name,
513 Node->Name,
514 Size);
515 }
516
517 /* Check if the node has a class */
518 if (Node->ClassLength > 0)
519 {
520 /* Set the class offset */
522 Offset = ALIGN_UP_BY(Offset, sizeof(ULONG));
523 Info->KeyNodeInformation.ClassOffset = Offset;
524
525 /* Get the class data */
526 ClassData = HvGetCell(Hive, Node->Class);
527 if (ClassData == NULL)
528 {
530 break;
531 }
532
533 /* Check if we can copy anything */
534 if (Length > Offset)
535 {
536 /* Copy the class data */
538 ClassData,
539 min(Node->ClassLength, Length - Offset));
540 }
541
542 /* Check if the buffer was large enough */
543 if (Length < Offset + Node->ClassLength)
544 {
546 }
547
548 /* Release the class cell */
549 HvReleaseCell(Hive, Node->Class);
550 }
551 else
552 {
553 /* It doesn't, so set offset to -1, not 0! */
554 Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
555 }
556 break;
557
558 /* Full information requsted */
560
561 /* This is the size we need */
563 Node->ClassLength;
564
565 /* This is what we can work with */
567
568 /* Return it to caller and assume success */
571
572 /* Check if the caller's buffer is to small */
573 if (Length < MinimumSize)
574 {
575 /* Let them know and fail */
577 break;
578 }
579
580 /* Now copy all the basic information */
581 Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
582 Info->KeyFullInformation.TitleIndex = 0;
583 Info->KeyFullInformation.ClassLength = Node->ClassLength;
584 Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[Stable] +
585 Node->SubKeyCounts[Volatile];
586 Info->KeyFullInformation.Values = Node->ValueList.Count;
587 Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
588 Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
589 Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
590 Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
591
592 /* Check if we have a class */
593 if (Node->ClassLength > 0)
594 {
595 /* Set the class offset */
597 Info->KeyFullInformation.ClassOffset = Offset;
598
599 /* Get the class data */
600 ClassData = HvGetCell(Hive, Node->Class);
601 if (ClassData == NULL)
602 {
604 break;
605 }
606
607 /* Copy the class data */
608 ASSERT(Length >= Offset);
609 RtlCopyMemory(Info->KeyFullInformation.Class,
610 ClassData,
611 min(Node->ClassLength, Length - Offset));
612
613 /* Check if the buffer was large enough */
614 if (Length < Offset + Node->ClassLength)
615 {
617 }
618
619 /* Release the class cell */
620 HvReleaseCell(Hive, Node->Class);
621 }
622 else
623 {
624 /* We don't have a class, so set offset to -1, not 0! */
625 Info->KeyFullInformation.ClassOffset = 0xFFFFFFFF;
626 }
627 break;
628
629 /* Any other class that got sent here is invalid! */
630 default:
631
632 /* Set failure code */
634 break;
635 }
636
637 /* Return status */
638 return Status;
639}
640
642NTAPI
645 IN ULONG Type,
646 IN PVOID Data,
648{
649 PHHIVE Hive = NULL;
652 HCELL_INDEX CurrentChild, Cell;
655 ULONG Count, ChildIndex, SmallData, Storage;
656 VALUE_SEARCH_RETURN_TYPE SearchResult;
657 BOOLEAN FirstTry = TRUE, FlusherLocked = FALSE;
658 HCELL_INDEX ParentCell = HCELL_NIL, ChildCell = HCELL_NIL;
659
660 /* Acquire hive and KCB lock */
663
664 /* Sanity check */
665 ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL);
666
667 /* Don't touch deleted KCBs */
668DoAgain:
669 if (Kcb->Delete)
670 {
671 /* Fail */
673 goto Quickie;
674 }
675
676 /* Don't let anyone mess with symlinks */
677 if ((Kcb->Flags & KEY_SYM_LINK) &&
678 ((Type != REG_LINK) ||
679 !(ValueName) ||
681 {
682 /* Invalid modification of a symlink key */
684 goto Quickie;
685 }
686
687 /* Check if this is the first attempt */
688 if (FirstTry)
689 {
690 /* Search for the value in the cache */
691 SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb,
692 ValueName,
693 Type,
694 Data,
695 DataLength);
696 if (SearchResult == SearchNeedExclusiveLock)
697 {
698 /* Try again with the exclusive lock */
700 goto DoAgain;
701 }
702 else if (SearchResult == SearchSuccess)
703 {
704 /* We don't actually need to do anything! */
706 goto Quickie;
707 }
708
709 /* We need the exclusive KCB lock now */
710 if (!CmpIsKcbLockedExclusive(Kcb) &&
712 {
713 /* Acquire exclusive lock */
715 }
716
717 /* Cache lookup failed, so don't try it next time */
718 FirstTry = FALSE;
719
720 /* Now grab the flush lock since the key will be modified */
721 ASSERT(FlusherLocked == FALSE);
722 CmpLockHiveFlusherShared((PCMHIVE)Kcb->KeyHive);
723 FlusherLocked = TRUE;
724 goto DoAgain;
725 }
726 else
727 {
728 /* Get pointer to key cell */
729 Hive = Kcb->KeyHive;
730 Cell = Kcb->KeyCell;
731
732 /* Get the parent */
733 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
734 ASSERT(Parent);
735 ParentCell = Cell;
736
737 /* Prepare to scan the key node */
738 Count = Parent->ValueList.Count;
739 Found = FALSE;
740 if (Count > 0)
741 {
742 /* Try to find the existing name */
744 &Parent->ValueList,
745 ValueName,
746 &ChildIndex,
747 &CurrentChild);
748 if (!Result)
749 {
750 /* Fail */
752 goto Quickie;
753 }
754
755 /* Check if we found something */
756 if (CurrentChild != HCELL_NIL)
757 {
758 /* Release existing child */
759 if (ChildCell != HCELL_NIL)
760 {
761 HvReleaseCell(Hive, ChildCell);
762 ChildCell = HCELL_NIL;
763 }
764
765 /* Get its value */
766 Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild);
767 if (!Value)
768 {
769 /* Fail */
771 goto Quickie;
772 }
773
774 /* Remember that we found it */
775 ChildCell = CurrentChild;
776 Found = TRUE;
777 }
778 }
779 else
780 {
781 /* No child list, we'll need to add it */
782 ChildIndex = 0;
783 }
784 }
785
786 /* Should only get here on the second pass */
788
789 /* The KCB must be locked exclusive at this point */
791
792 /* Mark the cell dirty */
793 if (!HvMarkCellDirty(Hive, Cell, FALSE))
794 {
795 /* Not enough log space, fail */
797 goto Quickie;
798 }
799
800 /* Get the storage type */
801 Storage = HvGetCellType(Cell);
802
803 /* Check if this is small data */
804 SmallData = 0;
805 if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0))
806 {
807 /* Need SEH because user data may be invalid */
809 {
810 /* Copy it */
811 RtlCopyMemory(&SmallData, Data, DataLength);
812 }
814 {
815 /* Return failure code */
817 _SEH2_YIELD(goto Quickie);
818 }
819 _SEH2_END;
820 }
821
822 /* Check if we didn't find a matching key */
823 if (!Found)
824 {
825 /* Call the internal routine */
827 Parent,
828 ValueName,
829 ChildIndex,
830 Type,
831 Data,
833 Storage,
834 SmallData);
835 }
836 else
837 {
838 /* Call the internal routine */
840 CurrentChild,
841 Value,
842 Type,
843 Data,
845 Storage,
846 SmallData);
847 }
848
849 /* Check for success */
850 if (NT_SUCCESS(Status))
851 {
852 /* Check if the maximum value name length changed */
853 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
854 if (Parent->MaxValueNameLen < ValueName->Length)
855 {
856 /* Set the new values */
857 Parent->MaxValueNameLen = ValueName->Length;
858 Kcb->KcbMaxValueNameLen = ValueName->Length;
859 }
860
861 /* Check if the maximum data length changed */
862 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
863 if (Parent->MaxValueDataLen < DataLength)
864 {
865 /* Update it */
866 Parent->MaxValueDataLen = DataLength;
867 Kcb->KcbMaxValueDataLen = Parent->MaxValueDataLen;
868 }
869
870 /* Save the write time */
871 KeQuerySystemTime(&Parent->LastWriteTime);
872 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
873
874 /* Check if the cell is cached */
875 if (Found && CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))
876 {
877 /* Shouldn't happen */
878 ASSERT(FALSE);
879 }
880 else
881 {
882 /* Cleanup the value cache */
884
885 /* Sanity checks */
886 ASSERT(!CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList));
887 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
888
889 /* Set the value cache */
890 Kcb->ValueCache.Count = Parent->ValueList.Count;
891 Kcb->ValueCache.ValueList = Parent->ValueList.List;
892 }
893
894 /* Notify registered callbacks */
895 CmpReportNotify(Kcb,
896 Hive,
897 Kcb->KeyCell,
899 }
900
901 /* Release the cells */
902Quickie:
903 if ((ParentCell != HCELL_NIL) && Hive) HvReleaseCell(Hive, ParentCell);
904 if ((ChildCell != HCELL_NIL) && Hive) HvReleaseCell(Hive, ChildCell);
905
906 /* Release the locks */
907 if (FlusherLocked) CmpUnlockHiveFlusher((PCMHIVE)Hive);
910 return Status;
911}
912
914NTAPI
917{
919 PHHIVE Hive;
921 HCELL_INDEX ChildCell, Cell;
924 ULONG ChildIndex;
926
927 /* Acquire hive lock */
929
930 /* Lock KCB exclusively */
932
933 /* Don't touch deleted keys */
934 if (Kcb->Delete)
935 {
936 /* Undo everything */
939 return STATUS_KEY_DELETED;
940 }
941
942 /* Get the hive and the cell index */
943 Hive = Kcb->KeyHive;
944 Cell = Kcb->KeyCell;
945
946 /* Lock flushes */
948
949 /* Get the parent key node */
950 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
951 ASSERT(Parent);
952
953 /* Get the value list and check if it has any entries */
954 ChildList = &Parent->ValueList;
955 if (ChildList->Count)
956 {
957 /* Try to find this value */
959 ChildList,
960 &ValueName,
961 &ChildIndex,
962 &ChildCell);
963 if (!Result)
964 {
965 /* Fail */
967 goto Quickie;
968 }
969
970 /* Value not found, return error */
971 if (ChildCell == HCELL_NIL) goto Quickie;
972
973 /* We found the value, mark all relevant cells dirty */
974 if (!(HvMarkCellDirty(Hive, Cell, FALSE) &&
975 HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE) &&
976 HvMarkCellDirty(Hive, ChildCell, FALSE)))
977 {
978 /* Not enough log space, fail */
980 goto Quickie;
981 }
982
983 /* Get the key value */
984 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ChildCell);
985 ASSERT(Value);
986
987 /* Mark it and all related data as dirty */
988 if (!CmpMarkValueDataDirty(Hive, Value))
989 {
990 /* Not enough log space, fail */
992 goto Quickie;
993 }
994
995 /* Sanity checks */
996 ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
997 ASSERT(HvIsCellDirty(Hive, ChildCell));
998
999 /* Remove the value from the child list */
1000 Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 /* Set known error */
1005 goto Quickie;
1006 }
1007
1008 /* Remove the value and its data itself */
1009 if (!CmpFreeValue(Hive, ChildCell))
1010 {
1011 /* Failed to free the value, fail */
1013 goto Quickie;
1014 }
1015
1016 /* Set the last write time */
1017 KeQuerySystemTime(&Parent->LastWriteTime);
1018 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
1019
1020 /* Sanity check */
1021 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1022 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1023 ASSERT(HvIsCellDirty(Hive, Cell));
1024
1025 /* Check if the value list is empty now */
1026 if (!Parent->ValueList.Count)
1027 {
1028 /* Then clear key node data */
1029 Parent->MaxValueNameLen = 0;
1030 Parent->MaxValueDataLen = 0;
1031 Kcb->KcbMaxValueNameLen = 0;
1032 Kcb->KcbMaxValueDataLen = 0;
1033 }
1034
1035 /* Cleanup the value cache */
1037
1038 /* Sanity checks */
1039 ASSERT(!CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList));
1040 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
1041
1042 /* Set the value cache */
1043 Kcb->ValueCache.Count = ChildList->Count;
1044 Kcb->ValueCache.ValueList = ChildList->List;
1045
1046 /* Notify registered callbacks */
1048
1049 /* Change default Status to success */
1051 }
1052
1053Quickie:
1054 /* Release the parent cell, if any */
1055 if (Parent) HvReleaseCell(Hive, Cell);
1056
1057 /* Check if we had a value */
1058 if (Value)
1059 {
1060 /* Release the child cell */
1061 ASSERT(ChildCell != HCELL_NIL);
1062 HvReleaseCell(Hive, ChildCell);
1063 }
1064
1065 /* Release locks */
1067 CmpReleaseKcbLock(Kcb);
1069 return Status;
1070}
1071
1073NTAPI
1077 IN PVOID KeyValueInformation,
1078 IN ULONG Length,
1080{
1083 ULONG Index;
1084 BOOLEAN ValueCached = FALSE;
1085 PCM_CACHED_VALUE *CachedValue;
1086 HCELL_INDEX CellToRelease;
1088 PHHIVE Hive;
1089 PAGED_CODE();
1090
1091 /* Acquire hive lock */
1093
1094 /* Lock the KCB shared */
1096
1097 /* Don't touch deleted keys */
1098DoAgain:
1099 if (Kcb->Delete)
1100 {
1101 /* Undo everything */
1102 CmpReleaseKcbLock(Kcb);
1104 return STATUS_KEY_DELETED;
1105 }
1106
1107 /* We don't deal with this yet */
1108 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1109 {
1110 /* Shouldn't happen */
1111 ASSERT(FALSE);
1112 }
1113
1114 /* Get the hive */
1115 Hive = Kcb->KeyHive;
1116
1117 /* Find the key value */
1119 &ValueName,
1120 &CachedValue,
1121 &Index,
1122 &ValueData,
1123 &ValueCached,
1124 &CellToRelease);
1126 {
1127 /* Check if we need an exclusive lock */
1128 ASSERT(CellToRelease == HCELL_NIL);
1129 ASSERT(ValueData == NULL);
1130
1131 /* Try with exclusive KCB lock */
1133 goto DoAgain;
1134 }
1135
1136 if (Result == SearchSuccess)
1137 {
1138 /* Sanity check */
1139 ASSERT(ValueData != NULL);
1140
1141 /* User data, protect against exceptions */
1142 _SEH2_TRY
1143 {
1144 /* Query the information requested */
1146 CachedValue,
1147 ValueData,
1148 ValueCached,
1150 KeyValueInformation,
1151 Length,
1153 &Status);
1155 {
1156 /* Release the value cell */
1157 if (CellToRelease != HCELL_NIL)
1158 {
1159 HvReleaseCell(Hive, CellToRelease);
1160 CellToRelease = HCELL_NIL;
1161 }
1162
1163 /* Try with exclusive KCB lock */
1165 _SEH2_YIELD(goto DoAgain);
1166 }
1167 }
1169 {
1171 }
1172 _SEH2_END;
1173 }
1174 else
1175 {
1176 /* Failed to find the value */
1178 }
1179
1180 /* If we have a cell to release, do so */
1181 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1182
1183 /* Release locks */
1184 CmpReleaseKcbLock(Kcb);
1186 return Status;
1187}
1188
1190NTAPI
1192 IN ULONG Index,
1194 IN PVOID KeyValueInformation,
1195 IN ULONG Length,
1197{
1199 PHHIVE Hive;
1201 HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL;
1203 BOOLEAN IndexIsCached, ValueIsCached = FALSE;
1204 PCELL_DATA CellData;
1205 PCM_CACHED_VALUE *CachedValue;
1207 PAGED_CODE();
1208
1209 /* Acquire hive lock */
1211
1212 /* Lock the KCB shared */
1214
1215 /* Don't touch deleted keys */
1216DoAgain:
1217 if (Kcb->Delete)
1218 {
1219 /* Undo everything */
1220 CmpReleaseKcbLock(Kcb);
1222 return STATUS_KEY_DELETED;
1223 }
1224
1225 /* Get the hive and parent */
1226 Hive = Kcb->KeyHive;
1227 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1228 ASSERT(Parent);
1229
1230 /* FIXME: Lack of cache? */
1231 if (Kcb->ValueCache.Count != Parent->ValueList.Count)
1232 {
1233 DPRINT1("HACK: Overriding value cache count\n");
1234 Kcb->ValueCache.Count = Parent->ValueList.Count;
1235 }
1236
1237 /* Make sure the index is valid */
1238 if (Index >= Kcb->ValueCache.Count)
1239 {
1240 /* Release the cell and fail */
1241 HvReleaseCell(Hive, Kcb->KeyCell);
1243 goto Quickie;
1244 }
1245
1246 /* We don't deal with this yet */
1247 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1248 {
1249 /* Shouldn't happen */
1250 ASSERT(FALSE);
1251 }
1252
1253 /* Find the value list */
1255 &CellData,
1256 &IndexIsCached,
1257 &CellToRelease);
1259 {
1260 /* Check if we need an exclusive lock */
1261 ASSERT(CellToRelease == HCELL_NIL);
1262 HvReleaseCell(Hive, Kcb->KeyCell);
1263
1264 /* Try with exclusive KCB lock */
1266 goto DoAgain;
1267 }
1268 else if (Result != SearchSuccess)
1269 {
1270 /* Sanity check */
1271 ASSERT(CellData == NULL);
1272
1273 /* Release the cell and fail */
1275 goto Quickie;
1276 }
1277
1278 /* Now get the key value */
1280 CellData,
1281 Index,
1282 &CachedValue,
1283 &ValueData,
1284 IndexIsCached,
1285 &ValueIsCached,
1286 &CellToRelease2);
1288 {
1289 /* Cleanup state */
1290 ASSERT(CellToRelease2 == HCELL_NIL);
1291 if (CellToRelease)
1292 {
1293 HvReleaseCell(Hive, CellToRelease);
1294 CellToRelease = HCELL_NIL;
1295 }
1296 HvReleaseCell(Hive, Kcb->KeyCell);
1297
1298 /* Try with exclusive KCB lock */
1300 goto DoAgain;
1301 }
1302 else if (Result != SearchSuccess)
1303 {
1304 /* Sanity check */
1305 ASSERT(ValueData == NULL);
1306
1307 /* Release the cells and fail */
1309 goto Quickie;
1310 }
1311
1312 /* User data, need SEH */
1313 _SEH2_TRY
1314 {
1315 /* Query the information requested */
1317 CachedValue,
1318 ValueData,
1319 ValueIsCached,
1321 KeyValueInformation,
1322 Length,
1324 &Status);
1326 {
1327 /* Cleanup state */
1328 if (CellToRelease2) HvReleaseCell(Hive, CellToRelease2);
1329 HvReleaseCell(Hive, Kcb->KeyCell);
1330 if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
1331
1332 /* Try with exclusive KCB lock */
1334 _SEH2_YIELD(goto DoAgain);
1335 }
1336 }
1338 {
1339 /* Get exception code */
1341 }
1342 _SEH2_END;
1343
1344Quickie:
1345 /* If we have a cell to release, do so */
1346 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1347
1348 /* Release the parent cell */
1349 HvReleaseCell(Hive, Kcb->KeyCell);
1350
1351 /* If we have a cell to release, do so */
1352 if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2);
1353
1354 /* Release locks */
1355 CmpReleaseKcbLock(Kcb);
1357 return Status;
1358}
1359
1360static
1364 _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo,
1367{
1369 PHHIVE KeyHive;
1370 HCELL_INDEX KeyCell;
1371 USHORT NameLength;
1372 PAGED_CODE();
1373
1374 /* Get the hive and cell index */
1375 KeyHive = Kcb->KeyHash.KeyHive;
1376 KeyCell = Kcb->KeyHash.KeyCell;
1377
1378#if DBG
1379 /* Get the cell node */
1380 Node = (PCM_KEY_NODE)HvGetCell(KeyHive, KeyCell);
1381 if (Node != NULL)
1382 {
1383 ULONG SubKeyCount;
1384 ASSERT(Node->ValueList.Count == Kcb->ValueCache.Count);
1385
1386 if (!(Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO))
1387 {
1388 SubKeyCount = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
1389 if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
1390 {
1391 ASSERT(SubKeyCount == 0);
1392 }
1393 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
1394 {
1395 ASSERT(SubKeyCount == 1);
1396 }
1397 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
1398 {
1399 ASSERT(SubKeyCount == Kcb->IndexHint->Count);
1400 }
1401 else
1402 {
1403 ASSERT(SubKeyCount == Kcb->SubKeyCount);
1404 }
1405 }
1406
1407 ASSERT(Node->LastWriteTime.QuadPart == Kcb->KcbLastWriteTime.QuadPart);
1408 ASSERT(Node->MaxNameLen == Kcb->KcbMaxNameLen);
1409 ASSERT(Node->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1410 ASSERT(Node->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1411
1412 /* Release the cell */
1413 HvReleaseCell(KeyHive, KeyCell);
1414 }
1415#endif // DBG
1416
1417 /* Make sure we have a name block */
1418 if (Kcb->NameBlock == NULL)
1419 {
1421 }
1422
1423 /* Check for compressed name */
1424 if (Kcb->NameBlock->Compressed)
1425 {
1426 /* Calculate the name size */
1427 NameLength = CmpCompressedNameSize(Kcb->NameBlock->NameHash.Name,
1428 Kcb->NameBlock->NameHash.NameLength);
1429 }
1430 else
1431 {
1432 /* Use the stored name size */
1433 NameLength = Kcb->NameBlock->NameHash.NameLength;
1434 }
1435
1436 /* Validate buffer length (we do not copy the name!) */
1437 *ResultLength = sizeof(*KeyCachedInfo);
1438 if (Length < *ResultLength)
1439 {
1441 }
1442
1443 /* Fill the structure */
1444 KeyCachedInfo->LastWriteTime = Kcb->KcbLastWriteTime;
1445 KeyCachedInfo->TitleIndex = 0;
1446 KeyCachedInfo->NameLength = NameLength;
1447 KeyCachedInfo->Values = Kcb->ValueCache.Count;
1448 KeyCachedInfo->MaxNameLen = Kcb->KcbMaxNameLen;
1449 KeyCachedInfo->MaxValueNameLen = Kcb->KcbMaxValueNameLen;
1450 KeyCachedInfo->MaxValueDataLen = Kcb->KcbMaxValueDataLen;
1451
1452 /* Check the ExtFlags for what we have */
1453 if (Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO)
1454 {
1455 /* Cache is not valid, do a full lookup */
1456 DPRINT1("Kcb cache incoherency detected, kcb = %p\n", Kcb);
1457
1458 /* Get the cell node */
1459 Node = (PCM_KEY_NODE)HvGetCell(KeyHive, KeyCell);
1460 if (Node == NULL)
1461 {
1463 }
1464
1465 /* Calculate number of subkeys */
1466 KeyCachedInfo->SubKeys = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
1467
1468 /* Release the cell */
1469 HvReleaseCell(KeyHive, KeyCell);
1470 }
1471 else if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
1472 {
1473 /* There are no subkeys */
1474 KeyCachedInfo->SubKeys = 0;
1475 }
1476 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
1477 {
1478 /* There is exactly one subley */
1479 KeyCachedInfo->SubKeys = 1;
1480 }
1481 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
1482 {
1483 /* Get the number of subkeys from the subkey hint */
1484 KeyCachedInfo->SubKeys = Kcb->IndexHint->Count;
1485 }
1486 else
1487 {
1488 /* No subkey hint, use the key count field */
1489 KeyCachedInfo->SubKeys = Kcb->SubKeyCount;
1490 }
1491
1492 return STATUS_SUCCESS;
1493}
1494
1495static
1499 _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo,
1502{
1503 /* Validate the buffer size */
1504 *ResultLength = sizeof(*KeyFlagsInfo);
1505 if (Length < *ResultLength)
1506 {
1508 }
1509
1510 /* Copy the user flags */
1511 KeyFlagsInfo->UserFlags = Kcb->KcbUserFlags;
1512
1513 return STATUS_SUCCESS;
1514}
1515
1516static
1520 _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo,
1523{
1524 ULONG NeededLength;
1525 PCM_KEY_CONTROL_BLOCK CurrentKcb;
1526
1527 NeededLength = 0;
1528 CurrentKcb = Kcb;
1529
1530 /* Count the needed buffer size */
1531 while (CurrentKcb)
1532 {
1533 if (CurrentKcb->NameBlock->Compressed)
1534 NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1535 else
1536 NeededLength += CurrentKcb->NameBlock->NameLength;
1537
1538 NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1539
1540 CurrentKcb = CurrentKcb->ParentKcb;
1541 }
1542
1543 _SEH2_TRY
1544 {
1548 if (Length < *ResultLength)
1549 {
1550 KeyNameInfo->NameLength = NeededLength;
1552 }
1553 }
1555 {
1557 }
1558 _SEH2_END;
1559
1560 /* Do the real copy */
1561 KeyNameInfo->NameLength = 0;
1562 CurrentKcb = Kcb;
1563
1564 _SEH2_TRY
1565 {
1566 while (CurrentKcb)
1567 {
1568 ULONG NameLength;
1569
1570 if (CurrentKcb->NameBlock->Compressed)
1571 {
1572 NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1573 /* Copy the compressed name */
1574 CmpCopyCompressedName(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1575 NameLength,
1576 CurrentKcb->NameBlock->Name,
1577 CurrentKcb->NameBlock->NameLength);
1578 }
1579 else
1580 {
1581 NameLength = CurrentKcb->NameBlock->NameLength;
1582 /* Otherwise, copy the raw name */
1583 RtlCopyMemory(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1584 CurrentKcb->NameBlock->Name,
1585 NameLength);
1586 }
1587
1588 NeededLength -= NameLength;
1589 NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1590 /* Add path separator */
1591 KeyNameInfo->Name[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1592 KeyNameInfo->NameLength += NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
1593
1594 CurrentKcb = CurrentKcb->ParentKcb;
1595 }
1596 }
1598 {
1600 }
1601 _SEH2_END;
1602
1603 /* Make sure we copied everything */
1604 ASSERT(NeededLength == 0);
1605 ASSERT(KeyNameInfo->Name[0] == OBJ_NAME_PATH_SEPARATOR);
1606
1607 /* We're done */
1608 return STATUS_SUCCESS;
1609}
1610
1611
1613NTAPI
1616 _Out_opt_ PVOID KeyInformation,
1619{
1621 PHHIVE Hive;
1623 HV_TRACK_CELL_REF CellReferences = {0};
1624
1625 /* Acquire hive lock */
1627
1628 /* Lock KCB shared */
1630
1631 /* Don't touch deleted keys */
1632 if (Kcb->Delete)
1633 {
1634 /* Fail */
1636 goto Quickie;
1637 }
1638
1639 /* Data can be user-mode, use SEH */
1640 _SEH2_TRY
1641 {
1642 /* Check what class we got */
1643 switch (KeyInformationClass)
1644 {
1645 /* Typical information */
1646 case KeyFullInformation:
1648 case KeyNodeInformation:
1649 {
1650 /* Get the hive and parent */
1651 Hive = Kcb->KeyHive;
1652 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1653 ASSERT(Parent);
1654
1655 /* Track cell references */
1656 if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
1657 {
1658 /* Not enough memory to track references */
1660 }
1661 else
1662 {
1663 /* Call the internal API */
1664 Status = CmpQueryKeyData(Hive,
1665 Parent,
1667 KeyInformation,
1668 Length,
1669 ResultLength);
1670 }
1671 break;
1672 }
1673
1675 {
1676 /* Call the internal API */
1678 KeyInformation,
1679 Length,
1680 ResultLength);
1681 break;
1682 }
1683
1685 {
1686 /* Call the internal API */
1688 KeyInformation,
1689 Length,
1690 ResultLength);
1691 break;
1692 }
1693
1694 case KeyNameInformation:
1695 {
1696 /* Call the internal API */
1698 KeyInformation,
1699 Length,
1700 ResultLength);
1701 break;
1702 }
1703
1704 /* Illegal classes */
1705 default:
1706 {
1707 /* Print message and fail */
1708 DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
1710 break;
1711 }
1712 }
1713 }
1715 {
1716 /* Fail with exception code */
1718 _SEH2_YIELD(goto Quickie);
1719 }
1720 _SEH2_END;
1721
1722Quickie:
1723 /* Release references */
1724 HvReleaseFreeCellRefArray(&CellReferences);
1725
1726 /* Release locks */
1727 CmpReleaseKcbLock(Kcb);
1729 return Status;
1730}
1731
1733NTAPI
1735 IN ULONG Index,
1737 IN PVOID KeyInformation,
1738 IN ULONG Length,
1740{
1742 PHHIVE Hive;
1744 HCELL_INDEX ChildCell;
1745 HV_TRACK_CELL_REF CellReferences = {0};
1746
1747 /* Acquire hive lock */
1749
1750 /* Lock the KCB shared */
1752
1753 /* Don't touch deleted keys */
1754 if (Kcb->Delete)
1755 {
1756 /* Undo everything */
1758 goto Quickie;
1759 }
1760
1761 /* Get the hive and parent */
1762 Hive = Kcb->KeyHive;
1763 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1764 ASSERT(Parent);
1765
1766 /* Get the child cell */
1767 ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
1768
1769 /* Release the parent cell */
1770 HvReleaseCell(Hive, Kcb->KeyCell);
1771
1772 /* Check if we found the child */
1773 if (ChildCell == HCELL_NIL)
1774 {
1775 /* We didn't, fail */
1777 goto Quickie;
1778 }
1779
1780 /* Now get the actual child node */
1781 Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
1782 ASSERT(Child);
1783
1784 /* Track references */
1785 if (!HvTrackCellRef(&CellReferences, Hive, ChildCell))
1786 {
1787 /* Can't allocate memory for tracking */
1789 goto Quickie;
1790 }
1791
1792 /* Data can be user-mode, use SEH */
1793 _SEH2_TRY
1794 {
1795 /* Query the data requested */
1796 Status = CmpQueryKeyData(Hive,
1797 Child,
1799 KeyInformation,
1800 Length,
1801 ResultLength);
1802 }
1804 {
1805 /* Fail with exception code */
1807 _SEH2_YIELD(goto Quickie);
1808 }
1809 _SEH2_END;
1810
1811Quickie:
1812 /* Release references */
1813 HvReleaseFreeCellRefArray(&CellReferences);
1814
1815 /* Release locks */
1816 CmpReleaseKcbLock(Kcb);
1818 return Status;
1819}
1820
1822NTAPI
1824{
1826 PHHIVE Hive;
1828 HCELL_INDEX Cell, ParentCell;
1830
1831 /* Acquire hive lock */
1833
1834 /* Get the kcb */
1835 Kcb = KeyBody->KeyControlBlock;
1836
1837 /* Don't allow deleting the root */
1838 if (!Kcb->ParentKcb)
1839 {
1840 /* Fail */
1842 return STATUS_CANNOT_DELETE;
1843 }
1844
1845 /* Lock parent and child */
1847
1848 /* Check if we're already being deleted */
1849 if (Kcb->Delete)
1850 {
1851 /* Don't do it twice */
1853 goto Quickie;
1854 }
1855
1856 /* Get the hive and node */
1857 Hive = Kcb->KeyHive;
1858 Cell = Kcb->KeyCell;
1859
1860 /* Lock flushes */
1862
1863 /* Get the key node */
1864 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1865 ASSERT(Node);
1866
1867 /* Sanity check */
1868 ASSERT(Node->Flags == Kcb->Flags);
1869
1870 /* Check if we don't have any children */
1871 if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]) &&
1872 !(Node->Flags & KEY_NO_DELETE))
1873 {
1874 /* Send notification to registered callbacks */
1875 CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_NAME);
1876
1877 /* Get the parent and free the cell */
1878 ParentCell = Node->Parent;
1879 Status = CmpFreeKeyByCell(Hive, Cell, TRUE);
1880 if (NT_SUCCESS(Status))
1881 {
1882 /* Flush any notifications */
1884
1885 /* Clean up information we have on the subkey */
1887
1888 /* Get the parent node */
1889 Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
1890 if (Parent)
1891 {
1892 /* Update the maximum name length */
1893 Kcb->ParentKcb->KcbMaxNameLen = (USHORT)Parent->MaxNameLen;
1894
1895 /* Make sure we're dirty */
1896 ASSERT(HvIsCellDirty(Hive, ParentCell));
1897
1898 /* Update the write time */
1899 KeQuerySystemTime(&Parent->LastWriteTime);
1900 Kcb->ParentKcb->KcbLastWriteTime = Parent->LastWriteTime;
1901
1902 /* Release the cell */
1903 HvReleaseCell(Hive, ParentCell);
1904 }
1905
1906 /* Set the KCB in delete mode and remove it */
1907 Kcb->Delete = TRUE;
1909
1910 /* Clear the cell */
1911 Kcb->KeyCell = HCELL_NIL;
1912 }
1913 }
1914 else
1915 {
1916 /* Fail */
1918 }
1919
1920 /* Release the cell */
1921 HvReleaseCell(Hive, Cell);
1922
1923 /* Release flush lock */
1925
1926 /* Release the KCB locks */
1927Quickie:
1928 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
1929
1930 /* Release hive lock */
1932 return Status;
1933}
1934
1936NTAPI
1939{
1940 PCMHIVE CmHive;
1941#if DBG
1942 CM_CHECK_REGISTRY_STATUS CheckStatus;
1943#endif
1945 PHHIVE Hive;
1946
1947 /* Ignore flushes until we're ready */
1948 if (CmpNoWrite) return STATUS_SUCCESS;
1949
1950 /* Get the hives */
1951 Hive = Kcb->KeyHive;
1952 CmHive = (PCMHIVE)Hive;
1953
1954 /* Check if this is the master hive */
1955 if (CmHive == CmiVolatileHive)
1956 {
1957 /* Flush all the hives instead */
1959 }
1960 else
1961 {
1962#if DBG
1963 /* Make sure the registry hive we're going to flush is OK */
1965 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
1966#endif
1967
1968 /* Don't touch the hive */
1970
1971 ASSERT(CmHive->ViewLock);
1974
1975 /* Will the hive shrink? */
1976 if (HvHiveWillShrink(Hive))
1977 {
1978 /* I don't believe the current Hv does shrinking */
1979 ASSERT(FALSE);
1980 // CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(CmHive);
1981 }
1982 else
1983 {
1984 /* Now we can release views */
1985 ASSERT(CmHive->ViewLock);
1986 // CMP_ASSERT_VIEW_LOCK_OWNED(CmHive);
1988 (CmHive->HiveIsLoading == TRUE) ||
1989 (CmHive->ViewLockOwner == KeGetCurrentThread()) ||
1991 CmHive->ViewLockOwner = NULL;
1993 }
1994
1995 /* Flush only this hive */
1996 if (!HvSyncHive(Hive))
1997 {
1998 /* Fail */
2000 }
2001
2002 /* Release the flush lock */
2003 CmpUnlockHiveFlusher(CmHive);
2004 }
2005
2006 /* Return the status */
2007 return Status;
2008}
2009
2011NTAPI
2013 IN POBJECT_ATTRIBUTES SourceFile,
2014 IN ULONG Flags,
2015 IN PCM_KEY_BODY KeyBody)
2016{
2017 SECURITY_QUALITY_OF_SERVICE ServiceQos;
2018 SECURITY_CLIENT_CONTEXT ClientSecurityContext;
2021 PCMHIVE CmHive, LoadedHive;
2023 CM_PARSE_CONTEXT ParseContext;
2024
2025 /* Check if we have a trust key */
2026 if (KeyBody)
2027 {
2028 /* Fail */
2029 DPRINT("Trusted classes not yet supported\n");
2030 }
2031
2032 /* Build a service QoS for a security context */
2033 ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2036 ServiceQos.EffectiveOnly = TRUE;
2038 &ServiceQos,
2039 FALSE,
2040 &ClientSecurityContext);
2041 if (!NT_SUCCESS(Status))
2042 {
2043 /* Fail */
2044 DPRINT1("Security context failed\n");
2045 return Status;
2046 }
2047
2048 /* Open the target key */
2049 RtlZeroMemory(&ParseContext, sizeof(ParseContext));
2050 ParseContext.CreateOperation = FALSE;
2051 Status = ObOpenObjectByName(TargetKey,
2053 KernelMode,
2054 NULL,
2055 KEY_READ,
2056 &ParseContext,
2057 &KeyHandle);
2059
2060 /* Open the hive */
2061 Status = CmpCmdHiveOpen(SourceFile,
2062 &ClientSecurityContext,
2063 &Allocate,
2064 &CmHive,
2066
2067 /* Get rid of the security context */
2068 SeDeleteClientSecurity(&ClientSecurityContext);
2069
2070 /* See if we failed */
2071 if (!NT_SUCCESS(Status))
2072 {
2073 /* See if the target already existed */
2074 if (KeyHandle)
2075 {
2076 /* Lock the registry */
2078
2079 /* Check if we are already loaded */
2080 if (CmpIsHiveAlreadyLoaded(KeyHandle, SourceFile, &LoadedHive))
2081 {
2082 /* That's okay then */
2083 ASSERT(LoadedHive);
2085 }
2086
2087 /* Release the registry */
2089 }
2090
2091 /* Close the key handle if we had one */
2093 return Status;
2094 }
2095
2096 /* Lock the registry shared */
2098
2099 /* Lock loading */
2101
2102 /* Lock the hive to this thread */
2103 CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING;
2104 CmHive->CreatorOwner = KeGetCurrentThread();
2105
2106 /* Set flag */
2108
2109 /* Link the hive */
2110 Status = CmpLinkHiveToMaster(TargetKey->ObjectName,
2111 TargetKey->RootDirectory,
2112 CmHive,
2113 Allocate,
2114 TargetKey->SecurityDescriptor);
2115 if (NT_SUCCESS(Status))
2116 {
2117 /* Add to HiveList key */
2118 CmpAddToHiveFileList(CmHive);
2119
2120 /* Sync the hive if necessary */
2121 if (Allocate)
2122 {
2123 /* Sync it under the flusher lock */
2125 HvSyncHive(&CmHive->Hive);
2126 CmpUnlockHiveFlusher(CmHive);
2127 }
2128
2129 /* Release the hive */
2130 CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING;
2131 CmHive->CreatorOwner = NULL;
2132 }
2133 else
2134 {
2135 DPRINT1("CmpLinkHiveToMaster failed, Status %lx\n", Status);
2136
2137 /* We're touching this hive, set the loading flag */
2138 CmHive->HiveIsLoading = TRUE;
2139
2140 /* Close associated file handles */
2141 CmpCloseHiveFiles(CmHive);
2142
2143 /* Cleanup its resources */
2144 CmpDestroyHive(CmHive);
2145 }
2146
2147 /* Allow loads */
2149
2150 /* Is this first profile load? */
2152 {
2153 /* User is now logged on, set quotas */
2156 }
2157
2158 /* Unlock the registry */
2160
2161 /* Close handle and return */
2163 return Status;
2164}
2165
2166static
2167BOOLEAN
2168NTAPI
2170 IN HCELL_INDEX Cell)
2171{
2172 PCELL_DATA CellData;
2173 HCELL_INDEX LinkCell;
2175
2176 DPRINT("CmpUnlinkHiveFromMaster()\n");
2177
2178 /* Get the cell data */
2179 CellData = HvGetCell(&CmHive->Hive, Cell);
2180 if (CellData == NULL)
2181 return FALSE;
2182
2183 /* Get the link cell and release the current cell */
2184 LinkCell = CellData->u.KeyNode.Parent;
2185 HvReleaseCell(&CmHive->Hive, Cell);
2186
2187 /* Remove the link cell from the master hive */
2190 LinkCell,
2191 TRUE);
2193 if (!NT_SUCCESS(Status))
2194 {
2195 DPRINT1("CmpFreeKeyByCell() failed (Status 0x%08lx)\n", Status);
2196 return FALSE;
2197 }
2198
2199 /* Remove the hive from the list */
2201 RemoveEntryList(&CmHive->HiveList);
2203
2204 return TRUE;
2205}
2206
2208NTAPI
2210 IN ULONG Flags)
2211{
2212 PHHIVE Hive;
2213 PCMHIVE CmHive;
2214 HCELL_INDEX Cell;
2215
2216 DPRINT("CmUnloadKey(%p, %lx)\n", Kcb, Flags);
2217
2218 /* Get the hive */
2219 Hive = Kcb->KeyHive;
2220 Cell = Kcb->KeyCell;
2221 CmHive = (PCMHIVE)Hive;
2222
2223 /* Fail if the key is not a hive root key */
2224 if (Cell != Hive->BaseBlock->RootCell)
2225 {
2226 DPRINT1("Key is not a hive root key!\n");
2228 }
2229
2230 /* Fail if we try to unload the master hive */
2231 if (CmHive == CmiVolatileHive)
2232 {
2233 DPRINT1("Do not try to unload the master hive!\n");
2235 }
2236
2237 /* Mark this hive as being unloaded */
2239
2240 /* Search for any opened keys in this hive, and take an appropriate action */
2241 if (Kcb->RefCount > 1)
2242 {
2243 if (Flags != REG_FORCE_UNLOAD)
2244 {
2245 if (CmpEnumerateOpenSubKeys(Kcb, FALSE, FALSE) != 0)
2246 {
2247 /* There are open subkeys but we don't force hive unloading, fail */
2248 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2249 return STATUS_CANNOT_DELETE;
2250 }
2251 }
2252 else
2253 {
2254 DPRINT1("CmUnloadKey: Force unloading is HALF-IMPLEMENTED, expect dangling KCBs problems!\n");
2255 if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE) != 0)
2256 {
2257 /* There are open subkeys that we cannot force to unload, fail */
2258 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2259 return STATUS_CANNOT_DELETE;
2260 }
2261 }
2262 }
2263
2264 /* Set the loading flag */
2265 CmHive->HiveIsLoading = TRUE;
2266
2267 /* Flush the hive */
2268 CmFlushKey(Kcb, TRUE);
2269
2270 /* Unlink the hive from the master hive */
2271 if (!CmpUnlinkHiveFromMaster(CmHive, Cell))
2272 {
2273 DPRINT("CmpUnlinkHiveFromMaster() failed!\n");
2274
2275 /* Remove the unloading flag */
2276 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2277
2278 /* Reset the loading flag */
2279 CmHive->HiveIsLoading = FALSE;
2280
2281 /* Return failure */
2283 }
2284
2285 /* Flush any notifications if we force hive unloading */
2286 if (Flags == REG_FORCE_UNLOAD)
2287 CmpFlushNotifiesOnKeyBodyList(Kcb, TRUE); // Lock is already held
2288
2289 /* Clean up information we have on the subkey */
2290 CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
2291
2292 /* Set the KCB in delete mode and remove it */
2293 Kcb->Delete = TRUE;
2295
2296 if (Flags != REG_FORCE_UNLOAD)
2297 {
2298 /* Release the KCB locks */
2299 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
2300
2301 /* Release the hive loading lock */
2303 }
2304
2305 /* Release hive lock */
2307
2308 /* Close file handles */
2309 CmpCloseHiveFiles(CmHive);
2310
2311 /* Remove the hive from the hive file list */
2313
2318 /* Destroy the security descriptor cache */
2320
2321 /* Destroy the view list */
2322 CmpDestroyHiveViewList(CmHive);
2323
2324 /* Delete the flusher lock */
2327
2328 /* Delete the view lock */
2330
2331 /* Free the hive storage */
2332 HvFree(Hive);
2333
2334 /* Free the hive */
2335 CmpFree(CmHive, TAG_CM);
2336
2337 return STATUS_SUCCESS;
2338}
2339
2340ULONG
2341NTAPI
2343 IN PCM_KEY_CONTROL_BLOCK RootKcb,
2344 IN BOOLEAN RemoveEmptyCacheEntries,
2345 IN BOOLEAN DereferenceOpenedEntries)
2346{
2348 PCM_KEY_CONTROL_BLOCK CachedKcb;
2349 PCM_KEY_CONTROL_BLOCK ParentKcb;
2350 ULONG ParentKeyCount;
2351 ULONG i, j;
2352 ULONG SubKeys = 0;
2353
2354 DPRINT("CmpEnumerateOpenSubKeys() called\n");
2355
2356 /* The root key is the only referenced key. There are no referenced sub keys. */
2357 if (RootKcb->RefCount == 1)
2358 {
2359 DPRINT("Open sub keys: 0\n");
2360 return 0;
2361 }
2362
2363 /* Enumerate all hash lists */
2364 for (i = 0; i < CmpHashTableSize; i++)
2365 {
2366 /* Get the first cache entry */
2368
2369 /* Enumerate all cache entries */
2370 while (Entry)
2371 {
2372 /* Get the KCB of the current cache entry */
2374
2375 /* Check keys only that are subkeys to our root key */
2376 if (CachedKcb->TotalLevels > RootKcb->TotalLevels)
2377 {
2378 /* Calculate the number of parent keys to the root key */
2379 ParentKeyCount = CachedKcb->TotalLevels - RootKcb->TotalLevels;
2380
2381 /* Find a parent key that could be the root key */
2382 ParentKcb = CachedKcb;
2383 for (j = 0; j < ParentKeyCount; j++)
2384 {
2385 ParentKcb = ParentKcb->ParentKcb;
2386 }
2387
2388 /* Check whether the parent is the root key */
2389 if (ParentKcb == RootKcb)
2390 {
2391 DPRINT("Found a sub key, RefCount = %u\n", CachedKcb->RefCount);
2392
2393 if (CachedKcb->RefCount > 0)
2394 {
2395 DPRINT("Found a sub key pointing to '%.*s', RefCount = %u\n",
2396 CachedKcb->NameBlock->NameLength, CachedKcb->NameBlock->Name,
2397 CachedKcb->RefCount);
2398
2399 /* If we dereference opened KCBs, don't touch read-only keys */
2400 if (DereferenceOpenedEntries &&
2401 !(CachedKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
2402 {
2403 /* Registry needs to be locked down */
2405
2406 /* Flush any notifications */
2407 CmpFlushNotifiesOnKeyBodyList(CachedKcb, TRUE); // Lock is already held
2408
2409 /* Clean up information we have on the subkey */
2410 CmpCleanUpSubKeyInfo(CachedKcb->ParentKcb);
2411
2412 /* Get and cache the next cache entry */
2413 // Entry = Entry->NextHash;
2414 Entry = CachedKcb->NextHash;
2415
2416 /* Set the KCB in delete mode and remove it */
2417 CachedKcb->Delete = TRUE;
2418 CmpRemoveKeyControlBlock(CachedKcb);
2419
2420 /* Clear the cell */
2421 CachedKcb->KeyCell = HCELL_NIL;
2422
2423 /* Restart with the next cache entry */
2424 continue;
2425 }
2426 /* Else, the key cannot be dereferenced, and we count it as in use */
2427
2428 /* Count the current hash entry if it is in use */
2429 SubKeys++;
2430 }
2431 else if ((CachedKcb->RefCount == 0) && RemoveEmptyCacheEntries)
2432 {
2433 /* Remove the current key from the delayed close list */
2434 CmpRemoveFromDelayedClose(CachedKcb);
2435
2436 /* Remove the current cache entry */
2437 CmpCleanUpKcbCacheWithLock(CachedKcb, TRUE);
2438
2439 /* Restart, because the hash list has changed */
2441 continue;
2442 }
2443 }
2444 }
2445
2446 /* Get the next cache entry */
2447 Entry = Entry->NextHash;
2448 }
2449 }
2450
2451 if (SubKeys > 0)
2452 DPRINT1("Open sub keys: %u\n", SubKeys);
2453
2454 return SubKeys;
2455}
2456
2457static
2460 IN HCELL_INDEX SrcKeyCell,
2461 IN PHHIVE DestinationHive,
2463 IN HSTORAGE_TYPE StorageType,
2464 OUT PHCELL_INDEX DestKeyCell OPTIONAL)
2465{
2467 PCM_KEY_NODE SrcNode;
2468 PCM_KEY_NODE DestNode = NULL;
2469 HCELL_INDEX NewKeyCell = HCELL_NIL;
2470 HCELL_INDEX NewClassCell = HCELL_NIL, NewSecCell = HCELL_NIL;
2471 HCELL_INDEX SubKey, NewSubKey;
2472 ULONG Index, SubKeyCount;
2473
2474 PAGED_CODE();
2475
2476 DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
2477 SourceHive,
2478 SrcKeyCell,
2479 DestinationHive,
2480 Parent,
2481 StorageType,
2482 DestKeyCell);
2483
2484 /* Get the source cell node */
2485 SrcNode = (PCM_KEY_NODE)HvGetCell(SourceHive, SrcKeyCell);
2486 ASSERT(SrcNode);
2487
2488 /* Sanity check */
2490
2491 /* Create a simple copy of the source key */
2492 NewKeyCell = CmpCopyCell(SourceHive,
2493 SrcKeyCell,
2494 DestinationHive,
2495 StorageType);
2496 if (NewKeyCell == HCELL_NIL)
2497 {
2498 /* Not enough storage space */
2500 goto Cleanup;
2501 }
2502
2503 /* Get the destination cell node */
2504 DestNode = (PCM_KEY_NODE)HvGetCell(DestinationHive, NewKeyCell);
2505 ASSERT(DestNode);
2506
2507 /* Set the parent and copy the flags */
2508 DestNode->Parent = Parent;
2509 DestNode->Flags = (SrcNode->Flags & KEY_COMP_NAME); // Keep only the single permanent flag
2510 if (Parent == HCELL_NIL)
2511 {
2512 /* This is the new root node */
2513 DestNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
2514 }
2515
2516 /* Copy the class cell */
2517 if (SrcNode->ClassLength > 0)
2518 {
2519 NewClassCell = CmpCopyCell(SourceHive,
2520 SrcNode->Class,
2521 DestinationHive,
2522 StorageType);
2523 if (NewClassCell == HCELL_NIL)
2524 {
2525 /* Not enough storage space */
2527 goto Cleanup;
2528 }
2529
2530 DestNode->Class = NewClassCell;
2531 DestNode->ClassLength = SrcNode->ClassLength;
2532 }
2533 else
2534 {
2535 DestNode->Class = HCELL_NIL;
2536 DestNode->ClassLength = 0;
2537 }
2538
2539 /* Copy the security cell (FIXME: HACKish poor-man version) */
2540 if (SrcNode->Security != HCELL_NIL)
2541 {
2542 NewSecCell = CmpCopyCell(SourceHive,
2543 SrcNode->Security,
2544 DestinationHive,
2545 StorageType);
2546 if (NewSecCell == HCELL_NIL)
2547 {
2548 /* Not enough storage space */
2550 goto Cleanup;
2551 }
2552 }
2553 DestNode->Security = NewSecCell;
2554
2555 /* Copy the value list */
2556 Status = CmpCopyKeyValueList(SourceHive,
2557 &SrcNode->ValueList,
2558 DestinationHive,
2559 &DestNode->ValueList,
2560 StorageType);
2561 if (!NT_SUCCESS(Status))
2562 goto Cleanup;
2563
2564 /* Clear the invalid subkey index */
2565 DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
2566 DestNode->SubKeyLists[Stable] = DestNode->SubKeyLists[Volatile] = HCELL_NIL;
2567
2568 /* Calculate the total number of subkeys */
2569 SubKeyCount = SrcNode->SubKeyCounts[Stable] + SrcNode->SubKeyCounts[Volatile];
2570
2571 /* Loop through all the subkeys */
2572 for (Index = 0; Index < SubKeyCount; Index++)
2573 {
2574 /* Get the subkey */
2575 SubKey = CmpFindSubKeyByNumber(SourceHive, SrcNode, Index);
2576 ASSERT(SubKey != HCELL_NIL);
2577
2578 /* Call the function recursively for the subkey */
2579 //
2580 // FIXME: Danger!! Kernel stack exhaustion!!
2581 //
2582 Status = CmpDeepCopyKeyInternal(SourceHive,
2583 SubKey,
2584 DestinationHive,
2585 NewKeyCell,
2586 StorageType,
2587 &NewSubKey);
2588 if (!NT_SUCCESS(Status))
2589 goto Cleanup;
2590
2591 /* Add the copy of the subkey to the new key */
2592 if (!CmpAddSubKey(DestinationHive,
2593 NewKeyCell,
2594 NewSubKey))
2595 {
2596 /* Cleanup allocated cell */
2597 HvFreeCell(DestinationHive, NewSubKey);
2598
2600 goto Cleanup;
2601 }
2602 }
2603
2604 /* Set success */
2606
2607Cleanup:
2608
2609 /* Release the cells */
2610 if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell);
2611 if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
2612
2613 /* Cleanup allocated cells in case of failure */
2614 if (!NT_SUCCESS(Status))
2615 {
2616 if (NewSecCell != HCELL_NIL)
2617 HvFreeCell(DestinationHive, NewSecCell);
2618
2619 if (NewClassCell != HCELL_NIL)
2620 HvFreeCell(DestinationHive, NewClassCell);
2621
2622 if (NewKeyCell != HCELL_NIL)
2623 HvFreeCell(DestinationHive, NewKeyCell);
2624
2625 NewKeyCell = HCELL_NIL;
2626 }
2627
2628 /* Set the cell index if requested and return status */
2629 if (DestKeyCell) *DestKeyCell = NewKeyCell;
2630 return Status;
2631}
2632
2634NTAPI
2636 IN HCELL_INDEX SrcKeyCell,
2637 IN PHHIVE DestinationHive,
2638 IN HSTORAGE_TYPE StorageType,
2639 OUT PHCELL_INDEX DestKeyCell OPTIONAL)
2640{
2641 /* Call the internal function */
2642 return CmpDeepCopyKeyInternal(SourceHive,
2643 SrcKeyCell,
2644 DestinationHive,
2645 HCELL_NIL,
2646 StorageType,
2647 DestKeyCell);
2648}
2649
2651NTAPI
2654 IN ULONG Flags)
2655{
2656#if DBG
2657 CM_CHECK_REGISTRY_STATUS CheckStatus;
2658 PCMHIVE HiveToValidate = NULL;
2659#endif
2661 PCMHIVE KeyHive = NULL;
2662 PAGED_CODE();
2663
2664 DPRINT("CmSaveKey(0x%08X, 0x%08X, %lu)\n", Kcb, FileHandle, Flags);
2665
2666 /* Lock the registry and KCB */
2669
2670#if DBG
2671 /* Get the hive for validation */
2672 HiveToValidate = (PCMHIVE)Kcb->KeyHive;
2673#endif
2674
2675 if (Kcb->Delete)
2676 {
2677 /* The source key has been deleted, do nothing */
2679 goto Cleanup;
2680 }
2681
2682 if (Kcb->KeyHive == &CmiVolatileHive->Hive)
2683 {
2684 /* Keys that are directly in the master hive can't be saved */
2686 goto Cleanup;
2687 }
2688
2689#if DBG
2690 /* Make sure this control block has a sane hive */
2692 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2693#endif
2694
2695 /* Create a new hive that will hold the key */
2696 Status = CmpInitializeHive(&KeyHive,
2700 NULL,
2701 NULL,
2702 NULL,
2703 NULL,
2704 NULL,
2705 NULL,
2707 if (!NT_SUCCESS(Status)) goto Cleanup;
2708
2709 /* Copy the key recursively into the new hive */
2710 Status = CmpDeepCopyKey(Kcb->KeyHive,
2711 Kcb->KeyCell,
2712 &KeyHive->Hive,
2713 Stable,
2714 &KeyHive->Hive.BaseBlock->RootCell);
2715 if (!NT_SUCCESS(Status)) goto Cleanup;
2716
2717 /* Set the primary handle of the hive */
2719
2720 /* Dump the hive into the file */
2721 HvWriteHive(&KeyHive->Hive);
2722
2723Cleanup:
2724
2725 /* Free the hive */
2726 if (KeyHive) CmpDestroyHive(KeyHive);
2727
2728#if DBG
2729 if (NT_SUCCESS(Status))
2730 {
2731 /* Before we say goodbye, make sure the hive is still OK */
2733 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2734 }
2735#endif
2736
2737 /* Release the locks */
2738 CmpReleaseKcbLock(Kcb);
2740
2741 return Status;
2742}
2743
2745NTAPI
2749{
2750#if DBG
2751 CM_CHECK_REGISTRY_STATUS CheckStatus;
2752 PCMHIVE LowHiveToValidate = NULL;
2753 PCMHIVE HighHiveToValidate = NULL;
2754#endif
2755 PCMHIVE KeyHive = NULL;
2757
2758 PAGED_CODE();
2759
2760 DPRINT("CmSaveKey(%p, %p, %p)\n", HighKcb, LowKcb, FileHandle);
2761
2762 /* Lock the registry and the KCBs */
2764 CmpAcquireKcbLockShared(HighKcb);
2766
2767#if DBG
2768 /* Get the high and low hives for validation */
2769 HighHiveToValidate = (PCMHIVE)HighKcb->KeyHive;
2770 LowHiveToValidate = (PCMHIVE)LowKcb->KeyHive;
2771#endif
2772
2773 if (LowKcb->Delete || HighKcb->Delete)
2774 {
2775 /* The source key has been deleted, do nothing */
2777 goto done;
2778 }
2779
2780#if DBG
2781 /* Make sure that both the high and low precedence hives are OK */
2783 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2785 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2786#endif
2787
2788 /* Create a new hive that will hold the key */
2789 Status = CmpInitializeHive(&KeyHive,
2793 NULL,
2794 NULL,
2795 NULL,
2796 NULL,
2797 NULL,
2798 NULL,
2800 if (!NT_SUCCESS(Status))
2801 goto done;
2802
2803 /* Copy the low precedence key recursively into the new hive */
2804 Status = CmpDeepCopyKey(LowKcb->KeyHive,
2805 LowKcb->KeyCell,
2806 &KeyHive->Hive,
2807 Stable,
2808 &KeyHive->Hive.BaseBlock->RootCell);
2809 if (!NT_SUCCESS(Status))
2810 goto done;
2811
2812 /* Copy the high precedence key recursively into the new hive */
2813 Status = CmpDeepCopyKey(HighKcb->KeyHive,
2814 HighKcb->KeyCell,
2815 &KeyHive->Hive,
2816 Stable,
2817 &KeyHive->Hive.BaseBlock->RootCell);
2818 if (!NT_SUCCESS(Status))
2819 goto done;
2820
2821 /* Set the primary handle of the hive */
2823
2824 /* Dump the hive into the file */
2825 HvWriteHive(&KeyHive->Hive);
2826
2827done:
2828 /* Free the hive */
2829 if (KeyHive)
2830 CmpDestroyHive(KeyHive);
2831
2832#if DBG
2833 if (NT_SUCCESS(Status))
2834 {
2835 /* Check those hives again before we say goodbye */
2837 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2839 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2840 }
2841#endif
2842
2843 /* Release the locks */
2844 CmpReleaseKcbLock(LowKcb);
2845 CmpReleaseKcbLock(HighKcb);
2847
2848 return Status;
2849}
#define PAGED_CODE()
#define ALIGN_UP_BY(size, align)
#define REG_FORCE_UNLOAD
#define CmpKeyObjectType
Definition: ObTypes.c:127
unsigned char BOOLEAN
Type
Definition: Type.h:7
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_Out_ PVOID * ClassData
Definition: batclass.h:336
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
return Found
Definition: dirsup.c:1270
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
HCELL_INDEX NTAPI CmpCopyCell(IN PHHIVE SourceHive, IN HCELL_INDEX SourceCell, IN PHHIVE DestinationHive, IN HSTORAGE_TYPE StorageType)
Definition: cmvalue.c:376
#define CM_KCB_SUBKEY_ONE
Definition: cm.h:53
enum _VALUE_SEARCH_RETURN_TYPE VALUE_SEARCH_RETURN_TYPE
#define CM_KCB_SUBKEY_HINT
Definition: cm.h:54
@ SearchSuccess
Definition: cm.h:139
@ SearchNeedExclusiveLock
Definition: cm.h:140
#define CM_KCB_SYM_LINK_FOUND
Definition: cm.h:55
#define CM_KCB_INVALID_CACHED_INFO
Definition: cm.h:58
#define CM_KCB_NO_SUBKEY
Definition: cm.h:52
struct _KEY_INFORMATION * PKEY_INFORMATION
#define CM_KCB_READ_ONLY_KEY
Definition: cm.h:59
FORCEINLINE VOID CmpAcquireKcbLockExclusive(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:116
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK()
Definition: cm_x.h:67
#define CMP_ASSERT_FLUSH_LOCK(h)
Definition: cm_x.h:282
#define CmpAcquireKcbLockShared(k)
Definition: cm_x.h:145
#define CMP_IS_CELL_CACHED(c)
Definition: cm_x.h:34
#define CmpIsKcbLockedExclusive(k)
Definition: cm_x.h:88
#define CMP_ASSERT_KCB_LOCK(k)
Definition: cm_x.h:261
FORCEINLINE VOID CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:205
FORCEINLINE VOID CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:185
FORCEINLINE BOOLEAN CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:156
static BOOLEAN NTAPI CmpUnlinkHiveFromMaster(IN PCMHIVE CmHive, IN HCELL_INDEX Cell)
Definition: cmapi.c:2169
NTSTATUS NTAPI CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Flags)
Definition: cmapi.c:2209
NTSTATUS NTAPI CmpSetValueKeyExisting(IN PHHIVE Hive, IN HCELL_INDEX OldChild, IN PCM_KEY_VALUE Value, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG TempData)
Definition: cmapi.c:270
static NTSTATUS CmpQueryKeyDataFromCache(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1362
BOOLEAN NTAPI CmpIsHiveAlreadyLoaded(IN HANDLE KeyHandle, IN POBJECT_ATTRIBUTES SourceFile, OUT PCMHIVE *CmHive)
Definition: cmapi.c:21
NTSTATUS NTAPI CmSetValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataLength)
Definition: cmapi.c:643
static NTSTATUS CmpDeepCopyKeyInternal(IN PHHIVE SourceHive, IN HCELL_INDEX SrcKeyCell, IN PHHIVE DestinationHive, IN HCELL_INDEX Parent, IN HSTORAGE_TYPE StorageType, OUT PHCELL_INDEX DestKeyCell OPTIONAL)
Definition: cmapi.c:2459
NTSTATUS NTAPI CmSaveMergedKeys(IN PCM_KEY_CONTROL_BLOCK HighKcb, IN PCM_KEY_CONTROL_BLOCK LowKcb, IN HANDLE FileHandle)
Definition: cmapi.c:2746
NTSTATUS NTAPI CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN ExclusiveLock)
Definition: cmapi.c:1937
NTSTATUS NTAPI CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
Definition: cmapi.c:1734
NTSTATUS NTAPI CmpSetValueKeyNew(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PUNICODE_STRING ValueName, IN ULONG Index, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG SmallData)
Definition: cmapi.c:146
NTSTATUS NTAPI CmpDeepCopyKey(IN PHHIVE SourceHive, IN HCELL_INDEX SrcKeyCell, IN PHHIVE DestinationHive, IN HSTORAGE_TYPE StorageType, OUT PHCELL_INDEX DestKeyCell OPTIONAL)
Definition: cmapi.c:2635
NTSTATUS NTAPI CmQueryValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN UNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
Definition: cmapi.c:1074
static NTSTATUS CmpQueryFlagsInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo, _In_ ULONG Length, _In_ PULONG ResultLength)
Definition: cmapi.c:1497
NTSTATUS NTAPI CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN UNICODE_STRING ValueName)
Definition: cmapi.c:915
NTSTATUS NTAPI CmEnumerateValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
Definition: cmapi.c:1191
NTSTATUS NTAPI CmSaveKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN HANDLE FileHandle, IN ULONG Flags)
Definition: cmapi.c:2652
BOOLEAN NTAPI CmpDoFlushAll(IN BOOLEAN ForceFlush)
Definition: cmapi.c:81
NTSTATUS NTAPI CmQueryKey(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _In_ KEY_INFORMATION_CLASS KeyInformationClass, _Out_opt_ PVOID KeyInformation, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1614
NTSTATUS NTAPI CmpQueryKeyData(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN KEY_INFORMATION_CLASS KeyInformationClass, IN OUT PVOID KeyInformation, IN ULONG Length, IN OUT PULONG ResultLength)
Definition: cmapi.c:375
NTSTATUS NTAPI CmDeleteKey(IN PCM_KEY_BODY KeyBody)
Definition: cmapi.c:1823
NTSTATUS NTAPI CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, IN PCM_KEY_BODY KeyBody)
Definition: cmapi.c:2012
ULONG NTAPI CmpEnumerateOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb, IN BOOLEAN RemoveEmptyCacheEntries, IN BOOLEAN DereferenceOpenedEntries)
Definition: cmapi.c:2342
static NTSTATUS CmpQueryNameInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1518
CM_CHECK_REGISTRY_STATUS NTAPI CmCheckRegistry(_In_ PCMHIVE RegistryHive, _In_ ULONG Flags)
Checks the registry that is consistent and its contents valid and not corrupted. More specifically th...
Definition: cmcheck.c:1633
EX_PUSH_LOCK CmpHiveListHeadLock
Definition: cmdata.c:39
EX_PUSH_LOCK CmpLoadHiveLock
Definition: cmdata.c:39
UNICODE_STRING CmSymbolicLinkValueName
Definition: cmdata.c:52
struct _CM_KEY_NODE * PCM_KEY_NODE
#define KEY_COMP_NAME
Definition: cmdata.h:35
struct _CM_KEY_VALUE * PCM_KEY_VALUE
#define KEY_NO_DELETE
Definition: cmdata.h:33
#define CM_KEY_VALUE_SIGNATURE
Definition: cmdata.h:24
#define VALUE_COMP_NAME
Definition: cmdata.h:44
#define CM_KEY_VALUE_SPECIAL_SIZE
Definition: cmdata.h:51
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
#define CM_KEY_VALUE_SMALL
Definition: cmdata.h:49
#define KEY_SYM_LINK
Definition: cmdata.h:34
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
VOID NTAPI CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmdelay.c:425
VOID NTAPI CmpRemoveFromHiveFileList(IN PCMHIVE Hive)
Definition: cmhvlist.c:254
NTSTATUS NTAPI CmpAddToHiveFileList(IN PCMHIVE Hive)
Definition: cmhvlist.c:130
BOOLEAN NTAPI CmpAddSubKey(IN PHHIVE Hive, IN HCELL_INDEX Parent, IN HCELL_INDEX Child)
Definition: cmindex.c:1465
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
VOID NTAPI CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:476
PCM_KEY_HASH_TABLE_ENTRY CmpCacheTable
Definition: cmkcbncb.c:18
VOID NTAPI CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:431
VOID NTAPI CmpFlushNotifiesOnKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeld)
Definition: cmkcbncb.c:1368
VOID NTAPI CmpCleanUpSubKeyInfo(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:517
VOID NTAPI CmpRemoveKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:306
ULONG CmpHashTableSize
Definition: cmkcbncb.c:17
NTSTATUS NTAPI CmpFreeKeyByCell(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN BOOLEAN Unlink)
Definition: cmkeydel.c:159
NTSTATUS NTAPI CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes, IN PSECURITY_CLIENT_CONTEXT ImpersonationContext, IN OUT PBOOLEAN Allocate, OUT PCMHIVE *NewHive, IN ULONG CheckFlags)
Definition: cmlazy.c:276
BOOLEAN CmpForceForceFlush
Definition: cmlazy.c:22
BOOLEAN CMAPI HvTrackCellRef(IN OUT PHV_TRACK_CELL_REF CellRef, IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: hivecell.c:554
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:455
USHORT NTAPI CmpCopyName(IN PHHIVE Hive, OUT PWCHAR Destination, IN PCUNICODE_STRING Source)
Definition: cmname.c:21
#define CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES
Definition: cmlib.h:228
BOOLEAN NTAPI CmpMarkValueDataDirty(IN PHHIVE Hive, IN PCM_KEY_VALUE Value)
Definition: cmvalue.c:19
BOOLEAN CMAPI HvHiveWillShrink(IN PHHIVE RegistryHive)
BOOLEAN NTAPI CmpFreeValue(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: cmvalue.c:73
BOOLEAN NTAPI CmpFreeValueData(IN PHHIVE Hive, IN HCELL_INDEX DataCell, IN ULONG DataLength)
Definition: cmvalue.c:44
#define TAG_CMHIVE
Definition: cmlib.h:214
NTSTATUS NTAPI CmpRemoveValueFromList(IN PHHIVE Hive, IN ULONG Index, IN OUT PCHILD_LIST ChildList)
Definition: cmvalue.c:320
#define CM_CHECK_REGISTRY_PURGE_VOLATILES
Definition: cmlib.h:229
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PCUNICODE_STRING Name)
Definition: cmname.c:74
BOOLEAN CMAPI HvSyncHive(PHHIVE RegistryHive)
NTSTATUS NTAPI CmpSetValueDataNew(IN PHHIVE Hive, IN PVOID Data, IN ULONG DataSize, IN HSTORAGE_TYPE StorageType, IN HCELL_INDEX ValueCell, OUT PHCELL_INDEX DataCell)
Definition: cmvalue.c:289
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
NTSTATUS NTAPI CmpCopyKeyValueList(IN PHHIVE SourceHive, IN PCHILD_LIST SrcValueList, IN PHHIVE DestinationHive, IN OUT PCHILD_LIST DestValueList, IN HSTORAGE_TYPE StorageType)
Definition: cmvalue.c:521
BOOLEAN CMAPI HvIsCellDirty(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: hivecell.c:153
VOID CMAPI HvReleaseFreeCellRefArray(IN OUT PHV_TRACK_CELL_REF CellRef)
Definition: hivecell.c:634
#define ASSERT_VALUE_BIG(h, s)
Definition: cmlib.h:382
#define CM_CHECK_REGISTRY_VALIDATE_HIVE
Definition: cmlib.h:231
static BOOLEAN CmpIsKeyValueSmall(OUT PULONG RealLength, IN ULONG Length)
Definition: cmlib.h:390
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:468
LONG CMAPI HvGetCellSize(PHHIVE RegistryHive, PVOID Cell)
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
Definition: cmlib.h:281
struct _CMHIVE * PCMHIVE
ULONG CM_CHECK_REGISTRY_STATUS
Definition: cmlib.h:223
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
Definition: hivecell.c:109
HCELL_INDEX CMAPI HvReallocateCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset, ULONG Size)
Definition: hivecell.c:421
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:452
HCELL_INDEX CMAPI HvAllocateCell(PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, IN HCELL_INDEX Vicinity)
#define TAG_CM
Definition: cmlib.h:212
VOID CMAPI HvFree(PHHIVE RegistryHive)
BOOLEAN CMAPI HvWriteHive(PHHIVE RegistryHive)
BOOLEAN NTAPI CmpFindNameInList(IN PHHIVE Hive, IN PCHILD_LIST ChildList, IN PCUNICODE_STRING Name, OUT PULONG ChildIndex OPTIONAL, OUT PHCELL_INDEX CellIndex)
Definition: cmname.c:149
NTSTATUS NTAPI CmpAddValueToList(IN PHHIVE Hive, IN HCELL_INDEX ValueCell, IN ULONG Index, IN HSTORAGE_TYPE StorageType, IN OUT PCHILD_LIST ChildList)
Definition: cmvalue.c:207
VOID NTAPI CmpDestroyHiveViewList(IN PCMHIVE Hive)
Definition: cmmapvw.c:35
VOID NTAPI CmpReportNotify(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PHHIVE Hive, IN HCELL_INDEX Cell, IN ULONG Filter)
Definition: cmnotify.c:19
VOID NTAPI CmpSetGlobalQuotaAllowed(VOID)
Definition: cmquota.c:22
VOID NTAPI CmpDestroySecurityCache(IN PCMHIVE Hive)
Definition: cmsecach.c:41
VOID NTAPI CmpLockRegistryExclusive(VOID)
Definition: cmsysini.c:1954
VOID NTAPI CmpUnlockRegistry(VOID)
Definition: cmsysini.c:2053
NTSTATUS NTAPI CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, IN HANDLE RootDirectory, IN PCMHIVE RegistryHive, IN BOOLEAN Allocate, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: cmsysini.c:802
VOID NTAPI CmpLockHiveFlusherExclusive(IN PCMHIVE Hive)
Definition: cmsysini.c:2003
VOID NTAPI CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2076
VOID NTAPI CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2105
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1967
VOID NTAPI CmpLockHiveFlusherShared(IN PCMHIVE Hive)
Definition: cmsysini.c:2014
BOOLEAN CmpSpecialBootCondition
Definition: cmsysini.c:26
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:16
BOOLEAN CmpProfileLoaded
Definition: cmsysini.c:33
BOOLEAN NTAPI CmpTestRegistryLockExclusive(VOID)
Definition: cmsysini.c:1995
LIST_ENTRY CmpHiveListHead
Definition: cmsysini.c:17
BOOLEAN CmpWasSetupBoot
Definition: cmsysini.c:32
BOOLEAN CmpNoWrite
Definition: cmsysini.c:30
VOID NTAPI CmpUnlockHiveFlusher(IN PCMHIVE Hive)
Definition: cmsysini.c:2025
VALUE_SEARCH_RETURN_TYPE NTAPI CmpQueryKeyValueData(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PCM_CACHED_VALUE *CachedValue, IN PCM_KEY_VALUE ValueKey, IN BOOLEAN ValueIsCached, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength, OUT PNTSTATUS Status)
Definition: cmvalche.c:327
VALUE_SEARCH_RETURN_TYPE NTAPI CmpFindValueByNameFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PCUNICODE_STRING Name, OUT PCM_CACHED_VALUE **CachedValue, OUT ULONG *Index, OUT PCM_KEY_VALUE *Value, OUT BOOLEAN *ValueIsCached, OUT PHCELL_INDEX CellToRelease)
Definition: cmvalche.c:194
VALUE_SEARCH_RETURN_TYPE NTAPI CmpGetValueListFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb, OUT PCELL_DATA *CellData, OUT BOOLEAN *IndexIsCached, OUT PHCELL_INDEX ValueListToRelease)
Definition: cmvalche.c:44
VALUE_SEARCH_RETURN_TYPE NTAPI CmpGetValueKeyFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PCELL_DATA CellData, IN ULONG Index, OUT PCM_CACHED_VALUE **CachedValue, OUT PCM_KEY_VALUE *Value, IN BOOLEAN IndexIsCached, OUT BOOLEAN *ValueIsCached, OUT PHCELL_INDEX CellToRelease)
Definition: cmvalche.c:96
VALUE_SEARCH_RETURN_TYPE NTAPI CmpCompareNewValueDataAgainstKCBCache(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: cmvalche.c:700
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union node Node
Definition: types.h:1255
static const WCHAR Cleanup[]
Definition: register.c:80
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
FORCEINLINE VOID ExReleasePushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1296
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1105
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN BOOLEAN ExclusiveLock
Definition: fatprocs.h:2714
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ Loaded
Definition: fs_rec.h:187
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define KeGetCurrentThread
Definition: hal.h:55
#define HINIT_CREATE
Definition: hivedata.h:13
ULONG * PHCELL_INDEX
Definition: hivedata.h:105
HSTORAGE_TYPE
Definition: hivedata.h:126
@ Volatile
Definition: hivedata.h:128
@ Stable
Definition: hivedata.h:127
#define HIVE_IS_UNLOADING
Definition: hivedata.h:28
#define HIVE_VOLATILE
Definition: hivedata.h:23
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
#define HCELL_NIL
Definition: hivedata.h:110
ULONG HCELL_INDEX
Definition: hivedata.h:105
#define HvGetCellType(Cell)
Definition: hivedata.h:120
#define HIVE_NOLAZYFLUSH
Definition: hivedata.h:24
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
@ KeyFlagsInformation
Definition: winternl.h:833
@ KeyCachedInformation
Definition: winternl.h:832
@ KeyNameInformation
Definition: winternl.h:831
if(dx< 0)
Definition: linetemp.h:194
@ SecurityImpersonation
Definition: lsa.idl:57
struct _SECURITY_QUALITY_OF_SERVICE SECURITY_QUALITY_OF_SERVICE
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
NTKERNELAPI NTSTATUS NTAPI SeCreateClientSecurity(IN PETHREAD Thread, IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, IN BOOLEAN RemoteClient, OUT PSECURITY_CLIENT_CONTEXT ClientContext)
static IStorage Storage
Definition: ole2.c:3548
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_opt_
Definition: ms_sal.h:346
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KernelMode
Definition: asm.h:34
_In_ ULONG _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
Definition: cmfuncs.h:94
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
int Count
Definition: noreturn.cpp:7
@ KeyBasicInformation
Definition: nt_native.h:1131
@ KeyNodeInformation
Definition: nt_native.h:1132
@ KeyFullInformation
Definition: nt_native.h:1133
#define REG_NO_LAZY_FLUSH
Definition: nt_native.h:1093
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
enum _KEY_VALUE_INFORMATION_CLASS KEY_VALUE_INFORMATION_CLASS
Definition: reg.c:135
enum _KEY_INFORMATION_CLASS KEY_INFORMATION_CLASS
#define REG_LINK
Definition: nt_native.h:1500
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ FirstTry
Definition: copy.c:25
VOID NTAPI CmpCloseHiveFiles(IN PCMHIVE Hive)
Definition: cminit.c:644
NTSTATUS NTAPI CmpInitializeHive(_Out_ PCMHIVE *CmHive, _In_ ULONG OperationType, _In_ ULONG HiveFlags, _In_ ULONG FileType, _In_opt_ PVOID HiveData, _In_ HANDLE Primary, _In_ HANDLE Log, _In_ HANDLE External, _In_ HANDLE Alternate, _In_opt_ PCUNICODE_STRING FileName, _In_ ULONG CheckFlags)
Definition: cminit.c:19
NTSTATUS NTAPI CmpDestroyHive(IN PCMHIVE CmHive)
Definition: cminit.c:242
#define STATUS_KEY_DELETED
Definition: ntstatus.h:613
#define STATUS_NO_LOG_SPACE
Definition: ntstatus.h:614
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define STATUS_REGISTRY_IO_FAILED
Definition: ntstatus.h:569
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2532
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
CM_KEY_VALUE KeyValue
Definition: cmdata.h:201
union _CELL_DATA::@4298 u
CM_KEY_NODE KeyNode
Definition: cmdata.h:200
Definition: cmlib.h:316
HHIVE Hive
Definition: cmlib.h:317
BOOLEAN HiveIsLoading
Definition: cmlib.h:357
BOOLEAN Frozen
Definition: cmlib.h:345
PKGUARDED_MUTEX ViewLock
Definition: cmlib.h:323
PERESOURCE FlusherLock
Definition: cmlib.h:327
ULONG UseCount
Definition: cmlib.h:337
PKTHREAD CreatorOwner
Definition: cmlib.h:358
HANDLE FileHandles[HFILE_TYPE_MAX]
Definition: cmlib.h:318
UNICODE_STRING FileUserName
Definition: cmlib.h:334
PKTHREAD ViewLockOwner
Definition: cmlib.h:324
struct _CM_KEY_CONTROL_BLOCK * KeyControlBlock
Definition: cm.h:234
ULONG TotalLevels
Definition: cm.h:276
PCM_NAME_CONTROL_BLOCK NameBlock
Definition: cm.h:290
ULONG RefCount
Definition: cm.h:269
PHHIVE KeyHive
Definition: cm.h:285
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:289
ULONG ExtFlags
Definition: cm.h:272
HCELL_INDEX KeyCell
Definition: cm.h:286
PCM_KEY_HASH NextHash
Definition: cm.h:284
PCM_KEY_HASH Entry
Definition: cm.h:162
USHORT Signature
Definition: cmdata.h:92
HCELL_INDEX Parent
Definition: cmdata.h:96
HCELL_INDEX SubKeyLists[HTYPE_COUNT]
Definition: cmdata.h:102
ULONG SubKeyCounts[HTYPE_COUNT]
Definition: cmdata.h:97
HCELL_INDEX Security
Definition: cmdata.h:107
USHORT ClassLength
Definition: cmdata.h:115
HCELL_INDEX Class
Definition: cmdata.h:108
CHILD_LIST ValueList
Definition: cmdata.h:103
USHORT Flags
Definition: cmdata.h:93
USHORT Signature
Definition: cmdata.h:124
ULONG Type
Definition: cmdata.h:128
HCELL_INDEX Data
Definition: cmdata.h:127
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:131
USHORT NameLength
Definition: cmdata.h:125
USHORT Flags
Definition: cmdata.h:129
ULONG DataLength
Definition: cmdata.h:126
BOOLEAN Compressed
Definition: cm.h:248
USHORT NameLength
Definition: cm.h:257
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:258
BOOLEAN CreateOperation
Definition: cm.h:441
HCELL_INDEX RootCell
Definition: hivedata.h:168
ULONG HiveFlags
Definition: hivedata.h:347
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:328
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode
Definition: lsa.idl:66
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
UINT32 Length
Definition: actbl.h:109
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
Definition: dlist.c:348
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFCHILDLIST * ChildList
Definition: wdfchildlist.h:481
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_opt_ PALLOCATE_FUNCTION Allocate
Definition: exfuncs.h:814
#define ObDereferenceObject
Definition: obfuncs.h:203
#define SECURITY_DYNAMIC_TRACKING
Definition: setypes.h:103
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ ULONG _In_ KEY_INFORMATION_CLASS KeyInformationClass
Definition: zwfuncs.h:167