/******************************Module*Header*******************************\
* Module Name: wowuserp.h                                                  *
*                                                                          *
* Declarations of USER services provided to WOW.                           *
*                                                                          *
* Created: 03-Mar-1993                                                     *
* Author: John Colleran [johnc]                                            *
*                                                                          *
* Copyright (c) 1993-1998 Microsoft Corporation                            *
\**************************************************************************/

#include "w32w64.h"

#pragma pack(1)
typedef struct _NE_MODULE_SEG {
    USHORT ns_sector;
    USHORT ns_cbseg;
    USHORT ns_flags;
    USHORT ns_minalloc;
    USHORT ns_handle;
} NEMODULESEG;
typedef struct _NE_MODULE_SEG UNALIGNED *PNEMODULESEG;
#pragma pack()


// Shared WOW32 prototypes called by USER32.
typedef HLOCAL  (WINAPI *PFNLALLOC)(UINT dwFlags, UINT dwBytes, HANDLE hInstance);
typedef HLOCAL  (WINAPI *PFNLREALLOC)(HLOCAL hMem, UINT dwBytes, UINT dwFlags, HANDLE hInstance, PVOID* ppv);
typedef LPVOID  (WINAPI *PFNLLOCK)(HLOCAL hMem, HANDLE hInstance);
typedef BOOL    (WINAPI *PFNLUNLOCK)(HLOCAL hMem, HANDLE hInstance);
typedef UINT    (WINAPI *PFNLSIZE)(HLOCAL hMem, HANDLE hInstance);
typedef HLOCAL  (WINAPI *PFNLFREE)(HLOCAL hMem, HANDLE hInstance);
typedef WORD    (WINAPI *PFN16GALLOC)(UINT flags, DWORD cb);
typedef VOID    (WINAPI *PFN16GFREE)(WORD h16Mem);
typedef DWORD   (WINAPI *PFNGETMODFNAME)(HANDLE hModule, LPTSTR lpszPath, DWORD cchPath);
typedef VOID    (WINAPI *PFNEMPTYCB)(VOID);
typedef DWORD   (WINAPI *PFNGETEXPWINVER)(HANDLE hModule);
typedef HANDLE  (WINAPI *PFNFINDA)(HANDLE hModule, LPCSTR lpName,  LPCSTR lpType,  WORD wLang);
typedef HANDLE  (WINAPI *PFNFINDW)(HANDLE hModule, LPCWSTR lpName, LPCWSTR lpType, WORD wLang);
typedef HANDLE  (WINAPI *PFNLOAD)(HANDLE hModule, HANDLE hResInfo);
typedef BOOL    (WINAPI *PFNFREE)(HANDLE hResData, HANDLE hModule);
typedef LPSTR   (WINAPI *PFNLOCK)(HANDLE hResData, HANDLE hModule);
typedef BOOL    (WINAPI *PFNUNLOCK)(HANDLE hResData, HANDLE hModule);
typedef DWORD   (WINAPI *PFNSIZEOF)(HANDLE hModule, HANDLE hResInfo);
typedef DWORD   (WINAPI *PFNWOWWNDPROCEX)(HWND hwnd, UINT uMsg, WPARAM uParam, LPARAM lParam, DWORD dw, PVOID adwWOW);
typedef BOOL    (WINAPI *PFNWOWDLGPROCEX)(HWND hwnd, UINT uMsg, WPARAM uParam, LPARAM lParam, DWORD dw, PVOID adwWOW);
typedef int     (WINAPI *PFNWOWEDITNEXTWORD)(LPSTR lpch, int ichCurrent, int cch, int code, DWORD dwProc16);
typedef VOID    (WINAPI *PFNWOWCBSTOREHANDLE)(WORD wFmt, WORD h16);
typedef WORD    (FASTCALL *PFNGETPROCMODULE16)(DWORD vpfn);
typedef VOID    (FASTCALL *PFNWOWMSGBOXINDIRECTCALLBACK)(DWORD vpfnCallback, LPHELPINFO lpHelpInfo);
typedef int     (WINAPI *PFNWOWILSTRCMP)(LPCWSTR lpString1, LPCWSTR lpString2);
typedef VOID    (FASTCALL *PFNWOWTELLWOWTHEHDLG)(HWND hDlg);

// Shared USER32 prototypes called by WOW32
typedef HWND    (WINAPI *PFNCSCREATEWINDOWEX)(DWORD dwExStyle, LPCTSTR lpClassName,
        LPCTSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID lpParam, DWORD Flags);
