Alexandre Julliard : kernel32: Fetch more information from the DosDevices directory for QueryDosDevice.

Alexandre Julliard julliard at winehq.org
Fri Jul 24 08:49:14 CDT 2009


Module: wine
Branch: master
Commit: f18276fe0bc0bedf5c58c51f53f9491265f500dc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f18276fe0bc0bedf5c58c51f53f9491265f500dc

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Jul 24 11:01:41 2009 +0200

kernel32: Fetch more information from the DosDevices directory for QueryDosDevice.

---

 dlls/kernel32/volume.c |   66 ++++++++++++++++++++++++++++-------------------
 1 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 0f4161c..9fcd061 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -1018,11 +1018,10 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
     static const WCHAR prnW[] = {'P','R','N',0};
     static const WCHAR comW[] = {'C','O','M',0};
     static const WCHAR lptW[] = {'L','P','T',0};
-    static const WCHAR rootW[] = {'A',':','\\',0};
     static const WCHAR com0W[] = {'\\','?','?','\\','C','O','M','0',0};
     static const WCHAR com1W[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','C','O','M','1',0,0};
     static const WCHAR lpt1W[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','L','P','T','1',0,0};
-    static const WCHAR driveW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','A',':',0};
+    static const WCHAR dosdevW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
 
     UNICODE_STRING nt_name;
     ANSI_STRING unix_name;
@@ -1046,15 +1045,21 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
             memcpy( name, devname + HIWORD(dosdev)/sizeof(WCHAR), LOWORD(dosdev) );
             name[LOWORD(dosdev)/sizeof(WCHAR)] = 0;
         }
-        else if (devname[0] && devname[1] == ':' && !devname[2])
+        else
         {
-            /* FIXME: should do this for all devices, not just drives */
             NTSTATUS status;
-            WCHAR buffer[sizeof(driveW)/sizeof(WCHAR)];
+            WCHAR *buffer;
 
-            memcpy( buffer, driveW, sizeof(driveW) );
-            buffer[12] = devname[0];
-            if ((status = read_nt_symlink( buffer, target, bufsize )))
+            if (!(buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(dosdevW) + strlenW(devname)*sizeof(WCHAR) )))
+            {
+                SetLastError( ERROR_OUTOFMEMORY );
+                return 0;
+            }
+            memcpy( buffer, dosdevW, sizeof(dosdevW) );
+            strcatW( buffer, devname );
+            status = read_nt_symlink( buffer, target, bufsize );
+            HeapFree( GetProcessHeap(), 0, buffer );
+            if (status)
             {
                 SetLastError( RtlNtStatusToDosError(status) );
                 return 0;
@@ -1062,11 +1067,8 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
             ret = strlenW( target ) + 1;
             goto done;
         }
-        else
-        {
-            SetLastError( ERROR_BAD_PATHNAME );
-            return 0;
-        }
+
+        /* FIXME: should read NT symlink for all devices */
 
         if (!(path = get_dos_device_path( name ))) return 0;
         link = read_symlink( path );
@@ -1125,6 +1127,8 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
     }
     else  /* return a list of all devices */
     {
+        OBJECT_ATTRIBUTES attr;
+        HANDLE handle;
         WCHAR *p = target;
         int i;
 
@@ -1134,6 +1138,8 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
             return 0;
         }
 
+        /* FIXME: these should be NT symlinks too */
+
         memcpy( p, auxW, sizeof(auxW) );
         p += sizeof(auxW) / sizeof(WCHAR);
         memcpy( p, nulW, sizeof(nulW) );
@@ -1180,30 +1186,36 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
             }
         }
 
-        strcpyW( nt_buffer + 4, rootW );
-        RtlInitUnicodeString( &nt_name, nt_buffer );
-
-        /* FIXME: should simply enumerate the DosDevices directory instead */
-        for (i = 0; i < 26; i++)
+        RtlInitUnicodeString( &nt_name, dosdevW );
+        nt_name.Length -= sizeof(WCHAR);  /* without trailing slash */
+        attr.Length = sizeof(attr);
+        attr.RootDirectory = 0;
+        attr.ObjectName = &nt_name;
+        attr.Attributes = OBJ_CASE_INSENSITIVE;
+        attr.SecurityDescriptor = NULL;
+        attr.SecurityQualityOfService = NULL;
+        status = NtOpenDirectoryObject( &handle, FILE_LIST_DIRECTORY, &attr );
+        if (!status)
         {
-            WCHAR buffer[sizeof(driveW)/sizeof(WCHAR)], dummy[8];
-            NTSTATUS status;
+            char data[1024];
+            DIRECTORY_BASIC_INFORMATION *info = (DIRECTORY_BASIC_INFORMATION *)data;
+            ULONG ctx = 0, len;
 
-            memcpy( buffer, driveW, sizeof(driveW) );
-            buffer[12] = 'A' + i;
-            status = read_nt_symlink( buffer, dummy, sizeof(dummy)/sizeof(WCHAR) );
-            if (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL)
+            while (!NtQueryDirectoryObject( handle, info, sizeof(data), 1, 0, &ctx, &len ))
             {
-                if (p + 3 >= target + bufsize)
+                if (p + info->ObjectName.Length/sizeof(WCHAR) + 1 >= target + bufsize)
                 {
                     SetLastError( ERROR_INSUFFICIENT_BUFFER );
+                    NtClose( handle );
                     return 0;
                 }
-                *p++ = 'A' + i;
-                *p++ = ':';
+                memcpy( p, info->ObjectName.Buffer, info->ObjectName.Length );
+                p += info->ObjectName.Length/sizeof(WCHAR);
                 *p++ = 0;
             }
+            NtClose( handle );
         }
+
         *p++ = 0;  /* terminating null */
         return p - target;
     }




More information about the wine-cvs mailing list