valinet / ExplorerPatcher

This project aims to enhance the working environment on Windows
GNU General Public License v2.0
24.94k stars 1.06k forks source link

Black screen is observed post installation of Moments Packages and unable to work with machine when Explorer Patcher is present on the system #1526

Closed Michellehdr closed 1 year ago

Michellehdr commented 1 year ago

Black screen is observed post installation of Moments Packages and unable to work with machine when Explorer Patcher is present on the system

ExplorerPacther Version: 22621.1555.55.1

Could you please take a look at the issue? Thanks!

pyrates999 commented 1 year ago

Moments package is a preview update and preview updates and insider builds are not supported by explorer patcher due to symbols not being available to download: https://github.com/valinet/ExplorerPatcher/wiki/Symbols

Uninstall explorer patcher if you want to install the Moments preview update, otherwise don't install preview updates.

kwinz commented 1 year ago

I had the same issue. I manually searched for updates in the Windows settings. Just one accidental click on the "cumulative update preview" (they kinda look the same as regular updates). And on the next reboot I was stuck on a black screen after login and kind of confused what had happend.

What helped was CTRL+ALT+DELETE, opening TaskManager, run new task. Locate ep_setup.exe and ep_setup.exe /uninstall. It's really unfortunate that it's so easy to accidentally lock yourself out.

Michellehdr commented 1 year ago

@pyrates999 thanks for your quick reply. In fact, the issue not only repro on Moments packages, but also on every released Windows Updates. do we have any plan to fix it?

pyrates999 commented 1 year ago

Try the following:

  1. uninstall explorer patcher
  2. export this registry key: "Computer\HKEY_CURRENT_USER\Software\ExplorerPatcher" and upload it to here
  3. delete the same registry key: "Computer\HKEY_CURRENT_USER\Software\ExplorerPatcher"
  4. install explorer patcher
  5. verify you get a notification that symbols have been downloaded
  6. restart windows explorer using either the task manager or in the properties window of explorer patcher
Michellehdr commented 1 year ago

@pyrates999 we tried with the above steps. seems like we were unable to see the Symbols notification in step5. Could you please take a look?

pyrates999 commented 1 year ago

Try that again, but first uninstall the moments update, reboot. It is a preview update and looks like it has bugs in it.

Then run winver and google the build number of windows that winver returns to you to check if you're still on a preview update. If you are, uninstall it and reboot. Keep doing this until the build number that winver returns to you is not a preview update.

Then try this:

  1. uninstall explorer patcher
  2. delete the registry key: "Computer\HKEY_CURRENT_USER\Software\ExplorerPatcher"
  3. reboot
Michellehdr commented 1 year ago

@pyrates999 thank you so much for your quick response. But the issue here might cause the system to fall into an unusable state on every Windows update. Is it possible to have a solution for the App to run on all Windows Updates?

pyrates999 commented 1 year ago

No, read here for why: https://github.com/valinet/ExplorerPatcher/wiki/Symbols

Michellehdr commented 1 year ago

@pyrates999 thanks for your response. Our engineer has found some root cause I would like to share with you. Could it be possible to share an email address to my personal mail: michellehdr@outlook.com. So that I can send through email via my MS account?

pyrates999 commented 1 year ago

No.

Michellehdr commented 1 year ago

@pyrates999 @valinet okay. Then I paste the investigation details from our engineer here: The black screen issue is confirmed to be caused by Explorer.exe getting into an erroneous state after twinui.pcshell.dll is updated by the moment package. Explorer.exe got into the erroneous state because its main thread was terminated by the app unexpectedly. The cause is stated as below:

  1. ExplorerPatcher redirects the Explorer.exe to load its own dxgi.dll instead of the system dxgi.dll.
  2. In the EntryPoint function of dxgi.dll, which is called in WinMain of Explorer.exe, the app tries to use funchook APIs to hook twinui.pcshell.dll!CLauncherTipContextMenu::ShowLauncherTipContextMenu. It attempts to use the last known good offset, which is stored at HKCU\Software\ExplorerPatcher\TwinUI.PCShell, to do the hooking.
  3. On the first boot after updating from 5B (22621.1702) to the moment package (22631.1835), the last known good offset is the offset for 5B version of twinui.pcshell.dll. So ExplorerPatcher still tries to use the 5B offset to do the hooking at that time.
  4. The moment package has updated twinui.pcshell.dll so the 5B offset becomes invalid. It happens to be near the end of another function on the moment binary. The funchook API detects this and thinks the function to hook is too short, so it returns error code 7 (FUNCHOOK_ERROR_TOO_SHORT_INSTRUCTIONS).
  5. ExplorerPatcher calls FreeLibraryAndExitThread() when the funchook API fails. But this is the main thread of the Explorer.exe. Terminating the main thread at early stage of WinMain leaves the whole process in an erroneous state.
  6. Before calling FreeLibraryAndExitThread(), ExplorerPatcher spawns a worker thread to download symbol file for the new twinui.pcshell.dll. This worker thread is not affected by the termination of the main thread and the symbol is download successfully. So the bug will go away on the next system reboot.

