Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions ExplorerPatcher/dllmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -11538,6 +11538,71 @@ DWORD StartUI_EnableRoundedCornersApply = TRUE;
DWORD StartUI_ShowMoreTiles = FALSE;
HKEY hKey_StartUI_TileGrid = NULL;

/*
* Fix bug where Recommended section would re-appear.
*
* Various interactions inside the Start Menu trigger OnSettingChanged(),
* which in turn calls UpdatePinnedListHeight(), which causes the problem.
* So hook OnSettingChanged(), mark that it has been called, and, when
* UpdatePinnedListHeight() is called afterwards, return from it.
*
* Pinned List Height can still be adjusted from Settings.
*
*/

static BOOL b_IsFromOnSettingChanged = 0;

typedef uintptr_t (__fastcall* StartMenu_OnSettingChanged_t)(
void* _this,
uintptr_t param_2,
void* param_3,
void* param_4
);

typedef void(__fastcall* StartMenu_UpdatePinnedListHeight_t)(
void* _this
);

static StartMenu_OnSettingChanged_t StartMenu_OnSettingChangedFunc = NULL;

static StartMenu_UpdatePinnedListHeight_t
StartMenu_UpdatePinnedListHeightFunc = NULL;

void __fastcall StartMenu_OnSettingChangedHook(void* _this, uintptr_t param_2, void* param_3, void* param_4)
{
// Mark that OnSettingChanged() has ran, if DisableRecommended is set
if (StartDocked_DisableRecommendedSection)
b_IsFromOnSettingChanged = TRUE;
StartMenu_OnSettingChangedFunc(_this, param_2, param_3, param_4);

/* OnSettingChanged() always returns before UpdatePinnedListHeight() is called.
* There is a chance that, in future (or some undocumented Insider) versions
* of Windows that do not call UpdatePinnedListHeight() from OnSettingChanged(),
* b_IsFromOnSettingChanged will always remain true and _UpdatePinnedListHeight()
* will always be skipped, regardless if we want to change Pinned List height or not.
* Hence, we will reset variable inside StartMenu_UpdatePinnedListHeightHook(),
* and the return will be guarded, so that we force a return only if
* StartDocked_DisableRecommendedSection is unset.
*
* See LVT_StartDocked_DisableRecommendedSection() for more details.
*/
}

void __fastcall StartMenu_UpdatePinnedListHeightHook(void* _this)
{
// If call is coming from OnSettingChanged(), reset the trigger variable
// and return, if DisableRecommended is set.
if (b_IsFromOnSettingChanged)
{
b_IsFromOnSettingChanged = FALSE;
if (StartDocked_DisableRecommendedSection)
return;
}

// Call original function, if trigger is unset.
StartMenu_UpdatePinnedListHeightFunc(_this);
}

void StartMenu_LoadSettings(BOOL bRestartIfChanged)
{
HKEY hKey = NULL;
Expand Down Expand Up @@ -12686,6 +12751,7 @@ DWORD InjectStartMenu()

HANDLE hStartDocked = NULL;
HANDLE hStartUI = NULL;
HANDLE hStartMenu = NULL;

if (!IsWindows11()) dwTaskbarAl = 0;

Expand Down Expand Up @@ -12731,6 +12797,18 @@ DWORD InjectStartMenu()
hStartDocked = GetModuleHandleW(L"StartDocked.dll");

VnPatchDelayIAT(hStartDocked, "ext-ms-win-ntuser-draw-l1-1-0.dll", "SetWindowRgn", Start_SetWindowRgn);

WCHAR wszStartMenuDll[MAX_PATH];
GetWindowsDirectoryW(wszStartMenuDll, MAX_PATH);
wcscat_s(
wszStartMenuDll,
MAX_PATH,
L"\\SystemApps\\MicrosoftWindows.Client.Core_cw5n1h2txyewy\\StartMenu.dll"
);
hStartMenu = LoadLibraryExW(wszStartMenuDll,
NULL,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
);
}

Setting* settings = calloc(6, sizeof(Setting));
Expand Down Expand Up @@ -12785,6 +12863,8 @@ DWORD InjectStartMenu()

int rv;
DWORD dwVal0 = 0, dwVal1 = 0, dwVal2 = 0, dwVal3 = 0, dwVal4 = 0;
DWORD dwStartMenuOnSettingChanged = 0;
DWORD dwStartMenuUpdatePinnedListHeight = 0;