typedef VOID    (WINAPI *PFNDIRECTEDYIELD)(DWORD ThreadId);
typedef VOID    (WINAPI *PFNFREEDDEDATA)(HANDLE hDDE, BOOL fIgnorefRelease, BOOL fFreeTruelyGlobalObjects);
typedef LONG    (WINAPI *PFNGETCLASSWOWWORDS)(HINSTANCE hInstance, LPCTSTR pString);
typedef BOOL    (WINAPI *PFNINITTASK)(UINT dwExpWinVer, DWORD dwAppCompatFlags, LPCSTR lpszModName, LPCSTR lpszBaseFileName, DWORD hTaskWow, DWORD dwHotkey, DWORD idTask, DWORD dwX, DWORD dwY, DWORD dwXSize, DWORD dwYSize);
typedef ATOM    (WINAPI *PFNREGISTERCLASSWOWA)(PVOID lpWndClass, LPDWORD pdwWOWstuff);
typedef BOOL    (WINAPI *PFNREGISTERUSERHUNGAPPHANDLERS)(PFNW32ET pfnW32EndTask, HANDLE hEventWowExec);
typedef HWND    (WINAPI *PFNSERVERCREATEDIALOG)(HANDLE hmod, LPDLGTEMPLATE lpDlgTemplate, DWORD cb, HWND hwndOwner , DLGPROC pfnWndProc, LPARAM dwInitParam, UINT fFlags);
typedef HCURSOR (WINAPI *PFNSERVERLOADCREATECURSORICON)(HANDLE hmod, LPTSTR lpModName, DWORD dwExpWinVer, LPCTSTR lpName, DWORD cb, PVOID pcur, LPTSTR lpType, BOOL fClient);
typedef HMENU   (WINAPI *PFNSERVERLOADCREATEMENU)(HANDLE hMod, LPTSTR lpName, CONST LPMENUTEMPLATE pmt, DWORD cb, BOOL fCallClient);
typedef BOOL    (WINAPI *PFNWOWCLEANUP)(HANDLE hInstance, DWORD hTaskWow);
typedef BOOL    (WINAPI *PFNWOWMODULEUNLOAD)(HANDLE hModule);
typedef HWND    (WINAPI *PFNWOWFINDWINDOW)(LPCSTR lpClassName, LPCSTR lpWindowName);
typedef HBITMAP (WINAPI *PFNWOWLOADBITMAPA)(HINSTANCE hmod, LPCSTR lpName, LPBYTE pResData, DWORD cbResData);
typedef BOOL    (WINAPI *PFNWOWWAITFORMSGANDEVENT)(HANDLE hevent);
typedef BOOL    (WINAPI *PFNYIELDTASK)(VOID);
typedef DWORD   (WINAPI *PFNGETFULLUSERHANDLE)(WORD wHandle);
typedef DWORD   (WINAPI *PFNGETMENUINDEX)(HMENU hMenu, HMENU hSubMenu);
typedef WORD    (WINAPI *PFNWOWGETDEFWINDOWPROCBITS)(PBYTE pDefWindowProcBits, WORD cbDefWindowProcBits);
typedef VOID    (WINAPI *PFNFILLWINDOW)(HWND hwndParent, HWND hwnd, HDC hdc, HANDLE hBrush);

// other prototypes
typedef BOOL    (WINAPI *PFNWOWGLOBALFREEHOOK)(HGLOBAL hMem);


/*
 * MEASUREITEMSTRUCT itemWidth tag telling wow the itemData is a flat pointer
 */
#define MIFLAG_FLAT      0x464C4154

/*
 * CallWindowProc Bits
 */
#define WOWCLASS_RPL_MASK  0x00060000  // the LDT bits that store the 2 high bits
#define WNDPROC_WOWPROC     0xC0000000  // These bits for WOW Window Procs
#define WNDPROC_WOWMASK     0x3fffffff  // To mask off wow bits
#define WNDPROC_HANDLE      0xFFFF      // HIWORD(x) == 0xFFFF for handle

// USER needs a way to distinguish between a WOW and a Win32 window proc. We
// used to achieve this by always setting the MSB of a 16:16 address as 1 (and
// storing the MSB in the Table indicator bit of the LDT which is always 1). The
// MSB of a user mode flat address was guranteed to be never 1 as the user mode
// address space was limited to 2GB. Starting with NT 5.0, user mode address
// space is being increased to 3GB. This change breaks the above assumption
// that a 32bit user mode flat address will never have the MSB as 1.
// To work around this problem, WOW is going to use the  two bits of a
// 16:16 address instead of just one. We will set both these bits as 1 because
// with 3GB address space, the user mode flat addresses cannot have 11 as the
// first two bits. To achieve this, we will save the 2 most significant bits of
// the selector in the bit 1 and bit 2. We are able to do this because for WOW
// because both these bits have fixed values.
//
// SudeepB 21-Nov-1996

