322 lines
9.7 KiB
C
322 lines
9.7 KiB
C
|
/*++
|
||
|
*
|
||
|
* WOW v1.0
|
||
|
*
|
||
|
* Copyright (c) 1991, Microsoft Corporation
|
||
|
*
|
||
|
* WUMAN.C
|
||
|
* WOW32 16-bit User API support (manually-coded thunks)
|
||
|
*
|
||
|
* History:
|
||
|
* Created 27-Jan-1991 by Jeff Parsons (jeffpar)
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
MODNAME(wuman.c);
|
||
|
|
||
|
WBP W32WordBreakProc = NULL;
|
||
|
|
||
|
extern DWORD fThunkStrRtns;
|
||
|
|
||
|
extern WORD gwKrnl386CodeSeg1;
|
||
|
extern WORD gwKrnl386CodeSeg2;
|
||
|
extern WORD gwKrnl386CodeSeg3;
|
||
|
extern WORD gwKrnl386DataSeg1;
|
||
|
|
||
|
ULONG FASTCALL WU32ExitWindows(PVDMFRAME pFrame)
|
||
|
// BUGBUG mattfe 4-mar-92, this routine should not return if we close down
|
||
|
// all the apps successfully.
|
||
|
{
|
||
|
ULONG ul;
|
||
|
register PEXITWINDOWS16 parg16;
|
||
|
|
||
|
GETARGPTR(pFrame, sizeof(EXITWINDOWS16), parg16);
|
||
|
|
||
|
ul = GETBOOL16(ExitWindows(
|
||
|
DWORD32(parg16->dwReserved),
|
||
|
WORD32(parg16->wReturnCode)
|
||
|
));
|
||
|
|
||
|
FREEARGPTR(parg16);
|
||
|
|
||
|
RETURN(ul);
|
||
|
}
|
||
|
|
||
|
WORD gUser16CS = 0;
|
||
|
|
||
|
ULONG FASTCALL WU32NotifyWow(PVDMFRAME pFrame)
|
||
|
{
|
||
|
ULONG ul = 0;
|
||
|
register PNOTIFYWOW16 parg16;
|
||
|
|
||
|
GETARGPTR(pFrame, sizeof(NOTIFYWOW16), parg16);
|
||
|
|
||
|
switch (FETCHWORD(parg16->Id)) {
|
||
|
case NW_LOADACCELERATORS:
|
||
|
ul = WU32LoadAccelerators(FETCHDWORD(parg16->pData));
|
||
|
break;
|
||
|
|
||
|
case NW_LOADICON:
|
||
|
case NW_LOADCURSOR:
|
||
|
ul = (ULONG) W32CheckIfAlreadyLoaded(parg16->pData, FETCHWORD(parg16->Id));
|
||
|
break;
|
||
|
|
||
|
case NW_WINHELP:
|
||
|
{
|
||
|
// this call is made from IWinHelp in USER.exe to find the
|
||
|
// '16bit' help window if it exists.
|
||
|
//
|
||
|
|
||
|
LPSZ lpszClass;
|
||
|
GETMISCPTR(parg16->pData, lpszClass);
|
||
|
ul = (ULONG)(pfnOut.pfnWOWFindWindow)((LPCSTR)lpszClass, (LPCSTR)NULL);
|
||
|
if (ul) {
|
||
|
// check if hwndWinHelp belongs to this process or not.
|
||
|
DWORD pid, pidT;
|
||
|
pid = pidT = GetCurrentProcessId();
|
||
|
GetWindowThreadProcessId((HWND)ul, &pid);
|
||
|
ul = (ULONG)MAKELONG((WORD)GETHWND16(ul),(WORD)(pid == pidT));
|
||
|
}
|
||
|
FREEMISCPTR(lpszClass);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NW_KRNL386SEGS:
|
||
|
{
|
||
|
PKRNL386SEGS pKrnl386Segs;
|
||
|
|
||
|
GETVDMPTR(parg16->pData, sizeof(KRNL386SEGS), pKrnl386Segs);
|
||
|
|
||
|
gwKrnl386CodeSeg1 = pKrnl386Segs->CodeSeg1;
|
||
|
gwKrnl386CodeSeg2 = pKrnl386Segs->CodeSeg2;
|
||
|
gwKrnl386CodeSeg3 = pKrnl386Segs->CodeSeg3;
|
||
|
gwKrnl386DataSeg1 = pKrnl386Segs->DataSeg1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NW_FINALUSERINIT:
|
||
|
{
|
||
|
static BYTE CallCsrFlag = 0;
|
||
|
extern DWORD gpsi;
|
||
|
PUSERCLIENTGLOBALS pfinit16;
|
||
|
WORD UNALIGNED *pwMaxDWPMsg;
|
||
|
PBYTE pDWPBits;
|
||
|
#ifdef DEBUG
|
||
|
WORD wMsg;
|
||
|
int i;
|
||
|
PSZ pszFormat;
|
||
|
#endif
|
||
|
|
||
|
GETVDMPTR(parg16->pData, sizeof(USERCLIENTGLOBALS), pfinit16);
|
||
|
GETVDMPTR(pfinit16->lpwMaxDWPMsg, sizeof(WORD), pwMaxDWPMsg);
|
||
|
GETVDMPTR(pfinit16->lpDWPBits, pfinit16->cbDWPBits, pDWPBits);
|
||
|
|
||
|
// store the 16bit hmod of user.exe
|
||
|
gUser16hInstance = (WORD)pfinit16->hInstance;
|
||
|
WOW32ASSERTMSGF((gUser16hInstance),
|
||
|
("WOW Error gUser16hInstance == NULL!\n"));
|
||
|
|
||
|
// store the 16bit CS of user.exe
|
||
|
gUser16CS = HIWORD(pFrame->vpCSIP);
|
||
|
|
||
|
// initialize user16client globals
|
||
|
|
||
|
if (pfinit16->lpgpsi) {
|
||
|
BYTE **lpT;
|
||
|
GETVDMPTR(pfinit16->lpgpsi, sizeof(DWORD), lpT);
|
||
|
*lpT = (BYTE *)gpsi;
|
||
|
FLUSHVDMCODEPTR((ULONG)pfinit16->lpgpsi, sizeof(DWORD), lpT);
|
||
|
FREEVDMPTR(lpT);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (pfinit16->lpCsrFlag) {
|
||
|
BYTE **lpT;
|
||
|
GETVDMPTR(pfinit16->lpCsrFlag, sizeof(DWORD), lpT);
|
||
|
*lpT = (LPSTR)&CallCsrFlag;
|
||
|
FLUSHVDMCODEPTR((ULONG)pfinit16->lpCsrFlag, sizeof(DWORD), lpT);
|
||
|
FREEVDMPTR(lpT);
|
||
|
}
|
||
|
|
||
|
if (pfinit16->lpHighestAddress) {
|
||
|
DWORD *lpT;
|
||
|
SYSTEM_BASIC_INFORMATION sbi;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
GETVDMPTR(pfinit16->lpHighestAddress, sizeof(DWORD), lpT);
|
||
|
Status = NtQuerySystemInformation(SystemBasicInformation,
|
||
|
&sbi,
|
||
|
sizeof(sbi),
|
||
|
NULL);
|
||
|
|
||
|
WOW32ASSERTMSGF((NT_SUCCESS(Status)),
|
||
|
("WOW Error NtQuerySystemInformation failed!\n"));
|
||
|
|
||
|
*lpT = sbi.MaximumUserModeAddress;
|
||
|
FLUSHVDMCODEPTR((ULONG)pfinit16->lpHighestAddress, sizeof(DWORD), lpT);
|
||
|
FREEVDMPTR(lpT);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* No longer required now that user32 & user.exe are separate
|
||
|
DEAD CODE if (HIWORD(pfinit16->dwBldInfo) != HIWORD(pfnOut.dwBldInfo)) {
|
||
|
DEAD CODE MessageBeep(0);
|
||
|
DEAD CODE MessageBoxA(NULL, "user.exe and user32.dll are mismatched.",
|
||
|
DEAD CODE "WOW Error", MB_OK | MB_ICONEXCLAMATION);
|
||
|
DEAD CODE }
|
||
|
*/
|
||
|
|
||
|
*pwMaxDWPMsg = (pfnOut.pfnWowGetDefWindowProcBits)(pDWPBits, pfinit16->cbDWPBits);
|
||
|
|
||
|
FLUSHVDMCODEPTR(pfinit16->lpwMaxDWPMsg, sizeof(WORD), pwMaxDWPMsg);
|
||
|
FLUSHVDMCODEPTR(pfinit16->lpDWPBits, pfinit16->cbDWPBits, pDWPBits);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
LOGDEBUG(LOG_TRACE, ("WU32NotifyWow: got DefWindowProc bits, wMaxDWPMsg = 0x%x.\n", *pwMaxDWPMsg));
|
||
|
LOGDEBUG(LOG_TRACE, ("The following messages will be passed on to 32-bit DefWindowProc:\n"));
|
||
|
|
||
|
#define FPASSTODWP32(msg) \
|
||
|
(pDWPBits[msg >> 3] & (1 << (msg & 7)))
|
||
|
|
||
|
wMsg = 0;
|
||
|
i = 0;
|
||
|
|
||
|
while (wMsg <= *pwMaxDWPMsg) {
|
||
|
if (FPASSTODWP32(wMsg)) {
|
||
|
if ( i & 3 ) {
|
||
|
pszFormat = ", %s";
|
||
|
} else {
|
||
|
pszFormat = "\n%s";
|
||
|
}
|
||
|
LOGDEBUG(LOG_TRACE, (pszFormat, aw32Msg[wMsg].lpszW32));
|
||
|
i++;
|
||
|
}
|
||
|
wMsg++;
|
||
|
}
|
||
|
|
||
|
LOGDEBUG(LOG_TRACE, ("\n\n"));
|
||
|
#endif
|
||
|
|
||
|
gpfn16GetProcModule = pfinit16->pfnGetProcModule;
|
||
|
|
||
|
//
|
||
|
// Return value tells User16 whether to thunk
|
||
|
// string routines to Win32 or use the fast
|
||
|
// US-only versions. TRUE means thunk.
|
||
|
//
|
||
|
// If the locale is U.S. English, we default to
|
||
|
// not thunking, outside the U.S. we default to
|
||
|
// thunking. See wow32.c's use of fThunkStrRtns.
|
||
|
//
|
||
|
// We engage in this nastiness because the Winstone 94
|
||
|
// Access 1.1 test takes *twice* as long to run in
|
||
|
// the US if we thunk lstrcmp and lstrcmpi to Win32.
|
||
|
//
|
||
|
// By adding a value "ThunkNLS" to the WOW registry
|
||
|
// key of type REG_DWORD, the user can force thunking
|
||
|
// to Win32 (value 1) or use the fast US-only ones (value 0).
|
||
|
//
|
||
|
|
||
|
ul = fThunkStrRtns;
|
||
|
|
||
|
FREEVDMPTR(pDWPBits);
|
||
|
FREEVDMPTR(pwMaxDWPMsg);
|
||
|
FREEVDMPTR(pfinit16);
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ul = 0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
FREEARGPTR(parg16);
|
||
|
return ul;
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG FASTCALL WU32WOWWordBreakProc(PVDMFRAME pFrame)
|
||
|
{
|
||
|
PSZ psz1;
|
||
|
ULONG ul;
|
||
|
register PWOWWORDBREAKPROC16 parg16;
|
||
|
|
||
|
GETARGPTR(pFrame, sizeof(*parg16), parg16);
|
||
|
GETPSZPTR(parg16->lpszEditText, psz1);
|
||
|
|
||
|
ul = (*W32WordBreakProc)(psz1, parg16->ichCurrentWord, parg16->cbEditText,
|
||
|
parg16->action);
|
||
|
|
||
|
FREEPSZPTR(psz1);
|
||
|
FREEARGPTR(parg16);
|
||
|
RETURN(ul);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// WU32MouseEvent: Thunk for 16-bit register-based API mouse_event,
|
||
|
// with the help of user16 function mouse_event (in
|
||
|
// winmisc2.asm).
|
||
|
//
|
||
|
|
||
|
ULONG FASTCALL WU32MouseEvent(PVDMFRAME pFrame)
|
||
|
{
|
||
|
ULONG ul;
|
||
|
register PMOUSEEVENT16 parg16;
|
||
|
typedef ULONG (WINAPI *PFMOUSE_EVENT)(DWORD, DWORD, DWORD, DWORD, DWORD);
|
||
|
|
||
|
GETARGPTR(pFrame, sizeof(PMOUSEEVENT16), parg16);
|
||
|
|
||
|
//
|
||
|
// mouse_event is declared void, but we'll return the same value as
|
||
|
// user32.
|
||
|
//
|
||
|
|
||
|
ul = ((PFMOUSE_EVENT)(PVOID)mouse_event)(
|
||
|
parg16->wFlags,
|
||
|
parg16->dx,
|
||
|
parg16->dy,
|
||
|
parg16->cButtons,
|
||
|
parg16->dwExtraInfo
|
||
|
);
|
||
|
|
||
|
FREEARGPTR(parg16);
|
||
|
RETURN(ul);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// WU32KeybdEvent: Thunk for 16-bit register-based API keybd_event,
|
||
|
// with the help of user16 function keybd_event (in
|
||
|
// winmisc2.asm).
|
||
|
//
|
||
|
|
||
|
ULONG FASTCALL WU32KeybdEvent(PVDMFRAME pFrame)
|
||
|
{
|
||
|
ULONG ul;
|
||
|
register PKEYBDEVENT16 parg16;
|
||
|
typedef ULONG (WINAPI *PFKEYBD_EVENT)(BYTE, BYTE, DWORD, DWORD);
|
||
|
|
||
|
GETARGPTR(pFrame, sizeof(PKEYBDEVENT16), parg16);
|
||
|
|
||
|
//
|
||
|
// keybd_event is declared void, but we'll return the same value as
|
||
|
// user32.
|
||
|
//
|
||
|
|
||
|
ul = ((PFKEYBD_EVENT)(PVOID)keybd_event)(
|
||
|
LOBYTE(parg16->bVirtualKey),
|
||
|
LOBYTE(parg16->bScanCode),
|
||
|
((HIBYTE(parg16->bVirtualKey) == 0x80) ? KEYEVENTF_KEYUP : 0) |
|
||
|
((HIBYTE(parg16->bScanCode) == 0x1) ? KEYEVENTF_EXTENDEDKEY : 0),
|
||
|
parg16->dwExtraInfo
|
||
|
);
|
||
|
|
||
|
FREEARGPTR(parg16);
|
||
|
RETURN(ul);
|
||
|
}
|