Uniform SYS/VXD Handling 1/6: Load also system files

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Sun Jul 10 09:18:59 CDT 2005


       Changelog:
       wine/dlls/kernel/file.c, dlls/kernel/vxd.c,
       dlls/kernel/kernel_private.h
       Load .sys drivers too, also for raw disk/cdroms
       Call DeviceIoProc with Device Handle
       
-- 
Uwe Bonnes                bon at elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
Index: wine/dlls/kernel/file.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/file.c,v
retrieving revision 1.39
diff -u -r1.39 file.c
--- wine/dlls/kernel/file.c	20 Jun 2005 10:40:37 -0000	1.39
+++ wine/dlls/kernel/file.c	10 Jul 2005 12:52:45 -0000
@@ -1184,6 +1184,7 @@
     IO_STATUS_BLOCK io;
     HANDLE ret;
     DWORD dosdev;
+    WCHAR driver[16] = {0};
     static const WCHAR bkslashes_with_dotW[] = {'\\','\\','.','\\',0};
     static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
@@ -1228,9 +1229,21 @@
         static const WCHAR pipeW[] = {'P','I','P','E','\\',0};
         static const WCHAR mailslotW[] = {'M','A','I','L','S','L','O','T','\\',0};
 
-        if ((isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0') ||
-            !strncmpiW( filename + 4, pipeW, 5 ) ||
-            !strncmpiW( filename + 4, mailslotW, 9 ))
+        if ((isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0') )
+        {
+	    static const WCHAR cdromW[]  = {'c','d','r','o','m','.','s','y','s',0};
+	    UINT type = GetDriveTypeW(&filename[4]);
+	    switch (type)
+	    {
+	    case DRIVE_CDROM:
+		strcpyW(driver, cdromW);
+		break;
+	    default:
+		TRACE("Raw Device of type %d should be handled by appropriate driver\n", type);
+	    }
+            dosdev = 0;
+        }
+	else if (!strncmpiW( filename + 4, pipeW, 5 ) || !strncmpiW( filename + 4, mailslotW, 9 ))
         {
             dosdev = 0;
         }
@@ -1240,7 +1253,7 @@
         }
         else if (filename[4])
         {
-            ret = VXD_Open( filename+4, access, sa );
+            ret = VXD_Open( filename+4, NULL, access, sa );
             goto done;
         }
         else
@@ -1327,7 +1340,12 @@
         else
             SetLastError( RtlNtStatusToDosError(status) );
     }
-    else SetLastError(0);
+    else 
+    {
+	SetLastError(0);
+	if (driver[0]) 
+	    ret = VXD_Open( driver, ret, access, sa );
+    }
     RtlFreeUnicodeString( &nameW );
 
  done:
Index: wine/dlls/kernel/vxd.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/vxd.c,v
retrieving revision 1.19
diff -u -r1.19 vxd.c
--- wine/dlls/kernel/vxd.c	20 Jun 2005 10:40:37 -0000	1.19
+++ wine/dlls/kernel/vxd.c	10 Jul 2005 12:52:45 -0000
@@ -46,7 +46,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(vxd);
 
-typedef BOOL (WINAPI *DeviceIoProc)(DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
+typedef BOOL (WINAPI *DeviceIoProc)(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
 typedef DWORD (WINAPI *VxDCallProc)(DWORD, CONTEXT86 *);
 
 struct vxd_module
@@ -56,6 +56,7 @@
     HANDLE       handle;
     HMODULE      module;
     DeviceIoProc proc;
+    HANDLE       devicehandle;
 };
 
 struct vxdcall_service
@@ -174,55 +175,75 @@
 
 
 /* load a VxD and return a file handle to it */
-HANDLE VXD_Open( LPCWSTR filenameW, DWORD access, SECURITY_ATTRIBUTES *sa )
+HANDLE VXD_Open( LPCWSTR drivernameW, HANDLE device, DWORD access, SECURITY_ATTRIBUTES *sa )
 {
     static const WCHAR dotVxDW[] = {'.','v','x','d',0};
+    static const WCHAR dotSysW[] = {'.','s','y','s',0};
     int i;
     HANDLE handle;
     HMODULE module;
-    WCHAR *p, name[16];
+    WCHAR *p, *q = NULL, name[16];
 
-    if (!(GetVersion() & 0x80000000))  /* there are no VxDs on NT */
-    {
-        SetLastError( ERROR_FILE_NOT_FOUND );
-        return 0;
-    }
+    TRACE("drivername %s  handle %p\n", debugstr_w(drivernameW), device);
+    /* normalize the drivername */
 
-    /* normalize the filename */
-
-    if (strlenW( filenameW ) >= sizeof(name)/sizeof(WCHAR) - 4 ||
-        strchrW( filenameW, '/' ) || strchrW( filenameW, '\\' ))
+    if (strlenW( drivernameW ) >= sizeof(name)/sizeof(WCHAR) - 4 ||
+        strchrW( drivernameW, '/' ) || strchrW( drivernameW, '\\' ))
     {
         SetLastError( ERROR_FILE_NOT_FOUND );
         return 0;
     }
-    strcpyW( name, filenameW );
+    strcpyW( name, drivernameW );
     strlwrW( name );
     p = strchrW( name, '.' );
-    if (!p) strcatW( name, dotVxDW );
-    else if (strcmpW( p, dotVxDW ))  /* existing extension has to be .vxd */
-    {
-        SetLastError( ERROR_FILE_NOT_FOUND );
-        return 0;
-    }
-
-    /* try to load the module first */
-
-    if (!(module = LoadLibraryW( name )))
+    if (!p) 
+	q = name + strlenW(name);
+    /* Try first to open as .sys file */
+    if (!p)
+	strcatW( name, dotSysW );
+    else
     {
-        FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
-               debugstr_w(name) );
-        SetLastError( ERROR_FILE_NOT_FOUND );
-        return 0;
+	if(strcmpW( p, dotVxDW ) && strcmpW( p, dotSysW ))
+	{
+	    SetLastError( ERROR_FILE_NOT_FOUND );
+	    return 0;
+	}
+    }
+    
+    module = LoadLibraryW( name );
+    if (!module)
+    {
+	if (!(GetVersion() & 0x80000000))  /* there are no VxDs on NT, try as .sys */
+	{
+	    FIXME( "Unsupported driver%s\n", debugstr_w(name) );
+	    SetLastError( ERROR_FILE_NOT_FOUND );
+	    return 0;
+	}
+	else /* now try as VXD as we are emulating a non-NT system */
+	{
+	    if (!p) 
+		strcatW( q, dotVxDW );
+	    else if (strcmpW( p, dotVxDW ))  /* existing extension has to be .vxd */
+	    {
+		SetLastError( ERROR_FILE_NOT_FOUND );
+		return 0;
+	    }
+	    if (!(module = LoadLibraryW( name )))
+	    {
+		FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
+		       debugstr_w(name) );
+		SetLastError( ERROR_FILE_NOT_FOUND );
+		return 0;
+	    }
+	}
     }
-
     /* register the module in the global list if necessary */
 
     RtlEnterCriticalSection( &vxd_section );
 
     for (i = 0; i < MAX_VXD_MODULES; i++)
     {
-        if (vxd_modules[i].module == module)
+        if (vxd_modules[i].module == module && (!device|| vxd_modules[i].devicehandle == device))
         {
             handle = vxd_modules[i].handle;
             goto done;  /* already registered */
@@ -232,12 +253,17 @@
             struct stat st;
             int fd;
 
-            /* get a file handle to the dummy file */
-            if (!(handle = open_vxd_handle( name )))
-            {
-                FreeLibrary( module );
-                goto done;
-            }
+	    if(!device) 
+	    {
+		/* get a file handle to the dummy file */
+		if (!(handle = open_vxd_handle( name )))
+		{
+		    FreeLibrary( module );
+		    goto done;
+		}
+	    }
+	    else
+		handle = device;
             wine_server_handle_to_fd( handle, 0, &fd, NULL );
             if (fstat( fd, &st ) != -1)
             {
@@ -328,10 +354,8 @@
  *		DeviceIoControl (KERNEL32.@)
  * This is one of those big ugly nasty procedure which can do
  * a million and one things when it comes to devices. It can also be
- * used for VxD communication.
+ * used for Driver communication (*.sys or *.vxd files)
  *
- * A return value of FALSE indicates that something has gone wrong which
- * GetLastError can decipher.
  */
 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
                             LPVOID lpvInBuffer, DWORD cbInBuffer,
@@ -345,35 +369,9 @@
            hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
            lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped );
 
-    /* Check if this is a user defined control code for a VxD */
-
-    if( HIWORD( dwIoControlCode ) == 0 )
-    {
-        DeviceIoProc proc = get_vxd_proc( hDevice );
-        if (proc) return proc( dwIoControlCode, lpvInBuffer, cbInBuffer,
-                               lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped );
-        return FALSE;
-    }
-
-    /* Not a VxD, let ntdll handle it */
-
-    if (lpOverlapped)
-    {
-        status = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent,
-                                       NULL, NULL, (PIO_STATUS_BLOCK)lpOverlapped,
-                                       dwIoControlCode, lpvInBuffer, cbInBuffer,
-                                       lpvOutBuffer, cbOutBuffer);
-        if (lpcbBytesReturned) *lpcbBytesReturned = lpOverlapped->InternalHigh;
-    }
-    else
-    {
-        IO_STATUS_BLOCK iosb;
-
-        status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &iosb,
-                                       dwIoControlCode, lpvInBuffer, cbInBuffer,
-                                       lpvOutBuffer, cbOutBuffer);
-        if (lpcbBytesReturned) *lpcbBytesReturned = iosb.Information;
-    }
-    if (status) SetLastError( RtlNtStatusToDosError(status) );
-    return !status;
+    DeviceIoProc proc = get_vxd_proc( hDevice );
+    if (proc) 
+	return proc( hDevice, dwIoControlCode, lpvInBuffer, cbInBuffer,
+		     lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped );
+    return FALSE;
 }
Index: wine/dlls/kernel/kernel_private.h
===================================================================
RCS file: /home/wine/wine/dlls/kernel/kernel_private.h,v
retrieving revision 1.25
diff -u -r1.25 kernel_private.h
--- wine/dlls/kernel/kernel_private.h	14 Jun 2005 11:42:34 -0000	1.25
+++ wine/dlls/kernel/kernel_private.h	10 Jul 2005 12:52:45 -0000
@@ -102,7 +102,7 @@
 
 extern BOOL NLS_IsUnicodeOnlyLcid(LCID);
 
-extern HANDLE VXD_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa );
+extern HANDLE VXD_Open( LPCWSTR filename, HANDLE device, DWORD access, LPSECURITY_ATTRIBUTES sa );
 
 extern WORD DOSMEM_0000H;
 extern WORD DOSMEM_BiosDataSeg;



More information about the wine-patches mailing list