windows-nt/Source/XPSP1/NT/windows/appcompat/shims/general/ignorehungapppaint.cpp

255 lines
4.4 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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