Jump to content

Trying to get rid of Explorer scrollup bug


UCyborg

Recommended Posts

There is this annoyance in Windows 10's Explorer, if the user enables desktop slideshow and Automatically pick an accent color from my background, the scrollbar will jump up on each desktop background change, which triggers accent color change which is actually indirectly responsible for current Explorer behavior. It seems unlikely, from various responses over the internet, including Reddit, that Microsoft will ever address this, so probably the only hope would be coding some hack to remedy this. I came up with a very simple prototype DLL that can get rid of this annoyance.

#include <Windows.h>
#include <easyhook.h>

HOOK_TRACE_INFO H_WindowProc_info;
LRESULT (CALLBACK *O_WindowProc)(HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK H_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (uMsg == WM_SETTINGCHANGE && !wParam)
	{
		return 0;
	}
	return O_WindowProc(hWnd, uMsg, wParam, lParam);
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	if (fdwReason == DLL_PROCESS_ATTACH)
	{
		DisableThreadLibraryCalls(hinstDLL);

		HWND hWnd = FindWindow(TEXT("CabinetWClass"), NULL);
		LONG_PTR WndProc = GetWindowLongPtr(hWnd, GWLP_WNDPROC);

		LhInstallHook(WndProc, H_WindowProc, NULL, &H_WindowProc_info);
		ULONG ACLEntries[1] = { 0 };
		LhSetExclusiveACL(ACLEntries, 1, &H_WindowProc_info);
		LhGetHookBypassAddress(&H_WindowProc_info, &O_WindowProc);
	}
	else if (fdwReason == DLL_PROCESS_DETACH)
	{
		LhUninstallHook(&H_WindowProc_info);
		LhWaitForPendingRemovals();
	}
	return TRUE;
}

This is just proof of concept. It seems intercepting certain WM_SETTINGCHANGE messages so they never make it to Explorer and therefore prevent it from refreshing whatever things it refreshes gets rid of the annoying behavior. I use EasyHook library for function hooking. There could be downsides, can't say for certain if there are cases where certain important system setting changes that would make the Explorer receive WM_SETTINGCHANGE with zero wParam and it would be a good thing to reload whatever settings it reloads.

The problem I'm facing, I have to somehow intercept window creation process and then hook its window procedure. The above code will only work for one already existent window, need to make this thing dynamic. I must be missing something obvious because if I hook the RegisterClassW function to get the address of window procedure to hook it (obviously I interfere only when the class name is CabinetWClass), the hook isn't called at all then, but LhInstallHook function doesn't return a failure. I think I'll try hooking one of CreateWindow functions next then use GetWindowLongPtr to get its window procedure address and hope that works.

Edit: It seems each window uses its own dynamically allocated window procedure, but I don't know how it's set, SetWindowLongPtr apparently isn't involved. Must be set when window is ready somehow. Thought this'd be easier.

Edited by UCyborg
Link to comment
Share on other sites


It might be possible if one knows some tricks, which would apparently be required to implement this correctly. OldNewExplorer is good at reverting certain behaviors in Explorer, this might be one of the things you could add to Fix-Newer-Windows-File-Explorer-Oddities list.

I went back to Windows 8.1 on my main machine after recent incident. Stlll, this information might be useful to someone else. I wonder how Windows 10 will be in general after 2 years from now, particularly when it comes to regressions like this.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...