#ifndef _WIN64

// MarkWOWProc
// zero out the RPL bits
// get the high two bit in position where they have to be saved
// save the high bits and mark it a wow proc

#define MarkWOWProc(vpfnProc,result)                                  \
{                                                                     \
    ULONG temp1,temp2;                                                \
    temp1 = (ULONG)vpfnProc & ~WOWCLASS_RPL_MASK;                     \
    temp2 = ((ULONG)vpfnProc & WNDPROC_WOWPROC) >> 13;                \
    (ULONG)result = temp1 | temp2 | WNDPROC_WOWPROC;                  \
}

// UnMarkWOWProc
// mask off the marker bits
// get the saved bits to right places
// restore the saved bits and set the RPL field correctly

#define UnMarkWOWProc(vpfnProc,result)                     \
{                                                          \
    ULONG temp1,temp2;                                     \
    temp1 = (ULONG)vpfnProc & WNDPROC_WOWMASK;             \
    temp2 = ((ULONG)vpfnProc & WOWCLASS_RPL_MASK) << 13;   \
    result = temp1 | temp2 | WOWCLASS_RPL_MASK;            \
}

#define IsWOWProc(vpfnProc) (((ULONG)vpfnProc & WNDPROC_WOWPROC) == WNDPROC_WOWPROC)

#else

#define MarkWOWProc(vpfnProc,result)    DBG_UNREFERENCED_PARAMETER(vpfnProc)
#define UnMarkWOWProc(vpfnProc,result)  DBG_UNREFERENCED_PARAMETER(vpfnProc)
#define IsWOWProc(vpfnProc)             (FALSE)

#endif

/*
 * CreateWindow flags
 */
#define CW_FLAGS_ANSI       0x00000001

typedef struct tagAPFNWOWHANDLERSIN
{
    // In'ees - passed from WOW32 to USER32 and called by USER32
    PFNLALLOC                           pfnLocalAlloc;
    PFNLREALLOC                         pfnLocalReAlloc;
    PFNLLOCK                            pfnLocalLock;
    PFNLUNLOCK                          pfnLocalUnlock;
    PFNLSIZE                            pfnLocalSize;
    PFNLFREE                            pfnLocalFree;
    PFNGETEXPWINVER                     pfnGetExpWinVer;
    PFN16GALLOC                         pfn16GlobalAlloc;
    PFN16GFREE                          pfn16GlobalFree;
    PFNEMPTYCB                          pfnEmptyCB;
    PFNFINDA                            pfnFindResourceEx;
    PFNLOAD                             pfnLoadResource;
    PFNFREE                             pfnFreeResource;
    PFNLOCK                             pfnLockResource;
    PFNUNLOCK                           pfnUnlockResource;
    PFNSIZEOF                           pfnSizeofResource;
    PFNWOWWNDPROCEX                     pfnWowWndProcEx;
    PFNWOWDLGPROCEX                     pfnWowDlgProcEx;
    PFNWOWEDITNEXTWORD                  pfnWowEditNextWord;
    PFNWOWCBSTOREHANDLE                 pfnWowCBStoreHandle;
    PFNGETPROCMODULE16                  pfnGetProcModule16;
    PFNWOWMSGBOXINDIRECTCALLBACK        pfnWowMsgBoxIndirectCallback;
    PFNWOWILSTRCMP                      pfnWowIlstrsmp;
    PFNWOWTELLWOWTHEHDLG                pfnWOWTellWOWThehDlg;
} PFNWOWHANDLERSIN, * APFNWOWHANDLERSIN;


typedef struct tagAPFNWOWHANDLERSOUT
{
    // Out'ees - passed from USER32 to WOW32 and called/used by WOW32
    DWORD                               dwBldInfo;
    PFNCSCREATEWINDOWEX                 pfnCsCreateWindowEx;
    PFNDIRECTEDYIELD                    pfnDirectedYield;
    PFNFREEDDEDATA                      pfnFreeDDEData;
    PFNGETCLASSWOWWORDS                 pfnGetClassWOWWords;
    PFNINITTASK                         pfnInitTask;
    PFNREGISTERCLASSWOWA                pfnRegisterClassWOWA;
    PFNREGISTERUSERHUNGAPPHANDLERS      pfnRegisterUserHungAppHandlers;
    PFNSERVERCREATEDIALOG               pfnServerCreateDialog;
    PFNSERVERLOADCREATECURSORICON       pfnServerLoadCreateCursorIcon;
    PFNSERVERLOADCREATEMENU             pfnServerLoadCreateMenu;
    PFNWOWCLEANUP                       pfnWOWCleanup;
    PFNWOWMODULEUNLOAD                  pfnWOWModuleUnload;
    PFNWOWFINDWINDOW                    pfnWOWFindWindow;
    PFNWOWLOADBITMAPA                   pfnWOWLoadBitmapA;
    PFNWOWWAITFORMSGANDEVENT            pfnWowWaitForMsgAndEvent;
    PFNYIELDTASK                        pfnYieldTask;
    PFNGETFULLUSERHANDLE                pfnGetFullUserHandle;
    PFNGETMENUINDEX                     pfnGetMenuIndex;
    PFNWOWGETDEFWINDOWPROCBITS          pfnWowGetDefWindowProcBits;
    PFNFILLWINDOW                       pfnFillWindow;
    INT *                               aiWowClass;
} PFNWOWHANDLERSOUT, * APFNWOWHANDLERSOUT;


