Protected mode interrupt problem

Mike McCormack mike at codeweavers.com
Wed Oct 8 15:09:57 CDT 2003


Hi All,

I've run into an interrupt related problem with Quicken 2002's installer.

Two 16bit programs launch, one after the other. Each program hooks INT 
0, however since our interrupt tables are global to all tasks, the 
second task retrieves the interrupt vector that the first task set.

The first task exits, and restores the original INT 0 vector.  When the 
second task exits, tries to restore the INT 0 vector set by the first 
task, which now has an invalid selector, so it crashes.

After a bit of discussion and writing a test program, we discovered that 
it appears that some interrupt vectors are task local, and some are 
global.  The local ones appear to be stored in the TDB (task descriptor 
block), in offsets 0x26 - 0x4a.

The attached patch fixes this, though we're not sure that it is correct 
for DOS programs.

I have enclosed a test program that shows the problem.

Mike

-------------- next part --------------
Index: include/task.h
===================================================================
RCS file: /cvstrees/crossover/office/wine/include/task.h,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 task.h
--- include/task.h	12 Sep 2003 18:37:36 -0000	1.1.1.5
+++ include/task.h	7 Oct 2003 06:29:43 -0000
@@ -98,13 +98,13 @@
     FARPROC16 sighandler WINE_PACKED;     /* 26 Signal handler */
     FARPROC16 userhandler WINE_PACKED;    /* 2a USER signal handler */
     FARPROC16 discardhandler WINE_PACKED; /* 2e Handler for GlobalNotify() */
-    DWORD     int0 WINE_PACKED;           /* 32 int 0 (divide by 0) handler */
-    DWORD     int2 WINE_PACKED;           /* 36 int 2 (NMI) handler */
-    DWORD     int4 WINE_PACKED;           /* 3a int 4 (INTO) handler */
-    DWORD     int6 WINE_PACKED;           /* 3e int 6 (invalid opc) handler */
-    DWORD     int7 WINE_PACKED;           /* 42 int 7 (coprocessor) handler */
-    DWORD     int3e WINE_PACKED;          /* 46 int 3e (80x87 emu) handler */
-    DWORD     int75 WINE_PACKED;          /* 4a int 75 (80x87 error) handler */
+    FARPROC16 int0 WINE_PACKED;           /* 32 int 0 (divide by 0) handler */
+    FARPROC16 int2 WINE_PACKED;           /* 36 int 2 (NMI) handler */
+    FARPROC16 int4 WINE_PACKED;           /* 3a int 4 (INTO) handler */
+    FARPROC16 int6 WINE_PACKED;           /* 3e int 6 (invalid opc) handler */
+    FARPROC16 int7 WINE_PACKED;           /* 42 int 7 (coprocessor) handler */
+    FARPROC16 int3e WINE_PACKED;          /* 46 int 3e (80x87 emu) handler */
+    FARPROC16 int75 WINE_PACKED;          /* 4a int 75 (80x87 error) handler */
     DWORD     compat_flags WINE_PACKED;   /* 4e Compatibility flags */
     BYTE      unused4[2];                 /* 52 */
     struct _TEB *teb;                     /* 54 Pointer to thread database */
Index: dlls/winedos/interrupts.c
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/winedos/interrupts.c,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 interrupts.c
--- dlls/winedos/interrupts.c	12 Sep 2003 18:37:31 -0000	1.1.1.8
+++ dlls/winedos/interrupts.c	7 Oct 2003 06:29:47 -0000
@@ -25,6 +25,7 @@
 #include "wine/winbase16.h"
 
 #include "thread.h"
+#include "task.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(int);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
@@ -541,9 +542,42 @@
  */
 FARPROC16 DOSVM_GetPMHandler16( BYTE intnum )
 {
+    TDB *pTask;
+    FARPROC16 proc = 0;
+
+    pTask = TASK_GetCurrent();
+    if (pTask)
+    {
+        switch( intnum )
+        {
+        case 0x00:
+            proc = pTask->int0;
+            break;
+        case 0x02:
+            proc = pTask->int2;
+            break;
+        case 0x04:
+            proc = pTask->int4;
+            break;
+        case 0x06:
+            proc = pTask->int6;
+            break;
+        case 0x07:
+            proc = pTask->int7;
+            break;
+        case 0x3e:
+            proc = pTask->int3e;
+            break;
+        case 0x75:
+            proc = pTask->int75;
+            break;
+        }
+        if( proc )
+            return proc;
+    }
     if (!DOSVM_Vectors16[intnum])
     {
-        FARPROC16 proc = (FARPROC16)MAKESEGPTR( DOSVM_dpmi_segments->int16_sel,
+        proc = (FARPROC16)MAKESEGPTR( DOSVM_dpmi_segments->int16_sel,
                                                 DOSVM_STUB_PM16 * intnum );
         DOSVM_Vectors16[intnum] = proc;
     }
@@ -558,9 +592,41 @@
  */
 void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler )
 {
+  TDB *pTask;
+
   TRACE("Set protected mode interrupt vector %02x <- %04x:%04x\n",
        intnum, HIWORD(handler), LOWORD(handler) );
-  DOSVM_Vectors16[intnum] = handler;
+
+  pTask = TASK_GetCurrent();
+  if (!pTask)
+    return;
+  switch( intnum )
+  {
+  case 0x00:
+    pTask->int0 = handler;
+    break;
+  case 0x02:
+    pTask->int2 = handler;
+    break;
+  case 0x04:
+    pTask->int4 = handler;
+    break;
+  case 0x06:
+    pTask->int6 = handler;
+    break;
+  case 0x07:
+    pTask->int7 = handler;
+    break;
+  case 0x3e:
+    pTask->int3e = handler;
+    break;
+  case 0x75:
+    pTask->int75 = handler;
+    break;
+  default:
+    DOSVM_Vectors16[intnum] = handler;
+    break;
+  }
 }
 
 
-------------- next part --------------
#include <stdio.h>                        
#include <windows.h>

void myintfn(void)
{
}

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, 
                    LPSTR lpCmdLine, int nCmdShow)
{
	int old_seg, old_ofs, new_seg, new_ofs;
	char str[16];
	                         
	/* get the old interrupt handler for int 0 */
    _asm {    
    	push bx
        push es
		mov ax,0x3502
		int 21h
		mov old_seg, es
		mov old_ofs, bx
		pop es
		pop bx
    }                                            
    /* print it in a message box */
    sprintf(str, "old %04x:%04x", old_seg, old_ofs );
    MessageBox( 0, str, "Int 02", MB_OK);
    /* set the new interrupt handler */
    _asm {     
    	push ds
    	push dx
    	mov ax,0x2502
    	push cs
    	pop ds
    	mov dx, offset myintfn
		int 21h
    	pop dx
    	pop ds 
    }                
    
    if( !hPrevInstance)
    	WinExec("taskint.exe",SW_SHOW);
    
	/* fetch it back again */
    _asm {    
    	push bx
        push es
		mov ax,0x3502
		int 21h
		mov new_seg, es
		mov new_ofs, bx
		pop es
		pop bx
    }
    sprintf(str, "new %04x:%04x", new_seg, new_ofs );
    MessageBox( 0, str, "Int 02", MB_OK);
    
    /* now set the original back again */
    _asm {     
    	push ds
    	push dx
    	mov ax,0x2502
    	mov ds, old_seg
    	mov dx, old_ofs
		int 21h
    	pop dx
    	pop ds 
    }
    
	return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: TASKINT.EXE
Type: application/x-msdownload
Size: 19688 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20031009/97c889ff/TASKINT.bin


More information about the wine-patches mailing list