mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
738 lines
20 KiB
738 lines
20 KiB
/*++
|
|
*
|
|
* WOW v1.0
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* WALIAS.C
|
|
* WOW32 16-bit handle alias support
|
|
*
|
|
* History:
|
|
* Created 27-Jan-1991 by Jeff Parsons (jeffpar)
|
|
* Modified 12-May-1992 by Mike Tricker (miketri) to add MultiMedia support
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
MODNAME(walias.c);
|
|
|
|
extern CRITICAL_SECTION gcsWOW;
|
|
extern PTD gptdTaskHead;
|
|
|
|
//BUGBUG - this must be removed once MM_MCISYSTEM_STRING is defined in MMSYSTEM.H.
|
|
#ifndef MM_MCISYSTEM_STRING
|
|
#define MM_MCISYSTEM_STRING 0x3CA
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
extern BOOL fSkipLog; // TRUE to temporarily skip certain logging
|
|
#endif
|
|
|
|
typedef struct _stdclass {
|
|
LPSTR lpszClassName;
|
|
ATOM aClassAtom;
|
|
WNDPROC lpfnWndProc;
|
|
INT iOrdinal;
|
|
DWORD vpfnWndProc;
|
|
} STDCLASS;
|
|
|
|
// Some cool defines stolen from USERSRV.H
|
|
#define MENUCLASS MAKEINTATOM(0x8000)
|
|
#define DESKTOPCLASS MAKEINTATOM(0x8001)
|
|
#define DIALOGCLASS MAKEINTATOM(0x8002)
|
|
#define SWITCHWNDCLASS MAKEINTATOM(0x8003)
|
|
#define ICONTITLECLASS MAKEINTATOM(0x8004)
|
|
|
|
// See WARNING below!
|
|
STDCLASS stdClasses[] = {
|
|
NULL, 0, NULL, 0, 0, // WOWCLASS_UNKNOWN
|
|
NULL, 0, NULL, 0, 0, // WOWCLASS_WIN16
|
|
"BUTTON", 0, NULL, FUN_BUTTONWNDPROC, 0, // WOWCLASS_BUTTON,
|
|
"COMBOBOX", 0, NULL, FUN_COMBOBOXCTLWNDPROC, 0, // WOWCLASS_COMBOBOX,
|
|
"EDIT", 0, NULL, FUN_EDITWNDPROC, 0, // WOWCLASS_EDIT,
|
|
"LISTBOX", 0, NULL, FUN_LBOXCTLWNDPROC, 0, // WOWCLASS_LISTBOX,
|
|
"MDICLIENT", 0, NULL, FUN_MDICLIENTWNDPROC, 0, // WOWCLASS_MDICLIENT,
|
|
"SCROLLBAR", 0, NULL, FUN_SBWNDPROC, 0, // WOWCLASS_SCROLLBAR,
|
|
"STATIC", 0, NULL, FUN_STATICWNDPROC, 0, // WOWCLASS_STATIC,
|
|
"#32769", (WORD)DESKTOPCLASS, NULL, FUN_DESKTOPWNDPROC, 0, // WOWCLASS_DESKTOP,
|
|
"#32770", (WORD)DIALOGCLASS, NULL, FUN_DEFDLGPROCTHUNK, 0, // WOWCLASS_DIALOG,
|
|
"#32772", (WORD)ICONTITLECLASS, NULL, FUN_TITLEWNDPROC, 0, // WOWCLASS_ICONTITLE,
|
|
"#32768", (WORD)MENUCLASS, NULL, FUN_MENUWNDPROC, 0, // WOWCLASS_MENU,
|
|
"#32771", (WORD)SWITCHWNDCLASS, NULL, 0, 0, // WOWCLASS_SWITCHWND,
|
|
"COMBOLBOX", 0, NULL, FUN_LBOXCTLWNDPROC, 0, // WOWCLASS_COMBOLBOX
|
|
};
|
|
//
|
|
// WARNING! The above sequence and values must be maintained otherwise the
|
|
// table in WMSG16.C for message thunking must be changed. Same goes for
|
|
// the #define's in WALIAS.H
|
|
//
|
|
// The above COMBOLBOX case is special because it is class that is
|
|
// almost identical to a listbox. Therefore we lie about it.
|
|
|
|
INT GetStdClassNumber(
|
|
PSZ pszClass
|
|
) {
|
|
INT i;
|
|
|
|
if ( HIWORD(pszClass) ) {
|
|
|
|
// They passed us a string
|
|
|
|
for ( i = WOWCLASS_BUTTON; i < NUMEL(stdClasses); i++ ) {
|
|
if ( WOW32_stricmp(pszClass, stdClasses[i].lpszClassName) == 0 ) {
|
|
return( i );
|
|
}
|
|
}
|
|
} else {
|
|
|
|
// They passed us an atom
|
|
|
|
for ( i = WOWCLASS_BUTTON; i < NUMEL(stdClasses); i++ ) {
|
|
if ( stdClasses[i].aClassAtom == 0 ) {
|
|
// RegisterWindowMessage is an undocumented way of determining
|
|
// an atom value in the context of the server-side heap.
|
|
stdClasses[i].aClassAtom = (ATOM)RegisterWindowMessage(stdClasses[i].lpszClassName);
|
|
}
|
|
if ( (ATOM)LOWORD(pszClass) == stdClasses[i].aClassAtom ) {
|
|
return( i );
|
|
}
|
|
}
|
|
}
|
|
return( WOWCLASS_WIN16 ); // private 16-bit class created by the app
|
|
}
|
|
|
|
// Returns a 32 window proc given a class index
|
|
|
|
WNDPROC GetStdClassWndProc(
|
|
DWORD iClass
|
|
) {
|
|
WNDPROC lpfn32;
|
|
|
|
if ( iClass < WOWCLASS_WIN16 || iClass > WOWCLASS_MAX ) {
|
|
WOW32ASSERT(FALSE);
|
|
return( NULL );
|
|
}
|
|
|
|
lpfn32 = stdClasses[iClass].lpfnWndProc;
|
|
|
|
if ( lpfn32 == NULL ) {
|
|
WNDCLASS wc;
|
|
BOOL f;
|
|
|
|
f = GetClassInfo( NULL, stdClasses[iClass].lpszClassName, &wc );
|
|
|
|
if ( f ) {
|
|
VPVOID vp;
|
|
DWORD UNALIGNED * lpdw;
|
|
|
|
lpfn32 = wc.lpfnWndProc;
|
|
stdClasses[iClass].lpfnWndProc = lpfn32;
|
|
|
|
vp = GetStdClassThunkProc(iClass);
|
|
vp = (VPVOID)((DWORD)vp - sizeof(DWORD)*3);
|
|
|
|
GETVDMPTR( vp, sizeof(DWORD)*3, lpdw );
|
|
|
|
WOW32ASSERT(*lpdw == SUBCLASS_MAGIC); // Are we editing the right stuff?
|
|
|
|
if (!lpdw)
|
|
*(lpdw+2) = (DWORD)lpfn32;
|
|
|
|
FLUSHVDMCODEPTR( vp, sizeof(DWORD)*3, lpdw );
|
|
FREEVDMPTR( lpdw );
|
|
|
|
}
|
|
}
|
|
return( lpfn32 );
|
|
}
|
|
|
|
// Returns a 16 window proc thunk given a class index
|
|
|
|
DWORD GetStdClassThunkProc(
|
|
INT iClass
|
|
) {
|
|
DWORD dwResult;
|
|
SHORT iOrdinal;
|
|
PARM16 Parm16;
|
|
|
|
if ( iClass < WOWCLASS_WIN16 || iClass > WOWCLASS_MAX ) {
|
|
WOW32ASSERT(FALSE);
|
|
return( 0 );
|
|
}
|
|
|
|
iOrdinal = (SHORT)stdClasses[iClass].iOrdinal;
|
|
|
|
if ( iOrdinal == 0 ) {
|
|
return( (DWORD)NULL );
|
|
}
|
|
|
|
// If we've already gotten this proc, then don't bother calling into 16-bit
|
|
dwResult = stdClasses[iClass].vpfnWndProc;
|
|
|
|
if ( dwResult == (DWORD)NULL ) {
|
|
|
|
// Callback into the 16-bit world asking for the 16:16 address
|
|
|
|
Parm16.SubClassProc.iOrdinal = iOrdinal;
|
|
|
|
if (!CallBack16(RET_SUBCLASSPROC, &Parm16, (VPPROC)NULL,
|
|
(PVPVOID)&dwResult)) {
|
|
WOW32ASSERT(FALSE);
|
|
return( 0 );
|
|
}
|
|
// Save it since it is a constant.
|
|
stdClasses[iClass].vpfnWndProc = dwResult;
|
|
}
|
|
return( dwResult );
|
|
}
|
|
|
|
/*
|
|
* PWC GetClassWOWWords(hInst, pszClass)
|
|
* is a ***private*** API for WOW only. It returns a pointer to the
|
|
* WOW Class structure in the server's window class structure.
|
|
* This is similar to GetClassLong(hwnd32, GCL_WOWWORDS) (see FindPWC),
|
|
* but in this case we don't have a hwnd32, we have the class name
|
|
* and instance handle.
|
|
*/
|
|
|
|
PWC FindClass16(LPCSTR pszClass, HAND16 hInst)
|
|
{
|
|
register PWC pwc;
|
|
|
|
pwc = (PWC)(pfnOut.pfnGetClassWOWWords)(HMODINST32(hInst), pszClass);
|
|
WOW32WARNMSGF(
|
|
pwc,
|
|
("WOW32 warning: GetClassWOWWords('%s', %04x) returned NULL\n", pszClass, hInst)
|
|
);
|
|
|
|
return (pwc);
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
INT nAliases;
|
|
INT iLargestListSlot;
|
|
|
|
PSZ apszHandleClasses[] = {
|
|
"Unknown", // WOWCLASS_UNKNOWN
|
|
"Window", // WOWCLASS_WIN16
|
|
"Button", // WOWCLASS_BUTTON
|
|
"ComboBox", // WOWCLASS_COMBOBOX
|
|
"Edit", // WOWCLASS_EDIT
|
|
"ListBox", // WOWCLASS_LISTBOX
|
|
"MDIClient", // WOWCLASS_MDICLIENT
|
|
"Scrollbar", // WOWCLASS_SCROLLBAR
|
|
"Static", // WOWCLASS_STATIC
|
|
"Desktop", // WOWCLASS_DESKTOP
|
|
"Dialog", // WOWCLASS_DIALOG
|
|
"Menu", // WOWCLASS_MENU
|
|
"IconTitle", // WOWCLASS_ICONTITLE
|
|
"Accel", // WOWCLASS_ACCEL
|
|
"Cursor", // WOWCLASS_CURSOR
|
|
"Icon", // WOWCLASS_ICON
|
|
"DC", // WOWCLASS_DC
|
|
"Font", // WOWCLASS_FONT
|
|
"MetaFile", // WOWCLASS_METAFILE
|
|
"Region", // WOWCLASS_RGN
|
|
"Bitmap", // WOWCLASS_BITMAP
|
|
"Brush", // WOWCLASS_BRUSH
|
|
"Palette", // WOWCLASS_PALETTE
|
|
"Pen", // WOWCLASS_PEN
|
|
"Object" // WOWCLASS_OBJECT
|
|
};
|
|
|
|
|
|
BOOL MessageNeedsThunking(UINT uMsg)
|
|
{
|
|
switch (uMsg) {
|
|
case WM_CREATE:
|
|
case WM_ACTIVATE:
|
|
case WM_SETFOCUS:
|
|
case WM_KILLFOCUS:
|
|
case WM_SETTEXT:
|
|
case WM_GETTEXT:
|
|
case WM_ERASEBKGND:
|
|
case WM_WININICHANGE:
|
|
case WM_DEVMODECHANGE:
|
|
case WM_ACTIVATEAPP:
|
|
case WM_SETCURSOR:
|
|
case WM_MOUSEACTIVATE:
|
|
case WM_GETMINMAXINFO:
|
|
case WM_ICONERASEBKGND:
|
|
case WM_NEXTDLGCTL:
|
|
case WM_DRAWITEM:
|
|
case WM_MEASUREITEM:
|
|
case WM_DELETEITEM:
|
|
case WM_VKEYTOITEM:
|
|
case WM_CHARTOITEM:
|
|
case WM_SETFONT:
|
|
case WM_GETFONT:
|
|
case WM_QUERYDRAGICON:
|
|
case WM_COMPAREITEM:
|
|
case WM_OTHERWINDOWCREATED:
|
|
case WM_OTHERWINDOWDESTROYED:
|
|
case WM_COMMNOTIFY:
|
|
case WM_WINDOWPOSCHANGING:
|
|
case WM_WINDOWPOSCHANGED:
|
|
case WM_NCCREATE:
|
|
case WM_NCCALCSIZE:
|
|
case WM_COMMAND:
|
|
case WM_HSCROLL:
|
|
case WM_VSCROLL:
|
|
case WM_INITMENU:
|
|
case WM_INITMENUPOPUP:
|
|
case WM_MENUSELECT:
|
|
case WM_MENUCHAR:
|
|
case WM_ENTERIDLE:
|
|
case WM_CTLCOLORMSGBOX:
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORLISTBOX:
|
|
case WM_CTLCOLORBTN:
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
case WM_CTLCOLORSTATIC:
|
|
case WM_PARENTNOTIFY:
|
|
case WM_MDICREATE:
|
|
case WM_MDIDESTROY:
|
|
case WM_MDIACTIVATE:
|
|
case WM_MDIGETACTIVE:
|
|
case WM_MDISETMENU:
|
|
case WM_RENDERFORMAT:
|
|
case WM_PAINTCLIPBOARD:
|
|
case WM_VSCROLLCLIPBOARD:
|
|
case WM_SIZECLIPBOARD:
|
|
case WM_ASKCBFORMATNAME:
|
|
case WM_CHANGECBCHAIN:
|
|
case WM_HSCROLLCLIPBOARD:
|
|
case WM_PALETTEISCHANGING:
|
|
case WM_PALETTECHANGED:
|
|
case MM_JOY1MOVE:
|
|
case MM_JOY2MOVE:
|
|
case MM_JOY1ZMOVE:
|
|
case MM_JOY2ZMOVE:
|
|
case MM_JOY1BUTTONDOWN:
|
|
case MM_JOY2BUTTONDOWN:
|
|
case MM_JOY1BUTTONUP:
|
|
case MM_JOY2BUTTONUP:
|
|
case MM_MCINOTIFY:
|
|
case MM_MCISYSTEM_STRING:
|
|
case MM_WOM_OPEN:
|
|
case MM_WOM_CLOSE:
|
|
case MM_WOM_DONE:
|
|
case MM_WIM_OPEN:
|
|
case MM_WIM_CLOSE:
|
|
case MM_WIM_DATA:
|
|
case MM_MIM_OPEN:
|
|
case MM_MIM_CLOSE:
|
|
case MM_MIM_DATA:
|
|
case MM_MIM_LONGDATA:
|
|
case MM_MIM_ERROR:
|
|
case MM_MIM_LONGERROR:
|
|
case MM_MOM_OPEN:
|
|
case MM_MOM_CLOSE:
|
|
case MM_MOM_DONE:
|
|
LOGDEBUG(LOG_IMPORTANT,
|
|
("MessageNeedsThunking: WM_msg %04x is not thunked\n", uMsg));
|
|
return TRUE;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
PTD ThreadProcID32toPTD(DWORD dwThreadID, DWORD dwProcessID)
|
|
{
|
|
PTD ptd, ptdThis;
|
|
PWOAINST pWOA;
|
|
|
|
//
|
|
// If we have active child instances of WinOldAp,
|
|
// try to map the process ID of a child Win32 app
|
|
// to the corresponding WinOldAp PTD.
|
|
//
|
|
|
|
ptdThis = CURRENTPTD();
|
|
|
|
EnterCriticalSection(&ptdThis->csTD);
|
|
|
|
pWOA = ptdThis->pWOAList;
|
|
|
|
while (pWOA && pWOA->dwChildProcessID != dwProcessID) {
|
|
pWOA = pWOA->pNext;
|
|
}
|
|
|
|
if (pWOA) {
|
|
|
|
ptd = pWOA->ptdWOA;
|
|
|
|
LeaveCriticalSection(&ptdThis->csTD);
|
|
|
|
} else {
|
|
|
|
LeaveCriticalSection(&ptdThis->csTD);
|
|
|
|
//
|
|
// We didn't find a WinOldAp PTD to return, see
|
|
// if the thread ID matches one of our app threads.
|
|
//
|
|
|
|
EnterCriticalSection(&gcsWOW);
|
|
|
|
ptd = gptdTaskHead;
|
|
|
|
while (ptd && ptd->dwThreadID != dwThreadID) {
|
|
ptd = ptd->ptdNext;
|
|
}
|
|
|
|
LeaveCriticalSection(&gcsWOW);
|
|
}
|
|
|
|
return ptd;
|
|
|
|
}
|
|
|
|
PTD Htask16toPTD(
|
|
HTASK16 htask16
|
|
) {
|
|
PTD ptd;
|
|
|
|
EnterCriticalSection(&gcsWOW);
|
|
|
|
ptd = gptdTaskHead;
|
|
|
|
while(ptd) {
|
|
|
|
if ( ptd->htask16 == htask16 ) {
|
|
break;
|
|
}
|
|
ptd = ptd->ptdNext;
|
|
}
|
|
|
|
LeaveCriticalSection(&gcsWOW);
|
|
|
|
return ptd;
|
|
}
|
|
|
|
|
|
HTASK16 ThreadID32toHtask16(
|
|
DWORD ThreadID32
|
|
) {
|
|
PTD ptd;
|
|
HTASK16 htask16;
|
|
|
|
|
|
if ( ThreadID32 == 0 ) {
|
|
WOW32ASSERTMSG(ThreadID32, "WOW::ThreadID32tohTask16: Thread ID is 0\n");
|
|
htask16 = 0;
|
|
} else {
|
|
|
|
ptd = ThreadProcID32toPTD( ThreadID32, (DWORD)-1 );
|
|
if ( ptd ) {
|
|
// Good, its one of our wow threads.
|
|
htask16 = ptd->htask16;
|
|
} else {
|
|
// Nope, its is some other 32-bit thread
|
|
htask16 = FindHtaskAlias( ThreadID32 );
|
|
if ( htask16 == 0 ) {
|
|
//
|
|
// See the comment in WOLE2.C for a nice description
|
|
//
|
|
htask16 = AddHtaskAlias( ThreadID32 );
|
|
}
|
|
}
|
|
}
|
|
|
|
return htask16;
|
|
}
|
|
|
|
DWORD Htask16toThreadID32(
|
|
HTASK16 htask16
|
|
) {
|
|
if ( htask16 == 0 ) {
|
|
return( 0 );
|
|
}
|
|
|
|
if ( ISTASKALIAS(htask16) ) {
|
|
return( GetHtaskAlias(htask16,NULL) );
|
|
} else {
|
|
return( THREADID32(htask16) );
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
// GetGCL_HMODULE - returns the valid hmodule if the window corresponds to
|
|
// a 16bit class else returns the hmodule of 16bit user.exe
|
|
// if the window is of a standard class.
|
|
//
|
|
// These cases are required for compatibility sake.
|
|
// apps like VirtualMonitor, hDC etc depend on such behaviour.
|
|
// - Nanduri
|
|
//***************************************************************************
|
|
WORD gUser16hInstance = 0;
|
|
|
|
ULONG GetGCL_HMODULE(HWND hwnd)
|
|
{
|
|
ULONG ul;
|
|
PTD ptd;
|
|
PWOAINST pWOA;
|
|
DWORD dwProcessID;
|
|
|
|
ul = (ULONG)GetClassLong(hwnd, GCL_HMODULE);
|
|
|
|
//
|
|
// hMod32 = 0xZZZZ0000
|
|
//
|
|
|
|
if (ul != 0 && LOWORD(ul) == 0) {
|
|
|
|
//
|
|
// If we have active WinOldAp children, see if this window
|
|
// belongs to a Win32 process spawned by one of the
|
|
// active winoldap's. If it is, return the hmodule
|
|
// of the corresponding winoldap. Otherwise we
|
|
// return user.exe's hinstance (why not hmodule?)
|
|
//
|
|
|
|
dwProcessID = (DWORD)-1;
|
|
GetWindowThreadProcessId(hwnd, &dwProcessID);
|
|
|
|
ptd = CURRENTPTD();
|
|
|
|
EnterCriticalSection(&ptd->csTD);
|
|
|
|
pWOA = ptd->pWOAList;
|
|
while (pWOA && pWOA->dwChildProcessID != dwProcessID) {
|
|
pWOA = pWOA->pNext;
|
|
}
|
|
|
|
if (pWOA) {
|
|
ul = pWOA->ptdWOA->hMod16;
|
|
LOGDEBUG(LOG_ALWAYS, ("WOW32 GetClassLong(0x%x, GWW_HMODULE) returning 0x%04x\n",
|
|
hwnd, ul));
|
|
} else {
|
|
ul = (ULONG) gUser16hInstance;
|
|
WOW32ASSERT(ul);
|
|
}
|
|
|
|
LeaveCriticalSection(&ptd->csTD);
|
|
}
|
|
else {
|
|
ul = (ULONG)GETHMOD16(ul); // 32-bit hmod is HMODINST32
|
|
}
|
|
|
|
return ul;
|
|
}
|
|
|
|
//
|
|
// EXPORTED handle mapping functions. WOW32 code should use the
|
|
// macros defined in walias.h -- these functions are for use by
|
|
// third-party 32-bit code running in WOW, for example called
|
|
// using generic thunks from WOW-specific 16-bit code.
|
|
//
|
|
|
|
HANDLE WOWHandle32 (WORD h16, WOW_HANDLE_TYPE htype)
|
|
{
|
|
switch (htype) {
|
|
case WOW_TYPE_HWND:
|
|
return HWND32(h16);
|
|
case WOW_TYPE_HMENU:
|
|
return HMENU32(h16);
|
|
case WOW_TYPE_HDWP:
|
|
return HDWP32(h16);
|
|
case WOW_TYPE_HDROP:
|
|
return HDROP32(h16);
|
|
case WOW_TYPE_HDC:
|
|
return HDC32(h16);
|
|
case WOW_TYPE_HFONT:
|
|
return HFONT32(h16);
|
|
case WOW_TYPE_HMETAFILE:
|
|
return HMETA32(h16);
|
|
case WOW_TYPE_HRGN:
|
|
return HRGN32(h16);
|
|
case WOW_TYPE_HBITMAP:
|
|
return HBITMAP32(h16);
|
|
case WOW_TYPE_HBRUSH:
|
|
return HBRUSH32(h16);
|
|
case WOW_TYPE_HPALETTE:
|
|
return HPALETTE32(h16);
|
|
case WOW_TYPE_HPEN:
|
|
return HPEN32(h16);
|
|
case WOW_TYPE_HACCEL:
|
|
return HACCEL32(h16);
|
|
case WOW_TYPE_HTASK:
|
|
return (HANDLE)HTASK32(h16);
|
|
case WOW_TYPE_FULLHWND:
|
|
return (HANDLE)FULLHWND32(h16);
|
|
default:
|
|
return(INVALID_HANDLE_VALUE);
|
|
}
|
|
}
|
|
|
|
WORD WOWHandle16 (HANDLE h32, WOW_HANDLE_TYPE htype)
|
|
{
|
|
switch (htype) {
|
|
case WOW_TYPE_HWND:
|
|
return GETHWND16(h32);
|
|
case WOW_TYPE_HMENU:
|
|
return GETHMENU16(h32);
|
|
case WOW_TYPE_HDWP:
|
|
return GETHDWP16(h32);
|
|
case WOW_TYPE_HDROP:
|
|
return GETHDROP16(h32);
|
|
case WOW_TYPE_HDC:
|
|
return GETHDC16(h32);
|
|
case WOW_TYPE_HFONT:
|
|
return GETHFONT16(h32);
|
|
case WOW_TYPE_HMETAFILE:
|
|
return GETHMETA16(h32);
|
|
case WOW_TYPE_HRGN:
|
|
return GETHRGN16(h32);
|
|
case WOW_TYPE_HBITMAP:
|
|
return GETHBITMAP16(h32);
|
|
case WOW_TYPE_HBRUSH:
|
|
return GETHBRUSH16(h32);
|
|
case WOW_TYPE_HPALETTE:
|
|
return GETHPALETTE16(h32);
|
|
case WOW_TYPE_HPEN:
|
|
return GETHPEN16(h32);
|
|
case WOW_TYPE_HACCEL:
|
|
return GETHACCEL16(h32);
|
|
case WOW_TYPE_HTASK:
|
|
return GETHTASK16(h32);
|
|
default:
|
|
return(0xffff);
|
|
}
|
|
}
|
|
|
|
PVOID gpGdiHandleInfo = (PVOID)-1;
|
|
|
|
//WARNING: This structure must match ENTRY in ntgdi\inc\hmgshare.h
|
|
|
|
typedef struct _ENTRYWOW
|
|
{
|
|
LONG l1;
|
|
LONG l2;
|
|
USHORT FullUnique;
|
|
USHORT us1;
|
|
LONG l3;
|
|
} ENTRYWOW, *PENTRYWOW;
|
|
|
|
//
|
|
// this routine converts a 16bit GDI handle to a 32bit handle. There
|
|
// is no need to do any validation on the handle since the 14bit space
|
|
// for handles ignoring the low two bits is completely contained in the
|
|
// valid 32bit handle space.
|
|
//
|
|
|
|
HANDLE hConvert16to32(int h16)
|
|
{
|
|
ULONG h32;
|
|
int i = h16 >> 2;
|
|
|
|
h32 = i | (ULONG)(((PENTRYWOW)gpGdiHandleInfo)[i].FullUnique) << 16;
|
|
|
|
return((HANDLE)h32);
|
|
}
|
|
|
|
|
|
// Implemented as temporary fix for Whistler Bug #435401
|
|
// Should be fixed for Blackcomb or sooner
|
|
extern HANDLE hmodWOW32;
|
|
|
|
HAND16 hConvert32to16(DWORD h32)
|
|
{
|
|
PARM16 Parm16;
|
|
VPVOID vp = 0;
|
|
|
|
// see if handle is over 14-bits
|
|
if(LOWORD(h32) > 0x00003FFF) {
|
|
char szErrorMessage[512];
|
|
char szTitle[512];
|
|
char szModName[9];
|
|
PTDB pTDB;
|
|
|
|
pTDB = (PVOID)SEGPTR(CURRENTPTD()->htask16,0);
|
|
|
|
RtlCopyMemory(szModName, pTDB->TDB_ModName, sizeof(szModName)-1);
|
|
szModName[sizeof(szModName)-1] = 0;
|
|
if (!LoadString(hmodWOW32, iszApplication,
|
|
szTitle, sizeof(szTitle)/sizeof(CHAR)))
|
|
{
|
|
szTitle[0] = 0;
|
|
}
|
|
strcat(szTitle, szModName);
|
|
|
|
LoadString(hmodWOW32,
|
|
iszExceedGDIHandleLimit,
|
|
szErrorMessage,
|
|
sizeof szErrorMessage);
|
|
|
|
// The GDI32 handle allocation has gone over the 16K threshhold
|
|
// This thread is toast.
|
|
WOWSysErrorBox(szTitle, szErrorMessage, SEB_OK | SEB_DEFBUTTON, 0, 0);
|
|
|
|
LOGDEBUG(LOG_ALWAYS,
|
|
("GDI32 handle limit exceeded for Task %04X \n",
|
|
CURRENTPTD()->htask16));
|
|
|
|
CallBack16(RET_FORCETASKEXIT, &Parm16, 0, &vp);
|
|
|
|
// this should never return
|
|
return(0);
|
|
}
|
|
|
|
// everything is hunky dory
|
|
return((HAND16)(((DWORD) (h32)) << 2));
|
|
}
|
|
|
|
// We probably don't need to worry about this buffer being too small since we're
|
|
// really only interested in the predefined standard classes which tend to
|
|
// be rather short-named.
|
|
#define MAX_CLASSNAME_LEN 64
|
|
|
|
// There is a time frame (from when an app calls CreateWindow until USER32 gets
|
|
// a message at one of its WndProc's for the window - see FritzS) during which
|
|
// the fnid (class type) can't be set officially for the window. If the
|
|
// GETICLASS macro is invoked during this period, it will be unable to find the
|
|
// iClass for windows created on any of the standard control classes using the
|
|
// fast fnid index method (see walias.h). Once the time frame is passed, the
|
|
// fast fnid method will work fine for these windows.
|
|
//
|
|
// This is manifested in apps that set CBT hooks and try to subclass the
|
|
// standard classes while in their hook proc. See bug #143811.
|
|
|
|
INT GetIClass(PWW pww, HWND hwnd)
|
|
{
|
|
INT iClass;
|
|
DWORD dwClassAtom;
|
|
|
|
// if it is a standard class
|
|
if(((pww->fnid & 0xfff) >= FNID_START) &&
|
|
((pww->fnid & 0xfff) <= FNID_END)) {
|
|
|
|
// return the class id for this initialized window
|
|
iClass = pfnOut.aiWowClass[( pww->fnid & 0xfff) - FNID_START];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
iClass = WOWCLASS_WIN16; // default return: app private class
|
|
|
|
dwClassAtom = GetClassLong(hwnd, GCW_ATOM);
|
|
|
|
if(dwClassAtom) {
|
|
iClass = GetStdClassNumber((PSZ)dwClassAtom);
|
|
}
|
|
}
|
|
|
|
return(iClass);
|
|
}
|
|
|