Sam Arun Raj Seeniraj:
authorAleksey Bragin <aleksey@reactos.org>
Mon, 25 Apr 2011 16:08:00 +0000 (16:08 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Mon, 25 Apr 2011 16:08:00 +0000 (16:08 +0000)
[NTOSKRNL.EXE]
- Complemented existing stub routines ObpDeleteSymbolicLinkName() and ObpCreateSymbolicLinkName(). Now when symbolic links are created, they are checked for dos drive mapping and ObSystemDeviceMap is updated accordingly.
- Updates to ObpDeviceMapLock are protected by a guarded mutex (changed from fast mutex by Aleksey Bragin).
- Aleksey Bragin: Fix concurrent access issues in ObDereferenceDeviceMap. The DeviceMap read/write operation must be atomic (within the ObpDeviceMapLock region).

[SUBST.EXE]
- Removed hard coded strings and moved it to resource file.

[WIN32CSR.DLL]
- Added a workaround, when target path end with a trailing '\', the substituted drive fails to parse to the target, this is a bug in the object manager, but working around it in CsrDefineDosDevice() by stripping trailing '\'.

See issue #993 for more details.

svn path=/trunk/; revision=51452

13 files changed:
reactos/base/system/subst/lang/en-US.rc [new file with mode: 0644]
reactos/base/system/subst/resource.h [new file with mode: 0644]
reactos/base/system/subst/rsrc.rc [new file with mode: 0644]
reactos/base/system/subst/subst.c
reactos/base/system/subst/subst.rbuild
reactos/base/system/subst/subst.rc
reactos/ntoskrnl/fstub/disksup.c
reactos/ntoskrnl/include/internal/ob.h
reactos/ntoskrnl/ob/obinit.c
reactos/ntoskrnl/ob/oblife.c
reactos/ntoskrnl/ob/oblink.c
reactos/ntoskrnl/ob/obname.c
reactos/subsystems/win32/csrss/win32csr/file.c

diff --git a/reactos/base/system/subst/lang/en-US.rc b/reactos/base/system/subst/lang/en-US.rc
new file mode 100644 (file)
index 0000000..790555b
--- /dev/null
@@ -0,0 +1,16 @@
+#include "resource.h"
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE
+BEGIN
+    IDS_INCORRECT_PARAMETER_COUNT "Incorrect number of parameters - %s\n"
+    IDS_INVALID_PARAMETER "Incorrect number of parameters - %s\n"
+    IDS_INVALID_PARAMETER2 "Invalid parameter - %s\n"
+    IDS_DRIVE_ALREAD_SUBSTED "Drive already SUBSTed\n"
+    IDS_FAILED_WITH_ERROCODE "Failed with error code 0x%x: %s\n"
+    IDS_USAGE "Associates a path with a drive letter.\n\nSUBST [drive1: [drive2:]path]\nSUBST drive1: /D\n\n   drive1:        \
+               Specifies a virtual drive to which you want to assign a path.\n   \
+               [drive2:]path  Specifies a physical drive and path you want to assign to\n                  \
+               a virtual drive.\n   /D             \
+               Deletes a substituted (virtual) drive.\n\nType SUBST with no parameters to display a list of current virtual drives.\n"
+END
diff --git a/reactos/base/system/subst/resource.h b/reactos/base/system/subst/resource.h
new file mode 100644 (file)
index 0000000..9baa5b3
--- /dev/null
@@ -0,0 +1,11 @@
+#define RC_STRING_MAX_SIZE          2048
+
+/* Strings */
+#define IDS_FAILED_WITH_ERROCODE        1001
+#define IDS_USAGE                       1002
+#define IDS_INCORRECT_PARAMETER_COUNT   1003
+#define IDS_INVALID_PARAMETER           1004
+#define IDS_INVALID_PARAMETER2          1005
+#define IDS_DRIVE_ALREAD_SUBSTED        1006
+
+/* EOF */
diff --git a/reactos/base/system/subst/rsrc.rc b/reactos/base/system/subst/rsrc.rc
new file mode 100644 (file)
index 0000000..a6f84e4
--- /dev/null
@@ -0,0 +1,6 @@
+#include <windows.h>
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#include "lang/en-US.rc"
index 7cb9256..3bfad0c 100644 (file)
 #include <tchar.h>
 #define NDEBUG
 #include <debug.h>
+#include "resource.h"
 
 /* FUNCTIONS ****************************************************************/
 
 void PrintError(DWORD ErrCode)
 {
+    TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
     TCHAR *buffer = (TCHAR*) calloc(2048,
                                     sizeof(TCHAR));
     TCHAR *msg = NULL;
@@ -32,9 +34,13 @@ void PrintError(DWORD ErrCode)
                       (TCHAR*)&msg,
                       0,
                       NULL);
+        LoadString(GetModuleHandle(NULL),
+                   IDS_FAILED_WITH_ERROCODE,
+                   szFmtString,
+                   sizeof(szFmtString) / sizeof(szFmtString[0]));
         _sntprintf(buffer,
                    2048,
-                   _T("Failed with error code 0x%x: %s\n"),
+                   szFmtString,
                    ErrCode,
                    msg);
         _tprintf(_T("%s"),
@@ -45,16 +51,15 @@ void PrintError(DWORD ErrCode)
     }
 }
 
