From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/mvdm/dpmi32/i386/dpmi386.c | 386 ++++++++++++++++++++++++++++++++++++ private/mvdm/dpmi32/i386/dpmimem.c | 266 +++++++++++++++++++++++++ private/mvdm/dpmi32/i386/dpmimisc.c | 71 +++++++ 3 files changed, 723 insertions(+) create mode 100644 private/mvdm/dpmi32/i386/dpmi386.c create mode 100644 private/mvdm/dpmi32/i386/dpmimem.c create mode 100644 private/mvdm/dpmi32/i386/dpmimisc.c (limited to 'private/mvdm/dpmi32/i386') diff --git a/private/mvdm/dpmi32/i386/dpmi386.c b/private/mvdm/dpmi32/i386/dpmi386.c new file mode 100644 index 000000000..19c9d678c --- /dev/null +++ b/private/mvdm/dpmi32/i386/dpmi386.c @@ -0,0 +1,386 @@ +/*++ + +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 +#include +#include + + +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); + } + +} diff --git a/private/mvdm/dpmi32/i386/dpmimem.c b/private/mvdm/dpmi32/i386/dpmimem.c new file mode 100644 index 000000000..00eada990 --- /dev/null +++ b/private/mvdm/dpmi32/i386/dpmimem.c @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + name-of-module-filename + +Abstract: + + This module contains the code for actually allocating memory for dpmi. + It uses the same suballocation pool as the xms code + +Author: + + Dave Hastings (daveh) creation-date 09-Feb-1994 + +Notes: + + These functions claim to return NTSTATUS. This is for commonality on + x86 where we actually have an NTSTATUS to return. For this file, we + simply logically invert the bool and return that. Callers of these + functions promise not to attach significance to the return values other + than STATUS_SUCCESS. + +Revision History: + + +--*/ +#include "precomp.h" +#pragma hdrstop +#include +#include +#include + + +NTSTATUS +DpmiAllocateVirtualMemory( + PVOID *Address, + PULONG Size + ) +/*++ + +Routine Description: + + This routine allocates a chunk of extended memory for dpmi. + +Arguments: + + Address -- Supplies a pointer to the Address. This is filled in + if the allocation is successfull + Size -- Supplies the size to allocate + +Return Value: + + STATUS_SUCCESS if successfull. + +--*/ +{ + return NtAllocateVirtualMemory( + NtCurrentProcess(), + Address, + 0L, + Size, + MEM_COMMIT, + PAGE_READWRITE + ); +} + +NTSTATUS +DpmiFreeVirtualMemory( + PVOID *Address, + PULONG Size + ) +/*++ + +Routine Description: + + This function frees memory for dpmi. It is returned to the suballocation + pool. + +Arguments: + + Address -- Supplies the address of the block to free + Size -- Supplies the size of the block to free + +Return Value: + + STATUS_SUCCESS if successful +--*/ +{ + return NtFreeVirtualMemory( + NtCurrentProcess(), + Address, + Size, + MEM_RELEASE + ); + +} + +BOOL +DpmiReallocateVirtualMemory( + PVOID OldAddress, + ULONG OldSize, + PVOID *NewAddress, + PULONG NewSize + ) +/*++ + +Routine Description: + + This function reallocates a block of memory for DPMI. + +Arguments: + + OldAddress -- Supplies the original address for the block + OldSize -- Supplies the original size for the address + NewAddress -- Supplies the pointer to the place to return the new + address + NewSize -- Supplies the new size + +Return Value: + + STATUS_SUCCESS if successfull +--*/ +{ + ULONG SizeChange; + ULONG BlockAddress; + ULONG NewPages, OldPages; + NTSTATUS Status; + + #define FOUR_K (1024 * 4) + + NewPages = (*NewSize + FOUR_K - 1) / FOUR_K; + OldPages = (OldSize + FOUR_K - 1) / FOUR_K; + + if ((NewPages == OldPages) || (NewPages < OldPages)) { + *NewAddress = OldAddress; + return STATUS_SUCCESS; + } + + BlockAddress = 0; + Status = NtAllocateVirtualMemory( + NtCurrentProcess(), + (PVOID)&BlockAddress, + 0L, + NewSize, + MEM_COMMIT, + PAGE_READWRITE + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n"); +#endif + return Status; + } + + *NewAddress = (PVOID) BlockAddress; + // + // Copy data to new block (choose smaller of the two sizes) + // + if (*NewSize > OldSize) { + SizeChange = OldSize; + } else { + SizeChange = *NewSize; + } + + CopyMemory((PVOID)BlockAddress, OldAddress, SizeChange); + + // + // Free up the old block + // + BlockAddress = (ULONG) OldAddress; + SizeChange = OldSize; + NtFreeVirtualMemory( + NtCurrentProcess(), + (PVOID)&(OldAddress), + &SizeChange, + MEM_RELEASE + ); + + return Status; +} + +VOID +DpmiGetMemoryInfo( + VOID + ) +/*++ + +Routine Description: + + This routine returns information about memory to the dos extender + +Arguments: + + None + +Return Value: + + None. + +--*/ +{ + MEMORYSTATUS MemStatus; + PDPMIMEMINFO MemInfo; + DWORD dwLargestFree; + + // + // Get a pointer to the return structure + // + MemInfo = (PDPMIMEMINFO)Sim32GetVDMPointer( + ((ULONG)getES()) << 16, + 1, + TRUE + ); + + (CHAR *)MemInfo += (*GetDIRegister)(); + + // + // Initialize the structure + // + RtlFillMemory(MemInfo, sizeof(DPMIMEMINFO), 0xFF); + + // + // Get the information on memory + // + MemStatus.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&MemStatus); + + // + // Return the information + // + + // + // Calculate the largest free block. This information is not returned + // by NT, so we take a percentage based on the allowable commit charge for + // the process. This is really what dwAvailPageFile is. But we limit + // that value to a maximum of 15meg, since some apps (e.g. pdox45.dos) + // can't handle more. + // + + // Filled in MaxUnlocked,MaxLocked,UnlockedPages fields in this structute. + // Director 4.0 get completlely confused if these fields are -1. + // MaxUnlocked is correct based on LargestFree. The other two are fake + // and match values on a real WFW machine. I have no way of making them + // any better than this at this point. Hell, it makes director happy. + // + // sudeepb 01-Mar-1995. + + dwLargestFree = (((MemStatus.dwAvailPageFile*4)/5)/4096)*4096; + + MemInfo->LargestFree = (dwLargestFree < 15*ONE_MB) ? + dwLargestFree : 15*ONE_MB; + + MemInfo->MaxUnlocked = MemInfo->LargestFree/4096; + MemInfo->MaxLocked = 0xb61; + MemInfo->AddressSpaceSize = MemStatus.dwTotalVirtual / 4096; + MemInfo->UnlockedPages = 0xb68; + MemInfo->FreePages = MemStatus.dwAvailPhys / 4096; + MemInfo->PhysicalPages = MemStatus.dwTotalPhys / 4096; + MemInfo->FreeAddressSpace = MemStatus.dwAvailVirtual / 4096; + MemInfo->PageFileSize = MemStatus.dwTotalPageFile / 4096; + +} diff --git a/private/mvdm/dpmi32/i386/dpmimisc.c b/private/mvdm/dpmi32/i386/dpmimisc.c new file mode 100644 index 000000000..22b741c1d --- /dev/null +++ b/private/mvdm/dpmi32/i386/dpmimisc.c @@ -0,0 +1,71 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + dpmimisc.c + +Abstract: + + This module contains misc 386 specific dpmi functions. + +Author: + + Dave Hastings (daveh) creation-date 09-Feb-1994 + +Revision History: + + +--*/ + +#include "precomp.h" +#pragma hdrstop +#include "softpc.h" +#include "stdio.h" + +VOID +DpmiDpmiInUse( + VOID + ) +/*++ + +Routine Description: + + This routine does not do anything on x86 + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + +} + +VOID +DpmiDpmiNoLongerInUse( + VOID + ) +/*++ + +Routine Description: + + This routine does not do anything on x86 + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + +} -- cgit v1.2.3