/**************************************************************************** * * PM/Pro Library * * Copyright (C) 1996 SciTech Software. * All rights reserved. * * Filename: $Workfile: pmpro.c $ * Version: $Revision: 1.0 $ * * Language: ANSI C * Environment: IBM PC (MSDOS) Real mode and 16/32 bit Protected Mode * * Description: Module implementing DOS extender independant protected * mode programming. This module will need to be included in * all programs that use SciTech Software's products that * are to be compiled in protected mode, and will need to be * compiled with the correct defines for the DOS extender that * you will be using (or with no defines for real mode * emulation of these routines). * * $Date: 05 Feb 1996 21:41:30 $ $Author: KendallB $ * ****************************************************************************/ #include #include #include #include "pmpro.h" #ifndef __WINDOWS__ /*--------------------------- Global variables ----------------------------*/ #ifndef REALMODE static int globalDataStart; #endif PM_criticalHandler _PM_critHandler = NULL; PM_breakHandler _PM_breakHandler = NULL; PM_intHandler _PM_timerHandler = NULL; PM_intHandler _PM_keyHandler = NULL; PM_key15Handler _PM_key15Handler = NULL; PM_mouseHandler _PM_mouseHandler = NULL; int _PM_mouseMask; uint _PM_ctrlCSel,_PM_ctrlCOff; /* Location of Ctrl-C flag */ uint _PM_ctrlBSel,_PM_ctrlBOff; /* Location of Ctrl-Break flag */ uint _PM_critSel,_PM_critOff; /* Location of Critical error Bf*/ PMFARPTR _PM_prevTimer = PMNULL; /* Previous timer handler */ PMFARPTR _PM_prevKey = PMNULL; /* Previous key handler */ PMFARPTR _PM_prevKey15 = PMNULL; /* Previous key15 handler */ PMFARPTR _PM_prevVBE = PMNULL; /* Previous VBE handler */ PMFARPTR _PM_prevBreak = PMNULL; /* Previous break handler */ PMFARPTR _PM_prevCtrlC = PMNULL; /* Previous CtrlC handler */ PMFARPTR _PM_prevCritical = PMNULL; /* Previous critical handler */ long _PM_prevRealTimer; /* Previous real mode timer */ long _PM_prevRealKey; /* Previous real mode key */ long _PM_prevRealKey15; /* Previous real mode key15 */ #ifndef REALMODE static int globalDataEnd; #endif /*----------------------------- Implementation ----------------------------*/ /* Globals for locking interrupt handlers in _pmpro.asm */ #ifndef REALMODE extern int _PM_pmproDataStart; extern int _PM_pmproDataEnd; void _ASMAPI _PM_pmproCodeStart(void); void _ASMAPI _PM_pmproCodeEnd(void); #endif /* Protected mode interrupt handlers, also called by PM callbacks below */ void _ASMAPI _PM_timerISR(void); void _ASMAPI _PM_keyISR(void); void _ASMAPI _PM_key15ISR(void); void _ASMAPI _PM_breakISR(void); void _ASMAPI _PM_ctrlCISR(void); void _ASMAPI _PM_criticalISR(void); void _ASMAPI _PM_mouseISR(void); /* Protected mode DPMI callback handlers */ void _ASMAPI _PM_mousePMCB(void); /* Routine to install a mouse handler function */ void _ASMAPI _PM_setMouseHandler(int mask); /* Routine to allocate DPMI real mode callback routines */ void _ASMAPI _DPMI_allocateCallback(void (_ASMAPI *pmcode)(),void *rmregs,long *RMCB); void _ASMAPI _DPMI_freeCallback(long RMCB); /* DPMI helper functions in PMLITE.C */ ulong DPMI_mapPhysicalToLinear(ulong physAddr,ulong limit); int DPMI_setSelectorBase(ushort sel,ulong linAddr); ulong DPMI_getSelectorBase(ushort sel); int DPMI_setSelectorLimit(ushort sel,ulong limit); uint DPMI_createSelector(ulong base,ulong limit); void DPMI_freeSelector(uint sel); int DPMI_lockLinearPages(ulong linear,ulong len); int DPMI_unlockLinearPages(ulong linear,ulong len); void PMAPI _PM_getRMvect(int intno, long *realisr); void PMAPI _PM_setRMvect(int intno, long realisr); /*-------------------------------------------------------------------------*/ /* Generic routines common to all extenders */ /*-------------------------------------------------------------------------*/ void PMAPI PM_resetMouseDriver(int hardReset) { RMREGS regs; PM_mouseHandler oldHandler = _PM_mouseHandler; PM_restoreMouseHandler(); regs.x.ax = hardReset ? 0 : 33; PM_int86(0x33, ®s, ®s); if (oldHandler) PM_setMouseHandler(_PM_mouseMask, oldHandler); } #ifndef REALMODE static void PMAPI lockPMHandlers(void) { static int locked = 0; int stat = 0; /* Lock all of the code and data used by our protected mode interrupt * handling routines, so that it will continue to work correctly * under real mode. */ if (!locked) { PM_saveDS(); stat = !PM_lockDataPages(&globalDataStart,(int)&globalDataEnd-(int)&globalDataStart); stat |= !PM_lockDataPages(&_PM_pmproDataStart,(int)&_PM_pmproDataEnd - (int)&_PM_pmproDataStart); stat |= !PM_lockCodePages((__codePtr)_PM_pmproCodeStart,(int)_PM_pmproCodeEnd-(int)_PM_pmproCodeStart); if (stat) { printf("Page locking services failed - interrupt handling not safe!\n"); exit(1); } locked = 1; } } #endif /*-------------------------------------------------------------------------*/ /* DOS Real Mode support. */ /*-------------------------------------------------------------------------*/ #ifdef REALMODE #ifndef MK_FP #define MK_FP(s,o) ( (void far *)( ((ulong)(s) << 16) + \ (ulong)(o) )) #endif int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { PM_saveDS(); _PM_mouseHandler = mh; _PM_setMouseHandler(_PM_mouseMask = mask); return 1; } void PMAPI PM_restoreMouseHandler(void) { union REGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; int86(0x33, ®s, ®s); _PM_mouseHandler = NULL; } } void PMAPI PM_setTimerHandler(PM_intHandler th) { _PM_getRMvect(0x8, (long*)&_PM_prevTimer); _PM_timerHandler = th; _PM_setRMvect(0x8, (long)_PM_timerISR); } void PMAPI PM_restoreTimerHandler(void) { if (_PM_timerHandler) { _PM_setRMvect(0x8, (long)_PM_prevTimer); _PM_timerHandler = NULL; } } void PMAPI PM_setKeyHandler(PM_intHandler kh) { _PM_getRMvect(0x9, (long*)&_PM_prevKey); _PM_keyHandler = kh; _PM_setRMvect(0x9, (long)_PM_keyISR); } void PMAPI PM_restoreKeyHandler(void) { if (_PM_keyHandler) { _PM_setRMvect(0x9, (long)_PM_prevKey); _PM_keyHandler = NULL; } } void PMAPI PM_setKey15Handler(PM_key15Handler kh) { _PM_getRMvect(0x15, (long*)&_PM_prevKey15); _PM_key15Handler = kh; _PM_setRMvect(0x15, (long)_PM_key15ISR); } void PMAPI PM_restoreKey15Handler(void) { if (_PM_key15Handler) { _PM_setRMvect(0x15, (long)_PM_prevKey15); _PM_key15Handler = NULL; } } void PMAPI PM_installAltBreakHandler(PM_breakHandler bh) { static int ctrlCFlag,ctrlBFlag; void *p; p = &ctrlCFlag; /* Need this for buggy compilers */ _PM_ctrlCSel = FP_SEG(p); _PM_ctrlCOff = FP_OFF(p); p = &ctrlBFlag; /* Need this for buggy compilers */ _PM_ctrlBSel = FP_SEG(p); _PM_ctrlBOff = FP_OFF(p); _PM_getRMvect(0x1B, (long*)&_PM_prevBreak); _PM_getRMvect(0x23, (long*)&_PM_prevCtrlC); _PM_breakHandler = bh; _PM_setRMvect(0x1B, (long)_PM_breakISR); _PM_setRMvect(0x23, (long)_PM_ctrlCISR); } void PMAPI PM_installBreakHandler(void) { PM_installAltBreakHandler(NULL); } void PMAPI PM_restoreBreakHandler(void) { if (_PM_prevBreak) { _PM_setRMvect(0x1B, (long)_PM_prevBreak); _PM_setRMvect(0x23, (long)_PM_prevCtrlC); _PM_prevBreak = NULL; _PM_breakHandler = NULL; } } void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch) { static short critBuf[2]; void *p; p = critBuf; /* Need this for buggy compilers */ _PM_critSel = FP_SEG(p); _PM_critOff = FP_OFF(p); _PM_getRMvect(0x24, (long*)&_PM_prevCritical); _PM_critHandler = ch; _PM_setRMvect(0x24, (long)_PM_criticalISR); } void PMAPI PM_installCriticalHandler(void) { PM_installAltCriticalHandler(NULL); } void PMAPI PM_restoreCriticalHandler(void) { if (_PM_prevCritical) { _PM_setRMvect(0x24, (long)_PM_prevCritical); _PM_prevCritical = NULL; _PM_critHandler = NULL; } } int PMAPI PM_lockDataPages(void *p,uint len) { p = p; len = len; /* Do nothing for real mode */ return 1; } int PMAPI PM_unlockDataPages(void *p,uint len) { p = p; len = len; /* Do nothing for real mode */ return 1; } int PMAPI PM_lockCodePages(void (*p)(),uint len) { p = p; len = len; /* Do nothing for real mode */ return 1; } int PMAPI PM_unlockCodePages(void (*p)(),uint len) { p = p; len = len; /* Do nothing for real mode */ return 1; } void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { long t; _PM_getRMvect(intno,&t); *isr = (void*)t; } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { PM_saveDS(); _PM_setRMvect(intno,(long)isr); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { _PM_setRMvect(intno,(long)isr); } #endif /*-------------------------------------------------------------------------*/ /* Borland DPMI16 DOS Power Pack support. */ /*-------------------------------------------------------------------------*/ #if defined(__WINDOWS16__) || defined(DPMI16) static long prevRealBreak; /* Previous real mode break handler */ static long prevRealCtrlC; /* Previous real mode CtrlC handler */ static long prevRealCritical; /* Prev real mode critical handler */ int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { lockPMHandlers(); /* Ensure our handlers are locked */ _PM_mouseHandler = mh; _PM_setMouseHandler(_PM_mouseMask = mask); return 1; } void PMAPI PM_restoreMouseHandler(void) { union REGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; int86(0x33, ®s, ®s); _PM_mouseHandler = NULL; } } void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { union REGS regs; regs.x.ax = 0x204; regs.h.bl = intno; int86(0x31,®s,®s); *isr = MK_FP(regs.x.cx, regs.x.dx); } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { PM_saveDS(); PM_restorePMvect(intno, (void*)isr); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { union REGS regs; regs.x.ax = 0x205; regs.h.bl = intno; regs.x.cx = FP_SEG(isr); regs.x.dx = FP_OFF(isr); int86(0x31,®s,®s); } static void getISR(int intno, PMFARPTR *pmisr, long *realisr) { PM_getPMvect(intno,pmisr); _PM_getRMvect(intno,realisr); } static void restoreISR(int intno, PMFARPTR pmisr, long realisr) { _PM_setRMvect(intno,realisr); PM_restorePMvect(intno,pmisr); } static void setISR(int intno, void (* PMAPI pmisr)()) { lockPMHandlers(); /* Ensure our handlers are locked */ PM_setPMvect(intno,pmisr); } void PMAPI PM_setTimerHandler(PM_intHandler th) { getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer); _PM_timerHandler = th; setISR(0x8, _PM_timerISR); } void PMAPI PM_restoreTimerHandler(void) { if (_PM_timerHandler) { restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer); _PM_timerHandler = NULL; } } void PMAPI PM_setKeyHandler(PM_intHandler kh) { getISR(0x9, &_PM_prevKey, &_PM_prevRealKey); _PM_keyHandler = kh; setISR(0x9, _PM_keyISR); } void PMAPI PM_restoreKeyHandler(void) { if (_PM_keyHandler) { restoreISR(0x9, _PM_prevKey, _PM_prevRealKey); _PM_keyHandler = NULL; } } void PMAPI PM_setKey15Handler(PM_key15Handler kh) { getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15); _PM_key15Handler = kh; setISR(0x15, _PM_key15ISR); } void PMAPI PM_restoreKey15Handler(void) { if (_PM_key15Handler) { restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15); _PM_key15Handler = NULL; } } /* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a * flag in the real mode code segment and exits. We save the location * of this flag in real mode memory so that both the real mode and * protected mode code will be modifying the same flags. */ static uchar ctrlHandler[] = { 0x00,0x00,0x00,0x00, /* ctrlBFlag */ 0x66,0x2E,0xC7,0x06,0x00,0x00, 0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */ 0xCF, /* iretf */ }; void PMAPI PM_installAltBreakHandler(PM_breakHandler bh) { uint rseg,roff; getISR(0x1B, &_PM_prevBreak, &prevRealBreak); getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC); _PM_breakHandler = bh; setISR(0x1B, _PM_breakISR); setISR(0x23, _PM_ctrlCISR); /* Hook the real mode vectors for these handlers, as these are not * normally reflected by the DPMI server up to protected mode */ PM_allocRealSeg(sizeof(ctrlHandler)*2, &_PM_ctrlBSel, &_PM_ctrlBOff, &rseg, &roff); PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff,ctrlHandler, sizeof(ctrlHandler)); PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff+sizeof(ctrlHandler), ctrlHandler,sizeof(ctrlHandler)); _PM_ctrlCSel = _PM_ctrlBSel; _PM_ctrlCOff = _PM_ctrlBOff + sizeof(ctrlHandler); _PM_setRMvect(0x1B,((long)rseg << 16) | roff+4); _PM_setRMvect(0x23,((long)rseg << 16) | roff+sizeof(ctrlHandler)+4); } void PMAPI PM_installBreakHandler(void) { PM_installAltBreakHandler(NULL); } void PMAPI PM_restoreBreakHandler(void) { if (_PM_prevBreak) { restoreISR(0x1B, _PM_prevBreak, prevRealBreak); restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC); PM_freeRealSeg(_PM_ctrlBSel, _PM_ctrlBOff); _PM_prevBreak = NULL; _PM_breakHandler = NULL; } } /* Real mode Critical Error handler. This handler simply saves the AX and * DI values in the real mode code segment and exits. We save the location * of this flag in real mode memory so that both the real mode and * protected mode code will be modifying the same flags. */ static uchar criticalHandler[] = { 0x00,0x00, /* axCode */ 0x00,0x00, /* diCode */ 0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */ 0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */ 0xB8,0x03,0x00, /* mov ax,3 */ 0xCF, /* iretf */ }; void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch) { uint rseg,roff; getISR(0x24, &_PM_prevCritical, &prevRealCritical); _PM_critHandler = ch; setISR(0x24, _PM_criticalISR); /* Hook the real mode vector, as this is not normally reflected by the * DPMI server up to protected mode. */ PM_allocRealSeg(sizeof(criticalHandler)*2, &_PM_critSel, &_PM_critOff, &rseg, &roff); PM_memcpyfn(_PM_critSel,_PM_critOff,criticalHandler, sizeof(criticalHandler)); _PM_setRMvect(0x24,((long)rseg << 16) | roff+4); } void PMAPI PM_installCriticalHandler(void) { PM_installAltCriticalHandler(NULL); } void PMAPI PM_restoreCriticalHandler(void) { if (_PM_prevCritical) { restoreISR(0x24, _PM_prevCritical, prevRealCritical); PM_freeRealSeg(_PM_critSel, _PM_critOff); _PM_prevCritical = NULL; _PM_critHandler = NULL; } } int PMAPI PM_lockDataPages(void *p,uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_lockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.ds),len); } int PMAPI PM_unlockDataPages(void *p,uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_unlockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.ds),len); } int PMAPI PM_lockCodePages(void (*p)(),uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_lockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.cs),len); } int PMAPI PM_unlockCodePages(void (*p)(),uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_unlockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.cs),len); } #endif /*-------------------------------------------------------------------------*/ /* Phar Lap TNT DOS Extender support. */ /*-------------------------------------------------------------------------*/ #ifdef TNT #include #include #include static long prevRealBreak; /* Previous real mode break handler */ static long prevRealCtrlC; /* Previous real mode CtrlC handler */ static long prevRealCritical; /* Prev real mode critical handler */ static uint mouseSel,mouseOff; /* The following real mode routine is used to call a 32 bit protected * mode FAR function from real mode. We use this for passing up control * from the real mode mouse callback to our protected mode code. */ static UCHAR realHandler[] = { /* Real mode code generic handler */ 0x00,0x00,0x00,0x00, /* __PM_callProtp */ 0x00,0x00, /* __PM_protCS */ 0x00,0x00,0x00,0x00, /* __PM_protHandler */ 0x66,0x60, /* pushad */ 0x1E, /* push ds */ 0x6A,0x00, /* push 0 */ 0x6A,0x00, /* push 0 */ 0x2E,0xFF,0x36,0x04,0x00, /* push [cs:__PM_protCS] */ 0x66,0x2E,0xFF,0x36,0x06,0x00, /* push [cs:__PM_protHandler] */ 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PM_callProtp] */ 0x83,0xC4,0x0A, /* add sp,10 */ 0x1F, /* pop ds */ 0x66,0x61, /* popad */ 0xCB, /* retf */ }; /* The following functions installs the above realmode callback mechanism * in real mode memory for calling the protected mode routine. */ int installCallback(void (PMAPI *pmCB)(),uint *psel, uint *poff, uint *rseg, uint *roff) { CONFIG_INF config; REALPTR realBufAdr,callProtp; ULONG bufSize; FARPTR protBufAdr; /* Get address of real mode routine to call up to protected mode */ _dx_rmlink_get(&callProtp, &realBufAdr, &bufSize, &protBufAdr); _dx_config_inf(&config, (UCHAR*)&config); /* Fill in the values in the real mode code segment so that it will * call the correct routine. */ *((REALPTR*)&realHandler[0]) = callProtp; *((USHORT*)&realHandler[4]) = config.c_cs_sel; *((ULONG*)&realHandler[6]) = (ULONG)pmCB; /* Copy the real mode handler to real mode memory */ if (!PM_allocRealSeg(sizeof(realHandler),psel,poff,rseg,roff)) return 0; PM_memcpyfn(*psel,*poff,realHandler,sizeof(realHandler)); /* Skip past global variabls in real mode code segment */ *roff += 0x0A; return 1; } int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { RMREGS regs; RMSREGS sregs; uint rseg,roff; lockPMHandlers(); /* Ensure our handlers are locked */ if (!installCallback(_PM_mouseISR, &mouseSel, &mouseOff, &rseg, &roff)) return 0; _PM_mouseHandler = mh; /* Install the real mode mouse handler */ sregs.es = rseg; regs.x.dx = roff; regs.x.cx = _PM_mouseMask = mask; regs.x.ax = 0xC; PM_int86x(0x33, ®s, ®s, &sregs); return 1; } void PMAPI PM_restoreMouseHandler(void) { RMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int86(0x33, ®s, ®s); PM_freeRealSeg(mouseSel,mouseOff); _PM_mouseHandler = NULL; } } void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { FARPTR ph; _dx_pmiv_get(intno, &ph); isr->sel = FP_SEL(ph); isr->off = FP_OFF(ph); } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { CONFIG_INF config; FARPTR ph; PM_saveDS(); _dx_config_inf(&config, (UCHAR*)&config); FP_SET(ph,(uint)isr,config.c_cs_sel); _dx_pmiv_set(intno,ph); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { FARPTR ph; FP_SET(ph,isr.off,isr.sel); _dx_pmiv_set(intno,ph); } static void getISR(int intno, PMFARPTR *pmisr, long *realisr) { PM_getPMvect(intno,pmisr); _PM_getRMvect(intno, realisr); } static void restoreISR(int intno, PMFARPTR pmisr, long realisr) { _PM_setRMvect(intno,realisr); PM_restorePMvect(intno,pmisr); } static void setISR(int intno, void (PMAPI *isr)()) { CONFIG_INF config; FARPTR ph; lockPMHandlers(); /* Ensure our handlers are locked */ _dx_config_inf(&config, (UCHAR*)&config); FP_SET(ph,(uint)isr,config.c_cs_sel); _dx_apmiv_set(intno,ph); } void PMAPI PM_setTimerHandler(PM_intHandler th) { getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer); _PM_timerHandler = th; setISR(0x8, _PM_timerISR); } void PMAPI PM_restoreTimerHandler(void) { if (_PM_timerHandler) { restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer); _PM_timerHandler = NULL; } } void PMAPI PM_setKeyHandler(PM_intHandler kh) { getISR(0x9, &_PM_prevKey, &_PM_prevRealKey); _PM_keyHandler = kh; setISR(0x9, _PM_keyISR); } void PMAPI PM_restoreKeyHandler(void) { if (_PM_keyHandler) { restoreISR(0x9, _PM_prevKey, _PM_prevRealKey); _PM_keyHandler = NULL; } } void PMAPI PM_setKey15Handler(PM_key15Handler kh) { getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15); _PM_key15Handler = kh; setISR(0x15, _PM_key15ISR); } void PMAPI PM_restoreKey15Handler(void) { if (_PM_key15Handler) { restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15); _PM_key15Handler = NULL; } } void PMAPI PM_installAltBreakHandler(PM_breakHandler bh) { static int ctrlCFlag,ctrlBFlag; CONFIG_INF config; _dx_config_inf(&config, (UCHAR*)&config); _PM_ctrlCSel = config.c_ds_sel; _PM_ctrlCOff = (uint)&ctrlCFlag; _PM_ctrlBSel = config.c_ds_sel; _PM_ctrlBOff = (uint)&ctrlBFlag; getISR(0x1B, &_PM_prevBreak, &prevRealBreak); getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC); _PM_breakHandler = bh; setISR(0x1B, _PM_breakISR); setISR(0x23, _PM_ctrlCISR); } void PMAPI PM_installBreakHandler(void) { PM_installAltBreakHandler(NULL); } void PMAPI PM_restoreBreakHandler(void) { if (_PM_prevBreak.sel) { restoreISR(0x1B, _PM_prevBreak, prevRealBreak); restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC); _PM_prevBreak.sel = 0; _PM_breakHandler = NULL; } } void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch) { static short critBuf[2]; CONFIG_INF config; _dx_config_inf(&config, (UCHAR*)&config); _PM_critSel = config.c_ds_sel; _PM_critOff = (uint)critBuf; getISR(0x24, &_PM_prevCritical, &prevRealCritical); _PM_critHandler = ch; setISR(0x24, _PM_criticalISR); } void PMAPI PM_installCriticalHandler(void) { PM_installAltCriticalHandler(NULL); } void PMAPI PM_restoreCriticalHandler(void) { if (_PM_prevCritical.sel) { restoreISR(0x24, _PM_prevCritical, prevRealCritical); _PM_prevCritical.sel = 0; _PM_critHandler = NULL; } } int PMAPI PM_lockDataPages(void *p,uint len) { return (_dx_lock_pgsn(p,len) == 0); } int PMAPI PM_unlockDataPages(void *p,uint len) { return (_dx_ulock_pgsn(p,len) == 0); } int PMAPI PM_lockCodePages(void (*p)(),uint len) { CONFIG_INF config; FARPTR fp; _dx_config_inf(&config, (UCHAR*)&config); FP_SET(fp,p,config.c_cs_sel); return (_dx_lock_pgs(fp,len) == 0); } int PMAPI PM_unlockCodePages(void (*p)(),uint len) { CONFIG_INF config; FARPTR fp; _dx_config_inf(&config, (UCHAR*)&config); FP_SET(fp,p,config.c_cs_sel); return (_dx_ulock_pgs(fp,len) == 0); } #endif /*-------------------------------------------------------------------------*/ /* Symantec C++ DOSX and FlashTek X-32/X-32VM support */ /*-------------------------------------------------------------------------*/ #if defined(DOSX) || defined(X32VM) #ifdef X32VM #include #endif static long prevRealBreak; /* Previous real mode break handler */ static long prevRealCtrlC; /* Previous real mode CtrlC handler */ static long prevRealCritical; /* Prev real mode critical handler */ static uint mouseSel = 0,mouseOff; /* The following real mode routine is used to call a 32 bit protected * mode FAR function from real mode. We use this for passing up control * from the real mode mouse callback to our protected mode code. */ static char realHandler[] = { /* Real mode code generic handler */ 0x00,0x00,0x00,0x00, /* __PM_callProtp */ 0x00,0x00, /* __PM_protCS */ 0x00,0x00,0x00,0x00, /* __PM_protHandler */ 0x1E, /* push ds */ 0x6A,0x00, /* push 0 */ 0x6A,0x00, /* push 0 */ 0x2E,0xFF,0x36,0x04,0x00, /* push [cs:__PM_protCS] */ 0x66,0x2E,0xFF,0x36,0x06,0x00, /* push [cs:__PM_protHandler] */ 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PM_callProtp] */ 0x83,0xC4,0x0A, /* add sp,10 */ 0x1F, /* pop ds */ 0xCB, /* retf */ }; /* The following functions installs the above realmode callback mechanism * in real mode memory for calling the protected mode routine. */ int installCallback(void (PMAPI *pmCB)(),uint *psel, uint *poff, uint *rseg, uint *roff) { PMREGS regs; PMSREGS sregs; regs.x.ax = 0x250D; PM_segread(&sregs); PM_int386x(0x21,®s,®s,&sregs); /* Get RM callback address */ /* Fill in the values in the real mode code segment so that it will * call the correct routine. */ *((ulong*)&realHandler[0]) = regs.e.eax; *((ushort*)&realHandler[4]) = sregs.cs; *((ulong*)&realHandler[6]) = (ulong)pmCB; /* Copy the real mode handler to real mode memory (only allocate the * buffer once since we cant dealloate it with X32). */ if (*psel == 0) { if (!PM_allocRealSeg(sizeof(realHandler),psel,poff,rseg,roff)) return 0; } PM_memcpyfn(*psel,*poff,realHandler,sizeof(realHandler)); /* Skip past global variables in real mode code segment */ *roff += 0x0A; return 1; } int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { RMREGS regs; RMSREGS sregs; uint rseg,roff; lockPMHandlers(); /* Ensure our handlers are locked */ if (!installCallback(_PM_mouseISR, &mouseSel, &mouseOff, &rseg, &roff)) return 0; _PM_mouseHandler = mh; /* Install the real mode mouse handler */ sregs.es = rseg; regs.x.dx = roff; regs.x.cx = _PM_mouseMask = mask; regs.x.ax = 0xC; PM_int86x(0x33, ®s, ®s, &sregs); return 1; } void PMAPI PM_restoreMouseHandler(void) { RMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int86(0x33, ®s, ®s); _PM_mouseHandler = NULL; } } void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.x.ax = 0x2502; /* Get PM interrupt vector */ regs.x.cx = intno; PM_int386x(0x21, ®s, ®s, &sregs); isr->sel = sregs.es; isr->off = regs.e.ebx; } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { PMFARPTR pmisr; PMSREGS sregs; PM_saveDS(); PM_segread(&sregs); pmisr.sel = sregs.cs; pmisr.off = (uint)isr; PM_restorePMvect(intno, pmisr); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.x.ax = 0x2505; /* Set PM interrupt vector */ regs.x.cx = intno; sregs.ds = isr.sel; regs.e.edx = isr.off; PM_int386x(0x21, ®s, ®s, &sregs); } static void getISR(int intno, PMFARPTR *pmisr, long *realisr) { PM_getPMvect(intno,pmisr); _PM_getRMvect(intno,realisr); } static void restoreISR(int intno, PMFARPTR pmisr, long realisr) { PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.x.ax = 0x2507; /* Set real and PM vectors */ regs.x.cx = intno; sregs.ds = pmisr.sel; regs.e.edx = pmisr.off; regs.e.ebx = realisr; PM_int386x(0x21, ®s, ®s, &sregs); } static void setISR(int intno, void *isr) { PMREGS regs; PMSREGS sregs; lockPMHandlers(); /* Ensure our handlers are locked */ PM_segread(&sregs); regs.x.ax = 0x2506; /* Hook real and protected vectors */ regs.x.cx = intno; sregs.ds = sregs.cs; regs.e.edx = (uint)isr; PM_int386x(0x21, ®s, ®s, &sregs); } void PMAPI PM_setTimerHandler(PM_intHandler th) { getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer); _PM_timerHandler = th; setISR(0x8, _PM_timerISR); } void PMAPI PM_restoreTimerHandler(void) { if (_PM_timerHandler) { restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer); _PM_timerHandler = NULL; } } void PMAPI PM_setKeyHandler(PM_intHandler kh) { getISR(0x9, &_PM_prevKey, &_PM_prevRealKey); _PM_keyHandler = kh; setISR(0x9, _PM_keyISR); } void PMAPI PM_restoreKeyHandler(void) { if (_PM_keyHandler) { restoreISR(0x9, _PM_prevKey, _PM_prevRealKey); _PM_keyHandler = NULL; } } void PMAPI PM_setKey15Handler(PM_key15Handler kh) { getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15); _PM_key15Handler = kh; setISR(0x15, _PM_key15ISR); } void PMAPI PM_restoreKey15Handler(void) { if (_PM_key15Handler) { restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15); _PM_key15Handler = NULL; } } void PMAPI PM_installAltBreakHandler(PM_breakHandler bh) { static int ctrlCFlag,ctrlBFlag; PMSREGS sregs; PM_segread(&sregs); _PM_ctrlCSel = sregs.ds; _PM_ctrlCOff = (uint)&ctrlCFlag; _PM_ctrlBSel = sregs.ds; _PM_ctrlBOff = (uint)&ctrlBFlag; getISR(0x1B, &_PM_prevBreak, &prevRealBreak); getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC); _PM_breakHandler = bh; setISR(0x1B, _PM_breakISR); setISR(0x23, _PM_ctrlCISR); } void PMAPI PM_installBreakHandler(void) { PM_installAltBreakHandler(NULL); } void PMAPI PM_restoreBreakHandler(void) { if (_PM_prevBreak.sel) { restoreISR(0x1B, _PM_prevBreak, prevRealBreak); restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC); _PM_prevBreak.sel = 0; _PM_breakHandler = NULL; } } void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch) { static short critBuf[2]; PMSREGS sregs; PM_segread(&sregs); _PM_critSel = sregs.ds; _PM_critOff = (uint)critBuf; getISR(0x24, &_PM_prevCritical, &prevRealCritical); _PM_critHandler = ch; setISR(0x24, _PM_criticalISR); } void PMAPI PM_installCriticalHandler(void) { PM_installAltCriticalHandler(NULL); } void PMAPI PM_restoreCriticalHandler(void) { if (_PM_prevCritical.sel) { restoreISR(0x24, _PM_prevCritical, prevRealCritical); _PM_prevCritical.sel = 0; _PM_critHandler = NULL; } } int PMAPI PM_lockDataPages(void *p,uint len) { return (_x386_memlock(p,len) == 0); } int PMAPI PM_unlockDataPages(void *p,uint len) { return (_x386_memunlock(p,len) == 0); } int PMAPI PM_lockCodePages(void (*p)(),uint len) { return (_x386_memlock(p,len) == 0); } int PMAPI PM_unlockCodePages(void (*p)(),uint len) { return (_x386_memunlock(p,len) == 0); } #endif /*-------------------------------------------------------------------------*/ /* Borland's DPMI32 DOS Power Pack Extender support. */ /*-------------------------------------------------------------------------*/ #ifdef DPMI32 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */ void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { PMREGS regs; regs.x.ax = 0x204; regs.h.bl = intno; PM_int386(0x31,®s,®s); isr->sel = regs.x.cx; isr->off = regs.e.edx; } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { PMSREGS sregs; PMREGS regs; PM_saveDS(); regs.x.ax = 0x205; /* Set protected mode vector */ regs.h.bl = intno; PM_segread(&sregs); regs.x.cx = sregs.cs; regs.e.edx = (uint)isr; PM_int386(0x31,®s,®s); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { PMREGS regs; regs.x.ax = 0x205; regs.h.bl = intno; regs.x.cx = isr.sel; regs.e.edx = isr.off; PM_int386(0x31,®s,®s); } /* The following is supposed to work, according to all the Borland * documentation and the sample code that they give us. However it * never does work 100% (never in the MGL code) so we install the * mouse handler ourselves using the real mode callback stuff. This * unfortunately has the effect of causing TD32's mouse handling stuff * to be hooked out. */ #if 0 #define MOUSE_SUPPORTED /* DPMI32 directly supports mouse */ int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { lockPMHandlers(); /* Ensure our handlers are locked */ _PM_mouseHandler = mh; _PM_setMouseHandler(_PM_mouseMask = mask); return 1; } void PMAPI PM_restoreMouseHandler(void) { PMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int386(0x33, ®s, ®s); _PM_mouseHandler = NULL; } } #endif #endif /*-------------------------------------------------------------------------*/ /* Watcom C/C++ with Rational DOS/4GW support. */ /*-------------------------------------------------------------------------*/ #ifdef DOS4GW #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */ #define MOUSE_SUPPORTED /* DOS4GW directly supports mouse */ /* We use the normal DOS services to save and restore interrupts handlers * for Watcom C++, because using the direct DPMI functions does not * appear to work properly. At least if we use the DPMI functions, we * dont get the auto-passup feature that we need to correctly trap * real and protected mode interrupts without installing Bi-model * interrupt handlers. */ void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.h.ah = 0x35; regs.h.al = intno; PM_int386x(0x21,®s,®s,&sregs); isr->sel = sregs.es; isr->off = regs.e.ebx; } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { PMREGS regs; PMSREGS sregs; PM_saveDS(); PM_segread(&sregs); regs.h.ah = 0x25; regs.h.al = intno; sregs.ds = sregs.cs; regs.e.edx = (uint)isr; PM_int386x(0x21,®s,®s,&sregs); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.h.ah = 0x25; regs.h.al = intno; sregs.ds = isr.sel; regs.e.edx = isr.off; PM_int386x(0x21,®s,®s,&sregs); } int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { lockPMHandlers(); /* Ensure our handlers are locked */ _PM_mouseHandler = mh; _PM_setMouseHandler(_PM_mouseMask = mask); return 1; } void PMAPI PM_restoreMouseHandler(void) { PMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int386(0x33, ®s, ®s); _PM_mouseHandler = NULL; } } #endif /*-------------------------------------------------------------------------*/ /* DJGPP port of GNU C++ support. */ /*-------------------------------------------------------------------------*/ #ifdef DJGPP #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */ #define MOUSE_SUPPORTED /* go32 directly supports mouse */ void PMAPI PM_getPMvect(int intno, PMFARPTR *isr) { PMREGS regs; regs.x.ax = 0x204; regs.h.bl = intno; PM_int386(0x31,®s,®s); isr->sel = regs.x.cx; isr->off = regs.e.edx; } void PMAPI PM_setPMvect(int intno, PM_intHandler isr) { PMSREGS sregs; PMREGS regs; PM_saveDS(); regs.x.ax = 0x205; /* Set protected mode vector */ regs.h.bl = intno; PM_segread(&sregs); regs.x.cx = sregs.cs; regs.e.edx = (uint)isr; PM_int386(0x31,®s,®s); } void PMAPI PM_restorePMvect(int intno, PMFARPTR isr) { PMREGS regs; regs.x.ax = 0x205; regs.h.bl = intno; regs.x.cx = isr.sel; regs.e.edx = isr.off; PM_int386(0x31,®s,®s); } int PM_setMouseHandler(int mask, PM_mouseHandler mh) { PMREGS regs; PMSREGS sregs; _PM_mouseHandler = mh; PM_segread(&sregs); sregs.es = sregs.cs; regs.e.edx = (uint)_PM_mouseISR; regs.x.cx = _PM_mouseMask = mask; regs.x.ax = 0xC; PM_int386x(0x33, ®s, ®s, &sregs); return 1; } void PM_restoreMouseHandler(void) { PMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int386(0x33, ®s, ®s); _PM_mouseHandler = NULL; } } #endif /*-------------------------------------------------------------------------*/ /* Generic 32 bit DPMI routines */ /*-------------------------------------------------------------------------*/ #if defined(GENERIC_DPMI32) static long prevRealBreak; /* Previous real mode break handler */ static long prevRealCtrlC; /* Previous real mode CtrlC handler */ static long prevRealCritical; /* Prev real mode critical handler */ #ifndef MOUSE_SUPPORTED /* The following real mode routine is used to call a 32 bit protected * mode FAR function from real mode. We use this for passing up control * from the real mode mouse callback to our protected mode code. */ static long mouseRMCB; /* Mouse real mode callback address */ static uint mouseSel,mouseOff; static char mouseRegs[0x32]; /* Real mode regs for mouse callback */ static char mouseHandler[] = { 0x00,0x00,0x00,0x00, /* _realRMCB */ 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:_realRMCB] */ 0xCB, /* retf */ }; int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh) { RMREGS regs; RMSREGS sregs; uint rseg,roff; lockPMHandlers(); /* Ensure our handlers are locked */ /* Copy the real mode handler to real mode memory */ if (!PM_allocRealSeg(sizeof(mouseHandler),&mouseSel,&mouseOff,&rseg,&roff)) return 0; PM_memcpyfn(mouseSel,mouseOff,mouseHandler,sizeof(mouseHandler)); _DPMI_allocateCallback(_PM_mousePMCB, mouseRegs, &mouseRMCB); PM_setLong(mouseSel,mouseOff,mouseRMCB); /* Install the real mode mouse handler */ _PM_mouseHandler = mh; sregs.es = rseg; regs.x.dx = roff+4; regs.x.cx = _PM_mouseMask = mask; regs.x.ax = 0xC; PM_int86x(0x33, ®s, ®s, &sregs); return 1; } void PMAPI PM_restoreMouseHandler(void) { RMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int86(0x33, ®s, ®s); PM_freeRealSeg(mouseSel,mouseOff); _DPMI_freeCallback(mouseRMCB); _PM_mouseHandler = NULL; } } #endif static void getISR(int intno, PMFARPTR *pmisr, long *realisr) { PM_getPMvect(intno,pmisr); _PM_getRMvect(intno,realisr); } static void restoreISR(int intno, PMFARPTR pmisr, long realisr) { _PM_setRMvect(intno,realisr); PM_restorePMvect(intno,pmisr); } static void setISR(int intno, void (* PMAPI pmisr)()) { lockPMHandlers(); /* Ensure our handlers are locked */ PM_setPMvect(intno,pmisr); } void PMAPI PM_setTimerHandler(PM_intHandler th) { getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer); _PM_timerHandler = th; setISR(0x8, _PM_timerISR); } void PMAPI PM_restoreTimerHandler(void) { if (_PM_timerHandler) { restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer); _PM_timerHandler = NULL; } } void PMAPI PM_setKeyHandler(PM_intHandler kh) { getISR(0x9, &_PM_prevKey, &_PM_prevRealKey); _PM_keyHandler = kh; setISR(0x9, _PM_keyISR); } void PMAPI PM_restoreKeyHandler(void) { if (_PM_keyHandler) { restoreISR(0x9, _PM_prevKey, _PM_prevRealKey); _PM_keyHandler = NULL; } } void PMAPI PM_setKey15Handler(PM_key15Handler kh) { getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15); _PM_key15Handler = kh; setISR(0x15, _PM_key15ISR); } void PMAPI PM_restoreKey15Handler(void) { if (_PM_key15Handler) { restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15); _PM_key15Handler = NULL; } } /* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a * flag in the real mode code segment and exit. We save the location * of this flag in real mode memory so that both the real mode and * protected mode code will be modifying the same flags. */ #ifndef DOS4GW static uchar ctrlHandler[] = { 0x00,0x00,0x00,0x00, /* ctrlBFlag */ 0x66,0x2E,0xC7,0x06,0x00,0x00, 0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */ 0xCF, /* iretf */ }; #endif void PMAPI PM_installAltBreakHandler(PM_breakHandler bh) { #ifndef DOS4GW uint rseg,roff; #else static int ctrlCFlag,ctrlBFlag; PMSREGS sregs; PM_segread(&sregs); _PM_ctrlCSel = sregs.ds; _PM_ctrlCOff = (uint)&ctrlCFlag; _PM_ctrlBSel = sregs.ds; _PM_ctrlBOff = (uint)&ctrlBFlag; #endif getISR(0x1B, &_PM_prevBreak, &prevRealBreak); getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC); _PM_breakHandler = bh; setISR(0x1B, _PM_breakISR); setISR(0x23, _PM_ctrlCISR); #ifndef DOS4GW /* Hook the real mode vectors for these handlers, as these are not * normally reflected by the DPMI server up to protected mode */ PM_allocRealSeg(sizeof(ctrlHandler)*2, &_PM_ctrlBSel, &_PM_ctrlBOff, &rseg, &roff); PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff,ctrlHandler, sizeof(ctrlHandler)); PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff+sizeof(ctrlHandler), ctrlHandler,sizeof(ctrlHandler)); _PM_ctrlCSel = _PM_ctrlBSel; _PM_ctrlCOff = _PM_ctrlBOff + sizeof(ctrlHandler); _PM_setRMvect(0x1B,((long)rseg << 16) | (roff+4)); _PM_setRMvect(0x23,((long)rseg << 16) | (roff+sizeof(ctrlHandler)+4)); #endif } void PMAPI PM_installBreakHandler(void) { PM_installAltBreakHandler(NULL); } void PMAPI PM_restoreBreakHandler(void) { if (_PM_prevBreak.sel) { restoreISR(0x1B, _PM_prevBreak, prevRealBreak); restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC); PM_freeRealSeg(_PM_ctrlBSel, _PM_ctrlBOff); _PM_prevBreak.sel = 0; _PM_breakHandler = NULL; } } /* Real mode Critical Error handler. This handler simply saves the AX and * DI values in the real mode code segment and exits. We save the location * of this flag in real mode memory so that both the real mode and * protected mode code will be modifying the same flags. */ #ifndef DOS4GW static uchar criticalHandler[] = { 0x00,0x00, /* axCode */ 0x00,0x00, /* diCode */ 0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */ 0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */ 0xB8,0x03,0x00, /* mov ax,3 */ 0xCF, /* iretf */ }; #endif void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch) { #ifndef DOS4GW uint rseg,roff; #else static short critBuf[2]; PMSREGS sregs; PM_segread(&sregs); _PM_critSel = sregs.ds; _PM_critOff = (uint)critBuf; #endif getISR(0x24, &_PM_prevCritical, &prevRealCritical); _PM_critHandler = ch; setISR(0x24, _PM_criticalISR); #ifndef DOS4GW /* Hook the real mode vector, as this is not normally reflected by the * DPMI server up to protected mode. */ PM_allocRealSeg(sizeof(criticalHandler)*2, &_PM_critSel, &_PM_critOff, &rseg, &roff); PM_memcpyfn(_PM_critSel,_PM_critOff,criticalHandler, sizeof(criticalHandler)); _PM_setRMvect(0x24,((long)rseg << 16) | (roff+4)); #endif } void PMAPI PM_installCriticalHandler(void) { PM_installAltCriticalHandler(NULL); } void PMAPI PM_restoreCriticalHandler(void) { if (_PM_prevCritical.sel) { restoreISR(0x24, _PM_prevCritical, prevRealCritical); PM_freeRealSeg(_PM_critSel, _PM_critOff); _PM_prevCritical.sel = 0; _PM_critHandler = NULL; } } int PMAPI PM_lockDataPages(void *p,uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len); } int PMAPI PM_unlockDataPages(void *p,uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len); } int PMAPI PM_lockCodePages(void (*p)(),uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len); } int PMAPI PM_unlockCodePages(void (*p)(),uint len) { PMSREGS sregs; PM_segread(&sregs); return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len); } #endif #endif /* !__WINDOWS__ */