-void DisplaySubstUsage()
+void DisplaySubstUsage(void)
 {
-    _tprintf(_T("Associates a path with a drive letter.\n\n"));
-    _tprintf(_T("SUBST [drive1: [drive2:]path]\n"));
-    _tprintf(_T("SUBST drive1: /D\n\n"));
-    _tprintf(_T("   drive1:        Specifies a virtual drive to which you want to assign a path.\n"));
-    _tprintf(_T("   [drive2:]path  Specifies a physical drive and path you want to assign to\n"));
-    _tprintf(_T("                  a virtual drive.\n"));
-    _tprintf(_T("   /D             Deletes a substituted (virtual) drive.\n\n"));
-    _tprintf(_T("Type SUBST with no parameters to display a list of current virtual drives.\n"));
+    TCHAR szHelp[RC_STRING_MAX_SIZE] = {0};
+
+    LoadString(GetModuleHandle(NULL),
+                IDS_USAGE,
+                szHelp,
+                sizeof(szHelp) / sizeof(szHelp[0]));
+    _tprintf(_T("%s"), szHelp);
 }
 
 BOOLEAN IsSubstedDrive(TCHAR *Drive)
@@ -103,7 +108,7 @@ BOOLEAN IsSubstedDrive(TCHAR *Drive)
     return Result;
 }
 