HMODULE hModule = LoadLibraryExW(L"Shlwapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hModule)
Expand Down Expand Up @@ -12835,6 +12915,24 @@ DWORD InjectStartMenu()
&dwVal4,
&dwSize
);
dwSize = sizeof(DWORD);
SHRegGetValueFromHKCUHKLM(
TEXT(REGPATH_STARTMENU) TEXT("\\") TEXT(STARTMENU_SB_NAME),
TEXT(STARTMENU_SB_STARTINNERFRAME_ONSETTINGCHANGED),
SRRF_RT_REG_DWORD,
NULL,
&dwStartMenuOnSettingChanged,
&dwSize
);
dwSize = sizeof(DWORD);
SHRegGetValueFromHKCUHKLM(
TEXT(REGPATH_STARTMENU) TEXT("\\") TEXT(STARTMENU_SB_NAME),
TEXT(STARTMENU_SB_STARTINNERFRAME_UPDATEPINNEDLISTHEIGHT),
SRRF_RT_REG_DWORD,
NULL,
&dwStartMenuUpdatePinnedListHeight,
&dwSize
);
}
FreeLibrary(hModule);
}
Expand Down Expand Up @@ -12890,6 +12988,39 @@ DWORD InjectStartMenu()
}
}

if (hStartMenu &&
dwStartMenuOnSettingChanged &&
dwStartMenuUpdatePinnedListHeight)
{
StartMenu_OnSettingChangedFunc = (StartMenu_OnSettingChanged_t)
((uintptr_t)hStartMenu + dwStartMenuOnSettingChanged);

StartMenu_UpdatePinnedListHeightFunc = (StartMenu_UpdatePinnedListHeight_t)
((uintptr_t)hStartMenu + dwStartMenuUpdatePinnedListHeight);

rv = funchook_prepare(
funchook,
(void**)&StartMenu_OnSettingChangedFunc,
StartMenu_OnSettingChangedHook
);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}

rv = funchook_prepare(
funchook,
(void**)&StartMenu_UpdatePinnedListHeightFunc,
StartMenu_UpdatePinnedListHeightHook
);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}
}

rv = funchook_install(funchook, 0);
if (rv != 0)
{
Expand Down
162 changes: 162 additions & 0 deletions ExplorerPatcher/symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ const char* startdocked_SN[STARTDOCKED_SB_CNT] = {
const char* startui_SN[STARTUI_SB_CNT] = {
STARTUI_SB_0,
};
const char* startmenu_SN[STARTMENU_SB_CNT] = {
STARTMENU_SB_STARTINNERFRAME_ONSETTINGCHANGED,
STARTMENU_SB_STARTINNERFRAME_UPDATEPINNEDLISTHEIGHT
};

const wchar_t DownloadNotificationXML[] =
L"<toast scenario=\"reminder\" "
Expand Down Expand Up @@ -390,6 +394,98 @@ static BOOL ProcessStartUISymbols(char* pszSettingsPath, DWORD* pOffsets)
return TRUE;
}

static BOOL ProcessStartMenuSymbols(char* pszSettingsPath, DWORD* pOffsets)
{
HKEY hKey = NULL;
DWORD dwDisposition;
RegCreateKeyExW(
HKEY_CURRENT_USER,
TEXT(REGPATH_STARTMENU) L"\\" TEXT(STARTMENU_SB_NAME),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisposition
);
if (!hKey || hKey == INVALID_HANDLE_VALUE)
{
printf("[Symbols] Unable to create registry key.\n");
return FALSE;
}

WCHAR wszPath[MAX_PATH];
ZeroMemory(wszPath, sizeof(wszPath));
GetWindowsDirectoryW(wszPath, MAX_PATH);
wcscat_s(
wszPath,
MAX_PATH,
L"\\SystemApps\\MicrosoftWindows.Client.Core_cw5n1h2txyewy\\" _T(STARTMENU_SB_NAME) L".dll"
);

if (!FileExistsW(wszPath))
{
if (hKey) RegCloseKey(hKey);
return TRUE; // StartMenu.dll is not present on this installation.
}

char startmenu_sb_dll[MAX_PATH];
ZeroMemory(startmenu_sb_dll, sizeof(startmenu_sb_dll));
GetWindowsDirectoryA(startmenu_sb_dll, MAX_PATH);
strcat_s(startmenu_sb_dll, MAX_PATH,
"\\SystemApps\\MicrosoftWindows.Client.Core_cw5n1h2txyewy\\" STARTMENU_SB_NAME ".dll");

CHAR szHash[100];
ZeroMemory(szHash, sizeof(szHash));
ComputeFileHash(wszPath, szHash, ARRAYSIZE(szHash));

printf("[Symbols] Downloading symbols for \"%s\" (\"%s\")...\n",
startmenu_sb_dll,
szHash
);

if (VnDownloadSymbols(
NULL,
startmenu_sb_dll,
pszSettingsPath,
MAX_PATH
))
{
printf("[Symbols] Symbols for \"%s\" are not available - unable to download.\n", startmenu_sb_dll);
printf("[Symbols] Please refer to \"https://github.com/valinet/ExplorerPatcher/wiki/Symbols\" for more information.\n");
if (hKey) RegCloseKey(hKey);
return FALSE;
}

printf("[Symbols] Reading symbols...\n");

BOOL bStartMenuSymbolsOk = TRUE;

if (VnGetSymbols(
pszSettingsPath,
pOffsets,
(char**)startmenu_SN,
STARTMENU_SB_CNT
))
{
printf("[Symbols] Failure in reading symbols for \"%s\".\n", startmenu_sb_dll);
if (hKey) RegCloseKey(hKey);
return FALSE;
}

RegSetValueExW(hKey, TEXT(STARTMENU_SB_STARTINNERFRAME_ONSETTINGCHANGED), 0, REG_DWORD, (const BYTE*)&pOffsets[0], sizeof(DWORD));
RegSetValueExW(hKey, TEXT(STARTMENU_SB_STARTINNERFRAME_UPDATEPINNEDLISTHEIGHT), 0, REG_DWORD, (const BYTE*)&pOffsets[1], sizeof(DWORD));

RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, (DWORD)(strlen(szHash) + 1));

SaveVersion(hKey, STARTMENU_SB_VERSION);

if (hKey) RegCloseKey(hKey);

return TRUE;
}

