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.
 
 
 
 
 
 

312 lines
7.1 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
dpmiselr.c
Abstract:
This is the code for maintaining descriptor data for dpmi32.
Author:
Dave Hart (davehart) 11-Apr-1993
Notes:
Revision History:
09-Feb-1994 (daveh)
Moved here from not386.c.
31-Jul-1995 (neilsa)
Merged with x86 source
12-Dec-1995 (neilsa)
Wrote VdmAddDescriptorMapping(), GetDescriptorMapping
--*/
#include "precomp.h"
#pragma hdrstop
#include "softpc.h"
#include "malloc.h"
#if DBG
USHORT CheckValue=0;
#endif
#ifndef i386
ULONG
GetDescriptorMapping(
USHORT Sel,
ULONG LdtBase
);
typedef struct _DESC_MAPPING {
USHORT Sel;
USHORT SelCount;
ULONG LdtBase;
ULONG FlatBase;
struct _DESC_MAPPING* pNext;
} DESC_MAPPING, *PDESC_MAPPING;
PDESC_MAPPING pDescMappingHead = NULL;
#endif // i386
//
// Imported functions from SoftPC world
//
extern VOID EnableEmulatorIretHooks(VOID);
extern VOID DisableEmulatorIretHooks(VOID);
BOOL
DpmiSetX86Descriptor(
LDT_ENTRY *Descriptors,
USHORT registerAX,
USHORT registerCX
);
VOID
DpmiSetDescriptorEntry(
VOID
)
/*++
Routine Description:
This function is stolen from i386\dpmi386.c and brain-damaged to
only maintain the FlatAddress array.
Arguments:
None
Return Value:
None.
--*/
{
LDT_ENTRY UNALIGNED *Descriptors;
USHORT i;
ULONG Base;
ULONG Limit;
USHORT registerCX;
USHORT registerAX;
registerAX = getAX();
if (registerAX % 8){
return;
}
Descriptors = (PLDT_ENTRY)Sim32GetVDMPointer(((getES() << 16) | getBX()),
0,
(UCHAR) (getMSW() & MSW_PE));
registerCX = getCX();
for (i = 0; i < registerCX; i++) {
// form Base and Limit values
Base = Descriptors[i].BaseLow | (Descriptors[i].HighWord.Bytes.BaseMid << 16) |
(Descriptors[i].HighWord.Bytes.BaseHi << 24);
Limit = Descriptors[i].LimitLow | (Descriptors[i].HighWord.Bits.LimitHi << 16);
Limit = (Limit << (12 * Descriptors[i].HighWord.Bits.Granularity)) +
Descriptors[i].HighWord.Bits.Granularity * 0xFFF;
//
// Do NOT remove the following code. There are several apps that
// choose arbitrarily high limits for theirs selectors. This works
// under windows 3.1, but NT won't allow us to do that.
// The following code fixes the limits for such selectors.
// Note: if the base is > 0x7FFEFFFF, the selector set will fail
//
if ((Limit > 0x7FFEFFFF) || (Base + Limit > 0x7FFEFFFF)) {
Limit = 0x7FFEFFFF - (Base + 0xFFF);
if (!Descriptors[i].HighWord.Bits.Granularity) {
Descriptors[i].LimitLow = (USHORT)(Limit & 0x0000FFFF);
Descriptors[i].HighWord.Bits.LimitHi =
(Limit & 0x000f0000) >> 16;
} else {
Descriptors[i].LimitLow = (USHORT)((Limit >> 12) & 0xFFFF);
Descriptors[i].HighWord.Bits.LimitHi =
((Limit >> 12) & 0x000f0000) >> 16;
}
}
if ((registerAX >> 3) != 0) {
#ifndef i386
{
ULONG BaseOrig = Base;
Base = GetDescriptorMapping(registerAX+i*8, Base);
if (BaseOrig == Base) {
Base += (ULONG)IntelBase;
}
}
#endif
FlatAddress[(registerAX >> 3) + i] = Base;
#if DBG
SelectorLimit[(registerAX >> 3) + i] = Limit;
#endif
}
}
#ifdef i386
if (!DpmiSetX86Descriptor(Descriptors, registerAX, registerCX)) {
return;
}
#endif
setAX(0);
#ifndef i386
#if DBG
//
// debugbug
//
if (registerAX == CheckValue) {
force_yoda();
}
#endif
#endif // not i386
}
#ifndef i386
BOOL
VdmAddDescriptorMapping(
USHORT SelectorStart,
USHORT SelectorCount,
ULONG LdtBase,
ULONG Flat
)
/*++
Routine Description:
This function was added to support the DIB.DRV implementation on RISC.
When an app uses DIB.DRV, then the situation arises where the Intel
linear base address + the flat address of the start of the Intel address
space does NOT equal the flat address of the memory. This happens when
the VdmAddVirtualMemory() api is used to set up an additional layer of
indirection for memory addressing in the emulator.
But there is more to the story. When app wants to use CreateDIBSection
via WinG we also need to map selectors, thus this routine should not
depend upon DpmiSetDesctriptorEntry being called afterwards. Thus, we go
and zap the flat address table with the new address.
Arguments:
SelectorStart, Count - range of selectors involved in the mapping
LdtBase - Intel base of start of range
Flat - True flat address base to be used for these selectors
Return Value:
This function returns TRUE on success, or FALSE for failure (out of mem)
--*/
{
PDESC_MAPPING pdm;
USHORT i;
if ((pdm = (PDESC_MAPPING) malloc(sizeof (DESC_MAPPING))) == NULL)
return FALSE;
pdm->Sel = SelectorStart &= ~7;
pdm->SelCount = SelectorCount;
pdm->LdtBase = LdtBase;
pdm->FlatBase = Flat;
pdm->pNext = pDescMappingHead;
pDescMappingHead = pdm;
// this code does what essentially desctribed in comment above
for (i = 0; i < SelectorCount; ++i) {
FlatAddress[(SelectorStart >> 3) + i] = Flat + 65536 * i;
}
return TRUE;
}
ULONG
GetDescriptorMapping(
USHORT sel,
ULONG LdtBase
)
/*++
Routine Description:
Arguments:
sel - the selector for which the base should be returned
LdtBase - the base for this selector as is set currently in the LDT
Return Value:
The true flat address for the specified selector.
--*/
{
PDESC_MAPPING pdm, pdmprev;
ULONG Base = LdtBase;
sel &= ~7; // and off lower 3 bits
pdm = pDescMappingHead;
while (pdm) {
if ((sel >= pdm->Sel) && (sel < (pdm->Sel + pdm->SelCount*8))) {
//
// We found a mapping for this selector. Now check to see if
// the ldt base still matches the base when the mapping was
// created.
//
if (LdtBase == (pdm->LdtBase + 65536*((sel-pdm->Sel)/8))) {
//
// The mapping appears still valid. Return the remapped address
//
return (pdm->FlatBase + 65536*((sel-pdm->Sel)/8));
} else {
//
// The ldt base doesn't match the mapping, so the mapping
// must be obselete. Free the mapping here.
//
if (pdm == pDescMappingHead) {
//
// mapping is the first in the list
//
pDescMappingHead = pdm->pNext;
} else {
pdmprev->pNext = pdm->pNext;
}
free(pdm);
}
break;
}
pdmprev = pdm;
pdm = pdm->pNext;
}
return Base;
}
#endif i386