Ingan121 / BasicThemer2

Apply the basic theme of Windows Vista-7 to Windows Vista-10, without disabling the DWM composition
MIT License
145 stars 6 forks source link

Possibly use detours to prevent DWM APIs from interfering? #1

Open Splitwirez opened 4 years ago

Splitwirez commented 4 years ago

Just figured I'd mention that Microsoft's Detours library ( https://github.com/microsoft/Detours ) could potentially be used to prevent DWM APIs from being called as needed. It could likely also be used to redirect attempts to retrieve DWM Visual Style parts to their Basic counterparts, e.g. for the Taskbar, File Explorer navigation bar, etc. It takes some knowledge of C++ to use though, unfortunately, and if my understanding is correct, the resulting DLLs would need to be compiled separately for 32-bit and 64-bit applications.

Ingan121 commented 4 years ago

Thanks, I will look at it.

Splitwirez commented 2 years ago

Finally got around to giving this a shot... Non-broken Ribbon Non-broken Internet Explorer

There are still a ton of problems to sort out, and there's no telling whether I have it in me to do so, but I'm...cautiously optimistic about where this is going...

Ingan121 commented 2 years ago

Nice, is it similar to the dwmapi.dll method?

Splitwirez commented 2 years ago

Update: https://github.com/Splitwirez/BasicThemer2/tree/detours

Ingan121 commented 2 years ago

It works well! I think it needs a better UI, but this is still nice to have a program to universally prevent extending Glass other than manually placing files and patching executables.

Splitwirez commented 2 years ago

@Ingan121 The current pop-up is just for testing. I completely agree this needs better UI...though, were you referring solely to the UI for injecting detour DLLs, or to the BasicThemer2 UI as a whole...?

Also, iit occured to to me that we might be better off moving the actual Basic theme frame-y stuff into the C++ component. Not sure so far. Struggling with my limited knowledge of C++ a lot on this tbh

gdl-blue commented 2 years ago

How can I obtain the binary of BasicThemer64.dll? Visual studio 2010, 2017 does not work, when I compile it on Visual Studio 2022, I only get BasicThemer32.dll and setting the target to x64 does not work. ( @Splitwirez )

Update: https://github.com/Splitwirez/BasicThemer2/tree/detours

gdl-blue commented 2 years ago

( @Ingan121 ) 그럼 Splitwirez가 위에서 언급한 방법으로 프로그램 업데이트 예정입니까?

Splitwirez commented 2 years ago

How can I obtain the binary of BasicThemer64.dll? Visual studio 2010, 2017 does not work, when I compile it on Visual Studio 2022, I only get BasicThemer32.dll and setting the target to x64 does not work. ( @Splitwirez )

Update: https://github.com/Splitwirez/BasicThemer2/tree/detours

Uh...clean and Rebuild Solution for x64 first, then switch to AnyCPU and build+run the actual program (along with everything else), I guess. I've mainly been working in VS2019, though I just tried with 2022 and needed a weird workaround to even get the .NET Framework 4.0 stuff to build. It did work after that though...let me know if you still run into trouble.

@Ingan121 Maybe we shouldn't have dropped the .NET Framework requirement to 4.0 after all... :(

Also, aforementioned .NET Framework 4.0 workaround: instructions from https://thomaslevesque.com/2021/11/12/building-a-project-that-target-net-45-in-visual-studio-2022/ but with https://www.nuget.org/packages/microsoft.netframework.referenceassemblies.net40 and the v4.0 folder

gdl-blue commented 2 years ago

It works. image

gdl-blue commented 2 years ago

However, how can I edit the code to hide the DOS window for every application I run?

image

I found the solution, I changed as bool _showConsole = false;

gdl-blue commented 2 years ago

Also, currently this breaks console applications (cmd, nodejs, etc...)

gdl-blue commented 2 years ago

I temporarily fixed it by whitelisting the exe filenames to inject.

            if (lpApplicationName.ToLower().EndsWith("\\explorer.exe") || lpApplicationName.ToLower().EndsWith("\\iexplore.exe") || lpApplicationName.ToLower().EndsWith("\\mspaint.exe") || lpApplicationName.ToLower().EndsWith("\\wordpad.exe") || lpApplicationName.ToLower().EndsWith("\\chrome.exe") || lpApplicationName.ToLower().EndsWith("\\firefox.exe") || lpApplicationName.ToLower().EndsWith("\\palemoon.exe") || lpApplicationName.ToLower().EndsWith("\\mypal.exe") || lpApplicationName.ToLower().EndsWith("\\centaury.exe") || lpApplicationName.ToLower().EndsWith("\\basilisk.exe") || lpApplicationName.ToLower().EndsWith("\\moviemaker.exe") || lpApplicationName.ToLower().EndsWith("\\photogallery.exe"))
            {
                string dllPath = @"C:\BasicThemer2\DetourDLLs\BasicThemer" + (is64bit ? "64" : "32") + ".dll";
                InjectDLL(processInfo, dllPath);
            }
gdl-blue commented 2 years ago

Also, currently this breaks console applications (cmd, nodejs, etc...)

It also breaks Windows Live Movie Maker, Photo Gallery, Mail. (End of Support does not matter)

Ingan121 commented 2 years ago

@Ingan121 The current pop-up is just for testing. I completely agree this needs better UI...though, were you referring solely to the UI for injecting detour DLLs, or to the BasicThemer2 UI as a whole...?

I only meant the injection UI. I'm thinking of placing a checkbox or button in the main UI for the injection. Also, I think the requirement of running in non-admin mode is not necessary for Windows 10 and later, as Explorer automatically de-elevates itself there. Windows 7 doesn't do this so it would be better to keep this only for 7 and below. (not sure about 8)

It works. image

How did you enable the Win7 ribbons? It looks pretty good.

Uh...clean and Rebuild Solution for x64 first, then switch to AnyCPU and build+run the actual program (along with everything else), I guess. I've mainly been working in VS2019, though I just tried with 2022 and needed a weird workaround to even get the .NET Framework 4.0 stuff to build. It did work after that though...let me know if you still run into trouble.

@Ingan121 Maybe we shouldn't have dropped the .NET Framework requirement to 4.0 after all... :(

Also, aforementioned .NET Framework 4.0 workaround: instructions from https://thomaslevesque.com/2021/11/12/building-a-project-that-target-net-45-in-visual-studio-2022/ but with https://www.nuget.org/packages/microsoft.netframework.referenceassemblies.net40 and the v4.0 folder

Thanks, I will look at that when I install vs2022. (Actually, I currently even have uninstalled vs2019 for some disk space to update to W11 beta.)

Splitwirez commented 2 years ago

Also, currently this breaks console applications (cmd, nodejs, etc...)

Does this still happen even if _showConsole is set to false?

I temporarily fixed it by whitelisting the exe filenames to inject.

          if (lpApplicationName.ToLower().EndsWith("\\explorer.exe") || lpApplicationName.ToLower().EndsWith("\\iexplore.exe") || lpApplicationName.ToLower().EndsWith("\\mspaint.exe") || lpApplicationName.ToLower().EndsWith("\\wordpad.exe") || lpApplicationName.ToLower().EndsWith("\\chrome.exe") || lpApplicationName.ToLower().EndsWith("\\firefox.exe") || lpApplicationName.ToLower().EndsWith("\\palemoon.exe") || lpApplicationName.ToLower().EndsWith("\\mypal.exe") || lpApplicationName.ToLower().EndsWith("\\centaury.exe") || lpApplicationName.ToLower().EndsWith("\\basilisk.exe") || lpApplicationName.ToLower().EndsWith("\\moviemaker.exe") || lpApplicationName.ToLower().EndsWith("\\photogallery.exe"))
          {
              string dllPath = @"C:\BasicThemer2\DetourDLLs\BasicThemer" + (is64bit ? "64" : "32") + ".dll";
              InjectDLL(processInfo, dllPath);
          }

Where did you do this? And what does it fix?

It also breaks Windows Live Movie Maker, Photo Gallery, Mail. (End of Support does not matter)

Breaks them...how, exactly?

gdl-blue commented 2 years ago

Breaks them...how, exactly?

Windows Live Movie Maker shows error - %1 is not a valid Win32 application. Windows Live Photo Gallery shows error - 0x80040154 (no description) Windows Live Mail just crashes while loading without error messages.

Where did you do this? And what does it fix?

In function public static uint CreateProcessWithBasicThemeDLLs. After if (!NativeMethodsInj.CreateProcess .... It just not injects the DLL for those executables. Not a fundamental solution.

Does this still happen even if _showConsole is set to false?

Oh it fixed it.

gdl-blue commented 2 years ago

How did you enable the Win7 ribbons? It looks pretty good.

@Ingan121 C:\Windows\system32 및 syswow64의 UIRibbon.dll, UIRibbonRes.dll, en-us/UIRibbon.dll.mui를 윈도우 8 빌드 8014에 내장된 것으로 교체하시면 됩니다(윈도우 7의 것으로 해도 작동하지만 안정성 문제가 나타나는 것 같습니다). 32비트 윈도우를 사용 중인 경우 system32에서 앞서 말한 세 파일을 윈도우 8 빌드 8008(32비트)의 것으로 교체하면 됩니다. 필요하시면 파일을 보내드릴 수 있습니다.

image

gdl-blue commented 2 years ago

@Splitwirez ) - WIll it be possible to make a patchable dwmapi.dll in system32? just injecting basicthemerXX.dll doesn't be a good way since if explorer.exe restarts for some reason it will stop working.

Splitwirez commented 2 years ago

@Splitwirez ) - WIll it be possible to make a patchable dwmapi.dll in system32? just injecting basicthemerXX.dll doesn't be a good way since if explorer.exe restarts for some reason it will stop working.

