ReactOS 0.4.15-dev-6068-g8061a6f
cmparse.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/cmparse.c
5 * PURPOSE: Configuration Manager - Object Manager Parse Interface
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include "ntoskrnl.h"
12#define NDEBUG
13#include "debug.h"
14
15/* GLOBALS *******************************************************************/
16
17/* FUNCTIONS *****************************************************************/
18
22 OUT PUNICODE_STRING NextName,
23 OUT PBOOLEAN LastName)
24{
25 BOOLEAN NameValid = TRUE;
26
27 ASSERT(RemainingName->Length % sizeof(WCHAR) == 0);
28
29 /* Check if there's nothing left in the name */
30 if (!(RemainingName->Buffer) ||
31 (!RemainingName->Length) ||
32 !(*RemainingName->Buffer))
33 {
34 /* Clear the next name and set this as last */
35 *LastName = TRUE;
36 NextName->Buffer = NULL;
37 NextName->Length = 0;
38 return TRUE;
39 }
40
41 /* Check if we have a path separator */
42 while ((RemainingName->Length) &&
44 {
45 /* Skip it */
46 RemainingName->Buffer++;
47 RemainingName->Length -= sizeof(WCHAR);
48 RemainingName->MaximumLength -= sizeof(WCHAR);
49 }
50
51 /* Start loop at where the current buffer is */
52 NextName->Buffer = RemainingName->Buffer;
53 while ((RemainingName->Length) &&
55 {
56 /* Move to the next character */
57 RemainingName->Buffer++;
58 RemainingName->Length -= sizeof(WCHAR);
59 RemainingName->MaximumLength -= sizeof(WCHAR);
60 }
61
62 /* See how many chars we parsed and validate the length */
63 NextName->Length = (USHORT)((ULONG_PTR)RemainingName->Buffer -
64 (ULONG_PTR)NextName->Buffer);
65 if (NextName->Length > 512) NameValid = FALSE;
66 NextName->MaximumLength = NextName->Length;
67
68 /* If there's nothing left, we're last */
69 *LastName = !RemainingName->Length;
70 return NameValid;
71}
72
77 IN OUT PCM_KEY_CONTROL_BLOCK SymbolicKcb,
79{
80 HCELL_INDEX LinkCell = HCELL_NIL;
81 PCM_KEY_VALUE LinkValue = NULL;
82 PWSTR LinkName = NULL;
83 BOOLEAN LinkNameAllocated = FALSE;
84 PWSTR NewBuffer;
85 ULONG Length = 0;
88 HCELL_INDEX CellToRelease = HCELL_NIL;
90 UNICODE_STRING NewObjectName;
91
92 /* Make sure we're not being deleted */
93 if (SymbolicKcb->Delete) return FALSE;
94
95 /* Get the key node */
96 Node = (PCM_KEY_NODE)HvGetCell(SymbolicKcb->KeyHive, SymbolicKcb->KeyCell);
97 if (!Node) goto Exit;
98
99 /* Find the symbolic link key */
101 HvReleaseCell(SymbolicKcb->KeyHive, SymbolicKcb->KeyCell);
102 if (LinkCell == HCELL_NIL) goto Exit;
103
104 /* Get the value cell */
105 LinkValue = (PCM_KEY_VALUE)HvGetCell(Hive, LinkCell);
106 if (!LinkValue) goto Exit;
107
108 /* Make sure it's a registry link */
109 if (LinkValue->Type != REG_LINK) goto Exit;
110
111 /* Now read the value data */
112 if (!CmpGetValueData(Hive,
113 LinkValue,
115 (PVOID*)&LinkName,
116 &LinkNameAllocated,
117 &CellToRelease))
118 {
119 /* Fail */
120 goto Exit;
121 }
122
123 /* Get the length */
124 Length = ValueLength + sizeof(WCHAR);
125
126 /* Make sure we start with a slash */
127 if (*LinkName != OBJ_NAME_PATH_SEPARATOR) goto Exit;
128
129 /* Add the remaining name if needed */
130 if (RemainingName) Length += RemainingName->Length + sizeof(WCHAR);
131
132 /* Check for overflow */
133 if (Length > 0xFFFF) goto Exit;
134
135 /* Check if we need a new buffer */
136 if (Length > ObjectName->MaximumLength)
137 {
138 /* We do -- allocate one */
140 if (!NewBuffer) goto Exit;
141
142 /* Setup the new string and copy the symbolic target */
143 NewObjectName.Buffer = NewBuffer;
144 NewObjectName.MaximumLength = (USHORT)Length;
145 NewObjectName.Length = (USHORT)ValueLength;
146 RtlCopyMemory(NewBuffer, LinkName, ValueLength);
147
148 /* Check if we need to add anything else */
149 if (RemainingName)
150 {
151 /* Add the remaining name */
152 NewBuffer[ValueLength / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
153 NewObjectName.Length += sizeof(WCHAR);
155 }
156
157 /* Free the old buffer */
158 ExFreePool(ObjectName->Buffer);
159 *ObjectName = NewObjectName;
160 }
161 else
162 {
163 /* The old name is large enough -- update the length */
164 ObjectName->Length = (USHORT)ValueLength;
165 if (RemainingName)
166 {
167 /* Copy the remaining name inside */
168 RtlMoveMemory(&ObjectName->Buffer[(ValueLength / sizeof(WCHAR)) + 1],
169 RemainingName->Buffer,
170 RemainingName->Length);
171
172 /* Add the slash and update the length */
174 ObjectName->Length += RemainingName->Length + sizeof(WCHAR);
175 }
176
177 /* Copy the symbolic link target name */
178 RtlCopyMemory(ObjectName->Buffer, LinkName, ValueLength);
179 }
180
181 /* Null-terminate the whole thing */
182 ObjectName->Buffer[ObjectName->Length / sizeof(WCHAR)] = UNICODE_NULL;
183 Result = TRUE;
184
185Exit:
186 /* Free the link name */
187 if (LinkNameAllocated) ExFreePool(LinkName);
188
189 /* Check if we had a value cell */
190 if (LinkValue)
191 {
192 /* Release it */
193 ASSERT(LinkCell != HCELL_NIL);
194 HvReleaseCell(Hive, LinkCell);
195 }
196
197 /* Check if we had an active cell and release it, then return the result */
198 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
199 return Result;
200}
201
203NTAPI
205 IN HCELL_INDEX ParentCell,
206 IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
210 IN PCM_PARSE_CONTEXT ParseContext,
211 IN PCM_KEY_CONTROL_BLOCK ParentKcb,
212 IN ULONG Flags,
213 OUT PHCELL_INDEX KeyCell,
215{
217 PCM_KEY_BODY KeyBody;
218 HCELL_INDEX ClassCell = HCELL_NIL;
219 PCM_KEY_NODE KeyNode;
220 PCELL_DATA CellData;
221 ULONG StorageType;
224
225 /* Get the storage type */
226 StorageType = Stable;
227 if (ParseContext->CreateOptions & REG_OPTION_VOLATILE) StorageType = Volatile;
228
229 /* Allocate the child */
230 *KeyCell = HvAllocateCell(Hive,
232 CmpNameSize(Hive, Name),
233 StorageType,
234 HCELL_NIL);
235 if (*KeyCell == HCELL_NIL)
236 {
237 /* Fail */
239 goto Quickie;
240 }
241
242 /* Get the key node */
243 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, *KeyCell);
244 if (!KeyNode)
245 {
246 /* Fail, this should never happen */
247 ASSERT(FALSE);
249 goto Quickie;
250 }
251
252 /* Release the cell */
253 HvReleaseCell(Hive, *KeyCell);
254
255 /* Check if we have a class name */
256 if (ParseContext->Class.Length > 0)
257 {
258 /* Allocate a class cell */
259 ClassCell = HvAllocateCell(Hive,
260 ParseContext->Class.Length,
261 StorageType,
262 HCELL_NIL);
263 if (ClassCell == HCELL_NIL)
264 {
265 /* Fail */
267 goto Quickie;
268 }
269 }
270
271 /* Allocate the Cm Object */
274 NULL,
276 NULL,
277 sizeof(CM_KEY_BODY),
278 0,
279 0,
280 Object);
281 if (!NT_SUCCESS(Status)) goto Quickie;
282
283 /* Setup the key body */
284 KeyBody = (PCM_KEY_BODY)(*Object);
285 KeyBody->Type = CM_KEY_BODY_TYPE;
286 KeyBody->KeyControlBlock = NULL;
287
288 /* Check if we had a class */
289 if (ParseContext->Class.Length > 0)
290 {
291 /* Get the class cell */
292 CellData = HvGetCell(Hive, ClassCell);
293 if (!CellData)
294 {
295 /* Fail, this should never happen */
296 ASSERT(FALSE);
299 goto Quickie;
300 }
301
302 /* Release the cell */
303 HvReleaseCell(Hive, ClassCell);
304
305 /* Copy the class data */
306 RtlCopyMemory(&CellData->u.KeyString[0],
307 ParseContext->Class.Buffer,
308 ParseContext->Class.Length);
309 }
310
311 /* Fill out the key node */
313 KeyNode->Flags = Flags;
315 KeyNode->Spare = 0;
316 KeyNode->Parent = ParentCell;
317 KeyNode->SubKeyCounts[Stable] = 0;
318 KeyNode->SubKeyCounts[Volatile] = 0;
319 KeyNode->SubKeyLists[Stable] = HCELL_NIL;
320 KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
321 KeyNode->ValueList.Count = 0;
322 KeyNode->ValueList.List = HCELL_NIL;
323 KeyNode->Security = HCELL_NIL;
324 KeyNode->Class = ClassCell;
325 KeyNode->ClassLength = ParseContext->Class.Length;
326 KeyNode->MaxValueDataLen = 0;
327 KeyNode->MaxNameLen = 0;
328 KeyNode->MaxValueNameLen = 0;
329 KeyNode->MaxClassLen = 0;
330 KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, Name);
331 if (KeyNode->NameLength < Name->Length) KeyNode->Flags |= KEY_COMP_NAME;
332
333 /* Create the KCB */
334 Kcb = CmpCreateKeyControlBlock(Hive,
335 *KeyCell,
336 KeyNode,
337 ParentKcb,
338 0, // CMP_LOCK_HASHES_FOR_KCB,
339 Name);
340 if (!Kcb)
341 {
342 /* Fail */
345 goto Quickie;
346 }
347
348 /* Sanity check */
349 ASSERT(Kcb->RefCount == 1);
350
351 /* Now fill out the Cm object */
352 KeyBody->NotifyBlock = NULL;
353 KeyBody->ProcessID = PsGetCurrentProcessId();
354 KeyBody->KeyControlBlock = Kcb;
355
356 /* Link it with the KCB */
357 EnlistKeyBodyWithKCB(KeyBody, 0);
358
359 /* Assign security */
360 Status = SeAssignSecurity(ParentDescriptor,
361 AccessState->SecurityDescriptor,
363 TRUE,
364 &AccessState->SubjectSecurityContext,
365 &CmpKeyObjectType->TypeInfo.GenericMapping,
366 CmpKeyObjectType->TypeInfo.PoolType);
367 if (NT_SUCCESS(Status))
368 {
370 AssignSecurityDescriptor,
371 NULL,
373 NULL,
374 NULL,
375 CmpKeyObjectType->TypeInfo.PoolType,
376 &CmpKeyObjectType->TypeInfo.GenericMapping);
377 }
378
379 /* Now that the security descriptor is copied in the hive, we can free the original */
380 SeDeassignSecurity(&NewDescriptor);
381
382 if (NT_SUCCESS(Status))
383 {
384 /* Send notification to registered callbacks */
386 }
387
388Quickie:
389 /* Check if we got here because of failure */
390 if (!NT_SUCCESS(Status))
391 {
392 /* Free any cells we might've allocated */
393 if (ParseContext->Class.Length > 0) HvFreeCell(Hive, ClassCell);
394 HvFreeCell(Hive, *KeyCell);
395 }
396
397 /* Return status */
398 return Status;
399}
400
402NTAPI
404 IN HCELL_INDEX Cell,
408 IN PCM_PARSE_CONTEXT ParseContext,
409 IN PCM_KEY_CONTROL_BLOCK ParentKcb,
411{
413 PCELL_DATA CellData;
414 HCELL_INDEX KeyCell;
415 ULONG ParentType;
416 PCM_KEY_BODY KeyBody;
419 PCM_KEY_NODE KeyNode;
420
421 /* Check if the parent is being deleted */
422 if (ParentKcb->Delete)
423 {
424 /* It has, quit */
425 ASSERT(FALSE);
427 goto Exit;
428 }
429
430 /* Get the parent node */
431 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
432 if (!KeyNode)
433 {
434 /* Fail */
435 ASSERT(FALSE);
437 goto Exit;
438 }
439
440 /* Make sure nobody added us yet */
441 if (CmpFindSubKeyByName(Hive, KeyNode, Name) != HCELL_NIL)
442 {
443 /* Fail */
444 ASSERT(FALSE);
446 goto Exit;
447 }
448
449 /* Sanity check */
450 ASSERT(Cell == ParentKcb->KeyCell);
451
452 /* Get the parent type */
453 ParentType = HvGetCellType(Cell);
454 if ((ParentType == Volatile) &&
455 !(ParseContext->CreateOptions & REG_OPTION_VOLATILE))
456 {
457 /* Children of volatile parents must also be volatile */
458 //ASSERT(FALSE);
460 goto Exit;
461 }
462
463 /* Don't allow children under symlinks */
464 if (ParentKcb->Flags & KEY_SYM_LINK)
465 {
466 /* Fail */
467 ASSERT(FALSE);
469 goto Exit;
470 }
471
472 /* Make the cell dirty for now */
473 HvMarkCellDirty(Hive, Cell, FALSE);
474
475 /* Do the actual create operation */
477 Cell,
480 Name,
482 ParseContext,
483 ParentKcb,
484 0,
485 &KeyCell,
486 Object);
487 if (NT_SUCCESS(Status))
488 {
489 /* Get the key body */
490 KeyBody = (PCM_KEY_BODY)(*Object);
491
492 /* Now add the subkey */
493 if (!CmpAddSubKey(Hive, Cell, KeyCell))
494 {
495 /* Failure! We don't handle this yet! */
496 ASSERT(FALSE);
497 }
498
499 /* Get the key node */
500 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
501 if (!KeyNode)
502 {
503 /* Fail, this shouldn't happen */
504 ASSERT(FALSE);
505 }
506
507 /* Sanity checks */
508 ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
509 ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
510 ASSERT(KeyBody->KeyControlBlock->ParentKcb == ParentKcb);
511 ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
512
513 /* Update the timestamp */
515 KeyNode->LastWriteTime = TimeStamp;
516 KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
517
518 /* Check if we need to update name maximum */
519 if (KeyNode->MaxNameLen < Name->Length)
520 {
521 /* Do it */
522 KeyNode->MaxNameLen = Name->Length;
523 KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name->Length;
524 }
525
526 /* Check if we need to update class length maximum */
527 if (KeyNode->MaxClassLen < ParseContext->Class.Length)
528 {
529 /* Update it */
530 KeyNode->MaxClassLen = ParseContext->Class.Length;
531 }
532
533 /* Check if we're creating a symbolic link */
534 if (ParseContext->CreateOptions & REG_OPTION_CREATE_LINK)
535 {
536 /* Get the cell data */
537 CellData = HvGetCell(Hive, KeyCell);
538 if (!CellData)
539 {
540 /* This shouldn't happen */
541 ASSERT(FALSE);
542 }
543
544 /* Update the flags */
545 CellData->u.KeyNode.Flags |= KEY_SYM_LINK;
546 KeyBody->KeyControlBlock->Flags = CellData->u.KeyNode.Flags;
547 HvReleaseCell(Hive, KeyCell);
548 }
549 }
550
551Exit:
552 /* Release the flusher lock and return status */
553 return Status;
554}
555
557NTAPI
559 IN HCELL_INDEX Cell,
565 IN ULONG ControlFlags,
566 IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb,
569{
571 PCM_KEY_BODY KeyBody = NULL;
573
574 /* Make sure the hive isn't locked */
575 if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&
576 (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))
577 {
578 /* It is, don't touch it */
580 }
581
582 /* Check if we have a context */
583 if (Context)
584 {
585 /* Check if this is a link create (which shouldn't be an open) */
586 if (Context->CreateLink)
587 {
589 }
590
591 /* Check if this is symlink create attempt */
592 if (Context->CreateOptions & REG_OPTION_CREATE_LINK)
593 {
594 /* Key already exists */
596 }
597
598 /* Set the disposition */
599 Context->Disposition = REG_OPENED_EXISTING_KEY;
600 }
601
602 /* Do this in the registry lock */
604
605 /* If we have a KCB, make sure it's locked */
606 //ASSERT(CmpIsKcbLockedExclusive(*CachedKcb));
607
608 /* Check if caller doesn't want to create a KCB */
609 if (ControlFlags & CMP_OPEN_KCB_NO_CREATE)
610 {
611 /* Check if this is a symlink */
612 if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
613 {
614 /* This case for a cached KCB is not implemented yet */
615 ASSERT(FALSE);
616 }
617
618 /* The caller wants to open a cached KCB */
619 if (!CmpReferenceKeyControlBlock(*CachedKcb))
620 {
621 /* Release the registry lock */
623
624 /* Return failure code */
626 }
627
628 /* Our kcb is that one */
629 Kcb = *CachedKcb;
630 }
631 else
632 {
633 /* Check if this is a symlink */
634 if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
635 {
636 /* Create the KCB for the symlink */
637 Kcb = CmpCreateKeyControlBlock(Hive,
638 Cell,
639 Node,
640 *CachedKcb,
641 0,
642 KeyName);
643 if (!Kcb)
644 {
645 /* Release registry lock and return failure */
648 }
649
650 /* Make sure it's also locked, and set the pointer */
651 //ASSERT(CmpIsKcbLockedExclusive(Kcb));
652 *CachedKcb = Kcb;
653
654 /* Release the registry lock */
656
657 /* Return reparse required */
658 return STATUS_REPARSE;
659 }
660
661 /* Create the KCB. FIXME: Use lock flag */
662 Kcb = CmpCreateKeyControlBlock(Hive,
663 Cell,
664 Node,
665 *CachedKcb,
666 0,
667 KeyName);
668 if (!Kcb)
669 {
670 /* Release registry lock and return failure */
673 }
674 }
675
676 /* Make sure it's also locked, and set the pointer */
677 //ASSERT(CmpIsKcbLockedExclusive(Kcb));
678 *CachedKcb = Kcb;
679
680 /* Release the registry lock */
682
683 /* Allocate the key object */
686 NULL,
688 NULL,
689 sizeof(CM_KEY_BODY),
690 0,
691 0,
692 Object);
693 if (NT_SUCCESS(Status))
694 {
695 /* Get the key body and fill it out */
696 KeyBody = (PCM_KEY_BODY)(*Object);
697 KeyBody->KeyControlBlock = Kcb;
698 KeyBody->Type = CM_KEY_BODY_TYPE;
699 KeyBody->ProcessID = PsGetCurrentProcessId();
700 KeyBody->NotifyBlock = NULL;
701
702 /* Link to the KCB */
703 EnlistKeyBodyWithKCB(KeyBody, 0);
704
707 FALSE,
709 &Status))
710 {
711 /* Access check failed */
713 }
714 }
715 else
716 {
717 /* Failed, dereference the KCB */
719 }
720
721 /* Return status */
722 return Status;
723}
724
726NTAPI
728 IN HCELL_INDEX Cell,
734 IN PCM_KEY_CONTROL_BLOCK ParentKcb,
736{
738 HCELL_INDEX KeyCell, LinkCell, ChildCell;
739 PCM_KEY_BODY KeyBody;
741 PCM_KEY_NODE KeyNode;
742 PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;
743
744 /* Link nodes only allowed on the master */
745 if (Hive != &CmiVolatileHive->Hive)
746 {
747 /* Fail */
748 DPRINT1("Invalid link node attempt\n");
750 }
751
752 /* Check if the parent is being deleted */
753 if (ParentKcb->Delete)
754 {
755 /* It is, quit */
756 ASSERT(FALSE);
758 goto Exit;
759 }
760
761 /* Allocate a link node */
762 LinkCell = HvAllocateCell(Hive,
764 CmpNameSize(Hive, &Name),
765 Stable,
766 HCELL_NIL);
767 if (LinkCell == HCELL_NIL)
768 {
769 /* Fail */
771 goto Exit;
772 }
773
774 /* Get the key cell */
775 KeyCell = Context->ChildHive.KeyCell;
776 if (KeyCell != HCELL_NIL)
777 {
778 /* Hive exists! */
779 ChildCell = KeyCell;
780
781 /* Get the node data */
782 KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);
783 if (!KeyNode)
784 {
785 /* Fail */
786 ASSERT(FALSE);
788 goto Exit;
789 }
790
791 /* Fill out the data */
792 KeyNode->Parent = LinkCell;
793 KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
794 HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
795
796 /* Now open the key cell */
797 KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell);
798 if (!KeyNode)
799 {
800 /* Fail */
801 ASSERT(FALSE);
803 goto Exit;
804 }
805
806 /* Open the parent */
807 Status = CmpDoOpen(Context->ChildHive.KeyHive,
808 KeyCell,
809 KeyNode,
813 NULL,
814 0,
815 &Kcb,
816 &Name,
817 Object);
818 HvReleaseCell(Context->ChildHive.KeyHive, KeyCell);
819 }
820 else
821 {
822 /* Do the actual create operation */
823 Status = CmpDoCreateChild(Context->ChildHive.KeyHive,
824 Cell,
825 NULL,
827 &Name,
829 Context,
830 ParentKcb,
832 &ChildCell,
833 Object);
834 if (NT_SUCCESS(Status))
835 {
836 /* Setup root pointer */
837 Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;
838 }
839 }
840
841 /* Check if open or create suceeded */
842 if (NT_SUCCESS(Status))
843 {
844 /* Mark the cell dirty */
845 HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE);
846
847 /* Get the key node */
848 KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);
849 if (!KeyNode)
850 {
851 /* Fail */
852 ASSERT(FALSE);
854 goto Exit;
855 }
856
857 /* Release it */
858 HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
859
860 /* Set the parent and flags */
861 KeyNode->Parent = LinkCell;
862 KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
863
864 /* Get the link node */
865 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, LinkCell);
866 if (!KeyNode)
867 {
868 /* Fail */
869 ASSERT(FALSE);
871 goto Exit;
872 }
873
874 /* Set it up */
876 KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE;
877 KeyNode->Parent = Cell;
878 KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, &Name);
879 if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME;
881 KeyNode->LastWriteTime = TimeStamp;
882
883 /* Clear out the rest */
884 KeyNode->SubKeyCounts[Stable] = 0;
885 KeyNode->SubKeyCounts[Volatile] = 0;
886 KeyNode->SubKeyLists[Stable] = HCELL_NIL;
887 KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
888 KeyNode->ValueList.Count = 0;
889 KeyNode->ValueList.List = HCELL_NIL;
890 KeyNode->ClassLength = 0;
891
892 /* Reference the root node */
893 KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive;
894 KeyNode->ChildHiveReference.KeyCell = ChildCell;
895 HvReleaseCell(Hive, LinkCell);
896
897 /* Get the parent node */
898 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
899 if (!KeyNode)
900 {
901 /* Fail */
902 ASSERT(FALSE);
904 goto Exit;
905 }
906
907 /* Now add the subkey */
908 if (!CmpAddSubKey(Hive, Cell, LinkCell))
909 {
910 /* Failure! We don't handle this yet! */
911 ASSERT(FALSE);
912 }
913
914 /* Get the key body */
915 KeyBody = (PCM_KEY_BODY)*Object;
916
917 /* Sanity checks */
918 ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
919 ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
920 ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
921
922 /* Update the timestamp */
924 KeyNode->LastWriteTime = TimeStamp;
925 KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
926
927 /* Check if we need to update name maximum */
928 if (KeyNode->MaxNameLen < Name.Length)
929 {
930 /* Do it */
931 KeyNode->MaxNameLen = Name.Length;
932 KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length;
933 }
934
935 /* Check if we need to update class length maximum */
936 if (KeyNode->MaxClassLen < Context->Class.Length)
937 {
938 /* Update it */
939 KeyNode->MaxClassLen = Context->Class.Length;
940 }
941
942 /* Release the cell */
943 HvReleaseCell(Hive, Cell);
944 }
945 else
946 {
947 /* Release the link cell */
948 HvReleaseCell(Hive, LinkCell);
949 }
950
951Exit:
952 /* Release the flusher locks and return status */
953 return Status;
954}
955
956VOID
957NTAPI
959 IN OUT HCELL_INDEX *Cell,
960 IN OUT PCM_KEY_NODE *KeyNode,
961 IN OUT PHHIVE *ReleaseHive,
962 IN OUT HCELL_INDEX *ReleaseCell)
963{
964 /* Check if we have anything to release */
965 if (*ReleaseCell != HCELL_NIL)
966 {
967 /* Release it */
968 ASSERT(*ReleaseHive != NULL);
969 HvReleaseCell(*ReleaseHive, *ReleaseCell);
970 }
971
972 /* Get the link references */
973 *Hive = (*KeyNode)->ChildHiveReference.KeyHive;
974 *Cell = (*KeyNode)->ChildHiveReference.KeyCell;
975
976 /* Get the new node */
977 *KeyNode = (PCM_KEY_NODE)HvGetCell(*Hive, *Cell);
978 if (*KeyNode)
979 {
980 /* Set the new release values */
981 *ReleaseCell = *Cell;
982 *ReleaseHive = *Hive;
983 }
984 else
985 {
986 /* Nothing to release */
987 *ReleaseCell = HCELL_NIL;
988 *ReleaseHive = NULL;
989 }
990}
991
993NTAPI
996 IN PUNICODE_STRING Current,
997 OUT PHHIVE *Hive,
998 OUT HCELL_INDEX *Cell,
999 OUT PULONG TotalRemainingSubkeys,
1000 OUT PULONG MatchRemainSubkeyLevel,
1001 OUT PULONG TotalSubkeys,
1002 OUT PULONG OuterStackArray,
1003 OUT PULONG *LockedKcbs)
1004{
1005 /* We don't lock anything for now */
1006 *LockedKcbs = NULL;
1007
1008 /* Calculate hash values */
1009 *TotalRemainingSubkeys = 0xBAADF00D;
1010
1011 /* Lock the registry */
1013
1014 /* Return hive and cell data */
1015 *Hive = (*Kcb)->KeyHive;
1016 *Cell = (*Kcb)->KeyCell;
1017
1018 /* Make sure it's not a dead KCB */
1019 ASSERT((*Kcb)->RefCount > 0);
1020
1021 /* Reference it */
1023
1024 /* Return success for now */
1025 return STATUS_SUCCESS;
1026}
1027
1029NTAPI
1035 IN OUT PUNICODE_STRING CompleteName,
1039 OUT PVOID *Object)
1040{
1042 PCM_KEY_CONTROL_BLOCK Kcb, ParentKcb;
1043 PHHIVE Hive = NULL;
1045 HCELL_INDEX Cell = HCELL_NIL, NextCell;
1046 PHHIVE HiveToRelease = NULL;
1047 HCELL_INDEX CellToRelease = HCELL_NIL;
1048 UNICODE_STRING Current, NextName;
1049 PCM_PARSE_CONTEXT ParseContext = Context;
1050 ULONG TotalRemainingSubkeys = 0, MatchRemainSubkeyLevel = 0, TotalSubkeys = 0;
1051 PULONG LockedKcbs = NULL;
1052 BOOLEAN Result, Last;
1053 PAGED_CODE();
1054
1055 /* Loop path separators at the end */
1056 while ((RemainingName->Length) &&
1057 (RemainingName->Buffer[(RemainingName->Length / sizeof(WCHAR)) - 1] ==
1059 {
1060 /* Remove path separator */
1061 RemainingName->Length -= sizeof(WCHAR);
1062 }
1063
1064 /* Fail if this isn't a key object */
1066
1067 /* Copy the remaining name */
1068 Current = *RemainingName;
1069
1070 /* Check if this is a create */
1071 if (!(ParseContext) || !(ParseContext->CreateOperation))
1072 {
1073 /* It isn't, so no context */
1074 ParseContext = NULL;
1075 }
1076
1077 /* Grab the KCB */
1078 Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
1079
1080 /* Sanity check */
1081 ASSERT(Kcb != NULL);
1082
1083 /* Fail if the key was marked as deleted */
1084 if (Kcb->Delete)
1085 return STATUS_KEY_DELETED;
1086
1087 /* Lookup in the cache */
1089 &Kcb,
1090 &Current,
1091 &Hive,
1092 &Cell,
1093 &TotalRemainingSubkeys,
1094 &MatchRemainSubkeyLevel,
1095 &TotalSubkeys,
1096 NULL,
1097 &LockedKcbs);
1098
1099 /* This is now the parent */
1100 ParentKcb = Kcb;
1101
1102 /* Sanity check */
1103 ASSERT(ParentKcb != NULL);
1104
1105 /* Check if everything was found cached */
1106 if (!TotalRemainingSubkeys)
1107 ASSERTMSG("Caching not implemented\n", FALSE);
1108
1109 /* Don't do anything if we're being deleted */
1110 if (Kcb->Delete)
1111 {
1113 goto Quickie;
1114 }
1115
1116 /* Check if this is a symlink */
1117 if (Kcb->Flags & KEY_SYM_LINK)
1118 {
1119 /* Get the next name */
1120 Result = CmpGetNextName(&Current, &NextName, &Last);
1121 Current.Buffer = NextName.Buffer;
1122
1123 /* Validate the current name string length */
1124 if (Current.Length + NextName.Length > MAXUSHORT)
1125 {
1126 /* too long */
1128 goto Quickie;
1129 }
1130 Current.Length += NextName.Length;
1131
1132 /* Validate the current name string maximum length */
1133 if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
1134 {
1135 /* too long */
1137 goto Quickie;
1138 }
1139 Current.MaximumLength += NextName.MaximumLength;
1140
1141 /* Parse the symlink */
1142 if (CmpGetSymbolicLink(Hive,
1143 CompleteName,
1144 Kcb,
1145 &Current))
1146 {
1147 /* Symlink parse succeeded */
1149 }
1150 else
1151 {
1152 /* Couldn't find symlink */
1154 }
1155
1156 /* We're done */
1157 goto Quickie;
1158 }
1159
1160 /* Get the key node */
1161 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1162 if (!Node)
1163 {
1165 goto Quickie;
1166 }
1167
1168 /* Start parsing */
1170 while (TRUE)
1171 {
1172 /* Get the next component */
1173 Result = CmpGetNextName(&Current, &NextName, &Last);
1174 if ((Result) && (NextName.Length))
1175 {
1176 /* See if this is a sym link */
1177 if (!(Kcb->Flags & KEY_SYM_LINK))
1178 {
1179 /* Find the subkey */
1180 NextCell = CmpFindSubKeyByName(Hive, Node, &NextName);
1181 if (NextCell != HCELL_NIL)
1182 {
1183 /* Get the new node */
1184 Cell = NextCell;
1185 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1186 ASSERT(Node);
1187
1188 /* Check if this was the last key */
1189 if (Last)
1190 {
1191 /* Is this an exit node */
1192 if (Node->Flags & KEY_HIVE_EXIT)
1193 {
1194 /* Handle it */
1195 CmpHandleExitNode(&Hive,
1196 &Cell,
1197 &Node,
1198 &HiveToRelease,
1199 &CellToRelease);
1200 if (!Node)
1201 {
1202 /* Fail */
1204 break;
1205 }
1206 }
1207
1208 /* Do the open */
1209 Status = CmpDoOpen(Hive,
1210 Cell,
1211 Node,
1213 AccessMode,
1214 Attributes,
1215 ParseContext,
1216 0,
1217 &Kcb,
1218 &NextName,
1219 Object);
1220 if (Status == STATUS_REPARSE)
1221 {
1222 /* Parse the symlink */
1223 if (!CmpGetSymbolicLink(Hive,
1224 CompleteName,
1225 Kcb,
1226 NULL))
1227 {
1228 /* Symlink parse failed */
1230 }
1231 }
1232
1233 /* We are done */
1234 break;
1235 }
1236
1237 /* Is this an exit node */
1238 if (Node->Flags & KEY_HIVE_EXIT)
1239 {
1240 /* Handle it */
1241 CmpHandleExitNode(&Hive,
1242 &Cell,
1243 &Node,
1244 &HiveToRelease,
1245 &CellToRelease);
1246 if (!Node)
1247 {
1248 /* Fail */
1250 break;
1251 }
1252 }
1253
1254 /* Create a KCB for this key */
1255 Kcb = CmpCreateKeyControlBlock(Hive,
1256 Cell,
1257 Node,
1258 ParentKcb,
1259 0,
1260 &NextName);
1261 if (!Kcb)
1262 {
1263 /* Fail */
1265 break;
1266 }
1267
1268 /* Dereference the parent and set the new one */
1270 ParentKcb = Kcb;
1271 }
1272 else
1273 {
1274 /* Check if this was the last key for a create */
1275 if ((Last) && (ParseContext))
1276 {
1277 /* Check if we're doing a link node */
1278 if (ParseContext->CreateLink)
1279 {
1280 /* The only thing we should see */
1282 Cell,
1284 NextName,
1285 AccessMode,
1286 Attributes,
1287 ParseContext,
1288 ParentKcb,
1289 Object);
1290 }
1291 else if (Hive == &CmiVolatileHive->Hive && CmpNoVolatileCreates)
1292 {
1293 /* Creating keys in the master hive is not allowed */
1295 }
1296 else
1297 {
1298 /* Do the create */
1299 Status = CmpDoCreate(Hive,
1300 Cell,
1302 &NextName,
1303 AccessMode,
1304 ParseContext,
1305 ParentKcb,
1306 Object);
1307 }
1308
1309 /* Check for reparse (in this case, someone beat us) */
1310 if (Status == STATUS_REPARSE) break;
1311
1312 /* Update disposition */
1313 ParseContext->Disposition = REG_CREATED_NEW_KEY;
1314 break;
1315 }
1316 else
1317 {
1318 /* Key not found */
1320 break;
1321 }
1322 }
1323 }
1324 else
1325 {
1326 /* Save the next name */
1327 Current.Buffer = NextName.Buffer;
1328
1329 /* Validate the current name string length */
1330 if (Current.Length + NextName.Length > MAXUSHORT)
1331 {
1332 /* too long */
1334 break;
1335 }
1336 Current.Length += NextName.Length;
1337
1338 /* Validate the current name string maximum length */
1339 if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
1340 {
1341 /* too long */
1343 break;
1344 }
1345 Current.MaximumLength += NextName.MaximumLength;
1346
1347 /* Parse the symlink */
1348 if (CmpGetSymbolicLink(Hive,
1349 CompleteName,
1350 Kcb,
1351 &Current))
1352 {
1353 /* Symlink parse succeeded */
1355 }
1356 else
1357 {
1358 /* Couldn't find symlink */
1360 }
1361
1362 /* We're done */
1363 break;
1364 }
1365 }
1366 else if ((Result) && (Last))
1367 {
1368 /* Opening the root. Is this an exit node? */
1369 if (Node->Flags & KEY_HIVE_EXIT)
1370 {
1371 /* Handle it */
1372 CmpHandleExitNode(&Hive,
1373 &Cell,
1374 &Node,
1375 &HiveToRelease,
1376 &CellToRelease);
1377 if (!Node)
1378 {
1379 /* Fail */
1381 break;
1382 }
1383 }
1384
1385 /* Do the open */
1386 Status = CmpDoOpen(Hive,
1387 Cell,
1388 Node,
1390 AccessMode,
1391 Attributes,
1392 ParseContext,
1393 CMP_OPEN_KCB_NO_CREATE /* | CMP_CREATE_KCB_KCB_LOCKED */,
1394 &Kcb,
1395 &NextName,
1396 Object);
1397 if (Status == STATUS_REPARSE)
1398 {
1399 /* Nothing to do */
1400 }
1401
1402 /* We're done */
1403 break;
1404 }
1405 else
1406 {
1407 /* Bogus */
1409 break;
1410 }
1411 }
1412
1413 /* Dereference the parent if it exists */
1414Quickie:
1415 if (ParentKcb)
1417
1418 /* Unlock the registry */
1420 return Status;
1421}
#define PAGED_CODE()
#define CmpKeyObjectType
Definition: ObTypes.c:127
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
#define CMP_OPEN_KCB_NO_CREATE
Definition: cm.h:90
struct _CM_KEY_BODY * PCM_KEY_BODY
#define CM_KEY_BODY_TYPE
Definition: cm.h:64
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 KEY_HIVE_EXIT
Definition: cmdata.h:31
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
#define CM_LINK_NODE_SIGNATURE
Definition: cmdata.h:22
#define KEY_SYM_LINK
Definition: cmdata.h:34
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
BOOLEAN NTAPI CmpAddSubKey(IN PHHIVE Hive, IN HCELL_INDEX Parent, IN HCELL_INDEX Child)
Definition: cmindex.c:1465
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
BOOLEAN NTAPI CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:357
PCM_KEY_CONTROL_BLOCK NTAPI CmpCreateKeyControlBlock(IN PHHIVE Hive, IN HCELL_INDEX Index, IN PCM_KEY_NODE Node, IN PCM_KEY_CONTROL_BLOCK Parent, IN ULONG Flags, IN PUNICODE_STRING KeyName)
Definition: cmkcbncb.c:655
VOID NTAPI CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:606
VOID NTAPI CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:571
VOID NTAPI EnlistKeyBodyWithKCB(IN PCM_KEY_BODY KeyBody, IN ULONG Flags)
Definition: cmkcbncb.c:1042
#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
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PCUNICODE_STRING Name)
Definition: cmname.c:74
BOOLEAN NTAPI CmpGetValueData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length, OUT PVOID *Buffer, OUT PBOOLEAN BufferAllocated, OUT PHCELL_INDEX CellToRelease)
Definition: cmvalue.c:125
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
Definition: cmvalue.c:99
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:468
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
Definition: hivecell.c:109
#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 NTAPI CmpReportNotify(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PHHIVE Hive, IN HCELL_INDEX Cell, IN ULONG Filter)
Definition: cmnotify.c:19
BOOLEAN NTAPI CmpGetSymbolicLink(IN PHHIVE Hive, IN OUT PUNICODE_STRING ObjectName, IN OUT PCM_KEY_CONTROL_BLOCK SymbolicKcb, IN PUNICODE_STRING RemainingName OPTIONAL)
Definition: cmparse.c:75
NTSTATUS NTAPI CmpCreateLinkNode(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PACCESS_STATE AccessState, IN UNICODE_STRING Name, IN KPROCESSOR_MODE AccessMode, IN ULONG CreateOptions, IN PCM_PARSE_CONTEXT Context, IN PCM_KEY_CONTROL_BLOCK ParentKcb, OUT PVOID *Object)
Definition: cmparse.c:727
NTSTATUS NTAPI CmpParseKey(IN PVOID ParseObject, IN PVOID ObjectType, IN OUT PACCESS_STATE AccessState, IN KPROCESSOR_MODE AccessMode, IN ULONG Attributes, IN OUT PUNICODE_STRING CompleteName, IN OUT PUNICODE_STRING RemainingName, IN OUT PVOID Context OPTIONAL, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *Object)
Definition: cmparse.c:1030
NTSTATUS NTAPI CmpDoOpen(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PCM_KEY_NODE Node, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE AccessMode, IN ULONG Attributes, IN PCM_PARSE_CONTEXT Context OPTIONAL, IN ULONG ControlFlags, IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb, IN PUNICODE_STRING KeyName, OUT PVOID *Object)
Definition: cmparse.c:558
NTSTATUS NTAPI CmpDoCreateChild(IN PHHIVE Hive, IN HCELL_INDEX ParentCell, IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PACCESS_STATE AccessState, IN PUNICODE_STRING Name, IN KPROCESSOR_MODE AccessMode, IN PCM_PARSE_CONTEXT ParseContext, IN PCM_KEY_CONTROL_BLOCK ParentKcb, IN ULONG Flags, OUT PHCELL_INDEX KeyCell, OUT PVOID *Object)
Definition: cmparse.c:204
VOID NTAPI CmpHandleExitNode(IN OUT PHHIVE *Hive, IN OUT HCELL_INDEX *Cell, IN OUT PCM_KEY_NODE *KeyNode, IN OUT PHHIVE *ReleaseHive, IN OUT HCELL_INDEX *ReleaseCell)
Definition: cmparse.c:958
NTSTATUS NTAPI CmpBuildHashStackAndLookupCache(IN PCM_KEY_BODY ParseObject, IN OUT PCM_KEY_CONTROL_BLOCK *Kcb, IN PUNICODE_STRING Current, OUT PHHIVE *Hive, OUT HCELL_INDEX *Cell, OUT PULONG TotalRemainingSubkeys, OUT PULONG MatchRemainSubkeyLevel, OUT PULONG TotalSubkeys, OUT PULONG OuterStackArray, OUT PULONG *LockedKcbs)
Definition: cmparse.c:994
NTSTATUS NTAPI CmpDoCreate(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PACCESS_STATE AccessState, IN PUNICODE_STRING Name, IN KPROCESSOR_MODE AccessMode, IN PCM_PARSE_CONTEXT ParseContext, IN PCM_KEY_CONTROL_BLOCK ParentKcb, OUT PVOID *Object)
Definition: cmparse.c:403
BOOLEAN NTAPI CmpGetNextName(IN OUT PUNICODE_STRING RemainingName, OUT PUNICODE_STRING NextName, OUT PBOOLEAN LastName)
Definition: cmparse.c:21
VOID NTAPI CmpUnlockRegistry(VOID)
Definition: cmsysini.c:1944
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1858
BOOLEAN CmpNoVolatileCreates
Definition: cmsysini.c:32
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:17
#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
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:25
#define KeGetCurrentThread
Definition: hal.h:55
ULONG * PHCELL_INDEX
Definition: hivedata.h:80
@ Volatile
Definition: hivedata.h:103
@ Stable
Definition: hivedata.h:102
#define HIVE_IS_UNLOADING
Definition: hivedata.h:28
#define HCELL_NIL
Definition: hivedata.h:85
ULONG HCELL_INDEX
Definition: hivedata.h:80
#define HvGetCellType(Cell)
Definition: hivedata.h:95
#define OBJ_OPENLINK
Definition: winternl.h:230
#define ASSERT(a)
Definition: mode.c:44
ObjectType
Definition: metafile.c:81
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define REG_OPTION_CREATE_LINK
Definition: nt_native.h:1063
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
#define REG_LINK
Definition: nt_native.h:1500
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI CmpSecurityMethod(IN PVOID ObjectBody, IN SECURITY_OPERATION_CODE OperationCode, IN PSECURITY_INFORMATION SecurityInformation, IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG BufferLength, IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping)
Definition: cmse.c:261
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_KEY_DELETED
Definition: ntstatus.h:613
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_CHILD_MUST_BE_VOLATILE
Definition: ntstatus.h:618
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
BOOLEAN NTAPI ObCheckObjectAccess(IN PVOID Object, IN OUT PACCESS_STATE AccessState, IN BOOLEAN LockHeld, IN KPROCESSOR_MODE AccessMode, OUT PNTSTATUS ReturnedStatus)
Definition: obsecure.c:441
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
VOID NTAPI ObDereferenceObjectDeferDelete(IN PVOID Object)
Definition: obref.c:358
unsigned short USHORT
Definition: pedump.c:61
SECURITY_INTEGER TimeStamp
Definition: sspi.h:78
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
union _CELL_DATA::@4090 u
WCHAR KeyString[ANYSIZE_ARRAY]
Definition: cmdata.h:206
CM_KEY_NODE KeyNode
Definition: cmdata.h:200
HCELL_INDEX List
Definition: cmdata.h:75
ULONG Count
Definition: cmdata.h:74
Definition: cmlib.h:245
HHIVE Hive
Definition: cmlib.h:246
ULONG Type
Definition: cm.h:221
HANDLE ProcessID
Definition: cm.h:224
struct _CM_NOTIFY_BLOCK * NotifyBlock
Definition: cm.h:223
struct _CM_KEY_CONTROL_BLOCK * KeyControlBlock
Definition: cm.h:222
ULONG RefCount
Definition: cm.h:254
HCELL_INDEX KeyCell
Definition: cm.h:271
USHORT Signature
Definition: cmdata.h:92
ULONG Spare
Definition: cmdata.h:95
CM_KEY_REFERENCE ChildHiveReference
Definition: cmdata.h:105
HCELL_INDEX Parent
Definition: cmdata.h:96
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
HCELL_INDEX SubKeyLists[HTYPE_COUNT]
Definition: cmdata.h:102
ULONG MaxValueNameLen
Definition: cmdata.h:111
ULONG MaxNameLen
Definition: cmdata.h:109
ULONG SubKeyCounts[HTYPE_COUNT]
Definition: cmdata.h:97
HCELL_INDEX Security
Definition: cmdata.h:107
USHORT NameLength
Definition: cmdata.h:114
USHORT ClassLength
Definition: cmdata.h:115
ULONG MaxClassLen
Definition: cmdata.h:110
HCELL_INDEX Class
Definition: cmdata.h:108
ULONG MaxValueDataLen
Definition: cmdata.h:112
CHILD_LIST ValueList
Definition: cmdata.h:103
USHORT Flags
Definition: cmdata.h:93
LARGE_INTEGER LastWriteTime
Definition: cmdata.h:94
PHHIVE KeyHive
Definition: cmdata.h:84
HCELL_INDEX KeyCell
Definition: cmdata.h:83
ULONG Type
Definition: cmdata.h:128
ULONG Disposition
Definition: cm.h:413
BOOLEAN CreateLink
Definition: cm.h:416
BOOLEAN CreateOperation
Definition: cm.h:417
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
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_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#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_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_opt_ WDFKEY _In_ PCUNICODE_STRING _In_ ACCESS_MASK _In_ ULONG CreateOptions
Definition: wdfregistry.h:118
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191
_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:426
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:396
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:417
_In_opt_ PSECURITY_DESCRIPTOR _Out_ PSECURITY_DESCRIPTOR * NewDescriptor
Definition: sefuncs.h:30
__wchar_t WCHAR
Definition: xmlstorage.h:180