-void DumpSubstedDrives()
+void DumpSubstedDrives(void)
 {
     TCHAR Drive[3] = _T("A:");
     LPTSTR lpTargetPath = NULL;
@@ -161,17 +166,23 @@ void DumpSubstedDrives()
 int DeleteSubst(TCHAR* Drive)
 {
     BOOL Result;
+    TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
+
+    LoadString(GetModuleHandle(NULL),
+                IDS_INVALID_PARAMETER2,
+                szFmtString,
+                sizeof(szFmtString) / sizeof(szFmtString[0]));
 
     if (_tcslen(Drive) > 2)
     {
-        _tprintf(_T("Invalid parameter - %s\n"),
+        _tprintf(szFmtString,
                  Drive);
         return 1;
     }
 
     if (! IsSubstedDrive(Drive))
     {
-        _tprintf(_T("Invalid Parameter - %s\n"),
+        _tprintf(szFmtString,
                 Drive);
         return 1;
     }
@@ -190,17 +201,33 @@ int DeleteSubst(TCHAR* Drive)
 int AddSubst(TCHAR* Drive, TCHAR *Path)
 {
     BOOL Result;
+    TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
 
-    if (_tcslen(Drive) > 2)
+    LoadString(GetModuleHandle(NULL),
+                IDS_INVALID_PARAMETER2,
+                szFmtString,
+                sizeof(szFmtString) / sizeof(szFmtString[0]));
+    if (_tcslen(Drive) != 2)
+    {
+        _tprintf(szFmtString,
+                 Drive);
+        return 1;
+    }
+
+    if (Drive[1] != _T(':'))
     {
-        _tprintf(_T("Invalid parameter - %s\n"),
+        _tprintf(szFmtString,
                  Drive);
         return 1;
     }
 
     if (IsSubstedDrive(Drive))
     {
-        _tprintf(_T("Drive already SUBSTed\n"));
+        LoadString(GetModuleHandle(NULL),
+                   IDS_DRIVE_ALREAD_SUBSTED,
+                   szFmtString,
+                   sizeof(szFmtString) / sizeof(szFmtString[0]));
+        _tprintf(szFmtString);
         return 1;
     }
 
@@ -218,6 +245,7 @@ int AddSubst(TCHAR* Drive, TCHAR *Path)
 int _tmain(int argc, TCHAR* argv[])
 {
     INT i;
+    TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
 
     for (i = 0; i < argc; i++)
     {
@@ -232,7 +260,11 @@ int _tmain(int argc, TCHAR* argv[])
     {
         if (argc >= 2)
         {
-            _tprintf(_T("Invalid parameter - %s\n"),
+            LoadString(GetModuleHandle(NULL),
+                       IDS_INVALID_PARAMETER,
+                       szFmtString,
+                       sizeof(szFmtString) / sizeof(szFmtString[0]));
+            _tprintf(szFmtString,
                      argv[1]);
             return 1;
         }
@@ -242,7 +274,11 @@ int _tmain(int argc, TCHAR* argv[])
 
     if (argc > 3)
     {
-        _tprintf(_T("Incorrect number of parameters - %s\n"),
+        LoadString(GetModuleHandle(NULL),
+                   IDS_INCORRECT_PARAMETER_COUNT,
+                   szFmtString,
+                   sizeof(szFmtString) / sizeof(szFmtString[0]));
+        _tprintf(szFmtString,
                  argv[3]);
         return 1;
     }
index fe93acb..8b77abd 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0"?>
 <!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
-<module name="subst" type="win32cui" installbase="system32" installname="subst.exe" >
+<module name="subst" type="win32cui" installbase="system32" installname="subst.exe" unicode="yes">
        <include base="ReactOS">include/reactos/wine</include>
        <include base="subst">.</include>
        <library>kernel32</library>
+       <library>user32</library>
        <file>subst.c</file>
        <file>subst.rc</file>
 </module>
index b81ea2c..db0df66 100644 (file)
@@ -3,3 +3,5 @@
 #define REACTOS_STR_INTERNAL_NAME      "subst\0"
 #define REACTOS_STR_ORIGINAL_FILENAME  "subst.exe\0"
 #include <reactos/version.rc>
+
+#include "rsrc.rc"
index 7c4f651..c4a67c3 100644 (file)
@@ -64,17 +64,20 @@ HalpAssignDrive(IN PUNICODE_STRING PartitionName,
     if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26))
     {
         /* Force assignment */
+        KeAcquireGuardedMutex(&ObpDeviceMapLock);
         if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
         {
             DbgPrint("Drive letter already used!\n");
+            KeReleaseGuardedMutex(&ObpDeviceMapLock);
             return FALSE;
         }
+        KeReleaseGuardedMutex(&ObpDeviceMapLock);
     }
     else
     {
         /* Automatic assignment */
         DriveNumber = AUTO_DRIVE;
-
+        KeAcquireGuardedMutex(&ObpDeviceMapLock);
         for (i = 2; i < 26; i++)
         {
             if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
@@ -83,6 +86,7 @@ HalpAssignDrive(IN PUNICODE_STRING PartitionName,
                 break;
             }
         }
+        KeReleaseGuardedMutex(&ObpDeviceMapLock);
 
         if (DriveNumber == AUTO_DRIVE)
         {
@@ -93,10 +97,6 @@ HalpAssignDrive(IN PUNICODE_STRING PartitionName,
 
     DPRINT("DriveNumber %d\n", DriveNumber);
 
-    /* Update the System Device Map */
-    ObSystemDeviceMap->DriveMap |= (1 << DriveNumber);
-    ObSystemDeviceMap->DriveType[DriveNumber] = DriveType;
-
     /* Build drive name */
     swprintf(DriveNameBuffer,
         L"\\??\\%C:",
index 521bf58..532565e 100644 (file)
@@ -578,6 +578,7 @@ ObGetProcessHandleCount(
 //
 extern ULONG ObpTraceLevel;
 extern KEVENT ObpDefaultObject;
+extern KGUARDED_MUTEX ObpDeviceMapLock;
 extern POBJECT_TYPE ObpTypeObjectType;
 extern POBJECT_TYPE ObSymbolicLinkType;
 extern POBJECT_TYPE ObpTypeObjectType;
index 5a24101..37d6f1b 100644 (file)
@@ -169,6 +169,9 @@ ObInitSystem(VOID)
     /* Initialize the Default Event */
     KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE);
 
+    /* Initialize the Dos Device Map mutex */
+    KeInitializeGuardedMutex(&ObpDeviceMapLock);
+
     /* Setup default access for the system process */
     PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS;
     PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS;
index f87e594..ad4d9f1 100644 (file)
@@ -21,6 +21,7 @@ extern ULONG NtGlobalFlag;
 
 POBJECT_TYPE ObpTypeObjectType = NULL;
 KEVENT ObpDefaultObject;
+KGUARDED_MUTEX ObpDeviceMapLock;
 
 GENERAL_LOOKASIDE ObpNameBufferLookasideList, ObpCreateInfoLookasideList;
 
@@ -107,7 +108,7 @@ ObpDeallocateObject(IN PVOID Object)
                 /* Add the SD charge too */
                 if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
             }
-            
+
             /* Return the quota */
             DPRINT("FIXME: Should return quotas: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge);
 #if 0
@@ -115,7 +116,7 @@ ObpDeallocateObject(IN PVOID Object)
                                     PagedPoolCharge,
                                     NonPagedPoolCharge);
 #endif
-            
+
         }
     }
 
@@ -1261,14 +1262,14 @@ ObpDeleteObjectType(IN PVOID Object)
 {
     ULONG i;
     POBJECT_TYPE ObjectType = (PVOID)Object;
-    
+
     /* Loop our locks */
     for (i = 0; i < 4; i++)
     {
         /* Delete each one */
         ExDeleteResourceLite(&ObjectType->ObjectLocks[i]);
     }
-    
+
     /* Delete our main mutex */
     ExDeleteResourceLite(&ObjectType->Mutex);
 }
index 5b14747..3648aa7 100644 (file)
@@ -23,8 +23,160 @@ VOID
 NTAPI
 ObpDeleteSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
 {
-    /* FIXME: Device maps not supported yet */
+    POBJECT_HEADER ObjectHeader;
+    POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+
+    /* FIXME: Need to support Device maps */
+
+    /* Get header data */
+    ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
+    ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
+
+    /* Check if we are not actually in a directory with a device map */
+    if (!(ObjectNameInfo) ||
+        !(ObjectNameInfo->Directory) /*||
+        !(ObjectNameInfo->Directory->DeviceMap)*/)
+    {
+        ObpDereferenceNameInfo(ObjectNameInfo);
+        return;
+    }
+
+    /* Check if it's a DOS drive letter, and remove the entry from drive map if needed */
+    if (SymbolicLink->DosDeviceDriveIndex != 0 &&
+        ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR) &&
+        ObjectNameInfo->Name.Buffer[1] == L':' &&
+        ( (ObjectNameInfo->Name.Buffer[0] >= L'A' &&
+            ObjectNameInfo->Name.Buffer[0] <= L'Z') ||
+          (ObjectNameInfo->Name.Buffer[0] >= L'a' &&
+            ObjectNameInfo->Name.Buffer[0] <= L'z') ))
+    {
+        /* Remove the drive entry */
+        KeAcquireGuardedMutex(&ObpDeviceMapLock);
+        ObSystemDeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex-1] =
+            DOSDEVICE_DRIVE_UNKNOWN;
+        ObSystemDeviceMap->DriveMap &=
+            ~(1 << (SymbolicLink->DosDeviceDriveIndex-1));
+        KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+        /* Reset the drive index, valid drive index starts from 1 */
+        SymbolicLink->DosDeviceDriveIndex = 0;
+    }
+
+    ObpDereferenceNameInfo(ObjectNameInfo);
+}
+
+NTSTATUS
+NTAPI
+ObpParseSymbolicLinkToIoDeviceObject(IN POBJECT_DIRECTORY SymbolicLinkDirectory,
+                                     IN OUT POBJECT_DIRECTORY *Directory,
+                                     IN OUT PUNICODE_STRING TargetPath,
+                                     IN OUT POBP_LOOKUP_CONTEXT Context,
+                                     OUT PVOID *Object)
+{
+    UNICODE_STRING Name;
+    BOOLEAN ManualUnlock;
+
+    if (! TargetPath || ! Object || ! Context || ! Directory ||
+        ! SymbolicLinkDirectory)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* FIXME: Need to support Device maps */
+
+    /* Try walking the target path and open each part of the path */
+    while (TargetPath->Length)
+    {
+        /* Strip '\' if present at the beginning of the target path */
+        if (TargetPath->Length >= sizeof(OBJ_NAME_PATH_SEPARATOR)&&
+            TargetPath->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
+        {
+            TargetPath->Buffer++;
+            TargetPath->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+        }
+
+        /* Remember the current component of the target path */
+        Name = *TargetPath;
+
+        /* Move forward to the next component of the target path */
+        while (TargetPath->Length >= sizeof(OBJ_NAME_PATH_SEPARATOR))
+        {
+            if (TargetPath->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
+            {
+                TargetPath->Buffer++;
+                TargetPath->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+            }
+            else
+                break;
+        }
+
+        Name.Length -= TargetPath->Length;
+
+        /* Finished processing the entire path, stop */
+        if (! Name.Length)
+            break;
 
+        /*
+         * Make sure a deadlock does not occur as an exclusive lock on a pushlock
+         * would have already taken one in ObpLookupObjectName() on the parent
+         * directory where the symlink is being created [ObInsertObject()].
+         * Prevent recursive locking by faking lock state in the lookup context
+         * when the current directory is same as the parent directory where
+         * the symlink is being created. If the lock state is not faked,
+         * ObpLookupEntryDirectory() will try to get a recursive lock on the
+         * pushlock and hang. For e.g. this happens when a substed drive is pointed to
+         * another substed drive.
+         */
+        if (*Directory == SymbolicLinkDirectory && ! Context->DirectoryLocked)
+        {
+            /* Fake lock state so that ObpLookupEntryDirectory() doesn't attempt a lock */
+            ManualUnlock = TRUE;
+            Context->DirectoryLocked = TRUE;
+        }
+        else
+            ManualUnlock = FALSE;
+
+        *Object = ObpLookupEntryDirectory(*Directory,
+                                          &Name,
+                                          0,
+                                          FALSE,
+                                          Context);
+
+        /* Locking was faked, undo it now */
+        if (*Directory == SymbolicLinkDirectory && ManualUnlock)
+            Context->DirectoryLocked = FALSE;
+
+        /* Lookup failed, stop */
+        if (! *Object)
+            break;
+
+        if (OBJECT_TO_OBJECT_HEADER(*Object)->Type == ObDirectoryType)
+        {
+            /* Make this current directory, and continue search */
+            *Directory = (POBJECT_DIRECTORY)*Object;
+        }
+        else if (OBJECT_TO_OBJECT_HEADER(*Object)->Type == ObSymbolicLinkType &&
+            (((POBJECT_SYMBOLIC_LINK)*Object)->DosDeviceDriveIndex == 0))
+        {
+            /* Symlink points to another initialized symlink, ask caller to reparse */
+            *Directory = ObpRootDirectoryObject;
+            TargetPath = &((POBJECT_SYMBOLIC_LINK)*Object)->LinkTarget;
+            return STATUS_REPARSE_OBJECT;
+        }
+        else
+        {
+            /* Neither directory or symlink, stop */
+            break;
+        }
+    }
+
+    /* Return a valid object, only if object type is IoDeviceObject */
+    if (*Object &&
+        OBJECT_TO_OBJECT_HEADER(*Object)->Type != IoDeviceObjectType)
+    {
+        *Object = NULL;
+    }
+    return STATUS_SUCCESS;
 }
 
 VOID
@@ -33,23 +185,124 @@ ObpCreateSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
 {
     POBJECT_HEADER ObjectHeader;
     POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+    PVOID Object = NULL;
+    POBJECT_DIRECTORY Directory;
+    UNICODE_STRING TargetPath;
+    NTSTATUS Status;
+    ULONG DriveType = DOSDEVICE_DRIVE_CALCULATE;
+    ULONG ReparseCnt;
+    const ULONG MaxReparseAttempts = 20;
+    OBP_LOOKUP_CONTEXT Context;
+
+    /* FIXME: Need to support Device maps */
 
     /* Get header data */
     ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
-    ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+    ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
 
     /* Check if we are not actually in a directory with a device map */
     if (!(ObjectNameInfo) ||
-        !(ObjectNameInfo->Directory) ||
-        !(ObjectNameInfo->Directory->DeviceMap))
+        !(ObjectNameInfo->Directory) /*||
+        !(ObjectNameInfo->Directory->DeviceMap)*/)
     {
-        /* There's nothing to do, return */
+        ObpDereferenceNameInfo(ObjectNameInfo);
         return;
     }
 
-    /* FIXME: We don't support device maps yet */
-    DPRINT1("Unhandled path!\n");
-    ASSERT(FALSE);
+    /* Check if it's a DOS drive letter, and set the drive index accordingly */
+    if (ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR) &&
+        ObjectNameInfo->Name.Buffer[1] == L':' &&
+        ( (ObjectNameInfo->Name.Buffer[0] >= L'A' &&
+            ObjectNameInfo->Name.Buffer[0] <= L'Z') ||
+          (ObjectNameInfo->Name.Buffer[0] >= L'a' &&
+            ObjectNameInfo->Name.Buffer[0] <= L'z') ))
+    {
+        SymbolicLink->DosDeviceDriveIndex =
+            RtlUpcaseUnicodeChar(ObjectNameInfo->Name.Buffer[0]) - L'A';
+        /* The Drive index start from 1 */
+        SymbolicLink->DosDeviceDriveIndex++;
+
+        /* Initialize lookup context */
+        ObpInitializeLookupContext(&Context);
+
+        /* Start the search from the root */
+        Directory = ObpRootDirectoryObject;
+        TargetPath = SymbolicLink->LinkTarget;
+
+        /*
+         * Locate the IoDeviceObject if any this symbolic link points to.
+         * To prevent endless reparsing, setting an upper limit on the 
+         * number of reparses.
+         */
+        Status = STATUS_REPARSE_OBJECT;
+        ReparseCnt = 0;
+        while (Status == STATUS_REPARSE_OBJECT &&
+               ReparseCnt < MaxReparseAttempts)
+        {
+            Status =
+                ObpParseSymbolicLinkToIoDeviceObject(ObjectNameInfo->Directory,
+                                                     &Directory,
+                                                     &TargetPath,
+                                                     &Context,
+                                                     &Object);
+            if (Status == STATUS_REPARSE_OBJECT)
+                ReparseCnt++;
+        }
+
+        /* Cleanup lookup context */
+        ObpReleaseLookupContext(&Context);
+
+        /* Error, or max resparse attemtps exceeded */
+        if (! NT_SUCCESS(Status) || ReparseCnt >= MaxReparseAttempts)
+        {
+            /* Cleanup */
+            ObpDereferenceNameInfo(ObjectNameInfo);
+            return;
+        }
+
+        if (Object)
+        {
+            /* Calculate the drive type */
+            switch(((PDEVICE_OBJECT)Object)->DeviceType)
+            {
+            case FILE_DEVICE_VIRTUAL_DISK:
+                DriveType = DOSDEVICE_DRIVE_RAMDISK;
+                break;
+            case FILE_DEVICE_CD_ROM:
+            case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
+                DriveType = DOSDEVICE_DRIVE_CDROM;
+                break;
+            case FILE_DEVICE_DISK:
+            case FILE_DEVICE_DISK_FILE_SYSTEM:
+            case FILE_DEVICE_FILE_SYSTEM:
+                if (((PDEVICE_OBJECT)Object)->Characteristics & FILE_REMOVABLE_MEDIA)
+                    DriveType = DOSDEVICE_DRIVE_REMOVABLE;
+                else
+                    DriveType = DOSDEVICE_DRIVE_FIXED;
+                break;
+            case FILE_DEVICE_NETWORK:
+            case FILE_DEVICE_NETWORK_FILE_SYSTEM:
+                DriveType = DOSDEVICE_DRIVE_REMOTE;
+                break;
+            default:
+                DPRINT1("Device Type %ld for %wZ is not known or unhandled\n",
+                        ((PDEVICE_OBJECT)Object)->DeviceType,
+                        &SymbolicLink->LinkTarget);
+                DriveType = DOSDEVICE_DRIVE_UNKNOWN;
+            }
+        }
+
+        /* Add a new drive entry */
+        KeAcquireGuardedMutex(&ObpDeviceMapLock);
+        ObSystemDeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex-1] =
+            (UCHAR)DriveType;
+        ObSystemDeviceMap->DriveMap |=
+            1 << (SymbolicLink->DosDeviceDriveIndex-1);
+        KeReleaseGuardedMutex(&ObpDeviceMapLock);
+    }
+
+    /* Cleanup */
+    ObpDereferenceNameInfo(ObjectNameInfo);
 }
 
 /*++
index a514af7..e4f7e18 100644 (file)
@@ -113,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);
@@ -138,8 +142,8 @@ ObDereferenceDeviceMap(IN PEPROCESS Process)
         }
         else
         {
-            /* FIXME: Release the DeviceMap Spinlock */
-            // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+            /* Release the devicemap lock */
+            KeReleaseGuardedMutex(&ObpDeviceMapLock);
         }
     }
 }
@@ -1144,15 +1148,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;
@@ -1160,8 +1161,7 @@ ObQueryDeviceMapInformation(IN PEPROCESS Process,
                   ObSystemDeviceMap->DriveType,
                   sizeof(ObSystemDeviceMap->DriveType));
 
-    /* FIXME: Release the DeviceMap Spinlock */
-    // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+    KeReleaseGuardedMutex(&ObpDeviceMapLock);
 }
 
 /* EOF */
index 862a014..982e8fe 100644 (file)
@@ -59,7 +59,7 @@ CSR_API(CsrDefineDosDevice)
     DWORD dwFlags;
     PWSTR lpBuffer;
 
-    DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n", 
+    DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
            Request->Data.DefineDosDeviceRequest.dwFlags,
            &Request->Data.DefineDosDeviceRequest.DeviceName,
            &Request->Data.DefineDosDeviceRequest.TargetName);
@@ -98,6 +98,17 @@ CSR_API(CsrDefineDosDevice)
 
         RequestLinkTarget =
             &Request->Data.DefineDosDeviceRequest.TargetName;
+        /*
+         * Strip off any trailing '\', if we leave a trailing slash the drive remains non-accessible.
+         * So working around it for now.
+         * FIXME: Need to fix this in the object manager ObpLookupObjectName()??, and remove this when the its fixed.
+         */
+        while (RequestLinkTarget->Length >= sizeof(WCHAR) &&
+               RequestLinkTarget->Buffer[(RequestLinkTarget->Length/sizeof(WCHAR)) - 1] == L'\\')
+        {
+            RequestLinkTarget->Length -= sizeof(WCHAR);
+        }
+
         lpBuffer = (PWSTR) RtlAllocateHeap(Win32CsrApiHeap,
                                            HEAP_ZERO_MEMORY,
                                            RequestDeviceName.MaximumLength + 5 * sizeof(WCHAR));
@@ -146,7 +157,7 @@ CSR_API(CsrDefineDosDevice)
                                                    &LinkTarget,
                                                    &Length);
             }
-            
+
             if (! NT_SUCCESS(Status))
             {
                 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
@@ -188,7 +199,7 @@ CSR_API(CsrDefineDosDevice)
                             CONTAINING_RECORD(Entry,
                                               CSRSS_DOS_DEVICE_HISTORY_ENTRY,
                                               Entry);
-                        Matched = 
+                        Matched =
                             ! RtlCompareUnicodeString(&RequestDeviceName,
                                                       &HistoryEntry->Device,
                                                       FALSE);
@@ -459,7 +470,7 @@ CSR_API(CsrDefineDosDevice)
                  &DeviceName, Status);
         }
     }
-    _SEH2_FINALLY 
+    _SEH2_FINALLY
     {
         (void) RtlLeaveCriticalSection(&Win32CsrDefineDosDeviceCritSec);
         if (DeviceName.Buffer)
@@ -504,13 +515,13 @@ CSR_API(CsrDefineDosDevice)
     return Status;
 }
 
-void CsrCleanupDefineDosDevice()
+void CsrCleanupDefineDosDevice(void)
 {
     PLIST_ENTRY Entry, ListHead;
     PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
 
     (void) RtlDeleteCriticalSection(&Win32CsrDefineDosDeviceCritSec);
-    
+
     ListHead = &DosDeviceHistory;
     Entry = ListHead->Flink;
     while (Entry != ListHead)