home *** CD-ROM | disk | FTP | other *** search
- /*
- WISPY.C -- Windows Interrupt Spy
-
- Copyright (c) Andrew Schulman & Dave Maxey, 1992
-
- Contact: Andrew Schulman (CompuServe 76320,302)
-
- From Chapter 4 of "Undocumented Windows" (Addison-Wesley 1992)
- by Andrew Schulman, Dave Maxey and Matt Pietrek
-
- Build using: WINIOBC WISPY (for Borland C++ v3.00)
- WINIOMS WISPY (for Microsoft C/SDK)
- Note: Ensure that WISPY.DEF is present
-
-
- syntax: wispy [0x]intno [[0x]intno] ...
-
- examples: to trap protected-mode INT 21h calls:
- wispy 0x21
-
- to trap DPMI calls:
- wispy 0x31
-
- to trap INT 2fh calls:
- wispy 0x2f
-
- to trap INT 2fh and DPMI calls:
- wispy 0x2f 0x31
-
- wispy 0x31 and wispy 0x2f show Windows use of undocumented DPMI calls
-
- the undoc 0x31 calls are in old versions of DPMI spec
-
- the undoc 0x2f calls are briefly mentioned in DDK int2fapi.inc
- */
-
- #include "windows.h"
- #include <stdlib.h>
- #include <dos.h>
- #include <string.h>
- #include "wmhandlr.h"
- #include "winio.h"
-
- #pragma pack(1)
-
- typedef struct {
- #ifdef __BORLANDC__
- unsigned bp,di,si,ds,es,dx,cx,bx,ax;
- #else
- unsigned es,ds,di,si,bp,sp,bx,dx,cx,ax; /* same as PUSHA */
- #endif
- unsigned ip,cs,flags;
- } REG_PARAMS;
-
- #define BUF_SIZE 512
- #define MAX_REQU (BUF_SIZE-1)
-
- #define SET_NEXT() { if (next==MAX_REQU) next=0; else next++; }
-
- typedef struct {
- int type;
- REG_PARAMS r;
- char taskname[9];
- char dsdx[40];
- int iInt;
- } REQUEST, FAR * LPREQUEST;
-
- #define REQU_FREE 'f' /* request block not in use */
- #define REQU_USE 'u' /* in use */
-
- #define BEGIN_CRIT_SEC() _asm cli
- #define END_CRIT_SEC() _asm sti
-
- #define IS_REQUEST(buf) \
- (buf[next].type != REQU_FREE)
-
- #define BUFFER_FULL(buf) \
- IS_REQUEST(buf)
-
- #ifndef MK_FP
- #define MK_FP(a,b) ((void far *)(((unsigned long)(a) << 16) | (b)))
- #endif
-
- WORD lsl(WORD sel)
- {
- _asm sub ax, ax
- _asm lsl ax, word ptr sel
- }
-
- static REQUEST far *requ;
-
- int WRT_REQUEST(REQUEST far *buf, REG_PARAMS far *pr,
- HANDLE task, int iInt)
- {
- WORD l;
- static int next = 0;
- char far *ptask = MK_FP(task, 0);
-
- if (BUFFER_FULL(buf))
- return 0;
- BEGIN_CRIT_SEC();
- _fmemcpy(&buf[next].taskname, &ptask[0xf2], 8);
- buf[next].taskname[8] = '\0';
- _fmemcpy(&buf[next].r, pr, sizeof(REG_PARAMS));
- buf[next].type = REQU_USE;
- buf[next].iInt = iInt;
- // oops! nice idea, but might cause fault!!!
- _fmemset(&buf[next].dsdx, 0, 40);
- if (((l = lsl(pr->ds)) != 0) && (l > pr->dx))
- {
- l -= pr->dx;
- _fmemcpy(&buf[next].dsdx, MK_FP(pr->ds, pr->dx), l > 39 ? 39 : l);
- }
- //buf[next].task = task;
- SET_NEXT();
- END_CRIT_SEC();
- PostMessage(__hMainWnd, WM_NULL, 0, 0);
- return 1;
- }
-
- // int RD_REQUEST(REQUEST far *buf, REG_PARAMS *pr, HANDLE *ptask)
- int RD_REQUEST(REQUEST far *buf, REG_PARAMS *pr, LPSTR ptaskname, int *piInt, LPSTR lpdsdx)
- {
- static int next = 0;
- if (! IS_REQUEST(buf))
- return 0;
- BEGIN_CRIT_SEC();
- _fmemcpy(pr, &buf[next].r, sizeof(REG_PARAMS));
- _fmemcpy(ptaskname, &buf[next].taskname, 9);
- _fmemcpy(lpdsdx, &buf[next].dsdx, 40);
- //*ptask = buf[next].task;
- *piInt = buf[next].iInt;
- buf[next].type = REQU_FREE;
- END_CRIT_SEC();
- SET_NEXT();
- return 1;
- }
-
- REQUEST far *INIT_REQUBUF(void)
- {
- LPREQUEST buf, p;
- int i;
- if (! (buf =
- (LPREQUEST) GlobalLock(GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
- BUF_SIZE * sizeof(REQUEST)))))
- return 0;
- for (i=BUF_SIZE, p=buf; i--; p++)
- p->type = REQU_FREE;
- return buf;
- }
-
- FARPROC (FAR PASCAL *GetSetKernelDosProc)(FARPROC DosProc) = 0;
-
- typedef void (_interrupt _far *INTRFUNC)();
-
-
- INTRFUNC _dos_getvect(int intno)
- {
- _asm push es;
- _asm mov ah, 35h;
- _asm mov al, byte ptr [intno];
- _asm int 21h;
- _asm mov dx, es;
- _asm mov ax, bx;
- _asm pop es;
- }
-
-
- void _dos_setvect(int intno, INTRFUNC ifunc)
- {
- _asm push ds;
- _asm mov ah, 25h;
- _asm mov al, byte ptr [intno];
- _asm lds dx, [ifunc];
- _asm int 21h;
- _asm pop ds;
- }
-
-
- INTRFUNC get_vect(unsigned intno)
- {
- if ((intno == 0x21) && GetSetKernelDosProc)
- {
- FARPROC dos = GetSetKernelDosProc(0);
- GetSetKernelDosProc(dos);
- return (INTRFUNC) dos;
- }
- else
- {
- return _dos_getvect(intno);
- }
- }
-
- int set_vect(unsigned intno, INTRFUNC handler)
- {
- if ((intno == 0x21) && GetSetKernelDosProc)
- {
- printf("Using GetSetKernelDosProc\n");
- GetSetKernelDosProc((FARPROC) handler);
- return TRUE;
- }
- else
- {
- _dos_setvect(intno, handler);
- return (get_vect(intno) == handler);
- }
- }
-
- void _interrupt _far IntHandler(REG_PARAMS r);
- FARPROC lpfn_dos;
-
- #define MAX_INTS 16
-
- static unsigned long calls = 0;
- static unsigned long lost = 0;
- static unsigned long missed = 0;
-
- static HMENU hmenuIntrs = 0;
- static HANDLE wispy_task;
- static int intno[MAX_INTS] = {0}; // INT 21h default
- static INTRFUNC old[MAX_INTS] = {0};
- static BOOL enabled[MAX_INTS] = {FALSE};
- static int tmpInt; // transient to hold iInt from thunk
- static int no_idle = 0;
- static unsigned long num_idle = 0;
-
- void on_close(HWND hwnd)
- {
- int i;
-
- // DestroyMenu(hmenuIntrs);
-
- winio_warn(FALSE, "WISPY",
- "%lu interrupts were intercepted\n"
- "(of which %lu were dropped"
- " through buffer overruns)\n\n"
- "%lu occurred while "
- "intercepts were disabled",
- calls, lost, missed);
-
- if (no_idle)
- winio_warn(FALSE, "WISPY",
- "%lu calls to W386_WIN_KERNEL_IDLE (2F/1689)\n"
- "were received", num_idle);
-
- for (i = 0; i < MAX_INTS; i++)
- if (intno[i] && (! set_vect(intno[i], old[i])))
- winio_warn(FALSE, "WISPY",
- "Couldn't restore Int %02Xh", intno[i]);
- }
-
- void set_intr(HWND hwnd, WORD wID)
- {
- enabled[wID - 1] ^= TRUE;
- CheckMenuItem(hmenuIntrs, wID,
- enabled[wID - 1] ? MF_CHECKED : MF_UNCHECKED);
- }
-
- unsigned verr(unsigned short sel)
- {
- _asm mov ax, 1
- _asm verr word ptr sel
- _asm je short okay
- _asm dec ax
- okay:;
- }
-
- void display_int(REG_PARAMS *pr)
- {
- printf("AX=%04x BX=%04x CX=%04x DX=%04x DS=%04x SI=%04x DI=%04x "
- "CS:IP=%04x:%04xh\n",
- pr->ax, pr->bx, pr->cx, pr->dx,
- pr->ds, pr->si, pr->di, pr->cs, pr->ip);
- }
-
- void display_dos_int(REG_PARAMS *pr, char *dsdx)
- {
- int ah = pr->ax >> 8;
- printf("(%02x) ", ah);
- switch (ah) // ICantBelieveIUsedASwitchStatement
- {
- case 0x0e: // set disk
- printf("SET DISK %02xh\n", pr->dx & 0xFF);
- break;
- case 0x19: // get current disk
- puts("GET DISK");
- break;
- case 0x1A: // set DTA
- printf("SET DTA %Fp\n", MK_FP(pr->ds, pr->dx));
- break;
- case 0x25: // set vect
- printf("SET VECT %02xh %04x:%04x\n",
- pr->ax & 0xFF, pr->ds, pr->dx);
- break;
- case 0x2A: // get date
- puts("GET DATE");
- break;
- case 0x2C: // get time
- puts("GET TIME");
- break;
- case 0x2F: // get DTA
- puts("GET DTA");
- break;
- case 0x30: // get vers
- puts("GET DOS VERS");
- break;
- case 0x35: // get vect
- printf("GET VECT %02xh\n", pr->ax & 0xFF);
- break;
- case 0x3B: // set curr dir
- printf("CHDIR %s\n", dsdx);
- break;
- case 0x3d: // open
- printf("OPEN %s\n", dsdx);
- break;
- case 0x3e: // close
- printf("CLOSE %u\n", pr->bx);
- break;
- case 0x3f: // read
- printf("READ %u cb=%u %Fp\n",
- pr->bx, pr->cx, MK_FP(pr->ds, pr->dx));
- break;
- case 0x40: // write
- printf("WRITE %u cb=%u %Fp\n",
- pr->bx, pr->cx, MK_FP(pr->ds, pr->dx));
- break;
- case 0x41: // delete
- printf("DELETE %s\n", dsdx);
- break;
- case 0x42: // seek
- printf("LSEEK%d %u %04x%04x\n",
- pr->ax & 0xFF, pr->bx, pr->cx, pr->dx);
- break;
- case 0x44: // IOCTL
- if ((pr->ax & 0xFF) == 0x00) // get dev info
- printf("IOCTL GET DEV INFO %04xh\n", pr->bx);
- else
- {
- printf("IOCTL ");
- display_int(pr);
- }
- break;
- case 0x4b: // exec
- printf("EXEC %s\n", dsdx);
- break;
- case 0x47: // get curr dir
- puts("GET CURR DIR");
- break;
- case 0x4c: // exit
- printf("EXIT %02xh\n", pr->ax & 0xff);
- break;
- case 0x4e: // find first
- printf("FIND FIRST %s\n", dsdx);
- break;
- case 0x4f: // find next
- puts("FIND NEXT");
- break;
- case 0x50:
- printf("SET PSP %04x\n", pr->bx);
- break;
- case 0x51:
- puts("GET PSP");
- break;
- case 0x52:
- puts("(UNDOC) GET LIST OF LISTS (SYSVARS)");
- break;
- case 0x55: // undoc: create PSP
- printf("(UNDOC) MK PSP %04xh size=%04xh\n", pr->dx, pr->si);
- break;
- case 0x59: // get extended error
- puts("GET EXTENDED ERROR INFO");
- break;
- default:
- display_int(pr);
- }
- }
-
- void display_dpmi_int(REG_PARAMS *pr, char *dsdx)
- {
- unsigned bl = pr->bx & 0xFF;
- printf("(%04x) ", pr->ax);
- switch (pr->ax) // ICantBelieveIUsedASwitchStatement
- {
- case 0x0000: // alloc LDT descriptors
- printf("ALLOC LDT DESC n=%u\n", pr->cx);
- break;
- case 0x0001: // free LDT descriptor
- printf("FREE LDT DESC %04xh\n", pr->bx);
- break;
- case 0x0002: // seg to desc
- printf("SEG TO DESC %04xh\n", pr->bx);
- break;
- case 0x0003: // get next sel incr
- puts("GET NEXT SEL INCR");
- break;
- case 0x0004: // reserved: Lock Selector Memory
- printf("(RESERVED) LOCK SEL %04xh\n", pr->bx);
- break;
- case 0x0005: // reserved
- printf("(RESERVED) UNLOCK SEL %04xh\n", pr->bx);
- break;
- case 0x0009: // set descriptor access rights
- printf("SET DESC ACCRGTS %04xh %04xh\n", pr->bx, pr->cx);
- break;
- case 0x0200: // get rmode intvec
- printf("GET RMODE VEC %02xh\n", bl);
- break;
- case 0x0201: // set rmode intvec
- printf("SET RMODE VEC %02xh %04x:%04xh\n", bl, pr->cx, pr->dx);
- break;
- case 0x0202: // get except vec
- printf("GET EXCEPT VEC %02xh\n", bl);
- break;
- case 0x0203: // set except vec
- printf("SET EXCEPT VEC %02xh %04x:%04xh\n", bl, pr->cx, pr->dx);
- break;
- case 0x0204: // get pmode intvect
- printf("GET PMODE VEC %02xh\n", bl);
- break;
- case 0x0205: // set pmode intvect
- printf("SET PMODE VEC %02xh %04x:%04xh\n", bl, pr->cx, pr->dx);
- break;
- case 0x0300: // simulate rmode intr
- printf("CALL RMODE INTR %02xh\n", bl);
- break;
- case 0x0301: // call rmode proc with far ret frame
- printf("CALL RMODE PROC %04x:%04xh\n", pr->es, pr->di);
- break;
- case 0x0302: // call rmode proc with iret frame
- printf("CALL RMODE PROC (IRET) %04x:%04xh\n", pr->es, pr->di);
- break;
- case 0x0500: // get free memory information
- puts("GET FREE MEM INFO");
- break;
- case 0x0501: // allocate memory block
- printf("ALLOC MEM nbytes=%x%04xh\n", pr->bx, pr->cx);
- break;
- case 0x0502: // free memory block
- printf("FREE MEM %04x%04xh\n", pr->si, pr->di);
- break;
- case 0x0600: // lock linear region
- printf("LOCK LINEAR @%04x%04x nbytes=%x%04xh\n",
- pr->bx, pr->cx, pr->si, pr->di);
- case 0x0700: // reserved: Mark Paging Candidates
- printf("(RESERVED) MARK PAGING CANDIDATES @%04x%04xh "
- "npages=%x%04xh\n",
- pr->bx, pr->cx, pr->si, pr->di);
- case 0x0701: // reserved: Discard Pages
- printf("(RESERVED) DISCARD PAGES @%04x%04xh "
- "npages=%x%04xh\n",
- pr->bx, pr->cx, pr->si, pr->di);
- break;
- case 0x0703: // discard page contents
- printf("DISCARD PAGES @%04x%04x nbytes=%x%04xh\n",
- pr->bx, pr->cx, pr->si, pr->di);
- break;
- case 0xA000:
- printf("GET VENDOR-SPECIFIC DPMI API \"%s\"\n", dsdx);
- break;
- default:
- display_int(pr);
- }
- }
-
- void display_2f_int(REG_PARAMS *pr, char *dsdx)
- {
- unsigned ah = pr->ax >> 8;
- unsigned al = pr->ax & 0xFF;
-
- if (no_idle && (pr->ax == 0x1689))
- {
- num_idle++;
- return;
- }
-
- printf("(%04x) ", pr->ax);
- switch (ah) // ICantBelieveIUsedASwitchStatement
- {
- case 0x16: // see DDK include/int2fapi.inc
- switch (al)
- {
- case 0x00:
- puts("W386_GETVERSION");
- break;
- case 0x02:
- puts("W386_OLD_GET_VMID_API");
- break;
- case 0x05:
- puts("W386_STARTUP");
- break;
- case 0x06:
- puts("W386_EXIT");
- break;
- case 0x07:
- puts("W386_DEVICE_BROADCAST");
- break;
- case 0x08:
- puts("W386_STARTUP_COMPLETE");
- break;
- case 0x09:
- puts("W386_BEGIN_EXIT");
- break;
- case 0x0A:
- puts("W386_WINDOWS_ID");
- break;
- case 0x0B:
- puts("W386_TSR_IDENTIFY");
- break;
- case 0x0C:
- puts("W386_ROM_DETECT (ROM WINDOWS)");
- break;
- case 0x80:
- puts("W386_RELEASE_TIME");
- break;
- case 0x81:
- puts("W386_BEGIN_CRITICAL");
- break;
- case 0x82:
- puts("W386_END_CRITICAL");
- break;
- case 0x83:
- puts("W386_GET_CUR_VMID");
- break;
- case 0x84:
- printf("W386_GET_DEVICE_API dev=0x%04x\n", pr->bx);
- break;
- case 0x85:
- puts("W386_SWITCH_AND_CALL");
- break;
- case 0x86:
- puts("W386_TEST_INT31_AVAIL (DPMI)");
- break;
- case 0x87:
- puts("W386_GET_PM_SWITCH_ADDR (DPMI)");
- break;
- case 0x88:
- puts("W386_GET_LDT_BASE_SEL");
- /* KRNL386.ASM:
- mov ax, 1688h
- mov bx, 0BADh (!)
- int 2Fh
- or ax, ax
- jnz ...
- mov LDT, bx
- */
- break;
- case 0x89:
- // can turn off with -noidle
- puts("W386_WIN_KERNEL_IDLE");
- break;
- case 0x8A:
- printf("W386_DPMI_EXTENSION \"%s\"\n", dsdx);
- break;
- default:
- display_int(pr);
- }
- break;
- case 0x40: // cf. DDK, pp. 2-16 - 2-18 (also OS/2 DOS box??)
- switch (al)
- {
- case 0x00:
- puts("ENABLE VM-ASSISTED SAVE/RESTORE");
- break;
- case 0x01:
- puts("NOTIFY BACKGROUND SWITCH");
- break;
- case 0x02:
- puts("NOTIFY FOREGROUND SWITCH");
- break;
- case 0x03:
- puts("ENTER CRITICAL SECTION");
- break;
- case 0x04:
- puts("EXIT CRITICAL SECTION");
- break;
- case 0x05:
- puts("SAVE VIDEO REGISTER STATE");
- break;
- case 0x06:
- puts("RESTORE VIDEO REGISTER STATE");
- break;
- case 0x07:
- puts("DISABLE VM-ASSISTED SAVE/RESTORE");
- break;
- default:
- display_int(pr);
- }
- break;
- case 0x46:
- // Standard mode winoa286.mod calls
- // 0x4680, 0x4601, 0x4602, 0x4604, 0x4603
- display_int(pr);
- default:
- display_int(pr);
- }
- }
-
- void display_ints(void)
- {
- REG_PARAMS r;
- //HANDLE task;
- static char modname[16];
- static char dsdx[40];
- static int iInt;
-
- // This loop looks for, extracts, and displays messages queued
- // up by the interrupt handler function. The only way we know to
- // terminate the function is because the window closes...
- while (winio_openwindows())
- {
- wmhandler_yield();
- while (RD_REQUEST(requ, &r, (LPSTR) &modname, &iInt, (LPSTR) &dsdx))
- {
- printf("<%s> Int %02Xh ", modname, intno[iInt]);
- if (intno[iInt] == 0x21) // DOS
- display_dos_int(&r, dsdx);
- else if (intno[iInt] == 0x31) // DPMI
- display_dpmi_int(&r, dsdx);
- else if (intno[iInt] == 0x2f) // INT 2Fh
- display_2f_int(&r, dsdx);
- else // other
- display_int(&r);
- }
- }
- }
-
- int axtoi(char *s)
- {
- int ret;
- if (s[0]=='0' && s[1]=='x')
- {
- sscanf(s+2, "%x", &ret);
- return ret;
- }
- else
- return atoi(s);
- }
-
-
- FARPROC MakeIntrInstance(FARPROC fp, HANDLE h, int iInt, WORD addr)
- {
- BYTE *pthunk;
- static BYTE thunk[] = {
- 0x1e, // push ds
- 0x50, // push ax
- 0xb8, 0, 0, // mov ax, h
- 0x8e, 0xd8, // mov ds, ax
- 0x58, // pop ax
- 0xc7, 0x06, 0, 0, 0, 0, // mov word ptr [addr], iInt
- 0x1f, // pop ds
- 0xea, 0, 0, 0, 0 // jmp far fp
- };
- #define OFS_H 0x03
- #define OFS_ADDR 0x0A
- #define OFS_IINT 0x0C
- #define OFS_FP 0x10
-
- static WORD hCS = 0;
-
- if ((! hCS) && (! (hCS = AllocDStoCSAlias(h))))
- return NULL;
-
- if (! (pthunk = malloc(sizeof(thunk))))
- return NULL;
-
- h &= 0xfffc;
- h |= 1;
- *((HANDLE *) &thunk[OFS_H]) = h;
- *((WORD *) &thunk[OFS_ADDR]) = addr;
- *((int *) &thunk[OFS_IINT]) = iInt;
- *((FARPROC *) &thunk[OFS_FP]) = fp;
-
- memcpy(pthunk, &thunk, sizeof(thunk));
- return (FARPROC) MK_FP(hCS, (WORD) pthunk);
- }
-
-
- main(int argc, char *argv[])
- {
- int i;
- char buf[128];
- char num[8];
-
- if (argc < 2)
- {
- winio_close(__hMainWnd);
- fail("To watch interrupts, include them\n"
- "on the command line.\n"
- "Example: WISPY 0x21 0x2f 0x31");
- }
-
- if (__hPrevInst)
- {
- winio_close(__hMainWnd);
- fail("Only one instance of WISPY\n"
- "can be run at a time. To watch\n"
- "multiple interrupts, include\n"
- "them all on the command line.\n"
- "Example: WISPY 0x21 0x2f 0x31");
- }
-
- winio_setbufsize(__hMainWnd, (WORD) 32768, TRUE);
-
- strcpy(buf, "WISPY");
-
- if (! (requ = INIT_REQUBUF()))
- fail("INIT_REQUBUF fail...!");
-
- winio_about("WISPY"
- "\nWindows Interrupt Spy"
- "\n\nCopyright (c) Andrew Schulman and Dave Maxey"
- "\n\nFrom Chapter 4 of"
- "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
- "\nby Andrew Schulman, David Maxey and Matt Pietrek"
- );
-
- hmenuIntrs = CreateMenu();
- InsertMenu(winio_hmenumain(__hMainWnd), 1, MF_POPUP | MF_BYPOSITION,
- hmenuIntrs, "&Interrupts");
-
- winio_onclose(__hMainWnd, (DESTROY_FUNC) on_close);
-
- wispy_task = GetCurrentTask();
-
- GetSetKernelDosProc = GetProcAddress(
- GetModuleHandle("KERNEL"), "GETSETKERNELDOSPROC");
-
- for (i = 0; (i < (argc - 1)) && (i < MAX_INTS); i++)
- {
- if ((strcmp(argv[i+1], "-noidle") == 0) ||
- (strcmp(argv[i+1], "-NOIDLE") == 0))
- {
- no_idle = 1;
- continue;
- }
- if (! (intno[i] = axtoi(argv[i + 1])))
- {
- winio_warn(FALSE, "WISPY",
- "'%s' is not a valid interrupt number", argv[i+1]);
- continue;
- }
- if (! (lpfn_dos = MakeIntrInstance((FARPROC) IntHandler,
- __hInst, i, (WORD) &tmpInt)))
- fail("Could not MakeIntrInstance..!");
-
- old[i] = get_vect(intno[i]);
- if (! set_vect(intno[i], (INTRFUNC) lpfn_dos))
- {
- printf("SetVect on Int %02xh failed!\n", intno[i]);
- intno[i] = 0;
- continue;
- }
- enabled[i] = TRUE;
-
- sprintf(num, " %02xh", intno[i]);
- strcat(buf, num);
-
- AppendMenu(hmenuIntrs, MF_STRING | MF_CHECKED | MF_ENABLED,
- (WORD) i + 1, (LPSTR) num);
- winio_setmenufunc(__hMainWnd, (WORD) i + 1, (MENU_FUNC) set_intr);
- }
-
- winio_settitle(__hMainWnd, buf);
-
- DrawMenuBar(__hMainWnd);
-
- display_ints();
-
- return 0;
- }
-
- void _interrupt _far IntHandler(REG_PARAMS r)
- {
- HANDLE task = GetCurrentTask();
-
- if (task != wispy_task) /* don't show my own ints */
- if (enabled[tmpInt])
- {
- /* tmpInt has been set by the MakeIntrInstance thunk */
- if (! WRT_REQUEST(requ, &r, task, tmpInt))
- lost++; /* buffer overflow */
- calls++;
- }
- else
- missed++;
-
- _chain_intr(old[tmpInt]);
-
- // need some way to get return regs!
- }
-
-
-