windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wuman.c
2020-09-26 16:20:57 +08:00

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);
}