Blog Post

Shaky Windows All The Way

How to perform "title bar window shake" programmatically in Windows.

Shaky Windows All The Way - How to perform "title bar window shake" programmatically in Windows.
This article contains functions and features that are not documented by the original manufacturer. By following advice in this article, you're doing so at your own risk. The methods presented in this article may rely on internal implementation and may not work in the future.

Intro

If you grab a window title on your Windows 11 (or Windows 10) system and shake it with the mouse, all other open windows on the screen will get minimized to the taskbar. Then if you shake the same window again, they will be brought back to the screen.

This feature is called "window shake" and it was available since Windows 10.

To enable (or disable) it on Windows 11, go to Start -> Settings -> System -> Multi-tasking. It will be available as a checkbox named, "Title bar window shake".

On Windows 10, the same option is a part of the "Snap windows" feature in the same multi-tasking settings screen.

The question becomes, can we perform the result of the "window shake" feature programmatically in code?

Rbmm had done some reverse engineering to answer that question.

BTW, the answer is yes.

And if you don't want to read how it works and just want to see the code, skip to the end.

"Window Shake" Feature Internals

It all starts in the ThemePreWndProc function in the uxtheme.dll module.

uxtheme.dll is mapped into most GUI processes and provides familiar Windows OS visual styles.

When that window procedure receives the WM_MOVING message, it calls the SHRegGetBoolUSValueW function to obtain the System Registry setting:

C++[Copy]
SHRegGetBoolUSValueW(
	L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
	L"DisallowShaking",
	FALSE,
	TRUE
);

The result of that check is used to determine whether to continue or not.

If DisallowShaking value is set to a non-zero in any of the following registry keys, the "window shake" option is not performed:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced

Otherwise it calls CShakeWnd::FromHwnd and if it returns 0, it calls CShakeWnd::Attach, which creates the CShakeWnd class and attaches it to the window handle in HWND using:

C++[Copy]
SetProp(hWnd, hAtom, this);

There's also an exported API from uxtheme.dll (only by its ordinal number #86). It has the following declaration:

C++[Copy]
BOOL WINAPI IsValidShakeWindow(HWND hWnd);

The CShakeWnd class has the following member functions:

CShakeWnd::AddReference
CShakeWnd::Attach
CShakeWnd::CShakeWnd
CShakeWnd::Detach
CShakeWnd::FromHwnd
CShakeWnd::FromHwndAddRef
CShakeWnd::GetMsgProc
CShakeWnd::HandleEscapeActions
CShakeWnd::IsGoodAngle
CShakeWnd::IsGoodLength
CShakeWnd::IsGoodRatio
CShakeWnd::MessageToShell
CShakeWnd::ReleaseReference
CShakeWnd::Shift
CShakeWnd::_cObj
CShakeWnd::_st

After some internal processing, the code will eventually call:

C++[Copy]
static LRESULT CShakeWnd::MessageToShell(HWND hWnd);

That function internally looks for the window with the "Shell_TrayWnd" window class:

C++[Copy]
if(HWND hwndTray = FindWindowW(L"Shell_TrayWnd", 0))
{
	//...
}

And then does:

C++[Copy]
ULONG dwProcessId;

if(GetWindowThreadProcessId(hwndTray, &dwProcessId))
{
	AllowSetForegroundWindow(dwProcessId);

	//...
}

And lastly:

C++[Copy]
//hWnd = window handle that was shaken
PostMessageW(hwndTray, 0x4F2, 0, (LPARAM)hWnd);

That sends the hwndTray a private message 0x4F2.

The 0x4F2 message is a private message for one of the Windows Explorer window classes in the WM_USER range.

All further processing is then done inside the Explorer.exe process.

The CShakeWnd::MessageToShell itself is called from:

C++[Copy]
LRESULT OnPreWindowMovingShakeHandler(CShakeWnd *, THEME_MSG *)

And from CShakeWnd::HandleEscapeAction as such:

