[SHELL32]
[reactos.git] / ntoskrnl / ob / obname.c
index 6d0efd3..7f6274d 100644 (file)
@@ -37,25 +37,48 @@ INIT_FUNCTION
 ObpCreateDosDevicesDirectory(VOID)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING Name, LinkName;
+    UNICODE_STRING RootName, TargetName, LinkName;
     HANDLE Handle, SymHandle;
     NTSTATUS Status;
 
-    /* Create the '\??' directory */
-    RtlInitUnicodeString(&Name, L"\\??");
+    /* Create the global DosDevices directory \?? */
+    RtlInitUnicodeString(&RootName, L"\\GLOBAL??");
     InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
+                               &RootName,
                                OBJ_PERMANENT,
                                NULL,
                                NULL);
     Status = NtCreateDirectoryObject(&Handle,
                                      DIRECTORY_ALL_ACCESS,
                                      &ObjectAttributes);
-    if (!NT_SUCCESS(Status)) return FALSE;
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /*********************************************\
+    |*** HACK until we support device mappings ***|
+    |*** Add a symlink \??\ <--> \GLOBAL??\    ***|
+    \*********************************************/
+    RtlInitUnicodeString(&LinkName, L"\\??");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_PERMANENT,
+                               NULL,
+                               NULL);
+    Status = NtCreateSymbolicLinkObject(&SymHandle,
+                                        SYMBOLIC_LINK_ALL_ACCESS,
+                                        &ObjectAttributes,
+                                        &RootName);
+    if (NT_SUCCESS(Status)) NtClose(SymHandle);
+    /*********************************************\
+    \*********************************************/
 
-    /* Initialize the GLOBALROOT path */
+    // FIXME: Create a device mapping for the global \?? directory
+
+    /*
+     * Initialize the \??\GLOBALROOT symbolic link
+     * pointing to the root directory \ .
+     */
     RtlInitUnicodeString(&LinkName, L"GLOBALROOT");
-    RtlInitUnicodeString(&Name, L"");
+    RtlInitUnicodeString(&TargetName, L"");
     InitializeObjectAttributes(&ObjectAttributes,
                                &LinkName,
                                OBJ_PERMANENT,
@@ -64,12 +87,16 @@ ObpCreateDosDevicesDirectory(VOID)
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
-                                        &Name);
+                                        &TargetName);
     if (NT_SUCCESS(Status)) NtClose(SymHandle);
 
-    /* Link \??\Global to \?? */
+    /*
+     * Initialize the \??\Global symbolic link pointing to the global
+     * DosDevices directory \?? . It is used to access the global \??
+     * by user-mode components which, by default, use a per-session
+     * DosDevices directory.
+     */
     RtlInitUnicodeString(&LinkName, L"Global");
-    RtlInitUnicodeString(&Name, L"\\??");
     InitializeObjectAttributes(&ObjectAttributes,
                                &LinkName,
                                OBJ_PERMANENT,
@@ -78,15 +105,20 @@ ObpCreateDosDevicesDirectory(VOID)
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
-                                        &Name);
+                                        &RootName);
     if (NT_SUCCESS(Status)) NtClose(SymHandle);
 
     /* Close the directory handle */
     NtClose(Handle);
     if (!NT_SUCCESS(Status)) return Status;
 
-    /* Create link from '\DosDevices' to '\??' directory */
+    /*
+     * Initialize the \DosDevices symbolic link pointing to the global
+     * DosDevices directory \?? , for backward compatibility with
+     * Windows NT-2000 systems.
+     */
     RtlCreateUnicodeString(&LinkName, L"\\DosDevices");
+    RtlInitUnicodeString(&RootName, (PCWSTR)&ObpDosDevicesShortNameRoot);
     InitializeObjectAttributes(&ObjectAttributes,
                                &LinkName,
                                OBJ_PERMANENT,
@@ -95,7 +127,7 @@ ObpCreateDosDevicesDirectory(VOID)
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
-                                        &Name);
+                                        &RootName);
     if (NT_SUCCESS(Status)) NtClose(SymHandle);
 
     /* FIXME: Hack Hack! */
@@ -437,7 +469,7 @@ ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
         }
         else if (!(ObjectName->Length) || !(ObjectName->Buffer))
         {
-            /* Just return the Root Directory if we didn't get a name*/
+            /* Just return the Root Directory if we didn't get a name */
             Status = ObReferenceObjectByPointer(RootDirectory,
                                                 0,
                                                 ObjectType,
@@ -719,7 +751,7 @@ ParseFromRoot:
                 if (ObjectNameInfo->Name.Buffer)
                 {
                     /* Free it */
-                    ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG );
+                    ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG);
                 }
 
                 /* Write new one */
@@ -796,6 +828,11 @@ ReparseObject:
                     /* Reparse again */
                     Reparse = TRUE;
                     --MaxReparse;
