windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wkmem.c
2020-09-26 16:20:57 +08:00

209 lines
5.6 KiB
C

/*++
*
* WOW v1.0
*
* Copyright (c) 1992, Microsoft Corporation
*
* WKMEM.C
* WOW32 KRNL386 Virtual Memory Management Functions
*
* History:
* Created 3-Dec-1992 by Matt Felton (mattfe)
*
--*/
#include "precomp.h"
#pragma hdrstop
#include "memapi.h"
MODNAME(wkman.c);
// some apps free global memory
LPVOID glpvDelayFree[4]; // which is in turn freed by kernel as the asks it
DWORD gdwDelayFree; // but then app comes back and tries to access it
// this is our hack variables to accomodate them
ULONG FASTCALL WK32VirtualAlloc(PVDMFRAME pFrame)
{
PVIRTUALALLOC16 parg16;
ULONG lpBaseAddress;
#ifndef i386
NTSTATUS Status;
#endif
GETARGPTR(pFrame, sizeof(VIRTUALALLOC16), parg16);
#ifndef i386
Status = VdmAllocateVirtualMemory(&lpBaseAddress,
parg16->cbSize,
TRUE);
if (!NT_SUCCESS(Status)) {
if (Status == STATUS_NOT_IMPLEMENTED) {
#endif // i386
lpBaseAddress = (ULONG) VirtualAlloc((LPVOID)parg16->lpvAddress,
parg16->cbSize,
parg16->fdwAllocationType,
parg16->fdwProtect);
#ifndef i386
} else {
lpBaseAddress = 0;
}
}
#endif // i386
#ifdef i386
//BUGBUG we need to either get this working on the new emulator, or
// fix the problem the "other" way, by letting the app fault and
// zap in just enough 'WOW's to avoid the problem.
if (lpBaseAddress) {
// Virtual alloc Zero's the allocated memory. We un-zero it by
// filling in with ' WOW'. This is required for Lotus Improv.
// When no printer is installed, Lotus Improv dies with divide
// by zero error (while opening the expenses.imp file) because
// it doesn't initialize a relevant portion of its data area.
//
// So we decided that this a convenient place to initialize
// the memory to a non-zero value.
// - Nanduri
//
// Dbase 5.0 for windows erroneously loops through (past its valid
// data) its data buffer till it finds a '\0' at some location -
// Most of the time the loop terminates before it reaches the segment
// limit. However if the block that was allocated is a 'fresh' block' ie
// the block is filled with ' WOW' it never finds a NULL in the buffer
// and thus loops past the segment limit to its death
//
// So we initialize the buffer with '\0WOW' instead of ' WOW'.
// - Nanduri
WOW32ASSERT((parg16->cbSize % 4) == 0); // DWORD aligned?
RtlFillMemoryUlong((PVOID)lpBaseAddress, parg16->cbSize, (ULONG)'\0WOW');
}
#endif
FREEARGPTR(parg16);
return (lpBaseAddress);
}
ULONG FASTCALL WK32VirtualFree(PVDMFRAME pFrame)
{
PVIRTUALFREE16 parg16;
ULONG fResult;
#ifndef i386
NTSTATUS Status;
#endif
// Delay free
// some apps, ntbug 90849 CreateScreenSavers Quick and Easy
// free 16 bit global heap then try to access it again
// but kernel has already freed/compacted global heap
// this will delay that process for a while (something similar to DisableHeapLookAside in nt
// Millenium implemented something similar
// -jarbats
if( NULL != glpvDelayFree[gdwDelayFree])
{
#ifndef i386
Status = VdmFreeVirtualMemory( glpvDelayFree[gdwDelayFree]);
fResult = NT_SUCCESS(Status);
if (Status == STATUS_NOT_IMPLEMENTED) {
#endif // i386
fResult = VirtualFree(glpvDelayFree[gdwDelayFree],
0,
MEM_RELEASE);
#ifndef i386
}
#endif // i386
}
GETARGPTR(pFrame, sizeof(VIRTUALFREE16), parg16);
glpvDelayFree[gdwDelayFree] = (LPVOID) parg16->lpvAddress;
gdwDelayFree++;
gdwDelayFree &= 3;
FREEARGPTR(parg16);
return (TRUE);
}
#if 0
ULONG FASTCALL WK32VirtualLock(PVDMFRAME pFrame)
{
PVIRTUALLOCK16 parg16;
BOOL fResult;
WOW32ASSERT(FALSE); //BUGBUG we don't appear to ever use this function
GETARGPTR(pFrame, sizeof(VIRTUALLOCK16), parg16);
fResult = VirtualLock((LPVOID)parg16->lpvAddress,
parg16->cbSize);
FREEARGPTR(parg16);
return (fResult);
}
ULONG FASTCALL WK32VirtualUnLock(PVDMFRAME pFrame)
{
PVIRTUALUNLOCK16 parg16;
BOOL fResult;
WOW32ASSERT(FALSE); //BUGBUG we don't appear to ever use this function
GETARGPTR(pFrame, sizeof(VIRTUALUNLOCK16), parg16);
fResult = VirtualUnlock((LPVOID)parg16->lpvAddress,
parg16->cbSize);
FREEARGPTR(parg16);
return (fResult);
}
#endif
ULONG FASTCALL WK32GlobalMemoryStatus(PVDMFRAME pFrame)
{
PGLOBALMEMORYSTATUS16 parg16;
LPMEMORYSTATUS pMemStat;
GETARGPTR(pFrame, sizeof(GLOBALMEMORYSTATUS16), parg16);
GETVDMPTR(parg16->lpmstMemStat, 32, pMemStat);
GlobalMemoryStatus(pMemStat);
//
// if /3GB switch is enabled in boot.ini, GlobalmemoryStatus may return
// 0x7fffffff dwTotalVirtual and dwAvailVirtal. This will confuse some apps
// in thinking something is wrong.
//
if (pMemStat->dwAvailVirtual == 0x7fffffff &&
pMemStat->dwTotalVirtual == 0x7fffffff ) { // yes we need to check dwTotalVirtual too
pMemStat->dwAvailVirtual -= 0x500000;
}
FREEVDMPTR(pMemStat);
FREEARGPTR(parg16);
return 0; // unused
}