Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

386 lines
7.7 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
dpmi386.c
Abstract:
This file contains support for 386/486 only dpmi bops
Author:
Dave Hastings (daveh) 27-Jun-1991
Revision History:
Matt Felton (mattfe) Dec 6 1992 removed unwanted verification
Dave Hastings (daveh) 24-Nov-1992 Moved to mvdm\dpmi32
Matt Felton (mattfe) 8 Feb 1992 optimize getvdmpointer for regular protect mode path.
--*/
#include "precomp.h"
#pragma hdrstop
#include <softpc.h>
#include <memory.h>
#include <malloc.h>
BOOL
DpmiSetX86Descriptor(
LDT_ENTRY *Descriptors,
USHORT registerAX,
USHORT registerCX
)
/*++
Routine Description:
This function puts descriptors into the Ldt. It verifies the contents
and calls nt to actually set up the selector(s).
Arguments:
None
Return Value:
None.
--*/
{
PPROCESS_LDT_INFORMATION LdtInformation = NULL;
NTSTATUS Status;
ULONG ulLdtEntrySize;
ULONG Selector0,Selector1;
ulLdtEntrySize = registerCX * sizeof(LDT_ENTRY);
//
// If there are only 2 descriptors, set them the fast way
//
Selector0 = (ULONG)registerAX;
if ((registerCX <= 2) && (Selector0 != 0)) {
if (registerCX == 2) {
Selector1 = registerAX + sizeof(LDT_ENTRY);
} else {
Selector1 = 0;
}
Status = NtSetLdtEntries(
Selector0,
*((PULONG)(&Descriptors[0])),
*((PULONG)(&Descriptors[0]) + 1),
Selector1,
*((PULONG)(&Descriptors[1])),
*((PULONG)(&Descriptors[1]) + 1)
);
if (NT_SUCCESS(Status)) {
return TRUE;
}
return FALSE;
}
LdtInformation = malloc(sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize);
LdtInformation->Start = registerAX;
LdtInformation->Length = ulLdtEntrySize;
CopyMemory(
&(LdtInformation->LdtEntries),
Descriptors,
ulLdtEntrySize
);
Status = NtSetInformationProcess(
NtCurrentProcess(),
ProcessLdtInformation,
LdtInformation,
sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize
);
if (!NT_SUCCESS(Status)) {
VDprint(
VDP_LEVEL_ERROR,
("DPMI: Failed to set selectors %lx\n", Status)
);
free(LdtInformation);
return FALSE;
}
free(LdtInformation);
return TRUE;
}
VOID
switch_to_protected_mode(
VOID
)
/*++
Routine Description:
This routine switches the dos applications context to protected mode.
Arguments:
None
Return Value:
None.
--*/
{
PCHAR StackPointer;
StackPointer = Sim32GetVDMPointer(((getSS() << 16) | getSP()),
0,
(UCHAR) (getMSW() & MSW_PE)
);
setCS(*(PUSHORT)(StackPointer + 12));
setEIP(*(PULONG)(StackPointer + 8));
setSS(*(PUSHORT)(StackPointer + 6));
setESP(*(PULONG)(StackPointer + 2));
setDS(*(PUSHORT)(StackPointer));
// Necessary to prevent loads of invalid selectors.
setES(0);
setGS(0);
setFS(0);
setMSW(getMSW() | MSW_PE);
//
// If we have fast if emulation in PM set the RealInstruction bit
//
if (VdmFeatureBits & PM_VIRTUAL_INT_EXTENSIONS) {
_asm {
mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
lock or dword ptr [eax], dword ptr RI_BIT_MASK
}
} else {
_asm {
mov eax, FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
lock and dword ptr [eax], dword ptr ~RI_BIT_MASK
}
}
//
// Turn off real mode bit
//
_asm {
mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
lock and dword ptr [eax], dword ptr ~RM_BIT_MASK
}
}
VOID
switch_to_real_mode(
VOID
)
/*++
Routine Description:
This routine services the switch to real mode bop. It is included in
DPMI.c so that all of the mode switching services are in the same place
Arguments:
None
Return Value:
None.
--*/
{
PCHAR StackPointer;
StackPointer = Sim32GetVDMPointer(((getSS() << 16) | getSP()),
0,
(UCHAR) (getMSW() & MSW_PE)
);
setDS(*(PUSHORT)(StackPointer));
setSP(*(PUSHORT)(StackPointer + 2));
setSS(*(PUSHORT)(StackPointer + 4));
setIP((*(PUSHORT)(StackPointer + 6)));
setCS(*(PUSHORT)(StackPointer + 8));
setMSW(getMSW() & ~MSW_PE);
//
// If we have v86 mode fast IF emulation set the RealInstruction bit
//
if (VdmFeatureBits & V86_VIRTUAL_INT_EXTENSIONS) {
_asm {
mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
lock or dword ptr [eax], dword ptr RI_BIT_MASK
}
} else {
_asm {
mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
lock and dword ptr [eax], dword ptr ~RI_BIT_MASK
}
}
//
// turn on real mode bit
//
_asm {
mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
lock or dword ptr [eax], dword ptr RM_BIT_MASK
}
}
VOID DpmiGetFastBopEntry(
VOID
)
/*++
Routine Description:
This routine is the front end for the routine that gets the address. It
is necessary to get the address in asm, because the CS value is not
available in c
Arguments:
None
Return Value:
None.
--*/
{
GetFastBopEntryAddress(&VdmTib.VdmContext);
}
UCHAR *
Sim32pGetVDMPointer(
ULONG Address,
UCHAR ProtectedMode
)
/*++
Routine Description:
This routine converts a 16/16 address to a linear address.
WARNIGN NOTE - This routine has been optimized so protect mode LDT lookup
falls stright through. This routine is call ALL the time by WOW, if you
need to modify it please re optimize the path - mattfe feb 8 92
Arguments:
Address -- specifies the address in seg:offset format
Size -- specifies the size of the region to be accessed.
ProtectedMode -- true if the address is a protected mode address
Return Value:
The pointer.
--*/
{
ULONG Selector;
PUCHAR ReturnPointer;
if (ProtectedMode) {
Selector = (Address & 0xFFFF0000) >> 16;
if (Selector != 40) {
Selector &= ~7;
ReturnPointer = (PUCHAR)FlatAddress[Selector >> 3];
ReturnPointer += (Address & 0xFFFF);
return ReturnPointer;
// Selector 40
} else {
ReturnPointer = (PUCHAR)0x400 + (Address & 0xFFFF);
}
// Real Mode
} else {
ReturnPointer = (PUCHAR)(((Address & 0xFFFF0000) >> 12) + (Address & 0xFFFF));
}
return ReturnPointer;
}
PUCHAR
ExpSim32GetVDMPointer(
ULONG Address,
ULONG Size,
UCHAR ProtectedMode
)
/*++
See Sim32pGetVDMPointer, above
This call must be maintaned as is because it is exported for VDD's
in product 1.0.
--*/
{
return Sim32pGetVDMPointer(Address,(UCHAR)ProtectedMode);
}
VOID
DpmiSetDebugRegisters(
VOID
)
/*++
Routine Description:
This routine is called by DOSX when an app has issued DPMI debug commands.
The six doubleword pointed to by the VDM's DS:SI are the desired values
for the real x86 hardware debug registers. This routine lets
ThreadSetDebugContext() do all the work.
Arguments:
None
Return Value:
None.
--*/
{
PCHAR RegisterPointer;
setCF(0);
RegisterPointer = Sim32GetVDMPointer(((getDS() << 16) | getSI()),
0,
(UCHAR) (getMSW() & MSW_PE)
);
if (!ThreadSetDebugContext((PULONG) RegisterPointer))
{
ULONG ClearDebugRegisters[6] = {0, 0, 0, 0, 0, 0};
//
// an error occurred. Reset everything to zero
//
ThreadSetDebugContext (&ClearDebugRegisters[0]);
setCF(1);
}
}