1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Kernel 3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory 4c2c66affSColin Finck * FILE: ntoskrnl/ob/obname.c 5c2c66affSColin Finck * PURPOSE: Manages all functions related to the Object Manager name- 6c2c66affSColin Finck * space, such as finding objects or querying their names. 7c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 8c2c66affSColin Finck * Eric Kohl 9c2c66affSColin Finck * Thomas Weidenmueller (w3seek@reactos.org) 10c2c66affSColin Finck */ 11c2c66affSColin Finck 12c2c66affSColin Finck /* INCLUDES ******************************************************************/ 13c2c66affSColin Finck 14c2c66affSColin Finck #include <ntoskrnl.h> 15c2c66affSColin Finck #define NDEBUG 16c2c66affSColin Finck #include <debug.h> 17c2c66affSColin Finck 18c2c66affSColin Finck BOOLEAN ObpCaseInsensitive = TRUE; 19c2c66affSColin Finck POBJECT_DIRECTORY ObpRootDirectoryObject; 20c2c66affSColin Finck POBJECT_DIRECTORY ObpTypeDirectoryObject; 21c2c66affSColin Finck 22c2c66affSColin Finck /* DOS Device Prefix \??\ and \?? */ 23c2c66affSColin Finck ALIGNEDNAME ObpDosDevicesShortNamePrefix = {{L'\\',L'?',L'?',L'\\'}}; 24c2c66affSColin Finck ALIGNEDNAME ObpDosDevicesShortNameRoot = {{L'\\',L'?',L'?',L'\0'}}; 25c2c66affSColin Finck UNICODE_STRING ObpDosDevicesShortName = 26c2c66affSColin Finck { 27c2c66affSColin Finck sizeof(ObpDosDevicesShortNamePrefix), 28c2c66affSColin Finck sizeof(ObpDosDevicesShortNamePrefix), 29c2c66affSColin Finck (PWSTR)&ObpDosDevicesShortNamePrefix 30c2c66affSColin Finck }; 31c2c66affSColin Finck 32b9423f07SPierre Schweitzer WCHAR ObpUnsecureGlobalNamesBuffer[128] = {0}; 33b9423f07SPierre Schweitzer ULONG ObpUnsecureGlobalNamesLength = sizeof(ObpUnsecureGlobalNamesBuffer); 34b9423f07SPierre Schweitzer 35*7898b2eaSPierre Schweitzer ULONG ObpLUIDDeviceMapsDisabled; 36*7898b2eaSPierre Schweitzer ULONG ObpLUIDDeviceMapsEnabled; 37*7898b2eaSPierre Schweitzer 38c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 39c2c66affSColin Finck 4071fefa32STimo Kreuzer INIT_FUNCTION 41c2c66affSColin Finck NTSTATUS 42c2c66affSColin Finck NTAPI 4395d303bfSPierre Schweitzer ObpGetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor) 44c2c66affSColin Finck { 45c2c66affSColin Finck PACL Dacl; 4695d303bfSPierre Schweitzer ULONG AclSize; 471b42731dSPierre Schweitzer NTSTATUS Status; 4895d303bfSPierre Schweitzer 4995d303bfSPierre Schweitzer /* Initialize the SD */ 501b42731dSPierre Schweitzer Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); 511b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 52c2c66affSColin Finck 5333f524c6SPierre Schweitzer if (ObpProtectionMode & 1) 5433f524c6SPierre Schweitzer { 55c2c66affSColin Finck AclSize = sizeof(ACL) + 56c2c66affSColin Finck sizeof(ACE) + RtlLengthSid(SeWorldSid) + 57c2c66affSColin Finck sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) + 58c2c66affSColin Finck sizeof(ACE) + RtlLengthSid(SeWorldSid) + 59c2c66affSColin Finck sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) + 60c2c66affSColin Finck sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) + 61c2c66affSColin Finck sizeof(ACE) + RtlLengthSid(SeCreatorOwnerSid); 62c2c66affSColin Finck 6395d303bfSPierre Schweitzer /* Allocate the ACL */ 6495d303bfSPierre Schweitzer Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'lcaD'); 6595d303bfSPierre Schweitzer if (Dacl == NULL) 66c2c66affSColin Finck { 67c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 68c2c66affSColin Finck } 69c2c66affSColin Finck 70c2c66affSColin Finck /* Initialize the DACL */ 711b42731dSPierre Schweitzer Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION); 721b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 73c2c66affSColin Finck 74c2c66affSColin Finck /* Add the ACEs */ 751b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, 76c2c66affSColin Finck ACL_REVISION, 77c2c66affSColin Finck GENERIC_READ | GENERIC_EXECUTE, 78c2c66affSColin Finck SeWorldSid); 791b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 80c2c66affSColin Finck 811b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, 82c2c66affSColin Finck ACL_REVISION, 83c2c66affSColin Finck GENERIC_ALL, 84c2c66affSColin Finck SeLocalSystemSid); 851b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 86c2c66affSColin Finck 871b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAceEx(Dacl, 88c2c66affSColin Finck ACL_REVISION, 89c2c66affSColin Finck INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, 90c2c66affSColin Finck GENERIC_EXECUTE, 91c2c66affSColin Finck SeWorldSid); 921b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 93c2c66affSColin Finck 941b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAceEx(Dacl, 95c2c66affSColin Finck ACL_REVISION, 96c2c66affSColin Finck INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, 97c2c66affSColin Finck GENERIC_ALL, 98c2c66affSColin Finck SeAliasAdminsSid); 991b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 100c2c66affSColin Finck 1011b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAceEx(Dacl, 102c2c66affSColin Finck ACL_REVISION, 103c2c66affSColin Finck INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, 104c2c66affSColin Finck GENERIC_ALL, 105c2c66affSColin Finck SeLocalSystemSid); 1061b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 107c2c66affSColin Finck 1081b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAceEx(Dacl, 109c2c66affSColin Finck ACL_REVISION, 110c2c66affSColin Finck INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, 111c2c66affSColin Finck GENERIC_ALL, 112c2c66affSColin Finck SeCreatorOwnerSid); 1131b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 11433f524c6SPierre Schweitzer } 11533f524c6SPierre Schweitzer else 11633f524c6SPierre Schweitzer { 11733f524c6SPierre Schweitzer AclSize = sizeof(ACL) + 11833f524c6SPierre Schweitzer sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) + 11933f524c6SPierre Schweitzer sizeof(ACE) + RtlLengthSid(SeWorldSid) + 12033f524c6SPierre Schweitzer sizeof(ACE) + RtlLengthSid(SeLocalSystemSid); 12133f524c6SPierre Schweitzer 12295d303bfSPierre Schweitzer /* Allocate the ACL */ 12395d303bfSPierre Schweitzer Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'lcaD'); 12495d303bfSPierre Schweitzer if (Dacl == NULL) 12533f524c6SPierre Schweitzer { 12633f524c6SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 12733f524c6SPierre Schweitzer } 12833f524c6SPierre Schweitzer 12933f524c6SPierre Schweitzer /* Initialize the DACL */ 1301b42731dSPierre Schweitzer Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION); 1311b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 13233f524c6SPierre Schweitzer 13333f524c6SPierre Schweitzer /* Add the ACEs */ 1341b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, 13533f524c6SPierre Schweitzer ACL_REVISION, 13633f524c6SPierre Schweitzer GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE, 13733f524c6SPierre Schweitzer SeWorldSid); 1381b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 13933f524c6SPierre Schweitzer 1401b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, 14133f524c6SPierre Schweitzer ACL_REVISION, 14233f524c6SPierre Schweitzer GENERIC_ALL, 14333f524c6SPierre Schweitzer SeLocalSystemSid); 1441b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 14533f524c6SPierre Schweitzer 1461b42731dSPierre Schweitzer Status = RtlAddAccessAllowedAceEx(Dacl, 14733f524c6SPierre Schweitzer ACL_REVISION, 14833f524c6SPierre Schweitzer INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, 14933f524c6SPierre Schweitzer GENERIC_ALL, 15033f524c6SPierre Schweitzer SeWorldSid); 1511b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 15233f524c6SPierre Schweitzer } 153c2c66affSColin Finck 154c2c66affSColin Finck /* Attach the DACL to the SD */ 1551b42731dSPierre Schweitzer Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE); 1561b42731dSPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 157c2c66affSColin Finck 15895d303bfSPierre Schweitzer return STATUS_SUCCESS; 159c2c66affSColin Finck } 160c2c66affSColin Finck 16171fefa32STimo Kreuzer INIT_FUNCTION 1628f655f94SPierre Schweitzer VOID 1638f655f94SPierre Schweitzer NTAPI 1648f655f94SPierre Schweitzer ObpFreeDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor) 1658f655f94SPierre Schweitzer { 1668f655f94SPierre Schweitzer PACL Dacl; 1678f655f94SPierre Schweitzer NTSTATUS Status; 1688f655f94SPierre Schweitzer BOOLEAN DaclPresent, DaclDefaulted; 1698f655f94SPierre Schweitzer 1708f655f94SPierre Schweitzer Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted); 1718f655f94SPierre Schweitzer ASSERT(NT_SUCCESS(Status)); 1728f655f94SPierre Schweitzer ASSERT(DaclPresent); 1738f655f94SPierre Schweitzer ASSERT(Dacl != NULL); 1748f655f94SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 1758f655f94SPierre Schweitzer } 1768f655f94SPierre Schweitzer 1778f655f94SPierre Schweitzer INIT_FUNCTION 178c2c66affSColin Finck NTSTATUS 179c2c66affSColin Finck NTAPI 180c2c66affSColin Finck ObpCreateDosDevicesDirectory(VOID) 181c2c66affSColin Finck { 182c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 183c2c66affSColin Finck UNICODE_STRING RootName, TargetName, LinkName; 184c2c66affSColin Finck HANDLE Handle, SymHandle; 18595d303bfSPierre Schweitzer SECURITY_DESCRIPTOR DosDevicesSD; 186c2c66affSColin Finck NTSTATUS Status; 187c2c66affSColin Finck 188*7898b2eaSPierre Schweitzer /* 189*7898b2eaSPierre Schweitzer * Enable LUID mappings only if not explicitely disabled 190*7898b2eaSPierre Schweitzer * and if protection mode is set 191*7898b2eaSPierre Schweitzer */ 192*7898b2eaSPierre Schweitzer if (ObpProtectionMode == 0 || ObpLUIDDeviceMapsDisabled != 0) 193*7898b2eaSPierre Schweitzer ObpLUIDDeviceMapsEnabled = 0; 194*7898b2eaSPierre Schweitzer 195c2c66affSColin Finck /* Create a custom security descriptor for the global DosDevices directory */ 19695d303bfSPierre Schweitzer Status = ObpGetDosDevicesProtection(&DosDevicesSD); 197c2c66affSColin Finck if (!NT_SUCCESS(Status)) 198c2c66affSColin Finck return Status; 199c2c66affSColin Finck 200c2c66affSColin Finck /* Create the global DosDevices directory \?? */ 201c2c66affSColin Finck RtlInitUnicodeString(&RootName, L"\\GLOBAL??"); 202c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 203c2c66affSColin Finck &RootName, 204c2c66affSColin Finck OBJ_PERMANENT, 205c2c66affSColin Finck NULL, 20695d303bfSPierre Schweitzer &DosDevicesSD); 207c2c66affSColin Finck Status = NtCreateDirectoryObject(&Handle, 208c2c66affSColin Finck DIRECTORY_ALL_ACCESS, 209c2c66affSColin Finck &ObjectAttributes); 210fe6c7f05SPierre Schweitzer if (!NT_SUCCESS(Status)) 211fe6c7f05SPierre Schweitzer goto done; 212c2c66affSColin Finck 213c2c66affSColin Finck /* Create the system device map */ 214933dddebSPierre Schweitzer Status = ObSetDeviceMap(NULL, Handle); 215c2c66affSColin Finck if (!NT_SUCCESS(Status)) 216fe6c7f05SPierre Schweitzer goto done; 217c2c66affSColin Finck 218c2c66affSColin Finck /*********************************************\ 219c2c66affSColin Finck |*** HACK until we support device mappings ***| 220c2c66affSColin Finck |*** Add a symlink \??\ <--> \GLOBAL??\ ***| 221c2c66affSColin Finck \*********************************************/ 222c2c66affSColin Finck RtlInitUnicodeString(&LinkName, L"\\??"); 223c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 224c2c66affSColin Finck &LinkName, 225c2c66affSColin Finck OBJ_PERMANENT, 226c2c66affSColin Finck NULL, 227fe6c7f05SPierre Schweitzer &DosDevicesSD); 228c2c66affSColin Finck Status = NtCreateSymbolicLinkObject(&SymHandle, 229c2c66affSColin Finck SYMBOLIC_LINK_ALL_ACCESS, 230c2c66affSColin Finck &ObjectAttributes, 231c2c66affSColin Finck &RootName); 232c2c66affSColin Finck if (NT_SUCCESS(Status)) NtClose(SymHandle); 233c2c66affSColin Finck /*********************************************\ 234c2c66affSColin Finck \*********************************************/ 235c2c66affSColin Finck 236c2c66affSColin Finck // FIXME: Create a device mapping for the global \?? directory 237c2c66affSColin Finck 238c2c66affSColin Finck /* 239c2c66affSColin Finck * Initialize the \??\GLOBALROOT symbolic link 240c2c66affSColin Finck * pointing to the root directory \ . 241c2c66affSColin Finck */ 242c2c66affSColin Finck RtlInitUnicodeString(&LinkName, L"GLOBALROOT"); 243c2c66affSColin Finck RtlInitUnicodeString(&TargetName, L""); 244c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 245c2c66affSColin Finck &LinkName, 246c2c66affSColin Finck OBJ_PERMANENT, 247c2c66affSColin Finck Handle, 248fe6c7f05SPierre Schweitzer &DosDevicesSD); 249c2c66affSColin Finck Status = NtCreateSymbolicLinkObject(&SymHandle, 250c2c66affSColin Finck SYMBOLIC_LINK_ALL_ACCESS, 251c2c66affSColin Finck &ObjectAttributes, 252c2c66affSColin Finck &TargetName); 253c2c66affSColin Finck if (NT_SUCCESS(Status)) NtClose(SymHandle); 254c2c66affSColin Finck 255c2c66affSColin Finck /* 256c2c66affSColin Finck * Initialize the \??\Global symbolic link pointing to the global 257c2c66affSColin Finck * DosDevices directory \?? . It is used to access the global \?? 258c2c66affSColin Finck * by user-mode components which, by default, use a per-session 259c2c66affSColin Finck * DosDevices directory. 260c2c66affSColin Finck */ 261c2c66affSColin Finck RtlInitUnicodeString(&LinkName, L"Global"); 262c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 263c2c66affSColin Finck &LinkName, 264c2c66affSColin Finck OBJ_PERMANENT, 265c2c66affSColin Finck Handle, 266fe6c7f05SPierre Schweitzer &DosDevicesSD); 267c2c66affSColin Finck Status = NtCreateSymbolicLinkObject(&SymHandle, 268c2c66affSColin Finck SYMBOLIC_LINK_ALL_ACCESS, 269c2c66affSColin Finck &ObjectAttributes, 270c2c66affSColin Finck &RootName); 271c2c66affSColin Finck if (NT_SUCCESS(Status)) NtClose(SymHandle); 272c2c66affSColin Finck 273c2c66affSColin Finck /* Close the directory handle */ 274c2c66affSColin Finck NtClose(Handle); 275fe6c7f05SPierre Schweitzer if (!NT_SUCCESS(Status)) 276fe6c7f05SPierre Schweitzer goto done; 277c2c66affSColin Finck 278c2c66affSColin Finck /* 279c2c66affSColin Finck * Initialize the \DosDevices symbolic link pointing to the global 280c2c66affSColin Finck * DosDevices directory \?? , for backward compatibility with 281c2c66affSColin Finck * Windows NT-2000 systems. 282c2c66affSColin Finck */ 283c2c66affSColin Finck RtlCreateUnicodeString(&LinkName, L"\\DosDevices"); 284c2c66affSColin Finck RtlInitUnicodeString(&RootName, (PCWSTR)&ObpDosDevicesShortNameRoot); 285c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 286c2c66affSColin Finck &LinkName, 287c2c66affSColin Finck OBJ_PERMANENT, 288c2c66affSColin Finck NULL, 289fe6c7f05SPierre Schweitzer &DosDevicesSD); 290c2c66affSColin Finck Status = NtCreateSymbolicLinkObject(&SymHandle, 291c2c66affSColin Finck SYMBOLIC_LINK_ALL_ACCESS, 292c2c66affSColin Finck &ObjectAttributes, 293c2c66affSColin Finck &RootName); 294c2c66affSColin Finck if (NT_SUCCESS(Status)) NtClose(SymHandle); 295c2c66affSColin Finck 296fe6c7f05SPierre Schweitzer done: 2978f655f94SPierre Schweitzer ObpFreeDosDevicesProtection(&DosDevicesSD); 298fe6c7f05SPierre Schweitzer 299c2c66affSColin Finck /* Return status */ 300c2c66affSColin Finck return Status; 301c2c66affSColin Finck } 302c2c66affSColin Finck 303c2c66affSColin Finck /*++ 304c2c66affSColin Finck * @name ObpDeleteNameCheck 305c2c66affSColin Finck * 306c2c66affSColin Finck * The ObpDeleteNameCheck routine checks if a named object should be 307c2c66affSColin Finck * removed from the object directory namespace. 308c2c66affSColin Finck * 309c2c66affSColin Finck * @param Object 310c2c66affSColin Finck * Pointer to the object to check for possible removal. 311c2c66affSColin Finck * 312c2c66affSColin Finck * @return None. 313c2c66affSColin Finck * 314c2c66affSColin Finck * @remarks An object is removed if the following 4 criteria are met: 315c2c66affSColin Finck * 1) The object has 0 handles open 316c2c66affSColin Finck * 2) The object is in the directory namespace and has a name 317c2c66affSColin Finck * 3) The object is not permanent 318c2c66affSColin Finck * 319c2c66affSColin Finck *--*/ 320c2c66affSColin Finck VOID 321c2c66affSColin Finck NTAPI 322c2c66affSColin Finck ObpDeleteNameCheck(IN PVOID Object) 323c2c66affSColin Finck { 324c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 325c2c66affSColin Finck OBP_LOOKUP_CONTEXT Context; 326c2c66affSColin Finck POBJECT_HEADER_NAME_INFO ObjectNameInfo; 327c2c66affSColin Finck POBJECT_TYPE ObjectType; 328c2c66affSColin Finck PVOID Directory = NULL; 329c2c66affSColin Finck 330c2c66affSColin Finck /* Get object structures */ 331c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 332c2c66affSColin Finck ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader); 333c2c66affSColin Finck ObjectType = ObjectHeader->Type; 334c2c66affSColin Finck 335c2c66affSColin Finck /* 336c2c66affSColin Finck * Check if the handle count is 0, if the object is named, 337c2c66affSColin Finck * and if the object isn't a permanent object. 338c2c66affSColin Finck */ 339c2c66affSColin Finck if (!(ObjectHeader->HandleCount) && 340c2c66affSColin Finck (ObjectNameInfo) && 341c2c66affSColin Finck (ObjectNameInfo->Name.Length) && 342c2c66affSColin Finck (ObjectNameInfo->Directory) && 343c2c66affSColin Finck !(ObjectHeader->Flags & OB_FLAG_PERMANENT)) 344c2c66affSColin Finck { 345c2c66affSColin Finck /* Setup a lookup context */ 346c2c66affSColin Finck ObpInitializeLookupContext(&Context); 347c2c66affSColin Finck 348c2c66affSColin Finck /* Lock the directory */ 349c2c66affSColin Finck ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context); 350c2c66affSColin Finck 351c2c66affSColin Finck /* Do the lookup */ 352c2c66affSColin Finck Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory, 353c2c66affSColin Finck &ObjectNameInfo->Name, 354c2c66affSColin Finck 0, 355c2c66affSColin Finck FALSE, 356c2c66affSColin Finck &Context); 357c2c66affSColin Finck if (Object) 358c2c66affSColin Finck { 359c2c66affSColin Finck /* Lock the object */ 360c2c66affSColin Finck ObpAcquireObjectLock(ObjectHeader); 361c2c66affSColin Finck 362c2c66affSColin Finck /* Make sure we can still delete the object */ 363c2c66affSColin Finck if (!(ObjectHeader->HandleCount) && 364c2c66affSColin Finck !(ObjectHeader->Flags & OB_FLAG_PERMANENT)) 365c2c66affSColin Finck { 366c2c66affSColin Finck /* First delete it from the directory */ 367c2c66affSColin Finck ObpDeleteEntryDirectory(&Context); 368c2c66affSColin Finck 369c2c66affSColin Finck /* Check if this is a symbolic link */ 3702c909db2STimo Kreuzer if (ObjectType == ObpSymbolicLinkObjectType) 371c2c66affSColin Finck { 372c2c66affSColin Finck /* Remove internal name */ 373c2c66affSColin Finck ObpDeleteSymbolicLinkName(Object); 374c2c66affSColin Finck } 375c2c66affSColin Finck 376c2c66affSColin Finck /* Check if the kernel exclusive is set */ 377c2c66affSColin Finck ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 378c2c66affSColin Finck if ((ObjectNameInfo) && 379c2c66affSColin Finck (ObjectNameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE)) 380c2c66affSColin Finck { 381c2c66affSColin Finck /* Remove protection flag */ 382c2c66affSColin Finck InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences, 383c2c66affSColin Finck -OB_FLAG_KERNEL_EXCLUSIVE); 384c2c66affSColin Finck } 385c2c66affSColin Finck 386c2c66affSColin Finck /* Get the directory */ 387c2c66affSColin Finck Directory = ObjectNameInfo->Directory; 388c2c66affSColin Finck } 389c2c66affSColin Finck 390c2c66affSColin Finck /* Release the lock */ 391c2c66affSColin Finck ObpReleaseObjectLock(ObjectHeader); 392c2c66affSColin Finck } 393c2c66affSColin Finck 394c2c66affSColin Finck /* Cleanup after lookup */ 395c2c66affSColin Finck ObpReleaseLookupContext(&Context); 396c2c66affSColin Finck 397c2c66affSColin Finck /* Remove another query reference since we added one on top */ 398c2c66affSColin Finck ObpDereferenceNameInfo(ObjectNameInfo); 399c2c66affSColin Finck 400c2c66affSColin Finck /* Check if we were inserted in a directory */ 401c2c66affSColin Finck if (Directory) 402c2c66affSColin Finck { 403c2c66affSColin Finck /* We were, so first remove the extra reference we had added */ 404c2c66affSColin Finck ObpDereferenceNameInfo(ObjectNameInfo); 405c2c66affSColin Finck 406c2c66affSColin Finck /* Now dereference the object as well */ 407c2c66affSColin Finck ObDereferenceObject(Object); 408c2c66affSColin Finck } 409c2c66affSColin Finck } 410c2c66affSColin Finck else 411c2c66affSColin Finck { 412c2c66affSColin Finck /* Remove the reference we added */ 413c2c66affSColin Finck ObpDereferenceNameInfo(ObjectNameInfo); 414c2c66affSColin Finck } 415c2c66affSColin Finck } 416c2c66affSColin Finck 4170f363535SPierre Schweitzer BOOLEAN 4180f363535SPierre Schweitzer NTAPI 4190f363535SPierre Schweitzer ObpIsUnsecureName(IN PUNICODE_STRING ObjectName, 4200f363535SPierre Schweitzer IN BOOLEAN CaseInSensitive) 4210f363535SPierre Schweitzer { 4220f363535SPierre Schweitzer BOOLEAN Unsecure; 4230f363535SPierre Schweitzer PWSTR UnsecureBuffer; 4240f363535SPierre Schweitzer UNICODE_STRING UnsecureName; 4250f363535SPierre Schweitzer 4260f363535SPierre Schweitzer /* No unsecure names known, quit */ 4270f363535SPierre Schweitzer if (ObpUnsecureGlobalNamesBuffer[0] == UNICODE_NULL) 4280f363535SPierre Schweitzer { 4290f363535SPierre Schweitzer return FALSE; 4300f363535SPierre Schweitzer } 4310f363535SPierre Schweitzer 4320f363535SPierre Schweitzer /* By default, we have a secure name */ 4330f363535SPierre Schweitzer Unsecure = FALSE; 4340f363535SPierre Schweitzer /* We will browse the whole string */ 4350f363535SPierre Schweitzer UnsecureBuffer = &ObpUnsecureGlobalNamesBuffer[0]; 4360f363535SPierre Schweitzer while (TRUE) 4370f363535SPierre Schweitzer { 4380f363535SPierre Schweitzer /* Initialize the unicode string */ 4390f363535SPierre Schweitzer RtlInitUnicodeString(&UnsecureName, UnsecureBuffer); 4400f363535SPierre Schweitzer /* We're at the end of the multisz string! */ 4410f363535SPierre Schweitzer if (UnsecureName.Length == 0) 4420f363535SPierre Schweitzer { 4430f363535SPierre Schweitzer break; 4440f363535SPierre Schweitzer } 4450f363535SPierre Schweitzer 4460f363535SPierre Schweitzer /* 4470f363535SPierre Schweitzer * Does the unsecure name prefix the object name? 4480f363535SPierre Schweitzer * If so, that's an unsecure name, and return so 4490f363535SPierre Schweitzer */ 4500f363535SPierre Schweitzer if (RtlPrefixUnicodeString(&UnsecureName, ObjectName, CaseInSensitive)) 4510f363535SPierre Schweitzer { 4520f363535SPierre Schweitzer Unsecure = TRUE; 4530f363535SPierre Schweitzer break; 4540f363535SPierre Schweitzer } 4550f363535SPierre Schweitzer 4560f363535SPierre Schweitzer /* 4570f363535SPierre Schweitzer * Move to the next string. As a reminder, ObpUnsecureGlobalNamesBuffer is 4580f363535SPierre Schweitzer * a multisz, so we move the string next to the current UNICODE_NULL char 4590f363535SPierre Schweitzer */ 4600f363535SPierre Schweitzer UnsecureBuffer = (PWSTR)((ULONG_PTR)UnsecureBuffer + UnsecureName.Length + sizeof(UNICODE_NULL)); 4610f363535SPierre Schweitzer } 4620f363535SPierre Schweitzer 4630f363535SPierre Schweitzer /* Return our findings */ 4640f363535SPierre Schweitzer return Unsecure; 4650f363535SPierre Schweitzer } 4660f363535SPierre Schweitzer 467c2c66affSColin Finck NTSTATUS 468c2c66affSColin Finck NTAPI 469c2c66affSColin Finck ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL, 470c2c66affSColin Finck IN OUT PUNICODE_STRING ObjectName, 471c2c66affSColin Finck IN ULONG Attributes, 472c2c66affSColin Finck IN POBJECT_TYPE ObjectType, 473c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 474c2c66affSColin Finck IN OUT PVOID ParseContext, 475c2c66affSColin Finck IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, 476c2c66affSColin Finck IN PVOID InsertObject OPTIONAL, 477c2c66affSColin Finck IN OUT PACCESS_STATE AccessState, 478c2c66affSColin Finck OUT POBP_LOOKUP_CONTEXT LookupContext, 479c2c66affSColin Finck OUT PVOID *FoundObject) 480c2c66affSColin Finck { 481c2c66affSColin Finck PVOID Object; 482c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 483c2c66affSColin Finck UNICODE_STRING ComponentName, RemainingName; 484c2c66affSColin Finck BOOLEAN Reparse = FALSE, SymLink = FALSE; 485c2c66affSColin Finck POBJECT_DIRECTORY Directory = NULL, ParentDirectory = NULL, RootDirectory; 486c2c66affSColin Finck POBJECT_DIRECTORY ReferencedDirectory = NULL, ReferencedParentDirectory = NULL; 487c2c66affSColin Finck KIRQL CalloutIrql; 488c2c66affSColin Finck OB_PARSE_METHOD ParseRoutine; 489c2c66affSColin Finck NTSTATUS Status; 490c2c66affSColin Finck KPROCESSOR_MODE AccessCheckMode; 491c2c66affSColin Finck PWCHAR NewName; 492c2c66affSColin Finck POBJECT_HEADER_NAME_INFO ObjectNameInfo; 493c2c66affSColin Finck ULONG MaxReparse = 30; 494c2c66affSColin Finck PAGED_CODE(); 495c2c66affSColin Finck OBTRACE(OB_NAMESPACE_DEBUG, 496c2c66affSColin Finck "%s - Finding Object: %wZ. Expecting: %p\n", 497c2c66affSColin Finck __FUNCTION__, 498c2c66affSColin Finck ObjectName, 499c2c66affSColin Finck InsertObject); 500c2c66affSColin Finck 501c2c66affSColin Finck /* Initialize starting state */ 502c2c66affSColin Finck ObpInitializeLookupContext(LookupContext); 503c2c66affSColin Finck *FoundObject = NULL; 504c2c66affSColin Finck Status = STATUS_SUCCESS; 505c2c66affSColin Finck Object = NULL; 506c2c66affSColin Finck 507c2c66affSColin Finck /* Check if case-insensitivity is checked */ 508c2c66affSColin Finck if (ObpCaseInsensitive) 509c2c66affSColin Finck { 510c2c66affSColin Finck /* Check if the object type requests this */ 511c2c66affSColin Finck if (!(ObjectType) || (ObjectType->TypeInfo.CaseInsensitive)) 512c2c66affSColin Finck { 513c2c66affSColin Finck /* Add the flag to disable case sensitivity */ 514c2c66affSColin Finck Attributes |= OBJ_CASE_INSENSITIVE; 515c2c66affSColin Finck } 516c2c66affSColin Finck } 517c2c66affSColin Finck 518c2c66affSColin Finck /* Check if this is a access checks are being forced */ 519c2c66affSColin Finck AccessCheckMode = (Attributes & OBJ_FORCE_ACCESS_CHECK) ? 520c2c66affSColin Finck UserMode : AccessMode; 521c2c66affSColin Finck 522c2c66affSColin Finck /* Check if we got a Root Directory */ 523c2c66affSColin Finck if (RootHandle) 524c2c66affSColin Finck { 525c2c66affSColin Finck /* We did. Reference it */ 526c2c66affSColin Finck Status = ObReferenceObjectByHandle(RootHandle, 527c2c66affSColin Finck 0, 528c2c66affSColin Finck NULL, 529c2c66affSColin Finck AccessMode, 530c2c66affSColin Finck (PVOID*)&RootDirectory, 531c2c66affSColin Finck NULL); 532c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 533c2c66affSColin Finck 534c2c66affSColin Finck /* Get the header */ 535c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory); 536c2c66affSColin Finck 537c2c66affSColin Finck /* The name cannot start with a separator, unless this is a file */ 538c2c66affSColin Finck if ((ObjectName->Buffer) && 539c2c66affSColin Finck (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) && 540c2c66affSColin Finck (ObjectHeader->Type != IoFileObjectType)) 541c2c66affSColin Finck { 542c2c66affSColin Finck /* The syntax is bad, so fail this request */ 543c2c66affSColin Finck ObDereferenceObject(RootDirectory); 544c2c66affSColin Finck return STATUS_OBJECT_PATH_SYNTAX_BAD; 545c2c66affSColin Finck } 546c2c66affSColin Finck 547c2c66affSColin Finck /* Don't parse a Directory */ 5482c909db2STimo Kreuzer if (ObjectHeader->Type != ObpDirectoryObjectType) 549c2c66affSColin Finck { 550c2c66affSColin Finck /* Make sure the Object Type has a parse routine */ 551c2c66affSColin Finck ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure; 552c2c66affSColin Finck if (!ParseRoutine) 553c2c66affSColin Finck { 554c2c66affSColin Finck /* We can't parse a name if we don't have a parse routine */ 555c2c66affSColin Finck ObDereferenceObject(RootDirectory); 556c2c66affSColin Finck return STATUS_INVALID_HANDLE; 557c2c66affSColin Finck } 558c2c66affSColin Finck 559c2c66affSColin Finck /* Set default parse count */ 560c2c66affSColin Finck MaxReparse = 30; 561c2c66affSColin Finck 562c2c66affSColin Finck /* Now parse */ 563c2c66affSColin Finck while (TRUE) 564c2c66affSColin Finck { 565c2c66affSColin Finck /* Start with the full name */ 566c2c66affSColin Finck RemainingName = *ObjectName; 567c2c66affSColin Finck 568c2c66affSColin Finck /* Call the Parse Procedure */ 569c2c66affSColin Finck ObpCalloutStart(&CalloutIrql); 570c2c66affSColin Finck Status = ParseRoutine(RootDirectory, 571c2c66affSColin Finck ObjectType, 572c2c66affSColin Finck AccessState, 573c2c66affSColin Finck AccessCheckMode, 574c2c66affSColin Finck Attributes, 575c2c66affSColin Finck ObjectName, 576c2c66affSColin Finck &RemainingName, 577c2c66affSColin Finck ParseContext, 578c2c66affSColin Finck SecurityQos, 579c2c66affSColin Finck &Object); 580c2c66affSColin Finck ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object); 581c2c66affSColin Finck 582c2c66affSColin Finck /* Check for success or failure, so not reparse */ 583c2c66affSColin Finck if ((Status != STATUS_REPARSE) && 584c2c66affSColin Finck (Status != STATUS_REPARSE_OBJECT)) 585c2c66affSColin Finck { 586c2c66affSColin Finck /* Check for failure */ 587c2c66affSColin Finck if (!NT_SUCCESS(Status)) 588c2c66affSColin Finck { 589c2c66affSColin Finck /* Parse routine might not have cleared this, do it */ 590c2c66affSColin Finck Object = NULL; 591c2c66affSColin Finck } 592c2c66affSColin Finck else if (!Object) 593c2c66affSColin Finck { 594c2c66affSColin Finck /* Modify status to reflect failure inside Ob */ 595c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND; 596c2c66affSColin Finck } 597c2c66affSColin Finck 598c2c66affSColin Finck /* We're done, return the status and object */ 599c2c66affSColin Finck *FoundObject = Object; 600c2c66affSColin Finck ObDereferenceObject(RootDirectory); 601c2c66affSColin Finck return Status; 602c2c66affSColin Finck } 603c2c66affSColin Finck else if ((!ObjectName->Length) || 604c2c66affSColin Finck (!ObjectName->Buffer) || 605c2c66affSColin Finck (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) 606c2c66affSColin Finck { 607c2c66affSColin Finck /* Reparsed to the root directory, so start over */ 608c2c66affSColin Finck ObDereferenceObject(RootDirectory); 609c2c66affSColin Finck RootDirectory = ObpRootDirectoryObject; 610c2c66affSColin Finck 611c2c66affSColin Finck /* Don't use this anymore, since we're starting at root */ 612c2c66affSColin Finck RootHandle = NULL; 613c2c66affSColin Finck goto ParseFromRoot; 614c2c66affSColin Finck } 615c2c66affSColin Finck else if (--MaxReparse) 616c2c66affSColin Finck { 617c2c66affSColin Finck /* Try reparsing again */ 618c2c66affSColin Finck continue; 619c2c66affSColin Finck } 620c2c66affSColin Finck else 621c2c66affSColin Finck { 622c2c66affSColin Finck /* Reparsed too many times */ 623c2c66affSColin Finck ObDereferenceObject(RootDirectory); 624c2c66affSColin Finck 625c2c66affSColin Finck /* Return the object and normalized status */ 626c2c66affSColin Finck *FoundObject = Object; 627c2c66affSColin Finck if (!Object) Status = STATUS_OBJECT_NAME_NOT_FOUND; 628c2c66affSColin Finck return Status; 629c2c66affSColin Finck } 630c2c66affSColin Finck } 631c2c66affSColin Finck } 632c2c66affSColin Finck else if (!(ObjectName->Length) || !(ObjectName->Buffer)) 633c2c66affSColin Finck { 634c2c66affSColin Finck /* Just return the Root Directory if we didn't get a name */ 635c2c66affSColin Finck Status = ObReferenceObjectByPointer(RootDirectory, 636c2c66affSColin Finck 0, 637c2c66affSColin Finck ObjectType, 638c2c66affSColin Finck AccessMode); 639c2c66affSColin Finck if (NT_SUCCESS(Status)) Object = RootDirectory; 640c2c66affSColin Finck 641c2c66affSColin Finck /* Remove the first reference we added and return the object */ 642c2c66affSColin Finck ObDereferenceObject(RootDirectory); 643c2c66affSColin Finck *FoundObject = Object; 644c2c66affSColin Finck return Status; 645c2c66affSColin Finck } 646c2c66affSColin Finck } 647c2c66affSColin Finck else 648c2c66affSColin Finck { 649c2c66affSColin Finck /* We did not get a Root Directory, so use the root */ 650c2c66affSColin Finck RootDirectory = ObpRootDirectoryObject; 651c2c66affSColin Finck 652c2c66affSColin Finck /* It must start with a path separator */ 653c2c66affSColin Finck if (!(ObjectName->Length) || 654c2c66affSColin Finck !(ObjectName->Buffer) || 655c2c66affSColin Finck (ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) 656c2c66affSColin Finck { 657c2c66affSColin Finck /* This name is invalid, so fail */ 658c2c66affSColin Finck return STATUS_OBJECT_PATH_SYNTAX_BAD; 659c2c66affSColin Finck } 660c2c66affSColin Finck 661c2c66affSColin Finck /* Check if the name is only the path separator */ 662c2c66affSColin Finck if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) 663c2c66affSColin Finck { 664c2c66affSColin Finck /* So the caller only wants the root directory; do we have one? */ 665c2c66affSColin Finck if (!RootDirectory) 666c2c66affSColin Finck { 667c2c66affSColin Finck /* This must be the first time we're creating it... right? */ 668c2c66affSColin Finck if (InsertObject) 669c2c66affSColin Finck { 670c2c66affSColin Finck /* Yes, so return it to ObInsert so that it can create it */ 671c2c66affSColin Finck Status = ObReferenceObjectByPointer(InsertObject, 672c2c66affSColin Finck 0, 673c2c66affSColin Finck ObjectType, 674c2c66affSColin Finck AccessMode); 675c2c66affSColin Finck if (NT_SUCCESS(Status)) *FoundObject = InsertObject; 676c2c66affSColin Finck return Status; 677c2c66affSColin Finck } 678c2c66affSColin Finck else 679c2c66affSColin Finck { 680c2c66affSColin Finck /* This should never really happen */ 681c2c66affSColin Finck ASSERT(FALSE); 682c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 683c2c66affSColin Finck } 684c2c66affSColin Finck } 685c2c66affSColin Finck else 686c2c66affSColin Finck { 687c2c66affSColin Finck /* We do have the root directory, so just return it */ 688c2c66affSColin Finck Status = ObReferenceObjectByPointer(RootDirectory, 689c2c66affSColin Finck 0, 690c2c66affSColin Finck ObjectType, 691c2c66affSColin Finck AccessMode); 692c2c66affSColin Finck if (NT_SUCCESS(Status)) *FoundObject = RootDirectory; 693c2c66affSColin Finck return Status; 694c2c66affSColin Finck } 695c2c66affSColin Finck } 696c2c66affSColin Finck else 697c2c66affSColin Finck { 698c2c66affSColin Finck ParseFromRoot: 699c2c66affSColin Finck /* FIXME: Check if we have a device map */ 700c2c66affSColin Finck 701c2c66affSColin Finck /* Check if this is a possible DOS name */ 702c2c66affSColin Finck if (!((ULONG_PTR)(ObjectName->Buffer) & 7)) 703c2c66affSColin Finck { 704c2c66affSColin Finck /* 705c2c66affSColin Finck * This could be one. Does it match the prefix? 706c2c66affSColin Finck * Note that as an optimization, the match is done as 64-bit 707c2c66affSColin Finck * compare since the prefix is "\??\" which is exactly 8 bytes. 708c2c66affSColin Finck * 709c2c66affSColin Finck * In the second branch, we test for "\??" which is also valid. 710c2c66affSColin Finck * This time, we use a 32-bit compare followed by a Unicode 711c2c66affSColin Finck * character compare (16-bit), since the sum is 6 bytes. 712c2c66affSColin Finck */ 713c2c66affSColin Finck if ((ObjectName->Length >= ObpDosDevicesShortName.Length) && 714c2c66affSColin Finck (*(PULONGLONG)(ObjectName->Buffer) == 715c2c66affSColin Finck ObpDosDevicesShortNamePrefix.Alignment.QuadPart)) 716c2c66affSColin Finck { 717c2c66affSColin Finck /* FIXME! */ 718c2c66affSColin Finck } 719c2c66affSColin Finck else if ((ObjectName->Length == ObpDosDevicesShortName.Length - 720c2c66affSColin Finck sizeof(WCHAR)) && 721c2c66affSColin Finck (*(PULONG)(ObjectName->Buffer) == 722c2c66affSColin Finck ObpDosDevicesShortNameRoot.Alignment.LowPart) && 723c2c66affSColin Finck (*((PWCHAR)(ObjectName->Buffer) + 2) == 724c2c66affSColin Finck (WCHAR)(ObpDosDevicesShortNameRoot.Alignment.HighPart))) 725c2c66affSColin Finck { 726c2c66affSColin Finck /* FIXME! */ 727c2c66affSColin Finck } 728c2c66affSColin Finck } 729c2c66affSColin Finck } 730c2c66affSColin Finck } 731c2c66affSColin Finck 732c2c66affSColin Finck /* Check if we were reparsing a symbolic link */ 733c2c66affSColin Finck if (!SymLink) 734c2c66affSColin Finck { 735c2c66affSColin Finck /* Allow reparse */ 736c2c66affSColin Finck Reparse = TRUE; 737c2c66affSColin Finck MaxReparse = 30; 738c2c66affSColin Finck } 739c2c66affSColin Finck 740c2c66affSColin Finck /* Reparse */ 741c2c66affSColin Finck while (Reparse && MaxReparse) 742c2c66affSColin Finck { 743c2c66affSColin Finck /* Get the name */ 744c2c66affSColin Finck RemainingName = *ObjectName; 745c2c66affSColin Finck 746c2c66affSColin Finck /* Disable reparsing again */ 747c2c66affSColin Finck Reparse = FALSE; 748c2c66affSColin Finck 749c2c66affSColin Finck /* Start parse loop */ 750c2c66affSColin Finck while (TRUE) 751c2c66affSColin Finck { 752c2c66affSColin Finck /* Clear object */ 753c2c66affSColin Finck Object = NULL; 754c2c66affSColin Finck 755c2c66affSColin Finck /* Check if the name starts with a path separator */ 756c2c66affSColin Finck if ((RemainingName.Length) && 757c2c66affSColin Finck (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) 758c2c66affSColin Finck { 759c2c66affSColin Finck /* Skip the path separator */ 760c2c66affSColin Finck RemainingName.Buffer++; 761c2c66affSColin Finck RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR); 762c2c66affSColin Finck } 763c2c66affSColin Finck 764c2c66affSColin Finck /* Find the next Part Name */ 765c2c66affSColin Finck ComponentName = RemainingName; 766c2c66affSColin Finck while (RemainingName.Length) 767c2c66affSColin Finck { 768c2c66affSColin Finck /* Break if we found the \ ending */ 769c2c66affSColin Finck if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break; 770c2c66affSColin Finck 771c2c66affSColin Finck /* Move on */ 772c2c66affSColin Finck RemainingName.Buffer++; 773c2c66affSColin Finck RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR); 774c2c66affSColin Finck } 775c2c66affSColin Finck 776c2c66affSColin Finck /* Get its size and make sure it's valid */ 777c2c66affSColin Finck ComponentName.Length -= RemainingName.Length; 778c2c66affSColin Finck if (!ComponentName.Length) 779c2c66affSColin Finck { 780c2c66affSColin Finck /* Invalid size, fail */ 781c2c66affSColin Finck Status = STATUS_OBJECT_NAME_INVALID; 782c2c66affSColin Finck break; 783c2c66affSColin Finck } 784c2c66affSColin Finck 785c2c66affSColin Finck /* Check if we're in the root */ 786c2c66affSColin Finck if (!Directory) Directory = RootDirectory; 787c2c66affSColin Finck 788c2c66affSColin Finck /* Check if this is a user-mode call that needs to traverse */ 789c2c66affSColin Finck if ((AccessCheckMode != KernelMode) && 790c2c66affSColin Finck !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE)) 791c2c66affSColin Finck { 792c2c66affSColin Finck /* We shouldn't have referenced a directory yet */ 793c2c66affSColin Finck ASSERT(ReferencedDirectory == NULL); 794c2c66affSColin Finck 795c2c66affSColin Finck /* Reference the directory */ 796c2c66affSColin Finck ObReferenceObject(Directory); 797c2c66affSColin Finck ReferencedDirectory = Directory; 798c2c66affSColin Finck 799c2c66affSColin Finck /* Check if we have a parent directory */ 800c2c66affSColin Finck if (ParentDirectory) 801c2c66affSColin Finck { 802c2c66affSColin Finck /* Check for traverse access */ 803c2c66affSColin Finck if (!ObpCheckTraverseAccess(ParentDirectory, 804c2c66affSColin Finck DIRECTORY_TRAVERSE, 805c2c66affSColin Finck AccessState, 806c2c66affSColin Finck FALSE, 807c2c66affSColin Finck AccessCheckMode, 808c2c66affSColin Finck &Status)) 809c2c66affSColin Finck { 810c2c66affSColin Finck /* We don't have it, fail */ 811c2c66affSColin Finck break; 812c2c66affSColin Finck } 813c2c66affSColin Finck } 814c2c66affSColin Finck } 815c2c66affSColin Finck 816c2c66affSColin Finck /* Check if we don't have a remaining name yet */ 817c2c66affSColin Finck if (!RemainingName.Length) 818c2c66affSColin Finck { 819c2c66affSColin Finck /* Check if we don't have a referenced directory yet */ 820c2c66affSColin Finck if (!ReferencedDirectory) 821c2c66affSColin Finck { 822c2c66affSColin Finck /* Reference it */ 823c2c66affSColin Finck ObReferenceObject(Directory); 824c2c66affSColin Finck ReferencedDirectory = Directory; 825c2c66affSColin Finck } 826c2c66affSColin Finck 827c2c66affSColin Finck /* Check if we are inserting an object */ 828c2c66affSColin Finck if (InsertObject) 829c2c66affSColin Finck { 830c2c66affSColin Finck /* Lock the directory */ 831c2c66affSColin Finck ObpAcquireDirectoryLockExclusive(Directory, LookupContext); 832c2c66affSColin Finck } 833c2c66affSColin Finck } 834c2c66affSColin Finck 835c2c66affSColin Finck /* Do the lookup */ 836c2c66affSColin Finck Object = ObpLookupEntryDirectory(Directory, 837c2c66affSColin Finck &ComponentName, 838c2c66affSColin Finck Attributes, 839c2c66affSColin Finck InsertObject ? FALSE : TRUE, 840c2c66affSColin Finck LookupContext); 841c2c66affSColin Finck if (!Object) 842c2c66affSColin Finck { 843c2c66affSColin Finck /* We didn't find it... do we still have a path? */ 844c2c66affSColin Finck if (RemainingName.Length) 845c2c66affSColin Finck { 846c2c66affSColin Finck /* Then tell the caller the path wasn't found */ 847c2c66affSColin Finck Status = STATUS_OBJECT_PATH_NOT_FOUND; 848c2c66affSColin Finck break; 849c2c66affSColin Finck } 850c2c66affSColin Finck else if (!InsertObject) 851c2c66affSColin Finck { 852c2c66affSColin Finck /* Otherwise, we have a path, but the name isn't valid */ 853c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND; 854c2c66affSColin Finck break; 855c2c66affSColin Finck } 856c2c66affSColin Finck 857c2c66affSColin Finck /* Check create access for the object */ 858c2c66affSColin Finck if (!ObCheckCreateObjectAccess(Directory, 8592c909db2STimo Kreuzer ObjectType == ObpDirectoryObjectType ? 860c2c66affSColin Finck DIRECTORY_CREATE_SUBDIRECTORY : 861c2c66affSColin Finck DIRECTORY_CREATE_OBJECT, 862c2c66affSColin Finck AccessState, 863c2c66affSColin Finck &ComponentName, 864c2c66affSColin Finck FALSE, 865c2c66affSColin Finck AccessCheckMode, 866c2c66affSColin Finck &Status)) 867c2c66affSColin Finck { 868c2c66affSColin Finck /* We don't have create access, fail */ 869c2c66affSColin Finck break; 870c2c66affSColin Finck } 871c2c66affSColin Finck 872c2c66affSColin Finck /* Get the object header */ 873c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(InsertObject); 874c2c66affSColin Finck 8759c603718SPierre Schweitzer /* 8769c603718SPierre Schweitzer * Deny object creation if: 8779c603718SPierre Schweitzer * That's a section object or a symbolic link 8789c603718SPierre Schweitzer * Which isn't in the same section that root directory 8799c603718SPierre Schweitzer * That doesn't have the SeCreateGlobalPrivilege 8809c603718SPierre Schweitzer * And that is not a known unsecure name 8819c603718SPierre Schweitzer */ 8829c603718SPierre Schweitzer if (RootDirectory->SessionId != -1) 8839c603718SPierre Schweitzer { 8849c603718SPierre Schweitzer if (ObjectHeader->Type == MmSectionObjectType || 8859c603718SPierre Schweitzer ObjectHeader->Type == ObpSymbolicLinkObjectType) 8869c603718SPierre Schweitzer { 8879c603718SPierre Schweitzer if (RootDirectory->SessionId != PsGetCurrentProcessSessionId() && 8889c603718SPierre Schweitzer !SeSinglePrivilegeCheck(SeCreateGlobalPrivilege, AccessCheckMode) && 8899c603718SPierre Schweitzer !ObpIsUnsecureName(&ComponentName, BooleanFlagOn(Attributes, OBJ_CASE_INSENSITIVE))) 8909c603718SPierre Schweitzer { 8919c603718SPierre Schweitzer Status = STATUS_ACCESS_DENIED; 8929c603718SPierre Schweitzer break; 8939c603718SPierre Schweitzer } 8949c603718SPierre Schweitzer } 8959c603718SPierre Schweitzer } 896c2c66affSColin Finck 897c2c66affSColin Finck /* Create Object Name */ 898c2c66affSColin Finck NewName = ExAllocatePoolWithTag(PagedPool, 899c2c66affSColin Finck ComponentName.Length, 900c2c66affSColin Finck OB_NAME_TAG); 901c2c66affSColin Finck if (!(NewName) || 902c2c66affSColin Finck !(ObpInsertEntryDirectory(Directory, 903c2c66affSColin Finck LookupContext, 904c2c66affSColin Finck ObjectHeader))) 905c2c66affSColin Finck { 906c2c66affSColin Finck /* Either couldn't allocate the name, or insert failed */ 907c2c66affSColin Finck if (NewName) ExFreePoolWithTag(NewName, OB_NAME_TAG); 908c2c66affSColin Finck 909c2c66affSColin Finck /* Fail due to memory reasons */ 910c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 911c2c66affSColin Finck break; 912c2c66affSColin Finck } 913c2c66affSColin Finck 914c2c66affSColin Finck /* Reference newly to be inserted object */ 915c2c66affSColin Finck ObReferenceObject(InsertObject); 916c2c66affSColin Finck 917c2c66affSColin Finck /* Get the name information */ 918c2c66affSColin Finck ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 919c2c66affSColin Finck 920c2c66affSColin Finck /* Reference the directory */ 921c2c66affSColin Finck ObReferenceObject(Directory); 922c2c66affSColin Finck 923c2c66affSColin Finck /* Copy the Name */ 924c2c66affSColin Finck RtlCopyMemory(NewName, 925c2c66affSColin Finck ComponentName.Buffer, 926c2c66affSColin Finck ComponentName.Length); 927c2c66affSColin Finck 928c2c66affSColin Finck /* Check if we had an old name */ 929c2c66affSColin Finck if (ObjectNameInfo->Name.Buffer) 930c2c66affSColin Finck { 931c2c66affSColin Finck /* Free it */ 932c2c66affSColin Finck ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG); 933c2c66affSColin Finck } 934c2c66affSColin Finck 935c2c66affSColin Finck /* Write new one */ 936c2c66affSColin Finck ObjectNameInfo->Name.Buffer = NewName; 937c2c66affSColin Finck ObjectNameInfo->Name.Length = ComponentName.Length; 938c2c66affSColin Finck ObjectNameInfo->Name.MaximumLength = ComponentName.Length; 939c2c66affSColin Finck 940c2c66affSColin Finck /* Return Status and the Expected Object */ 941c2c66affSColin Finck Status = STATUS_SUCCESS; 942c2c66affSColin Finck Object = InsertObject; 943c2c66affSColin Finck 944c2c66affSColin Finck /* Get out of here */ 945c2c66affSColin Finck break; 946c2c66affSColin Finck } 947c2c66affSColin Finck 948c2c66affSColin Finck ReparseObject: 949c2c66affSColin Finck /* We found it, so now get its header */ 950c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 951c2c66affSColin Finck 952c2c66affSColin Finck /* 953c2c66affSColin Finck * Check for a parse Procedure, but don't bother to parse for an insert 954c2c66affSColin Finck * unless it's a Symbolic Link, in which case we MUST parse 955c2c66affSColin Finck */ 956c2c66affSColin Finck ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure; 957c2c66affSColin Finck if ((ParseRoutine) && 958c2c66affSColin Finck (!(InsertObject) || (ParseRoutine == ObpParseSymbolicLink))) 959c2c66affSColin Finck { 960c2c66affSColin Finck /* Use the Root Directory next time */ 961c2c66affSColin Finck Directory = NULL; 962c2c66affSColin Finck 963c2c66affSColin Finck /* Increment the pointer count */ 964ff7cc6f3STimo Kreuzer InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1); 965c2c66affSColin Finck 966c2c66affSColin Finck /* Cleanup from the first lookup */ 967c2c66affSColin Finck ObpReleaseLookupContext(LookupContext); 968c2c66affSColin Finck 969c2c66affSColin Finck /* Check if we have a referenced directory */ 970c2c66affSColin Finck if (ReferencedDirectory) 971c2c66affSColin Finck { 972c2c66affSColin Finck /* We do, dereference it */ 973c2c66affSColin Finck ObDereferenceObject(ReferencedDirectory); 974c2c66affSColin Finck ReferencedDirectory = NULL; 975c2c66affSColin Finck } 976c2c66affSColin Finck 977c2c66affSColin Finck /* Check if we have a referenced parent directory */ 978c2c66affSColin Finck if (ReferencedParentDirectory) 979c2c66affSColin Finck { 980c2c66affSColin Finck /* We do, dereference it */ 981c2c66affSColin Finck ObDereferenceObject(ReferencedParentDirectory); 982c2c66affSColin Finck ReferencedParentDirectory = NULL; 983c2c66affSColin Finck } 984c2c66affSColin Finck 985c2c66affSColin Finck /* Call the Parse Procedure */ 986c2c66affSColin Finck ObpCalloutStart(&CalloutIrql); 987c2c66affSColin Finck Status = ParseRoutine(Object, 988c2c66affSColin Finck ObjectType, 989c2c66affSColin Finck AccessState, 990c2c66affSColin Finck AccessCheckMode, 991c2c66affSColin Finck Attributes, 992c2c66affSColin Finck ObjectName, 993c2c66affSColin Finck &RemainingName, 994c2c66affSColin Finck ParseContext, 995c2c66affSColin Finck SecurityQos, 996c2c66affSColin Finck &Object); 997c2c66affSColin Finck ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object); 998c2c66affSColin Finck 999c2c66affSColin Finck /* Remove our extra reference */ 1000c2c66affSColin Finck ObDereferenceObject(&ObjectHeader->Body); 1001c2c66affSColin Finck 1002c2c66affSColin Finck /* Check if we have to reparse */ 1003c2c66affSColin Finck if ((Status == STATUS_REPARSE) || 1004c2c66affSColin Finck (Status == STATUS_REPARSE_OBJECT)) 1005c2c66affSColin Finck { 1006c2c66affSColin Finck /* Reparse again */ 1007c2c66affSColin Finck Reparse = TRUE; 1008c2c66affSColin Finck --MaxReparse; 1009c2c66affSColin Finck if (MaxReparse == 0) 1010c2c66affSColin Finck { 1011c2c66affSColin Finck Object = NULL; 1012c2c66affSColin Finck break; 1013c2c66affSColin Finck } 1014c2c66affSColin Finck 1015c2c66affSColin Finck /* Start over from root if we got sent back there */ 1016c2c66affSColin Finck if ((Status == STATUS_REPARSE_OBJECT) || 1017c2c66affSColin Finck (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) 1018c2c66affSColin Finck { 1019c2c66affSColin Finck /* Check if we got a root directory */ 1020c2c66affSColin Finck if (RootHandle) 1021c2c66affSColin Finck { 1022c2c66affSColin Finck /* Stop using it, because we have a new directory now */ 1023c2c66affSColin Finck ObDereferenceObject(RootDirectory); 1024c2c66affSColin Finck RootHandle = NULL; 1025c2c66affSColin Finck } 1026c2c66affSColin Finck 1027c2c66affSColin Finck /* Start at Root */ 1028c2c66affSColin Finck ParentDirectory = NULL; 1029c2c66affSColin Finck RootDirectory = ObpRootDirectoryObject; 1030c2c66affSColin Finck 1031c2c66affSColin Finck /* Check for reparse status */ 1032c2c66affSColin Finck if (Status == STATUS_REPARSE_OBJECT) 1033c2c66affSColin Finck { 1034c2c66affSColin Finck /* Don't reparse again */ 1035c2c66affSColin Finck Reparse = FALSE; 1036c2c66affSColin Finck 1037c2c66affSColin Finck /* Did we actually get an object to which to reparse? */ 1038c2c66affSColin Finck if (!Object) 1039c2c66affSColin Finck { 1040c2c66affSColin Finck /* We didn't, so set a failure status */ 1041c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND; 1042c2c66affSColin Finck } 1043c2c66affSColin Finck else 1044c2c66affSColin Finck { 1045c2c66affSColin Finck /* We did, so we're free to parse the new object */ 1046c2c66affSColin Finck goto ReparseObject; 1047c2c66affSColin Finck } 1048c2c66affSColin Finck } 1049c2c66affSColin Finck else 1050c2c66affSColin Finck { 1051c2c66affSColin Finck /* This is a symbolic link */ 1052c2c66affSColin Finck SymLink = TRUE; 1053c2c66affSColin Finck goto ParseFromRoot; 1054c2c66affSColin Finck } 1055c2c66affSColin Finck } 1056c2c66affSColin Finck else if (RootDirectory == ObpRootDirectoryObject) 1057c2c66affSColin Finck { 1058c2c66affSColin Finck /* We got STATUS_REPARSE but are at the Root Directory */ 1059c2c66affSColin Finck Object = NULL; 1060c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND; 1061c2c66affSColin Finck Reparse = FALSE; 1062c2c66affSColin Finck } 1063c2c66affSColin Finck } 1064c2c66affSColin Finck else if (!NT_SUCCESS(Status)) 1065c2c66affSColin Finck { 1066c2c66affSColin Finck /* Total failure */ 1067c2c66affSColin Finck Object = NULL; 1068c2c66affSColin Finck } 1069c2c66affSColin Finck else if (!Object) 1070c2c66affSColin Finck { 1071c2c66affSColin Finck /* We didn't reparse but we didn't find the Object Either */ 1072c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND; 1073c2c66affSColin Finck } 1074c2c66affSColin Finck 1075c2c66affSColin Finck /* Break out of the loop */ 1076c2c66affSColin Finck break; 1077c2c66affSColin Finck } 1078c2c66affSColin Finck else 1079c2c66affSColin Finck { 1080c2c66affSColin Finck /* No parse routine...do we still have a remaining name? */ 1081c2c66affSColin Finck if (!RemainingName.Length) 1082c2c66affSColin Finck { 1083c2c66affSColin Finck /* Are we creating an object? */ 1084c2c66affSColin Finck if (!InsertObject) 1085c2c66affSColin Finck { 1086c2c66affSColin Finck /* Check if this is a user-mode call that needs to traverse */ 1087c2c66affSColin Finck if ((AccessCheckMode != KernelMode) && 1088c2c66affSColin Finck !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE)) 1089c2c66affSColin Finck { 1090c2c66affSColin Finck /* Check if we can get it */ 1091c2c66affSColin Finck if (!ObpCheckTraverseAccess(Directory, 1092c2c66affSColin Finck DIRECTORY_TRAVERSE, 1093c2c66affSColin Finck AccessState, 1094c2c66affSColin Finck FALSE, 1095c2c66affSColin Finck AccessCheckMode, 1096c2c66affSColin Finck &Status)) 1097c2c66affSColin Finck { 1098c2c66affSColin Finck /* We don't have access, fail */ 1099c2c66affSColin Finck Object = NULL; 1100c2c66affSColin Finck break; 1101c2c66affSColin Finck } 1102c2c66affSColin Finck } 1103c2c66affSColin Finck 1104c2c66affSColin Finck /* Reference the Object */ 1105c2c66affSColin Finck Status = ObReferenceObjectByPointer(Object, 1106c2c66affSColin Finck 0, 1107c2c66affSColin Finck ObjectType, 1108c2c66affSColin Finck AccessMode); 1109c2c66affSColin Finck if (!NT_SUCCESS(Status)) Object = NULL; 1110c2c66affSColin Finck } 1111c2c66affSColin Finck 1112c2c66affSColin Finck /* And get out of the reparse loop */ 1113c2c66affSColin Finck break; 1114c2c66affSColin Finck } 1115c2c66affSColin Finck else 1116c2c66affSColin Finck { 1117c2c66affSColin Finck /* We still have a name; check if this is a directory object */ 11182c909db2STimo Kreuzer if (ObjectHeader->Type == ObpDirectoryObjectType) 1119c2c66affSColin Finck { 1120c2c66affSColin Finck /* Check if we have a referenced parent directory */ 1121c2c66affSColin Finck if (ReferencedParentDirectory) 1122c2c66affSColin Finck { 1123c2c66affSColin Finck /* Dereference it */ 1124c2c66affSColin Finck ObDereferenceObject(ReferencedParentDirectory); 1125c2c66affSColin Finck } 1126c2c66affSColin Finck 1127c2c66affSColin Finck /* Restart the lookup from this directory */ 1128c2c66affSColin Finck ReferencedParentDirectory = ReferencedDirectory; 1129c2c66affSColin Finck ParentDirectory = Directory; 1130c2c66affSColin Finck Directory = Object; 1131c2c66affSColin Finck ReferencedDirectory = NULL; 1132c2c66affSColin Finck } 1133c2c66affSColin Finck else 1134c2c66affSColin Finck { 1135c2c66affSColin Finck /* We still have a name, but no parse routine for it */ 1136c2c66affSColin Finck Status = STATUS_OBJECT_TYPE_MISMATCH; 1137c2c66affSColin Finck Object = NULL; 1138c2c66affSColin Finck break; 1139c2c66affSColin Finck } 1140c2c66affSColin Finck } 1141c2c66affSColin Finck } 1142c2c66affSColin Finck } 1143c2c66affSColin Finck } 1144c2c66affSColin Finck 1145c2c66affSColin Finck /* Check if we failed */ 1146c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1147c2c66affSColin Finck { 1148c2c66affSColin Finck /* Cleanup after lookup */ 1149c2c66affSColin Finck ObpReleaseLookupContext(LookupContext); 1150c2c66affSColin Finck } 1151c2c66affSColin Finck 1152c2c66affSColin Finck /* Check if we have a device map and dereference it if so */ 1153c2c66affSColin Finck //if (DeviceMap) ObfDereferenceDeviceMap(DeviceMap); 1154c2c66affSColin Finck 1155c2c66affSColin Finck /* Check if we have a referenced directory and dereference it if so */ 1156c2c66affSColin Finck if (ReferencedDirectory) ObDereferenceObject(ReferencedDirectory); 1157c2c66affSColin Finck 1158c2c66affSColin Finck /* Check if we have a referenced parent directory */ 1159c2c66affSColin Finck if (ReferencedParentDirectory) 1160c2c66affSColin Finck { 1161c2c66affSColin Finck /* We do, dereference it */ 1162c2c66affSColin Finck ObDereferenceObject(ReferencedParentDirectory); 1163c2c66affSColin Finck } 1164c2c66affSColin Finck 1165c2c66affSColin Finck /* Set the found object and check if we got one */ 1166c2c66affSColin Finck *FoundObject = Object; 1167c2c66affSColin Finck if (!Object) 1168c2c66affSColin Finck { 1169c2c66affSColin Finck /* Nothing was found. Did we reparse or get success? */ 1170c2c66affSColin Finck if ((Status == STATUS_REPARSE) || (NT_SUCCESS(Status))) 1171c2c66affSColin Finck { 1172c2c66affSColin Finck /* Set correct failure */ 1173c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND; 1174c2c66affSColin Finck } 1175c2c66affSColin Finck } 1176c2c66affSColin Finck 1177c2c66affSColin Finck /* Check if we had a root directory */ 1178c2c66affSColin Finck if (RootHandle) ObDereferenceObject(RootDirectory); 1179c2c66affSColin Finck 1180c2c66affSColin Finck /* Return status to caller */ 1181c2c66affSColin Finck OBTRACE(OB_NAMESPACE_DEBUG, 1182c2c66affSColin Finck "%s - Found Object: %p. Expected: %p\n", 1183c2c66affSColin Finck __FUNCTION__, 1184c2c66affSColin Finck *FoundObject, 1185c2c66affSColin Finck InsertObject); 1186c2c66affSColin Finck return Status; 1187c2c66affSColin Finck } 1188c2c66affSColin Finck 1189c2c66affSColin Finck /* PUBLIC FUNCTIONS *********************************************************/ 1190c2c66affSColin Finck 1191c2c66affSColin Finck NTSTATUS 1192c2c66affSColin Finck NTAPI 1193c2c66affSColin Finck ObQueryNameString(IN PVOID Object, 1194c2c66affSColin Finck OUT POBJECT_NAME_INFORMATION ObjectNameInfo, 1195c2c66affSColin Finck IN ULONG Length, 1196c2c66affSColin Finck OUT PULONG ReturnLength) 1197c2c66affSColin Finck { 1198c2c66affSColin Finck POBJECT_HEADER_NAME_INFO LocalInfo; 1199c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 1200c2c66affSColin Finck POBJECT_DIRECTORY ParentDirectory; 1201c2c66affSColin Finck ULONG NameSize; 1202c2c66affSColin Finck PWCH ObjectName; 1203c2c66affSColin Finck BOOLEAN ObjectIsNamed; 1204c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 1205c2c66affSColin Finck 1206c2c66affSColin Finck /* Get the Kernel Meta-Structures */ 1207c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 1208c2c66affSColin Finck LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 1209c2c66affSColin Finck 1210c2c66affSColin Finck /* Check if a Query Name Procedure is available */ 1211c2c66affSColin Finck if (ObjectHeader->Type->TypeInfo.QueryNameProcedure) 1212c2c66affSColin Finck { 1213c2c66affSColin Finck /* Call the procedure inside SEH */ 1214c2c66affSColin Finck ObjectIsNamed = ((LocalInfo) && (LocalInfo->Name.Length > 0)); 1215c2c66affSColin Finck 1216c2c66affSColin Finck _SEH2_TRY 1217c2c66affSColin Finck { 1218c2c66affSColin Finck Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object, 1219c2c66affSColin Finck ObjectIsNamed, 1220c2c66affSColin Finck ObjectNameInfo, 1221c2c66affSColin Finck Length, 1222c2c66affSColin Finck ReturnLength, 1223c2c66affSColin Finck KernelMode); 1224c2c66affSColin Finck } 1225c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1226c2c66affSColin Finck { 1227c2c66affSColin Finck /* Return the exception code */ 1228c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 1229c2c66affSColin Finck } 1230c2c66affSColin Finck _SEH2_END; 1231c2c66affSColin Finck 1232c2c66affSColin Finck return Status; 1233c2c66affSColin Finck } 1234c2c66affSColin Finck 1235c2c66affSColin Finck /* Check if the object doesn't even have a name */ 1236c2c66affSColin Finck if (!(LocalInfo) || !(LocalInfo->Name.Buffer)) 1237c2c66affSColin Finck { 1238c2c66affSColin Finck Status = STATUS_SUCCESS; 1239c2c66affSColin Finck 1240c2c66affSColin Finck _SEH2_TRY 1241c2c66affSColin Finck { 1242c2c66affSColin Finck /* We're returning the name structure */ 1243c2c66affSColin Finck *ReturnLength = sizeof(OBJECT_NAME_INFORMATION); 1244c2c66affSColin Finck 1245c2c66affSColin Finck /* Check if we were given enough space */ 1246c2c66affSColin Finck if (*ReturnLength > Length) 1247c2c66affSColin Finck { 1248c2c66affSColin Finck Status = STATUS_INFO_LENGTH_MISMATCH; 1249c2c66affSColin Finck } 1250c2c66affSColin Finck else 1251c2c66affSColin Finck { 1252c2c66affSColin Finck /* Return an empty buffer */ 1253c2c66affSColin Finck RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0); 1254c2c66affSColin Finck } 1255c2c66affSColin Finck } 1256c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1257c2c66affSColin Finck { 1258c2c66affSColin Finck /* Return the exception code */ 1259c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 1260c2c66affSColin Finck } 1261c2c66affSColin Finck _SEH2_END; 1262c2c66affSColin Finck 1263c2c66affSColin Finck return Status; 1264c2c66affSColin Finck } 1265c2c66affSColin Finck 1266c2c66affSColin Finck /* 1267c2c66affSColin Finck * Find the size needed for the name. We won't do 1268c2c66affSColin Finck * this during the Name Creation loop because we want 1269c2c66affSColin Finck * to let the caller know that the buffer isn't big 1270c2c66affSColin Finck * enough right at the beginning, not work our way through 1271c2c66affSColin Finck * and find out at the end 1272c2c66affSColin Finck */ 1273c2c66affSColin Finck _SEH2_TRY 1274c2c66affSColin Finck { 1275c2c66affSColin Finck if (Object == ObpRootDirectoryObject) 1276c2c66affSColin Finck { 1277c2c66affSColin Finck /* Size of the '\' string */ 1278c2c66affSColin Finck NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR); 1279c2c66affSColin Finck } 1280c2c66affSColin Finck else 1281c2c66affSColin Finck { 1282c2c66affSColin Finck /* Get the Object Directory and add name of Object */ 1283c2c66affSColin Finck ParentDirectory = LocalInfo->Directory; 1284c2c66affSColin Finck NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length; 1285c2c66affSColin Finck 1286c2c66affSColin Finck /* Loop inside the directory to get the top-most one (meaning root) */ 1287c2c66affSColin Finck while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory)) 1288c2c66affSColin Finck { 1289c2c66affSColin Finck /* Get the Name Information */ 1290c2c66affSColin Finck LocalInfo = OBJECT_HEADER_TO_NAME_INFO( 1291c2c66affSColin Finck OBJECT_TO_OBJECT_HEADER(ParentDirectory)); 1292c2c66affSColin Finck 1293c2c66affSColin Finck /* Add the size of the Directory Name */ 1294c2c66affSColin Finck if (LocalInfo && LocalInfo->Directory) 1295c2c66affSColin Finck { 1296c2c66affSColin Finck /* Size of the '\' string + Directory Name */ 1297c2c66affSColin Finck NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) + 1298c2c66affSColin Finck LocalInfo->Name.Length; 1299c2c66affSColin Finck 1300c2c66affSColin Finck /* Move to next parent Directory */ 1301c2c66affSColin Finck ParentDirectory = LocalInfo->Directory; 1302c2c66affSColin Finck } 1303c2c66affSColin Finck else 1304c2c66affSColin Finck { 1305c2c66affSColin Finck /* Directory with no name. We append "...\" */ 1306c2c66affSColin Finck NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR); 1307c2c66affSColin Finck break; 1308c2c66affSColin Finck } 1309c2c66affSColin Finck } 1310c2c66affSColin Finck } 1311c2c66affSColin Finck 1312c2c66affSColin Finck /* Finally, add the name of the structure and the null char */ 1313c2c66affSColin Finck *ReturnLength = NameSize + 1314c2c66affSColin Finck sizeof(OBJECT_NAME_INFORMATION) + 1315c2c66affSColin Finck sizeof(UNICODE_NULL); 1316c2c66affSColin Finck 1317c2c66affSColin Finck /* Check if we were given enough space */ 1318c2c66affSColin Finck if (*ReturnLength > Length) _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); 1319c2c66affSColin Finck 1320c2c66affSColin Finck /* 1321c2c66affSColin Finck * Now we will actually create the name. We work backwards because 1322c2c66affSColin Finck * it's easier to start off from the Name we have and walk up the 1323c2c66affSColin Finck * parent directories. We use the same logic as Name Length calculation. 1324c2c66affSColin Finck */ 1325c2c66affSColin Finck LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 1326c2c66affSColin Finck ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength); 1327c2c66affSColin Finck *--ObjectName = UNICODE_NULL; 1328c2c66affSColin Finck 1329c2c66affSColin Finck /* Check if the object is actually the Root directory */ 1330c2c66affSColin Finck if (Object == ObpRootDirectoryObject) 1331c2c66affSColin Finck { 1332c2c66affSColin Finck /* This is already the Root Directory, return "\\" */ 1333c2c66affSColin Finck *--ObjectName = OBJ_NAME_PATH_SEPARATOR; 1334c2c66affSColin Finck ObjectNameInfo->Name.Length = (USHORT)NameSize; 1335c2c66affSColin Finck ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + 1336c2c66affSColin Finck sizeof(UNICODE_NULL)); 1337c2c66affSColin Finck ObjectNameInfo->Name.Buffer = ObjectName; 1338c2c66affSColin Finck Status = STATUS_SUCCESS; 1339c2c66affSColin Finck } 1340c2c66affSColin Finck else 1341c2c66affSColin Finck { 1342c2c66affSColin Finck /* Start by adding the Object's Name */ 1343c2c66affSColin Finck ObjectName = (PWCH)((ULONG_PTR)ObjectName - 1344c2c66affSColin Finck LocalInfo->Name.Length); 1345c2c66affSColin Finck RtlCopyMemory(ObjectName, 1346c2c66affSColin Finck LocalInfo->Name.Buffer, 1347c2c66affSColin Finck LocalInfo->Name.Length); 1348c2c66affSColin Finck 1349c2c66affSColin Finck /* Now parse the Parent directories until we reach the top */ 1350c2c66affSColin Finck ParentDirectory = LocalInfo->Directory; 1351c2c66affSColin Finck while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory)) 1352c2c66affSColin Finck { 1353c2c66affSColin Finck /* Get the name information */ 1354c2c66affSColin Finck LocalInfo = OBJECT_HEADER_TO_NAME_INFO( 1355c2c66affSColin Finck OBJECT_TO_OBJECT_HEADER(ParentDirectory)); 1356c2c66affSColin Finck 1357c2c66affSColin Finck /* Add the "\" */ 1358c2c66affSColin Finck *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR; 1359c2c66affSColin Finck 1360c2c66affSColin Finck /* Add the Parent Directory's Name */ 1361c2c66affSColin Finck if (LocalInfo && LocalInfo->Name.Buffer) 1362c2c66affSColin Finck { 1363c2c66affSColin Finck /* Add the name */ 1364c2c66affSColin Finck ObjectName = (PWCH)((ULONG_PTR)ObjectName - 1365c2c66affSColin Finck LocalInfo->Name.Length); 1366c2c66affSColin Finck RtlCopyMemory(ObjectName, 1367c2c66affSColin Finck LocalInfo->Name.Buffer, 1368c2c66affSColin Finck LocalInfo->Name.Length); 1369c2c66affSColin Finck 1370c2c66affSColin Finck /* Move to next parent */ 1371c2c66affSColin Finck ParentDirectory = LocalInfo->Directory; 1372c2c66affSColin Finck } 1373c2c66affSColin Finck else 1374c2c66affSColin Finck { 1375c2c66affSColin Finck /* Directory without a name, we add "..." */ 1376c2c66affSColin Finck ObjectName = (PWCH)((ULONG_PTR)ObjectName - 1377c2c66affSColin Finck sizeof(L"...") + 1378c2c66affSColin Finck sizeof(UNICODE_NULL)); 1379c2c66affSColin Finck RtlCopyMemory(ObjectName, L"...", sizeof(L"...")); 1380c2c66affSColin Finck break; 1381c2c66affSColin Finck } 1382c2c66affSColin Finck } 1383c2c66affSColin Finck 1384c2c66affSColin Finck /* Add Root Directory Name */ 1385c2c66affSColin Finck *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR; 1386c2c66affSColin Finck ObjectNameInfo->Name.Length = (USHORT)NameSize; 1387c2c66affSColin Finck ObjectNameInfo->Name.MaximumLength = 1388c2c66affSColin Finck (USHORT)(NameSize + sizeof(UNICODE_NULL)); 1389c2c66affSColin Finck ObjectNameInfo->Name.Buffer = ObjectName; 1390c2c66affSColin Finck } 1391c2c66affSColin Finck } 1392c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1393c2c66affSColin Finck { 1394c2c66affSColin Finck /* Return the exception code */ 1395c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 1396c2c66affSColin Finck } 1397c2c66affSColin Finck _SEH2_END; 1398c2c66affSColin Finck 1399c2c66affSColin Finck /* Return success */ 1400c2c66affSColin Finck return Status; 1401c2c66affSColin Finck } 1402c2c66affSColin Finck 1403c2c66affSColin Finck /* EOF */ 1404