/*++
 *
 *  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);


LPVOID FASTCALL WK32VirtualAlloc(PVDMFRAME pFrame)
{
    PVIRTUALALLOC16 parg16;
    LPVOID lpBaseAddress;
#ifndef i386
    NTSTATUS Status;
#endif

    GETARGPTR(pFrame, sizeof(VIRTUALALLOC16), parg16);


#ifndef i386
    Status = VdmAllocateVirtualMemory((PULONG)&lpBaseAddress,
                                      parg16->cbSize,
                                      TRUE);

    if (!NT_SUCCESS(Status)) {

        if (Status == STATUS_NOT_IMPLEMENTED) {
#endif // i386

            lpBaseAddress = VirtualAlloc((LPVOID)parg16->lpvAddress,
                                            parg16->cbSize,
                                            parg16->fdwAllocationType,
                                            parg16->fdwProtect);


#ifndef i386
        } else {

            lpBaseAddress = NULL;
        }

    }
#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(lpBaseAddress, parg16->cbSize, (ULONG)'\0WOW');
    }
#endif

    FREEARGPTR(parg16);
    return (lpBaseAddress);
}

BOOL FASTCALL WK32VirtualFree(PVDMFRAME pFrame)
{
    PVIRTUALFREE16 parg16;
    BOOL fResult;
#ifndef i386
    NTSTATUS Status;
#endif

    GETARGPTR(pFrame, sizeof(VIRTUALFREE16), parg16);

#ifndef i386
    Status = VdmFreeVirtualMemory((ULONG)parg16->lpvAddress);
    fResult = NT_SUCCESS(Status);

    if (Status == STATUS_NOT_IMPLEMENTED) {
#endif // i386

        fResult = VirtualFree((LPVOID)parg16->lpvAddress,
                                 parg16->cbSize,
                                 parg16->fdwFreeType);


#ifndef i386
    }
#endif // i386

    FREEARGPTR(parg16);
    return (fResult);
}


#if 0
BOOL 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);
}

BOOL 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


VOID FASTCALL WK32GlobalMemoryStatus(PVDMFRAME pFrame)
{
    PGLOBALMEMORYSTATUS16 parg16;
    LPMEMORYSTATUS pMemStat;

    GETARGPTR(pFrame, sizeof(GLOBALMEMORYSTATUS16), parg16);
    GETVDMPTR(parg16->lpmstMemStat, 32, pMemStat);

    GlobalMemoryStatus(pMemStat);

    FREEVDMPTR(pMemStat);
    FREEARGPTR(parg16);
}
