diff --git a/ExplorerPatcher.sln b/ExplorerPatcher.sln index a7903ed..4427751 100644 --- a/ExplorerPatcher.sln +++ b/ExplorerPatcher.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30002.166 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPatcher", "ExplorerPatcher\ExplorerPatcher.vcxproj", "{DB3E4319-2969-42B6-B7E8-BB57AA8C9FA9}" EndProject @@ -9,6 +9,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ep_generate_release_descrip EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ep_generate_release_name", "ep_generate_release_name\ep_generate_release_name.vcxproj", "{78D0C3CF-25C0-41D4-9359-0E9AB72B9874}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ep_setup", "ep_setup\ep_setup.vcxproj", "{2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}" + ProjectSection(ProjectDependencies) = postProject + {DB3E4319-2969-42B6-B7E8-BB57AA8C9FA9} = {DB3E4319-2969-42B6-B7E8-BB57AA8C9FA9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ep_setup_patch", "ep_setup_patch\ep_setup_patch.vcxproj", "{0C13E5F3-106B-4836-A7C2-8E5808A6ED78}" + ProjectSection(ProjectDependencies) = postProject + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF} = {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|amd64 = Debug|amd64 @@ -37,6 +47,18 @@ Global {78D0C3CF-25C0-41D4-9359-0E9AB72B9874}.Release|amd64.ActiveCfg = Release|x64 {78D0C3CF-25C0-41D4-9359-0E9AB72B9874}.Release|amd64.Build.0 = Release|x64 {78D0C3CF-25C0-41D4-9359-0E9AB72B9874}.Release|IA-32.ActiveCfg = Release|Win32 + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}.Debug|amd64.ActiveCfg = Debug|x64 + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}.Debug|amd64.Build.0 = Debug|x64 + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}.Debug|IA-32.ActiveCfg = Debug|Win32 + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}.Release|amd64.ActiveCfg = Release|x64 + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}.Release|amd64.Build.0 = Release|x64 + {2FD40B09-F224-4E9A-B2FE-A22B50B2DEBF}.Release|IA-32.ActiveCfg = Release|Win32 + {0C13E5F3-106B-4836-A7C2-8E5808A6ED78}.Debug|amd64.ActiveCfg = Debug|x64 + {0C13E5F3-106B-4836-A7C2-8E5808A6ED78}.Debug|amd64.Build.0 = Debug|x64 + {0C13E5F3-106B-4836-A7C2-8E5808A6ED78}.Debug|IA-32.ActiveCfg = Debug|Win32 + {0C13E5F3-106B-4836-A7C2-8E5808A6ED78}.Release|amd64.ActiveCfg = Release|x64 + {0C13E5F3-106B-4836-A7C2-8E5808A6ED78}.Release|amd64.Build.0 = Release|x64 + {0C13E5F3-106B-4836-A7C2-8E5808A6ED78}.Release|IA-32.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ExplorerPatcher/ExplorerPatcher.rc b/ExplorerPatcher/ExplorerPatcher.rc index c6ffe3a..91e5855 100644 --- a/ExplorerPatcher/ExplorerPatcher.rc +++ b/ExplorerPatcher/ExplorerPatcher.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 22000,318,36,1 - PRODUCTVERSION 22000,318,36,1 + FILEVERSION 22000,318,37,0 + PRODUCTVERSION 22000,318,37,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "VALINET Solutions SRL" VALUE "FileDescription", "ExplorerPatcher" - VALUE "FileVersion", "22000.318.36.1" + VALUE "FileVersion", "22000.318.37.0" VALUE "InternalName", "ExplorerPatcher.dll" VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved." VALUE "OriginalFilename", "ExplorerPatcher.dll" VALUE "ProductName", "ExplorerPatcher" - VALUE "ProductVersion", "22000.318.36.1" + VALUE "ProductVersion", "22000.318.37.0" END END BLOCK "VarFileInfo" diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj index 915df97..23090ef 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj @@ -267,6 +267,12 @@ true true + + true + + + true + true true @@ -298,6 +304,7 @@ + diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj.filters b/ExplorerPatcher/ExplorerPatcher.vcxproj.filters index a104f4c..81e93b7 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj.filters +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj.filters @@ -108,6 +108,9 @@ Header Files\internal + + Header Files + @@ -175,6 +178,9 @@ Source Files\sws + + Source Files + diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c index 72fb1a0..e0ae341 100644 --- a/ExplorerPatcher/dllmain.c +++ b/ExplorerPatcher/dllmain.c @@ -22,6 +22,7 @@ #include #pragma comment(lib, "Dbghelp.lib") #include +#include #ifdef _WIN64 #include #endif @@ -31,8 +32,6 @@ #include #include -#define EP_CLSID "{D17F1E1A-5919-4427-8F89-A1A8503CA3EB}" - #define WINX_ADJUST_X 5 #define WINX_ADJUST_Y 5 @@ -65,6 +64,7 @@ DWORD bClockFlyoutOnWinC = FALSE; DWORD bDisableImmersiveContextMenu = FALSE; DWORD bClassicThemeMitigations = FALSE; DWORD bHookStartMenu = TRUE; +DWORD bPropertiesInWinX = FALSE; DWORD bNoMenuAccelerator = FALSE; DWORD bTaskbarMonitorOverride = 0; DWORD dwIMEStyle = 0; @@ -120,6 +120,8 @@ DWORD S_Icon_Dark_Widgets = 0; #endif #include "SettingsMonitor.h" #include "HideExplorerSearchBar.h" +#include "updates.h" +DWORD dwUpdatePolicy = UPDATE_POLICY_DEFAULT; HRESULT WINAPI _DllRegisterServer(); HRESULT WINAPI _DllUnregisterServer(); @@ -130,6 +132,49 @@ HRESULT WINAPI _DllGetClassObject( LPVOID* ppv ); + +#pragma region "Updates" +#ifdef _WIN64 +DWORD CheckForUpdatesThread(LPVOID unused) +{ + HANDLE hEvents[2]; + hEvents[0] = CreateEventW(NULL, FALSE, FALSE, L"EP_Ev_CheckForUpdates_" _T(EP_CLSID)); + hEvents[1] = CreateEventW(NULL, FALSE, FALSE, L"EP_Ev_InstallUpdates_" _T(EP_CLSID)); + if (hEvents[0] && hEvents[1]) + { + if (dwUpdatePolicy != UPDATE_POLICY_MANUAL) + { + InstallUpdatesIfAvailable(UPDATES_OP_DEFAULT, bAllocConsole, dwUpdatePolicy); + } + DWORD dwRet = 0; + while (TRUE) + { + switch (WaitForMultipleObjects(2, hEvents, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + { + InstallUpdatesIfAvailable(UPDATES_OP_CHECK, bAllocConsole, dwUpdatePolicy); + break; + } + case WAIT_OBJECT_0 + 1: + { + InstallUpdatesIfAvailable(UPDATES_OP_INSTALL, bAllocConsole, dwUpdatePolicy); + break; + } + default: + { + break; + } + } + } + CloseHandle(hEvents[0]); + CloseHandle(hEvents[1]); + } +} +#endif +#pragma endregion + + #pragma region "Generics" #ifdef _WIN64 HWND GetMonitorInfoFromPointForTaskbarFlyoutActivation(POINT ptCursor, DWORD dwFlags, LPMONITORINFO lpMi) @@ -183,6 +228,123 @@ HWND GetMonitorInfoFromPointForTaskbarFlyoutActivation(POINT ptCursor, DWORD dwF return hWnd; } +POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight, BOOL bAdjust) +{ + if (lpBottom) *lpBottom = FALSE; + if (lpRight) *lpRight = FALSE; + POINT point; + point.x = 0; + point.y = 0; + POINT ptCursor; + GetCursorPos(&ptCursor); + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + HWND hWnd = GetMonitorInfoFromPointForTaskbarFlyoutActivation( + ptCursor, + MONITOR_DEFAULTTOPRIMARY, + &mi + ); + if (hWnd) + { + RECT rc; + GetWindowRect(hWnd, &rc); + if (rc.left - mi.rcMonitor.left <= 0) + { + if (bUseRcWork) + { + point.x = mi.rcWork.left; + } + else + { + point.x = mi.rcMonitor.left; + } + if (bAdjust) + { + point.x++; + } + if (rc.top - mi.rcMonitor.top <= 0) + { + if (bUseRcWork) + { + point.y = mi.rcWork.top; + } + else + { + point.y = mi.rcMonitor.top; + } + if (bAdjust) + { + point.y++; + } + } + else + { + if (lpBottom) *lpBottom = TRUE; + if (bUseRcWork) + { + point.y = mi.rcWork.bottom; + } + else + { + point.y = mi.rcMonitor.bottom; + } + if (bAdjust) + { + point.y--; + } + } + } + else + { + if (lpRight) *lpRight = TRUE; + if (bUseRcWork) + { + point.x = mi.rcWork.right; + } + else + { + point.x = mi.rcMonitor.right; + } + if (bAdjust) + { + point.x--; + } + if (rc.top - mi.rcMonitor.top <= 0) + { + if (bUseRcWork) + { + point.y = mi.rcWork.top; + } + else + { + point.y = mi.rcMonitor.top; + } + if (bAdjust) + { + point.y++; + } + } + else + { + if (lpBottom) *lpBottom = TRUE; + if (bUseRcWork) + { + point.y = mi.rcWork.bottom; + } + else + { + point.y = mi.rcMonitor.bottom; + } + if (bAdjust) + { + point.y--; + } + } + } + } + return point; +} + long long elapsedCheckForeground = 0; HANDLE hCheckForegroundThread = NULL; DWORD CheckForegroundThread(wchar_t* wszClassName) @@ -581,21 +743,26 @@ DWORD ShowLauncherTipContextMenu( } } + BOOL bCreatedMenu = FALSE; MENUITEMINFOW menuInfo; ZeroMemory(&menuInfo, sizeof(MENUITEMINFOW)); menuInfo.cbSize = sizeof(MENUITEMINFOW); - menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_STATE; + menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA; menuInfo.wID = 3999; menuInfo.dwItemData = 0; menuInfo.fType = MFT_STRING; menuInfo.dwTypeData = buffer; menuInfo.cch = wcslen(buffer); - InsertMenuItemW( - *((HMENU*)((char*)params->_this + 0xe8)), - GetMenuItemCount(*((HMENU*)((char*)params->_this + 0xe8))) - 1, - TRUE, - &menuInfo - ); + if (bPropertiesInWinX) + { + InsertMenuItemW( + *((HMENU*)((char*)params->_this + 0xe8)), + GetMenuItemCount(*((HMENU*)((char*)params->_this + 0xe8))) - 1, + TRUE, + &menuInfo + ); + bCreatedMenu = TRUE; + } INT64* unknown_array = NULL; if (bSkinMenus) @@ -630,64 +797,20 @@ DWORD ShowLauncherTipContextMenu( free(unknown_array); } - RemoveMenu( - *((HMENU*)((char*)params->_this + 0xe8)), - 3999, - MF_BYCOMMAND - ); + if (bCreatedMenu) + { + RemoveMenu( + *((HMENU*)((char*)params->_this + 0xe8)), + 3999, + MF_BYCOMMAND + ); + } if (res > 0) { - if (res == 3999) + if (bCreatedMenu && res == 3999) { - //CreateThread(0, 0, ZZGUI, 0, 0, 0); - wchar_t wszPath[MAX_PATH * 2]; - ZeroMemory( - wszPath, - (MAX_PATH * 2) * sizeof(wchar_t) - ); - wszPath[0] = '\"'; - GetSystemDirectoryW( - wszPath + 1, - MAX_PATH - ); - wcscat_s( - wszPath, - MAX_PATH * 2, - L"\\rundll32.exe\" \"" - ); - GetModuleFileNameW( - hModule, - wszPath + wcslen(wszPath), - MAX_PATH - ); - wcscat_s( - wszPath, - MAX_PATH * 2, - L"\",ZZGUI" - ); - wprintf(L"Launching : %s\n", wszPath); - STARTUPINFO si; - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(si); - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - if (CreateProcessW( - NULL, - wszPath, - NULL, - NULL, - TRUE, - CREATE_UNICODE_ENVIRONMENT, - NULL, - NULL, - &si, - &pi - )) - { - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - } + LaunchPropertiesGUI(hModule); } else if (res < 4000) { @@ -914,6 +1037,125 @@ void UpdateStartMenuPositioning(LPARAM loIsShouldInitializeArray_hiIsShouldRoIni #pragma region "Shell_TrayWnd subclass" #ifdef _WIN64 +HMENU explorer_LoadMenuW(HINSTANCE hInstance, LPCWSTR lpMenuName) +{ + HMENU hMenu = LoadMenuW(hInstance, lpMenuName); + if (hInstance == GetModuleHandle(NULL) && lpMenuName == MAKEINTRESOURCEW(205)) + { + HMENU hSubMenu = GetSubMenu(hMenu, 0); + if (hSubMenu) + { + TCHAR buffer[260]; + LoadStringW(GetModuleHandleW(L"ExplorerFrame.dll"), 50222, buffer + (bNoMenuAccelerator ? 0 : 1), 260); + if (!bNoMenuAccelerator) + { + buffer[0] = L'&'; + } + wchar_t* p = wcschr(buffer, L'('); + if (p) + { + p--; + if (p == L' ') + { + *p = 0; + } + else + { + p++; + *p = 0; + } + } + MENUITEMINFOW menuInfo; + ZeroMemory(&menuInfo, sizeof(MENUITEMINFOW)); + menuInfo.cbSize = sizeof(MENUITEMINFOW); + menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA; + menuInfo.wID = 3999; + menuInfo.dwItemData = CheckForUpdatesThread; + menuInfo.fType = MFT_STRING; + menuInfo.dwTypeData = buffer; + menuInfo.cch = wcslen(buffer); + InsertMenuItemW( + hSubMenu, + GetMenuItemCount(hSubMenu) - 4, + TRUE, + &menuInfo + ); + } + } + return hMenu; +} + +HHOOK Shell_TrayWndMouseHook = NULL; + +BOOL Shell_TrayWnd_IsTaskbarRightClick(POINT pt) +{ + HRESULT hr = S_OK; + IUIAutomation2* pIUIAutomation2 = NULL; + IUIAutomationElement* pIUIAutomationElement = NULL; + HWND hWnd = NULL; + BOOL bRet = FALSE; + + if (SUCCEEDED(hr)) + { + hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation2, &pIUIAutomation2); + } + if (SUCCEEDED(hr)) + { + hr = pIUIAutomation2->lpVtbl->ElementFromPoint(pIUIAutomation2, pt, &pIUIAutomationElement); + } + if (SUCCEEDED(hr)) + { + hr = pIUIAutomationElement->lpVtbl->get_CurrentNativeWindowHandle(pIUIAutomationElement, &hWnd); + } + if (SUCCEEDED(hr)) + { + if (IsWindow(hWnd)) + { + HWND hAncestor = GetAncestor(hWnd, GA_ROOT); + HWND hWindow = FindWindowExW(hAncestor, NULL, L"Windows.UI.Composition.DesktopWindowContentBridge", NULL); + if (IsWindow(hWindow)) + { + hWindow = FindWindowExW(hWindow, NULL, L"Windows.UI.Input.InputSite.WindowClass", NULL); + if (IsWindow(hWindow)) + { + if (hWindow == hWnd) + { + bRet = TRUE; + } + } + } + } + } + if (pIUIAutomationElement) + { + pIUIAutomationElement->lpVtbl->Release(pIUIAutomationElement); + } + if (pIUIAutomation2) + { + pIUIAutomation2->lpVtbl->Release(pIUIAutomation2); + } + return bRet; +} + +LRESULT CALLBACK Shell_TrayWndMouseProc( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam +) +{ + if (nCode == HC_ACTION && wParam == WM_RBUTTONUP && Shell_TrayWnd_IsTaskbarRightClick(((MOUSEHOOKSTRUCT*)lParam)->pt)) + { + PostMessageW( + FindWindowW(L"Shell_TrayWnd", NULL), + RegisterWindowMessageW(L"Windows11ContextMenu_" _T(EP_CLSID)), + 0, + MAKELPARAM(((MOUSEHOOKSTRUCT*)lParam)->pt.x, ((MOUSEHOOKSTRUCT*)lParam)->pt.y) + ); + return 1; + } + return CallNextHookEx(Shell_TrayWndMouseHook, nCode, wParam, lParam); +} + INT64 Shell_TrayWndSubclassProc( _In_ HWND hWnd, _In_ UINT uMsg, @@ -944,6 +1186,142 @@ INT64 Shell_TrayWndSubclassProc( { UpdateStartMenuPositioning(MAKELPARAM(TRUE, FALSE)); } + else if (!bOldTaskbar && uMsg == WM_PARENTNOTIFY && wParam == WM_RBUTTONDOWN && !Shell_TrayWndMouseHook) // && !IsUndockingDisabled + { + DWORD dwThreadId = GetCurrentThreadId(); + Shell_TrayWndMouseHook = SetWindowsHookExW(WH_MOUSE, Shell_TrayWndMouseProc, NULL, dwThreadId); + } + else if (uMsg == WM_COMMAND) + { + printf("DA\n"); + } + else if (uMsg == RegisterWindowMessageW(L"Windows11ContextMenu_" _T(EP_CLSID))) + { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + HMENU hMenu = LoadMenuW(GetModuleHandle(NULL), MAKEINTRESOURCEW(205)); + if (hMenu) + { + HMENU hSubMenu = GetSubMenu(hMenu, 0); + if (hSubMenu) + { + if (GetAsyncKeyState(VK_SHIFT) >= 0 || GetAsyncKeyState(VK_CONTROL) >= 0) + { + DeleteMenu(hSubMenu, 518, MF_BYCOMMAND); // Exit Explorer + } + DeleteMenu(hSubMenu, 424, MF_BYCOMMAND); // Lock the taskbar + DeleteMenu(hSubMenu, 425, MF_BYCOMMAND); // Lock all taskbars + DeleteMenu(hSubMenu, 416, MF_BYCOMMAND); // Undo + DeleteMenu(hSubMenu, 437, MF_BYCOMMAND); // Show Pen button + DeleteMenu(hSubMenu, 438, MF_BYCOMMAND); // Show touchpad button + DeleteMenu(hSubMenu, 435, MF_BYCOMMAND); // Show People on the taskbar + DeleteMenu(hSubMenu, 430, MF_BYCOMMAND); // Show Task View button + DeleteMenu(hSubMenu, 449, MF_BYCOMMAND); // Show Cortana button + DeleteMenu(hSubMenu, 621, MF_BYCOMMAND); // News and interests + DeleteMenu(hSubMenu, 445, MF_BYCOMMAND); // Cortana + DeleteMenu(hSubMenu, 431, MF_BYCOMMAND); // Search + DeleteMenu(hSubMenu, 421, MF_BYCOMMAND); // Customize notification icons + DeleteMenu(hSubMenu, 408, MF_BYCOMMAND); // Adjust date/time + DeleteMenu(hSubMenu, 436, MF_BYCOMMAND); // Show touch keyboard button + DeleteMenu(hSubMenu, 0, MF_BYPOSITION); // Separator + DeleteMenu(hSubMenu, 0, MF_BYPOSITION); // Separator + + TCHAR buffer[260]; + LoadStringW(GetModuleHandleW(L"ExplorerFrame.dll"), 50222, buffer + (bNoMenuAccelerator ? 0 : 1), 260); + if (!bNoMenuAccelerator) + { + buffer[0] = L'&'; + } + wchar_t* p = wcschr(buffer, L'('); + if (p) + { + p--; + if (p == L' ') + { + *p = 0; + } + else + { + p++; + *p = 0; + } + } + MENUITEMINFOW menuInfo; + ZeroMemory(&menuInfo, sizeof(MENUITEMINFOW)); + menuInfo.cbSize = sizeof(MENUITEMINFOW); + menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_STATE; + menuInfo.wID = 3999; + menuInfo.dwItemData = 0; + menuInfo.fType = MFT_STRING; + menuInfo.dwTypeData = buffer; + menuInfo.cch = wcslen(buffer); + InsertMenuItemW( + hSubMenu, + GetMenuItemCount(hSubMenu) - 1, + TRUE, + &menuInfo + ); + + INT64* unknown_array = NULL; + if (bSkinMenus) + { + unknown_array = calloc(4, sizeof(INT64)); + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc( + hSubMenu, + hWnd, + &pt, + 0xc, + unknown_array + ); + } + + BOOL res = TrackPopupMenu( + hSubMenu, + TPM_RETURNCMD | TPM_RIGHTBUTTON, + pt.x, + pt.y, + 0, + hWnd, + 0 + ); + if (res == 3999) + { + LaunchPropertiesGUI(hModule); + } + else if (res == 403) + { + CascadeWindows(NULL, 0, NULL, 0, NULL); + } + else if (res == 404) + { + TileWindows(NULL, 0, NULL, 0, NULL); + } + else if (res == 405) + { + TileWindows(NULL, 1, NULL, 0, NULL); + } + else + { + PostMessageW(hWnd, WM_COMMAND, res, 0); + } + + if (bSkinMenus) + { + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( + hSubMenu, + hWnd, + &pt + ); + free(unknown_array); + } + + DestroyMenu(hSubMenu); + } + DestroyMenu(hMenu); + } + } return DefSubclassProc(hWnd, uMsg, wParam, lParam); } #endif @@ -1143,6 +1521,27 @@ void RemoveOwnerDrawFromMenu(int level, HMENU hMenu) } } } +BOOL CheckIfMenuContainsOwnPropertiesItem(HMENU hMenu) +{ +#ifdef _WIN64 + if (hMenu) + { + int k = GetMenuItemCount(hMenu); + for (int i = k - 1; i >= 0; i--) + { + MENUITEMINFO mii; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_DATA | MIIM_ID; + BOOL b = GetMenuItemInfoW(hMenu, i, TRUE, &mii); + if (b && (mii.wID == 3999 || mii.wID == 4000) && mii.dwItemData == CheckForUpdatesThread) + { + return TRUE; + } + } + } +#endif + return FALSE; +} BOOL TrackPopupMenuHookEx( HMENU hMenu, UINT uFlags, @@ -1160,6 +1559,12 @@ BOOL TrackPopupMenuHookEx( BOOL bIsTaskbar = (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd")) ? !bSkinMenus : bDisableImmersiveContextMenu; //wprintf(L">> %s %d %d\n", wszClassName, bIsTaskbar, bIsExplorerProcess); + BOOL bContainsOwn = FALSE; + if (bIsExplorerProcess && (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd"))) + { + bContainsOwn = CheckIfMenuContainsOwnPropertiesItem(hMenu); + } + if (bIsTaskbar && (bIsExplorerProcess ? 1 : (!wcscmp(wszClassName, L"SHELLDLL_DefView") || !wcscmp(wszClassName, L"SysTreeView32")))) { EnumPropsA(hWnd, CheckIfImmersiveContextMenu); @@ -1193,12 +1598,18 @@ BOOL TrackPopupMenuHookEx( hWnd, lptpm ); - +#ifdef _WIN64 + if (bContainsOwn && (bRet == 3999 || bRet == 4000)) + { + LaunchPropertiesGUI(hModule); + return FALSE; + } +#endif return bRet; } IsImmersiveMenu = FALSE; } - return TrackPopupMenuEx( + BOOL b = TrackPopupMenuEx( hMenu, uFlags, x, @@ -1206,6 +1617,14 @@ BOOL TrackPopupMenuHookEx( hWnd, lptpm ); +#ifdef _WIN64 + if (bContainsOwn && (b == 3999 || b == 4000)) + { + LaunchPropertiesGUI(hModule); + return FALSE; + } +#endif + return b; } BOOL TrackPopupMenuHook( HMENU hMenu, @@ -1225,6 +1644,12 @@ BOOL TrackPopupMenuHook( BOOL bIsTaskbar = (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd")) ? !bSkinMenus : bDisableImmersiveContextMenu; //wprintf(L">> %s %d %d\n", wszClassName, bIsTaskbar, bIsExplorerProcess); + BOOL bContainsOwn = FALSE; + if (bIsExplorerProcess && (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd"))) + { + bContainsOwn = CheckIfMenuContainsOwnPropertiesItem(hMenu); + } + if (bIsTaskbar && (bIsExplorerProcess ? 1 : (!wcscmp(wszClassName, L"SHELLDLL_DefView") || !wcscmp(wszClassName, L"SysTreeView32")))) { EnumPropsA(hWnd, CheckIfImmersiveContextMenu); @@ -1259,12 +1684,18 @@ BOOL TrackPopupMenuHook( hWnd, prcRect ); - +#ifdef _WIN64 + if (bContainsOwn && (bRet == 3999 || bRet == 4000)) + { + LaunchPropertiesGUI(hModule); + return FALSE; + } +#endif return bRet; } IsImmersiveMenu = FALSE; } - return TrackPopupMenu( + BOOL b = TrackPopupMenu( hMenu, uFlags, x, @@ -1273,6 +1704,14 @@ BOOL TrackPopupMenuHook( hWnd, prcRect ); +#ifdef _WIN64 + if (bContainsOwn && (b == 3999 || b == 4000)) + { + LaunchPropertiesGUI(hModule); + return FALSE; + } +#endif + return b; } #ifdef _WIN64 #define TB_POS_NOWHERE 0 @@ -1383,6 +1822,15 @@ BOOL explorer_TrackPopupMenuExHook( { long long elapsed = milliseconds_now() - explorer_TrackPopupMenuExElapsed; BOOL b = FALSE; + + wchar_t wszClassName[200]; + GetClassNameW(hWnd, wszClassName, 200); + BOOL bContainsOwn = FALSE; + if (bIsExplorerProcess && (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd"))) + { + bContainsOwn = CheckIfMenuContainsOwnPropertiesItem(hMenu); + } + if (elapsed > POPUPMENU_EX_ELAPSED || !bFlyoutMenus) { if (bCenterMenus) @@ -1414,6 +1862,11 @@ BOOL explorer_TrackPopupMenuExHook( hWnd, lptpm ); + if (bContainsOwn && (b == 3999 || b == 4000)) + { + LaunchPropertiesGUI(hModule); + return FALSE; + } explorer_TrackPopupMenuExElapsed = milliseconds_now(); } return b; @@ -2267,7 +2720,7 @@ INT64 ShowDesktopSubclassProc( DWORD SignalShellReady(DWORD wait) { printf("Started \"Signal shell ready\" thread.\n"); - UpdateStartMenuPositioning(MAKELPARAM(TRUE, TRUE)); + //UpdateStartMenuPositioning(MAKELPARAM(TRUE, TRUE)); while (!wait && TRUE) { @@ -2289,7 +2742,7 @@ DWORD SignalShellReady(DWORD wait) { if (IsWindowVisible(hWnd)) { - // UpdateStartMenuPositioning(MAKELPARAM(TRUE, TRUE)); + UpdateStartMenuPositioning(MAKELPARAM(TRUE, TRUE)); break; } } @@ -2480,8 +2933,11 @@ void sws_ReadSettings(sws_WindowSwitcher* sws) DWORD WindowSwitcher(DWORD unused) { - WaitForSingleObject(hWin11AltTabInitialized, INFINITE); - Sleep(500); + if (!bOldTaskbar) + { + WaitForSingleObject(hWin11AltTabInitialized, INFINITE); + Sleep(500); + } while (TRUE) { @@ -2788,6 +3244,15 @@ void WINAPI LoadSettings(BOOL bIsExplorer) &dwSize ); dwSize = sizeof(DWORD); + RegQueryValueExW( + hKey, + TEXT("PropertiesInWinX"), + 0, + NULL, + &bPropertiesInWinX, + &dwSize + ); + dwSize = sizeof(DWORD); RegQueryValueExW( hKey, TEXT("NoMenuAccelerator"), @@ -2814,6 +3279,15 @@ void WINAPI LoadSettings(BOOL bIsExplorer) &dwIMEStyle, &dwSize ); + dwSize = sizeof(DWORD); + RegQueryValueExW( + hKey, + TEXT("UpdatePolicy"), + 0, + NULL, + &dwUpdatePolicy, + &dwSize + ); RegCloseKey(hKey); } @@ -3130,7 +3604,7 @@ HWND CreateWindowExWHook( { SetWindowSubclass(hWnd, ShowDesktopSubclassProc, ShowDesktopSubclassProc, 0); } - else if (bOldTaskbar && bIsExplorerProcess && (*((WORD*)&(lpClassName)+1)) && !wcscmp(lpClassName, L"Shell_TrayWnd")) + else if (bIsExplorerProcess && (*((WORD*)&(lpClassName)+1)) && !wcscmp(lpClassName, L"Shell_TrayWnd")) { SetWindowSubclass(hWnd, Shell_TrayWndSubclassProc, Shell_TrayWndSubclassProc, 0); } @@ -3195,13 +3669,24 @@ HRESULT explorer_DrawThemeBackground( HFONT hFont = CreateFontIndirectW(&(ncm.lfCaptionFont)); + UINT dpiX, dpiY; + HRESULT hr = GetDpiForMonitor( + MonitorFromWindow(WindowFromDC(hdc), MONITOR_DEFAULTTOPRIMARY), + MDT_DEFAULT, + &dpiX, + &dpiY + ); + double dx = dpiX / 96.0, dy = dpiY / 96.0; + HGDIOBJ hOldFont = SelectObject(hdc, hFont); - DWORD dwTextFlags = DT_SINGLELINE | DT_CENTER; + DWORD dwTextFlags = DT_SINGLELINE | DT_CENTER | DT_VCENTER; + RECT rc = *pRect; + rc.bottom -= 7 * dy; DrawTextW( hdc, L"\u2026", -1, - pRect, + &rc, dwTextFlags ); SelectObject(hdc, hOldFont); @@ -3487,6 +3972,7 @@ HRESULT explorer_DrawThemeTextEx( #pragma region "Change clock links" +#ifdef _WIN64 HINSTANCE explorer_ShellExecuteW( HWND hwnd, LPCWSTR lpOperation, @@ -3512,8 +3998,14 @@ HINSTANCE explorer_ShellExecuteW( lpParameters, lpDirectory, nShowCmd ); } + /*else if (!wcscmp(lpFile, L"ms-settings:taskbar")) + { + LaunchPropertiesGUI(hModule); + return 0; + }*/ return ShellExecuteW(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd); } +#endif #pragma endregion @@ -3612,103 +4104,61 @@ HRESULT explorer_CoCreateInstanceHook( #pragma endregion -DWORD InjectBasicFunctions(BOOL bIsExplorer, BOOL bInstall) +#pragma region "Explorer Registry Hooks" +LSTATUS explorer_RegCreateKeyExW(HKEY a1, const WCHAR* a2, DWORD a3, WCHAR* a4, DWORD a5, REGSAM a6, struct _SECURITY_ATTRIBUTES* a7, HKEY* a8, DWORD* a9) { - //Sleep(150); + const wchar_t* v13; // rdx + int v14; // eax - HMODULE hShlwapi = LoadLibraryW(L"Shlwapi.dll"); - if (bInstall) + if (lstrcmpW(a2, L"MMStuckRects3")) { - SHRegGetValueFromHKCUHKLMFunc = GetProcAddress(hShlwapi, "SHRegGetValueFromHKCUHKLM"); - } - else - { - FreeLibrary(hShlwapi); - FreeLibrary(hShlwapi); - } - - HANDLE hShell32 = LoadLibraryW(L"shell32.dll"); - if (bInstall) - { - VnPatchIAT(hShell32, "user32.dll", "TrackPopupMenu", TrackPopupMenuHook); - VnPatchIAT(hShell32, "user32.dll", "SystemParametersInfoW", DisableImmersiveMenus_SystemParametersInfoW); - if (!bIsExplorer) + v14 = lstrcmpW(a2, L"StuckRects3"); + v13 = L"StuckRectsLegacy"; + if (v14) { - CreateWindowExWFunc = CreateWindowExW; - VnPatchIAT(hShell32, "user32.dll", "CreateWindowExW", CreateWindowExWHook); + v13 = a2; } } else { - VnPatchIAT(hShell32, "user32.dll", "TrackPopupMenu", TrackPopupMenu); - VnPatchIAT(hShell32, "user32.dll", "SystemParametersInfoW", SystemParametersInfoW); - if (!bIsExplorer) - { - VnPatchIAT(hShell32, "user32.dll", "CreateWindowExW", CreateWindowExW); - } - FreeLibrary(hShell32); - FreeLibrary(hShell32); + v13 = L"MMStuckRectsLegacy"; } - HANDLE hShcore = LoadLibraryW(L"shcore.dll"); - if (bInstall) - { - explorerframe_SHCreateWorkerWindowFunc = GetProcAddress(hShcore, (LPCSTR)188); - } - else - { - FreeLibrary(hShcore); - FreeLibrary(hShcore); - } + return RegCreateKeyExW(a1, v13, a3, a4, a5, a6, a7, a8, a9); +} - HANDLE hExplorerFrame = LoadLibraryW(L"ExplorerFrame.dll"); - if (bInstall) +LSTATUS explorer_SHGetValueW(HKEY a1, const WCHAR* a2, const WCHAR* a3, DWORD* a4, void* a5, DWORD* a6) +{ + const WCHAR* v10; // rdx + int v11; // eax + + if (lstrcmpW(a2, L"MMStuckRects3")) { - VnPatchIAT(hExplorerFrame, "user32.dll", "TrackPopupMenu", TrackPopupMenuHook); - VnPatchIAT(hExplorerFrame, "user32.dll", "SystemParametersInfoW", DisableImmersiveMenus_SystemParametersInfoW); - VnPatchIAT(hExplorerFrame, "shcore.dll", (LPCSTR)188, explorerframe_SHCreateWorkerWindowHook); // <<>> - if (!bIsExplorer) - { - CreateWindowExWFunc = CreateWindowExW; - VnPatchIAT(hExplorerFrame, "user32.dll", "CreateWindowExW", CreateWindowExWHook); - } + v11 = lstrcmpW(a2, L"StuckRects3"); + v10 = L"StuckRectsLegacy"; + if (v11) + v10 = a2; } else { - VnPatchIAT(hExplorerFrame, "user32.dll", "TrackPopupMenu", TrackPopupMenu); - VnPatchIAT(hExplorerFrame, "user32.dll", "SystemParametersInfoW", SystemParametersInfoW); - VnPatchIAT(hExplorerFrame, "shcore.dll", (LPCSTR)188, explorerframe_SHCreateWorkerWindowFunc); - if (!bIsExplorer) - { - VnPatchIAT(hExplorerFrame, "user32.dll", "CreateWindowExW", CreateWindowExW); - } - FreeLibrary(hExplorerFrame); - FreeLibrary(hExplorerFrame); + v10 = L"MMStuckRectsLegacy"; } - HANDLE hWindowsUIFileExplorer = LoadLibraryW(L"Windows.UI.FileExplorer.dll"); - if (hWindowsUIFileExplorer) - { - VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "TrackPopupMenu", TrackPopupMenuHook); - VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "SystemParametersInfoW", DisableImmersiveMenus_SystemParametersInfoW); - if (!bIsExplorer) - { - CreateWindowExWFunc = CreateWindowExW; - VnPatchIAT(hWindowsUIFileExplorer, "user32.dll", "CreateWindowExW", CreateWindowExWHook); - } - } - else + return SHGetValueW(a1, v10, a3, a4, a5, a6); +} + +LSTATUS explorer_RegOpenKeyExW(HKEY a1, WCHAR* a2, DWORD a3, REGSAM a4, HKEY* a5) +{ + DWORD flOldProtect[6]; + + if (!lstrcmpiW(a2, L"Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\TrayNotify") + && VirtualProtect(a2, 0xC8ui64, 0x40u, flOldProtect)) { - VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "TrackPopupMenu", TrackPopupMenu); - VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "SystemParametersInfoW", SystemParametersInfoW); - if (!bIsExplorer) - { - VnPatchIAT(hWindowsUIFileExplorer, "user32.dll", "CreateWindowExW", CreateWindowExW); - } - FreeLibrary(hWindowsUIFileExplorer); - FreeLibrary(hWindowsUIFileExplorer); + lstrcpyW(a2, L"Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\TrayNotSIB"); + VirtualProtect(a2, 0xC8ui64, flOldProtect[0], flOldProtect); } + return RegOpenKeyExW(a1, a2, a3, a4, a5); } LSTATUS explorer_RegSetValueExW( @@ -3789,7 +4239,7 @@ LSTATUS twinuipcshell_RegGetValueW( { LSTATUS lRes = RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - if (!lstrcmpW(lpValue, L"AltTabSettings")) + if (!bOldTaskbar && !lstrcmpW(lpValue, L"AltTabSettings")) { if (*(DWORD*)pvData) { @@ -3952,6 +4402,106 @@ HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( } return explorer_SHCreateStreamOnModuleResourceWFunc(hModule, pwszName, pwszType, ppStream); } +#pragma endregion + + +DWORD InjectBasicFunctions(BOOL bIsExplorer, BOOL bInstall) +{ + //Sleep(150); + + HMODULE hShlwapi = LoadLibraryW(L"Shlwapi.dll"); + if (bInstall) + { + SHRegGetValueFromHKCUHKLMFunc = GetProcAddress(hShlwapi, "SHRegGetValueFromHKCUHKLM"); + } + else + { + FreeLibrary(hShlwapi); + FreeLibrary(hShlwapi); + } + + HANDLE hShell32 = LoadLibraryW(L"shell32.dll"); + if (bInstall) + { + VnPatchIAT(hShell32, "user32.dll", "TrackPopupMenu", TrackPopupMenuHook); + VnPatchIAT(hShell32, "user32.dll", "SystemParametersInfoW", DisableImmersiveMenus_SystemParametersInfoW); + if (!bIsExplorer) + { + CreateWindowExWFunc = CreateWindowExW; + VnPatchIAT(hShell32, "user32.dll", "CreateWindowExW", CreateWindowExWHook); + } + } + else + { + VnPatchIAT(hShell32, "user32.dll", "TrackPopupMenu", TrackPopupMenu); + VnPatchIAT(hShell32, "user32.dll", "SystemParametersInfoW", SystemParametersInfoW); + if (!bIsExplorer) + { + VnPatchIAT(hShell32, "user32.dll", "CreateWindowExW", CreateWindowExW); + } + FreeLibrary(hShell32); + FreeLibrary(hShell32); + } + + HANDLE hShcore = LoadLibraryW(L"shcore.dll"); + if (bInstall) + { + explorerframe_SHCreateWorkerWindowFunc = GetProcAddress(hShcore, (LPCSTR)188); + } + else + { + FreeLibrary(hShcore); + FreeLibrary(hShcore); + } + + HANDLE hExplorerFrame = LoadLibraryW(L"ExplorerFrame.dll"); + if (bInstall) + { + VnPatchIAT(hExplorerFrame, "user32.dll", "TrackPopupMenu", TrackPopupMenuHook); + VnPatchIAT(hExplorerFrame, "user32.dll", "SystemParametersInfoW", DisableImmersiveMenus_SystemParametersInfoW); + VnPatchIAT(hExplorerFrame, "shcore.dll", (LPCSTR)188, explorerframe_SHCreateWorkerWindowHook); // <<>> + if (!bIsExplorer) + { + CreateWindowExWFunc = CreateWindowExW; + VnPatchIAT(hExplorerFrame, "user32.dll", "CreateWindowExW", CreateWindowExWHook); + } + } + else + { + VnPatchIAT(hExplorerFrame, "user32.dll", "TrackPopupMenu", TrackPopupMenu); + VnPatchIAT(hExplorerFrame, "user32.dll", "SystemParametersInfoW", SystemParametersInfoW); + VnPatchIAT(hExplorerFrame, "shcore.dll", (LPCSTR)188, explorerframe_SHCreateWorkerWindowFunc); + if (!bIsExplorer) + { + VnPatchIAT(hExplorerFrame, "user32.dll", "CreateWindowExW", CreateWindowExW); + } + FreeLibrary(hExplorerFrame); + FreeLibrary(hExplorerFrame); + } + + HANDLE hWindowsUIFileExplorer = LoadLibraryW(L"Windows.UI.FileExplorer.dll"); + if (hWindowsUIFileExplorer) + { + VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "TrackPopupMenu", TrackPopupMenuHook); + VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "SystemParametersInfoW", DisableImmersiveMenus_SystemParametersInfoW); + if (!bIsExplorer) + { + CreateWindowExWFunc = CreateWindowExW; + VnPatchIAT(hWindowsUIFileExplorer, "user32.dll", "CreateWindowExW", CreateWindowExWHook); + } + } + else + { + VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "TrackPopupMenu", TrackPopupMenu); + VnPatchDelayIAT(hWindowsUIFileExplorer, "user32.dll", "SystemParametersInfoW", SystemParametersInfoW); + if (!bIsExplorer) + { + VnPatchIAT(hWindowsUIFileExplorer, "user32.dll", "CreateWindowExW", CreateWindowExW); + } + FreeLibrary(hWindowsUIFileExplorer); + FreeLibrary(hWindowsUIFileExplorer); + } +} DWORD Inject(BOOL bIsExplorer) { @@ -4209,8 +4759,12 @@ DWORD Inject(BOOL bIsExplorer) VnPatchIAT(hExplorer, "shell32.dll", "ShellExecuteW", explorer_ShellExecuteW); VnPatchIAT(hExplorer, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegGetValueW", explorer_RegGetValueW); VnPatchIAT(hExplorer, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegSetValueExW", explorer_RegSetValueExW); + VnPatchIAT(hExplorer, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegCreateKeyExW", explorer_RegCreateKeyExW); + VnPatchIAT(hExplorer, "API-MS-WIN-SHCORE-REGISTRY-L1-1-0.DLL", "SHGetValueW", explorer_SHGetValueW); VnPatchIAT(hExplorer, "user32.dll", "MonitorFromRect", explorer_MonitorFromRect); + VnPatchIAT(hExplorer, "user32.dll", "LoadMenuW", explorer_LoadMenuW); } + VnPatchIAT(hExplorer, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegOpenKeyExW", explorer_RegOpenKeyExW); VnPatchIAT(hExplorer, "user32.dll", "TrackPopupMenuEx", explorer_TrackPopupMenuExHook); if (bClassicThemeMitigations) { @@ -4480,7 +5034,11 @@ DWORD Inject(BOOL bIsExplorer) } - if (bHookStartMenu) + + CreateThread(NULL, 0, CheckForUpdatesThread, 0, 0, NULL); + + + /*if (bHookStartMenu) { HookStartMenuParams* params2 = calloc(1, sizeof(HookStartMenuParams)); params2->dwTimeout = 1000; @@ -4488,7 +5046,9 @@ DWORD Inject(BOOL bIsExplorer) params2->proc = InjectStartFromExplorer; GetModuleFileNameW(hModule, params2->wszModulePath, MAX_PATH); CreateThread(0, 0, HookStartMenu, params2, 0, 0); - } + }*/ + + // This notifies applications when the taskbar has recomputed its layout /*if (SUCCEEDED(TaskbarCenter_Initialize(hExplorer))) @@ -4677,6 +5237,7 @@ INT64 StartDocked_StartSizingFrame_StartSizingFrameHook(void* _this) int WINAPI SetupMessage(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) { + return 0; LPCWSTR lpOldText = lpText; LPCWSTR lpOldCaption = lpCaption; wchar_t wszText[MAX_PATH]; @@ -4926,7 +5487,7 @@ HRESULT WINAPI _DllRegisterServer() Code = 1; if (dwLastError) Code = -Code; - ZZRestartExplorer(); + //ZZRestartExplorer(0, 0, 0, 0); return dwLastError == 0 ? S_OK : HRESULT_FROM_WIN32(dwLastError); } @@ -5067,7 +5628,7 @@ HRESULT WINAPI _DllUnregisterServer() Code = 2; if (dwLastError) Code = -Code; - ZZRestartExplorer(); + //ZZRestartExplorer(0, 0, 0, 0); return dwLastError == 0 ? S_OK : HRESULT_FROM_WIN32(dwLastError); } diff --git a/ExplorerPatcher/updates.c b/ExplorerPatcher/updates.c new file mode 100644 index 0000000..9c5650d --- /dev/null +++ b/ExplorerPatcher/updates.c @@ -0,0 +1,593 @@ +#include "updates.h" + +BOOL IsUpdatePolicy(LPCWSTR wszDataStore, DWORD dwUpdatePolicy) +{ + HKEY hKey = NULL; + DWORD dwSize = 0; + DWORD dwQueriedPolicy = 0; + BOOL bIsPolicyMatch = (dwUpdatePolicy == UPDATE_POLICY_AUTO); + + RegCreateKeyExW( + HKEY_CURRENT_USER, + wszDataStore, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WOW64_64KEY, + NULL, + &hKey, + NULL + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + dwSize = sizeof(DWORD); + RegQueryValueExW( + hKey, + TEXT("UpdatePolicy"), + 0, + NULL, + &dwQueriedPolicy, + &dwSize + ); + RegCloseKey(hKey); + bIsPolicyMatch = (dwQueriedPolicy == dwUpdatePolicy); + } + return bIsPolicyMatch; +} + +void IsUpdateAvailableHelperCallback( + HINTERNET hInternet, + struct IsUpdateAvailableParameters* params, + DWORD dwInternetStatus, + INTERNET_ASYNC_RESULT* lpvStatusInformation, + DWORD dwStatusInformationLength +) +{ + if (dwInternetStatus == INTERNET_STATUS_REQUEST_COMPLETE) + { + params->hInternet = lpvStatusInformation->dwResult; + SetEvent(params->hEvent); + } +} + +BOOL IsUpdateAvailableHelper(char* url, char* szCheckAgainst, DWORD dwUpdateTimeout, BOOL* lpFail) +{ + BOOL bIsUpdateAvailable = FALSE; + + struct IsUpdateAvailableParameters params; + params.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!params.hEvent) + { + return bIsUpdateAvailable; + } + + HINTERNET hInternet = NULL; + if (hInternet = InternetOpenA( + UPDATES_USER_AGENT, + INTERNET_OPEN_TYPE_PRECONFIG, + NULL, + NULL, + INTERNET_FLAG_ASYNC + )) + { + InternetSetOptionA(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, &dwUpdateTimeout, sizeof(DWORD)); + if (InternetSetStatusCallbackA(hInternet, IsUpdateAvailableHelperCallback) != INTERNET_INVALID_STATUS_CALLBACK) + { + HINTERNET hConnect = InternetOpenUrlA( + hInternet, + url, + NULL, + 0, + INTERNET_FLAG_RAW_DATA | + INTERNET_FLAG_RELOAD | + INTERNET_FLAG_RESYNCHRONIZE | + INTERNET_FLAG_NO_COOKIES | + INTERNET_FLAG_NO_UI | + INTERNET_FLAG_NO_CACHE_WRITE, + ¶ms + ); + if (!hConnect && GetLastError() == ERROR_IO_PENDING) + { + if (WaitForSingleObject(params.hEvent, dwUpdateTimeout) == WAIT_OBJECT_0) + { + hConnect = params.hInternet; + } + } + if (hConnect) + { + if (szCheckAgainst) + { + BOOL bRet = FALSE; + DWORD dwRead = 0; + char hash[DOSMODE_OFFSET + UPDATES_HASH_SIZE + 1]; + ZeroMemory(hash, DOSMODE_OFFSET + UPDATES_HASH_SIZE + 1); + if (bRet = InternetReadFile( + hConnect, + hash, + DOSMODE_OFFSET + UPDATES_HASH_SIZE, + &dwRead + ) && dwRead == DOSMODE_OFFSET + UPDATES_HASH_SIZE) + { +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Hash of remote file is \"%s\" (%s).\n", DOSMODE_OFFSET + hash, (hash[0] == 0x4D && hash[1] == 0x5A) ? "valid" : "invalid"); +#endif + if (hash[0] == 0x4D && hash[1] == 0x5A && _stricmp(DOSMODE_OFFSET + hash, szCheckAgainst)) + { + bIsUpdateAvailable = TRUE; + } + } + else + { + if (lpFail) *lpFail = TRUE; + } + } + else + { + WCHAR wszPath[MAX_PATH]; + ZeroMemory(wszPath, MAX_PATH * sizeof(WCHAR)); + SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); + wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH)); + BOOL bRet = CreateDirectoryW(wszPath, NULL); + if (bRet || (!bRet && GetLastError() == ERROR_ALREADY_EXISTS)) + { + wcscat_s(wszPath, MAX_PATH, L"\\Update for " _T(PRODUCT_NAME) L" from "); + WCHAR wszURL[MAX_PATH]; + ZeroMemory(wszURL, MAX_PATH * sizeof(WCHAR)); + MultiByteToWideChar( + CP_UTF8, + MB_PRECOMPOSED, + url, + -1, + wszURL, + MAX_PATH + ); + if (wszURL[95]) + { + wszURL[94] = L'.'; + wszURL[95] = L'.'; + wszURL[96] = L'.'; + wszURL[97] = L'e'; + wszURL[98] = L'x'; + wszURL[99] = L'e'; + wszURL[100] = 0; + } + for (unsigned int i = 0; i < wszURL; ++i) + { + if (!wszURL[i]) + { + break; + } + if (wszURL[i] == L'/') + { + wszURL[i] = L'\u2215'; + } + else if (wszURL[i] == L':') + { + wszURL[i] = L'\ua789'; + } + } + wcscat_s(wszPath, MAX_PATH, wszURL); +#ifdef UPDATES_VERBOSE_OUTPUT + wprintf(L"[Updates] Download path is \"%s\".\n", wszPath); +#endif + + BOOL bRet = DeleteFileW(wszPath); + if (bRet || (!bRet && GetLastError() == ERROR_FILE_NOT_FOUND)) + { + FILE* f = NULL; + if (!_wfopen_s( + &f, + wszPath, + L"wb" + ) && f) + { + BYTE* buffer = (BYTE*)malloc(UPDATES_BUFSIZ); + if (buffer != NULL) + { + DWORD dwRead = 0; + bRet = FALSE; + while (bRet = InternetReadFile( + hConnect, + buffer, + UPDATES_BUFSIZ, + &dwRead + )) + { + if (dwRead == 0) + { + bIsUpdateAvailable = TRUE; +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Downloaded finished.\n"); +#endif + break; + } +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Downloaded %d bytes.\n", dwRead); +#endif + fwrite( + buffer, + sizeof(BYTE), + dwRead, + f + ); + dwRead = 0; + } + free(buffer); + } + fclose(f); + } + if (bIsUpdateAvailable) + { + bIsUpdateAvailable = FALSE; +#ifdef UPDATES_VERBOSE_OUTPUT + printf( + "[Updates] In order to install this update for the product \"" + PRODUCT_NAME + "\", please allow the elevation request.\n" + ); +#endif + SHELLEXECUTEINFO ShExecInfo = { 0 }; + ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); + ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + ShExecInfo.hwnd = NULL; + ShExecInfo.lpVerb = L"runas"; + ShExecInfo.lpFile = wszPath; + ShExecInfo.lpParameters = L"/update_silent"; + ShExecInfo.lpDirectory = NULL; + ShExecInfo.nShow = SW_SHOW; + ShExecInfo.hInstApp = NULL; + if (ShellExecuteExW(&ShExecInfo) && ShExecInfo.hProcess) + { + WaitForSingleObject(ShExecInfo.hProcess, INFINITE); + DWORD dwExitCode = 0; + if (GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode) && !dwExitCode) + { + bIsUpdateAvailable = TRUE; +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Update successful, File Explorer will probably restart momentarly.\n"); +#endif + } + else + { + SetLastError(dwExitCode); +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Update failed because the following error has occured: %d.\n", dwExitCode); +#endif + } + CloseHandle(ShExecInfo.hProcess); + } + else + { + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED) + { +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Update failed because the elevation request was denied.\n"); +#endif + } + else + { +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Update failed because the following error has occured: %d.\n", GetLastError()); +#endif + } + } + } + } + } + } + InternetCloseHandle(hConnect); + } + else + { + if (lpFail) *lpFail = TRUE; + } + } + InternetCloseHandle(hInternet); + } + + CloseHandle(params.hEvent); + + return bIsUpdateAvailable; +} + +BOOL IsUpdateAvailable(LPCWSTR wszDataStore, char* szCheckAgainst, BOOL* lpFail) +{ + HKEY hKey = NULL; + DWORD dwSize = 0; + DWORD dwQueriedPolicy = 0; + BOOL bIsPolicyMatch = FALSE; + CHAR szUpdateURL[MAX_PATH]; + ZeroMemory(szUpdateURL, MAX_PATH * sizeof(CHAR)); + strcat_s(szUpdateURL, MAX_PATH, "https://github.com/valinet/ExplorerPatcher/releases/latest/download/"); +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Checking against hash \"%s\"\n", szCheckAgainst); +#endif + DWORD dwUpdateTimeout = UPDATES_DEFAULT_TIMEOUT; + + RegCreateKeyExW( + HKEY_CURRENT_USER, + wszDataStore, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WOW64_64KEY, + NULL, + &hKey, + NULL + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + dwSize = MAX_PATH; + RegQueryValueExA( + hKey, + "UpdateURL", + 0, + NULL, + szUpdateURL, + &dwSize + ); + strcat_s(szUpdateURL, MAX_PATH, SETUP_UTILITY_NAME); + dwSize = sizeof(DWORD); + RegQueryValueExA( + hKey, + "UpdateTimeout", + 0, + NULL, + &dwUpdateTimeout, + &dwSize + ); + RegCloseKey(hKey); + } +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Update URL: %s\n", szUpdateURL); +#endif + return IsUpdateAvailableHelper(szUpdateURL, szCheckAgainst, dwUpdateTimeout, lpFail); +} + +BOOL UpdateProduct(LPCWSTR wszDataStore) +{ + HKEY hKey = NULL; + DWORD dwSize = 0; + DWORD dwQueriedPolicy = 0; + BOOL bIsPolicyMatch = FALSE; + CHAR szUpdateURL[MAX_PATH]; + ZeroMemory(szUpdateURL, MAX_PATH * sizeof(CHAR)); + strcat_s(szUpdateURL, MAX_PATH, "https://github.com/valinet/ExplorerPatcher/releases/latest/download/"); + + DWORD dwUpdateTimeout = UPDATES_DEFAULT_TIMEOUT; + + RegCreateKeyExW( + HKEY_CURRENT_USER, + wszDataStore, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WOW64_64KEY, + NULL, + &hKey, + NULL + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + dwSize = MAX_PATH; + RegQueryValueExA( + hKey, + "UpdateURL", + 0, + NULL, + szUpdateURL, + &dwSize + ); + strcat_s(szUpdateURL, MAX_PATH, SETUP_UTILITY_NAME); + dwSize = sizeof(DWORD); + RegQueryValueExA( + hKey, + "UpdateTimeout", + 0, + NULL, + &dwUpdateTimeout, + &dwSize + ); + RegCloseKey(hKey); + } +#ifdef UPDATES_VERBOSE_OUTPUT + printf("[Updates] Update URL: %s\n", szUpdateURL); +#endif + return IsUpdateAvailableHelper(szUpdateURL, NULL, dwUpdateTimeout, NULL); +} + +BOOL InstallUpdatesIfAvailable(DWORD dwOperation, DWORD bAllocConsole, DWORD dwUpdatePolicy) +{ + if (bAllocConsole) + { + switch (dwUpdatePolicy) + { + default: + case UPDATE_POLICY_AUTO: + { + dwUpdatePolicy = UPDATE_POLICY_AUTO; + printf("[Updates] Configured update policy on this system: \"Install updates automatically\".\n"); + break; + } + case UPDATE_POLICY_NOTIFY: + { + printf("[Updates] Configured update policy on this system: \"Check for updates but let me choose whether to download and install them\".\n"); + break; + } + case UPDATE_POLICY_MANUAL: + { + printf("[Updates] Configured update policy on this system: \"Manually check for updates\".\n"); + break; + } + } + } + + if (dwOperation == UPDATES_OP_INSTALL) + { + const wchar_t UpdateAvailableXML[] = + L"\r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n"; + HRESULT hr = S_OK; + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL; + hr = String2IXMLDocument( + UpdateAvailableXML, + wcslen(UpdateAvailableXML), + &inputXml, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + } + + WCHAR dllName[MAX_PATH]; + GetModuleFileNameW(hModule, dllName, MAX_PATH); + wprintf(L"[Updates] Path to module: %s\n", dllName); + + CHAR hash[100]; + ZeroMemory(hash, 100 * sizeof(CHAR)); + ComputeFileHash(dllName, hash, 100); + + BOOL bFail = FALSE; + if (IsUpdateAvailable(_T(REGPATH), hash, &bFail)) + { + printf("[Updates] An update is available.\n"); + if ((dwOperation == UPDATES_OP_DEFAULT && dwUpdatePolicy == UPDATE_POLICY_AUTO) || (dwOperation == UPDATES_OP_INSTALL)) + { + UpdateProduct(_T(REGPATH)); + } + else if ((dwOperation == UPDATES_OP_DEFAULT && dwUpdatePolicy == UPDATE_POLICY_NOTIFY) || (dwOperation == UPDATES_OP_CHECK)) + { + const wchar_t UpdateAvailableXML[] = + L"\r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n"; + HRESULT hr = S_OK; + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL; + hr = String2IXMLDocument( + UpdateAvailableXML, + wcslen(UpdateAvailableXML), + &inputXml, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + } + + return TRUE; + } + else + { + if (bFail) + { + printf("[Updates] Unable to check for updates because the remote server is unavailable.\n"); + } + else + { + printf("[Updates] No updates are available.\n"); + } + if (dwOperation == UPDATES_OP_CHECK || dwOperation == UPDATES_OP_INSTALL) + { + const wchar_t UpdateAvailableXML[] = + L"\r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n"; + const wchar_t UpdateAvailableXML2[] = + L"\r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n" + L" \r\n"; + HRESULT hr = S_OK; + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL; + hr = String2IXMLDocument( + bFail ? UpdateAvailableXML2 : UpdateAvailableXML, + wcslen(bFail ? UpdateAvailableXML2 : UpdateAvailableXML), + &inputXml, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + } + return FALSE; + } +} \ No newline at end of file diff --git a/ExplorerPatcher/updates.h b/ExplorerPatcher/updates.h new file mode 100644 index 0000000..5681fb9 --- /dev/null +++ b/ExplorerPatcher/updates.h @@ -0,0 +1,39 @@ +#ifndef _H_UPDATES_H_ +#define _H_UPDATES_H_ +#include +#include +#include +#pragma comment(lib, "Wininet.lib") +#include +#include "utility.h" + +extern HMODULE hModule; + +#define UPDATES_VERBOSE_OUTPUT + +#define UPDATE_POLICY_AUTO 0 +#define UPDATE_POLICY_NOTIFY 1 +#define UPDATE_POLICY_MANUAL 2 +#define UPDATE_POLICY_DEFAULT UPDATE_POLICY_NOTIFY + +#define UPDATES_OP_DEFAULT 0 +#define UPDATES_OP_CHECK 1 +#define UPDATES_OP_INSTALL 2 + +#define UPDATES_USER_AGENT "ExplorerPatcher" +#define UPDATES_FORM_HEADERS "Content-Type: text/plain;\r\n" +#define UPDATES_HASH_SIZE 32 +#define UPDATES_BUFSIZ 10240 +#define UPDATES_DEFAULT_TIMEOUT 600 + +typedef struct IsUpdateAvailableParameters +{ + HINTERNET hInternet; + HANDLE hEvent; +}; + +BOOL IsUpdatePolicy(LPCWSTR wszDataStore, DWORD dwUpdatePolicy); +BOOL IsUpdateAvailable(LPCWSTR wszDataStore, char* szCheckAgainst); +BOOL UpdateProduct(LPCWSTR wszDataStore); +BOOL InstallUpdatesIfAvailable(DWORD dwOperation, DWORD bAllocConsole, DWORD dwUpdatePolicy); +#endif \ No newline at end of file diff --git a/ep_setup/ep_setup.c b/ep_setup/ep_setup.c new file mode 100644 index 0000000..29edfb0 --- /dev/null +++ b/ep_setup/ep_setup.c @@ -0,0 +1,525 @@ +#include +#pragma comment(linker,"\"/manifestdependency:type='win32' \ +name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ +processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#include +#include +#pragma comment(lib, "Shlwapi.lib") +#include "resource.h" +#include "../ExplorerPatcher/utility.h" + +BOOL SetupUninstallEntry(BOOL bInstall, WCHAR* wszPath) +{ + DWORD dwLastError = ERROR_SUCCESS; + HKEY hKey = NULL; + + if (bInstall) + { + + if (!dwLastError) + { + dwLastError = RegCreateKeyExW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" _T(EP_CLSID) L"_" _T(PRODUCT_NAME), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_WRITE | KEY_WOW64_64KEY, + NULL, + &hKey, + NULL + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + if (!dwLastError) + { + dwLastError = RegSetValueExW( + hKey, + L"UninstallString", + 0, + REG_SZ, + wszPath, + (wcslen(wszPath) + 1) * sizeof(wchar_t) + ); + } + if (!dwLastError) + { + dwLastError = RegSetValueExW( + hKey, + L"DisplayName", + 0, + REG_SZ, + _T(PRODUCT_NAME), + (wcslen(_T(PRODUCT_NAME)) + 1) * sizeof(wchar_t) + ); + } + if (!dwLastError) + { + dwLastError = RegSetValueExW( + hKey, + L"Publisher", + 0, + REG_SZ, + _T(PRODUCT_PUBLISHER), + (wcslen(_T(PRODUCT_PUBLISHER)) + 1) * sizeof(wchar_t) + ); + } + if (!dwLastError) + { + DWORD dw1 = TRUE; + dwLastError = RegSetValueExW( + hKey, + L"NoModify", + 0, + REG_DWORD, + &dw1, + sizeof(DWORD) + ); + } + if (!dwLastError) + { + DWORD dw1 = TRUE; + dwLastError = RegSetValueExW( + hKey, + L"NoRepair", + 0, + REG_DWORD, + &dw1, + sizeof(DWORD) + ); + } + if (!dwLastError) + { + PathRemoveFileSpecW(wszPath); + wcscat_s(wszPath, MAX_PATH, L"\\" _T(PRODUCT_NAME) L".amd64.dll"); + HMODULE hEP = LoadLibraryExW(wszPath, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (hEP) + { + DWORD dwLeftMost = 0; + DWORD dwSecondLeft = 0; + DWORD dwSecondRight = 0; + DWORD dwRightMost = 0; + + QueryVersionInfo(hEP, VS_VERSION_INFO, &dwLeftMost, &dwSecondLeft, &dwSecondRight, &dwRightMost); + + WCHAR wszBuf[20]; + swprintf_s(wszBuf, 20, L"%d.%d.%d.%d", dwLeftMost, dwSecondLeft, dwSecondRight, dwRightMost); + + if (!dwLastError) + { + dwLastError = RegSetValueExW( + hKey, + L"DisplayVersion", + 0, + REG_SZ, + wszBuf, + (wcslen(wszBuf) + 1) * sizeof(wchar_t) + ); + if (!dwLastError) + { + dwLastError = RegSetValueExW( + hKey, + L"VersionMajor", + 0, + REG_DWORD, + &dwSecondRight, + sizeof(DWORD) + ); + if (!dwLastError) + { + dwLastError = RegSetValueExW( + hKey, + L"VersionMinor", + 0, + REG_DWORD, + &dwRightMost, + sizeof(DWORD) + ); + } + } + } + + FreeLibrary(hEP); + } + } + if (!dwLastError) + { + GetWindowsDirectoryW(wszPath, MAX_PATH); + wcscat_s(wszPath, MAX_PATH, L"\\explorer.exe"); + dwLastError = RegSetValueExW( + hKey, + L"DisplayIcon", + 0, + REG_SZ, + wszPath, + (wcslen(wszPath) + 1) * sizeof(wchar_t) + ); + } + RegCloseKey(hKey); + } + } + } + else + { + if (!dwLastError) + { + dwLastError = RegOpenKeyW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" _T(EP_CLSID) L"_" _T(PRODUCT_NAME), + &hKey + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + dwLastError = RegDeleteTreeW( + hKey, + 0 + ); + RegCloseKey(hKey); + if (!dwLastError) + { + RegDeleteKeyW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" _T(EP_CLSID) L"_" _T(PRODUCT_NAME) + ); + } + return TRUE; + } + } + } + return !dwLastError; +} + +BOOL InstallResource(BOOL bInstall, HMODULE hModule, int res, WCHAR* wszPath) +{ + if (PathFileExistsW(wszPath)) + { + WCHAR wszReplace[MAX_PATH]; + wcscpy_s(wszReplace, MAX_PATH, wszPath); + PathRemoveExtensionW(wszReplace); + wcscat_s(wszReplace, MAX_PATH, L".prev"); + BOOL bRet = DeleteFileW(wszReplace); + if (bRet || (!bRet && GetLastError() == ERROR_FILE_NOT_FOUND)) + { + if (!MoveFileW(wszPath, wszReplace)) + { + return FALSE; + } + } + else + { + return FALSE; + } + } + if (res == 0) + { + if (bInstall) + { + wchar_t path[MAX_PATH]; + GetModuleFileNameW(hModule, path, MAX_PATH); + return CopyFileW(path, wszPath, FALSE); + } + return TRUE; + } + else + { + HRSRC hRscr = FindResource( + hModule, + MAKEINTRESOURCE(res), + RT_RCDATA + ); + if (!hRscr) + { + return FALSE; + } + HGLOBAL hgRscr = LoadResource( + hModule, + hRscr + ); + if (!hgRscr) + { + return FALSE; + } + void* pRscr = LockResource(hgRscr); + DWORD cbRscr = SizeofResource( + hModule, + hRscr + ); + if (bInstall) + { + HANDLE hFile = CreateFileW( + wszPath, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (!hFile) + { + return FALSE; + } + DWORD dwNumberOfBytesWritten = 0; + if (!WriteFile( + hFile, + pRscr, + cbRscr, + &dwNumberOfBytesWritten, + NULL + )) + { + return FALSE; + } + CloseHandle(hFile); + } + return TRUE; + } +} + +int WINAPI wWinMain( + _In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nShowCmd +) +{ + BOOL bOk = TRUE, bInstall = TRUE, bWasShellExt = FALSE; + + SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + + if (!IsAppRunningAsAdminMode()) + { + WCHAR wszPath[MAX_PATH]; + ZeroMemory(wszPath, ARRAYSIZE(wszPath)); + if (GetModuleFileNameW(NULL, wszPath, ARRAYSIZE(wszPath))) + { + SHELLEXECUTEINFOW sei; + ZeroMemory(&sei, sizeof(SHELLEXECUTEINFOW)); + sei.cbSize = sizeof(sei); + sei.lpVerb = L"runas"; + sei.lpFile = wszPath; + sei.lpParameters = lpCmdLine; + sei.hwnd = NULL; + sei.nShow = SW_NORMAL; + if (!ShellExecuteExW(&sei)) + { + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED) + { + } + } + exit(0); + } + } + + int argc = 0; + LPWSTR* wargv = CommandLineToArgvW( + lpCmdLine, + &argc + ); + + WCHAR wszPath[MAX_PATH]; + ZeroMemory(wszPath, MAX_PATH * sizeof(WCHAR)); + if (bOk) + { + bOk = GetWindowsDirectoryW(wszPath, MAX_PATH); + } + if (bOk) + { + wcscat_s(wszPath, MAX_PATH, L"\\dxgi.dll"); + bInstall = !FileExistsW(wszPath) || (argc >= 1 && !_wcsicmp(wargv[0], L"/update_silent")); + } + if (!bInstall) + { + if (MessageBoxW( + NULL, + L"Are you sure you want to remove " _T(PRODUCT_NAME) L" from your computer?", + _T(PRODUCT_NAME), + MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION + ) == IDNO) + { + exit(0); + } + } + + SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); + wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH)); + bOk = CreateDirectoryW(wszPath, NULL); + if (bOk || (!bOk && GetLastError() == ERROR_ALREADY_EXISTS)) + { + bOk = TRUE; + + GetSystemDirectoryW(wszPath, MAX_PATH); + wcscat_s(wszPath, MAX_PATH, L"\\taskkill.exe"); + ShellExecuteW( + NULL, + L"open", + wszPath, + L"/f /im explorer.exe", + NULL, + SW_SHOWMINIMIZED + ); + + if (bOk) + { + SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); + wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH) L"\\" _T(SETUP_UTILITY_NAME)); + bOk = InstallResource(bInstall, hInstance, 0, wszPath); + } + if (bOk) + { + if (!bInstall) + { + HKEY hKey; + RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Classes\\CLSID\\" TEXT(EP_CLSID) L"\\InProcServer32", + REG_OPTION_NON_VOLATILE, + KEY_READ, + &hKey + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + bWasShellExt = TRUE; + RegCloseKey(hKey); + } + if (bWasShellExt) + { + WCHAR wszArgs[MAX_PATH]; + wszArgs[0] = L'/'; + wszArgs[1] = L'u'; + wszArgs[2] = L' '; + wszArgs[3] = L'"'; + SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszArgs + 4); + wcscat_s(wszArgs, MAX_PATH, _T(APP_RELATIVE_PATH) L"\\" _T(PRODUCT_NAME) L".amd64.dll\""); + wprintf(L"%s\n", wszArgs); + WCHAR wszApp[MAX_PATH * 2]; + GetSystemDirectoryW(wszApp, MAX_PATH * 2); + wcscat_s(wszApp, MAX_PATH * 2, L"\\regsvr32.exe"); + wprintf(L"%s\n", wszApp); + SHELLEXECUTEINFOW sei; + ZeroMemory(&sei, sizeof(SHELLEXECUTEINFOW)); + sei.cbSize = sizeof(sei); + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.hwnd = NULL; + sei.hInstApp = NULL; + sei.lpVerb = NULL; + sei.lpFile = wszApp; + sei.lpParameters = wszArgs; + sei.hwnd = NULL; + sei.nShow = SW_NORMAL; + if (ShellExecuteExW(&sei) && sei.hProcess) + { + WaitForSingleObject(sei.hProcess, INFINITE); + DWORD dwExitCode = 0; + GetExitCodeProcess(sei.hProcess, &dwExitCode); + SetLastError(dwExitCode); + } + } + } + } + if (bOk) + { + SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); + wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH) L"\\" _T(PRODUCT_NAME) L".IA-32.dll"); + bOk = InstallResource(bInstall, hInstance, IDR_EP_IA32, wszPath); + } + if (bOk) + { + PathRemoveFileSpecW(wszPath); + wcscat_s(wszPath, MAX_PATH, L"\\" _T(PRODUCT_NAME) L".amd64.dll"); + bOk = InstallResource(bInstall, hInstance, IDR_EP_AMD64, wszPath); + } + if (bOk) + { + bOk = GetWindowsDirectoryW(wszPath, MAX_PATH); + } + if (bOk) + { + wcscat_s(wszPath, MAX_PATH, L"\\dxgi.dll"); + bOk = InstallResource(bInstall, hInstance, IDR_EP_AMD64, wszPath); + } + if (bOk) + { + bOk = GetWindowsDirectoryW(wszPath, MAX_PATH); + } + if (bOk) + { + wcscat_s(wszPath, MAX_PATH, L"\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\dxgi.dll"); + bOk = InstallResource(bInstall, hInstance, IDR_EP_AMD64, wszPath); + } + if (bOk) + { + SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); + wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH) L"\\" _T(SETUP_UTILITY_NAME)); + bOk = SetupUninstallEntry(bInstall, wszPath); + } + + if (bOk) + { + if (!bInstall) + { + if (bWasShellExt) + { + if (MessageBoxW( + NULL, + L"Please reboot the computer to complete the uninstall.\n\nDo you want to reboot now?", + _T(PRODUCT_NAME), + MB_YESNO | MB_DEFBUTTON1 | MB_ICONQUESTION + ) == IDYES) + { + SystemShutdown(TRUE); + } + } + else + { + MessageBoxW( + NULL, + L"Uninstall completed. Thank you for using " _T(PRODUCT_NAME) L".", + _T(PRODUCT_NAME), + MB_ICONASTERISK | MB_OK | MB_DEFBUTTON1 + ); + } + } + else + { + //ZZRestartExplorer(0, 0, 0, 0); + } + } + if (!bOk && !(argc >= 1 && !_wcsicmp(wargv[0], L"/update_silent"))) + { + MessageBoxW( + NULL, + L"An error has occured when attempting to service the product. Please reboot the computer and try again.", + _T(PRODUCT_NAME), + MB_ICONERROR | MB_OK | MB_DEFBUTTON1 + ); + } + + GetWindowsDirectoryW(wszPath, MAX_PATH); + wcscat_s(wszPath, MAX_PATH, L"\\explorer.exe"); + Sleep(1000); + ShellExecuteW( + NULL, + L"open", + wszPath, + NULL, + NULL, + SW_SHOWNORMAL + ); + } + + return GetLastError(); +} \ No newline at end of file diff --git a/ep_setup/ep_setup.rc b/ep_setup/ep_setup.rc new file mode 100644 index 0000000..ad005ea --- /dev/null +++ b/ep_setup/ep_setup.rc @@ -0,0 +1,110 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2021,11,13,1 + PRODUCTVERSION 2021,11,13,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "VALINET Solutions SRL" + VALUE "FileDescription", "ExplorerPatcher Setup Program" + VALUE "FileVersion", "2021.11.13.1" + VALUE "InternalName", "ep_setup.exe" + VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved." + VALUE "OriginalFilename", "ep_setup.exe" + VALUE "ProductName", "ExplorerPatcher" + VALUE "ProductVersion", "2021.11.13.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// RCDATA +// + +IDR_EP_AMD64 RCDATA "..\\build\\Release\\ExplorerPatcher.amd64.dll" + +IDR_EP_IA32 RCDATA "..\\build\\Release\\ExplorerPatcher.IA-32.dll" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ep_setup/ep_setup.vcxproj b/ep_setup/ep_setup.vcxproj new file mode 100644 index 0000000..70e682a --- /dev/null +++ b/ep_setup/ep_setup.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {2fd40b09-f224-4e9a-b2fe-a22b50b2debf} + epsetup + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(Configuration) + + + false + $(SolutionDir)\build\$(Configuration) + + + true + $(SolutionDir)\build\$(Configuration) + + + false + $(SolutionDir)\build\$(Configuration) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Windows + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Windows + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ep_setup/ep_setup.vcxproj.filters b/ep_setup/ep_setup.vcxproj.filters new file mode 100644 index 0000000..b7ab033 --- /dev/null +++ b/ep_setup/ep_setup.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + + + + + Resource Files + + + \ No newline at end of file diff --git a/ep_setup/resource.h b/ep_setup/resource.h new file mode 100644 index 0000000..6be02ae --- /dev/null +++ b/ep_setup/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ep_setup.rc +// +#define IDR_EP_AMD64 103 +#define IDR_EP_IA32 104 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ep_setup_patch/ep_setup_patch.c b/ep_setup_patch/ep_setup_patch.c new file mode 100644 index 0000000..9703f9e --- /dev/null +++ b/ep_setup_patch/ep_setup_patch.c @@ -0,0 +1,69 @@ +#include +#include +#pragma comment(lib, "Shlwapi.lib") +#include "../ExplorerPatcher/utility.h" + +int main(int argc, char** argv) +{ + WCHAR wszPath[MAX_PATH]; + GetModuleFileNameW(GetModuleHandle(NULL), wszPath, MAX_PATH); + PathRemoveFileSpecW(wszPath); + wcscat_s(wszPath, MAX_PATH, L"\\" _T(PRODUCT_NAME) L".amd64.dll"); + + CHAR hash[100]; + ZeroMemory(hash, 100); + ComputeFileHash(wszPath, hash, 100); + + PathRemoveFileSpecW(wszPath); + wcscat_s(wszPath, MAX_PATH, L"\\" _T(SETUP_UTILITY_NAME)); + + HANDLE hFile = CreateFileW(wszPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hFile == INVALID_HANDLE_VALUE) + { + return 1; + } + + HANDLE hFileMapping = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); + if (hFileMapping == 0) + { + CloseHandle(hFile); + return 2; + } + + char* lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (lpFileBase == 0) + { + CloseHandle(hFileMapping); + CloseHandle(hFile); + return 3; + } + + memcpy(lpFileBase + DOSMODE_OFFSET, hash, strlen(hash)); + + UnmapViewOfFile(lpFileBase); + CloseHandle(hFileMapping); + CloseHandle(hFile); + + if (argc > 1) + { + SHELLEXECUTEINFO ShExecInfo = { 0 }; + ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); + ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + ShExecInfo.hwnd = NULL; + ShExecInfo.lpVerb = L"runas"; + ShExecInfo.lpFile = wszPath; + ShExecInfo.lpParameters = L"/update_silent"; + ShExecInfo.lpDirectory = NULL; + ShExecInfo.nShow = SW_SHOW; + ShExecInfo.hInstApp = NULL; + if (ShellExecuteExW(&ShExecInfo) && ShExecInfo.hProcess) + { + WaitForSingleObject(ShExecInfo.hProcess, INFINITE); + DWORD dwExitCode = 0; + GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode); + return dwExitCode; + } + } + + return 0; +} \ No newline at end of file diff --git a/ep_setup_patch/ep_setup_patch.vcxproj b/ep_setup_patch/ep_setup_patch.vcxproj new file mode 100644 index 0000000..74ae05e --- /dev/null +++ b/ep_setup_patch/ep_setup_patch.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {0c13e5f3-106b-4836-a7c2-8e5808a6ed78} + epsetuppatch + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(Configuration) + + + false + $(SolutionDir)\build\$(Configuration) + + + true + $(SolutionDir)\build\$(Configuration) + + + false + $(SolutionDir)\build\$(Configuration) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/ep_setup_patch/ep_setup_patch.vcxproj.filters b/ep_setup_patch/ep_setup_patch.vcxproj.filters new file mode 100644 index 0000000..2eb5c1e --- /dev/null +++ b/ep_setup_patch/ep_setup_patch.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file