ReactOS  0.4.15-dev-3440-g915569a
obname.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/ob/obname.c
5  * PURPOSE: Manages all functions related to the Object Manager name-
6  * space, such as finding objects or querying their names.
7  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8  * Eric Kohl
9  * Thomas Weidenmueller (w3seek@reactos.org)
10  */
11 
12 /* INCLUDES ******************************************************************/
13 
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <debug.h>
17 
21 
22 /* DOS Device Prefix \??\ and \?? */
26 {
30 };
31 
34 
35 /* PRIVATE FUNCTIONS *********************************************************/
36 
37 CODE_SEG("INIT")
39 NTAPI
41 {
42  PACL Dacl;
43  ULONG AclSize;
45 
46  /* Initialize the SD */
49 
50  if (ObpProtectionMode & 1)
51  {
52  AclSize = sizeof(ACL) +
53  sizeof(ACE) + RtlLengthSid(SeWorldSid) +
54  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
55  sizeof(ACE) + RtlLengthSid(SeWorldSid) +
56  sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) +
57  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
59 
60  /* Allocate the ACL */
61  Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'lcaD');
62  if (Dacl == NULL)
63  {
65  }
66 
67  /* Initialize the DACL */
68  Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
70 
71  /* Add the ACEs */
75  SeWorldSid);
77 
83 
88  SeWorldSid);
90 
97 
101  GENERIC_ALL,
104 
106  ACL_REVISION,
108  GENERIC_ALL,
111  }
112  else
113  {
114  AclSize = sizeof(ACL) +
115  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
116  sizeof(ACE) + RtlLengthSid(SeWorldSid) +
117  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid);
118 
119  /* Allocate the ACL */
120  Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'lcaD');
121  if (Dacl == NULL)
122  {
124  }
125 
126  /* Initialize the DACL */
127  Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
129 
130  /* Add the ACEs */
132  ACL_REVISION,
134  SeWorldSid);
136 
138  ACL_REVISION,
139  GENERIC_ALL,
142 
144  ACL_REVISION,
146  GENERIC_ALL,
147  SeWorldSid);
149  }
150 
151  /* Attach the DACL to the SD */
154 
155  return STATUS_SUCCESS;
156 }
157 
158 CODE_SEG("INIT")
159 VOID
160 NTAPI
162 {
163  PACL Dacl;
166 
170  ASSERT(Dacl != NULL);
171  ExFreePoolWithTag(Dacl, 'lcaD');
172 }
173 
174 CODE_SEG("INIT")
175 NTSTATUS
176 NTAPI
178 {
180  UNICODE_STRING RootName, TargetName, LinkName;
181  HANDLE Handle, SymHandle;
182  SECURITY_DESCRIPTOR DosDevicesSD;
184 
185  /*
186  * Enable LUID mappings only if not explicitely disabled
187  * and if protection mode is set
188  */
191  else
193 
194  /* Create a custom security descriptor for the global DosDevices directory */
195  Status = ObpGetDosDevicesProtection(&DosDevicesSD);
196  if (!NT_SUCCESS(Status))
197  return Status;
198 
199  /* Create the global DosDevices directory \?? */
200  RtlInitUnicodeString(&RootName, L"\\GLOBAL??");
202  &RootName,
204  NULL,
205  &DosDevicesSD);
209  if (!NT_SUCCESS(Status))
210  goto done;
211 
212  /* Create the system device map */
214  if (!NT_SUCCESS(Status))
215  goto done;
216 
217  /*
218  * Initialize the \??\GLOBALROOT symbolic link
219  * pointing to the root directory \ .
220  */
221  RtlInitUnicodeString(&LinkName, L"GLOBALROOT");
224  &LinkName,
226  Handle,
227  &DosDevicesSD);
228  Status = NtCreateSymbolicLinkObject(&SymHandle,
231  &TargetName);
232  if (NT_SUCCESS(Status)) NtClose(SymHandle);
233 
234  /*
235  * Initialize the \??\Global symbolic link pointing to the global
236  * DosDevices directory \?? . It is used to access the global \??
237  * by user-mode components which, by default, use a per-session
238  * DosDevices directory.
239  */
240  RtlInitUnicodeString(&LinkName, L"Global");
242  &LinkName,
244  Handle,
245  &DosDevicesSD);
246  Status = NtCreateSymbolicLinkObject(&SymHandle,
249  &RootName);
250  if (NT_SUCCESS(Status)) NtClose(SymHandle);
251 
252  /* Close the directory handle */
253  NtClose(Handle);
254  if (!NT_SUCCESS(Status))
255  goto done;
256 
257  /*
258  * Initialize the \DosDevices symbolic link pointing to the global
259  * DosDevices directory \?? , for backward compatibility with
260  * Windows NT-2000 systems.
261  */
262  RtlInitUnicodeString(&LinkName, L"\\DosDevices");
265  &LinkName,
267  NULL,
268  &DosDevicesSD);
269  Status = NtCreateSymbolicLinkObject(&SymHandle,
272  &RootName);
273  if (NT_SUCCESS(Status)) NtClose(SymHandle);
274 
275 done:
276  ObpFreeDosDevicesProtection(&DosDevicesSD);
277 
278  /* Return status */
279  return Status;
280 }
281 
282 /*++
283 * @name ObpDeleteNameCheck
284 *
285 * The ObpDeleteNameCheck routine checks if a named object should be
286 * removed from the object directory namespace.
287 *
288 * @param Object
289 * Pointer to the object to check for possible removal.
290 *
291 * @return None.
292 *
293 * @remarks An object is removed if the following 4 criteria are met:
294 * 1) The object has 0 handles open
295 * 2) The object is in the directory namespace and has a name
296 * 3) The object is not permanent
297 *
298 *--*/
299 VOID
300 NTAPI
302 {
303  POBJECT_HEADER ObjectHeader;
305  POBJECT_HEADER_NAME_INFO ObjectNameInfo;
307  PVOID Directory = NULL;
308 
309  /* Get object structures */
310  ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
311  ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
312  ObjectType = ObjectHeader->Type;
313 
314  /*
315  * Check if the handle count is 0, if the object is named,
316  * and if the object isn't a permanent object.
317  */
318  if (!(ObjectHeader->HandleCount) &&
319  (ObjectNameInfo) &&
320  (ObjectNameInfo->Name.Length) &&
321  (ObjectNameInfo->Directory) &&
322  !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
323  {
324  /* Setup a lookup context and lock it */
326  ObpAcquireLookupContextLock(&Context, ObjectNameInfo->Directory);
327 
328  /* Do the lookup */
329  Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
330  &ObjectNameInfo->Name,
331  0,
332  FALSE,
333  &Context);
334  if (Object)
335  {
336  /* Lock the object */
337  ObpAcquireObjectLock(ObjectHeader);
338 
339  /* Make sure we can still delete the object */
340  if (!(ObjectHeader->HandleCount) &&
341  !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
342  {
343  /* First delete it from the directory */
345 
346  /* Check if this is a symbolic link */
348  {
349  /* Remove internal name */
351  }
352 
353  /* Check if the kernel exclusive flag is set */
354  ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
355  if ((ObjectNameInfo) &&
356  (ObjectNameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE))
357  {
358  /* Remove protection flag */
359  InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
361  }
362 
363  /* Get the directory */
364  Directory = ObjectNameInfo->Directory;
365  }
366 
367  /* Release the lock */
368  ObpReleaseObjectLock(ObjectHeader);
369  }
370 
371  /* Cleanup after lookup */
373 
374  /* Remove another query reference since we added one on top */
375  ObpDereferenceNameInfo(ObjectNameInfo);
376 
377  /* Check if we were inserted in a directory */
378  if (Directory)
379  {
380  /* We were, so first remove the extra reference we had added */
381  ObpDereferenceNameInfo(ObjectNameInfo);
382 
383  /* Now dereference the object as well */
385  }
386  }
387  else
388  {
389  /* Remove the reference we added */
390  ObpDereferenceNameInfo(ObjectNameInfo);
391  }
392 }
393 
394 BOOLEAN
395 NTAPI
398 {
399  BOOLEAN Unsecure;
400  PWSTR UnsecureBuffer;
401  UNICODE_STRING UnsecureName;
402 
403  /* No unsecure names known, quit */
405  {
406  return FALSE;
407  }
408 
409  /* By default, we have a secure name */
410  Unsecure = FALSE;
411  /* We will browse the whole string */
412  UnsecureBuffer = &ObpUnsecureGlobalNamesBuffer[0];
413  while (TRUE)
414  {
415  /* Initialize the unicode string */
416  RtlInitUnicodeString(&UnsecureName, UnsecureBuffer);
417  /* We're at the end of the multisz string! */
418  if (UnsecureName.Length == 0)
419  {
420  break;
421  }
422 
423  /*
424  * Does the unsecure name prefix the object name?
425  * If so, that's an unsecure name, and return so
426  */
428  {
429  Unsecure = TRUE;
430  break;
431  }
432 
433  /*
434  * Move to the next string. As a reminder, ObpUnsecureGlobalNamesBuffer is
435  * a multisz, so we move the string next to the current UNICODE_NULL char
436  */
437  UnsecureBuffer = (PWSTR)((ULONG_PTR)UnsecureBuffer + UnsecureName.Length + sizeof(UNICODE_NULL));
438  }
439 
440  /* Return our findings */
441  return Unsecure;
442 }
443 
444 NTSTATUS
445 NTAPI
451  IN OUT PVOID ParseContext,
453  IN PVOID InsertObject OPTIONAL,
455  OUT POBP_LOOKUP_CONTEXT LookupContext,
456  OUT PVOID *FoundObject)
457 {
458  PVOID Object;
459  POBJECT_HEADER ObjectHeader;
460  UNICODE_STRING ComponentName, RemainingName;
461  BOOLEAN Reparse = FALSE, SymLink = FALSE;
463  POBJECT_DIRECTORY ReferencedDirectory = NULL, ReferencedParentDirectory = NULL;
464  KIRQL CalloutIrql;
465  OB_PARSE_METHOD ParseRoutine;
467  KPROCESSOR_MODE AccessCheckMode;
468  PWCHAR NewName;
469  POBJECT_HEADER_NAME_INFO ObjectNameInfo;
470  ULONG MaxReparse = 30;
471  PDEVICE_MAP DeviceMap = NULL;
472  UNICODE_STRING LocalName;
473  PAGED_CODE();
475  "%s - Finding Object: %wZ. Expecting: %p\n",
476  __FUNCTION__,
477  ObjectName,
478  InsertObject);
479 
480  /* Initialize starting state */
481  ObpInitializeLookupContext(LookupContext);
482  *FoundObject = NULL;
484  Object = NULL;
485 
486  /* Check if case-insensitivity is checked */
487  if (ObpCaseInsensitive)
488  {
489  /* Check if the object type requests this */
490  if (!(ObjectType) || (ObjectType->TypeInfo.CaseInsensitive))
491  {
492  /* Add the flag to disable case sensitivity */
494  }
495  }
496 
497  /* Check if this is a access checks are being forced */
498  AccessCheckMode = (Attributes & OBJ_FORCE_ACCESS_CHECK) ?
500 
501  /* Check if we got a Root Directory */
502  if (RootHandle)
503  {
504  /* We did. Reference it */
505  Status = ObReferenceObjectByHandle(RootHandle,
506  0,
507  NULL,
508  AccessMode,
509  (PVOID*)&RootDirectory,
510  NULL);
511  if (!NT_SUCCESS(Status)) return Status;
512 
513  /* Get the header */
514  ObjectHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory);
515 
516  /* The name cannot start with a separator, unless this is a file */
517  if ((ObjectName->Buffer) &&
518  (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
519  (ObjectHeader->Type != IoFileObjectType))
520  {
521  /* The syntax is bad, so fail this request */
524  }
525 
526  /* Don't parse a Directory */
527  if (ObjectHeader->Type != ObpDirectoryObjectType)
528  {
529  /* Make sure the Object Type has a parse routine */
530  ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
531  if (!ParseRoutine)
532  {
533  /* We can't parse a name if we don't have a parse routine */
535  return STATUS_INVALID_HANDLE;
536  }
537 
538  /* Set default parse count */
539  MaxReparse = 30;
540 
541  /* Now parse */
542  while (TRUE)
543  {
544  /* Start with the full name */
546 
547  /* Call the Parse Procedure */
548  ObpCalloutStart(&CalloutIrql);
549  Status = ParseRoutine(RootDirectory,
550  ObjectType,
551  AccessState,
552  AccessCheckMode,
553  Attributes,
554  ObjectName,
555  &RemainingName,
556  ParseContext,
557  SecurityQos,
558  &Object);
559  ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
560 
561  /* Check for success or failure, so not reparse */
562  if ((Status != STATUS_REPARSE) &&
564  {
565  /* Check for failure */
566  if (!NT_SUCCESS(Status))
567  {
568  /* Parse routine might not have cleared this, do it */
569  Object = NULL;
570  }
571  else if (!Object)
572  {
573  /* Modify status to reflect failure inside Ob */
575  }
576 
577  /* We're done, return the status and object */
578  *FoundObject = Object;
580  return Status;
581  }
582  else if ((!ObjectName->Length) ||
583  (!ObjectName->Buffer) ||
584  (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
585  {
586  /* Reparsed to the root directory, so start over */
589 
590  /* Don't use this anymore, since we're starting at root */
591  RootHandle = NULL;
592  goto ParseFromRoot;
593  }
594  else if (--MaxReparse)
595  {
596  /* Try reparsing again */
597  continue;
598  }
599  else
600  {
601  /* Reparsed too many times */
603 
604  /* Return the object and normalized status */
605  *FoundObject = Object;
607  return Status;
608  }
609  }
610  }
611  else if (!(ObjectName->Length) || !(ObjectName->Buffer))
612  {
613  /* Just return the Root Directory if we didn't get a name */
615  0,
616  ObjectType,
617  AccessMode);
619 
620  /* Remove the first reference we added and return the object */
622  *FoundObject = Object;
623  return Status;
624  }
625 
626  LocalName = *ObjectName;
627  }
628  else
629  {
630  /* We did not get a Root Directory, so use the root */
632 
633  /* It must start with a path separator */
634  if (!(ObjectName->Length) ||
635  !(ObjectName->Buffer) ||
636  (ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
637  {
638  /* This name is invalid, so fail */
640  }
641 
642  /* Check if the name is only the path separator */
643  if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR))
644  {
645  /* So the caller only wants the root directory; do we have one? */
646  if (!RootDirectory)
647  {
648  /* This must be the first time we're creating it... right? */
649  if (InsertObject)
650  {
651  /* Yes, so return it to ObInsert so that it can create it */
652  Status = ObReferenceObjectByPointer(InsertObject,
653  0,
654  ObjectType,
655  AccessMode);
656  if (NT_SUCCESS(Status)) *FoundObject = InsertObject;
657  return Status;
658  }
659  else
660  {
661  /* This should never really happen */
662  ASSERT(FALSE);
664  }
665  }
666  else
667  {
668  /* We do have the root directory, so just return it */
670  0,
671  ObjectType,
672  AccessMode);
673  if (NT_SUCCESS(Status)) *FoundObject = RootDirectory;
674  return Status;
675  }
676  }
677  else
678  {
679 ParseFromRoot:
680  LocalName = *ObjectName;
681 
682  /* Deference the device map if we already have one */
683  if (DeviceMap != NULL)
684  {
685  ObfDereferenceDeviceMap(DeviceMap);
686  DeviceMap = NULL;
687  }
688 
689  /* Check if this is a possible DOS name */
690  if (!((ULONG_PTR)(ObjectName->Buffer) & 7))
691  {
692  /*
693  * This could be one. Does it match the prefix?
694  * Note that as an optimization, the match is done as 64-bit
695  * compare since the prefix is "\??\" which is exactly 8 bytes.
696  *
697  * In the second branch, we test for "\??" which is also valid.
698  * This time, we use a 32-bit compare followed by a Unicode
699  * character compare (16-bit), since the sum is 6 bytes.
700  */
701  if ((ObjectName->Length >= ObpDosDevicesShortName.Length) &&
702  (*(PULONGLONG)(ObjectName->Buffer) ==
704  {
705  DeviceMap = ObpReferenceDeviceMap();
706  /* We have a local mapping, drop the ?? prefix */
707  if (DeviceMap != NULL && DeviceMap->DosDevicesDirectory != NULL)
708  {
709  LocalName.Length -= ObpDosDevicesShortName.Length;
711  LocalName.Buffer += (ObpDosDevicesShortName.Length / sizeof(WCHAR));
712 
713  /* We'll browse that local directory */
714  Directory = DeviceMap->DosDevicesDirectory;
715  }
716  }
717  else if ((ObjectName->Length == ObpDosDevicesShortName.Length -
718  sizeof(WCHAR)) &&
719  (*(PULONG)(ObjectName->Buffer) ==
721  (*((PWCHAR)(ObjectName->Buffer) + 2) ==
723  {
724  DeviceMap = ObpReferenceDeviceMap();
725 
726  /* Caller is looking for the directory itself */
727  if (DeviceMap != NULL && DeviceMap->DosDevicesDirectory != NULL)
728  {
730  0,
731  ObjectType,
732  AccessMode);
733  if (NT_SUCCESS(Status))
734  {
735  *FoundObject = DeviceMap->DosDevicesDirectory;
736  }
737 
738  ObfDereferenceDeviceMap(DeviceMap);
739  return Status;
740  }
741  }
742  }
743  }
744  }
745 
746  /* Check if we were reparsing a symbolic link */
747  if (!SymLink)
748  {
749  /* Allow reparse */
750  Reparse = TRUE;
751  MaxReparse = 30;
752  }
753 
754  /* Reparse */
755  while (Reparse && MaxReparse)
756  {
757  /* Get the name */
758  RemainingName = LocalName;
759 
760  /* Disable reparsing again */
761  Reparse = FALSE;
762 
763  /* Start parse loop */
764  while (TRUE)
765  {
766  /* Clear object */
767  Object = NULL;
768 
769  /* Check if the name starts with a path separator */
770  if ((RemainingName.Length) &&
771  (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
772  {
773  /* Skip the path separator */
774  RemainingName.Buffer++;
775  RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
776  }
777 
778  /* Find the next Part Name */
779  ComponentName = RemainingName;
780  while (RemainingName.Length)
781  {
782  /* Break if we found the \ ending */
783  if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
784 
785  /* Move on */
786  RemainingName.Buffer++;
787  RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
788  }
789 
790  /* Get its size and make sure it's valid */
791  ComponentName.Length -= RemainingName.Length;
792  if (!ComponentName.Length)
793  {
794  /* Invalid size, fail */
796  break;
797  }
798 
799  /* Check if we're in the root */
801 
802  /* Check if this is a user-mode call that needs to traverse */
803  if ((AccessCheckMode != KernelMode) &&
805  {
806  /* We shouldn't have referenced a directory yet */
807  ASSERT(ReferencedDirectory == NULL);
808 
809  /* Reference the directory */
811  ReferencedDirectory = Directory;
812 
813  /* Check if we have a parent directory */
814  if (ParentDirectory)
815  {
816  /* Check for traverse access */
819  AccessState,
820  FALSE,
821  AccessCheckMode,
822  &Status))
823  {
824  /* We don't have it, fail */
825  break;
826  }
827  }
828  }
829 
830  /* Check if we don't have a remaining name yet */
831  if (!RemainingName.Length)
832  {
833  /* Check if we don't have a referenced directory yet */
834  if (!ReferencedDirectory)
835  {
836  /* Reference it */
838  ReferencedDirectory = Directory;
839  }
840 
841  /* Check if we are inserting an object */
842  if (InsertObject)
843  {
844  /* Lock the lookup context */
845  ObpAcquireLookupContextLock(LookupContext, Directory);
846  }
847  }
848 
849  /* Do the lookup */
851  &ComponentName,
852  Attributes,
853  InsertObject ? FALSE : TRUE,
854  LookupContext);
855  if (!Object)
856  {
857  /* We didn't find it... do we still have a path? */
858  if (RemainingName.Length)
859  {
860  /* Then tell the caller the path wasn't found */
862  break;
863  }
864  else if (!InsertObject)
865  {
866  /* Otherwise, we have a path, but the name isn't valid */
868  break;
869  }
870 
871  /* Check create access for the object */
876  AccessState,
877  &ComponentName,
878  FALSE,
879  AccessCheckMode,
880  &Status))
881  {
882  /* We don't have create access, fail */
883  break;
884  }
885 
886  /* Get the object header */
887  ObjectHeader = OBJECT_TO_OBJECT_HEADER(InsertObject);
888 
889  /*
890  * Deny object creation if:
891  * That's a section object or a symbolic link
892  * Which isn't in the same section that root directory
893  * That doesn't have the SeCreateGlobalPrivilege
894  * And that is not a known unsecure name
895  */
896  if (RootDirectory->SessionId != -1)
897  {
898  if (ObjectHeader->Type == MmSectionObjectType ||
899  ObjectHeader->Type == ObpSymbolicLinkObjectType)
900  {
901  if (RootDirectory->SessionId != PsGetCurrentProcessSessionId() &&
902  !SeSinglePrivilegeCheck(SeCreateGlobalPrivilege, AccessCheckMode) &&
904  {
906  break;
907  }
908  }
909  }
910 
911  /* Create Object Name */
913  ComponentName.Length,
914  OB_NAME_TAG);
915  if (!(NewName) ||
917  LookupContext,
918  ObjectHeader)))
919  {
920  /* Either couldn't allocate the name, or insert failed */
922 
923  /* Fail due to memory reasons */
925  break;
926  }
927 
928  /* Reference newly to be inserted object */
929  ObReferenceObject(InsertObject);
930 
931  /* Get the name information */
932  ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
933 
934  /* Reference the directory */
936 
937  /* Copy the Name */
939  ComponentName.Buffer,
940  ComponentName.Length);
941 
942  /* Check if we had an old name */
943  if (ObjectNameInfo->Name.Buffer)
944  {
945  /* Free it */
946  ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG);
947  }
948 
949  /* Write new one */
950  ObjectNameInfo->Name.Buffer = NewName;
951  ObjectNameInfo->Name.Length = ComponentName.Length;
952  ObjectNameInfo->Name.MaximumLength = ComponentName.Length;
953 
954  /* Return Status and the Expected Object */
956  Object = InsertObject;
957 
958  /* Get out of here */
959  break;
960  }
961 
962 ReparseObject:
963  /* We found it, so now get its header */
964  ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
965 
966  /*
967  * Check for a parse Procedure, but don't bother to parse for an insert
968  * unless it's a Symbolic Link, in which case we MUST parse
969  */
970  ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
971  if ((ParseRoutine) &&
972  (!(InsertObject) || (ParseRoutine == ObpParseSymbolicLink)))
973  {
974  /* Use the Root Directory next time */
975  Directory = NULL;
976 
977  /* Increment the pointer count */
978  InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1);
979 
980  /* Cleanup from the first lookup */
981  ObpReleaseLookupContext(LookupContext);
982 
983  /* Check if we have a referenced directory */
984  if (ReferencedDirectory)
985  {
986  /* We do, dereference it */
987  ObDereferenceObject(ReferencedDirectory);
988  ReferencedDirectory = NULL;
989  }
990 
991  /* Check if we have a referenced parent directory */
992  if (ReferencedParentDirectory)
993  {
994  /* We do, dereference it */
995  ObDereferenceObject(ReferencedParentDirectory);
996  ReferencedParentDirectory = NULL;
997  }
998 
999  /* Call the Parse Procedure */
1000  ObpCalloutStart(&CalloutIrql);
1001  Status = ParseRoutine(Object,
1002  ObjectType,
1003  AccessState,
1004  AccessCheckMode,
1005  Attributes,
1006  ObjectName,
1007  &RemainingName,
1008  ParseContext,
1009  SecurityQos,
1010  &Object);
1011  ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
1012 
1013  /* Remove our extra reference */
1014  ObDereferenceObject(&ObjectHeader->Body);
1015 
1016  /* Check if we have to reparse */
1017  if ((Status == STATUS_REPARSE) ||
1019  {
1020  /* Reparse again */
1021  Reparse = TRUE;
1022  --MaxReparse;
1023  if (MaxReparse == 0)
1024  {
1025  Object = NULL;
1026  break;
1027  }
1028 
1029  /* Start over from root if we got sent back there */
1030  if ((Status == STATUS_REPARSE_OBJECT) ||
1031  (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
1032  {
1033  /* Check if we got a root directory */
1034  if (RootHandle)
1035  {
1036  /* Stop using it, because we have a new directory now */
1038  RootHandle = NULL;
1039  }
1040 
1041  /* Start at Root */
1044 
1045  /* Check for reparse status */
1047  {
1048  /* Don't reparse again */
1049  Reparse = FALSE;
1050 
1051  /* Did we actually get an object to which to reparse? */
1052  if (!Object)
1053  {
1054  /* We didn't, so set a failure status */
1056  }
1057  else
1058  {
1059  /* We did, so we're free to parse the new object */
1060  goto ReparseObject;
1061  }
1062  }
1063  else
1064  {
1065  /* This is a symbolic link */
1066  SymLink = TRUE;
1067  goto ParseFromRoot;
1068  }
1069  }
1071  {
1072  /* We got STATUS_REPARSE but are at the Root Directory */
1073  Object = NULL;
1075  Reparse = FALSE;
1076  }
1077  }
1078  else if (!NT_SUCCESS(Status))
1079  {
1080  /* Total failure */
1081  Object = NULL;
1082  }
1083  else if (!Object)
1084  {
1085  /* We didn't reparse but we didn't find the Object Either */
1087  }
1088 
1089  /* Break out of the loop */
1090  break;
1091  }
1092  else
1093  {
1094  /* No parse routine...do we still have a remaining name? */
1095  if (!RemainingName.Length)
1096  {
1097  /* Are we creating an object? */
1098  if (!InsertObject)
1099  {
1100  /* Check if this is a user-mode call that needs to traverse */
1101  if ((AccessCheckMode != KernelMode) &&
1103  {
1104  /* Check if we can get it */
1107  AccessState,
1108  FALSE,
1109  AccessCheckMode,
1110  &Status))
1111  {
1112  /* We don't have access, fail */
1113  Object = NULL;
1114  break;
1115  }
1116  }
1117 
1118  /* Reference the Object */
1120  0,
1121  ObjectType,
1122  AccessMode);
1123  if (!NT_SUCCESS(Status)) Object = NULL;
1124  }
1125 
1126  /* And get out of the reparse loop */
1127  break;
1128  }
1129  else
1130  {
1131  /* We still have a name; check if this is a directory object */
1132  if (ObjectHeader->Type == ObpDirectoryObjectType)
1133  {
1134  /* Check if we have a referenced parent directory */
1135  if (ReferencedParentDirectory)
1136  {
1137  /* Dereference it */
1138  ObDereferenceObject(ReferencedParentDirectory);
1139  }
1140 
1141  /* Restart the lookup from this directory */
1142  ReferencedParentDirectory = ReferencedDirectory;
1144  Directory = Object;
1145  ReferencedDirectory = NULL;
1146  }
1147  else
1148  {
1149  /* We still have a name, but no parse routine for it */
1151  Object = NULL;
1152  break;
1153  }
1154  }
1155  }
1156  }
1157  }
1158 
1159  /* Check if we failed */
1160  if (!NT_SUCCESS(Status))
1161  {
1162  /* Cleanup after lookup */
1163  ObpReleaseLookupContext(LookupContext);
1164  }
1165 
1166  /* Check if we have a device map and dereference it if so */
1167  if (DeviceMap) ObfDereferenceDeviceMap(DeviceMap);
1168 
1169  /* Check if we have a referenced directory and dereference it if so */
1170  if (ReferencedDirectory) ObDereferenceObject(ReferencedDirectory);
1171 
1172  /* Check if we have a referenced parent directory */
1173  if (ReferencedParentDirectory)
1174  {
1175  /* We do, dereference it */
1176  ObDereferenceObject(ReferencedParentDirectory);
1177  }
1178 
1179  /* Set the found object and check if we got one */
1180  *FoundObject = Object;
1181  if (!Object)
1182  {
1183  /* Nothing was found. Did we reparse or get success? */
1184  if ((Status == STATUS_REPARSE) || (NT_SUCCESS(Status)))
1185  {
1186  /* Set correct failure */
1188  }
1189  }
1190 
1191  /* Check if we had a root directory */
1192  if (RootHandle) ObDereferenceObject(RootDirectory);
1193 
1194  /* Return status to caller */
1196  "%s - Found Object: %p. Expected: %p\n",
1197  __FUNCTION__,
1198  *FoundObject,
1199  InsertObject);
1200  return Status;
1201 }
1202 
1203 /* PUBLIC FUNCTIONS *********************************************************/
1204 
1205 NTSTATUS
1206 NTAPI
1208  OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
1209  IN ULONG Length,
1211 {
1212  POBJECT_HEADER_NAME_INFO LocalInfo;
1213  POBJECT_HEADER ObjectHeader;
1215  ULONG NameSize;
1216  PWCH ObjectName;
1217  BOOLEAN ObjectIsNamed;
1219 
1220  /* Get the Kernel Meta-Structures */
1221  ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
1222  LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
1223 
1224  /* Check if a Query Name Procedure is available */
1225  if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
1226  {
1227  /* Call the procedure inside SEH */
1228  ObjectIsNamed = ((LocalInfo) && (LocalInfo->Name.Length > 0));
1229 
1230  _SEH2_TRY
1231  {
1232  Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
1233  ObjectIsNamed,
1234  ObjectNameInfo,
1235  Length,
1236  ReturnLength,
1237  KernelMode);
1238  }
1240  {
1241  /* Return the exception code */
1243  }
1244  _SEH2_END;
1245 
1246  return Status;
1247  }
1248 
1249  /* Check if the object doesn't even have a name */
1250  if (!(LocalInfo) || !(LocalInfo->Name.Buffer))
1251  {
1253 
1254  _SEH2_TRY
1255  {
1256  /* We're returning the name structure */
1258 
1259  /* Check if we were given enough space */
1260  if (*ReturnLength > Length)
1261  {
1263  }
1264  else
1265  {
1266  /* Return an empty buffer */
1267  RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
1268  }
1269  }
1271  {
1272  /* Return the exception code */
1274  }
1275  _SEH2_END;
1276 
1277  return Status;
1278  }
1279 
1280  /*
1281  * Find the size needed for the name. We won't do
1282  * this during the Name Creation loop because we want
1283  * to let the caller know that the buffer isn't big
1284  * enough right at the beginning, not work our way through
1285  * and find out at the end
1286  */
1287  _SEH2_TRY
1288  {
1290  {
1291  /* Size of the '\' string */
1292  NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
1293  }
1294  else
1295  {
1296  /* Get the Object Directory and add name of Object */
1297  ParentDirectory = LocalInfo->Directory;
1298  NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
1299 
1300  /* Loop inside the directory to get the top-most one (meaning root) */
1302  {
1303  /* Get the Name Information */
1304  LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
1306 
1307  /* Add the size of the Directory Name */
1308  if (LocalInfo && LocalInfo->Directory)
1309  {
1310  /* Size of the '\' string + Directory Name */
1311  NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
1312  LocalInfo->Name.Length;
1313 
1314  /* Move to next parent Directory */
1315  ParentDirectory = LocalInfo->Directory;
1316  }
1317  else
1318  {
1319  /* Directory with no name. We append "...\" */
1320  NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
1321  break;
1322  }
1323  }
1324  }
1325 
1326  /* Finally, add the name of the structure and the null char */
1327  *ReturnLength = NameSize +
1328  sizeof(OBJECT_NAME_INFORMATION) +
1329  sizeof(UNICODE_NULL);
1330 
1331  /* Check if we were given enough space */
1333 
1334  /*
1335  * Now we will actually create the name. We work backwards because
1336  * it's easier to start off from the Name we have and walk up the
1337  * parent directories. We use the same logic as Name Length calculation.
1338  */
1339  LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
1340  ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
1341  *--ObjectName = UNICODE_NULL;
1342 
1343  /* Check if the object is actually the Root directory */
1345  {
1346  /* This is already the Root Directory, return "\\" */
1348  ObjectNameInfo->Name.Length = (USHORT)NameSize;
1349  ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
1350  sizeof(UNICODE_NULL));
1351  ObjectNameInfo->Name.Buffer = ObjectName;
1353  }
1354  else
1355  {
1356  /* Start by adding the Object's Name */
1358  LocalInfo->Name.Length);
1360  LocalInfo->Name.Buffer,
1361  LocalInfo->Name.Length);
1362 
1363  /* Now parse the Parent directories until we reach the top */
1364  ParentDirectory = LocalInfo->Directory;
1366  {
1367  /* Get the name information */
1368  LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
1370 
1371  /* Add the "\" */
1373 
1374  /* Add the Parent Directory's Name */
1375  if (LocalInfo && LocalInfo->Name.Buffer)
1376  {
1377  /* Add the name */
1379  LocalInfo->Name.Length);
1381  LocalInfo->Name.Buffer,
1382  LocalInfo->Name.Length);
1383 
1384  /* Move to next parent */
1385  ParentDirectory = LocalInfo->Directory;
1386  }
1387  else
1388  {
1389  /* Directory without a name, we add "..." */
1391  sizeof(L"...") +
1392  sizeof(UNICODE_NULL));
1393  RtlCopyMemory(ObjectName, L"...", sizeof(L"..."));
1394  break;
1395  }
1396  }
1397 
1398  /* Add Root Directory Name */
1400  ObjectNameInfo->Name.Length = (USHORT)NameSize;
1401  ObjectNameInfo->Name.MaximumLength =
1402  (USHORT)(NameSize + sizeof(UNICODE_NULL));
1403  ObjectNameInfo->Name.Buffer = ObjectName;
1404  }
1405  }
1407  {
1408  /* Return the exception code */
1410  }
1411  _SEH2_END;
1412 
1413  /* Return success */
1414  return Status;
1415 }
1416 
1417 /* EOF */
POBJECT_DIRECTORY Directory
Definition: obtypes.h:432
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
ObjectType
Definition: metafile.c:80
UNICODE_STRING ObpDosDevicesShortName
Definition: obname.c:25
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define IN
Definition: typedefs.h:39
#define GENERIC_ALL
Definition: nt_native.h:92
BOOLEAN ObpCaseInsensitive
Definition: obname.c:18
FORCEINLINE VOID ObpAcquireObjectLock(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:48
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
LONG_PTR HandleCount
Definition: obtypes.h:490
_In_ BOOLEAN _In_opt_ PACL _In_opt_ BOOLEAN DaclDefaulted
Definition: rtlfuncs.h:1594
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS NTAPI ObpGetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: obname.c:40
USHORT MaximumLength
Definition: env_spec_w32.h:370
ULONG ObpLUIDDeviceMapsEnabled
Definition: devicemap.c:18
#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
NTSTATUS NTAPI ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL, IN OUT PUNICODE_STRING ObjectName, IN ULONG Attributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, IN PVOID InsertObject OPTIONAL, IN OUT PACCESS_STATE AccessState, OUT POBP_LOOKUP_CONTEXT LookupContext, OUT PVOID *FoundObject)
Definition: obname.c:446
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
uint16_t * PWSTR
Definition: typedefs.h:56
#define DIRECTORY_CREATE_OBJECT
Definition: nt_native.h:1256
VOID FASTCALL ObfDereferenceDeviceMap(IN PDEVICE_MAP DeviceMap)
Definition: devicemap.c:477
VOID NTAPI ObpDeleteNameCheck(IN PVOID Object)
Definition: obname.c:301
struct _ACE ACE
FORCEINLINE VOID ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:84
BOOLEAN NTAPI ObpIsUnsecureName(IN PUNICODE_STRING ObjectName, IN BOOLEAN CaseInSensitive)
Definition: obname.c:396
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI ObSetDeviceMap(IN PEPROCESS Process, IN HANDLE DirectoryHandle)
Definition: devicemap.c:24
UNICODE_STRING Name
Definition: obtypes.h:433
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
$ULONG LowPart
Definition: ntbasedef.h:569
#define OBJECT_HEADER_TO_NAME_INFO(h)
Definition: obtypes.h:114
#define TOKEN_HAS_TRAVERSE_PRIVILEGE
Definition: setypes.h:1156
BOOLEAN NTAPI ObpCheckTraverseAccess(IN PVOID Object, IN ACCESS_MASK TraverseAccess, IN PACCESS_STATE AccessState OPTIONAL, IN BOOLEAN LockHeld, IN KPROCESSOR_MODE AccessMode, OUT PNTSTATUS AccessStatus)
Definition: obsecure.c:267
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
uint16_t * PWCHAR
Definition: typedefs.h:56
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:62
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL, DWORD, DWORD, PSID)
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1267
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
_In_ BOOLEAN DaclPresent
Definition: rtlfuncs.h:1594
NTSYSAPI NTSTATUS NTAPI RtlGetDaclSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Out_ PBOOLEAN DaclPresent, _Out_ PACL *Dacl, _Out_ PBOOLEAN DaclDefaulted)
#define OB_FLAG_PERMANENT
Definition: obtypes.h:101
_SEH2_TRY
Definition: create.c:4226
NTSYSAPI NTSTATUS NTAPI RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision)
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define OBJECT_TO_OBJECT_HEADER(o)
Definition: obtypes.h:111
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULARGE_INTEGER Alignment
Definition: ob.h:149
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
_In_ const STRING _In_ BOOLEAN CaseInSensitive
Definition: rtlfuncs.h:2335
#define GENERIC_WRITE
Definition: nt_native.h:90
#define STATUS_REPARSE_OBJECT
Definition: ntstatus.h:102
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:395
unsigned char BOOLEAN
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
FORCEINLINE VOID ObpCalloutStart(IN PKIRQL CalloutIrql)
Definition: ob_x.h:497
struct _ACL ACL
UCHAR Flags
Definition: obtypes.h:497
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
NTSTATUS(NTAPI * OB_PARSE_METHOD)(_In_ PVOID ParseObject, _In_ PVOID ObjectType, _Inout_ PACCESS_STATE AccessState, _In_ KPROCESSOR_MODE AccessMode, _In_ ULONG Attributes, _Inout_ PUNICODE_STRING CompleteName, _Inout_ PUNICODE_STRING RemainingName, _Inout_opt_ PVOID Context, _In_opt_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, _Out_ PVOID *Object)
Definition: obtypes.h:215
#define InterlockedExchangeAdd
Definition: interlocked.h:181
BOOLEAN NTAPI ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent, IN POBP_LOOKUP_CONTEXT Context, IN POBJECT_HEADER ObjectHeader)
Definition: obdir.c:45
#define DIRECTORY_TRAVERSE
Definition: nt_native.h:1255
Status
Definition: gdiplustypes.h:24
#define CONTAINER_INHERIT_ACE
Definition: setypes.h:747
ULONG NTAPI PsGetCurrentProcessSessionId(VOID)
Definition: process.c:1133
#define OB_NAME_TAG
Definition: tag.h:151
#define ObpDirectoryObjectType
Definition: ObTypes.c:123
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
$ULONG HighPart
Definition: ntbasedef.h:570
#define DIRECTORY_CREATE_SUBDIRECTORY
Definition: nt_native.h:1257
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
FORCEINLINE POBJECT_HEADER_NAME_INFO ObpReferenceNameInfo(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:102
#define ObDereferenceObject
Definition: obfuncs.h:203
OB_PARSE_METHOD ParseProcedure
Definition: obtypes.h:370
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
ALIGNEDNAME ObpDosDevicesShortNameRoot
Definition: obname.c:24
POBJECT_TYPE MmSectionObjectType
Definition: section.c:195
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
static const LUID SeCreateGlobalPrivilege
Definition: authpackage.c:168
_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
WCHAR * PWCH
Definition: ntbasedef.h:410
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1552
BOOLEAN NTAPI ObCheckCreateObjectAccess(IN PVOID Object, IN ACCESS_MASK CreateAccess, IN PACCESS_STATE AccessState, IN PUNICODE_STRING ComponentName, IN BOOLEAN LockHeld, IN KPROCESSOR_MODE AccessMode, OUT PNTSTATUS AccessStatus)
Definition: obsecure.c:203
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
PSID SeAliasAdminsSid
Definition: sid.c:41
FORCEINLINE VOID ObpCalloutEnd(IN KIRQL CalloutIrql, IN PCHAR Procedure, IN POBJECT_TYPE ObjectType, IN PVOID Object)
Definition: ob_x.h:505
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAceEx(PACL, DWORD, DWORD, DWORD, PSID)
#define OBJ_FORCE_ACCESS_CHECK
Definition: winternl.h:232
PVOID NTAPI ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory, IN PUNICODE_STRING Name, IN ULONG Attributes, IN UCHAR SearchShadow, IN POBP_LOOKUP_CONTEXT Context)
Definition: obdir.c:158
ULONG ObpUnsecureGlobalNamesLength
Definition: obname.c:33
PSID SeCreatorOwnerSid
Definition: sid.c:27
POBJECT_DIRECTORY ObpRootDirectoryObject
Definition: obname.c:19
POBJECT_DIRECTORY ObpTypeDirectoryObject
Definition: obname.c:20
#define OBJ_PERMANENT
Definition: winternl.h:226
WCHAR TargetName[256]
Definition: arping.c:27
#define GENERIC_READ
Definition: compat.h:135
OBJECT_TYPE_INITIALIZER TypeInfo
Definition: obtypes.h:390
PSID SeWorldSid
Definition: sid.c:25
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
#define OB_NAMESPACE_DEBUG
Definition: ob.h:18
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
FORCEINLINE VOID ObpReleaseLookupContext(IN POBP_LOOKUP_CONTEXT Context)
Releases an initialized object directory lookup context. Unlocks it if necessary, and dereferences th...
Definition: ob_x.h:323
VOID NTAPI ObpDeleteSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
Definition: oblink.c:326
NTSTATUS NTAPI NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:765
_SEH2_END
Definition: create.c:4400
#define ObpSymbolicLinkObjectType
Definition: ObTypes.c:124
FORCEINLINE VOID ObpInitializeLookupContext(IN POBP_LOOKUP_CONTEXT Context)
Initializes a new object directory lookup context. Used for lookup operations (insertions/deletions) ...
Definition: ob_x.h:258
ULONG ObpProtectionMode
Definition: obinit.c:57
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
unsigned short USHORT
Definition: pedump.c:61
#define DIRECTORY_ALL_ACCESS
Definition: nt_native.h:1259
NTSTATUS NTAPI ObpParseSymbolicLink(IN PVOID ParsedObject, IN PVOID ObjectType, IN OUT PACCESS_STATE AccessState, IN KPROCESSOR_MODE AccessMode, IN ULONG Attributes, IN OUT PUNICODE_STRING FullPath, IN OUT PUNICODE_STRING RemainingName, IN OUT PVOID Context OPTIONAL, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *NextObject)
Definition: oblink.c:431
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define OBTRACE(x, fmt,...)
Definition: ob.h:34
unsigned int * PULONG
Definition: retypes.h:1
LONG_PTR PointerCount
Definition: obtypes.h:487
#define NULL
Definition: types.h:112
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
IN PDCB ParentDirectory
Definition: fatprocs.h:698
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
#define ACL_REVISION
Definition: setypes.h:39
PSID SeLocalSystemSid
Definition: sid.c:38
_In_ PUNICODE_STRING NewName
Definition: zwfuncs.h:1203
_In_ HANDLE Handle
Definition: extypes.h:390
struct tagContext Context
Definition: acpixf.h:1034
#define OUT
Definition: typedefs.h:40
#define ObReferenceObject
Definition: obfuncs.h:204
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
unsigned int ULONG
Definition: retypes.h:1
ALIGNEDNAME ObpDosDevicesShortNamePrefix
Definition: obname.c:23
OB_QUERYNAME_METHOD QueryNameProcedure
Definition: obtypes.h:372
base for all directory entries
Definition: entries.h:138
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
ULONG ObpLUIDDeviceMapsDisabled
Definition: devicemap.c:17
POBJECT_DIRECTORY DosDevicesDirectory
Definition: obtypes.h:525
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define INHERIT_ONLY_ACE
Definition: setypes.h:749
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
PDEVICE_MAP NTAPI ObpReferenceDeviceMap(VOID)
Definition: devicemap.c:325
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
VOID NTAPI ObpFreeDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: obname.c:161
WCHAR ObpUnsecureGlobalNamesBuffer[128]
Definition: obname.c:32
#define STATUS_OBJECT_PATH_SYNTAX_BAD
Definition: ntstatus.h:295
POBJECT_TYPE Type
Definition: obtypes.h:493
#define GENERIC_EXECUTE
Definition: nt_native.h:91
_In_ BOOLEAN _In_ USHORT Directory
Definition: rtlfuncs.h:3885
NTSTATUS NTAPI ObpCreateDosDevicesDirectory(VOID)
Definition: obname.c:177
#define __FUNCTION__
Definition: types.h:112
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
signed int * PLONG
Definition: retypes.h:5
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
FORCEINLINE VOID ObpDereferenceNameInfo(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
Definition: ob_x.h:143
#define OB_FLAG_KERNEL_EXCLUSIVE
Definition: obtypes.h:109
Definition: rtltypes.h:990
#define OBJECT_INHERIT_ACE
Definition: setypes.h:746
BOOLEAN NTAPI ObpDeleteEntryDirectory(IN POBP_LOOKUP_CONTEXT Context)
#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
FORCEINLINE VOID ObpAcquireLookupContextLock(IN POBP_LOOKUP_CONTEXT Context, IN POBJECT_DIRECTORY Directory)
Locks an object directory lookup context for performing lookup operations (insertions/deletions) in a...
Definition: ob_x.h:281
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68