ReactOS  0.4.14-dev-583-g2a1ba2c
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 Quickie:
383  /* Check if we got here because of failure */
384  if (!NT_SUCCESS(Status))
385  {
386  /* Free any cells we might've allocated */
387  if (ParseContext->Class.Length > 0) HvFreeCell(Hive, ClassCell);
388  HvFreeCell(Hive, *KeyCell);
389  }
390 
391  /* Return status */
392  return Status;
393 }
394 
395 NTSTATUS
396 NTAPI
398  IN HCELL_INDEX Cell,
402  IN PCM_PARSE_CONTEXT ParseContext,
403  IN PCM_KEY_CONTROL_BLOCK ParentKcb,
404  OUT PVOID *Object)
405 {
407  PCELL_DATA CellData;
408  HCELL_INDEX KeyCell;
409  ULONG ParentType;
410  PCM_KEY_BODY KeyBody;
413  PCM_KEY_NODE KeyNode;
414 
415  /* Check if the parent is being deleted */
416  if (ParentKcb->Delete)
417  {
418  /* It has, quit */
419  ASSERT(FALSE);
421  goto Exit;
422  }
423 
424  /* Get the parent node */
425  KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
426  if (!KeyNode)
427  {
428  /* Fail */
429  ASSERT(FALSE);
431  goto Exit;
432  }
433 
434  /* Make sure nobody added us yet */
435  if (CmpFindSubKeyByName(Hive, KeyNode, Name) != HCELL_NIL)
436  {
437  /* Fail */
438  ASSERT(FALSE);
440  goto Exit;
441  }
442 
443  /* Sanity check */
444  ASSERT(Cell == ParentKcb->KeyCell);
445 
446  /* Get the parent type */
447  ParentType = HvGetCellType(Cell);
448  if ((ParentType == Volatile) &&
449  !(ParseContext->CreateOptions & REG_OPTION_VOLATILE))
450  {
451  /* Children of volatile parents must also be volatile */
452  //ASSERT(FALSE);
454  goto Exit;
455  }
456 
457  /* Don't allow children under symlinks */
458  if (ParentKcb->Flags & KEY_SYM_LINK)
459  {
460  /* Fail */
461  ASSERT(FALSE);
463  goto Exit;
464  }
465 
466  /* Make the cell dirty for now */
467  HvMarkCellDirty(Hive, Cell, FALSE);
468 
469  /* Do the actual create operation */
470  Status = CmpDoCreateChild(Hive,
471  Cell,
473  AccessState,
474  Name,
475  AccessMode,
476  ParseContext,
477  ParentKcb,
478  0,
479  &KeyCell,
480  Object);
481  if (NT_SUCCESS(Status))
482  {
483  /* Get the key body */
484  KeyBody = (PCM_KEY_BODY)(*Object);
485 
486  /* Now add the subkey */
487  if (!CmpAddSubKey(Hive, Cell, KeyCell))
488  {
489  /* Failure! We don't handle this yet! */
490  ASSERT(FALSE);
491  }
492 
493  /* Get the key node */
494  KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
495  if (!KeyNode)
496  {
497  /* Fail, this shouldn't happen */
498  ASSERT(FALSE);
499  }
500 
501  /* Sanity checks */
502  ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
503  ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
504  ASSERT(KeyBody->KeyControlBlock->ParentKcb == ParentKcb);
505  ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
506 
507  /* Update the timestamp */
509  KeyNode->LastWriteTime = TimeStamp;
510  KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
511 
512  /* Check if we need to update name maximum */
513  if (KeyNode->MaxNameLen < Name->Length)
514  {
515  /* Do it */
516  KeyNode->MaxNameLen = Name->Length;
517  KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name->Length;
518  }
519 
520  /* Check if we need to update class length maximum */
521  if (KeyNode->MaxClassLen < ParseContext->Class.Length)
522  {
523  /* Update it */
524  KeyNode->MaxClassLen = ParseContext->Class.Length;
525  }
526 
527  /* Check if we're creating a symbolic link */
528  if (ParseContext->CreateOptions & REG_OPTION_CREATE_LINK)
529  {
530  /* Get the cell data */
531  CellData = HvGetCell(Hive, KeyCell);
532  if (!CellData)
533  {
534  /* This shouldn't happen */
535  ASSERT(FALSE);
536  }
537 
538  /* Update the flags */
539  CellData->u.KeyNode.Flags |= KEY_SYM_LINK;
540  KeyBody->KeyControlBlock->Flags = CellData->u.KeyNode.Flags;
541  HvReleaseCell(Hive, KeyCell);
542  }
543  }
544 
545 Exit:
546  /* Release the flusher lock and return status */
547  return Status;
548 }
549 
550 NTSTATUS
551 NTAPI
553  IN HCELL_INDEX Cell,
559  IN ULONG ControlFlags,
560  IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb,
562  OUT PVOID *Object)
563 {
565  PCM_KEY_BODY KeyBody = NULL;
567 
568  /* Make sure the hive isn't locked */
569  if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&
570  (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))
571  {
572  /* It is, don't touch it */
574  }
575 
576  /* Check if we have a context */
577  if (Context)
578  {
579  /* Check if this is a link create (which shouldn't be an open) */
580  if (Context->CreateLink)
581  {
582  return STATUS_ACCESS_DENIED;
583  }
584 
585  /* Check if this is symlink create attempt */
586  if (Context->CreateOptions & REG_OPTION_CREATE_LINK)
587  {
588  /* Key already exists */
590  }
591 
592  /* Set the disposition */
593  Context->Disposition = REG_OPENED_EXISTING_KEY;
594  }
595 
596  /* Do this in the registry lock */
597  CmpLockRegistry();
598 
599  /* If we have a KCB, make sure it's locked */
600  //ASSERT(CmpIsKcbLockedExclusive(*CachedKcb));
601 
602  /* Check if caller doesn't want to create a KCB */
603  if (ControlFlags & CMP_OPEN_KCB_NO_CREATE)
604  {
605  /* Check if this is a symlink */
606  if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
607  {
608  /* This case for a cached KCB is not implemented yet */
609  ASSERT(FALSE);
610  }
611 
612  /* The caller wants to open a cached KCB */
613  if (!CmpReferenceKeyControlBlock(*CachedKcb))
614  {
615  /* Release the registry lock */
617 
618  /* Return failure code */
620  }
621 
622  /* Our kcb is that one */
623  Kcb = *CachedKcb;
624  }
625  else
626  {
627  /* Check if this is a symlink */
628  if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
629  {
630  /* Create the KCB for the symlink */
631  Kcb = CmpCreateKeyControlBlock(Hive,
632  Cell,
633  Node,
634  *CachedKcb,
635  0,
636  KeyName);
637  if (!Kcb)
638  {
639  /* Release registry lock and return failure */
642  }
643 
644  /* Make sure it's also locked, and set the pointer */
645  //ASSERT(CmpIsKcbLockedExclusive(Kcb));
646  *CachedKcb = Kcb;
647 
648  /* Release the registry lock */
650 
651  /* Return reparse required */
652  return STATUS_REPARSE;
653  }
654 
655  /* Create the KCB. FIXME: Use lock flag */
656  Kcb = CmpCreateKeyControlBlock(Hive,
657  Cell,
658  Node,
659  *CachedKcb,
660  0,
661  KeyName);
662  if (!Kcb)
663  {
664  /* Release registry lock and return failure */
667  }
668  }
669 
670  /* Make sure it's also locked, and set the pointer */
671  //ASSERT(CmpIsKcbLockedExclusive(Kcb));
672  *CachedKcb = Kcb;
673 
674  /* Release the registry lock */
676 
677  /* Allocate the key object */
680  NULL,
681  AccessMode,
682  NULL,
683  sizeof(CM_KEY_BODY),
684  0,
685  0,
686  Object);
687  if (NT_SUCCESS(Status))
688  {
689  /* Get the key body and fill it out */
690  KeyBody = (PCM_KEY_BODY)(*Object);
691  KeyBody->KeyControlBlock = Kcb;
692  KeyBody->Type = CM_KEY_BODY_TYPE;
693  KeyBody->ProcessID = PsGetCurrentProcessId();
694  KeyBody->NotifyBlock = NULL;
695 
696  /* Link to the KCB */
697  EnlistKeyBodyWithKCB(KeyBody, 0);
698 
700  AccessState,
701  FALSE,
702  AccessMode,
703  &Status))
704  {
705  /* Access check failed */
707  }
708  }
709  else
710  {
711  /* Failed, dereference the KCB */
713  }
714 
715  /* Return status */
716  return Status;
717 }
718 
719 NTSTATUS
720 NTAPI
722  IN HCELL_INDEX Cell,
728  IN PCM_KEY_CONTROL_BLOCK ParentKcb,
729  OUT PVOID *Object)
730 {
732  HCELL_INDEX KeyCell, LinkCell, ChildCell;
733  PCM_KEY_BODY KeyBody;
735  PCM_KEY_NODE KeyNode;
736  PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;
737 
738  /* Link nodes only allowed on the master */
739  if (Hive != &CmiVolatileHive->Hive)
740  {
741  /* Fail */
742  DPRINT1("Invalid link node attempt\n");
743  return STATUS_ACCESS_DENIED;
744  }
745 
746  /* Check if the parent is being deleted */
747  if (ParentKcb->Delete)
748  {
749  /* It is, quit */
750  ASSERT(FALSE);
752  goto Exit;
753  }
754 
755  /* Allocate a link node */
756  LinkCell = HvAllocateCell(Hive,
758  CmpNameSize(Hive, &Name),
759  Stable,
760  HCELL_NIL);
761  if (LinkCell == HCELL_NIL)
762  {
763  /* Fail */
765  goto Exit;
766  }
767 
768  /* Get the key cell */
769  KeyCell = Context->ChildHive.KeyCell;
770  if (KeyCell != HCELL_NIL)
771  {
772  /* Hive exists! */
773  ChildCell = KeyCell;
774 
775  /* Get the node data */
776  KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);
777  if (!KeyNode)
778  {
779  /* Fail */
780  ASSERT(FALSE);
782  goto Exit;
783  }
784 
785  /* Fill out the data */
786  KeyNode->Parent = LinkCell;
787  KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
788  HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
789 
790  /* Now open the key cell */
791  KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell);
792  if (!KeyNode)
793  {
794  /* Fail */
795  ASSERT(FALSE);
797  goto Exit;
798  }
799 
800  /* Open the parent */
801  Status = CmpDoOpen(Context->ChildHive.KeyHive,
802  KeyCell,
803  KeyNode,
804  AccessState,
805  AccessMode,
807  NULL,
808  0,
809  &Kcb,
810  &Name,
811  Object);
812  HvReleaseCell(Context->ChildHive.KeyHive, KeyCell);
813  }
814  else
815  {
816  /* Do the actual create operation */
817  Status = CmpDoCreateChild(Context->ChildHive.KeyHive,
818  Cell,
819  NULL,
820  AccessState,
821  &Name,
822  AccessMode,
823  Context,
824  ParentKcb,
826  &ChildCell,
827  Object);
828  if (NT_SUCCESS(Status))
829  {
830  /* Setup root pointer */
831  Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;
832  }
833  }
834 
835  /* Check if open or create suceeded */
836  if (NT_SUCCESS(Status))
837  {
838  /* Mark the cell dirty */
839  HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE);
840 
841  /* Get the key node */
842  KeyNode = HvGetCell(Context->ChildHive.KeyHive, ChildCell);
843  if (!KeyNode)
844  {
845  /* Fail */
846  ASSERT(FALSE);
848  goto Exit;
849  }
850 
851  /* Release it */
852  HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
853 
854  /* Set the parent and flags */
855  KeyNode->Parent = LinkCell;
856  KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
857 
858  /* Get the link node */
859  KeyNode = HvGetCell(Hive, LinkCell);
860  if (!KeyNode)
861  {
862  /* Fail */
863  ASSERT(FALSE);
865  goto Exit;
866  }
867 
868  /* Set it up */
870  KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE;
871  KeyNode->Parent = Cell;
872  KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, &Name);
873  if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME;
875  KeyNode->LastWriteTime = TimeStamp;
876 
877  /* Clear out the rest */
878  KeyNode->SubKeyCounts[Stable] = 0;
879  KeyNode->SubKeyCounts[Volatile] = 0;
880  KeyNode->SubKeyLists[Stable] = HCELL_NIL;
881  KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
882  KeyNode->ValueList.Count = 0;
883  KeyNode->ValueList.List = HCELL_NIL;
884  KeyNode->ClassLength = 0;
885 
886  /* Reference the root node */
887  KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive;
888  KeyNode->ChildHiveReference.KeyCell = ChildCell;
889  HvReleaseCell(Hive, LinkCell);
890 
891  /* Get the parent node */
892  KeyNode = HvGetCell(Hive, Cell);
893  if (!KeyNode)
894  {
895  /* Fail */
896  ASSERT(FALSE);
898  goto Exit;
899  }
900 
901  /* Now add the subkey */
902  if (!CmpAddSubKey(Hive, Cell, LinkCell))
903  {
904  /* Failure! We don't handle this yet! */
905  ASSERT(FALSE);
906  }
907 
908  /* Get the key body */
909  KeyBody = (PCM_KEY_BODY)*Object;
910 
911  /* Sanity checks */
912  ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
913  ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
914  ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
915 
916  /* Update the timestamp */
918  KeyNode->LastWriteTime = TimeStamp;
919  KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
920 
921  /* Check if we need to update name maximum */
922  if (KeyNode->MaxNameLen < Name.Length)
923  {
924  /* Do it */
925  KeyNode->MaxNameLen = Name.Length;
926  KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length;
927  }
928 
929  /* Check if we need to update class length maximum */
930  if (KeyNode->MaxClassLen < Context->Class.Length)
931  {
932  /* Update it */
933  KeyNode->MaxClassLen = Context->Class.Length;
934  }
935 
936  /* Release the cell */
937  HvReleaseCell(Hive, Cell);
938  }
939  else
940  {
941  /* Release the link cell */
942  HvReleaseCell(Hive, LinkCell);
943  }
944 
945 Exit:
946  /* Release the flusher locks and return status */
947  return Status;
948 }
949 
950 VOID
951 NTAPI
953  IN OUT HCELL_INDEX *Cell,
954  IN OUT PCM_KEY_NODE *KeyNode,
955  IN OUT PHHIVE *ReleaseHive,
956  IN OUT HCELL_INDEX *ReleaseCell)
957 {
958  /* Check if we have anything to release */
959  if (*ReleaseCell != HCELL_NIL)
960  {
961  /* Release it */
962  ASSERT(*ReleaseHive != NULL);
963  HvReleaseCell(*ReleaseHive, *ReleaseCell);
964  }
965 
966  /* Get the link references */
967  *Hive = (*KeyNode)->ChildHiveReference.KeyHive;
968  *Cell = (*KeyNode)->ChildHiveReference.KeyCell;
969 
970  /* Get the new node */
971  *KeyNode = (PCM_KEY_NODE)HvGetCell(*Hive, *Cell);
972  if (*KeyNode)
973  {
974  /* Set the new release values */
975  *ReleaseCell = *Cell;
976  *ReleaseHive = *Hive;
977  }
978  else
979  {
980  /* Nothing to release */
981  *ReleaseCell = HCELL_NIL;
982  *ReleaseHive = NULL;
983  }
984 }
985 
986 NTSTATUS
987 NTAPI
990  IN PUNICODE_STRING Current,
991  OUT PHHIVE *Hive,
992  OUT HCELL_INDEX *Cell,
993  OUT PULONG TotalRemainingSubkeys,
994  OUT PULONG MatchRemainSubkeyLevel,
995  OUT PULONG TotalSubkeys,
996  OUT PULONG OuterStackArray,
997  OUT PULONG *LockedKcbs)
998 {
999  /* We don't lock anything for now */
1000  *LockedKcbs = NULL;
1001 
1002  /* Calculate hash values */
1003  *TotalRemainingSubkeys = 0xBAADF00D;
1004 
1005  /* Lock the registry */
1006  CmpLockRegistry();
1007 
1008  /* Return hive and cell data */
1009  *Hive = (*Kcb)->KeyHive;
1010  *Cell = (*Kcb)->KeyCell;
1011 
1012  /* Make sure it's not a dead KCB */
1013  ASSERT((*Kcb)->RefCount > 0);
1014 
1015  /* Reference it */
1017 
1018  /* Return success for now */
1019  return STATUS_SUCCESS;
1020 }
1021 
1022 NTSTATUS
1023 NTAPI
1024 CmpParseKey(IN PVOID ParseObject,
1029  IN OUT PUNICODE_STRING CompleteName,
1033  OUT PVOID *Object)
1034 {
1035  NTSTATUS Status;
1036  PCM_KEY_CONTROL_BLOCK Kcb, ParentKcb;
1037  PHHIVE Hive = NULL;
1039  HCELL_INDEX Cell = HCELL_NIL, NextCell;
1040  PHHIVE HiveToRelease = NULL;
1041  HCELL_INDEX CellToRelease = HCELL_NIL;
1042  UNICODE_STRING Current, NextName;
1043  PCM_PARSE_CONTEXT ParseContext = Context;
1044  ULONG TotalRemainingSubkeys = 0, MatchRemainSubkeyLevel = 0, TotalSubkeys = 0;
1045  PULONG LockedKcbs = NULL;
1046  BOOLEAN Result, Last;
1047  PAGED_CODE();
1048 
1049  /* Loop path separators at the end */
1050  while ((RemainingName->Length) &&
1051  (RemainingName->Buffer[(RemainingName->Length / sizeof(WCHAR)) - 1] ==
1053  {
1054  /* Remove path separator */
1055  RemainingName->Length -= sizeof(WCHAR);
1056  }
1057 
1058  /* Fail if this isn't a key object */
1060 
1061  /* Copy the remaining name */
1062  Current = *RemainingName;
1063 
1064  /* Check if this is a create */
1065  if (!(ParseContext) || !(ParseContext->CreateOperation))
1066  {
1067  /* It isn't, so no context */
1068  ParseContext = NULL;
1069  }
1070 
1071  /* Grab the KCB */
1072  Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
1073 
1074  /* Sanity check */
1075  ASSERT(Kcb != NULL);
1076 
1077  /* Fail if the key was marked as deleted */
1078  if (Kcb->Delete)
1079  return STATUS_KEY_DELETED;
1080 
1081  /* Lookup in the cache */
1083  &Kcb,
1084  &Current,
1085  &Hive,
1086  &Cell,
1087  &TotalRemainingSubkeys,
1088  &MatchRemainSubkeyLevel,
1089  &TotalSubkeys,
1090  NULL,
1091  &LockedKcbs);
1092 
1093  /* This is now the parent */
1094  ParentKcb = Kcb;
1095 
1096  /* Sanity check */
1097  ASSERT(ParentKcb != NULL);
1098 
1099  /* Check if everything was found cached */
1100  if (!TotalRemainingSubkeys)
1101  ASSERTMSG("Caching not implemented\n", FALSE);
1102 
1103  /* Don't do anything if we're being deleted */
1104  if (Kcb->Delete)
1105  {
1107  goto Quickie;
1108  }
1109 
1110  /* Check if this is a symlink */
1111  if (Kcb->Flags & KEY_SYM_LINK)
1112  {
1113  /* Get the next name */
1114  Result = CmpGetNextName(&Current, &NextName, &Last);
1115  Current.Buffer = NextName.Buffer;
1116 
1117  /* Validate the current name string length */
1118  if (Current.Length + NextName.Length > MAXUSHORT)
1119  {
1120  /* too long */
1122  goto Quickie;
1123  }
1124  Current.Length += NextName.Length;
1125 
1126  /* Validate the current name string maximum length */
1127  if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
1128  {
1129  /* too long */
1131  goto Quickie;
1132  }
1133  Current.MaximumLength += NextName.MaximumLength;
1134 
1135  /* Parse the symlink */
1136  if (CmpGetSymbolicLink(Hive,
1137  CompleteName,
1138  Kcb,
1139  &Current))
1140  {
1141  /* Symlink parse succeeded */
1143  }
1144  else
1145  {
1146  /* Couldn't find symlink */
1148  }
1149 
1150  /* We're done */
1151  goto Quickie;
1152  }
1153 
1154  /* Get the key node */
1155  Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1156  if (!Node)
1157  {
1159  goto Quickie;
1160  }
1161 
1162  /* Start parsing */
1164  while (TRUE)
1165  {
1166  /* Get the next component */
1167  Result = CmpGetNextName(&Current, &NextName, &Last);
1168  if ((Result) && (NextName.Length))
1169  {
1170  /* See if this is a sym link */
1171  if (!(Kcb->Flags & KEY_SYM_LINK))
1172  {
1173  /* Find the subkey */
1174  NextCell = CmpFindSubKeyByName(Hive, Node, &NextName);
1175  if (NextCell != HCELL_NIL)
1176  {
1177  /* Get the new node */
1178  Cell = NextCell;
1179  Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1180  if (!Node) ASSERT(FALSE);
1181 
1182  /* Check if this was the last key */
1183  if (Last)
1184  {
1185  /* Is this an exit node */
1186  if (Node->Flags & KEY_HIVE_EXIT)
1187  {
1188  /* Handle it */
1189  CmpHandleExitNode(&Hive,
1190  &Cell,
1191  &Node,
1192  &HiveToRelease,
1193  &CellToRelease);
1194  if (!Node)
1195  {
1196  /* Fail */
1198  break;
1199  }
1200  }
1201 
1202  /* Do the open */
1203  Status = CmpDoOpen(Hive,
1204  Cell,
1205  Node,
1206  AccessState,
1207  AccessMode,
1208  Attributes,
1209  ParseContext,
1210  0,
1211  &Kcb,
1212  &NextName,
1213  Object);
1214  if (Status == STATUS_REPARSE)
1215  {
1216  /* Parse the symlink */
1217  if (!CmpGetSymbolicLink(Hive,
1218  CompleteName,
1219  Kcb,
1220  NULL))
1221  {
1222  /* Symlink parse failed */
1224  }
1225  }
1226 
1227  /* We are done */
1228  break;
1229  }
1230 
1231  /* Is this an exit node */
1232  if (Node->Flags & KEY_HIVE_EXIT)
1233  {
1234  /* Handle it */
1235  CmpHandleExitNode(&Hive,
1236  &Cell,
1237  &Node,
1238  &HiveToRelease,
1239  &CellToRelease);
1240  if (!Node)
1241  {
1242  /* Fail */
1244  break;
1245  }
1246  }
1247 
1248  /* Create a KCB for this key */
1249  Kcb = CmpCreateKeyControlBlock(Hive,
1250  Cell,
1251  Node,
1252  ParentKcb,
1253  0,
1254  &NextName);
1255  if (!Kcb)
1256  {
1257  /* Fail */
1259  break;
1260  }
1261 
1262  /* Dereference the parent and set the new one */
1263  CmpDereferenceKeyControlBlock(ParentKcb);
1264  ParentKcb = Kcb;
1265  }
1266  else
1267  {
1268  /* Check if this was the last key for a create */
1269  if ((Last) && (ParseContext))
1270  {
1271  /* Check if we're doing a link node */
1272  if (ParseContext->CreateLink)
1273  {
1274  /* The only thing we should see */
1275  Status = CmpCreateLinkNode(Hive,
1276  Cell,
1277  AccessState,
1278  NextName,
1279  AccessMode,
1280  Attributes,
1281  ParseContext,
1282  ParentKcb,
1283  Object);
1284  }
1285  else if (Hive == &CmiVolatileHive->Hive && CmpNoVolatileCreates)
1286  {
1287  /* Creating keys in the master hive is not allowed */
1289  }
1290  else
1291  {
1292  /* Do the create */
1293  Status = CmpDoCreate(Hive,
1294  Cell,
1295  AccessState,
1296  &NextName,
1297  AccessMode,
1298  ParseContext,
1299  ParentKcb,
1300  Object);
1301  }
1302 
1303  /* Check for reparse (in this case, someone beat us) */
1304  if (Status == STATUS_REPARSE) break;
1305 
1306  /* Update disposition */
1307  ParseContext->Disposition = REG_CREATED_NEW_KEY;
1308  break;
1309  }
1310  else
1311  {
1312  /* Key not found */
1314  break;
1315  }
1316  }
1317  }
1318  else
1319  {
1320  /* Save the next name */
1321  Current.Buffer = NextName.Buffer;
1322 
1323  /* Validate the current name string length */
1324  if (Current.Length + NextName.Length > MAXUSHORT)
1325  {
1326  /* too long */
1328  break;
1329  }
1330  Current.Length += NextName.Length;
1331 
1332  /* Validate the current name string maximum length */
1333  if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
1334  {
1335  /* too long */
1337  break;
1338  }
1339  Current.MaximumLength += NextName.MaximumLength;
1340 
1341  /* Parse the symlink */
1342  if (CmpGetSymbolicLink(Hive,
1343  CompleteName,
1344  Kcb,
1345  &Current))
1346  {
1347  /* Symlink parse succeeded */
1349  }
1350  else
1351  {
1352  /* Couldn't find symlink */
1354  }
1355 
1356  /* We're done */
1357  break;
1358  }
1359  }
1360  else if ((Result) && (Last))
1361  {
1362  /* Opening the root. Is this an exit node? */
1363  if (Node->Flags & KEY_HIVE_EXIT)
1364  {
1365  /* Handle it */
1366  CmpHandleExitNode(&Hive,
1367  &Cell,
1368  &Node,
1369  &HiveToRelease,
1370  &CellToRelease);
1371  if (!Node)
1372  {
1373  /* Fail */
1375  break;
1376  }
1377  }
1378 
1379  /* Do the open */
1380  Status = CmpDoOpen(Hive,
1381  Cell,
1382  Node,
1383  AccessState,
1384  AccessMode,
1385  Attributes,
1386  ParseContext,
1387  CMP_OPEN_KCB_NO_CREATE /* | CMP_CREATE_KCB_KCB_LOCKED */,
1388  &Kcb,
1389  &NextName,
1390  Object);
1391  if (Status == STATUS_REPARSE)
1392  {
1393  /* Nothing to do */
1394  }
1395 
1396  /* We're done */
1397  break;
1398  }
1399  else
1400  {
1401  /* Bogus */
1403  break;
1404  }
1405  }
1406 
1407  /* Dereference the parent if it exists */
1408 Quickie:
1409  if (ParentKcb)
1410  CmpDereferenceKeyControlBlock(ParentKcb);
1411 
1412  /* Unlock the registry */
1414  return Status;
1415 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define KEY_COMP_NAME
Definition: cmdata.h:35
ObjectType
Definition: metafile.c:80
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4711
#define IN
Definition: typedefs.h:38
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 TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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:262
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
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
USHORT MaximumLength
Definition: env_spec_w32.h:370
_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:54
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:390
LONG NTSTATUS
Definition: precomp.h:26
#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
VOID NTAPI CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:571
#define OBJ_OPENLINK
Definition: winternl.h:230
#define CM_KEY_BODY_TYPE
Definition: cm.h:66
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:397
#define HvGetCellType(Cell)
Definition: hivedata.h:95
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
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:230
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 PAGED_CODE()
Definition: video.h:57
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define CM_LINK_NODE_SIGNATURE
Definition: cmdata.h:22
HANDLE ProcessID
Definition: cm.h:231
uint32_t ULONG_PTR
Definition: typedefs.h:63
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:552
ULONG MaxNameLen
Definition: cmdata.h:109
ULONG Disposition
Definition: cm.h:485
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
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 UNICODE_NULL
VOID NTAPI ObDereferenceObjectDeferDelete(IN PVOID Object)
Definition: obref.c:360
#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
union _CELL_DATA::@3925 u
PVOID CMAPI HvGetCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:67
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:396
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
smooth NULL
Definition: ftsmooth.c:416
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:393
#define HIVE_IS_UNLOADING
Definition: hivedata.h:28
#define STATUS_KEY_DELETED
Definition: ntstatus.h:599
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:17
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
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:952
struct _CM_KEY_CONTROL_BLOCK * KeyControlBlock
Definition: cm.h:229
CHILD_LIST ValueList
Definition: cmdata.h:103
#define KEY_HIVE_EXIT
Definition: cmdata.h:31
#define REG_LINK
Definition: nt_native.h:1500
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:259
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
__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
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
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG _In_ ULONG _In_ ULONG CreateOptions
Definition: fltkernel.h:1230
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
static IUnknown Object
Definition: main.c:512
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_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:604
#define TAG_CM
Definition: cmlib.h:203
char * PBOOLEAN
Definition: retypes.h:11
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PUNICODE_STRING Name)
Definition: cmname.c:74
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
#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
UNICODE_STRING CmSymbolicLinkValueName
Definition: cmdata.c:52
Status
Definition: gdiplustypes.h:24
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:721
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
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
#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:254
#define STATUS_REPARSE
Definition: ntstatus.h:83
unsigned int * PULONG
Definition: retypes.h:1
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
WCHAR KeyString[ANYSIZE_ARRAY]
Definition: cmdata.h:206
ULONG MaxValueDataLen
Definition: cmdata.h:112
#define MAXUSHORT
Definition: typedefs.h:81
#define DPRINT1
Definition: precomp.h:8
#define CMP_OPEN_KCB_NO_CREATE
Definition: cm.h:97
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:1024
VOID NTAPI CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:606
#define OUT
Definition: typedefs.h:39
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
ULONG RefCount
Definition: cm.h:261
#define CmpKeyObjectType
Definition: ObTypes.c:132
#define ULONG_PTR
Definition: config.h:101
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
ULONG Spare
Definition: cmdata.h:95
#define KeGetCurrentThread
Definition: hal.h:44
ULONG Type
Definition: cm.h:228
struct _CM_KEY_BODY * PCM_KEY_BODY
BOOLEAN CreateLink
Definition: cm.h:488
return STATUS_SUCCESS
Definition: btrfs.c:2938
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:988
PHHIVE KeyHive
Definition: cmdata.h:84
BOOLEAN CreateOperation
Definition: cm.h:489
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: cm.h:391
USHORT Flags
Definition: cmdata.h:93
Definition: dlist.c:348
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:806
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68