//
// The WW structure is embedded at the end of USER's WND structure.
// However, WOW and USER use different names to access the WW
// fields. So this structure is defined as a union of two structures,
// WHICH MUST HAVE THE SAME SIZE, just different field names.
//
// Make sure that WND_CNT_WOWDWORDS matches the number of DWORDs
//  used by the WOW only fields.
//
// FindPWW(hwnd) returns a read-only pointer to this structure for
// a given window.  To change elements of this structure, use
// SETWW (== SetWindowLong) with the appropriate GWL_WOW* offset
// defined below.
//

/* WOW class/handle type identifiers (see WARNING below)
 */

#define FNID_START                  0x0000029A
#define FNID_END                    0x000002B4

#define WOWCLASS_UNKNOWN    0   // here begin our "window handle" classes
#define WOWCLASS_WIN16      1
#define WOWCLASS_BUTTON     2
#define WOWCLASS_COMBOBOX   3
#define WOWCLASS_EDIT       4
#define WOWCLASS_LISTBOX    5
#define WOWCLASS_MDICLIENT  6
#define WOWCLASS_SCROLLBAR  7
#define WOWCLASS_STATIC     8
#define WOWCLASS_DESKTOP    9
#define WOWCLASS_DIALOG     10
#define WOWCLASS_ICONTITLE  11
#define WOWCLASS_MENU       12
#define WOWCLASS_SWITCHWND  13
#define WOWCLASS_COMBOLBOX  14
#define WOWCLASS_MAX        14  // Always equal to the last value used.

#define WOWCLASS_NOTHUNK    0xFF // not an actual class index
//
// WARNING! The above sequence and values must be maintained otherwise the
// table in WMSG16.C for message thunking must be changed.  Same goes for
// table in WALIAS.C.
//


//
// When including this from USER, VPWNDPROC is undefined
//
#ifndef _WALIAS_
typedef DWORD VPWNDPROC;
typedef DWORD VPSZ;
#endif

typedef struct tagWOWCLS {
    VPSZ       vpszMenu;
    WORD       iClsExtra;   // app's value for class extra
    WORD       hMod16;
    } WC;

typedef WC UNALIGNED *PWC;

typedef struct _WW { /* ww */
    /*
     *
     * WOW/USER fields
     * NOTE: The order and size of the following 4 fields is assumed
     *       by the SetWF, ClrWF, TestWF, MaskWF macros.
     *       Specifically, state must remain the first field in this structure.
     *
     */
    DWORD         state;        // State flags
    DWORD         state2;       //
    DWORD         ExStyle;      // Extended Style
    DWORD         style;        // Style flags

    KHANDLE       hModule;      // Handle to module instance data (32-bit).
    WORD          hMod16;       // WOW only -- hMod of wndproc
    WORD          fnid;         // record window proc used by this hwnd
                        // access through GETFNID

} WW, *PWW, **PPWW;

// this is tied to WFISINITIALIZED in ntuser\inc\user.h
#define WINDOW_IS_INITIALIZED   0x80000000

ULONG_PTR UserRegisterWowHandlers(APFNWOWHANDLERSIN apfnWowIn, APFNWOWHANDLERSOUT apfnWowOut);

VOID WINAPI RegisterWowBaseHandlers(PFNWOWGLOBALFREEHOOK pfn);

BOOL
InitTask(
    UINT dwExpWinVer,
    DWORD dwAppCompatFlags,
    LPCSTR lpszModName,
    LPCSTR lpszBaseFileName,
    DWORD hTaskWow,
    DWORD dwHotkey,
    DWORD idTask,
    DWORD dwX,
    DWORD dwY,
    DWORD dwXSize,
    DWORD dwYSize);

BOOL YieldTask(VOID);

#define DY_OLDYIELD     ((DWORD)-1)
VOID DirectedYield(DWORD ThreadId);
DWORD UserGetInt16State(void);


