209 lines
5.6 KiB
C
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
|
|
}
|