/*++
 *
 *  WOW v1.0
 *
 *  Copyright (c) 1991, Microsoft Corporation
 *
 *  WCALL32.C
 *  WOW32 16-bit resource support
 *
 *  History:
 *  Created 11-Mar-1991 by Jeff Parsons (jeffpar)
--*/


#include "precomp.h"
#pragma hdrstop

MODNAME(wcall32.c);

//
// the 16-bit local handles are treated as 32-bit quantities.
// the low word contains the 16-bit handle and the high word
// contains the data segment for the block.
// when we do a callback to WOW16LocalAlloc it will
// return the DS in the high word (which is normally unused).
// on subsequent callbacks to realloc/lock/unlock/size/free
// the 16-bit code sets the DS to this value.
//


HANDLE APIENTRY W32LocalAlloc(DWORD dwFlags, DWORD dwBytes, HANDLE hInstance)
{

    //
    // If hInstance is not ours, then make Win32 call and return the
    // result to USER.
    //

    if (LOWORD (hInstance) == 0) {
        return (LocalAlloc(dwFlags, dwBytes));
    }


#if !defined(i386)
    if (dwBytes != 0)
        dwBytes += 4;
#endif

    return LocalAlloc16((WORD)dwFlags, (INT)dwBytes, hInstance);
}


HANDLE APIENTRY W32LocalReAlloc(HANDLE hMem, DWORD dwBytes, DWORD dwFlags, HANDLE hInstance)
{

    //
    // If hInstance is not ours, then make Win32 call and return the
    // result to USER.
    //

    if (LOWORD (hInstance) == 0) {
        return (LocalReAlloc(hMem, dwBytes, dwFlags));
    }



#if !defined(i386)
    if (dwBytes != 0)
        dwBytes += 4;
#endif

    return LocalReAlloc16(hMem, (INT)dwBytes, (WORD)dwFlags);
}

LPSTR  APIENTRY W32LocalLock(HANDLE hMem, HANDLE hInstance)
{
    VPVOID vp;

    //
    // If hInstance is not ours, then make Win32 call and return the
    // result to USER.
    //

    if (LOWORD (hInstance) == 0) {
        return (LocalLock(hMem));
    }

    if (vp = LocalLock16(hMem)) {
        return (LPSTR)VDMPTR(vp, 0);
    }
    else
        return NULL;
}




BOOL APIENTRY W32LocalUnlock(HANDLE hMem, HANDLE hInstance)
{

    //
    // If hInstance is not ours, then make Win32 call and return the
    // result to USER.
    //

    if (LOWORD (hInstance) == 0) {
        return (LocalUnlock(hMem));
    }


    return LocalUnlock16(hMem);
}


DWORD  APIENTRY W32LocalSize(HANDLE hMem, HANDLE hInstance)
{
    DWORD   dwSize;



    //
    // If hInstance is not ours, then make Win32 call and return the
    // result to USER.
    //

    if (LOWORD (hInstance) == 0) {
        return (LocalSize(hMem));
    }



    dwSize = LocalSize16(hMem);

#if !defined(i386)
    if (dwSize >= 4)
        dwSize -= 4;
#endif

    return dwSize;
}


HANDLE APIENTRY W32LocalFree(HANDLE hMem, HANDLE hInstance)
{

    //
    // If hInstance is not ours, then make Win32 call and return the
    // result to USER.
    //

    if (LOWORD (hInstance) == 0) {
        return (LocalFree(hMem));
    }

    return LocalFree16(hMem);
}

ULONG APIENTRY W32GetExpWinVer(HANDLE hInst)
{
    PARM16 Parm16;
    ULONG ul;

    // makes a direct call to krnl286:GetExpWinVer
    //

    if (LOWORD((DWORD)hInst) == (WORD) NULL) {

        //
        // Window is created by a 32 bit DLL, which is
        // linked to NTVDM process. So, we should not
        // passs it to the 16 bit kernel.
        //

        return (WOWRtlGetExpWinVer(hInst));
    }
    else {
        LPBYTE lpNewExeHdr;
        VPVOID vp = (DWORD)hInst & 0xffff0000;

        GETMISCPTR(vp, lpNewExeHdr);
        if (lpNewExeHdr) {
            ul = MAKELONG(*(PWORD16)&lpNewExeHdr[NE_LOWINVER_OFFSET],
                          (*(PWORD16)&lpNewExeHdr[NE_HIWINVER_OFFSET] &
                                                           FLAG_NE_PROPFONT));
        }
        else {
            Parm16.WndProc.wParam = LOWORD(hInst);
            CallBack16(RET_GETEXPWINVER, &Parm16, 0, &ul );
        }
        return ul;
    }


}


