1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2024-11-12 02:00:46 +01:00

Start10: Prevent menu closing delay when patching standalone (without ExplorerPatcher injecting explorer.exe)

The Windows 10 Start menu has a delay when closing if one is injecting
it without injecting `explorer.exe` as well. The reason for this is
that animations are fixed, which in turn fixes this delay, using code
run when ExplorerPatcher is injected in `explorer.exe`. It cannot be
patched from the Start menu's host process itself
(`StartMenuExperienceHost.exe`) because that doesn't load
`twinui.pchsell.dll` where the actual patching happens. This commit
works around this shortcoming by employing the old fix for this delay:
hiding the Start menu when animations haven't been fixed (so when
`explorer.exe` is not injected by ExplorerPatcher).

We needed to detect when animations were successfully patched from
`explorer.exe` in order to disable this workaround, thus this commit
offers an example on how to create a kernel object, in this case a
mutex, that can be 'seen' by a process running inside an app container,
as is the case for Start menu's host process
(`StartMenuExperienceHost.exe`).
This commit is contained in:
Valentin Radu 2024-04-04 03:38:00 +03:00
parent c286ab5610
commit 45bd735856
3 changed files with 149 additions and 3 deletions

View File

@ -51,6 +51,8 @@ RTL_OSVERSIONINFOW global_rovi;
DWORD32 global_ubr;
#endif
#include <featurestagingapi.h>
#include <userenv.h>
#pragma comment(lib, "Userenv.lib")
#define WINX_ADJUST_X 5
#define WINX_ADJUST_Y 5
@ -234,6 +236,12 @@ HRESULT WINAPI _DllGetClassObject(
LPVOID* ppv
);
// {09717D01-5D10-4FB5-BD05-46380B5165AA}
#define CLSID_EPStart10_TEXT "{A6EA9C2D-4982-4827-9204-0AC532959F6D}"
#define EPStart10_AnimationsPatched "EPStart10_AnimationsPatched_" CLSID_EPStart10_TEXT
DEFINE_GUID(CLSID_EPStart10,
0x9717d01, 0x5d10, 0x4fb5, 0xbd, 0x5, 0x46, 0x38, 0xb, 0x51, 0x65, 0xaa);
#pragma region "Updates"
#ifdef _WIN64
DWORD CheckForUpdatesThread(LPVOID timeout)
@ -12572,7 +12580,28 @@ DWORD Inject(BOOL bIsExplorer)
GetCrashCounterSettings(&cfg);
if (!cfg.bDisabled)
{
FixStartMenuAnimation(&miTwinuiPcshell);
if (FixStartMenuAnimation(&miTwinuiPcshell)) {
PSID pMainSid = NULL;
GetLogonSid(&pMainSid);
PSID pSecondaySid = NULL;
DeriveAppContainerSidFromAppContainerName(L"Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy", &pSecondaySid);
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
if (PrepareSecurityDescriptor(pMainSid, STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS, pSecondaySid, SYNCHRONIZE, &pSecurityDescriptor))
{
SECURITY_ATTRIBUTES SecurityAttributes;
ZeroMemory(&SecurityAttributes, sizeof(SecurityAttributes));
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.bInheritHandle = FALSE;
SecurityAttributes.lpSecurityDescriptor = pSecurityDescriptor;
if (CreateMutexW(&SecurityAttributes, FALSE, _T(EPStart10_AnimationsPatched)))
{
printf("[SMA] Advertising successful animations patching.\n");
}
free(pSecurityDescriptor);
}
if (pMainSid) free(pMainSid);
if (pSecondaySid) FreeSid(pSecondaySid);
}
}
}
#endif
@ -13503,8 +13532,19 @@ int Start_SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
HRESULT hr = IsThreadCoreWindowVisible(&bIsWindowVisible);
if (SUCCEEDED(hr))
{
/*if (global_rovi.dwBuildNumber >= 25000 && dwStartShowClassicMode)
ShowWindow(hWnd, bIsWindowVisible ? SW_SHOW : SW_HIDE);*/
if (dwStartShowClassicMode && IsWindows11())
{
HANDLE hAnimationsPatched = OpenMutexW(SYNCHRONIZE, FALSE, _T(EPStart10_AnimationsPatched));
if (hAnimationsPatched)
{
CloseHandle(hAnimationsPatched);
if (!IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_SHOW);
}
else
{
ShowWindow(hWnd, bIsWindowVisible ? SW_SHOW : SW_HIDE);
}
}
DWORD TaskbarAl = InterlockedAdd(&dwTaskbarAl, 0);
if (bIsWindowVisible && (!TaskbarAl ? (dwStartShowClassicMode ? StartUI_EnableRoundedCornersApply : StartDocked_DisableRecommendedSectionApply) : 1))
{

View File

@ -1611,4 +1611,106 @@ PVOID FindPattern(PVOID pBase, SIZE_T dwSize, LPCSTR lpPattern, LPCSTR lpMask)
dwSize -= strlen(lpMask);
return FindPatternHelper(pBase, dwSize, lpPattern, lpMask);
}
// https://learn.microsoft.com/en-us/windows/uwp/communication/sharing-named-objects
// https://learn.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath#examples
BOOL GetLogonSid(PSID* ppsid)
{
BOOL bSuccess = FALSE;
HANDLE hToken = INVALID_HANDLE_VALUE;
DWORD dwLength = 0;
PTOKEN_GROUPS ptg = NULL;
if (NULL == ppsid)
goto Cleanup;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
goto Cleanup;
if (!GetTokenInformation(hToken, TokenLogonSid, (LPVOID)ptg, 0, &dwLength))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto Cleanup;
ptg = (PTOKEN_GROUPS)calloc(1, dwLength);
}
if (ptg == NULL)
goto Cleanup;
if (!GetTokenInformation(hToken, TokenLogonSid, (LPVOID)ptg, dwLength, &dwLength) || ptg->GroupCount != 1)
goto Cleanup;
dwLength = GetLengthSid(ptg->Groups[0].Sid);
*ppsid = (PSID)calloc(1, dwLength);
if (*ppsid == NULL)
goto Cleanup;
if (!CopySid(dwLength, *ppsid, ptg->Groups[0].Sid))
{
free((LPVOID)*ppsid);
goto Cleanup;
}
bSuccess = TRUE;
Cleanup:
if (ptg != NULL)
free((LPVOID)ptg);
return bSuccess;
}
// https://learn.microsoft.com/en-us/windows/uwp/communication/sharing-named-objects
// https://learn.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath#examples
BOOL PrepareSecurityDescriptor(PSID pMainSid, DWORD dwMainPermissions, PSID pSecondarySid, DWORD dwSecondayPermissions, PSECURITY_DESCRIPTOR* ppSD)
{
BOOL bSuccess = FALSE;
DWORD dwRes = ERROR_SUCCESS;
PACL pACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea[2];
if (pMainSid == NULL || pSecondarySid == NULL)
goto Cleanup;
ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = dwMainPermissions;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER;
ea[0].Trustee.ptstrName = (LPTSTR)pMainSid;
ea[1].grfAccessPermissions = dwSecondayPermissions;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_USER;
ea[1].Trustee.ptstrName = (LPTSTR)pSecondarySid;
dwRes = SetEntriesInAclW(2, ea, NULL, &pACL);
if (dwRes != ERROR_SUCCESS)
goto Cleanup;
pSD = (PSECURITY_DESCRIPTOR)calloc(1, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
goto Cleanup;
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
goto Cleanup;
if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE))
goto Cleanup;
*ppSD = pSD;
pSD = NULL;
bSuccess = TRUE;
Cleanup:
if (pACL)
LocalFree(pACL);
if (pSD)
free(pSD);
return bSuccess;
}
#endif

View File

@ -267,6 +267,10 @@ WCHAR* StrReplaceAllW(const WCHAR* s, const WCHAR* oldW, const WCHAR* newW, int*
HRESULT InputBox(BOOL bPassword, HWND hWnd, LPCWSTR wszPrompt, LPCWSTR wszTitle, LPCWSTR wszDefault, LPWSTR wszAnswer, DWORD cbAnswer, BOOL* bCancelled);
BOOL GetLogonSid(PSID* ppsid);
BOOL PrepareSecurityDescriptor(PSID pMainSid, DWORD dwMainPermissions, PSID pSecondarySid, DWORD dwSecondayPermissions, PSECURITY_DESCRIPTOR* ppSD);
inline BOOL IsHighContrast()
{
HIGHCONTRASTW highContrast;