Synchronize with trunk.
[reactos.git] / ntoskrnl / ob / obname.c
index c97d4ce..38e0574 100644 (file)
@@ -33,6 +33,7 @@ UNICODE_STRING ObpDosDevicesShortName =
 
 NTSTATUS
 NTAPI
+INIT_FUNCTION
 ObpCreateDosDevicesDirectory(VOID)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -112,24 +113,28 @@ VOID
 NTAPI
 ObDereferenceDeviceMap(IN PEPROCESS Process)
 {
-    //KIRQL OldIrql;
-    PDEVICE_MAP DeviceMap = Process->DeviceMap;
+    PDEVICE_MAP DeviceMap;
 
-    /* FIXME: We don't use Process Devicemaps yet */
+    /* Get the pointer to this process devicemap and reset it
+       holding devicemap lock */
+    KeAcquireGuardedMutex(&ObpDeviceMapLock);
+    DeviceMap = Process->DeviceMap;
+    Process->DeviceMap = NULL;
+    KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+    /* Continue only if there is a devicemap to dereference */
     if (DeviceMap)
     {
-        /* FIXME: Acquire the DeviceMap Spinlock */
-        // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
+        KeAcquireGuardedMutex(&ObpDeviceMapLock);
 
         /* Delete the device map link and dereference it */
-        Process->DeviceMap = NULL;
         if (--DeviceMap->ReferenceCount)
         {
             /* Nobody is referencing it anymore, unlink the DOS directory */
             DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
 
-            /* FIXME: Release the DeviceMap Spinlock */
-            // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+            /* Release the devicemap lock */
+            KeReleaseGuardedMutex(&ObpDeviceMapLock);
 
             /* Dereference the DOS Devices Directory and free the Device Map */
             ObDereferenceObject(DeviceMap->DosDevicesDirectory);
@@ -137,8 +142,8 @@ ObDereferenceDeviceMap(IN PEPROCESS Process)
         }
         else
         {
-            /* FIXME: Release the DeviceMap Spinlock */
-            // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+            /* Release the devicemap lock */
+            KeReleaseGuardedMutex(&ObpDeviceMapLock);
         }
     }
 }
@@ -432,7 +437,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,
@@ -539,7 +544,7 @@ ParseFromRoot:
     }
 
     /* Reparse */
-    while (Reparse)
+    while (Reparse && MaxReparse)
     {
         /* Get the name */
         RemainingName = *ObjectName;
@@ -689,7 +694,7 @@ ParseFromRoot:
                                               ObjectHeader)))
                 {
                     /* Either couldn't allocate the name, or insert failed */
-                    if (NewName) ExFreePool(NewName);
+                    if (NewName) ExFreePoolWithTag(NewName, OB_NAME_TAG);
 
                     /* Fail due to memory reasons */
                     Status = STATUS_INSUFFICIENT_RESOURCES;
@@ -714,7 +719,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 */
@@ -790,6 +795,12 @@ 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) ||
@@ -980,6 +991,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);
@@ -988,28 +1000,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);
+
+            /* 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 an empty buffer */
-        RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
-        return STATUS_SUCCESS;
+        return Status;
     }
 
     /*
@@ -1019,123 +1060,136 @@ ObQueryNameString(IN PVOID Object,
      * enough right at the beginning, not work our way through
      * and find out at the end
      */
-    if (Object == ObpRootDirectoryObject)
+    _SEH2_TRY
     {
-        /* 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;
-
-        /* 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)
         {
-            /* Get the name information */
-            LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
-                            OBJECT_TO_OBJECT_HEADER(ParentDirectory));
+            /* 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
+        {
+            /* 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"...") + sizeof(UNICODE_NULL));
+                    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
@@ -1143,15 +1197,12 @@ NTAPI
 ObQueryDeviceMapInformation(IN PEPROCESS Process,
                             IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
 {
-    //KIRQL OldIrql ;
-
     /*
     * FIXME: This is an ugly hack for now, to always return the System Device Map
     * instead of returning the Process Device Map. Not important yet since we don't use it
     */
 
-    /* FIXME: Acquire the DeviceMap Spinlock */
-    // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
+    KeAcquireGuardedMutex(&ObpDeviceMapLock);
 
     /* Make a copy */
     DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
@@ -1159,8 +1210,33 @@ ObQueryDeviceMapInformation(IN PEPROCESS Process,
                   ObSystemDeviceMap->DriveType,
                   sizeof(ObSystemDeviceMap->DriveType));
 
-    /* FIXME: Release the DeviceMap Spinlock */
-    // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+    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 */