|
|
/*++
* * 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
}
|