x86-64[Copy]
; void CShakeWnd::HandleEscapeAction(CShakeWnd::_ESC_ACTION)
;
; rcx = this
; rdx = _ESC_ACTION

	mov         qword ptr [rsp+8],rbx
	push        rdi
	sub         rsp,20h
	mov         rbx,rcx
	mov         edi,edx

	mov         rcx,qword ptr [rcx+58h]
	test        rcx,rcx
	jne         lbl_1
	cmp         edx,1
	jne         lbl_2

	call        qword ptr [GetCurrentThreadId]
	nop         dword ptr [rax+rax]

	xor         r8d,r8d
	lea         rdx,[CShakeWnd::GetMsgProc]
	mov         r9d,eax
	lea         ecx,[rdi+2]
	call        qword ptr [SetWindowsHookExW]
	nop         dword ptr [rax+rax]

	mov         qword ptr [rbx+58h],rax
	jmp         lbl_2

lbl_1:

	call        qword ptr [UnhookWindowsHookEx]
	nop         dword ptr [rax+rax]

	and         qword ptr [rbx+58h],0
	cmp         edi,2
	jne         lbl_2

	mov         rcx,qword ptr [rbx+18h]
	call        CShakeWnd::MessageToShell

lbl_2:

	mov         rbx,qword ptr [rsp+30h]
	add         rsp,20h
	pop         rdi
	ret

The OnPreWindowMovingShakeHandler invokes CShakeWnd::IsGoodLength, CShakeWnd::IsGoodAngle, CShakeWnd::IsGoodRatio to determine what mouse moves to interpret as a shake.

"Window Shake" Implementation In Explorer.exe

Inside the Explorer.exe, when it receives the 0x4F2 private message, it calls:

C++[Copy]
//'hWnd' = window handle for the window that was shaken
LRESULT CTray::_ShakeTriggered(enum SHOWDESKTOPTRIGGER, HWND hWnd)

That internally calls IsValidShakeWindow(hWnd) and then IsShakeEnabled, that is defined as such:

x86-64[Copy]
; int IsShakeEnabled(void)

	push        rbx
	sub         rsp,20h
	lea         rcx,[POLID_NoWindowMinimizingShortcuts]       ; {4BF2C693-2A9A-48F8-89A6-0A778F7B1D7D}
	call        qword ptr [SHWindowsPolicy]
	nop         dword ptr [rax+rax]

	test        eax,eax
	jne         lbl_10

	lea         ebx,[rax+1]
	mov         dl,bl
	lea         rcx,['wil::Feature<__WilFeatureTraits_Feature_AeroShakeEnabled>::GetImpl'::'2'::impl]
	call        'wil::details::FeatureImpl<__WilFeatureTraits_Feature_AeroShakeEnabled>::ReportUsage'

	mov         r9d,ebx
	lea         rdx,L"DisallowShaking"
	xor         r8d,r8d
	lea         rcx,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
	call        qword ptr [SHRegGetBoolUSValueW]
	nop         dword ptr [rax+rax]

	test        eax,eax
	jne         lbl_10

	call        IsShakedAllowedInSku

	test        eax,eax
	jne         lbl_11

lbl_10:

	xor         ebx,ebx

lbl_11:

	mov         eax,ebx
	add         rsp,20h
	pop         rbx
	ret
IsShakedAllowedInSku is a gigantic function that determines if the "window shake" feature could be used, besides what is already specified by the "DisallowShaking" Registry setting.

If IsShakeEnabled function returns success, the code invokes the private CTray::_MinimizeAll function:

C++[Copy]
int CTray::_MinimizeAll(BOOL , HANDLE hEvent)

That in turn calls TrayUI::MinimizeAll:

C++[Copy]
virtual BOOL TrayUI::MinimizeAll(BOOL b, HANDLE hEvent)
{
	SendMessageW(hwnd, 0x435, (WPARAM)hEvent, b);
}

That function sends another private message 0x435 to the window with the "MSTaskSwWClass" window class and the "Running applications" title.

Then the following function gets called:

C++[Copy]
int CTaskBand::_MinimizeAll(HEVENT hEvent, BOOL b)

That creates a new worker thread:

C++[Copy]
static ULONG CTaskBand::MinimizeAllThreadProc(void *)

