Current implementation for handling the Win+X combination works fine but it is hacky. There exists a proper implementation but, unfortunately, it does not work, because the returned pMenu pointer differs on each call and is never what it should be. I don't understand why it happens. Open Shell seems to be able to get the pointer just fine running hooked in Explorer as well.
#include <initguid.h>
#include <Windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
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;
};
DEFINE_GUID(IID_ILauncherTipContextMenu,
0xb8c1db5f,
0xcbb3, 0x48bc, 0xaf, 0xd9,
0xce, 0x6b, 0x88, 0x0c, 0x79, 0xed
);
typedef interface ILauncherTipContextMenu ILauncherTipContextMenu;
typedef struct ILauncherTipContextMenuVtbl
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
ILauncherTipContextMenu* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
ULONG(STDMETHODCALLTYPE* AddRef)(
ILauncherTipContextMenu* This);
ULONG(STDMETHODCALLTYPE* Release)(
ILauncherTipContextMenu* This);
HRESULT(STDMETHODCALLTYPE* ShowLauncherTipContextMenu)(
ILauncherTipContextMenu* This,
/* [in] */ POINT* pt);
END_INTERFACE
} ILauncherTipContextMenuVtbl;
interface ILauncherTipContextMenu
{
CONST_VTBL struct ILauncherTipContextMenuVtbl* lpVtbl;
};
int some_method()
{
HRESULT hr = S_OK;
hr = CoInitialize(NULL);
IUnknown* pImmersiveShell = NULL;
hr = CoCreateInstance(
&CLSID_ImmersiveShell,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IServiceProvider,
&pImmersiveShell
);
if (SUCCEEDED(hr))
{
printf("b\n");
IImmersiveMonitorService* pMonitorService = NULL;
IUnknown_QueryService(
pImmersiveShell,
&SID_IImmersiveMonitorService,
&IID_IImmersiveMonitorService,
&pMonitorService
);
if (pMonitorService)
{
printf("c\n");
DWORD pts = GetMessagePos();
POINT pt;
pt.x = GET_X_LPARAM(pts);
pt.y = GET_Y_LPARAM(pts);
HMONITOR monitor = MonitorFromPoint(
pt,
MONITOR_DEFAULTTONULL
);
if (monitor)
{
printf("d\n");
IUnknown* pMonitor = NULL;
pMonitorService->lpVtbl->GetFromHandle(
pMonitorService,
monitor,
&pMonitor
);
if (pMonitor)
{
printf("e\n");
ILauncherTipContextMenu* pMenu = NULL;
IUnknown_QueryService(
pMonitor,
&IID_ILauncherTipContextMenu,
&IID_ILauncherTipContextMenu,
&pMenu
);
if (pMenu)
{
printf("f %p\n", pMenu);
pMenu->lpVtbl->ShowLauncherTipContextMenu(
pMenu,
0
);
pMenu->lpVtbl->Release(pMenu);
}
pMonitor->lpVtbl->Release(pMonitor);
}
}
pMonitorService->lpVtbl->Release(pMonitorService);
}
pImmersiveShell->lpVtbl->Release(pImmersiveShell);
}
return 0;
}
Current implementation for handling the Win+X combination works fine but it is hacky. There exists a proper implementation but, unfortunately, it does not work, because the returned
pMenupointer differs on each call and is never what it should be. I don't understand why it happens. Open Shell seems to be able to get the pointer just fine running hooked in Explorer as well.