/********************************************************************** * DOSVM_Int25Handler * * Handler for int 25h (absolute disk read). */ void WINAPI DOSVM_Int25Handler( CONTEXT *context ) { WCHAR drivespec[] = {'A', ':', '\\', 0}; BYTE *dataptr = CTX_SEG_OFF_TO_LIN( context, context->SegDs, context->Ebx ); DWORD begin; DWORD length; //!! WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); WORD eip = *stack; WORD cs = *++stack; context->Esp += 4; PUSH_WORD16(context, (WORD)context->EFlags); PUSH_WORD16(context, cs); PUSH_WORD16(context, eip); drivespec[0] += AL_reg( context ); if (GetDriveTypeW( drivespec ) == DRIVE_NO_ROOT_DIR || GetDriveTypeW( drivespec ) == DRIVE_UNKNOWN) { SET_CFLAG( context ); SET_AX( context, 0x0201 ); /* unknown unit */ return; } if (CX_reg( context ) == 0xffff) { begin = *(DWORD *)dataptr; length = *(WORD *)(dataptr + 4); dataptr = (BYTE *)CTX_SEG_OFF_TO_LIN( context, *(WORD *)(dataptr + 8), *(DWORD *)(dataptr + 6) ); } else { begin = DX_reg( context ); length = CX_reg( context ); } DOSVM_RawRead( AL_reg( context ), begin, length, dataptr, TRUE ); RESET_CFLAG( context ); }
/********************************************************************** * DOSVM_HardwareInterruptRM * * Emulate call to interrupt handler in real mode. * * Either calls directly builtin handler or pushes interrupt frame to * stack and changes instruction pointer to interrupt handler. */ void DOSVM_HardwareInterruptRM( CONTEXT86 *context, BYTE intnum ) { FARPROC16 handler = DOSVM_GetRMHandler( intnum ); /* check if the call goes to an unhooked interrupt */ if (SELECTOROF(handler) == 0xf000) { /* if so, call it directly */ TRACE( "builtin interrupt %02x has been invoked " "(through vector %02x)\n", OFFSETOF(handler)/DOSVM_STUB_RM, intnum ); DOSVM_CallBuiltinHandler( context, OFFSETOF(handler)/DOSVM_STUB_RM ); } else { /* the interrupt is hooked, simulate interrupt in DOS space */ WORD flag = LOWORD( context->EFlags ); TRACE( "invoking hooked interrupt %02x at %04x:%04x\n", intnum, SELECTOROF(handler), OFFSETOF(handler) ); /* Copy virtual interrupt flag to pushed interrupt flag. */ if (context->EFlags & VIF_MASK) flag |= IF_MASK; else flag &= ~IF_MASK; PUSH_WORD16( context, flag ); PUSH_WORD16( context, context->SegCs ); PUSH_WORD16( context, LOWORD( context->Eip )); context->SegCs = SELECTOROF( handler ); context->Eip = OFFSETOF( handler ); /* Clear virtual interrupt flag and trap flag. */ context->EFlags &= ~(VIF_MASK | TF_MASK); } }
/********************************************************************** * DOSVM_HardwareInterruptPM * * Emulate call to interrupt handler in 16-bit or 32-bit protected mode. * * Pushes interrupt frame to stack and changes instruction * pointer to interrupt handler. */ void DOSVM_HardwareInterruptPM( CONTEXT86 *context, BYTE intnum ) { if(DOSVM_IsDos32()) { FARPROC48 addr = DOSVM_GetPMHandler48( intnum ); if (addr.selector == DOSVM_dpmi_segments->int48_sel) { TRACE( "builtin interrupt %02lx has been invoked " "(through vector %02x)\n", addr.offset / DOSVM_STUB_PM48, intnum ); if (intnum == 0x25 || intnum == 0x26) DOSVM_PushFlags( context, TRUE, FALSE ); else if (DOSVM_IsIRQ(intnum)) DOSVM_PrepareIRQ( context, TRUE ); DOSVM_BuildCallFrame( context, DOSVM_IntProcRelay, DOSVM_GetBuiltinHandler( addr.offset/DOSVM_STUB_PM48 ) ); } else { DWORD *stack; TRACE( "invoking hooked interrupt %02x at %04x:%08lx\n", intnum, addr.selector, addr.offset ); if (DOSVM_IsIRQ(intnum)) DOSVM_PrepareIRQ( context, FALSE ); /* Push the flags and return address on the stack */ stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); *(--stack) = context->EFlags; *(--stack) = context->SegCs; *(--stack) = context->Eip; context->Esp += -12; /* Jump to the interrupt handler */ context->SegCs = addr.selector; context->Eip = addr.offset; } } else { FARPROC16 addr = DOSVM_GetPMHandler16( intnum ); if (SELECTOROF(addr) == DOSVM_dpmi_segments->int16_sel) { TRACE( "builtin interrupt %02x has been invoked " "(through vector %02x)\n", OFFSETOF(addr)/DOSVM_STUB_PM16, intnum ); if (intnum == 0x25 || intnum == 0x26) DOSVM_PushFlags( context, FALSE, FALSE ); else if (DOSVM_IsIRQ(intnum)) DOSVM_PrepareIRQ( context, TRUE ); DOSVM_BuildCallFrame( context, DOSVM_IntProcRelay, DOSVM_GetBuiltinHandler( OFFSETOF(addr)/DOSVM_STUB_PM16 ) ); } else { TRACE( "invoking hooked interrupt %02x at %04x:%04x\n", intnum, SELECTOROF(addr), OFFSETOF(addr) ); if (DOSVM_IsIRQ(intnum)) DOSVM_PrepareIRQ( context, FALSE ); /* Push the flags and return address on the stack */ PUSH_WORD16( context, LOWORD(context->EFlags) ); PUSH_WORD16( context, context->SegCs ); PUSH_WORD16( context, LOWORD(context->Eip) ); /* Jump to the interrupt handler */ context->SegCs = HIWORD(addr); context->Eip = LOWORD(addr); } } }