|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
ClueFinders3rdGrade.cpp
Abstract:
This shim simulates the behaviour of Win9x wrt static controls and Get/SetWindowText. Basically, Win9x stored the resource id for a static control in it's name. On NT, this isn't stored.
We used to set a low-level window hook that catches the CreateWindow calls, but gave up because it kept regressing and it would be too expensive for the layer.
Notes: This is an app specific shim.
History:
06/19/2000 linstev Created 11/17/2000 linstev Made app specific
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(ClueFinders3rdGrade) #include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN APIHOOK_ENUM_ENTRY(GetWindowTextA) APIHOOK_ENUM_ENTRY(SetWindowTextA) APIHOOK_ENUM_ENTRY(CreateDialogIndirectParamA) APIHOOK_ENUM_END
typedef HMODULE (*_pfn_GetModuleHandleA)(LPCSTR lpModuleName); //
// List of static handles
//
struct HWNDITEM { HWND hWnd; DWORD dwRsrcId; HWNDITEM *next; }; HWNDITEM *g_hWndList = NULL;
//
// Handle to use for CallNextHook
//
HHOOK g_hHookCbt = 0;
//
// Critical section for list access
//
CRITICAL_SECTION g_csList;
/*++
Search the window list for a resource id if GetWindowTextA fails.
--*/
int APIHOOK(GetWindowTextA)( HWND hWnd, LPSTR lpString, int nMaxCount ) { int iRet = ORIGINAL_API(GetWindowTextA)( hWnd, lpString, nMaxCount);
if (iRet == 0) { //
// Check for Resource Id
//
EnterCriticalSection(&g_csList);
HWNDITEM *hitem = g_hWndList; while (hitem) { if (hitem->hWnd == hWnd) { //
// Copy the resource id into the buffer
//
if ((hitem->dwRsrcId != (DWORD)-1) && (nMaxCount >= 3)) { MoveMemory(lpString, (LPBYTE) &hitem->dwRsrcId + 1, 3); iRet = 2; DPFN( eDbgLevelError, "Returning ResourceId: %08lx for HWND=%08lx", *(LPDWORD)lpString, hWnd); }
break; } hitem = hitem->next; }
LeaveCriticalSection(&g_csList); }
return iRet; } /*++
Hook SetWindowText so the list is kept in sync.
--*/
BOOL APIHOOK(SetWindowTextA)( HWND hWnd, LPCSTR lpString ) { //
// Set the text for this window if it's in our list
//
EnterCriticalSection(&g_csList); HWNDITEM *hitem = g_hWndList; while (hitem) { if (hitem->hWnd == hWnd) { if (lpString && (*(LPBYTE) lpString == 0xFF)) { hitem->dwRsrcId = *(LPDWORD) lpString; }
break; }
hitem = hitem->next; } LeaveCriticalSection(&g_csList);
return ORIGINAL_API(SetWindowTextA)(hWnd, lpString); }
/*++
Hook to find CreateWindow calls and get the attached resource id.
--*/
LRESULT CALLBACK CBTProcW( int nCode, WPARAM wParam, LPARAM lParam ) { HWND hWnd = (HWND) wParam; LPCBT_CREATEWNDW pCbtWnd;
switch (nCode) { case HCBT_CREATEWND:
//
// Add to our list of windows if it's a static - or we don't know
//
pCbtWnd = (LPCBT_CREATEWNDW) lParam;
if (pCbtWnd && pCbtWnd->lpcs && pCbtWnd->lpcs->lpszClass && (IsBadReadPtr(pCbtWnd->lpcs->lpszClass, 4) || (_wcsicmp(pCbtWnd->lpcs->lpszClass, L"static") == 0))) { HWNDITEM *hitem = (HWNDITEM *) malloc(sizeof(HWNDITEM));
if (hitem) { hitem->hWnd = hWnd;
//
// Check for a resource id in the name
//
if (pCbtWnd->lpcs->lpszName && (*(LPBYTE) pCbtWnd->lpcs->lpszName == 0xFF)) { hitem->dwRsrcId = *(LPDWORD) pCbtWnd->lpcs->lpszName; } else { hitem->dwRsrcId = (DWORD)-1; }
//
// Update our list
//
EnterCriticalSection(&g_csList); hitem->next = g_hWndList; g_hWndList = hitem; LeaveCriticalSection(&g_csList);
DPFN( eDbgLevelError, "CreateWindow HWND=%08lx, ResourceId=%08lx", hitem->hWnd, hitem->dwRsrcId); } else { DPFN( eDbgLevelError, "Failed to allocate list item"); } } break;
case HCBT_DESTROYWND: //
// Remove the window from our list
//
EnterCriticalSection(&g_csList);
HWNDITEM *hitem = g_hWndList, *hprev = NULL; while (hitem) { if (hitem->hWnd == hWnd) { if (hprev) { hprev->next = hitem->next; } else { g_hWndList = hitem->next; }
free(hitem);
DPFN( eDbgLevelError, "DestroyWindow %08lx", hWnd);
break; } hprev = hitem; hitem = hitem->next; }
LeaveCriticalSection(&g_csList);
break; }
return CallNextHookEx(g_hHookCbt, nCode, wParam, lParam); }
/*++
Hook CreateDialog which is where the problem occurs
--*/
HWND APIHOOK(CreateDialogIndirectParamA)( HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit ) { if (!g_hHookCbt) { g_hHookCbt = SetWindowsHookExW(WH_CBT, CBTProcW, GetModuleHandleW(0), 0); DPFN( eDbgLevelInfo, "[CreateDialogIndirectParamA] Hook added"); }
HWND hRet = ORIGINAL_API(CreateDialogIndirectParamA)( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit);
if (g_hHookCbt) { UnhookWindowsHookEx(g_hHookCbt); g_hHookCbt = 0; }
return hRet; }
/*++
Register hooked functions
--*/
BOOL NOTIFY_FUNCTION( DWORD fdwReason) { if (fdwReason == DLL_PROCESS_ATTACH) { //
// Initialize our critical section here
//
if (!InitializeCriticalSectionAndSpinCount(&g_csList, 0x80000000)) { return FALSE; }
} else if (fdwReason == DLL_PROCESS_DETACH) { //
// Clear the hook
//
if (g_hHookCbt) { UnhookWindowsHookEx(g_hHookCbt); } }
return TRUE; }
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY(USER32.DLL, GetWindowTextA) APIHOOK_ENTRY(USER32.DLL, SetWindowTextA) APIHOOK_ENTRY(USER32.DLL, CreateDialogIndirectParamA)
HOOK_END
IMPLEMENT_SHIM_END
|