windows-nt/Source/XPSP1/NT/base/mvdm/dpmi32/i386/dpmi386.c

307 lines
6.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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>
#include <nt_vdd.h>
BOOL
DpmiSetX86Descriptor(
USHORT SelStart,
USHORT SelCount
)
/*++
Routine Description:
This function puts descriptors into the real LDT. It uses the client's
LDT as a source for the descriptor data.
Arguments:
SelStart - The first selector in the block of selectors to set
SelCount - The number of selectors to set
Return Value:
This function returns TRUE if successful, FALSE otherwise
--*/
{
LDT_ENTRY UNALIGNED *Descriptors = &Ldt[SelStart>>3];
PPROCESS_LDT_INFORMATION LdtInformation = NULL;
NTSTATUS Status;
ULONG ulLdtEntrySize;
ULONG Selector0,Selector1;
ulLdtEntrySize = SelCount * sizeof(LDT_ENTRY);
//
// If there are only 2 descriptors, set them the fast way
//
Selector0 = (ULONG)SelStart;
if ((SelCount <= 2) && (Selector0 != 0)) {
VDMSET_LDT_ENTRIES_DATA ServiceData;
if (SelCount == 2) {
Selector1 = SelStart + sizeof(LDT_ENTRY);
} else {
Selector1 = 0;
}
ServiceData.Selector0 = Selector0;
ServiceData.Entry0Low = *((PULONG)(&Descriptors[0]));
ServiceData.Entry0Hi = *((PULONG)(&Descriptors[0]) + 1);
ServiceData.Selector1 = Selector1;
ServiceData.Entry1Low = *((PULONG)(&Descriptors[1]));
ServiceData.Entry1Hi = *((PULONG)(&Descriptors[1]) + 1);
Status = NtVdmControl(VdmSetLdtEntries, &ServiceData);
if (NT_SUCCESS(Status)) {
return TRUE;
}
return FALSE;
}
LdtInformation = malloc(sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize);
if (!LdtInformation ) {
return FALSE;
} else {
VDMSET_PROCESS_LDT_INFO_DATA ServiceData;
LdtInformation->Start = SelStart;
LdtInformation->Length = ulLdtEntrySize;
CopyMemory(
&(LdtInformation->LdtEntries),
Descriptors,
ulLdtEntrySize
);
ServiceData.LdtInformation = LdtInformation;
ServiceData.LdtInformationLength = sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize;
Status = NtVdmControl(VdmSetProcessLdtInfo, &ServiceData);
if (!NT_SUCCESS(Status)) {
VDprint(
VDP_LEVEL_ERROR,
("DPMI: Failed to set selectors %lx\n", Status)
);
free(LdtInformation);
return FALSE;
}
free(LdtInformation);
return TRUE;
}
}
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);
}
PVOID
VdmMapFlat(
WORD selector,
ULONG offset,
VDM_MODE mode
)
/*++
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.
--*/
{
PUCHAR ReturnPointer;
if (mode == VDM_PM) {
if (selector != 40) {
selector &= ~7;
ReturnPointer = (PUCHAR)FlatAddress[selector >> 3] + offset;
return ReturnPointer;
// Selector 40
} else {
ReturnPointer = (PUCHAR)0x400 + (offset & 0xFFFF);
}
// Real Mode
} else {
ReturnPointer = (PUCHAR)((((ULONG)selector) << 4) + (offset & 0xFFFF));
}
return ReturnPointer;
}
BOOL
DpmiSetDebugRegisters(
PULONG RegisterPointer
)
/*++
Routine Description:
This routine is called by dpmi when an app has issued DPMI debug commands.
The six doubleword pointed to by the input parameter are the desired values
for the real x86 hardware debug registers. This routine lets
ThreadSetDebugContext() do all the work.
Arguments:
None
Return Value:
None.
--*/
{
BOOL bReturn = TRUE;
if (!ThreadSetDebugContext(RegisterPointer))
{
ULONG ClearDebugRegisters[6] = {0, 0, 0, 0, 0, 0};
//
// an error occurred. Reset everything to zero
//
ThreadSetDebugContext (&ClearDebugRegisters[0]);
bReturn = FALSE;
}
return bReturn;
}
BOOL
DpmiGetDebugRegisters(
PULONG RegisterPointer
)
/*++
Routine Description:
This routine is called by DOSX when an app has issued DPMI debug commands.
The six doubleword pointed to by the input parameter are the desired values
for the real x86 hardware debug registers. This routine lets
ThreadGetDebugContext() do all the work.
Arguments:
None
Return Value:
None.
--*/
{
return (ThreadGetDebugContext(RegisterPointer));
}