255 lines
4.4 KiB
C++
255 lines
4.4 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
IgnoreHungAppPaint.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Setup the hollow brush to prevent user from trashing peoples windows.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This is a general purpose shim.
|
||
|
|
||
|
History:
|
||
|
|
||
|
12/04/2000 linstev Created
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include "LegalStr.h"
|
||
|
|
||
|
IMPLEMENT_SHIM_BEGIN(IgnoreHungAppPaint)
|
||
|
#include "ShimHookMacro.h"
|
||
|
|
||
|
APIHOOK_ENUM_BEGIN
|
||
|
APIHOOK_ENUM_ENTRY(RegisterClassA)
|
||
|
APIHOOK_ENUM_ENTRY(RegisterClassW)
|
||
|
APIHOOK_ENUM_ENTRY(RegisterClassExA)
|
||
|
APIHOOK_ENUM_ENTRY(RegisterClassExW)
|
||
|
APIHOOK_ENUM_END
|
||
|
|
||
|
struct HUNGCLASS
|
||
|
{
|
||
|
char szClass[MAX_PATH];
|
||
|
HUNGCLASS *next;
|
||
|
};
|
||
|
HUNGCLASS *g_lHungList = NULL;
|
||
|
|
||
|
BOOL g_bAll = FALSE;
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Check if a class needs a hollow brush.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
IsHungClassA(LPCSTR szClass)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
if (szClass)
|
||
|
{
|
||
|
HUNGCLASS *h = g_lHungList;
|
||
|
while (h)
|
||
|
{
|
||
|
if (_stricmp(szClass, h->szClass) == 0)
|
||
|
{
|
||
|
LOGN(eDbgLevelWarning, "Matched hung class: forcing HOLLOW_BRUSH");
|
||
|
|
||
|
bRet = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
h = h->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Check if a class needs a hollow brush.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
IsHungClassW(LPCWSTR wszClass)
|
||
|
{
|
||
|
CHAR szClass[MAX_PATH];
|
||
|
|
||
|
WideCharToMultiByte(
|
||
|
CP_ACP,
|
||
|
0,
|
||
|
(LPWSTR) wszClass,
|
||
|
MAX_PATH,
|
||
|
(LPSTR) szClass,
|
||
|
MAX_PATH,
|
||
|
0,
|
||
|
0);
|
||
|
|
||
|
return IsHungClassA(szClass);
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Hook all possible calls that can initialize or change a window's
|
||
|
WindowProc (or DialogProc)
|
||
|
|
||
|
--*/
|
||
|
|
||
|
ATOM
|
||
|
APIHOOK(RegisterClassA)(
|
||
|
WNDCLASSA *lpWndClass
|
||
|
)
|
||
|
{
|
||
|
if (lpWndClass && (g_bAll || IsHungClassA(lpWndClass->lpszClassName)))
|
||
|
{
|
||
|
lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
|
||
|
}
|
||
|
|
||
|
return ORIGINAL_API(RegisterClassA)(lpWndClass);
|
||
|
}
|
||
|
|
||
|
ATOM
|
||
|
APIHOOK(RegisterClassW)(
|
||
|
WNDCLASSW *lpWndClass
|
||
|
)
|
||
|
{
|
||
|
if (lpWndClass && IsHungClassW(lpWndClass->lpszClassName))
|
||
|
{
|
||
|
lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
|
||
|
}
|
||
|
|
||
|
return ORIGINAL_API(RegisterClassW)(lpWndClass);
|
||
|
}
|
||
|
|
||
|
ATOM
|
||
|
APIHOOK(RegisterClassExA)(
|
||
|
WNDCLASSEXA *lpWndClass
|
||
|
)
|
||
|
{
|
||
|
if (lpWndClass && IsHungClassA(lpWndClass->lpszClassName))
|
||
|
{
|
||
|
lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
|
||
|
}
|
||
|
|
||
|
return ORIGINAL_API(RegisterClassExA)(lpWndClass);
|
||
|
}
|
||
|
|
||
|
ATOM
|
||
|
APIHOOK(RegisterClassExW)(
|
||
|
WNDCLASSEXW *lpWndClass
|
||
|
)
|
||
|
{
|
||
|
if (lpWndClass && IsHungClassW(lpWndClass->lpszClassName))
|
||
|
{
|
||
|
lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
|
||
|
}
|
||
|
|
||
|
return ORIGINAL_API(RegisterClassExW)(lpWndClass);
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Parse the command line for fixes:
|
||
|
|
||
|
CLASS1; CLASS2; CLASS3 ...
|
||
|
|
||
|
--*/
|
||
|
|
||
|
VOID
|
||
|
ParseCommandLineA(
|
||
|
LPCSTR lpCommandLine
|
||
|
)
|
||
|
{
|
||
|
// Add all the defaults if no command line is specified
|
||
|
if (!lpCommandLine || (lpCommandLine[0] == '\0'))
|
||
|
{
|
||
|
g_bAll = TRUE;
|
||
|
DPFN(eDbgLevelInfo, "All classes will use HOLLOW_BRUSH");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char seps[] = " ,\t;";
|
||
|
char *token = NULL;
|
||
|
|
||
|
// Since strtok modifies the string, we need to copy it
|
||
|
LPSTR szCommandLine = (LPSTR) malloc(strlen(lpCommandLine) + 1);
|
||
|
if (!szCommandLine) goto Exit;
|
||
|
|
||
|
strcpy(szCommandLine, lpCommandLine);
|
||
|
|
||
|
//
|
||
|
// Run the string, looking for fix names
|
||
|
//
|
||
|
|
||
|
token = _strtok(szCommandLine, seps);
|
||
|
while (token)
|
||
|
{
|
||
|
HUNGCLASS *h;
|
||
|
|
||
|
h = (HUNGCLASS *) malloc(sizeof(HUNGCLASS));
|
||
|
if (h)
|
||
|
{
|
||
|
h->next = g_lHungList;
|
||
|
g_lHungList = h;
|
||
|
|
||
|
strncpy(h->szClass, token, MAX_PATH);
|
||
|
DPFN(eDbgLevelInfo, "Adding %s", token);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DPFN(eDbgLevelError, "Out of memory");
|
||
|
}
|
||
|
|
||
|
// Get the next token
|
||
|
token = _strtok(NULL, seps);
|
||
|
}
|
||
|
|
||
|
Exit:
|
||
|
if (szCommandLine)
|
||
|
{
|
||
|
free(szCommandLine);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Register hooked functions
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
NOTIFY_FUNCTION(
|
||
|
DWORD fdwReason
|
||
|
)
|
||
|
{
|
||
|
if (fdwReason == DLL_PROCESS_ATTACH) {
|
||
|
ParseCommandLineA(COMMAND_LINE);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
HOOK_BEGIN
|
||
|
|
||
|
CALL_NOTIFY_FUNCTION
|
||
|
APIHOOK_ENTRY(USER32.DLL, RegisterClassA)
|
||
|
APIHOOK_ENTRY(USER32.DLL, RegisterClassW);
|
||
|
APIHOOK_ENTRY(USER32.DLL, RegisterClassExA);
|
||
|
APIHOOK_ENTRY(USER32.DLL, RegisterClassExW);
|
||
|
|
||
|
HOOK_END
|
||
|
|
||
|
|
||
|
IMPLEMENT_SHIM_END
|
||
|
|