From 4f4b0cf732ca3ce5b29c9569cfb0c4c48aa67941 Mon Sep 17 00:00:00 2001 From: narzoul Date: Thu, 24 Mar 2016 23:12:28 +0100 Subject: [PATCH] Disabled immersive context menus Immersive context menus don't display correctly when theming is disabled: all menu items have empty labels and no icons. Disabled this menu style through a faked registry value. --- DDrawCompat/CompatGdiPaintHandlers.cpp | 8 ++ DDrawCompat/CompatRegistry.cpp | 103 ++++++++++++++++++++++++ DDrawCompat/CompatRegistry.h | 11 +++ DDrawCompat/DDrawCompat.vcxproj | 2 + DDrawCompat/DDrawCompat.vcxproj.filters | 6 ++ DDrawCompat/DDrawLog.h | 8 ++ DDrawCompat/DllMain.cpp | 4 + DDrawCompat/Hook.cpp | 2 +- 8 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 DDrawCompat/CompatRegistry.cpp create mode 100644 DDrawCompat/CompatRegistry.h diff --git a/DDrawCompat/CompatGdiPaintHandlers.cpp b/DDrawCompat/CompatGdiPaintHandlers.cpp index 272e78b..87afd39 100644 --- a/DDrawCompat/CompatGdiPaintHandlers.cpp +++ b/DDrawCompat/CompatGdiPaintHandlers.cpp @@ -3,6 +3,7 @@ #include "CompatGdiPaintHandlers.h" #include "CompatGdiScrollBar.h" #include "CompatGdiTitleBar.h" +#include "CompatRegistry.h" #include "DDrawLog.h" #include "Hook.h" @@ -297,6 +298,13 @@ namespace CompatGdiPaintHandlers { void installHooks() { + // Immersive context menus don't display properly (empty items) when theming is disabled + CompatRegistry::setValue( + HKEY_LOCAL_MACHINE, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FlightedFeatures", + "ImmersiveContextMenu", + 0); + CompatGdi::hookWndProc("Edit", g_origEditWndProc, &editWndProc); CompatGdi::hookWndProc("ListBox", g_origListBoxWndProc, &listBoxWndProc); CompatGdi::hookWndProc("#32768", g_origMenuWndProc, &menuWndProc); diff --git a/DDrawCompat/CompatRegistry.cpp b/DDrawCompat/CompatRegistry.cpp new file mode 100644 index 0000000..4652702 --- /dev/null +++ b/DDrawCompat/CompatRegistry.cpp @@ -0,0 +1,103 @@ +#include +#include +#include + +#include + +#include "CompatRegistry.h" +#include "DDrawLog.h" +#include "Hook.h" + +namespace +{ + struct RegistryKey + { + HKEY key; + CStringW subKey; + CStringW value; + + RegistryKey(HKEY key, CStringW subKey, CStringW value) : key(key), subKey(subKey), value(value) {} + + bool operator<(const RegistryKey& rhs) const + { + if (key < rhs.key) { return true; } + if (key > rhs.key) { return false; } + const int subKeyComp = subKey.CompareNoCase(rhs.subKey); + if (subKeyComp < 0) { return true; } + if (subKeyComp > 0) { return false; } + return value.CompareNoCase(rhs.value) < 0; + } + + bool operator==(const RegistryKey& rhs) const + { + return key == rhs.key && + 0 == subKey.CompareNoCase(rhs.subKey) && + 0 == value.CompareNoCase(rhs.value); + } + }; + + std::map g_registryOverride; + + LSTATUS WINAPI regGetValueW(HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue, + DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData) + { + Compat::LogEnter("regGetValueW", hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + LSTATUS result = ERROR_SUCCESS; + + const auto it = hkey && lpSubKey && lpValue && (dwFlags & RRF_RT_REG_DWORD) + ? g_registryOverride.find(RegistryKey(hkey, lpSubKey, lpValue)) + : g_registryOverride.end(); + + if (it != g_registryOverride.end()) + { + if (pdwType) + { + *pdwType = REG_DWORD; + } + + if (pvData) + { + if (!pcbData) + { + result = ERROR_INVALID_PARAMETER; + } + else if (*pcbData >= sizeof(DWORD)) + { + std::memcpy(pvData, &it->second, sizeof(DWORD)); + } + else + { + result = ERROR_MORE_DATA; + } + } + + if (pcbData) + { + *pcbData = sizeof(DWORD); + } + } + else + { + result = CALL_ORIG_FUNC(RegGetValueW)(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + } + + Compat::LogLeave("regGetValueW", hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData) << result; + return result; + } +} + +namespace CompatRegistry +{ + void installHooks() + { + Compat::beginHookTransaction(); + HOOK_FUNCTION(KernelBase, RegGetValueW, regGetValueW); + Compat::endHookTransaction(); + } + + void setValue(HKEY key, const char* subKey, const char* valueName, DWORD value) + { + assert(key && subKey && valueName); + g_registryOverride[RegistryKey(key, subKey, valueName)] = value; + } +} diff --git a/DDrawCompat/CompatRegistry.h b/DDrawCompat/CompatRegistry.h new file mode 100644 index 0000000..1411791 --- /dev/null +++ b/DDrawCompat/CompatRegistry.h @@ -0,0 +1,11 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN + +#include + +namespace CompatRegistry +{ + void installHooks(); + void setValue(HKEY key, const char* subKey, const char* valueName, DWORD value); +} diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index f40baa4..142578d 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -155,6 +155,7 @@ + @@ -185,6 +186,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index a1420c1..d85158d 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -96,6 +96,9 @@ Header Files + + Header Files + @@ -164,6 +167,9 @@ Source Files + + Source Files + diff --git a/DDrawCompat/DDrawLog.h b/DDrawCompat/DDrawLog.h index b1791d7..108be79 100644 --- a/DDrawCompat/DDrawLog.h +++ b/DDrawCompat/DDrawLog.h @@ -93,6 +93,8 @@ namespace Compat }; #ifdef _DEBUG + typedef Log LogDebug; + class LogEnter : private Log { public: @@ -117,6 +119,12 @@ namespace Compat } }; #else + class LogDebug + { + public: + template LogDebug& operator<<(const T&) { return *this; } + }; + class LogEnter { public: diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index 0f98350..423c2e8 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -9,6 +9,7 @@ #include "CompatDirectDrawSurface.h" #include "CompatDirectDrawPalette.h" #include "CompatGdi.h" +#include "CompatRegistry.h" #include "CompatVtable.h" #include "DDrawProcs.h" @@ -102,6 +103,9 @@ namespace Compat::Log() << "Installing GDI hooks"; CompatGdi::installHooks(); + Compat::Log() << "Installing registry hooks"; + CompatRegistry::installHooks(); + dd->lpVtbl->Release(dd); } else diff --git a/DDrawCompat/Hook.cpp b/DDrawCompat/Hook.cpp index 0aaecd4..2f9d05f 100644 --- a/DDrawCompat/Hook.cpp +++ b/DDrawCompat/Hook.cpp @@ -69,7 +69,7 @@ namespace Compat FARPROC procAddr = getProcAddress(GetModuleHandle(moduleName), funcName); if (!procAddr) { - Compat::Log() << "Failed to load the address of a function: " << funcName; + Compat::LogDebug() << "Failed to load the address of a function: " << funcName; return; }