Windows2003-3790/windows/appcompat/shims/general/ignorenomodechange.cpp
2020-09-30 16:53:55 +02:00

227 lines
4.9 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
IgnoreNoModeChange.cpp
Abstract:
Ignore mode changes that are not really different from the current mode.
The problem is that even if there is no real mode change, the uniqueness
value for the mode is still updated. DirectDraw checks this value every
time it enters any API and if the mode uniqueness value has changed, it
resets all it's objects.
Applications will hit this if they call ChangeDisplaySettings* and don't
realize that even if the mode is identical, they'll still have to reset
all their objects.
Notes:
This is a general purpose shim.
History:
01/20/2000 linstev Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(IgnoreNoModeChange)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsA)
APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsW)
APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsExA)
APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsExW)
APIHOOK_ENUM_END
BOOL
IsModeEqual(
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBitsPerPel,
DWORD dwRefresh
)
{
BOOL bRet = FALSE;
DEVMODEA dm;
dm.dmSize = sizeof(DEVMODEA);
//
// Get the existing settings.
//
if (EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &dm)) {
//
// Assume that 0 or 1 means default refresh.
//
if (dwRefresh <= 1) {
dwRefresh = dm.dmDisplayFrequency;
}
bRet = (dwWidth == dm.dmPelsWidth) &&
(dwHeight == dm.dmPelsHeight) &&
(dwBitsPerPel == dm.dmBitsPerPel) &&
(dwRefresh == dm.dmDisplayFrequency);
}
if (bRet) {
LOGN(
eDbgLevelInfo,
"[IsModeEqual] Ignoring irrelevant mode change.");
} else {
LOGN(
eDbgLevelInfo,
"Mode change is required.");
}
return bRet;
}
/*++
Force temporary change.
--*/
LONG
APIHOOK(ChangeDisplaySettingsA)(
LPDEVMODEA lpDevMode,
DWORD dwFlags
)
{
if (lpDevMode &&
IsModeEqual(
lpDevMode->dmPelsWidth,
lpDevMode->dmPelsHeight,
lpDevMode->dmBitsPerPel,
lpDevMode->dmDisplayFrequency)) {
return DISP_CHANGE_SUCCESSFUL;
}
return ORIGINAL_API(ChangeDisplaySettingsA)(
lpDevMode,
CDS_FULLSCREEN);
}
/*++
Force temporary change.
--*/
LONG
APIHOOK(ChangeDisplaySettingsW)(
LPDEVMODEW lpDevMode,
DWORD dwFlags
)
{
if (lpDevMode &&
IsModeEqual(
lpDevMode->dmPelsWidth,
lpDevMode->dmPelsHeight,
lpDevMode->dmBitsPerPel,
lpDevMode->dmDisplayFrequency)) {
return DISP_CHANGE_SUCCESSFUL;
}
return ORIGINAL_API(ChangeDisplaySettingsW)(
lpDevMode,
CDS_FULLSCREEN);
}
/*++
Force temporary change.
--*/
LONG
APIHOOK(ChangeDisplaySettingsExA)(
LPCSTR lpszDeviceName,
LPDEVMODEA lpDevMode,
HWND hwnd,
DWORD dwflags,
LPVOID lParam
)
{
if (lpDevMode &&
IsModeEqual(
lpDevMode->dmPelsWidth,
lpDevMode->dmPelsHeight,
lpDevMode->dmBitsPerPel,
lpDevMode->dmDisplayFrequency)) {
return DISP_CHANGE_SUCCESSFUL;
}
return ORIGINAL_API(ChangeDisplaySettingsExA)(
lpszDeviceName,
lpDevMode,
hwnd,
CDS_FULLSCREEN,
lParam);
}
/*++
Force temporary change.
--*/
LONG
APIHOOK(ChangeDisplaySettingsExW)(
LPCWSTR lpszDeviceName,
LPDEVMODEW lpDevMode,
HWND hwnd,
DWORD dwflags,
LPVOID lParam
)
{
if (lpDevMode &&
IsModeEqual(
lpDevMode->dmPelsWidth,
lpDevMode->dmPelsHeight,
lpDevMode->dmBitsPerPel,
lpDevMode->dmDisplayFrequency)) {
return DISP_CHANGE_SUCCESSFUL;
}
return ORIGINAL_API(ChangeDisplaySettingsExW)(
lpszDeviceName,
lpDevMode,
hwnd,
CDS_FULLSCREEN,
lParam);
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsA)
APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsW)
APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsExA)
APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsExW)
HOOK_END
IMPLEMENT_SHIM_END