From #6 we know it’s not an issue about symbol not available for preview package. Actually the symbol gets downloaded and explorer.exe launches correctly thereafter. This issue can happen on any WU update as long as the last known good offset can cause the funchook API to return any error code for the new binary. ExplorerPatcher needs to do something to avoid the black screen. For example, the app should not call FreeLibraryAndExitThread() in the Explorer main thread. Or the app can just intentionally crash itself when funchook API fails so this can be detected by InformUserAboutCrash and the app can disable itself.

Below debugging info on the moment package (22631.1835) is for your reference:

0:000> kp "# Child-SP RetAddr Call Site 00 00000000002ddb48 00007ffc45ead287 KERNELBASE!LoadLibraryW(wchar_t lpwLibFileName = 0x00007ffc45f02198 "twinui.pcshell.dll") [minkernel\kernelbase\module.c @ 915] 01 00000000002ddb50 00007ffc45eb105d dxgi!UpdateHMDEmulationStatus+0xff67 02 00000000002de2f0 00007ffc45eb10cb dxgi!DllUnregisterServer+0x19bd 03 00000000002df2d0 00007ff7d375e3cc dxgi!DXGIDeclareAdapterRemovalSupport+0xb 04 00000000002df300 00007ff7`d377dee0 explorer!wWinMain(struct HINSTANCE__ hInstance = 0x00007ff7d3740000, struct HINSTANCE__ * __formal = 0x0000000000000000, wchar_t formal = 0x00000000`00000000 "", int formal = 0n0)+0x58 [pcshell\shell\explorer\initcab.cpp @ 1195] 05 (Inline Function) ---------------- explorer!invoke_main(void)+0x21 [VCCRT\vcstartup\src\startup\exe_common.inl @ 118] 06 00000000002df960 00007ffc608326ad explorer!__scrt_common_main_seh(void)+0x110 [VCCRT\vcstartup\src\startup\exe_common.inl @ 288] 07 00000000002df9a0 00007ffc`61d4a9f8 KERNEL32!BaseThreadInitThunk(unsigned long RunProcessInit = , StartAddress = , void Argument = )+0x1d [clientcore\base\win32\client\thread.c @ 75] 08 00000000002df9d0 0000000000000000 ntdll!RtlUserThreadStart( StartAddress = 0x0000000000000000, void * Argument = 0x0000000000000000)+0x28 [minkernel\ntdll\rtlstrt.c @ 1166] 0:000> gu ModLoad: 00007ffc46140000 00007ffc46a6f000 C:\Windows\SYSTEM32\twinui.pcshell.dll ModLoad: 00007ffc54a20000 00007ffc54cd1000 C:\Windows\SYSTEM32\iertutil.dll ModLoad: 00007ffc52650000 00007ffc526c3000 C:\Windows\SYSTEM32\wincorlib.DLL ModLoad: 00007ffc589b0000 00007ffc58a55000 C:\Windows\SYSTEM32\policymanager.dll ModLoad: 00007ffc58890000 00007ffc58923000 C:\Windows\SYSTEM32\msvcp110_win.dll rax=00007ffc46140000 rbx=00007ffc5c720000 rcx=a952a13752b10000 rdx=0000000000000279 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead287 rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc61e269c0 r9=0000000000000004 r10=0000000000000000 r11=00000000002ddb30 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 dxgi!UpdateHMDEmulationStatus+0xff67: 00007ffc45ead287 488bd8 mov rbx,rax 0:000> pc rax=00007ffc467bfab0 rbx=00007ffc46140000 rcx=00000000009f0000 rdx=00007ffc45f1df78 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead33f rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc45e9e900 r9=0000000000000004 r10=0000000000000000 r11=00000000002ddb30 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl nz na po cy cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000207 dxgi!UpdateHMDEmulationStatus+0x1001f: 00007ffc45ead33f e80cc70100 call dxgi!ZZRestartExplorer+0x32f0 (00007ffc45ec9a50) // Calling funchook API to hook CLauncherTipContextMenu::ShowLauncherTipContextMenu. 0:000> dp @rdx l1 00007ffc45f1df78 00007ffc467bfab0 // 00007ffc467bfab0 = 00007ffc46140000 + 0067fab0. This is the base address of twinui.pcshell.dll + 5B offset of CLauncherTipContextMenu::ShowLauncherTipContextMenu. 0:000> u 00007ffc467bfab0 twinui_pcshell!winrt::impl::promise_base<std::experimental::coroutine_traits<winrt::Windows::Foundation::IAsyncAction,winrt::Windows::Internal::Shell::implementation::WindowsTracker *>::promise_type,winrt::Windows::Foundation::IAsyncAction,void>::Completed+0xb0 [internal\sdk\inc\cppwinrt\winrt\Windows.Foundation.h @ 3642]: 00007ffc467bfab0 405f pop rdi 00007ffc467bfab2 c3 ret // We can see it’s pointing to the end of another function of the moment binary. 00007ffc467bfab3 cc int 3 twinui_pcshell!winrt::impl::promise_base<std::experimental::coroutine_traits<winrt::Windows::Foundation::IAsyncAction,winrt::Windows::Internal::Shell::implementation::WindowsTracker *>::promise_type,winrt::Windows::Foundation::IAsyncAction,void>::Completed'::1'::dtor$0: 00007ffc467bfab4 488d8a68000000 lea rcx,[rdx+68h] 00007ffc467bfabb e9f0dad0ff jmp twinui_pcshell!winrt::slim_lock_guard::~slim_lock_guard (00007ffc464cd5b0) 00007ffc467bfac0 cc int 3 00007ffc467bfac1 cc int 3 00007ffc467bfac2 cc int 3 0:000> p rax=0000000000000007 rbx=00007ffc46140000 rcx=0000000000000000 // funchook API returns 7 (FUNCHOOK_ERROR_TOO_SHORT_INSTRUCTIONS). rdx=00007ffc45ef0258 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead344 rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc467bfab0 r9=00007ffc467bfab0 r10=00000000002d9988 r11=00000000002d96c0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 dxgi!UpdateHMDEmulationStatus+0x10024: 00007ffc45ead344 85c0 test eax,eax 0:000> p rax=0000000000000007 rbx=00007ffc46140000 rcx=0000000000000000 rdx=00007ffc45ef0258 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead346 rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc467bfab0 r9=00007ffc467bfab0 r10=00000000002d9988 r11=00000000002d96c0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 dxgi!UpdateHMDEmulationStatus+0x10026: 00007ffc45ead346 7410 je dxgi!UpdateHMDEmulationStatus+0x10038 (00007ffc45ead358) [br=0] 0:000> rax=0000000000000007 rbx=00007ffc46140000 rcx=0000000000000000 rdx=00007ffc45ef0258 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead348 rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc467bfab0 r9=00007ffc467bfab0 r10=00000000002d9988 r11=00000000002d96c0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 dxgi!UpdateHMDEmulationStatus+0x10028: 00007ffc45ead348 488b0dd90a0700 mov rcx,qword ptr [dxgi!ZZRestartExplorer+0x576c8 (00007ffc45f1de28)] ds:00007ffc45f1de28={dxgi (00007ffc45e90000)} 0:000> rax=0000000000000007 rbx=00007ffc46140000 rcx=00007ffc45e90000 rdx=00007ffc45ef0258 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead34f rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc467bfab0 r9=00007ffc467bfab0 r10=00000000002d9988 r11=00000000002d96c0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 dxgi!UpdateHMDEmulationStatus+0x1002f: 00007ffc45ead34f 8bd0 mov edx,eax 0:000> rax=0000000000000007 rbx=00007ffc46140000 rcx=00007ffc45e90000 rdx=0000000000000007 rsi=00007ff7d3740000 rdi=0000000000000000 rip=00007ffc45ead351 rsp=00000000002ddb50 rbp=00000000002ddc50 r8=00007ffc467bfab0 r9=00007ffc467bfab0 r10=00000000002d9988 r11=00000000002d96c0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000001 r15=0000000000000000 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 dxgi!UpdateHMDEmulationStatus+0x10031: 00007ffc45ead351 ff1521220400 call qword ptr [dxgi!ZZRestartExplorer+0x28e18 (00007ffc45eef578)] ds:00007ffc45eef578={KERNEL32!FreeLibraryAndExitThreadStub (00007ffc60839ca0)} // Terminating current thread.

pyrates999 commented 1 year ago

Thank you for the details. One of the programmers here may find that useful then. I am not one of them as I am not a programmer.

If you get that without explorer patcher installed, I suggest you contact Microsoft then.

Michellehdr commented 1 year ago

@valinet could you please take a look at the investigation details above?

Michellehdr commented 1 year ago

@valinet could you please take a look at the issue above? @pyrates999 do you know any of the explorerpatcher developers that we could loop in this conversation?

pyrates999 commented 1 year ago

I am not actively engaged in the project. I just try to help with troubleshooting.

Amrsatrio commented 1 year ago

Hi Microsoft representative, it's good to see that EP is tested by Microsoft. Anyways, since some time ago I've fixed this bogus offsets issue by pairing them with the respective binary's hash that, if doesn't match, will not be loaded therefore will no longer cause black screens.

Sorry if it took that long. I just joined here to fix major breaking issues in EP since almost two months ago. Cheers :)