You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
4.5 KiB
218 lines
4.5 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
vdmint21.c
|
|
|
|
Abstract:
|
|
|
|
This module implements interfaces that support manipulation of i386
|
|
int 21 entry of IDT. These entry points only exist on i386 machines.
|
|
|
|
Author:
|
|
|
|
Shie-Lin Tzong (shielint) 26-Dec-1993
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ki.h"
|
|
#pragma hdrstop
|
|
#include "vdmntos.h"
|
|
|
|
#define IDT_ACCESS_DPL_USER 0x6000
|
|
#define IDT_ACCESS_TYPE_386_TRAP 0xF00
|
|
#define IDT_ACCESS_TYPE_286_TRAP 0x700
|
|
#define IDT_ACCESS_PRESENT 0x8000
|
|
#define LDT_MASK 4
|
|
|
|
//
|
|
// External Reference
|
|
//
|
|
|
|
BOOLEAN
|
|
Ki386GetSelectorParameters(
|
|
IN USHORT Selector,
|
|
OUT PULONG Flags,
|
|
OUT PULONG Base,
|
|
OUT PULONG Limit
|
|
);
|
|
|
|
//
|
|
// Define forward referenced function prototypes.
|
|
//
|
|
|
|
VOID
|
|
Ki386LoadTargetInt21Entry (
|
|
IN PKIPI_CONTEXT SignalDone,
|
|
IN PVOID Parameter1,
|
|
IN PVOID Parameter2,
|
|
IN PVOID Parameter3
|
|
);
|
|
|
|
#define KiLoadInt21Entry() \
|
|
KeGetPcr()->IDT[0x21] = PsGetCurrentProcess()->Pcb.Int21Descriptor
|
|
|
|
typedef struct _INT21INFO {
|
|
KIDTENTRY IdtDescriptor;
|
|
PKPROCESS Process;
|
|
} INT21INFO, *PINT21INFO;
|
|
|
|
|
|
NTSTATUS
|
|
Ke386SetVdmInterruptHandler (
|
|
PKPROCESS Process,
|
|
ULONG Interrupt,
|
|
USHORT Selector,
|
|
ULONG Offset,
|
|
BOOLEAN Gate32
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The specified (software) interrupt entry of IDT will be updated to
|
|
point to the specified handler. For all threads which belong to the
|
|
specified process, their execution processors will be notified to
|
|
make the same change.
|
|
|
|
This function only exists on i386 and i386 compatible processors.
|
|
|
|
No checking is done on the validity of the interrupt handler.
|
|
|
|
Arguments:
|
|
|
|
Process - Pointer to KPROCESS object describing the process for
|
|
which the int 21 entry is to be set.
|
|
|
|
Interrupt - The software interrupt vector which will be updated.
|
|
|
|
Selector, offset - Specified the address of the new handler.
|
|
|
|
Gate32 - True if the gate should be 32 bit, false otherwise
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
KIDTENTRY IdtDescriptor;
|
|
ULONG Flags, Base, Limit;
|
|
INT21INFO Int21Info;
|
|
|
|
|
|
//
|
|
// Check the validity of the request
|
|
// 1. Currently, we support int21 redirection only
|
|
// 2. The specified interrupt handler must be in user space.
|
|
//
|
|
|
|
if (Interrupt != 0x21 || Offset >= (ULONG)MM_HIGHEST_USER_ADDRESS ||
|
|
!Ki386GetSelectorParameters(Selector, &Flags, &Base, &Limit) ){
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Initialize the contents of the IDT entry
|
|
//
|
|
|
|
IdtDescriptor.Offset = (USHORT)Offset;
|
|
IdtDescriptor.Selector = Selector | RPL_MASK | LDT_MASK;
|
|
IdtDescriptor.ExtendedOffset = (USHORT)(Offset >> 16);
|
|
IdtDescriptor.Access = IDT_ACCESS_DPL_USER | IDT_ACCESS_PRESENT;
|
|
if (Gate32) {
|
|
IdtDescriptor.Access |= IDT_ACCESS_TYPE_386_TRAP;
|
|
|
|
} else {
|
|
IdtDescriptor.Access |= IDT_ACCESS_TYPE_286_TRAP;
|
|
}
|
|
|
|
Int21Info.IdtDescriptor = IdtDescriptor;
|
|
Int21Info.Process = Process;
|
|
|
|
KeGenericCallDpc (Ki386LoadTargetInt21Entry,
|
|
&Int21Info);
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
Ki386LoadTargetInt21Entry (
|
|
PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SystemArgument1,
|
|
IN PVOID SystemArgument2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reload local Ldt register and clear signal bit in TargetProcessor mask
|
|
|
|
Arguments:
|
|
|
|
Argument - pointer to a ipi packet structure.
|
|
ReadyFlag - Pointer to flag to be set once LDTR has been reloaded
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
PINT21INFO Int21Info;
|
|
|
|
UNREFERENCED_PARAMETER (Dpc);
|
|
|
|
Int21Info = DeferredContext;
|
|
|
|
//
|
|
// Make sure all DPC's are running so a load of the process
|
|
// LdtDescriptor field can't be torn
|
|
//
|
|
|
|
if (KeSignalCallDpcSynchronize (SystemArgument2)) {
|
|
|
|
|
|
//
|
|
// Set the Ldt fields in the process object
|
|
//
|
|
|
|
Int21Info->Process->Int21Descriptor = Int21Info->IdtDescriptor;
|
|
}
|
|
|
|
//
|
|
// Wait till everyone is at this point before continuing
|
|
//
|
|
|
|
KeSignalCallDpcSynchronize (SystemArgument2);
|
|
|
|
//
|
|
// Set the int 21 entry of IDT from currently active process object
|
|
//
|
|
|
|
KiLoadInt21Entry ();
|
|
|
|
//
|
|
// Signal that all processing has been done
|
|
//
|
|
|
|
KeSignalCallDpcDone (SystemArgument1);
|
|
|
|
return;
|
|
}
|
|
|