ReactOS  0.4.15-dev-3326-ga91f5e8
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 
19 BOOLEAN
20 NTAPI
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 
73 BOOLEAN
74 NTAPI
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;
86  ULONG ValueLength = 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 */
100  LinkCell = CmpFindValueByName(Hive, Node, &CmSymbolicLinkValueName);
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,
114  &ValueLength,
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 
185 Exit:
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 
202 NTSTATUS
203 NTAPI
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,
214  OUT PVOID *Object)
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,
275  AccessMode,
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 */
312  KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
313  KeyNode->Flags = Flags;
314  KeQuerySystemTime(&KeyNode->LastWriteTime);
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,
362  &NewDescriptor,
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 
388 Quickie:
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 
401 NTSTATUS
402 NTAPI
404  IN HCELL_INDEX Cell,
408  IN PCM_PARSE_CONTEXT ParseContext,
409  IN PCM_KEY_CONTROL_BLOCK ParentKcb,
410  OUT PVOID *Object)
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 */
476  Status = CmpDoCreateChild(Hive,
477  Cell,
479  AccessState,
480  Name,
481  AccessMode,
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 
551 Exit:
552  /* Release the flusher lock and return status */
553  return Status;
554 }
555 
556 NTSTATUS
557 NTAPI
559  IN HCELL_INDEX Cell,
565  IN ULONG ControlFlags,
566  IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb,
568  OUT PVOID *Object)
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  {
588  return STATUS_ACCESS_DENIED;
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 */
603  CmpLockRegistry();
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,
687  AccessMode,
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 
706  AccessState,
707  FALSE,
708  AccessMode,
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 
725 NTSTATUS
726 NTAPI
728  IN HCELL_INDEX Cell,
734  IN PCM_KEY_CONTROL_BLOCK ParentKcb,
735  OUT PVOID *Object)
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");
749  return STATUS_ACCESS_DENIED;
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,
810  AccessState,
811  AccessMode,
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,
826  AccessState,
827  &Name,
828  AccessMode,
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 = 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 = 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 = 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 
951 Exit:
952  /* Release the flusher locks and return status */
953  return Status;
954 }
955 
956 VOID
957 NTAPI
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 
992 NTSTATUS
993 NTAPI
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 */
1012  CmpLockRegistry();
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 
1028 NTSTATUS
1029 NTAPI
1030 CmpParseKey(IN PVOID ParseObject,
1035  IN OUT PUNICODE_STRING CompleteName,
1039  OUT PVOID *Object)
1040 {
1041  NTSTATUS Status;
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  if (!Node) ASSERT(FALSE);
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,
1212  AccessState,
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 */
1269  CmpDereferenceKeyControlBlock(ParentKcb);
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 */
1281  Status = CmpCreateLinkNode(Hive,
1282  Cell,
1283  AccessState,
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,
1301  AccessState,
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,
1389  AccessState,
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 */
1414 Quickie:
1415  if (ParentKcb)
1416  CmpDereferenceKeyControlBlock(ParentKcb);
1417 
1418  /* Unlock the registry */
1420  return Status;
1421 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define OBJ_OPENLINK
Definition: winternl.h:230
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define KEY_COMP_NAME
Definition: cmdata.h:35
ObjectType
Definition: metafile.c:80
#define IN
Definition: typedefs.h:39
BOOLEAN NTAPI CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:357
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
CM_KEY_NODE KeyNode
Definition: cmdata.h:200
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
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
HCELL_INDEX List
Definition: cmdata.h:75
BOOLEAN NTAPI CmpAddSubKey(IN PHHIVE Hive, IN HCELL_INDEX Parent, IN HCELL_INDEX Child)
Definition: cmindex.c:1467
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TRUE
Definition: types.h:120
_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:182
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:56
ULONG MaxValueNameLen
Definition: cmdata.h:111
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
USHORT ClassLength
Definition: cmdata.h:115
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
#define HvReleaseCell(h, c)
Definition: cmlib.h:392
LONG NTSTATUS
Definition: precomp.h:26
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38
#define HCELL_NIL
Definition: hivedata.h:85
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
HCELL_INDEX KeyCell
Definition: cm.h:279
VOID NTAPI CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:571
#define CM_KEY_BODY_TYPE
Definition: cm.h:67
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
#define HvGetCellType(Cell)
Definition: hivedata.h:95
HCELL_INDEX CMAPI HvAllocateCell(PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, IN HCELL_INDEX Vicinity)
HCELL_INDEX KeyCell
Definition: cmdata.h:83
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:62
CM_KEY_REFERENCE ChildHiveReference
Definition: cmdata.h:105
struct _CM_NOTIFY_BLOCK * NotifyBlock
Definition: cm.h:231
USHORT NameLength
Definition: cmdata.h:114
_In_opt_ PSECURITY_DESCRIPTOR _Out_ PSECURITY_DESCRIPTOR * NewDescriptor
Definition: sefuncs.h:29
#define REG_OPTION_CREATE_LINK
Definition: nt_native.h:1063
VOID NTAPI EnlistKeyBodyWithKCB(IN PCM_KEY_BODY KeyBody, IN ULONG Flags)
Definition: cmkcbncb.c:1043
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CM_LINK_NODE_SIGNATURE
Definition: cmdata.h:22
HANDLE ProcessID
Definition: cm.h:232
uint32_t ULONG_PTR
Definition: typedefs.h:65
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
ULONG MaxNameLen
Definition: cmdata.h:109
ULONG Disposition
Definition: cm.h:486
return STATUS_NOT_IMPLEMENTED
HCELL_INDEX Class
Definition: cmdata.h:108
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
VOID NTAPI ObDereferenceObjectDeferDelete(IN PVOID Object)
Definition: obref.c:358
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
union node Node
Definition: types.h:1255
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
PVOID CMAPI HvGetCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:67
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:395
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
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
HCELL_INDEX SubKeyLists[HTYPE_COUNT]
Definition: cmdata.h:102
unsigned char BOOLEAN
struct _CM_KEY_NODE * PCM_KEY_NODE
ULONG * PHCELL_INDEX
Definition: hivedata.h:80
_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
HHIVE Hive
Definition: cm.h:394
#define HIVE_IS_UNLOADING
Definition: hivedata.h:28
#define STATUS_KEY_DELETED
Definition: ntstatus.h:613
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:17
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2697
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
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:952
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
struct _CM_KEY_CONTROL_BLOCK * KeyControlBlock
Definition: cm.h:230
CHILD_LIST ValueList
Definition: cmdata.h:103
Status
Definition: gdiplustypes.h:24
#define KEY_HIVE_EXIT
Definition: cmdata.h:31
union _CELL_DATA::@4043 u
#define REG_LINK
Definition: nt_native.h:1500
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PUNICODE_STRING Name)
Definition: cmvalue.c:99
USHORT NTAPI CmpCopyName(IN PHHIVE Hive, OUT PWCHAR Destination, IN PUNICODE_STRING Source)
Definition: cmname.c:21
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
HCELL_INDEX Parent
Definition: cmdata.h:96
ULONG HCELL_INDEX
Definition: hivedata.h:80
ULONG SubKeyCounts[HTYPE_COUNT]
Definition: cmdata.h:97
static void Exit(void)
Definition: sock.c:1331
VOID NTAPI CmpUnlockRegistry(VOID)
Definition: cmsysini.c:1993
USHORT Signature
Definition: cmdata.h:92
#define ObDereferenceObject
Definition: obfuncs.h:203
BOOLEAN NTAPI CmpGetNextName(IN OUT PUNICODE_STRING RemainingName, OUT PUNICODE_STRING NextName, OUT PBOOLEAN LastName)
Definition: cmparse.c:21
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
Definition: hivecell.c:100
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:414
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:441
#define STATUS_CHILD_MUST_BE_VOLATILE
Definition: ntstatus.h:618
#define TAG_CM
Definition: cmlib.h:205
char * PBOOLEAN
Definition: retypes.h:11
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PUNICODE_STRING Name)
Definition: cmname.c:74
#define VOID
Definition: acefi.h:82
LARGE_INTEGER LastWriteTime
Definition: cmdata.h:94
#define KEY_NO_DELETE
Definition: cmdata.h:33
SECURITY_INTEGER TimeStamp
Definition: sspi.h:78
ULONG Count
Definition: cmdata.h:74
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_opt_ WDFKEY _In_ PCUNICODE_STRING _In_ ACCESS_MASK _In_ ULONG CreateOptions
Definition: wdfregistry.h:112
UNICODE_STRING CmSymbolicLinkValueName
Definition: cmdata.c:52
HCELL_INDEX Security
Definition: cmdata.h:107
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
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
#define KEY_SYM_LINK
Definition: cmdata.h:34
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
BOOLEAN CmpNoVolatileCreates
Definition: cmsysini.c:32
ULONG MaxClassLen
Definition: cmdata.h:110
unsigned short USHORT
Definition: pedump.c:61
struct _CM_KEY_VALUE * PCM_KEY_VALUE
ULONG Type
Definition: cmdata.h:128
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define STATUS_REPARSE
Definition: ntstatus.h:83
unsigned int * PULONG
Definition: retypes.h:1
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define NULL
Definition: types.h:112
WCHAR KeyString[ANYSIZE_ARRAY]
Definition: cmdata.h:206
ULONG MaxValueDataLen
Definition: cmdata.h:112
#define MAXUSHORT
Definition: typedefs.h:83
#define DPRINT1
Definition: precomp.h:8
#define CMP_OPEN_KCB_NO_CREATE
Definition: cm.h:98
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
VOID NTAPI CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:606
struct tagContext Context
Definition: acpixf.h:1034
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
ULONG RefCount
Definition: cm.h:262
#define CmpKeyObjectType
Definition: ObTypes.c:132
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
VOID NTAPI CmpReportNotify(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PHHIVE Hive, IN HCELL_INDEX Cell, IN ULONG Filter)
Definition: cmnotify.c:19
#define STATUS_SUCCESS
Definition: shellext.h:65
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
ULONG Spare
Definition: cmdata.h:95
#define KeGetCurrentThread
Definition: hal.h:55
ULONG Type
Definition: cm.h:229
struct _CM_KEY_BODY * PCM_KEY_BODY
BOOLEAN CreateLink
Definition: cm.h:489
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1907
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
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
PHHIVE KeyHive
Definition: cmdata.h:84
BOOLEAN CreateOperation
Definition: cm.h:490
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: cm.h:392
USHORT Flags
Definition: cmdata.h:93
Definition: dlist.c:348
#define PAGED_CODE()
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:801
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:271
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68