+                    if (MaxReparse == 0)
+                    {
+                        Object = NULL;
+                        break;
+                    }
 
                     /* Start over from root if we got sent back there */
                     if ((Status == STATUS_REPARSE_OBJECT) ||
@@ -986,6 +1023,7 @@ ObQueryNameString(IN PVOID Object,
     ULONG NameSize;
     PWCH ObjectName;
     BOOLEAN ObjectIsNamed;
+    NTSTATUS Status = STATUS_SUCCESS;
 
     /* Get the Kernel Meta-Structures */
     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
@@ -994,28 +1032,57 @@ ObQueryNameString(IN PVOID Object,
     /* Check if a Query Name Procedure is available */
     if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
     {
-        /* Call the procedure */
+        /* Call the procedure inside SEH */
         ObjectIsNamed = ((LocalInfo) && (LocalInfo->Name.Length > 0));
-        return ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
+
+        _SEH2_TRY
+        {
+            Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
                                                                ObjectIsNamed,
                                                                ObjectNameInfo,
                                                                Length,
                                                                ReturnLength,
                                                                KernelMode);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Return the exception code */
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        return Status;
     }
 
     /* Check if the object doesn't even have a name */
     if (!(LocalInfo) || !(LocalInfo->Name.Buffer))
     {
-        /* We're returning the name structure */
-        *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
+        Status = STATUS_SUCCESS;
 
-        /* Check if we were given enough space */
-        if (*ReturnLength > Length) return STATUS_INFO_LENGTH_MISMATCH;
+        _SEH2_TRY
+        {
+            /* We're returning the name structure */
+            *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
 
-        /* Return an empty buffer */
-        RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
-        return STATUS_SUCCESS;
+            /* Check if we were given enough space */
+            if (*ReturnLength > Length)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+            }
+            else
+            {
+                /* Return an empty buffer */
+                RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
+            }
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Return the exception code */
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        return Status;
     }
 
     /*
@@ -1025,123 +1092,134 @@ ObQueryNameString(IN PVOID Object,
      * enough right at the beginning, not work our way through
      * and find out at the end
      */
-    if (Object == ObpRootDirectoryObject)
-    {
-        /* Size of the '\' string */
-        NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
-    }
-    else
+    _SEH2_TRY
     {
-        /* Get the Object Directory and add name of Object */
-        ParentDirectory = LocalInfo->Directory;
-        NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
-
-        /* Loop inside the directory to get the top-most one (meaning root) */
-        while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
+        if (Object == ObpRootDirectoryObject)
         {
-            /* Get the Name Information */
-            LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
-                            OBJECT_TO_OBJECT_HEADER(ParentDirectory));
+            /* Size of the '\' string */
+            NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
+        }
+        else
+        {
+            /* Get the Object Directory and add name of Object */
+            ParentDirectory = LocalInfo->Directory;
+            NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
 
-            /* Add the size of the Directory Name */
-            if (LocalInfo && LocalInfo->Directory)
+            /* Loop inside the directory to get the top-most one (meaning root) */
+            while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
             {
-                /* Size of the '\' string + Directory Name */
-                NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
-                            LocalInfo->Name.Length;
+                /* Get the Name Information */
+                LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
+                    OBJECT_TO_OBJECT_HEADER(ParentDirectory));
 
-                /* Move to next parent Directory */
-                ParentDirectory = LocalInfo->Directory;
-            }
-            else
-            {
-                /* Directory with no name. We append "...\" */
-                NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
-                break;
+                /* Add the size of the Directory Name */
+                if (LocalInfo && LocalInfo->Directory)
+                {
+                    /* Size of the '\' string + Directory Name */
+                    NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
+                                LocalInfo->Name.Length;
+
+                    /* Move to next parent Directory */
+                    ParentDirectory = LocalInfo->Directory;
+                }
+                else
+                {
+                    /* Directory with no name. We append "...\" */
+                    NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
+                    break;
+                }
             }
         }
-    }
-
-    /* Finally, add the name of the structure and the null char */
-    *ReturnLength = NameSize +
-                    sizeof(OBJECT_NAME_INFORMATION) +
-                    sizeof(UNICODE_NULL);
-
-    /* Check if we were given enough space */
-    if (*ReturnLength > Length) return STATUS_INFO_LENGTH_MISMATCH;
 
-    /*
-     * Now we will actually create the name. We work backwards because
-     * it's easier to start off from the Name we have and walk up the
-     * parent directories. We use the same logic as Name Length calculation.
-     */
-    LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
-    ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
-    *--ObjectName = UNICODE_NULL;
+        /* Finally, add the name of the structure and the null char */
+        *ReturnLength = NameSize +
+                        sizeof(OBJECT_NAME_INFORMATION) +
+                        sizeof(UNICODE_NULL);
 
-    /* Check if the object is actually the Root directory */
-    if (Object == ObpRootDirectoryObject)
-    {
-        /* This is already the Root Directory, return "\\" */
-        *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
-        ObjectNameInfo->Name.Length = (USHORT)NameSize;
-        ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
-                                                      sizeof(UNICODE_NULL));
-        ObjectNameInfo->Name.Buffer = ObjectName;
-        return STATUS_SUCCESS;
-    }
-    else
-    {
-        /* Start by adding the Object's Name */
-        ObjectName = (PWCH)((ULONG_PTR)ObjectName -
-                            LocalInfo->Name.Length);
-        RtlCopyMemory(ObjectName,
-                      LocalInfo->Name.Buffer,
-                      LocalInfo->Name.Length);
-
-        /* Now parse the Parent directories until we reach the top */
-        ParentDirectory = LocalInfo->Directory;
-        while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
+        /* Check if we were given enough space */
+        if (*ReturnLength > Length) _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH);
+
+        /*
+        * Now we will actually create the name. We work backwards because
+        * it's easier to start off from the Name we have and walk up the
+        * parent directories. We use the same logic as Name Length calculation.
+        */
+        LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+        ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
+        *--ObjectName = UNICODE_NULL;
+
+        /* Check if the object is actually the Root directory */
+        if (Object == ObpRootDirectoryObject)
+        {
+            /* This is already the Root Directory, return "\\" */
+            *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
+            ObjectNameInfo->Name.Length = (USHORT)NameSize;
+            ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
+                                                          sizeof(UNICODE_NULL));
+            ObjectNameInfo->Name.Buffer = ObjectName;
+            Status = STATUS_SUCCESS;
+        }
+        else
         {
-            /* Get the name information */
-            LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
-                            OBJECT_TO_OBJECT_HEADER(ParentDirectory));
+            /* Start by adding the Object's Name */
+            ObjectName = (PWCH)((ULONG_PTR)ObjectName -
+                                           LocalInfo->Name.Length);
+            RtlCopyMemory(ObjectName,
+                          LocalInfo->Name.Buffer,
+                          LocalInfo->Name.Length);
+
+            /* Now parse the Parent directories until we reach the top */
+            ParentDirectory = LocalInfo->Directory;
+            while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
+            {
+                /* Get the name information */
+                LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
+                    OBJECT_TO_OBJECT_HEADER(ParentDirectory));
 
