ReactOS 0.4.15-dev-6656-gbbb33a6
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 DPRINT1("ERROR: Hive is frozen\n");
71 while (TRUE);
72 }
73 }
74
75 /* Dereference and return result */
76 ObDereferenceObject(KeyBody);
77 return Loaded;
78 }
79
83{
84 PLIST_ENTRY NextEntry;
85 PCMHIVE Hive;
88
89 /* Make sure that the registry isn't read-only now */
90 if (CmpNoWrite) return TRUE;
91
92 /* Otherwise, acquire the hive list lock and disable force flush */
95
96 /* Loop the hive list */
97 NextEntry = CmpHiveListHead.Flink;
98 while (NextEntry != &CmpHiveListHead)
99 {
100 /* Get the hive */
101 Hive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList);
102 if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))
103 {
104 /* Acquire the flusher lock */
106
107 /* Check for illegal state */
108 if ((ForceFlush) && (Hive->UseCount))
109 {
110 /* Registry needs to be locked down */
112 DPRINT1("FIXME: Hive is damaged and needs fixup\n");
113 while (TRUE);
114 }
115
116 /* Only sync if we are forced to or if it won't cause a hive shrink */
117 if ((ForceFlush) || (!HvHiveWillShrink(&Hive->Hive)))
118 {
119 /* Do the sync */
120 Status = HvSyncHive(&Hive->Hive);
121
122 /* If something failed - set the flag and continue looping */
123 if (!NT_SUCCESS(Status)) Result = FALSE;
124 }
125 else
126 {
127 /* We won't flush if the hive might shrink */
128 Result = FALSE;
130 }
131
132 /* Release the flusher lock */
134 }
135
136 /* Try the next entry */
137 NextEntry = NextEntry->Flink;
138 }
139
140 /* Release lock and return */
142 return Result;
143}
144
146NTAPI
150 IN ULONG Index,
151 IN ULONG Type,
152 IN PVOID Data,
154 IN ULONG StorageType,
155 IN ULONG SmallData)
156{
157 PCELL_DATA CellData;
158 HCELL_INDEX ValueCell;
160
161 /* Check if we already have a value list */
162 if (Parent->ValueList.Count)
163 {
164 /* Then make sure it's valid and dirty it */
165 ASSERT(Parent->ValueList.List != HCELL_NIL);
166 if (!HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE))
167 {
168 /* Fail if we're out of space for log changes */
169 return STATUS_NO_LOG_SPACE;
170 }
171 }
172
173 /* Allocate a value cell */
174 ValueCell = HvAllocateCell(Hive,
176 CmpNameSize(Hive, ValueName),
177 StorageType,
178 HCELL_NIL);
179 if (ValueCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
180
181 /* Get the actual data for it */
182 CellData = HvGetCell(Hive, ValueCell);
183 ASSERT(CellData);
184
185 /* Now we can release it, make sure it's also dirty */
186 HvReleaseCell(Hive, ValueCell);
187 ASSERT(HvIsCellDirty(Hive, ValueCell));
188
189 /* Set it up and copy the name */
192 {
193 /* This can crash since the name is coming from user-mode */
194 CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
195 CellData->u.KeyValue.Name,
196 ValueName);
197 }
199 {
200 /* Fail */
201 DPRINT1("Invalid user data!\n");
202 HvFreeCell(Hive, ValueCell);
204 }
205 _SEH2_END;
206
207 /* Check for compressed name */
208 if (CellData->u.KeyValue.NameLength < ValueName->Length)
209 {
210 /* This is a compressed name */
211 CellData->u.KeyValue.Flags = VALUE_COMP_NAME;
212 }
213 else
214 {
215 /* No flags to set */
216 CellData->u.KeyValue.Flags = 0;
217 }
218
219 /* Check if this is a normal key */
221 {
222 /* Build a data cell for it */
224 Data,
225 DataSize,
226 StorageType,
227 ValueCell,
228 &CellData->u.KeyValue.Data);
229 if (!NT_SUCCESS(Status))
230 {
231 /* We failed, free the cell */
232 HvFreeCell(Hive, ValueCell);
233 return Status;
234 }
235
236 /* Otherwise, set the data length, and make sure the data is dirty */
237 CellData->u.KeyValue.DataLength = DataSize;
238 ASSERT(HvIsCellDirty(Hive, CellData->u.KeyValue.Data));
239 }
240 else
241 {
242 /* This is a small key, set the data directly inside */
244 CellData->u.KeyValue.Data = SmallData;
245 }
246
247 /* Set the type now */
248 CellData->u.KeyValue.Type = Type;
249
250 /* Add this value cell to the child list */
252 ValueCell,
253 Index,
254 StorageType,
255 &Parent->ValueList);
256
257 /* If we failed, free the entire cell, including the data */
258 if (!NT_SUCCESS(Status))
259 {
260 /* Overwrite the status with a known one */
261 CmpFreeValue(Hive, ValueCell);
263 }
264
265 /* Return Status */
266 return Status;
267}
268
270NTAPI
272 IN HCELL_INDEX OldChild,
274 IN ULONG Type,
275 IN PVOID Data,
277 IN ULONG StorageType,
278 IN ULONG TempData)
279{
280 HCELL_INDEX DataCell, NewCell;
281 PCELL_DATA CellData;
283 BOOLEAN WasSmall, IsSmall;
284
285 /* Registry writes must be blocked */
287
288 /* Mark the old child cell dirty */
289 if (!HvMarkCellDirty(Hive, OldChild, FALSE)) return STATUS_NO_LOG_SPACE;
290
291 /* See if this is a small or normal key */
292 WasSmall = CmpIsKeyValueSmall(&Length, Value->DataLength);
293
294 /* See if our new data can fit in a small key */
295 IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
296
297 /* Big keys are unsupported */
300
301 /* Mark the old value dirty */
303
304 /* Check if we have a small key */
305 if (IsSmall)
306 {
307 /* Check if we had a normal key with some data in it */
308 if (!(WasSmall) && (Length > 0))
309 {
310 /* Free the previous data */
311 CmpFreeValueData(Hive, Value->Data, Length);
312 }
313
314 /* Write our data directly */
316 Value->Data = TempData;
317 Value->Type = Type;
318 return STATUS_SUCCESS;
319 }
320
321 /* We have a normal key. Was the old cell also normal and had data? */
322 if (!(WasSmall) && (Length > 0))
323 {
324 /* Get the current data cell and actual data inside it */
325 DataCell = Value->Data;
326 ASSERT(DataCell != HCELL_NIL);
327 CellData = HvGetCell(Hive, DataCell);
328 if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
329
330 /* Immediately release the cell */
331 HvReleaseCell(Hive, DataCell);
332
333 /* Make sure that the data cell actually has a size */
334 ASSERT(HvGetCellSize(Hive, CellData) > 0);
335
336 /* Check if the previous data cell could fit our new data */
337 if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData)))
338 {
339 /* Re-use it then */
340 NewCell = DataCell;
341 }
342 else
343 {
344 /* Otherwise, re-allocate the current data cell */
345 NewCell = HvReallocateCell(Hive, DataCell, DataSize);
346 if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
347 }
348 }
349 else
350 {
351 /* This was a small key, or a key with no data, allocate a cell */
352 NewCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
353 if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
354 }
355
356 /* Now get the actual data for our data cell */
357 CellData = HvGetCell(Hive, NewCell);
358 ASSERT(CellData);
359
360 /* Release it immediately */
361 HvReleaseCell(Hive, NewCell);
362
363 /* Copy our data into the data cell's buffer, and set up the value */
364 RtlCopyMemory(CellData, Data, DataSize);
365 Value->Data = NewCell;
366 Value->DataLength = DataSize;
367 Value->Type = Type;
368
369 /* Return success */
370 ASSERT(HvIsCellDirty(Hive, NewCell));
371 return STATUS_SUCCESS;
372}
373
375NTAPI
379 IN OUT PVOID KeyInformation,
382{
384 ULONG Size, SizeLeft, MinimumSize, Offset;
385 PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
386 USHORT NameLength;
388
389 /* Check if the value is compressed */
390 if (Node->Flags & KEY_COMP_NAME)
391 {
392 /* Get the compressed name size */
393 NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
394 }
395 else
396 {
397 /* Get the real size */
398 NameLength = Node->NameLength;
399 }
400
401 /* Check what kind of information is being requested */
402 switch (KeyInformationClass)
403 {
404 /* Basic information */
406
407 /* This is the size we need */
409
410 /* And this is the minimum we can work with */
412
413 /* Let the caller know and assume success */
416
417 /* Check if the bufer we got is too small */
418 if (Length < MinimumSize)
419 {
420 /* Let the caller know and fail */
422 break;
423 }
424
425 /* Copy the basic information */
426 Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
427 Info->KeyBasicInformation.TitleIndex = 0;
428 Info->KeyBasicInformation.NameLength = NameLength;
429
430 /* Only the name is left */
431 SizeLeft = Length - MinimumSize;
432 Size = NameLength;
433
434 /* Check if we don't have enough space for the name */
435 if (SizeLeft < Size)
436 {
437 /* Truncate the name we'll return, and tell the caller */
438 Size = SizeLeft;
440 }
441
442 /* Check if this is a compressed key */
443 if (Node->Flags & KEY_COMP_NAME)
444 {
445 /* Copy the compressed name */
446 CmpCopyCompressedName(Info->KeyBasicInformation.Name,
447 SizeLeft,
448 Node->Name,
449 Node->NameLength);
450 }
451 else
452 {
453 /* Otherwise, copy the raw name */
454 RtlCopyMemory(Info->KeyBasicInformation.Name,
455 Node->Name,
456 Size);
457 }
458 break;
459
460 /* Node information */
462
463 /* Calculate the size we need */
465 NameLength +
466 Node->ClassLength;
467
468 /* And the minimum size we can support */
469 MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
470
471 /* Return the size to the caller and assume succes */
474
475 /* Check if the caller's buffer is too small */
476 if (Length < MinimumSize)
477 {
478 /* Let them know, and fail */
480 break;
481 }
482
483 /* Copy the basic information */
484 Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
485 Info->KeyNodeInformation.TitleIndex = 0;
486 Info->KeyNodeInformation.ClassLength = Node->ClassLength;
487 Info->KeyNodeInformation.NameLength = NameLength;
488
489 /* Now the name is left */
490 SizeLeft = Length - MinimumSize;
491 Size = NameLength;
492
493 /* Check if the name can fit entirely */
494 if (SizeLeft < Size)
495 {
496 /* It can't, we'll have to truncate. Tell the caller */
497 Size = SizeLeft;
499 }
500
501 /* Check if the key node name is compressed */
502 if (Node->Flags & KEY_COMP_NAME)
503 {
504 /* Copy the compressed name */
505 CmpCopyCompressedName(Info->KeyNodeInformation.Name,
506 SizeLeft,
507 Node->Name,
508 Node->NameLength);
509 }
510 else
511 {
512 /* It isn't, so copy the raw name */
513 RtlCopyMemory(Info->KeyNodeInformation.Name,
514 Node->Name,
515 Size);
516 }
517
518 /* Check if the node has a class */
519 if (Node->ClassLength > 0)
520 {
521 /* Set the class offset */
523 Offset = ALIGN_UP_BY(Offset, sizeof(ULONG));
524 Info->KeyNodeInformation.ClassOffset = Offset;
525
526 /* Get the class data */
527 ClassData = HvGetCell(Hive, Node->Class);
528 if (ClassData == NULL)
529 {
531 break;
532 }
533
534 /* Check if we can copy anything */
535 if (Length > Offset)
536 {
537 /* Copy the class data */
539 ClassData,
540 min(Node->ClassLength, Length - Offset));
541 }
542
543 /* Check if the buffer was large enough */
544 if (Length < Offset + Node->ClassLength)
545 {
547 }
548
549 /* Release the class cell */
550 HvReleaseCell(Hive, Node->Class);
551 }
552 else
553 {
554 /* It doesn't, so set offset to -1, not 0! */
555 Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
556 }
557 break;
558
559 /* Full information requsted */
561
562 /* This is the size we need */
564 Node->ClassLength;
565
566 /* This is what we can work with */
568
569 /* Return it to caller and assume success */
572
573 /* Check if the caller's buffer is to small */
574 if (Length < MinimumSize)
575 {
576 /* Let them know and fail */
578 break;
579 }
580
581 /* Now copy all the basic information */
582 Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
583 Info->KeyFullInformation.TitleIndex = 0;
584 Info->KeyFullInformation.ClassLength = Node->ClassLength;
585 Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[Stable] +
586 Node->SubKeyCounts[Volatile];
587 Info->KeyFullInformation.Values = Node->ValueList.Count;
588 Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
589 Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
590 Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
591 Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
592
593 /* Check if we have a class */
594 if (Node->ClassLength > 0)
595 {
596 /* Set the class offset */
598 Info->KeyFullInformation.ClassOffset = Offset;
599
600 /* Get the class data */
601 ClassData = HvGetCell(Hive, Node->Class);
602 if (ClassData == NULL)
603 {
605 break;
606 }
607
608 /* Copy the class data */
609 ASSERT(Length >= Offset);
610 RtlCopyMemory(Info->KeyFullInformation.Class,
611 ClassData,
612 min(Node->ClassLength, Length - Offset));
613
614 /* Check if the buffer was large enough */
615 if (Length < Offset + Node->ClassLength)
616 {
618 }
619
620 /* Release the class cell */
621 HvReleaseCell(Hive, Node->Class);
622 }
623 else
624 {
625 /* We don't have a class, so set offset to -1, not 0! */
626 Info->KeyFullInformation.ClassOffset = 0xFFFFFFFF;
627 }
628 break;
629
630 /* Any other class that got sent here is invalid! */
631 default:
632
633 /* Set failure code */
635 break;
636 }
637
638 /* Return status */
639 return Status;
640}
641
643NTAPI
646 IN ULONG Type,
647 IN PVOID Data,
649{
650 PHHIVE Hive = NULL;
653 HCELL_INDEX CurrentChild, Cell;
656 ULONG Count, ChildIndex, SmallData, Storage;
657 VALUE_SEARCH_RETURN_TYPE SearchResult;
658 BOOLEAN FirstTry = TRUE, FlusherLocked = FALSE;
659 HCELL_INDEX ParentCell = HCELL_NIL, ChildCell = HCELL_NIL;
660
661 /* Acquire hive and KCB lock */
664
665 /* Sanity check */
666 ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL);
667
668 /* Don't touch deleted KCBs */
669DoAgain:
670 if (Kcb->Delete)
671 {
672 /* Fail */
674 goto Quickie;
675 }
676
677 /* Don't let anyone mess with symlinks */
678 if ((Kcb->Flags & KEY_SYM_LINK) &&
679 ((Type != REG_LINK) ||
680 !(ValueName) ||
682 {
683 /* Invalid modification of a symlink key */
685 goto Quickie;
686 }
687
688 /* Check if this is the first attempt */
689 if (FirstTry)
690 {
691 /* Search for the value in the cache */
692 SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb,
693 ValueName,
694 Type,
695 Data,
696 DataLength);
697 if (SearchResult == SearchNeedExclusiveLock)
698 {
699 /* Try again with the exclusive lock */
701 goto DoAgain;
702 }
703 else if (SearchResult == SearchSuccess)
704 {
705 /* We don't actually need to do anything! */
707 goto Quickie;
708 }
709
710 /* We need the exclusive KCB lock now */
711 if (!(CmpIsKcbLockedExclusive(Kcb)) &&
713 {
714 /* Acquire exclusive lock */
716 }
717
718 /* Cache lookup failed, so don't try it next time */
719 FirstTry = FALSE;
720
721 /* Now grab the flush lock since the key will be modified */
722 ASSERT(FlusherLocked == FALSE);
723 CmpLockHiveFlusherShared((PCMHIVE)Kcb->KeyHive);
724 FlusherLocked = TRUE;
725 goto DoAgain;
726 }
727 else
728 {
729 /* Get pointer to key cell */
730 Hive = Kcb->KeyHive;
731 Cell = Kcb->KeyCell;
732
733 /* Get the parent */
734 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
735 ASSERT(Parent);
736 ParentCell = Cell;
737
738 /* Prepare to scan the key node */
739 Count = Parent->ValueList.Count;
740 Found = FALSE;
741 if (Count > 0)
742 {
743 /* Try to find the existing name */
745 &Parent->ValueList,
746 ValueName,
747 &ChildIndex,
748 &CurrentChild);
749 if (!Result)
750 {
751 /* Fail */
753 goto Quickie;
754 }
755
756 /* Check if we found something */
757 if (CurrentChild != HCELL_NIL)
758 {
759 /* Release existing child */
760 if (ChildCell != HCELL_NIL)
761 {
762 HvReleaseCell(Hive, ChildCell);
763 ChildCell = HCELL_NIL;
764 }
765
766 /* Get its value */
767 Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild);
768 if (!Value)
769 {
770 /* Fail */
772 goto Quickie;
773 }
774
775 /* Remember that we found it */
776 ChildCell = CurrentChild;
777 Found = TRUE;
778 }
779 }
780 else
781 {
782 /* No child list, we'll need to add it */
783 ChildIndex = 0;
784 }
785 }
786
787 /* Should only get here on the second pass */
789
790 /* The KCB must be locked exclusive at this point */
792
793 /* Mark the cell dirty */
794 if (!HvMarkCellDirty(Hive, Cell, FALSE))
795 {
796 /* Not enough log space, fail */
798 goto Quickie;
799 }
800
801 /* Get the storage type */
802 Storage = HvGetCellType(Cell);
803
804 /* Check if this is small data */
805 SmallData = 0;
806 if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0))
807 {
808 /* Need SEH because user data may be invalid */
810 {
811 /* Copy it */
812 RtlCopyMemory(&SmallData, Data, DataLength);
813 }
815 {
816 /* Return failure code */
818 _SEH2_YIELD(goto Quickie);
819 }
820 _SEH2_END;
821 }
822
823 /* Check if we didn't find a matching key */
824 if (!Found)
825 {
826 /* Call the internal routine */
828 Parent,
829 ValueName,
830 ChildIndex,
831 Type,
832 Data,
834 Storage,
835 SmallData);
836 }
837 else
838 {
839 /* Call the internal routine */
841 CurrentChild,
842 Value,
843 Type,
844 Data,
846 Storage,
847 SmallData);
848 }
849
850 /* Check for success */
851 if (NT_SUCCESS(Status))
852 {
853 /* Check if the maximum value name length changed */
854 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
855 if (Parent->MaxValueNameLen < ValueName->Length)
856 {
857 /* Set the new values */
858 Parent->MaxValueNameLen = ValueName->Length;
859 Kcb->KcbMaxValueNameLen = ValueName->Length;
860 }
861
862 /* Check if the maximum data length changed */
863 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
864 if (Parent->MaxValueDataLen < DataLength)
865 {
866 /* Update it */
867 Parent->MaxValueDataLen = DataLength;
868 Kcb->KcbMaxValueDataLen = Parent->MaxValueDataLen;
869 }
870
871 /* Save the write time */
872 KeQuerySystemTime(&Parent->LastWriteTime);
873 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
874
875 /* Check if the cell is cached */
876 if ((Found) && (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)))
877 {
878 /* Shouldn't happen */
879 ASSERT(FALSE);
880 }
881 else
882 {
883 /* Cleanup the value cache */
885
886 /* Sanity checks */
887 ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
888 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
889
890 /* Set the value cache */
891 Kcb->ValueCache.Count = Parent->ValueList.Count;
892 Kcb->ValueCache.ValueList = Parent->ValueList.List;
893 }
894
895 /* Notify registered callbacks */
896 CmpReportNotify(Kcb,
897 Hive,
898 Kcb->KeyCell,
900 }
901
902 /* Release the cells */
903Quickie:
904 if ((ParentCell != HCELL_NIL) && (Hive)) HvReleaseCell(Hive, ParentCell);
905 if ((ChildCell != HCELL_NIL) && (Hive)) HvReleaseCell(Hive, ChildCell);
906
907 /* Release the locks */
908 if (FlusherLocked) CmpUnlockHiveFlusher((PCMHIVE)Hive);
911 return Status;
912}
913
915NTAPI
918{
920 PHHIVE Hive;
922 HCELL_INDEX ChildCell, Cell;
925 ULONG ChildIndex;
927
928 /* Acquire hive lock */
930
931 /* Lock KCB exclusively */
933
934 /* Don't touch deleted keys */
935 if (Kcb->Delete)
936 {
937 /* Undo everything */
940 return STATUS_KEY_DELETED;
941 }
942
943 /* Get the hive and the cell index */
944 Hive = Kcb->KeyHive;
945 Cell = Kcb->KeyCell;
946
947 /* Lock flushes */
949
950 /* Get the parent key node */
951 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
952 ASSERT(Parent);
953
954 /* Get the value list and check if it has any entries */
955 ChildList = &Parent->ValueList;
956 if (ChildList->Count)
957 {
958 /* Try to find this value */
960 ChildList,
961 &ValueName,
962 &ChildIndex,
963 &ChildCell);
964 if (!Result)
965 {
966 /* Fail */
968 goto Quickie;
969 }
970
971 /* Value not found, return error */
972 if (ChildCell == HCELL_NIL) goto Quickie;
973
974 /* We found the value, mark all relevant cells dirty */
975 if (!((HvMarkCellDirty(Hive, Cell, FALSE)) &&
976 (HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE)) &&
977 (HvMarkCellDirty(Hive, ChildCell, FALSE))))
978 {
979 /* Not enough log space, fail */
981 goto Quickie;
982 }
983
984 /* Get the key value */
985 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ChildCell);
986 ASSERT(Value);
987
988 /* Mark it and all related data as dirty */
989 if (!CmpMarkValueDataDirty(Hive, Value))
990 {
991 /* Not enough log space, fail */
993 goto Quickie;
994 }
995
996 /* Sanity checks */
997 ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
998 ASSERT(HvIsCellDirty(Hive, ChildCell));
999
1000 /* Remove the value from the child list */
1001 Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList);
1002 if (!NT_SUCCESS(Status))
1003 {
1004 /* Set known error */
1006 goto Quickie;
1007 }
1008
1009 /* Remove the value and its data itself */
1010 if (!CmpFreeValue(Hive, ChildCell))
1011 {
1012 /* Failed to free the value, fail */
1014 goto Quickie;
1015 }
1016
1017 /* Set the last write time */
1018 KeQuerySystemTime(&Parent->LastWriteTime);
1019 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
1020
1021 /* Sanity check */
1022 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1023 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1024 ASSERT(HvIsCellDirty(Hive, Cell));
1025
1026 /* Check if the value list is empty now */
1027 if (!Parent->ValueList.Count)
1028 {
1029 /* Then clear key node data */
1030 Parent->MaxValueNameLen = 0;
1031 Parent->MaxValueDataLen = 0;
1032 Kcb->KcbMaxValueNameLen = 0;
1033 Kcb->KcbMaxValueDataLen = 0;
1034 }
1035
1036 /* Cleanup the value cache */
1038
1039 /* Sanity checks */
1040 ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
1041 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
1042
1043 /* Set the value cache */
1044 Kcb->ValueCache.Count = ChildList->Count;
1045 Kcb->ValueCache.ValueList = ChildList->List;
1046
1047 /* Notify registered callbacks */
1049
1050 /* Change default Status to success */
1052 }
1053
1054Quickie:
1055 /* Release the parent cell, if any */
1056 if (Parent) HvReleaseCell(Hive, Cell);
1057
1058 /* Check if we had a value */
1059 if (Value)
1060 {
1061 /* Release the child cell */
1062 ASSERT(ChildCell != HCELL_NIL);
1063 HvReleaseCell(Hive, ChildCell);
1064 }
1065
1066 /* Release locks */
1068 CmpReleaseKcbLock(Kcb);
1070 return Status;
1071}
1072
1074NTAPI
1078 IN PVOID KeyValueInformation,
1079 IN ULONG Length,
1081{
1084 ULONG Index;
1085 BOOLEAN ValueCached = FALSE;
1086 PCM_CACHED_VALUE *CachedValue;
1087 HCELL_INDEX CellToRelease;
1089 PHHIVE Hive;
1090 PAGED_CODE();
1091
1092 /* Acquire hive lock */
1094
1095 /* Lock the KCB shared */
1097
1098 /* Don't touch deleted keys */
1099DoAgain:
1100 if (Kcb->Delete)
1101 {
1102 /* Undo everything */
1103 CmpReleaseKcbLock(Kcb);
1105 return STATUS_KEY_DELETED;
1106 }
1107
1108 /* We don't deal with this yet */
1109 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1110 {
1111 /* Shouldn't happen */
1112 ASSERT(FALSE);
1113 }
1114
1115 /* Get the hive */
1116 Hive = Kcb->KeyHive;
1117
1118 /* Find the key value */
1120 &ValueName,
1121 &CachedValue,
1122 &Index,
1123 &ValueData,
1124 &ValueCached,
1125 &CellToRelease);
1127 {
1128 /* Check if we need an exclusive lock */
1129 ASSERT(CellToRelease == HCELL_NIL);
1130 ASSERT(ValueData == NULL);
1131
1132 /* Try with exclusive KCB lock */
1134 goto DoAgain;
1135 }
1136
1137 if (Result == SearchSuccess)
1138 {
1139 /* Sanity check */
1140 ASSERT(ValueData != NULL);
1141
1142 /* User data, protect against exceptions */
1143 _SEH2_TRY
1144 {
1145 /* Query the information requested */
1147 CachedValue,
1148 ValueData,
1149 ValueCached,
1151 KeyValueInformation,
1152 Length,
1154 &Status);
1156 {
1157 /* Release the value cell */
1158 if (CellToRelease != HCELL_NIL)
1159 {
1160 HvReleaseCell(Hive, CellToRelease);
1161 CellToRelease = HCELL_NIL;
1162 }
1163
1164 /* Try with exclusive KCB lock */
1166 _SEH2_YIELD(goto DoAgain);
1167 }
1168 }
1170 {
1172 }
1173 _SEH2_END;
1174 }
1175 else
1176 {
1177 /* Failed to find the value */
1179 }
1180
1181 /* If we have a cell to release, do so */
1182 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1183
1184 /* Release locks */
1185 CmpReleaseKcbLock(Kcb);
1187 return Status;
1188}
1189
1191NTAPI
1193 IN ULONG Index,
1195 IN PVOID KeyValueInformation,
1196 IN ULONG Length,
1198{
1200 PHHIVE Hive;
1202 HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL;
1204 BOOLEAN IndexIsCached, ValueIsCached = FALSE;
1205 PCELL_DATA CellData;
1206 PCM_CACHED_VALUE *CachedValue;
1208 PAGED_CODE();
1209
1210 /* Acquire hive lock */
1212
1213 /* Lock the KCB shared */
1215
1216 /* Don't touch deleted keys */
1217DoAgain:
1218 if (Kcb->Delete)
1219 {
1220 /* Undo everything */
1221 CmpReleaseKcbLock(Kcb);
1223 return STATUS_KEY_DELETED;
1224 }
1225
1226 /* Get the hive and parent */
1227 Hive = Kcb->KeyHive;
1228 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1229 ASSERT(Parent);
1230
1231 /* FIXME: Lack of cache? */
1232 if (Kcb->ValueCache.Count != Parent->ValueList.Count)
1233 {
1234 DPRINT1("HACK: Overriding value cache count\n");
1235 Kcb->ValueCache.Count = Parent->ValueList.Count;
1236 }
1237
1238 /* Make sure the index is valid */
1239 if (Index >= Kcb->ValueCache.Count)
1240 {
1241 /* Release the cell and fail */
1242 HvReleaseCell(Hive, Kcb->KeyCell);
1244 goto Quickie;
1245 }
1246
1247 /* We don't deal with this yet */
1248 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1249 {
1250 /* Shouldn't happen */
1251 ASSERT(FALSE);
1252 }
1253
1254 /* Find the value list */
1256 &CellData,
1257 &IndexIsCached,
1258 &CellToRelease);
1260 {
1261 /* Check if we need an exclusive lock */
1262 ASSERT(CellToRelease == HCELL_NIL);
1263 HvReleaseCell(Hive, Kcb->KeyCell);
1264
1265 /* Try with exclusive KCB lock */
1267 goto DoAgain;
1268 }
1269 else if (Result != SearchSuccess)
1270 {
1271 /* Sanity check */
1272 ASSERT(CellData == NULL);
1273
1274 /* Release the cell and fail */
1276 goto Quickie;
1277 }
1278
1279 /* Now get the key value */
1281 CellData,
1282 Index,
1283 &CachedValue,
1284 &ValueData,
1285 IndexIsCached,
1286 &ValueIsCached,
1287 &CellToRelease2);
1289 {
1290 /* Cleanup state */
1291 ASSERT(CellToRelease2 == HCELL_NIL);
1292 if (CellToRelease)
1293 {
1294 HvReleaseCell(Hive, CellToRelease);
1295 CellToRelease = HCELL_NIL;
1296 }
1297 HvReleaseCell(Hive, Kcb->KeyCell);
1298
1299 /* Try with exclusive KCB lock */
1301 goto DoAgain;
1302 }
1303 else if (Result != SearchSuccess)
1304 {
1305 /* Sanity check */
1306 ASSERT(ValueData == NULL);
1307
1308 /* Release the cells and fail */
1310 goto Quickie;
1311 }
1312
1313 /* User data, need SEH */
1314 _SEH2_TRY
1315 {
1316 /* Query the information requested */
1318 CachedValue,
1319 ValueData,
1320 ValueIsCached,
1322 KeyValueInformation,
1323 Length,
1325 &Status);
1327 {
1328 /* Cleanup state */
1329 if (CellToRelease2) HvReleaseCell(Hive, CellToRelease2);
1330 HvReleaseCell(Hive, Kcb->KeyCell);
1331 if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
1332
1333 /* Try with exclusive KCB lock */
1335 _SEH2_YIELD(goto DoAgain);
1336 }
1337 }
1339 {
1340 /* Get exception code */
1342 }
1343 _SEH2_END;
1344
1345Quickie:
1346 /* If we have a cell to release, do so */
1347 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1348
1349 /* Release the parent cell */
1350 HvReleaseCell(Hive, Kcb->KeyCell);
1351
1352 /* If we have a cell to release, do so */
1353 if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2);
1354
1355 /* Release locks */
1356 CmpReleaseKcbLock(Kcb);
1358 return Status;
1359}
1360
1361static
1365 _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo,
1368{
1370 PHHIVE KeyHive;
1371 HCELL_INDEX KeyCell;
1372 USHORT NameLength;
1373 PAGED_CODE();
1374
1375 /* Get the hive and cell index */
1376 KeyHive = Kcb->KeyHash.KeyHive;
1377 KeyCell = Kcb->KeyHash.KeyCell;
1378
1379#if DBG
1380 /* Get the cell node */
1381 Node = (PCM_KEY_NODE)HvGetCell(KeyHive, KeyCell);
1382 if (Node != NULL)
1383 {
1384 ULONG SubKeyCount;
1385 ASSERT(Node->ValueList.Count == Kcb->ValueCache.Count);
1386
1387 if (!(Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO))
1388 {
1389 SubKeyCount = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
1390 if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
1391 {
1392 ASSERT(SubKeyCount == 0);
1393 }
1394 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
1395 {
1396 ASSERT(SubKeyCount == 1);
1397 }
1398 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
1399 {
1400 ASSERT(SubKeyCount == Kcb->IndexHint->Count);
1401 }
1402 else
1403 {
1404 ASSERT(SubKeyCount == Kcb->SubKeyCount);
1405 }
1406 }
1407
1408 ASSERT(Node->LastWriteTime.QuadPart == Kcb->KcbLastWriteTime.QuadPart);
1409 ASSERT(Node->MaxNameLen == Kcb->KcbMaxNameLen);
1410 ASSERT(Node->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1411 ASSERT(Node->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1412
1413 /* Release the cell */
1414 HvReleaseCell(KeyHive, KeyCell);
1415 }
1416#endif // DBG
1417
1418 /* Make sure we have a name block */
1419 if (Kcb->NameBlock == NULL)
1420 {
1422 }
1423
1424 /* Check for compressed name */
1425 if (Kcb->NameBlock->Compressed)
1426 {
1427 /* Calculate the name size */
1428 NameLength = CmpCompressedNameSize(Kcb->NameBlock->NameHash.Name,
1429 Kcb->NameBlock->NameHash.NameLength);
1430 }
1431 else
1432 {
1433 /* Use the stored name size */
1434 NameLength = Kcb->NameBlock->NameHash.NameLength;
1435 }
1436
1437 /* Validate buffer length (we do not copy the name!) */
1438 *ResultLength = sizeof(*KeyCachedInfo);
1439 if (Length < *ResultLength)
1440 {
1442 }
1443
1444 /* Fill the structure */
1445 KeyCachedInfo->LastWriteTime = Kcb->KcbLastWriteTime;
1446 KeyCachedInfo->TitleIndex = 0;
1447 KeyCachedInfo->NameLength = NameLength;
1448 KeyCachedInfo->Values = Kcb->ValueCache.Count;
1449 KeyCachedInfo->MaxNameLen = Kcb->KcbMaxNameLen;
1450 KeyCachedInfo->MaxValueNameLen = Kcb->KcbMaxValueNameLen;
1451 KeyCachedInfo->MaxValueDataLen = Kcb->KcbMaxValueDataLen;
1452
1453 /* Check the ExtFlags for what we have */
1454 if (Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO)
1455 {
1456 /* Cache is not valid, do a full lookup */
1457 DPRINT1("Kcb cache incoherency detected, kcb = %p\n", Kcb);
1458
1459 /* Get the cell node */
1460 Node = (PCM_KEY_NODE)HvGetCell(KeyHive, KeyCell);
1461 if (Node == NULL)
1462 {
1464 }
1465
1466 /* Calculate number of subkeys */
1467 KeyCachedInfo->SubKeys = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
1468
1469 /* Release the cell */
1470 HvReleaseCell(KeyHive, KeyCell);
1471 }
1472 else if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
1473 {
1474 /* There are no subkeys */
1475 KeyCachedInfo->SubKeys = 0;
1476 }
1477 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
1478 {
1479 /* There is exactly one subley */
1480 KeyCachedInfo->SubKeys = 1;
1481 }
1482 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
1483 {
1484 /* Get the number of subkeys from the subkey hint */
1485 KeyCachedInfo->SubKeys = Kcb->IndexHint->Count;
1486 }
1487 else
1488 {
1489 /* No subkey hint, use the key count field */
1490 KeyCachedInfo->SubKeys = Kcb->SubKeyCount;
1491 }
1492
1493 return STATUS_SUCCESS;
1494}
1495
1496static
1500 _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo,
1503{
1504 /* Validate the buffer size */
1505 *ResultLength = sizeof(*KeyFlagsInfo);
1506 if (Length < *ResultLength)
1507 {
1509 }
1510
1511 /* Copy the user flags */
1512 KeyFlagsInfo->UserFlags = Kcb->KcbUserFlags;
1513
1514 return STATUS_SUCCESS;
1515}
1516
1517static
1521 _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo,
1524{
1525 ULONG NeededLength;
1526 PCM_KEY_CONTROL_BLOCK CurrentKcb;
1527
1528 NeededLength = 0;
1529 CurrentKcb = Kcb;
1530
1531 /* Count the needed buffer size */
1532 while (CurrentKcb)
1533 {
1534 if (CurrentKcb->NameBlock->Compressed)
1535 NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1536 else
1537 NeededLength += CurrentKcb->NameBlock->NameLength;
1538
1539 NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1540
1541 CurrentKcb = CurrentKcb->ParentKcb;
1542 }
1543
1544 _SEH2_TRY
1545 {
1549 if (Length < *ResultLength)
1550 {
1551 KeyNameInfo->NameLength = NeededLength;
1553 }
1554 }
1556 {
1558 }
1559 _SEH2_END;
1560
1561 /* Do the real copy */
1562 KeyNameInfo->NameLength = 0;
1563 CurrentKcb = Kcb;
1564
1565 _SEH2_TRY
1566 {
1567 while (CurrentKcb)
1568 {
1569 ULONG NameLength;
1570
1571 if (CurrentKcb->NameBlock->Compressed)
1572 {
1573 NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1574 /* Copy the compressed name */
1575 CmpCopyCompressedName(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1576 NameLength,
1577 CurrentKcb->NameBlock->Name,
1578 CurrentKcb->NameBlock->NameLength);
1579 }
1580 else
1581 {
1582 NameLength = CurrentKcb->NameBlock->NameLength;
1583 /* Otherwise, copy the raw name */
1584 RtlCopyMemory(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1585 CurrentKcb->NameBlock->Name,
1586 NameLength);
1587 }
1588
1589 NeededLength -= NameLength;
1590 NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1591 /* Add path separator */
1592 KeyNameInfo->Name[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1593 KeyNameInfo->NameLength += NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
1594
1595 CurrentKcb = CurrentKcb->ParentKcb;
1596 }
1597 }
1599 {
1601 }
1602 _SEH2_END;
1603
1604 /* Make sure we copied everything */
1605 ASSERT(NeededLength == 0);
1606 ASSERT(KeyNameInfo->Name[0] == OBJ_NAME_PATH_SEPARATOR);
1607
1608 /* We're done */
1609 return STATUS_SUCCESS;
1610}
1611
1612
1614NTAPI
1617 _Out_opt_ PVOID KeyInformation,
1620{
1622 PHHIVE Hive;
1624 HV_TRACK_CELL_REF CellReferences = {0};
1625
1626 /* Acquire hive lock */
1628
1629 /* Lock KCB shared */
1631
1632 /* Don't touch deleted keys */
1633 if (Kcb->Delete)
1634 {
1635 /* Fail */
1637 goto Quickie;
1638 }
1639
1640 /* Data can be user-mode, use SEH */
1641 _SEH2_TRY
1642 {
1643 /* Check what class we got */
1644 switch (KeyInformationClass)
1645 {
1646 /* Typical information */
1647 case KeyFullInformation:
1649 case KeyNodeInformation:
1650 {
1651 /* Get the hive and parent */
1652 Hive = Kcb->KeyHive;
1653 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1654 ASSERT(Parent);
1655
1656 /* Track cell references */
1657 if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
1658 {
1659 /* Not enough memory to track references */
1661 }
1662 else
1663 {
1664 /* Call the internal API */
1665 Status = CmpQueryKeyData(Hive,
1666 Parent,
1668 KeyInformation,
1669 Length,
1670 ResultLength);
1671 }
1672 break;
1673 }
1674
1676 {
1677 /* Call the internal API */
1679 KeyInformation,
1680 Length,
1681 ResultLength);
1682 break;
1683 }
1684
1686 {
1687 /* Call the internal API */
1689 KeyInformation,
1690 Length,
1691 ResultLength);
1692 break;
1693 }
1694
1695 case KeyNameInformation:
1696 {
1697 /* Call the internal API */
1699 KeyInformation,
1700 Length,
1701 ResultLength);
1702 break;
1703 }
1704
1705 /* Illegal classes */
1706 default:
1707 {
1708 /* Print message and fail */
1709 DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
1711 break;
1712 }
1713 }
1714 }
1716 {
1717 /* Fail with exception code */
1719 _SEH2_YIELD(goto Quickie);
1720 }
1721 _SEH2_END;
1722
1723Quickie:
1724 /* Release references */
1725 HvReleaseFreeCellRefArray(&CellReferences);
1726
1727 /* Release locks */
1728 CmpReleaseKcbLock(Kcb);
1730 return Status;
1731}
1732
1734NTAPI
1736 IN ULONG Index,
1738 IN PVOID KeyInformation,
1739 IN ULONG Length,
1741{
1743 PHHIVE Hive;
1745 HCELL_INDEX ChildCell;
1746 HV_TRACK_CELL_REF CellReferences = {0};
1747
1748 /* Acquire hive lock */
1750
1751 /* Lock the KCB shared */
1753
1754 /* Don't touch deleted keys */
1755 if (Kcb->Delete)
1756 {
1757 /* Undo everything */
1759 goto Quickie;
1760 }
1761
1762 /* Get the hive and parent */
1763 Hive = Kcb->KeyHive;
1764 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1765 ASSERT(Parent);
1766
1767 /* Get the child cell */
1768 ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
1769
1770 /* Release the parent cell */
1771 HvReleaseCell(Hive, Kcb->KeyCell);
1772
1773 /* Check if we found the child */
1774 if (ChildCell == HCELL_NIL)
1775 {
1776 /* We didn't, fail */
1778 goto Quickie;
1779 }
1780
1781 /* Now get the actual child node */
1782 Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
1783 ASSERT(Child);
1784
1785 /* Track references */
1786 if (!HvTrackCellRef(&CellReferences, Hive, ChildCell))
1787 {
1788 /* Can't allocate memory for tracking */
1790 goto Quickie;
1791 }
1792
1793 /* Data can be user-mode, use SEH */
1794 _SEH2_TRY
1795 {
1796 /* Query the data requested */
1797 Status = CmpQueryKeyData(Hive,
1798 Child,
1800 KeyInformation,
1801 Length,
1802 ResultLength);
1803 }
1805 {
1806 /* Fail with exception code */
1808 _SEH2_YIELD(goto Quickie);
1809 }
1810 _SEH2_END;
1811
1812Quickie:
1813 /* Release references */
1814 HvReleaseFreeCellRefArray(&CellReferences);
1815
1816 /* Release locks */
1817 CmpReleaseKcbLock(Kcb);
1819 return Status;
1820}
1821
1823NTAPI
1825{
1827 PHHIVE Hive;
1829 HCELL_INDEX Cell, ParentCell;
1831
1832 /* Acquire hive lock */
1834
1835 /* Get the kcb */
1836 Kcb = KeyBody->KeyControlBlock;
1837
1838 /* Don't allow deleting the root */
1839 if (!Kcb->ParentKcb)
1840 {
1841 /* Fail */
1843 return STATUS_CANNOT_DELETE;
1844 }
1845
1846 /* Lock parent and child */
1848
1849 /* Check if we're already being deleted */
1850 if (Kcb->Delete)
1851 {
1852 /* Don't do it twice */
1854 goto Quickie;
1855 }
1856
1857 /* Get the hive and node */
1858 Hive = Kcb->KeyHive;
1859 Cell = Kcb->KeyCell;
1860
1861 /* Lock flushes */
1863
1864 /* Get the key node */
1865 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1866 ASSERT(Node);
1867
1868 /* Sanity check */
1869 ASSERT(Node->Flags == Kcb->Flags);
1870
1871 /* Check if we don't have any children */
1872 if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]) &&
1873 !(Node->Flags & KEY_NO_DELETE))
1874 {
1875 /* Send notification to registered callbacks */
1876 CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_NAME);
1877
1878 /* Get the parent and free the cell */
1879 ParentCell = Node->Parent;
1880 Status = CmpFreeKeyByCell(Hive, Cell, TRUE);
1881 if (NT_SUCCESS(Status))
1882 {
1883 /* Flush any notifications */
1885
1886 /* Clean up information we have on the subkey */
1888
1889 /* Get the parent node */
1890 Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
1891 if (Parent)
1892 {
1893 /* Update the maximum name length */
1894 Kcb->ParentKcb->KcbMaxNameLen = (USHORT)Parent->MaxNameLen;
1895
1896 /* Make sure we're dirty */
1897 ASSERT(HvIsCellDirty(Hive, ParentCell));
1898
1899 /* Update the write time */
1900 KeQuerySystemTime(&Parent->LastWriteTime);
1901 Kcb->ParentKcb->KcbLastWriteTime = Parent->LastWriteTime;
1902
1903 /* Release the cell */
1904 HvReleaseCell(Hive, ParentCell);
1905 }
1906
1907 /* Set the KCB in delete mode and remove it */
1908 Kcb->Delete = TRUE;
1910
1911 /* Clear the cell */
1912 Kcb->KeyCell = HCELL_NIL;
1913 }
1914 }
1915 else
1916 {
1917 /* Fail */
1919 }
1920
1921 /* Release the cell */
1922 HvReleaseCell(Hive, Cell);
1923
1924 /* Release flush lock */
1926
1927 /* Release the KCB locks */
1928Quickie:
1929 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
1930
1931 /* Release hive lock */
1933 return Status;
1934}
1935
1937NTAPI
1940{
1941 PCMHIVE CmHive;
1943 PHHIVE Hive;
1944
1945 /* Ignore flushes until we're ready */
1946 if (CmpNoWrite) return STATUS_SUCCESS;
1947
1948 /* Get the hives */
1949 Hive = Kcb->KeyHive;
1950 CmHive = (PCMHIVE)Hive;
1951
1952 /* Check if this is the master hive */
1953 if (CmHive == CmiVolatileHive)
1954 {
1955 /* Flush all the hives instead */
1957 }
1958 else
1959 {
1960 /* Don't touch the hive */
1962
1963 ASSERT(CmHive->ViewLock);
1966
1967 /* Will the hive shrink? */
1968 if (HvHiveWillShrink(Hive))
1969 {
1970 /* I don't believe the current Hv does shrinking */
1971 ASSERT(FALSE);
1972 // CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(CmHive);
1973 }
1974 else
1975 {
1976 /* Now we can release views */
1977 ASSERT(CmHive->ViewLock);
1978 // CMP_ASSERT_VIEW_LOCK_OWNED(CmHive);
1980 (CmHive->HiveIsLoading == TRUE) ||
1981 (CmHive->ViewLockOwner == KeGetCurrentThread()) ||
1983 CmHive->ViewLockOwner = NULL;
1985 }
1986
1987 /* Flush only this hive */
1988 if (!HvSyncHive(Hive))
1989 {
1990 /* Fail */
1992 }
1993
1994 /* Release the flush lock */
1995 CmpUnlockHiveFlusher(CmHive);
1996 }
1997
1998 /* Return the status */
1999 return Status;
2000}
2001
2003NTAPI
2005 IN POBJECT_ATTRIBUTES SourceFile,
2006 IN ULONG Flags,
2007 IN PCM_KEY_BODY KeyBody)
2008{
2009 SECURITY_QUALITY_OF_SERVICE ServiceQos;
2010 SECURITY_CLIENT_CONTEXT ClientSecurityContext;
2013 PCMHIVE CmHive, LoadedHive;
2015 CM_PARSE_CONTEXT ParseContext;
2016
2017 /* Check if we have a trust key */
2018 if (KeyBody)
2019 {
2020 /* Fail */
2021 DPRINT("Trusted classes not yet supported\n");
2022 }
2023
2024 /* Build a service QoS for a security context */
2025 ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2028 ServiceQos.EffectiveOnly = TRUE;
2030 &ServiceQos,
2031 FALSE,
2032 &ClientSecurityContext);
2033 if (!NT_SUCCESS(Status))
2034 {
2035 /* Fail */
2036 DPRINT1("Security context failed\n");
2037 return Status;
2038 }
2039
2040 /* Open the target key */
2041 RtlZeroMemory(&ParseContext, sizeof(ParseContext));
2042 ParseContext.CreateOperation = FALSE;
2043 Status = ObOpenObjectByName(TargetKey,
2045 KernelMode,
2046 NULL,
2047 KEY_READ,
2048 &ParseContext,
2049 &KeyHandle);
2051
2052 /* Open the hive */
2053 Status = CmpCmdHiveOpen(SourceFile,
2054 &ClientSecurityContext,
2055 &Allocate,
2056 &CmHive,
2057 0);
2058
2059 /* Get rid of the security context */
2060 SeDeleteClientSecurity(&ClientSecurityContext);
2061
2062 /* See if we failed */
2063 if (!NT_SUCCESS(Status))
2064 {
2065 /* See if the target already existed */
2066 if (KeyHandle)
2067 {
2068 /* Lock the registry */
2070
2071 /* Check if we are already loaded */
2072 if (CmpIsHiveAlreadyLoaded(KeyHandle, SourceFile, &LoadedHive))
2073 {
2074 /* That's okay then */
2075 ASSERT(LoadedHive);
2077 }
2078
2079 /* Release the registry */
2081 }
2082
2083 /* Close the key handle if we had one */
2085 return Status;
2086 }
2087
2088 /* Lock the registry shared */
2090
2091 /* Lock loading */
2093
2094 /* Lock the hive to this thread */
2095 CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING;
2096 CmHive->CreatorOwner = KeGetCurrentThread();
2097
2098 /* Set flag */
2100
2101 /* Link the hive */
2102 Status = CmpLinkHiveToMaster(TargetKey->ObjectName,
2103 TargetKey->RootDirectory,
2104 CmHive,
2105 Allocate,
2106 TargetKey->SecurityDescriptor);
2107 if (NT_SUCCESS(Status))
2108 {
2109 /* Add to HiveList key */
2110 CmpAddToHiveFileList(CmHive);
2111
2112 /* Sync the hive if necessary */
2113 if (Allocate)
2114 {
2115 /* Sync it under the flusher lock */
2117 HvSyncHive(&CmHive->Hive);
2118 CmpUnlockHiveFlusher(CmHive);
2119 }
2120
2121 /* Release the hive */
2122 CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING;
2123 CmHive->CreatorOwner = NULL;
2124 }
2125 else
2126 {
2127 DPRINT1("CmpLinkHiveToMaster failed, Status %lx\n", Status);
2128
2129 /* We're touching this hive, set the loading flag */
2130 CmHive->HiveIsLoading = TRUE;
2131
2132 /* Close associated file handles */
2133 CmpCloseHiveFiles(CmHive);
2134
2135 /* Cleanup its resources */
2136 CmpDestroyHive(CmHive);
2137 }
2138
2139 /* Allow loads */
2141
2142 /* Is this first profile load? */
2144 {
2145 /* User is now logged on, set quotas */
2148 }
2149
2150 /* Unlock the registry */
2152
2153 /* Close handle and return */
2155 return Status;
2156}
2157
2158static
2159BOOLEAN
2160NTAPI
2162 IN HCELL_INDEX Cell)
2163{
2164 PCELL_DATA CellData;
2165 HCELL_INDEX LinkCell;
2167
2168 DPRINT("CmpUnlinkHiveFromMaster()\n");
2169
2170 /* Get the cell data */
2171 CellData = HvGetCell(&CmHive->Hive, Cell);
2172 if (CellData == NULL)
2173 return FALSE;
2174
2175 /* Get the link cell and release the current cell */
2176 LinkCell = CellData->u.KeyNode.Parent;
2177 HvReleaseCell(&CmHive->Hive, Cell);
2178
2179 /* Remove the link cell from the master hive */
2182 LinkCell,
2183 TRUE);
2185 if (!NT_SUCCESS(Status))
2186 {
2187 DPRINT1("CmpFreeKeyByCell() failed (Status 0x%08lx)\n", Status);
2188 return FALSE;
2189 }
2190
2191 /* Remove the hive from the list */
2193 RemoveEntryList(&CmHive->HiveList);
2195
2196 return TRUE;
2197}
2198
2200NTAPI
2202 IN ULONG Flags)
2203{
2204 PHHIVE Hive;
2205 PCMHIVE CmHive;
2206 HCELL_INDEX Cell;
2207
2208 DPRINT("CmUnloadKey(%p, %lx)\n", Kcb, Flags);
2209
2210 /* Get the hive */
2211 Hive = Kcb->KeyHive;
2212 Cell = Kcb->KeyCell;
2213 CmHive = (PCMHIVE)Hive;
2214
2215 /* Fail if the key is not a hive root key */
2216 if (Cell != Hive->BaseBlock->RootCell)
2217 {
2218 DPRINT1("Key is not a hive root key!\n");
2220 }
2221
2222 /* Fail if we try to unload the master hive */
2223 if (CmHive == CmiVolatileHive)
2224 {
2225 DPRINT1("Do not try to unload the master hive!\n");
2227 }
2228
2229 /* Mark this hive as being unloaded */
2231
2232 /* Search for any opened keys in this hive, and take an appropriate action */
2233 if (Kcb->RefCount > 1)
2234 {
2235 if (Flags != REG_FORCE_UNLOAD)
2236 {
2237 if (CmpEnumerateOpenSubKeys(Kcb, FALSE, FALSE) != 0)
2238 {
2239 /* There are open subkeys but we don't force hive unloading, fail */
2240 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2241 return STATUS_CANNOT_DELETE;
2242 }
2243 }
2244 else
2245 {
2246 DPRINT1("CmUnloadKey: Force unloading is HALF-IMPLEMENTED, expect dangling KCBs problems!\n");
2247 if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE) != 0)
2248 {
2249 /* There are open subkeys that we cannot force to unload, fail */
2250 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2251 return STATUS_CANNOT_DELETE;
2252 }
2253 }
2254 }
2255
2256 /* Set the loading flag */
2257 CmHive->HiveIsLoading = TRUE;
2258
2259 /* Flush the hive */
2260 CmFlushKey(Kcb, TRUE);
2261
2262 /* Unlink the hive from the master hive */
2263 if (!CmpUnlinkHiveFromMaster(CmHive, Cell))
2264 {
2265 DPRINT("CmpUnlinkHiveFromMaster() failed!\n");
2266
2267 /* Remove the unloading flag */
2268 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2269
2270 /* Reset the loading flag */
2271 CmHive->HiveIsLoading = FALSE;
2272
2273 /* Return failure */
2275 }
2276
2277 /* Flush any notifications if we force hive unloading */
2278 if (Flags == REG_FORCE_UNLOAD)
2279 CmpFlushNotifiesOnKeyBodyList(Kcb, TRUE); // Lock is already held
2280
2281 /* Clean up information we have on the subkey */
2282 CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
2283
2284 /* Set the KCB in delete mode and remove it */
2285 Kcb->Delete = TRUE;
2287
2288 if (Flags != REG_FORCE_UNLOAD)
2289 {
2290 /* Release the KCB locks */
2291 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
2292
2293 /* Release the hive loading lock */
2295 }
2296
2297 /* Release hive lock */
2299
2300 /* Close file handles */
2301 CmpCloseHiveFiles(CmHive);
2302
2303 /* Remove the hive from the hive file list */
2305
2310 /* Destroy the security descriptor cache */
2312
2313 /* Destroy the view list */
2314 CmpDestroyHiveViewList(CmHive);
2315
2316 /* Delete the flusher lock */
2319
2320 /* Delete the view lock */
2322
2323 /* Free the hive storage */
2324 HvFree(Hive);
2325
2326 /* Free the hive */
2327 CmpFree(CmHive, TAG_CM);
2328
2329 return STATUS_SUCCESS;
2330}
2331
2332ULONG
2333NTAPI
2335 IN PCM_KEY_CONTROL_BLOCK RootKcb,
2336 IN BOOLEAN RemoveEmptyCacheEntries,
2337 IN BOOLEAN DereferenceOpenedEntries)
2338{
2340 PCM_KEY_CONTROL_BLOCK CachedKcb;
2341 PCM_KEY_CONTROL_BLOCK ParentKcb;
2342 ULONG ParentKeyCount;
2343 ULONG i, j;
2344 ULONG SubKeys = 0;
2345
2346 DPRINT("CmpEnumerateOpenSubKeys() called\n");
2347
2348 /* The root key is the only referenced key. There are no referenced sub keys. */
2349 if (RootKcb->RefCount == 1)
2350 {
2351 DPRINT("Open sub keys: 0\n");
2352 return 0;
2353 }
2354
2355 /* Enumerate all hash lists */
2356 for (i = 0; i < CmpHashTableSize; i++)
2357 {
2358 /* Get the first cache entry */
2360
2361 /* Enumerate all cache entries */
2362 while (Entry)
2363 {
2364 /* Get the KCB of the current cache entry */
2366
2367 /* Check keys only that are subkeys to our root key */
2368 if (CachedKcb->TotalLevels > RootKcb->TotalLevels)
2369 {
2370 /* Calculate the number of parent keys to the root key */
2371 ParentKeyCount = CachedKcb->TotalLevels - RootKcb->TotalLevels;
2372
2373 /* Find a parent key that could be the root key */
2374 ParentKcb = CachedKcb;
2375 for (j = 0; j < ParentKeyCount; j++)
2376 {
2377 ParentKcb = ParentKcb->ParentKcb;
2378 }
2379
2380 /* Check whether the parent is the root key */
2381 if (ParentKcb == RootKcb)
2382 {
2383 DPRINT("Found a sub key, RefCount = %u\n", CachedKcb->RefCount);
2384
2385 if (CachedKcb->RefCount > 0)
2386 {
2387 DPRINT("Found a sub key pointing to '%.*s', RefCount = %u\n",
2388 CachedKcb->NameBlock->NameLength, CachedKcb->NameBlock->Name,
2389 CachedKcb->RefCount);
2390
2391 /* If we dereference opened KCBs, don't touch read-only keys */
2392 if (DereferenceOpenedEntries &&
2393 !(CachedKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
2394 {
2395 /* Registry needs to be locked down */
2397
2398 /* Flush any notifications */
2399 CmpFlushNotifiesOnKeyBodyList(CachedKcb, TRUE); // Lock is already held
2400
2401 /* Clean up information we have on the subkey */
2402 CmpCleanUpSubKeyInfo(CachedKcb->ParentKcb);
2403
2404 /* Get and cache the next cache entry */
2405 // Entry = Entry->NextHash;
2406 Entry = CachedKcb->NextHash;
2407
2408 /* Set the KCB in delete mode and remove it */
2409 CachedKcb->Delete = TRUE;
2410 CmpRemoveKeyControlBlock(CachedKcb);
2411
2412 /* Clear the cell */
2413 CachedKcb->KeyCell = HCELL_NIL;
2414
2415 /* Restart with the next cache entry */
2416 continue;
2417 }
2418 /* Else, the key cannot be dereferenced, and we count it as in use */
2419
2420 /* Count the current hash entry if it is in use */
2421 SubKeys++;
2422 }
2423 else if ((CachedKcb->RefCount == 0) && RemoveEmptyCacheEntries)
2424 {
2425 /* Remove the current key from the delayed close list */
2426 CmpRemoveFromDelayedClose(CachedKcb);
2427
2428 /* Remove the current cache entry */
2429 CmpCleanUpKcbCacheWithLock(CachedKcb, TRUE);
2430
2431 /* Restart, because the hash list has changed */
2433 continue;
2434 }
2435 }
2436 }
2437
2438 /* Get the next cache entry */
2439 Entry = Entry->NextHash;
2440 }
2441 }
2442
2443 if (SubKeys > 0)
2444 DPRINT1("Open sub keys: %u\n", SubKeys);
2445
2446 return SubKeys;
2447}
2448
2449static
2452 IN HCELL_INDEX SrcKeyCell,
2453 IN PHHIVE DestinationHive,
2455 IN HSTORAGE_TYPE StorageType,
2456 OUT PHCELL_INDEX DestKeyCell OPTIONAL)
2457{
2459 PCM_KEY_NODE SrcNode;
2460 PCM_KEY_NODE DestNode = NULL;
2461 HCELL_INDEX NewKeyCell = HCELL_NIL;
2462 HCELL_INDEX NewClassCell = HCELL_NIL, NewSecCell = HCELL_NIL;
2463 HCELL_INDEX SubKey, NewSubKey;
2464 ULONG Index, SubKeyCount;
2465
2466 PAGED_CODE();
2467
2468 DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
2469 SourceHive,
2470 SrcKeyCell,
2471 DestinationHive,
2472 Parent,
2473 StorageType,
2474 DestKeyCell);
2475
2476 /* Get the source cell node */
2477 SrcNode = (PCM_KEY_NODE)HvGetCell(SourceHive, SrcKeyCell);
2478 ASSERT(SrcNode);
2479
2480 /* Sanity check */
2482
2483 /* Create a simple copy of the source key */
2484 NewKeyCell = CmpCopyCell(SourceHive,
2485 SrcKeyCell,
2486 DestinationHive,
2487 StorageType);
2488 if (NewKeyCell == HCELL_NIL)
2489 {
2490 /* Not enough storage space */
2492 goto Cleanup;
2493 }
2494
2495 /* Get the destination cell node */
2496 DestNode = (PCM_KEY_NODE)HvGetCell(DestinationHive, NewKeyCell);
2497 ASSERT(DestNode);
2498
2499 /* Set the parent and copy the flags */
2500 DestNode->Parent = Parent;
2501 DestNode->Flags = (SrcNode->Flags & KEY_COMP_NAME); // Keep only the single permanent flag
2502 if (Parent == HCELL_NIL)
2503 {
2504 /* This is the new root node */
2505 DestNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
2506 }
2507
2508 /* Copy the class cell */
2509 if (SrcNode->ClassLength > 0)
2510 {
2511 NewClassCell = CmpCopyCell(SourceHive,
2512 SrcNode->Class,
2513 DestinationHive,
2514 StorageType);
2515 if (NewClassCell == HCELL_NIL)
2516 {
2517 /* Not enough storage space */
2519 goto Cleanup;
2520 }
2521
2522 DestNode->Class = NewClassCell;
2523 DestNode->ClassLength = SrcNode->ClassLength;
2524 }
2525 else
2526 {
2527 DestNode->Class = HCELL_NIL;
2528 DestNode->ClassLength = 0;
2529 }
2530
2531 /* Copy the security cell (FIXME: HACKish poor-man version) */
2532 if (SrcNode->Security != HCELL_NIL)
2533 {
2534 NewSecCell = CmpCopyCell(SourceHive,
2535 SrcNode->Security,
2536 DestinationHive,
2537 StorageType);
2538 if (NewSecCell == HCELL_NIL)
2539 {
2540 /* Not enough storage space */
2542 goto Cleanup;
2543 }
2544 }
2545 DestNode->Security = NewSecCell;
2546
2547 /* Copy the value list */
2548 Status = CmpCopyKeyValueList(SourceHive,
2549 &SrcNode->ValueList,
2550 DestinationHive,
2551 &DestNode->ValueList,
2552 StorageType);
2553 if (!NT_SUCCESS(Status))
2554 goto Cleanup;
2555
2556 /* Clear the invalid subkey index */
2557 DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
2558 DestNode->SubKeyLists[Stable] = DestNode->SubKeyLists[Volatile] = HCELL_NIL;
2559
2560 /* Calculate the total number of subkeys */
2561 SubKeyCount = SrcNode->SubKeyCounts[Stable] + SrcNode->SubKeyCounts[Volatile];
2562
2563 /* Loop through all the subkeys */
2564 for (Index = 0; Index < SubKeyCount; Index++)
2565 {
2566 /* Get the subkey */
2567 SubKey = CmpFindSubKeyByNumber(SourceHive, SrcNode, Index);
2568 ASSERT(SubKey != HCELL_NIL);
2569
2570 /* Call the function recursively for the subkey */
2571 //
2572 // FIXME: Danger!! Kernel stack exhaustion!!
2573 //
2574 Status = CmpDeepCopyKeyInternal(SourceHive,
2575 SubKey,
2576 DestinationHive,
2577 NewKeyCell,
2578 StorageType,
2579 &NewSubKey);
2580 if (!NT_SUCCESS(Status))
2581 goto Cleanup;
2582
2583 /* Add the copy of the subkey to the new key */
2584 if (!CmpAddSubKey(DestinationHive,
2585 NewKeyCell,
2586 NewSubKey))
2587 {
2588 /* Cleanup allocated cell */
2589 HvFreeCell(DestinationHive, NewSubKey);
2590
2592 goto Cleanup;
2593 }
2594 }
2595
2596 /* Set success */
2598
2599Cleanup:
2600
2601 /* Release the cells */
2602 if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell);
2603 if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
2604
2605 /* Cleanup allocated cells in case of failure */
2606 if (!NT_SUCCESS(Status))
2607 {
2608 if (NewSecCell != HCELL_NIL)
2609 HvFreeCell(DestinationHive, NewSecCell);
2610
2611 if (NewClassCell != HCELL_NIL)
2612 HvFreeCell(DestinationHive, NewClassCell);
2613
2614 if (NewKeyCell != HCELL_NIL)
2615 HvFreeCell(DestinationHive, NewKeyCell);
2616
2617 NewKeyCell = HCELL_NIL;
2618 }
2619
2620 /* Set the cell index if requested and return status */
2621 if (DestKeyCell) *DestKeyCell = NewKeyCell;
2622 return Status;
2623}
2624
2626NTAPI
2628 IN HCELL_INDEX SrcKeyCell,
2629 IN PHHIVE DestinationHive,
2630 IN HSTORAGE_TYPE StorageType,
2631 OUT PHCELL_INDEX DestKeyCell OPTIONAL)
2632{
2633 /* Call the internal function */
2634 return CmpDeepCopyKeyInternal(SourceHive,
2635 SrcKeyCell,
2636 DestinationHive,
2637 HCELL_NIL,
2638 StorageType,
2639 DestKeyCell);
2640}
2641
2643NTAPI
2646 IN ULONG Flags)
2647{
2649 PCMHIVE KeyHive = NULL;
2650 PAGED_CODE();
2651
2652 DPRINT("CmSaveKey(0x%08X, 0x%08X, %lu)\n", Kcb, FileHandle, Flags);
2653
2654 /* Lock the registry and KCB */
2657
2658 if (Kcb->Delete)
2659 {
2660 /* The source key has been deleted, do nothing */
2662 goto Cleanup;
2663 }
2664
2665 if (Kcb->KeyHive == &CmiVolatileHive->Hive)
2666 {
2667 /* Keys that are directly in the master hive can't be saved */
2669 goto Cleanup;
2670 }
2671
2672 /* Create a new hive that will hold the key */
2673 Status = CmpInitializeHive(&KeyHive,
2677 NULL,
2678 NULL,
2679 NULL,
2680 NULL,
2681 NULL,
2682 0);
2683 if (!NT_SUCCESS(Status)) goto Cleanup;
2684
2685 /* Copy the key recursively into the new hive */
2686 Status = CmpDeepCopyKey(Kcb->KeyHive,
2687 Kcb->KeyCell,
2688 &KeyHive->Hive,
2689 Stable,
2690 &KeyHive->Hive.BaseBlock->RootCell);
2691 if (!NT_SUCCESS(Status)) goto Cleanup;
2692
2693 /* Set the primary handle of the hive */
2695
2696 /* Dump the hive into the file */
2697 HvWriteHive(&KeyHive->Hive);
2698
2699Cleanup:
2700
2701 /* Free the hive */
2702 if (KeyHive) CmpDestroyHive(KeyHive);
2703
2704 /* Release the locks */
2705 CmpReleaseKcbLock(Kcb);
2707
2708 return Status;
2709}
2710
2712NTAPI
2716{
2717 PCMHIVE KeyHive = NULL;
2719
2720 PAGED_CODE();
2721
2722 DPRINT("CmSaveKey(%p, %p, %p)\n", HighKcb, LowKcb, FileHandle);
2723
2724 /* Lock the registry and the KCBs */
2726 CmpAcquireKcbLockShared(HighKcb);
2728
2729 if (LowKcb->Delete || HighKcb->Delete)
2730 {
2731 /* The source key has been deleted, do nothing */
2733 goto done;
2734 }
2735
2736 /* Create a new hive that will hold the key */
2737 Status = CmpInitializeHive(&KeyHive,
2741 NULL,
2742 NULL,
2743 NULL,
2744 NULL,
2745 NULL,
2746 0);
2747 if (!NT_SUCCESS(Status))
2748 goto done;
2749
2750 /* Copy the low precedence key recursively into the new hive */
2751 Status = CmpDeepCopyKey(LowKcb->KeyHive,
2752 LowKcb->KeyCell,
2753 &KeyHive->Hive,
2754 Stable,
2755 &KeyHive->Hive.BaseBlock->RootCell);
2756 if (!NT_SUCCESS(Status))
2757 goto done;
2758
2759 /* Copy the high precedence key recursively into the new hive */
2760 Status = CmpDeepCopyKey(HighKcb->KeyHive,
2761 HighKcb->KeyCell,
2762 &KeyHive->Hive,
2763 Stable,
2764 &KeyHive->Hive.BaseBlock->RootCell);
2765 if (!NT_SUCCESS(Status))
2766 goto done;
2767
2768 /* Set the primary handle of the hive */
2770
2771 /* Dump the hive into the file */
2772 HvWriteHive(&KeyHive->Hive);
2773
2774done:
2775 /* Free the hive */
2776 if (KeyHive)
2777 CmpDestroyHive(KeyHive);
2778
2779 /* Release the locks */
2780 CmpReleaseKcbLock(LowKcb);
2781 CmpReleaseKcbLock(HighKcb);
2783
2784 return Status;
2785}
#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:127
@ SearchNeedExclusiveLock
Definition: cm.h:128
#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:102
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK()
Definition: cm_x.h:61
#define CMP_ASSERT_FLUSH_LOCK(h)
Definition: cm_x.h:266
#define CmpAcquireKcbLockShared(k)
Definition: cm_x.h:121
#define CMP_IS_CELL_CACHED(c)
Definition: cm_x.h:28
#define CmpIsKcbLockedExclusive(k)
Definition: cm_x.h:82
#define CMP_ASSERT_KCB_LOCK(k)
Definition: cm_x.h:245
FORCEINLINE VOID CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:189
FORCEINLINE VOID CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:169
FORCEINLINE BOOLEAN CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:140
static BOOLEAN NTAPI CmpUnlinkHiveFromMaster(IN PCMHIVE CmHive, IN HCELL_INDEX Cell)
Definition: cmapi.c:2161
NTSTATUS NTAPI CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Flags)
Definition: cmapi.c:2201
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:271
static NTSTATUS CmpQueryKeyDataFromCache(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1363
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:644
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:2451
NTSTATUS NTAPI CmSaveMergedKeys(IN PCM_KEY_CONTROL_BLOCK HighKcb, IN PCM_KEY_CONTROL_BLOCK LowKcb, IN HANDLE FileHandle)
Definition: cmapi.c:2713
NTSTATUS NTAPI CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN ExclusiveLock)
Definition: cmapi.c:1938
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:1735
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:147
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:2627
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:1075
static NTSTATUS CmpQueryFlagsInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo, _In_ ULONG Length, _In_ PULONG ResultLength)
Definition: cmapi.c:1498
NTSTATUS NTAPI CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN UNICODE_STRING ValueName)
Definition: cmapi.c:916
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:1192
NTSTATUS NTAPI CmSaveKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN HANDLE FileHandle, IN ULONG Flags)
Definition: cmapi.c:2644
BOOLEAN NTAPI CmpDoFlushAll(IN BOOLEAN ForceFlush)
Definition: cmapi.c:82
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:1615
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:376
NTSTATUS NTAPI CmDeleteKey(IN PCM_KEY_BODY KeyBody)
Definition: cmapi.c:1824
NTSTATUS NTAPI CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, IN PCM_KEY_BODY KeyBody)
Definition: cmapi.c:2004
ULONG NTAPI CmpEnumerateOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb, IN BOOLEAN RemoveEmptyCacheEntries, IN BOOLEAN DereferenceOpenedEntries)
Definition: cmapi.c:2334
static NTSTATUS CmpQueryNameInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1519
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:1139
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:271
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:384
USHORT NTAPI CmpCopyName(IN PHHIVE Hive, OUT PWCHAR Destination, IN PCUNICODE_STRING Source)
Definition: cmname.c:21
BOOLEAN NTAPI CmpMarkValueDataDirty(IN PHHIVE Hive, IN PCM_KEY_VALUE Value)
Definition: cmvalue.c:19
BOOLEAN CMAPI HvHiveWillShrink(IN PHHIVE RegistryHive)
Definition: hivewrt.c:277
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:207
NTSTATUS NTAPI CmpRemoveValueFromList(IN PHHIVE Hive, IN ULONG Index, IN OUT PCHILD_LIST ChildList)
Definition: cmvalue.c:320
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PCUNICODE_STRING Name)
Definition: cmname.c:74
BOOLEAN CMAPI HvSyncHive(PHHIVE RegistryHive)
Definition: hivewrt.c:243
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:311
static BOOLEAN CmpIsKeyValueSmall(OUT PULONG RealLength, IN ULONG Length)
Definition: cmlib.h:319
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:468
LONG CMAPI HvGetCellSize(PHHIVE RegistryHive, PVOID Cell)
struct _CMHIVE * PCMHIVE
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:381
HCELL_INDEX CMAPI HvAllocateCell(PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, IN HCELL_INDEX Vicinity)
#define TAG_CM
Definition: cmlib.h:205
VOID CMAPI HvFree(PHHIVE RegistryHive)
Definition: hiveinit.c:628
BOOLEAN CMAPI HvWriteHive(PHHIVE RegistryHive)
Definition: hivewrt.c:285
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:1839
VOID NTAPI CmpUnlockRegistry(VOID)
Definition: cmsysini.c:1938
NTSTATUS NTAPI CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, IN HANDLE RootDirectory, IN PCMHIVE RegistryHive, IN BOOLEAN Allocate, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: cmsysini.c:797
VOID NTAPI CmpLockHiveFlusherExclusive(IN PCMHIVE Hive)
Definition: cmsysini.c:1888
VOID NTAPI CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:1961
VOID NTAPI CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:1990
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1852
VOID NTAPI CmpLockHiveFlusherShared(IN PCMHIVE Hive)
Definition: cmsysini.c:1899
BOOLEAN CmpSpecialBootCondition
Definition: cmsysini.c:27
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:16
BOOLEAN CmpProfileLoaded
Definition: cmsysini.c:30
BOOLEAN NTAPI CmpTestRegistryLockExclusive(VOID)
Definition: cmsysini.c:1880
LIST_ENTRY CmpHiveListHead
Definition: cmsysini.c:17
BOOLEAN CmpWasSetupBoot
Definition: cmsysini.c:29
BOOLEAN CmpNoWrite
Definition: cmsysini.c:28
VOID NTAPI CmpUnlockHiveFlusher(IN PCMHIVE Hive)
Definition: cmsysini.c:1910
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 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:80
HSTORAGE_TYPE
Definition: hivedata.h:101
@ Volatile
Definition: hivedata.h:103
@ Stable
Definition: hivedata.h:102
#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:85
ULONG HCELL_INDEX
Definition: hivedata.h:80
#define HvGetCellType(Cell)
Definition: hivedata.h:95
#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
@ 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
NTSTATUS NTAPI CmpInitializeHive(OUT PCMHIVE *CmHive, IN ULONG OperationType, IN ULONG HiveFlags, IN ULONG FileType, IN PVOID HiveData OPTIONAL, IN HANDLE Primary, IN HANDLE Log, IN HANDLE External, IN PCUNICODE_STRING FileName OPTIONAL, IN ULONG CheckFlags)
Definition: cminit.c:19
VOID NTAPI CmpCloseHiveFiles(IN PCMHIVE Hive)
Definition: cminit.c:637
NTSTATUS NTAPI CmpDestroyHive(IN PCMHIVE CmHive)
Definition: cminit.c:235
#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
union _CELL_DATA::@4098 u
CM_KEY_VALUE KeyValue
Definition: cmdata.h:201
CM_KEY_NODE KeyNode
Definition: cmdata.h:200
Definition: cmlib.h:245
HHIVE Hive
Definition: cmlib.h:246
BOOLEAN HiveIsLoading
Definition: cmlib.h:286
BOOLEAN Frozen
Definition: cmlib.h:274
PKGUARDED_MUTEX ViewLock
Definition: cmlib.h:252
PERESOURCE FlusherLock
Definition: cmlib.h:256
ULONG UseCount
Definition: cmlib.h:266
PKTHREAD CreatorOwner
Definition: cmlib.h:287
HANDLE FileHandles[HFILE_TYPE_MAX]
Definition: cmlib.h:247
UNICODE_STRING FileUserName
Definition: cmlib.h:263
PKTHREAD ViewLockOwner
Definition: cmlib.h:253
struct _CM_KEY_CONTROL_BLOCK * KeyControlBlock
Definition: cm.h:222
ULONG TotalLevels
Definition: cm.h:261
PCM_NAME_CONTROL_BLOCK NameBlock
Definition: cm.h:275
ULONG RefCount
Definition: cm.h:254
PHHIVE KeyHive
Definition: cm.h:270
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:274
ULONG ExtFlags
Definition: cm.h:257
HCELL_INDEX KeyCell
Definition: cm.h:271
PCM_KEY_HASH NextHash
Definition: cm.h:269
PCM_KEY_HASH Entry
Definition: cm.h:150
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:233
USHORT NameLength
Definition: cm.h:242
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:243
BOOLEAN CreateOperation
Definition: cm.h:417
HCELL_INDEX RootCell
Definition: hivedata.h:143
ULONG HiveFlags
Definition: hivedata.h:321
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:303
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