That thread minimizes all windows and at the end signals the hEvent that was passed earlier into CTaskBand::_MinimizeAll.

Also depending on the boolean variable, that was passed into CTaskBand::_MinimizeAll, it can send a private message into the Shell desktop window (that is returned by a call to the GetShellWindow function.) As a result it will call the internal CDesktopBrowser::_Raise(BOOL) function, with the following call-tree:

CDesktopBrowser::_WndProcBS
  CDesktopBrowser::_OnRaise
    CDesktopBrowser::_Raise
      GetLastActivePopup
      CDesktopBrowser::_EnsureRaisedDesktop
        SHCreateWorkerWindowW
        SetPropW
        GlobalAddAtomW
        SetPropW
        GlobalDeleteAtom
        SetPropW
        SetPropW
        DwmSetWindowAttribute
        CZOrderManager::InsertWindowInZOrder
        SHRestricted
        RegisterDragDrop
        CDesktopBrowser::_ShowOrHideDesktopIconsBasedOnDesktopVisibility
        __security_check_cookie
        ret
      LockWindowUpdate
      CDesktopBrowser::_SwapParents
      GetWindowRect
      SetWindowPos
      SetForegroundWindow
      LockWindowUpdate
      SetFocus
      __security_check_cookie
      ret
    PostMessageW
  __security_check_cookie
  ret

Proof Of Concept

If we eliminate all the System Registry checks, and most importantly, the IsShakedAllowedInSku call, we can create the following POC function that will minimize all open windows, except for the one passed in as hwndMy:

C++[Copy]
void MinimizeAll(_In_ BOOL bDialogsToo, _In_opt_ HWND hwndMy)
{
	if (HWND hwnd = FindWindowW(L"Shell_TrayWnd", 0))
	{
		ULONG dwProcessId;

		if (GetWindowThreadProcessId(hwnd, &dwProcessId))
		{
			AllowSetForegroundWindow(dwProcessId);

			//WCHAR name[0x100];
			//if (HMODULE hmod = LoadLibraryExW(L"taskbar.dll",
			//                                  0,
			//                                  LOAD_LIBRARY_AS_IMAGE_RESOURCE))
			//{
			//	LoadStringW(hmod, 0x252, name, _countof(name));
			//	FreeLibrary(hmod);
			//}

			HWND hWndChild = 0;
			while (hWndChild = FindWindowExW(hwnd, 
			                                 hWndChild,
											 REBARCLASSNAMEW,
											 0))
			{
				if (HWND hwndTask = FindWindowEx(hWndChild,
				                                 0, 
												 L"MSTaskSwWClass", 
												 0 /*name*/))
				{
					if (HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE,
					                                  FALSE,
													  dwProcessId))
					{
						if (HANDLE hEvent = CreateEvent(0, 0, 0, 0))
						{
							HANDLE hRemoteEvent;
							if (DuplicateHandle(GetCurrentProcess(),
							                    hEvent, 
												hProcess, 
												&hRemoteEvent, 
												0, 
												0, 
												DUPLICATE_SAME_ACCESS))
							{
								if (PostMessageW(hwndTask, 
								                 0x435, 
												 (WPARAM)hRemoteEvent, 
												 bDialogsToo))
								{
									ULONG n;
									while (1 == (n = 
									      MsgWaitForMultipleObjectsEx(1,
									                                  &hEvent, 
																      2000, 
																      QS_ALLINPUT, 
																      MWMO_INPUTAVAILABLE)))
									{
										MSG msg;
										while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
										{
											DispatchMessageW(&msg);
										}
									}

									if (WAIT_OBJECT_0 != n)
									{
										assert(false);
									}
								}

								DuplicateHandle(hProcess, 
								                hRemoteEvent, 
												0, 
												0, 
												0, 
												0, 
												DUPLICATE_CLOSE_SOURCE);
							}

							CloseHandle(hEvent);
						}

						CloseHandle(hProcess);
					}
					break;
				}
			}
		}
	}
}
You can get this code snippet at Rbmm's GitHub page.

Conclusion

"Window shake" is a convenience feature of the Windows Explorer that could come handy if you want to minimize all windows, except one.

Related Articles