/*++ * * 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; /* Called By Kernel When Initialization is Complete */ ULONG FASTCALL WU32FinalUserInit(PVDMFRAME pFrame) { UNREFERENCED_PARAMETER(pFrame); return TRUE; } 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; register PNOTIFYWOW16 parg16; GETARGPTR(pFrame, sizeof(NOTIFYWOW16), parg16); switch (FETCHWORD(parg16->Id)) { case FUN_LOADACCELERATORS: ul = WU32LoadAccelerators(FETCHDWORD(parg16->pData)); break; case FUN_LOADICON: case FUN_LOADCURSOR: ul = (ULONG) W32CheckIfAlreadyLoaded(parg16->pData, FETCHWORD(parg16->Id)); break; case FUN_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 FUN_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 (HIWORD(pfinit16->dwBldInfo) != HIWORD(pfnOut.dwBldInfo)) { MessageBeep(0); MessageBoxA(NULL, "user.exe and user32.dll are mismatched.", "WOW Error", MB_OK | MB_ICONEXCLAMATION); } *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 // // 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 WU32WordBreakProc(PVDMFRAME pFrame) { PSZ psz1; ULONG ul; register PWORDBREAKPROC16 parg16; GETARGPTR(pFrame, sizeof(WORDBREAKPROC16), 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); }