Actually, my entire motive for trying to do this all via DLL injection was to avoid patching system files.

If we want BasicThemer2 to have any hope of ever amounting to anything more than a toy, it must not jeopardize the user's ability to use their computer - not in the present, nor the unforeseeable future.

Patching system files ensures that our changes will either break, or be broken by, a Windows update eventually. There's no telling what that will look like when it happens, but interfering with the user's ability to use their computer is a very real possibility. This is problem has only been exacerbated by WaaS. Furthermore, any attempt to write code to "un-patch" the system files is at the mercy of whether or not Windows can start up, log in, etc., far enough to run said code successfully. Not likely if the user can't even log in because DWM is toast.

Conversely, DLL injection has to be repeated every time explorer starts...which, critically, includes every time the user logs in. This means Windows starts without our changes affecting it, and allows an opportunity to abort injection if things go south, e.g. perhaps due to unforeseen changes made by a Windows update.

Not only this, but patching system DLLs requires ongoing upkeep, for the event in which the DLLs are updated. DLL injection opens up an opportunity to lessen this pain as well - as long as we only detour documented APIs, any changes Microsoft makes to the DLLs in question outside of those particular APIs have a very real possibility of having no effect on us, meaning our changes may very well continue to work as they did previously. Any changes Microsoft makes to the DLLs in question which do affect the APIs we're concerned with...are highly unlikely to occur - I'm sure you know how Microsoft is about backwards-compatibility. We can use that to our advantage by using DLL injection, to achieve greater sustainability...and if you ask me, every shred counts these days, given how hard it's gotten to achieve any degree of sustainability.

You're not wrong that we don't have a solution for the explorer restart scenario, but I'd argue we'd be fools to turn away from code injection because of that alone, especially without trying everything we can to address the explorer restart scenario as best we can.

Admittedly, I do fear that we've veered too close to the present limits of my knowledge of C++ for my comfort, but I do intend to resume my research sooner or later, if nothing else.