This project aims to enhance the working environment on Windows
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

896 lines
23 KiB

#include <initguid.h>
#include <stdio.h>
#include <stdbool.h>
#include <Windows.h>
#include <funchook.h>
#pragma comment(lib, "Psapi.lib") // required by funchook
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <dwmapi.h>
#pragma comment(lib, "Dwmapi.lib")
#include <windowsx.h>
#define DEBUG
#undef DEBUG
funchook_t* funchook = NULL;
HMODULE hModule = NULL;
HWND messageWindow = NULL;
static HWND(WINAPI* CreateWindowInBand)(
_In_ DWORD dwExStyle,
_In_opt_ ATOM atom,
_In_opt_ LPCWSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int X,
_In_ int Y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam,
DWORD band
);
static INT64(*CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)(
void* _this,
POINT* pt
);
static void(*CLauncherTipContextMenu_ExecuteCommand)(
void* _this,
int a2
);
static void(*CLauncherTipContextMenu_ExecuteShutdownCommand)(
void* _this,
void* a2
);
static INT64(*InternalAddRef)(
void* a1,
INT64 a2
);
static INT64(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu)(
HMENU h1,
HMENU h2,
HWND a3,
unsigned int a4,
void* data
);
static void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu)(
HMENU _this,
HMENU hWnd,
HWND a3
);
static INT64(*CLauncherTipContextMenu_GetMenuItemsAsync)(
void* _this,
void* rect,
void** iunk
);
static INT64(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc)(
HWND hWnd,
int a2,
HWND a3,
int a4,
BOOL* a5
);
DEFINE_GUID(IID_ILauncherTipContextMenu,
0xb8c1db5f,
0xcbb3, 0x48bc, 0xaf, 0xd9,
0xce, 0x6b, 0x88, 0x0c, 0x79, 0xed
);
#define CLASS_NAME L"LauncherTipWnd"
static HRESULT(*CImmersiveHotkeyNotification_OnMessageFunc)(
void* _this,
INT64 msg,
INT wParam,
INT64 lParam
);
static INT64(*CImmersiveHotkeyNotification_GetMonitorForHotkeyNotificationFunc)(
void* _this,
void** a2,
HWND* a3
);
static BOOL(*IsDesktopInputContextFunc)(
void* p1,
void* p2
);
DEFINE_GUID(CLSID_ImmersiveShell,
0xc2f03a33,
0x21f5, 0x47fa, 0xb4, 0xbb,
0x15, 0x63, 0x62, 0xa2, 0xf2, 0x39
);
DEFINE_GUID(SID_IImmersiveMonitorService,
0x47094e3a,
0x0cf2, 0x430f, 0x80, 0x6f,
0xcf, 0x9e, 0x4f, 0x0f, 0x12, 0xdd
);
DEFINE_GUID(IID_IImmersiveMonitorService,
0x4d4c1e64,
0xe410, 0x4faa, 0xba, 0xfa,
0x59, 0xca, 0x06, 0x9b, 0xfe, 0xc2
);
DEFINE_GUID(SID_ImmersiveLauncher,
0x6f86e01c,
0xc649, 0x4d61, 0xbe, 0x23,
0xf1, 0x32, 0x2d, 0xde, 0xca, 0x9d
);
DEFINE_GUID(IID_IImmersiveLauncher10RS,
0xd8d60399,
0xa0f1, 0xf987, 0x55, 0x51,
0x32, 0x1f, 0xd1, 0xb4, 0x98, 0x64
);
typedef interface IImmersiveMonitorService IImmersiveMonitorService;
typedef struct IImmersiveMonitorServiceVtbl
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
IImmersiveMonitorService* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
ULONG(STDMETHODCALLTYPE* AddRef)(
IImmersiveMonitorService* This);
ULONG(STDMETHODCALLTYPE* Release)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method3)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method4)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method5)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* GetFromHandle)(
IImmersiveMonitorService* This,
/* [in] */ HMONITOR hMonitor,
_COM_Outptr_ IUnknown** ppvObject);
END_INTERFACE
} IImmersiveMonitorServiceVtbl;
interface IImmersiveMonitorService
{
CONST_VTBL struct IImmersiveMonitorServiceVtbl* lpVtbl;
};
typedef interface IImmersiveLauncher10RS IImmersiveLauncher10RS;
typedef struct IImmersiveLauncher10RSVtbl
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
IImmersiveLauncher10RS* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
ULONG(STDMETHODCALLTYPE* AddRef)(
IImmersiveLauncher10RS* This);
ULONG(STDMETHODCALLTYPE* Release)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* ShowStartView)(
IImmersiveLauncher10RS* This,
/* [in] */ int method,
/* [in] */ int flags);
HRESULT(STDMETHODCALLTYPE* Dismiss)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* method5)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* method6)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* IsVisible)(
IImmersiveLauncher10RS* This,
/* [in] */ BOOL* ret);
HRESULT(STDMETHODCALLTYPE* method8)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* method9)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* ConnectToMonitor)(
IImmersiveLauncher10RS* This,
/* [in] */ IUnknown* monitor);
HRESULT(STDMETHODCALLTYPE* GetMonitor)(
IImmersiveLauncher10RS* This,
/* [in] */ IUnknown** monitor);
END_INTERFACE
} IImmersiveLauncher10RSVtbl;
interface IImmersiveLauncher10RS
{
CONST_VTBL struct IImmersiveLauncher10RSVtbl* lpVtbl;
};
HANDLE hThread;
LRESULT CALLBACK CLauncherTipContextMenu_WndProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
LRESULT result;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCs = lParam;
if (pCs->lpCreateParams)
{
*((HWND*)((char*)pCs->lpCreateParams + 0x78)) = hWnd;
SetWindowLongPtr(
hWnd,
GWLP_USERDATA,
pCs->lpCreateParams
);
result = DefWindowProc(
hWnd,
uMsg,
wParam,
lParam
);
}
else
{
result = 0;
}
}
else
{
void* _this = GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (_this)
{
BOOL v12 = FALSE;
if ((uMsg == WM_DRAWITEM || uMsg == WM_MEASUREITEM) &&
CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc(
hWnd,
uMsg,
wParam,
lParam,
&v12
))
{
result = 0;
}
else
{
result = DefWindowProc(
hWnd,
uMsg,
wParam,
lParam
);
}
if (uMsg == WM_NCDESTROY)
{
SetWindowLongPtrW(
hWnd,
GWLP_USERDATA,
0
);
*((HWND*)((char*)_this + 0x78)) = 0;
}
}
else
{
result = DefWindowProc(
hWnd,
uMsg,
wParam,
lParam
);
}
}
return result;
}
typedef struct
{
void* _this;
POINT point;
IUnknown* iunk;
} ShowLauncherTipContextMenuParameters;
DWORD ShowLauncherTipContextMenu(
ShowLauncherTipContextMenuParameters* params
)
{
WNDCLASS wc = { 0 };
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = CLauncherTipContextMenu_WndProc;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = CLASS_NAME;
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
RegisterClass(&wc);
HWND hWnd = CreateWindowInBand(
0,
CLASS_NAME,
0,
WS_POPUP,
0,
0,
0,
0,
0,
0,
GetModuleHandle(NULL),
(char*)params->_this - 0x58,
7
);
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
while (!(*((HMENU*)((char*)params->_this + 0xe8))))
{
Sleep(1);
}
if (!(*((HMENU*)((char*)params->_this + 0xe8))))
{
goto finalize;
}
INT64* unknown_array = calloc(4, sizeof(INT64));
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu(
*((HMENU*)((char*)params->_this + 0xe8)),
hWnd,
&(params->point),
0xc,
unknown_array
);
BOOL res = TrackPopupMenu(
*((HMENU*)((char*)params->_this + 0xe8)),
TPM_RETURNCMD,
params->point.x,
params->point.y,
0,
hWnd,
0
);
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu(
*((HMENU*)((char*)params->_this + 0xe8)),
hWnd,
&(params->point)
);
free(unknown_array);
if (res > 0)
{
if (res < 4000)
{
INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xa8 - 0x58)) + (INT64)res * 8 - 8);
CLauncherTipContextMenu_ExecuteCommand(
(char*)params->_this - 0x58,
&info
);
}
else
{
INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xc8 - 0x58)) + ((INT64)res - 4000) * 8);
CLauncherTipContextMenu_ExecuteShutdownCommand(
(char*)params->_this - 0x58,
&info
);
}
}
finalize:
params->iunk->lpVtbl->Release(params->iunk);
SendMessage(
hWnd,
WM_CLOSE,
0,
0
);
free(params);
hThread = NULL;
return 0;
}
INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
void* _this,
POINT* pt
)
{
if (hThread)
{
goto finalize;
}
POINT point;
if (pt)
{
point = *pt;
}
else
{
POINT ptCursor;
GetCursorPos(&ptCursor);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(
MonitorFromPoint(
ptCursor,
MONITOR_DEFAULTTONEAREST
),
&mi
);
// https://stackoverflow.com/questions/44746234/programatically-get-windows-taskbar-info-autohidden-state-taskbar-coordinates
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
if (abd.rc.left < 5 && abd.rc.top > 5)
{
// TB_POS_BOTTOM
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.bottom;
}
else if (abd.rc.left < 5 && abd.rc.top < 5 && abd.rc.right > abd.rc.bottom)
{
// TB_POS_TOP
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.top;
}
else if (abd.rc.left < 5 && abd.rc.top < 5 && abd.rc.right < abd.rc.bottom)
{
// TB_POS_LEFT
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.top;
}
else if (abd.rc.left > 5 && abd.rc.top < 5)
{
// TB_POS_RIGHT
point.x = mi.rcMonitor.right;
point.y = mi.rcMonitor.top;
}
}
IUnknown* iunk;
INT64 r = CLauncherTipContextMenu_GetMenuItemsAsync(
_this,
&point,
&iunk
);
iunk->lpVtbl->AddRef(iunk);
ShowLauncherTipContextMenuParameters* params = malloc(
sizeof(ShowLauncherTipContextMenuParameters)
);
params->_this = _this;
params->point = point;
params->iunk = iunk;
hThread = CreateThread(
0,
0,
ShowLauncherTipContextMenu,
params,
0,
0
);
finalize:
return CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt);
}
HRESULT CImmersiveHotkeyNotification_OnMessageHook(
void* _this,
INT64 msg,
INT wParam,
INT64 lParam
)
{
if (wParam == 28 && IsDesktopInputContextFunc(_this, msg)) // 15
{
IUnknown* pMonitor;
HRESULT hr = CImmersiveHotkeyNotification_GetMonitorForHotkeyNotificationFunc(
(char*)_this - 0x68,
&pMonitor,
0
);
if (SUCCEEDED(hr))
{
IUnknown* pMenu;
IUnknown_QueryService(
pMonitor,
&IID_ILauncherTipContextMenu,
&IID_ILauncherTipContextMenu,
&pMenu
);
if (pMenu)
{
CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
pMenu,
0
);
pMenu->lpVtbl->Release(pMenu);
}
}
return 0;
}
return CImmersiveHotkeyNotification_OnMessageFunc(
_this,
msg,
wParam,
lParam
);
}
// Slightly tweaked version of function available in Open Shell
// (Open-Shell-Menu\Src\StartMenu\StartMenuHelper\StartMenuHelper.cpp)
LRESULT CALLBACK HookProgManThread(int code, WPARAM wParam, LPARAM lParam)
{
if (code == HC_ACTION && wParam)
{
MSG* msg = (MSG*)lParam;
if (msg->message == WM_SYSCOMMAND && (msg->wParam & 0xFFF0) == SC_TASKLIST)
{
BOOL bShouldCheckHKLM = FALSE;
HKEY hKey;
if (RegOpenKeyEx(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage"),
0,
KEY_READ,
&hKey
) != ERROR_SUCCESS)
{
bShouldCheckHKLM = TRUE;
}
DWORD dwStatus = 0;
DWORD dwSize = sizeof(DWORD);
if (RegGetValue(
hKey,
NULL,
TEXT("MonitorOverride"),
RRF_RT_REG_DWORD,
NULL,
&dwStatus,
(LPDWORD)(&dwSize)
) != ERROR_SUCCESS)
{
bShouldCheckHKLM = TRUE;
}
RegCloseKey(hKey);
if (bShouldCheckHKLM)
{
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage"),
0,
KEY_READ,
&hKey
) != ERROR_SUCCESS)
{
goto finish;
}
dwStatus = 0;
dwSize = sizeof(DWORD);
if (RegGetValue(
hKey,
NULL,
TEXT("MonitorOverride"),
RRF_RT_REG_DWORD,
NULL,
&dwStatus,
(LPDWORD)(&dwSize)
) != ERROR_SUCCESS)
{
goto finish;
}
RegCloseKey(hKey);
}
if (dwStatus == 1)
{
goto finish;
}
DWORD pts = GetMessagePos();
POINT pt;
pt.x = GET_X_LPARAM(pts);
pt.y = GET_Y_LPARAM(pts);
HMONITOR monitor = MonitorFromPoint(
pt,
MONITOR_DEFAULTTONULL
);
HRESULT hr = S_OK;
IUnknown* pImmersiveShell;
hr = CoCreateInstance(
&CLSID_ImmersiveShell,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IServiceProvider,
&pImmersiveShell
);
if (SUCCEEDED(hr))
{
IImmersiveMonitorService* pMonitorService = NULL;
IUnknown_QueryService(
pImmersiveShell,
&SID_IImmersiveMonitorService,
&IID_IImmersiveMonitorService,
&pMonitorService
);
if (pMonitorService)
{
IUnknown* pMonitor = NULL;
pMonitorService->lpVtbl->GetFromHandle(
pMonitorService,
monitor,
&pMonitor
);
IImmersiveLauncher10RS* pLauncher = NULL;
IUnknown_QueryService(
pImmersiveShell,
&SID_ImmersiveLauncher,
&IID_IImmersiveLauncher10RS,
&pLauncher
);
if (pLauncher)
{
BOOL bIsVisible = FALSE;
pLauncher->lpVtbl->IsVisible(pLauncher, &bIsVisible);
if (SUCCEEDED(hr))
{
if (!bIsVisible)
{
if (pMonitor)
{
pLauncher->lpVtbl->ConnectToMonitor(pLauncher, pMonitor);
}
pLauncher->lpVtbl->ShowStartView(pLauncher, 11, 0);
}
else
{
pLauncher->lpVtbl->Dismiss(pLauncher);
}
}
pLauncher->lpVtbl->Release(pLauncher);
}
if (pMonitor)
{
pMonitor->lpVtbl->Release(pMonitor);
}
pMonitorService->lpVtbl->Release(pMonitorService);
}
pImmersiveShell->lpVtbl->Release(pImmersiveShell);
}
msg->message = WM_NULL;
}
}
finish:
return CallNextHookEx(NULL, code, wParam, lParam);
}
DWORD OpenStartOnCurentMonitorThread(LPVOID unused)
{
HWND g_ProgWin = FindWindowEx(
NULL,
NULL,
L"Progman",
NULL
);
DWORD progThread = GetWindowThreadProcessId(
g_ProgWin,
NULL
);
HHOOK g_ProgHook = SetWindowsHookEx(
WH_GETMESSAGE,
HookProgManThread,
NULL,
progThread
);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
__declspec(dllexport) DWORD WINAPI main(
_In_ LPVOID lpParameter
)
{
#ifdef DEBUG
FILE* conout;
AllocConsole();
freopen_s(
&conout,
"CONOUT$",
"w",
stdout
);
#endif
int rv;
if (!funchook)
{
messageWindow = (HWND)lpParameter;
funchook = funchook_create();
CreateThread(
0,
0,
OpenStartOnCurentMonitorThread,
0,
0,
0
);
HANDLE hUser32 = GetModuleHandle(L"user32.dll");
if (hUser32) CreateWindowInBand = GetProcAddress(hUser32, "CreateWindowInBand");
HANDLE hTwinuiPcshell = GetModuleHandle(L"twinui.pcshell.dll");
CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc = (INT64(*)(HWND, int, HWND, int, BOOL*))
((uintptr_t)hTwinuiPcshell + 0xB0E12);
InternalAddRef = (INT64(*)(void*, INT64))
((uintptr_t)hTwinuiPcshell + 0x46650);
CLauncherTipContextMenu_GetMenuItemsAsync = (INT64(*)(void*, void*, void**))
((uintptr_t)hTwinuiPcshell + 0x5051F0);
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu = (INT64(*)(HMENU, HMENU, HWND, unsigned int, void*))
((uintptr_t)hTwinuiPcshell + 0x535AF8);
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu = (void(*)(HMENU, HMENU, HWND))
((uintptr_t)hTwinuiPcshell + 0x536300);
CLauncherTipContextMenu_ExecuteShutdownCommand = (void(*)(void*, void*))
((uintptr_t)hTwinuiPcshell + 0x514714);
CLauncherTipContextMenu_ExecuteCommand = (void(*)(void*, int))
((uintptr_t)hTwinuiPcshell + 0x5143D0);
CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc = (INT64(*)(void*, POINT*))
((uintptr_t)hTwinuiPcshell + 0x506EE0);
rv = funchook_prepare(
funchook,
(void**)&CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc,
CLauncherTipContextMenu_ShowLauncherTipContextMenuHook
);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}
HANDLE hTwinui = GetModuleHandle(L"twinui.dll");
CImmersiveHotkeyNotification_GetMonitorForHotkeyNotificationFunc = (INT64(*)(void*, void**, HWND*))
((uintptr_t)hTwinui + 0x24B4A8);
IsDesktopInputContextFunc = (BOOL(*)(void*, void*))
((uintptr_t)hTwinui + 0x24A5C4);
CImmersiveHotkeyNotification_OnMessageFunc = (HRESULT(*)(void*, INT64, INT, INT64))
((uintptr_t)hTwinui + 0xB2A70);
rv = funchook_prepare(
funchook,
(void**)&CImmersiveHotkeyNotification_OnMessageFunc,
CImmersiveHotkeyNotification_OnMessageHook
);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}
rv = funchook_install(funchook, 0);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}
}
else
{
rv = funchook_uninstall(funchook, 0);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}
rv = funchook_destroy(funchook);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}
FreeLibraryAndExitThread(hModule, 0);
}
return 0;
}
BOOL WINAPI DllMain(
_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved
)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
hModule = hinstDLL;
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}