WindowsXP-SP1/windows/oleacc/oleacc/imports.cpp
2020-09-30 16:53:49 +02:00

919 lines
30 KiB
C++

// Copyright (c) 1996-2000 Microsoft Corporation
// --------------------------------------------------------------------------
//
// imports
//
// GetProcAddress'd APIs
//
// --------------------------------------------------------------------------
#include "oleacc_p.h"
// #include "imports.h" - already in oleacc_p.h
#include "w95trace.h"
typedef BOOL (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD, PGUITHREADINFO);
typedef BOOL (STDAPICALLTYPE *LPFNGETCURSORINFO)(LPCURSORINFO);
typedef BOOL (STDAPICALLTYPE *LPFNGETWINDOWINFO)(HWND, LPWINDOWINFO);
typedef BOOL (STDAPICALLTYPE *LPFNGETTITLEBARINFO)(HWND, LPTITLEBARINFO);
typedef BOOL (STDAPICALLTYPE *LPFNGETSCROLLBARINFO)(HWND, LONG, LPSCROLLBARINFO);
typedef BOOL (STDAPICALLTYPE *LPFNGETCOMBOBOXINFO)(HWND, LPCOMBOBOXINFO);
typedef HWND (STDAPICALLTYPE *LPFNGETANCESTOR)(HWND, UINT);
typedef HWND (STDAPICALLTYPE *LPFNREALCHILDWINDOWFROMPOINT)(HWND, POINT);
typedef UINT (STDAPICALLTYPE *LPFNREALGETWINDOWCLASS)(HWND, LPTSTR, UINT);
typedef BOOL (STDAPICALLTYPE *LPFNGETALTTABINFO)(HWND, int, LPALTTABINFO, LPTSTR, UINT);
typedef BOOL (STDAPICALLTYPE *LPFNGETMENUBARINFO)(HWND, LONG, LONG, LPMENUBARINFO);
typedef DWORD (STDAPICALLTYPE* LPFNGETLISTBOXINFO)(HWND);
typedef BOOL (STDAPICALLTYPE *LPFNSENDINPUT)(UINT, LPINPUT, INT);
typedef BOOL (STDAPICALLTYPE *LPFNBLOCKINPUT)(BOOL);
typedef DWORD (STDAPICALLTYPE* LPFNGETMODULEFILENAME)(HMODULE,LPTSTR,DWORD);
typedef PVOID (STDAPICALLTYPE* LPFNINTERLOCKCMPEXCH)(PVOID *,PVOID,PVOID);
typedef LPVOID (STDAPICALLTYPE* LPFNVIRTUALALLOCEX)(HANDLE,LPVOID,DWORD,DWORD,DWORD);
typedef BOOL (STDAPICALLTYPE* LPFNVIRTUALFREEEX)(HANDLE,LPVOID,DWORD,DWORD);
typedef LONG (STDAPICALLTYPE* LPFNNTQUERYINFORMATIONPROCESS)(HANDLE,INT,PVOID,ULONG,PULONG);
typedef LONG (STDAPICALLTYPE* LPFNNTALLOCATEVIRTUALMEMORY)(HANDLE,PVOID *,ULONG_PTR,PSIZE_T,ULONG,ULONG);
typedef LONG (STDAPICALLTYPE* LPFNNTFREEVIRTUALMEMORY)(HANDLE,PVOID *,PSIZE_T,ULONG);
LPFNGETGUITHREADINFO lpfnGuiThreadInfo; // USER32 GetGUIThreadInfo()
LPFNGETCURSORINFO lpfnCursorInfo; // USER32 GetCursorInfo()
LPFNGETWINDOWINFO lpfnWindowInfo; // USER32 GetWindowInfo()
LPFNGETTITLEBARINFO lpfnTitleBarInfo; // USER32 GetTitleBarInfo()
LPFNGETSCROLLBARINFO lpfnScrollBarInfo; // USER32 GetScrollBarInfo()
LPFNGETCOMBOBOXINFO lpfnComboBoxInfo; // USER32 GetComboBoxInfo()
LPFNGETANCESTOR lpfnGetAncestor; // USER32 GetAncestor()
LPFNREALCHILDWINDOWFROMPOINT lpfnRealChildWindowFromPoint; // USER32 RealChildWindowFromPoint
LPFNREALGETWINDOWCLASS lpfnRealGetWindowClass; // USER32 RealGetWindowClass()
LPFNGETALTTABINFO lpfnAltTabInfo; // USER32 GetAltTabInfo()
LPFNGETLISTBOXINFO lpfnGetListBoxInfo; // USER32 GetListBoxInfo()
LPFNGETMENUBARINFO lpfnMenuBarInfo; // USER32 GetMenuBarInfo()
LPFNSENDINPUT lpfnSendInput; // USER32 SendInput()
LPFNBLOCKINPUT lpfnBlockInput; // USER32 BlockInput()
LPFNGETMODULEFILENAME lpfnGetModuleFileName; // KERNEL32 GetModuleFileName()
LPFNMAPLS lpfnMapLS; // KERNEL32 MapLS()
LPFNUNMAPLS lpfnUnMapLS; // KERNEL32 UnMapLS()
LPFNINTERLOCKCMPEXCH lpfnInterlockedCompareExchange; // NT KERNEL32 InterlockedCompareExchange
LPFNVIRTUALALLOCEX lpfnVirtualAllocEx; // NT KERNEL32 VirtualAllocEx
LPFNVIRTUALFREEEX lpfnVirtualFreeEx; // NT KERNEL32 VirtualFreeEx
LPFNNTQUERYINFORMATIONPROCESS lpfnNtQueryInformationProcess; // NTDLL NtQueryInformationProcess
LPFNNTALLOCATEVIRTUALMEMORY lpfnNtAllocateVirtualMemory; // NTDLL NtAllocateVirtualMemory
LPFNNTFREEVIRTUALMEMORY lpfnNtFreeVirtualMemory; // NTDLL NtAllocateVirtualMemory
// Try getting pName1 first; if that fails, try pName2 instead.
// Both names are in ANSI, since GetProcAddress always takes ANSI names.
struct ImportInfo
{
void * ppfn;
int iModule;
BOOL fNTOnly;
LPCSTR pName1;
LPCSTR pName2;
};
enum {
M_USER, // 0
M_KERN, // 1
M_NTDLL,// 2
};
// _AW_ means add the ...A or ...W suffix as appropriate, for Ansi or Unicode compiles.
// _AONLY_ means only do this on Ansi builds - evaluates to NULL on Unicode compiles.
#ifdef UNICODE
#define _AW_ "W"
#define _AONLY_( str ) NULL
#else
#define _AW_ "A"
#define _AONLY_( str ) str
#endif
ImportInfo g_Imports [ ] =
{
// USER Imports...
{ & lpfnGuiThreadInfo, M_USER, FALSE, "GetGUIThreadInfo" },
{ & lpfnCursorInfo, M_USER, FALSE, "GetAccCursorInfo", "GetCursorInfo" },
{ & lpfnWindowInfo, M_USER, FALSE, "GetWindowInfo" },
{ & lpfnTitleBarInfo, M_USER, FALSE, "GetTitleBarInfo" },
{ & lpfnScrollBarInfo, M_USER, FALSE, "GetScrollBarInfo" },
{ & lpfnComboBoxInfo, M_USER, FALSE, "GetComboBoxInfo" },
{ & lpfnGetAncestor, M_USER, FALSE, "GetAncestor" },
{ & lpfnRealChildWindowFromPoint, M_USER, FALSE, "RealChildWindowFromPoint" },
{ & lpfnRealGetWindowClass, M_USER, FALSE, "RealGetWindowClass" _AW_, _AONLY_( "RealGetWindowClass" ) },
{ & lpfnAltTabInfo, M_USER, FALSE, "GetAltTabInfo" _AW_, _AONLY_( "GetAltTabInfo" ) },
{ & lpfnGetListBoxInfo, M_USER, FALSE, "GetListBoxInfo" },
{ & lpfnMenuBarInfo, M_USER, FALSE, "GetMenuBarInfo" },
{ & lpfnSendInput, M_USER, FALSE, "SendInput" },
{ & lpfnBlockInput, M_USER, FALSE, "BlockInput" },
// KERNEL imports...
{ & lpfnMapLS, M_KERN, FALSE, "MapLS" },
{ & lpfnUnMapLS, M_KERN, FALSE, "UnMapLS" },
{ & lpfnGetModuleFileName, M_KERN, FALSE, "GetModuleFileName" _AW_ },
// KERNEL imports - NT only...
{ & lpfnInterlockedCompareExchange, M_KERN, TRUE, "InterlockedCompareExchange" },
{ & lpfnVirtualAllocEx, M_KERN, TRUE, "VirtualAllocEx" },
{ & lpfnVirtualFreeEx, M_KERN, TRUE, "VirtualFreeEx" },
// NTDLL imports - NT only...
{ & lpfnNtQueryInformationProcess, M_NTDLL, TRUE, "NtQueryInformationProcess" },
{ & lpfnNtAllocateVirtualMemory, M_NTDLL, TRUE, "NtAllocateVirtualMemory" },
{ & lpfnNtFreeVirtualMemory, M_NTDLL, TRUE, "NtFreeVirtualMemory" },
};
#ifdef _DEBUG
LPCTSTR g_ImportNames [ ] =
{
// USER Imports...
TEXT("GetGUIThreadInfo"),
TEXT("GetAccCursorInfo"),
TEXT("GetWindowInfo"),
TEXT("GetTitleBarInfo"),
TEXT("GetScrollBarInfo"),
TEXT("GetComboBoxInfo"),
TEXT("GetAncestor"),
TEXT("RealChildWindowFromPoint"),
TEXT("RealGetWindowClass"),
TEXT("GetAltTabInfo"),
TEXT("GetListBoxInfo"),
TEXT("GetMenuBarInfo"),
TEXT("SendInput"),
TEXT("BlockInput"),
// KERNEL imports...
TEXT("MapLS"),
TEXT("UnMapLS"),
TEXT("GetModuleFileName"),
// KERNEL imports - NT only...
TEXT("InterlockedCompareExchange"),
TEXT("VirtualAllocEx"),
TEXT("VirtualFreeEx"),
// NTDLL imports - NT only...
TEXT("NtQueryInformationProcess"),
TEXT("NtAllocateVirtualMemory"),
};
#endif // _DEBUG
void ImportFromModule( HMODULE * pahModule, ImportInfo * pInfo, int cInfo )
{
for( ; cInfo ; pInfo++, cInfo-- )
{
HMODULE hModule = pahModule[ pInfo->iModule ];
FARPROC pfnAddress = GetProcAddress( hModule, pInfo->pName1 );
// If that didn't work, try the alternate name, if it exists...
if( ! pfnAddress && pInfo->pName2 )
{
pfnAddress = GetProcAddress( hModule, pInfo->pName2 );
}
*( (FARPROC *) pInfo->ppfn ) = pfnAddress;
}
}
void InitImports()
{
HMODULE hModules[ 3 ];
hModules[ 0 ] = GetModuleHandle( TEXT("USER32.DLL") );
hModules[ 1 ] = GetModuleHandle( TEXT("KERNEL32.DLL") );
hModules[ 2 ] = GetModuleHandle( TEXT("NTDLL.DLL") );
ImportFromModule( hModules, g_Imports, ARRAYSIZE( g_Imports ) );
}
#ifdef _DEBUG
void ReportMissingImports( LPTSTR pStr )
{
*pStr = '\0';
for( int c = 0 ; c < ARRAYSIZE( g_Imports ) ; c++ )
{
if( * (FARPROC *) g_Imports[ c ].ppfn == NULL )
{
// Only report the NT-only ones when on 9x...
#ifdef _X86_
if( ! g_Imports[ c ].fNTOnly || ! fWindows95 )
#endif // _X86_
{
lstrcat( pStr, g_ImportNames[ c ] );
lstrcat( pStr, TEXT("\r\n") );
}
}
}
}
#endif // _DEBUG
// --------------------------------------------------------------------------
//
// MyGetGUIThreadInfo()
//
// Calls USER32 function if present. Fills in cbSize field to save callers
// some code.
//
// --------------------------------------------------------------------------
BOOL MyGetGUIThreadInfo(DWORD idThread, PGUITHREADINFO lpGui)
{
if (! lpfnGuiThreadInfo)
return(FALSE);
lpGui->cbSize = sizeof(GUITHREADINFO);
return((* lpfnGuiThreadInfo)(idThread, lpGui));
}
// --------------------------------------------------------------------------
//
// MyGetCursorInfo()
//
// Calls USER32 function if present. Fills in cbSize field to save callers
// some code.
//
// --------------------------------------------------------------------------
BOOL MyGetCursorInfo(LPCURSORINFO lpci)
{
if (! lpfnCursorInfo)
return(FALSE);
lpci->cbSize = sizeof(CURSORINFO);
return((* lpfnCursorInfo)(lpci));
}
// --------------------------------------------------------------------------
//
// MyGetWindowInfo()
//
// Calls USER32 function if present. Fills in cbSize field to save callers
// some code.
//
// --------------------------------------------------------------------------
BOOL MyGetWindowInfo(HWND hwnd, LPWINDOWINFO lpwi)
{
if (!IsWindow(hwnd))
{
DBPRINTF (TEXT("OLEACC: warning - calling MyGetWindowInfo for bad hwnd 0x%x\r\n"),hwnd);
return (FALSE);
}
if (! lpfnWindowInfo)
{
// BOGUS
// beginning of a hack for NT4
{
GetWindowRect(hwnd,&lpwi->rcWindow);
GetClientRect( hwnd, & lpwi->rcClient );
// Convert client rect to screen coords...
MapWindowPoints( hwnd, NULL, (POINT *) & lpwi->rcClient, 2 );
lpwi->dwStyle = GetWindowLong (hwnd,GWL_STYLE);
lpwi->dwExStyle = GetWindowLong (hwnd,GWL_EXSTYLE);
lpwi->dwWindowStatus = 0; // should have WS_ACTIVECAPTION in here if active
lpwi->cxWindowBorders = 0; // wrong
lpwi->cyWindowBorders = 0; // wrong
lpwi->atomWindowType = 0; // wrong, but not used anyways
lpwi->wCreatorVersion = 0; // wrong, only used in SDM proxy. The "WINVER"
return (TRUE);
} // end hack for NT4
return(FALSE);
}
lpwi->cbSize = sizeof(WINDOWINFO);
return((* lpfnWindowInfo)(hwnd, lpwi));
}
// --------------------------------------------------------------------------
//
// MyGetMenuBarInfo()
//
// Calls USER32 function if present. Fills in cbSize field to save callers
// some code.
//
// --------------------------------------------------------------------------
BOOL MyGetMenuBarInfo(HWND hwnd, long idObject, long idItem, LPMENUBARINFO lpmbi)
{
if( ! lpfnMenuBarInfo )
return FALSE;
// Get the hMenu, and then check that it is valid...
// We can only do this for _MENU and _CLIENT.
// Can't use GetSystemMenu for _SYSMENU, since that API *modifies* the
// system menu of the given hwnd.
if( idObject == OBJID_MENU ||
idObject == OBJID_CLIENT )
{
HMENU hMenu;
if( idObject == OBJID_MENU )
{
// GetMenu is not defined for child windows
DWORD dwStyle = GetWindowLong( hwnd, GWL_STYLE );
if( dwStyle & WS_CHILD )
{
hMenu = 0;
}
else
{
hMenu = GetMenu( hwnd );
}
}
else
{
hMenu = (HMENU)SendMessage( hwnd, MN_GETHMENU, 0, 0 );
}
if( ! hMenu || ! IsMenu( hMenu ) )
{
// If we didn't get a valid menu, quit now...
return FALSE;
}
}
else if( idObject != OBJID_SYSMENU )
{
return FALSE;
}
lpmbi->cbSize = sizeof( MENUBARINFO );
return lpfnMenuBarInfo( hwnd, idObject, idItem, lpmbi );
}
// --------------------------------------------------------------------------
//
// MyGetTitleBarInfo()
//
// Calls USER32 function if present. Fills in cbSize field to save callers
// some code.
//
// --------------------------------------------------------------------------
BOOL MyGetTitleBarInfo(HWND hwnd, LPTITLEBARINFO lpti)
{
if (! lpfnTitleBarInfo)
return(FALSE);
lpti->cbSize = sizeof(TITLEBARINFO);
return((* lpfnTitleBarInfo)(hwnd, lpti));
}
// --------------------------------------------------------------------------
//
// MyGetScrollBarInfo
//
// Calls USER32 function if present. Fills in cbSize field to save callers
// some code.
//
// --------------------------------------------------------------------------
BOOL MyGetScrollBarInfo(HWND hwnd, LONG idObject, LPSCROLLBARINFO lpsbi)
{
if (! lpfnScrollBarInfo)
return(FALSE);
lpsbi->cbSize = sizeof(SCROLLBARINFO);
return((* lpfnScrollBarInfo)(hwnd, idObject, lpsbi));
}
// --------------------------------------------------------------------------
//
// MyGetComboBoxInfo()
//
// Calls USER32 if present. Fills in cbSize field for callers.
//
// --------------------------------------------------------------------------
BOOL MyGetComboBoxInfo(HWND hwnd, LPCOMBOBOXINFO lpcbi)
{
if (! lpfnComboBoxInfo)
return(FALSE);
lpcbi->cbSize = sizeof(COMBOBOXINFO);
BOOL b = ((* lpfnComboBoxInfo)(hwnd, lpcbi));
// Some comboxes (eg. comctlV6 port) without edits return a hwndItem
// equal to the combo hwnd instead of NULL (Their logic is that they are
// using themselves as the edit...) We compensate for this here...
if( lpcbi->hwndItem == lpcbi->hwndCombo )
{
// item == combo means this combo doesn't have an edit...
lpcbi->hwndItem = NULL;
}
// ComboEx's have their own child edit that the real COMBO doesn't
// know about - try and find it...
// (This may also be called on a ComboLBox list - but we're safe here
// since it won't have children anyway.)
if( b && lpcbi->hwndItem == NULL )
{
lpcbi->hwndItem = FindWindowEx( hwnd, NULL, TEXT("EDIT"), NULL );
if( lpcbi->hwndItem )
{
// Get real item area from area of Edit.
// (In a ComboEx, there's a gap between the left edge of the
// combo and the left edge of the Edit, where an icon is drawn)
GetWindowRect( lpcbi->hwndItem, & lpcbi->rcItem );
MapWindowPoints( HWND_DESKTOP, hwnd, (POINT*)& lpcbi->rcItem, 2 );
}
}
return b;
}
// --------------------------------------------------------------------------
//
// MyGetAncestor()
//
// This gets the ancestor window where
// GA_PARENT gets the "real" parent window
// GA_ROOT gets the "real" top level parent window (not inc. owner)
// GA_ROOTOWNER gets the "real" top level parent owner
//
// * The _real_ parent. This does NOT include the owner, unlike
// GetParent(). Stops at a top level window unless we start with
// the desktop. In which case, we return the desktop.
// * The _real_ root, caused by walking up the chain getting the
// ancestor.
// * The _real_ owned root, caused by GetParent()ing up.
//
// Note: On Win98, USER32's winable.c:GetAncestor(GA_ROOT) faults is called
// on the invisible alt-tab or system pupop windows. To work-around, we're
// simulating GA_ROOT by looping GA_PARENT (which is actually what winable.c
// does, only we're more careful about checking for NULL handles...)
// - see MSAA bug #891
// --------------------------------------------------------------------------
HWND MyGetAncestor(HWND hwnd, UINT gaFlags)
{
if (! lpfnGetAncestor)
{
// BOGUS
// This block is here to work around the lack of this function in NT4.
// It is modeled on the code in winable2.c in USER.
{
HWND hwndParent;
HWND hwndDesktop;
DWORD dwStyle;
if (!IsWindow(hwnd))
{
//DebugErr(DBF_ERROR, "MyGetAncestor: Bogus window");
return(NULL);
}
if ((gaFlags < GA_MIN) || (gaFlags > GA_MAX))
{
//DebugErr(DBF_ERROR, "MyGetAncestor: Bogus flags");
return(NULL);
}
hwndDesktop = GetDesktopWindow();
if (hwnd == hwndDesktop)
return(NULL);
dwStyle = GetWindowLong (hwnd,GWL_STYLE);
switch (gaFlags)
{
case GA_PARENT:
if (dwStyle & WS_CHILD)
hwndParent = GetParent(hwnd);
else
hwndParent = GetWindow (hwnd,GW_OWNER);
hwnd = hwndParent;
break;
case GA_ROOT:
if (dwStyle & WS_CHILD)
hwndParent = GetParent(hwnd);
else
hwndParent = GetWindow (hwnd,GW_OWNER);
while (hwndParent != hwndDesktop &&
hwndParent != NULL)
{
hwnd = hwndParent;
dwStyle = GetWindowLong(hwnd,GWL_STYLE);
if (dwStyle & WS_CHILD)
hwndParent = GetParent(hwnd);
else
hwndParent = GetWindow (hwnd,GW_OWNER);
}
break;
case GA_ROOTOWNER:
while (hwndParent = GetParent(hwnd))
hwnd = hwndParent;
break;
}
return(hwnd);
} // end of the workaround block for NT4
return(FALSE);
}
else if( gaFlags == GA_ROOT )
{
// BOGUS
// work-around for win98-user inability to handle GA_ROOT
// correctly on alt-tab (WinSwitch) and Popup windows
// - see MSAA bug #891
// (Asise: we *could* special-case 98vs95 - ie. call
// GA_ROOT as usual on 95 and special case only on 98...
// Non special-case-ing may be slightly more inefficient, but
// means that when testing, there's only *one* code path,
// so we don't have to worry about ensuring that the
// win95 version behaves the same as the win98 one.)
HWND hwndDesktop = GetDesktopWindow();
if( ! IsWindow( hwnd ) )
return NULL;
// Climb up through parents - stop if parent is desktop - or NULL...
for( ; ; )
{
HWND hwndParent = lpfnGetAncestor( hwnd, GA_PARENT );
if( hwndParent == NULL || hwndParent == hwndDesktop )
break;
hwnd = hwndParent;
}
return hwnd;
}
else
{
return lpfnGetAncestor(hwnd, gaFlags);
}
}
// --------------------------------------------------------------------------
//
// MyRealChildWindowFromPoint()
//
// --------------------------------------------------------------------------
#if 0
// Old version - called USER's 'RealChildWindowFromPoint'.
HWND MyRealChildWindowFromPoint(HWND hwnd, POINT pt)
{
if (! lpfnRealChildWindowFromPoint)
{
// BOGUS
// beginning of a hack for NT4
{
return (ChildWindowFromPoint(hwnd,pt));
} // end of a hack for NT4
return(NULL);
}
return((* lpfnRealChildWindowFromPoint)(hwnd, pt));
}
#endif
/*
* Similar to USER's ChildWindowFromPoint, except this
* checks the HT_TRANSPARENT bit.
* USER's ChildWindowFromPoint can't "see through" groupboxes or
* other HTTRANSPARENT things,
* USER's RealChildWindowFromPoint can "see through" groupboxes but
* not other HTTRANSPARENT things (it special cases only groupboxes!)
* This can see through anything that responds to WM_NCHITTEST with
* HTTRANSPARENT.
*/
HWND MyRealChildWindowFromPoint( HWND hwnd,
POINT pt )
{
HWND hBestFitTransparent = NULL;
RECT rcBest;
// Translate hwnd-relative points to screen-relative...
MapWindowPoints( hwnd, NULL, & pt, 1 );
// Infinite looping is 'possible' (though unlikely) when
// using GetWindow(...NEXT), so we counter-limit this loop...
int SanityLoopCount = 1024;
for( HWND hChild = GetWindow( hwnd, GW_CHILD ) ;
hChild && --SanityLoopCount ;
hChild = GetWindow( hChild, GW_HWNDNEXT ) )
{
// Skip invisible...
if( ! IsWindowVisible( hChild ) )
continue;
// Check for rect...
RECT rc;
GetWindowRect( hChild, & rc );
if( ! PtInRect( & rc, pt ) )
continue;
// Try for transparency...
LRESULT lr = SendMessage( hChild, WM_NCHITTEST, 0, MAKELPARAM( pt.x, pt.y ) );
if( lr == HTTRANSPARENT )
{
// For reasons best known to the writers of USER, statics - used
// as labels - claim to be transparent. So that we do hit-test
// to these, we remember the hwnd here, so if nothing better
// comes along, we'll use this.
// If we come accross two or more of these, we remember the
// one that fts inside the other - if any. That way,
// we hit-test to siblings 'within' siblings - eg. statics in
// a groupbox.
if( ! hBestFitTransparent )
{
hBestFitTransparent = hChild;
GetWindowRect( hChild, & rcBest );
}
else
{
// Is this child within the last remembered transparent?
// If so, remember it instead.
RECT rcChild;
GetWindowRect( hChild, & rcChild );
if( rcChild.left >= rcBest.left &&
rcChild.top >= rcBest.top &&
rcChild.right <= rcBest.right &&
rcChild.bottom <= rcBest.bottom )
{
hBestFitTransparent = hChild;
rcBest = rcChild;
}
}
continue;
}
// Got the window!
return hChild;
}
if( SanityLoopCount == 0 )
return NULL;
// Did we find a transparent (eg. a static) on our travels? If so, since
// we couldn't find anything better, may as well use it.
if( hBestFitTransparent )
return hBestFitTransparent;
// Otherwise return the original window (not NULL!) if no child found...
return hwnd;
}
// --------------------------------------------------------------------------
//
// MyGetWindowClass()
//
// Gets the "real" window type, works for superclassers like "ThunderEdit32"
// and so on.
//
// --------------------------------------------------------------------------
UINT MyGetWindowClass(HWND hwnd, LPTSTR lpszName, UINT cchName)
{
*lpszName = 0;
if (! lpfnRealGetWindowClass)
{
// BOGUS
// Hack for NT 4
{
return (GetClassName(hwnd,lpszName,cchName));
} // end of hack for NT 4
return(0);
}
return((* lpfnRealGetWindowClass)(hwnd, lpszName, cchName));
}
// --------------------------------------------------------------------------
//
// MyGetAltTabInfo()
//
// Gets the alt tab information
//
// --------------------------------------------------------------------------
BOOL MyGetAltTabInfo(HWND hwnd, int iItem, LPALTTABINFO lpati, LPTSTR lpszItem,
UINT cchItem)
{
if (! lpfnAltTabInfo)
return(FALSE);
lpati->cbSize = sizeof(ALTTABINFO);
return((* lpfnAltTabInfo)(hwnd, iItem, lpati, lpszItem, cchItem));
}
// --------------------------------------------------------------------------
//
// MyGetListBoxInfo()
//
// Gets the # of items per column currently in a listbox
//
// --------------------------------------------------------------------------
DWORD MyGetListBoxInfo(HWND hwnd)
{
if (! lpfnGetListBoxInfo)
return(0);
return((* lpfnGetListBoxInfo)(hwnd));
}
// --------------------------------------------------------------------------
//
// MySendInput()
//
// Calls USER32 function if present.
//
// --------------------------------------------------------------------------
BOOL MySendInput(UINT cInputs, LPINPUT pInputs, INT cbSize)
{
if (! lpfnSendInput)
return(FALSE);
return((* lpfnSendInput)(cInputs,pInputs,cbSize));
}
//--------------------------------------------------------
// [v-jaycl, 6/7/97] Added MyBlockInput support for NT 4.0
//--------------------------------------------------------
// --------------------------------------------------------------------------
//
// MyBlockInput()
//
// Calls USER32 function if present.
//
// --------------------------------------------------------------------------
BOOL MyBlockInput(BOOL bBlock)
{
if (! lpfnBlockInput)
return(FALSE);
return((* lpfnBlockInput)( bBlock ) );
}
// --------------------------------------------------------------------------
// MyInterlockedCompareExchange
//
// Calls the function when we are running on NT
// --------------------------------------------------------------------------
PVOID MyInterlockedCompareExchange(PVOID *Destination,PVOID Exchange,PVOID Comperand)
{
if (!lpfnInterlockedCompareExchange)
return (NULL);
return ((* lpfnInterlockedCompareExchange)(Destination,Exchange,Comperand));
}
// --------------------------------------------------------------------------
// MyVirtualAllocEx
//
// Calls the function when we are running on NT
// --------------------------------------------------------------------------
LPVOID MyVirtualAllocEx(HANDLE hProcess,LPVOID lpAddress,DWORD dwSize,DWORD flAllocationType,DWORD flProtect)
{
if (!lpfnVirtualAllocEx)
return (NULL);
return ((* lpfnVirtualAllocEx)(hProcess,lpAddress,dwSize,flAllocationType,flProtect));
}
// --------------------------------------------------------------------------
// MyVirtualFreeEx
//
// Calls the function when we are running on NT.
// --------------------------------------------------------------------------
BOOL MyVirtualFreeEx(HANDLE hProcess,LPVOID lpAddress,DWORD dwSize,DWORD dwFreeType)
{
if (!lpfnVirtualFreeEx)
return (FALSE);
return ((* lpfnVirtualFreeEx)(hProcess,lpAddress,dwSize,dwFreeType));
}
// --------------------------------------------------------------------------
// MyGetModuleFileName
// --------------------------------------------------------------------------
DWORD MyGetModuleFileName(HMODULE hModule,LPTSTR lpFilename,DWORD nSize)
{
if (!lpfnGetModuleFileName)
return (0);
return ((* lpfnGetModuleFileName)(hModule,lpFilename,nSize));
}
// --------------------------------------------------------------------------
// MyNtQueryInformationProcess
//
// Calls the function when we are running on NT.
// --------------------------------------------------------------------------
LONG MyNtQueryInformationProcess(HANDLE hProcess, INT iProcInfo, PVOID pvBuf, ULONG ccbBuf, PULONG pulRetLen)
{
if (!lpfnNtQueryInformationProcess)
return -1;
return (* lpfnNtQueryInformationProcess)(hProcess, iProcInfo, pvBuf, ccbBuf, pulRetLen);
}
void * Alloc_32BitCompatible( SIZE_T cbSize )
{
#ifndef _WIN64
return new BYTE [ cbSize ];
#else
if( ! lpfnNtAllocateVirtualMemory
|| ! lpfnNtFreeVirtualMemory )
{
return new BYTE [ cbSize ];
}
// Note that the mask-style of the ZeroBits param only works on Win64. This
// mask specifies which bits may be used in the address. 7FFFFFFF -> 31-bit
// address
// ISSUE-2000/08/11-brendanm
// Since granularity of returned blocks is 64k, we should do some sort of
// block suballocation to avoid wasting memory.
PVOID pBaseAddress = NULL;
LONG ret = lpfnNtAllocateVirtualMemory( GetCurrentProcess(),
& pBaseAddress,
0x7FFFFFFF,
& cbSize,
MEM_COMMIT,
PAGE_READWRITE );
if( ret < 0 )
{
return NULL;
}
return pBaseAddress;
#endif
}
void Free_32BitCompatible( void * pv )
{
#ifndef _WIN64
delete [ ] (BYTE *) pv;
#else
if( ! lpfnNtAllocateVirtualMemory
|| ! lpfnNtFreeVirtualMemory )
{
delete [ ] (BYTE *) pv;
}
DWORD_PTR cbSize = 0;
lpfnNtFreeVirtualMemory( GetCurrentProcess(), & pv, & cbSize, MEM_RELEASE );
#endif
}