/*
 *  VOID W32InitDlg(HWND hDlg, LONG lParam);
 *
 *  this function is called by USER during dialog creation
 *  before any messages are sent.
 */

DWORD    APIENTRY W32InitDlg(HWND hDlg, LONG lParam)
{
    register PWW pww;

    if (!lParam) {
        LOGDEBUG(2,("    Warning: W32InitDlg called with null lParam\n"));
        return (DWORD)0;
    }

    // FindPWW was here

    if (!(pww = (PWW) GetWindowLong(hDlg, GWL_WOWWORDS))) {
        LOGDEBUG(0,("    W32InitDlg ERROR: cannot create alias for window %08lx\n", hDlg));
        WOW32ASSERT(pww);
        return (DWORD)0;
    }

    // the reason we need the hmap.vpfnDlgProc field is because some
    // dialogs have both a window proc and a dialog proc.  this happens
    // when the dialog template has a class in it and the app also
    // passes a dialog proc to CreateDialogxxx()
    //

    SETWL(hDlg, GWL_WOWiClassAndflState,
            MAKECLASSANDSTATE(WOWCLASS_DIALOG, WWSTATE_ICLASSISSET));
    SETWL(hDlg, GWL_WOWvpfnDlgProc, ((PDLGDATA)lParam)->vpfnDlgProc);

    return ((PDLGDATA)lParam)->dwUserInitParam;
}


WORD    APIENTRY W32GlobalAlloc16(UINT uFlags, DWORD dwBytes)
{
    return HIWORD(GlobalAllocLock16((WORD)uFlags, dwBytes, NULL));
}


VOID    APIENTRY W32GlobalFree16(WORD selector)
{
    GlobalUnlockFree16(MAKELONG(0, selector));
    return;
}



int     APIENTRY W32EditNextWord (LPSZ lpszEditText, int ichCurrentWord,
                                  int cbEditText, int action, DWORD dwProc16)
{
    PARM16  Parm16;
    ULONG   lReturn = 0;
    PBYTE   lpstr16;
    VPVOID  vpstr16;
    VPVOID  vpfn;

    if (vpstr16 = malloc16 (cbEditText)) {
        GETMISCPTR (vpstr16, lpstr16);
        if (lpstr16) {
            lstrcpy (lpstr16, lpszEditText);

            vpfn = dwProc16 & WNDPROC_MASK;

            //
            // if the actual selector had the high bit on then we turned off
            // bit 2 of the selector (the LDT bit, which will always be on)
            //

            if (!(vpfn & WOWCLASS_VIRTUAL_NOT_BIT31)) {
                vpfn |= (WNDPROC_WOW | WOWCLASS_VIRTUAL_NOT_BIT31);
            }

            Parm16.WordBreakProc.action = GETINT16(action);
            Parm16.WordBreakProc.cbEditText = GETINT16(cbEditText);
            Parm16.WordBreakProc.ichCurrentWord = GETINT16(ichCurrentWord);
            Parm16.WordBreakProc.lpszEditText = vpstr16;

            CallBack16(RET_SETWORDBREAKPROC, &Parm16, vpfn, (PVPVOID)&lReturn);

            FREEMISCPTR (lpstr16);
        }

        free16(vpstr16);
    }

    return (INT32(LOWORD(lReturn)));
}


/***************************************************************************\
* WOWRtlGetExpWinVer
*
* Returns the expected windows version, in the same format as Win3.1's
* GetExpWinVer(). This takes it out of the module header.
*
* 09-9-92 ChandanC       Created.
\***************************************************************************/

DWORD WOWRtlGetExpWinVer(
    HANDLE hmod)
{
    PIMAGE_NT_HEADERS pnthdr;
    DWORD dwMajor = 3;
    DWORD dwMinor = 0xA;

    if (hmod != NULL) {
        try {
            pnthdr = (PIMAGE_NT_HEADERS)RtlImageNtHeader((PVOID)hmod);
            dwMajor = pnthdr->OptionalHeader.MajorSubsystemVersion;
            dwMinor = pnthdr->OptionalHeader.MinorSubsystemVersion;
        } except (EXCEPTION_EXECUTE_HANDLER) {
            dwMajor = 3;        // just to be safe
            dwMinor = 0xA;
        }
    }

// !!! HACK until linker is fixed!!! 05-Aug-1992 Bug #3211
if (((dwMajor == 3) && (dwMinor == 1)) || (dwMajor == 1)) {
    dwMajor = 0x3;
    dwMinor = 0xA;
}


    /*
     * Return this is a win3.1 compatible format:
     *
     * 0x030A == win3.1
     * 0x0300 == win3.0
     * 0x0200 == win2.0, etc.
     *
     */

    return (DWORD)MAKELONG(MAKEWORD((BYTE)dwMinor, (BYTE)dwMajor), 0);
}