DWORD DownloadSymbols(DownloadSymbolsParams* params)
{
Sleep(6000);
Expand Down Expand Up @@ -549,6 +645,12 @@ DWORD DownloadSymbols(DownloadSymbolsParams* params)
bAnySuccess |= bSuccess;
bAllSuccess &= bSuccess;
}
if (params->loadResult.bNeedToDownloadStartMenuSymbols && IsWindows11())
{
BOOL bSuccess = ProcessStartMenuSymbols(szSettingsPath, symbols_PTRS.startmenu_PTRS);
bAnySuccess |= bSuccess;
bAllSuccess &= bSuccess;
}

printf("[Symbols] Finished gathering symbol data.\n");

Expand Down Expand Up @@ -842,6 +944,66 @@ LoadSymbolsResult LoadSymbols(symbols_addr* symbols_PTRS)
);
}
}
if (IsWindows11())
{
// Load StartMenu.dll offsets
bOffsetsValid = FALSE;
RegCreateKeyExW(
HKEY_CURRENT_USER,
TEXT(REGPATH_STARTMENU) L"\\" TEXT(STARTMENU_SB_NAME),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&hKey,
&dwDisposition
);

GetWindowsDirectoryW(wszPath, MAX_PATH);
wcscat_s(
wszPath,
MAX_PATH,
L"\\SystemApps\\MicrosoftWindows.Client.Core_cw5n1h2txyewy\\"
TEXT(STARTMENU_SB_NAME)
L".dll"
);

if (ComputeFileHash(wszPath, szHash, ARRAYSIZE(szHash)) == ERROR_SUCCESS)
{
szStoredHash[0] = 0;
dwSize = sizeof(szStoredHash);
if (RegQueryValueExA(hKey, "Hash", 0, NULL, szStoredHash, &dwSize) == ERROR_SUCCESS
&& !_stricmp(szHash, szStoredHash) && CheckVersion(hKey, STARTMENU_SB_VERSION))
{
dwSize = sizeof(DWORD);
RegQueryValueExW(hKey, TEXT(STARTMENU_SB_STARTINNERFRAME_ONSETTINGCHANGED), 0, NULL, (LPBYTE)&symbols_PTRS->startmenu_PTRS[0], &dwSize);
RegQueryValueExW(hKey, TEXT(STARTMENU_SB_STARTINNERFRAME_UPDATEPINNEDLISTHEIGHT), 0, NULL, (LPBYTE)&symbols_PTRS->startmenu_PTRS[1], &dwSize);

bOffsetsValid =
symbols_PTRS->startmenu_PTRS[0] &&
symbols_PTRS->startmenu_PTRS[1];
}

if (!bOffsetsValid)
{
printf("[Symbols] Symbols for \"%s\" are not available.\n", STARTMENU_SB_NAME);
#ifdef _M_X64 // TODO Add support for ARM64
result.bNeedToDownloadStartMenuSymbols = TRUE;
#endif
}
}

if (hKey) RegCloseKey(hKey);

if (!bOffsetsValid)
{
RegDeleteTreeW(
HKEY_CURRENT_USER,
TEXT(REGPATH_STARTMENU) L"\\" TEXT(STARTMENU_SB_NAME)
);
}
}

// Delete "OSBuild" value from previous versions of EP
RegCreateKeyExW(
Expand Down
Loading