227 lines
4.7 KiB
C++
227 lines
4.7 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
|
||
|
|