-            /* Add the "\" */
-            *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
+                /* Add the "\" */
+                *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
 
-            /* Add the Parent Directory's Name */
-            if (LocalInfo && LocalInfo->Name.Buffer)
-            {
-                /* Add the name */
-                ObjectName = (PWCH)((ULONG_PTR)ObjectName -
-                                    LocalInfo->Name.Length);
-                RtlCopyMemory(ObjectName,
-                              LocalInfo->Name.Buffer,
-                              LocalInfo->Name.Length);
-
-                /* Move to next parent */
-                ParentDirectory = LocalInfo->Directory;
-            }
-            else
-            {
-                /* Directory without a name, we add "..." */
-                ObjectName -= sizeof(L"...");
-                ObjectName = L"...";
-                break;
+                /* Add the Parent Directory's Name */
+                if (LocalInfo && LocalInfo->Name.Buffer)
+                {
+                    /* Add the name */
+                    ObjectName = (PWCH)((ULONG_PTR)ObjectName -
+                                                   LocalInfo->Name.Length);
+                    RtlCopyMemory(ObjectName,
+                                  LocalInfo->Name.Buffer,
+                                  LocalInfo->Name.Length);
+
+                    /* Move to next parent */
+                    ParentDirectory = LocalInfo->Directory;
+                }
+                else
+                {
+                    /* Directory without a name, we add "..." */
+                    ObjectName = (PWCH)((ULONG_PTR)ObjectName -
+                                                   sizeof(L"...") +
+                                                   sizeof(UNICODE_NULL));
+                    RtlCopyMemory(ObjectName, L"...", sizeof(L"..."));
+                    break;
+                }
             }
-        }
 
-        /* Add Root Directory Name */
-        *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
-        ObjectNameInfo->Name.Length = (USHORT)NameSize;
-        ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
-                                                      sizeof(UNICODE_NULL));
-        ObjectNameInfo->Name.Buffer = ObjectName;
+            /* Add Root Directory Name */
+            *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
+            ObjectNameInfo->Name.Length = (USHORT)NameSize;
+            ObjectNameInfo->Name.MaximumLength =
+                (USHORT)(NameSize + sizeof(UNICODE_NULL));
+            ObjectNameInfo->Name.Buffer = ObjectName;
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Return the exception code */
+        Status = _SEH2_GetExceptionCode();
     }
+    _SEH2_END;
 
     /* Return success */
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 VOID
@@ -1165,4 +1243,30 @@ ObQueryDeviceMapInformation(IN PEPROCESS Process,
     KeReleaseGuardedMutex(&ObpDeviceMapLock);
 }
 
+NTSTATUS
+NTAPI
+ObIsDosDeviceLocallyMapped(
+    IN ULONG Index,
+    OUT PUCHAR DosDeviceState)
+{
+    /* check parameters */
+    if (Index < 1 || Index > 26)
+    {
+        /* invalid index */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* acquire lock */
+    KeAcquireGuardedMutex(&ObpDeviceMapLock);
+
+    /* get drive mapping status */
+    *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
+
+    /* release lock */
+    KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+    /* done */
+    return STATUS_SUCCESS;
+}
+
 /* EOF */