Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ExplorerPatcher/ExplorerPatcher.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@
<ClCompile Include="StartMenu.c">
<ExcludedFromBuild Condition="'$(WithMainPatcher)'!='true'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="StartMenuMonitorState.c">
<ExcludedFromBuild Condition="'$(WithMainPatcher)'!='true'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="StartMenuSettings.cpp">
<ExcludedFromBuild Condition="'$(WithMainPatcher)'!='true'">true</ExcludedFromBuild>
</ClCompile>
Expand Down Expand Up @@ -302,6 +305,7 @@
<ClInclude Include="SettingsMonitor.h" />
<ClInclude Include="StartExperience.h" />
<ClInclude Include="StartMenu.h" />
<ClInclude Include="StartMenuMonitorState.h" />
<ClInclude Include="StartupSound.h" />
<ClInclude Include="symbols.h" />
<ClInclude Include="TaskbarCenter.h" />
Expand Down
22 changes: 18 additions & 4 deletions ExplorerPatcher/StartMenu.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#include "StartMenu.h"
#include "StartMenuMonitorState.h"

void OpenStartOnMonitor(HMONITOR monitor)
{
START_MENU_MONITOR_REQUEST_ID monitorRequestId = BeginStartMenuTargetMonitorRequest();

HRESULT hr = S_OK;
IUnknown* pImmersiveShell = NULL;
hr = CoCreateInstance(
Expand Down Expand Up @@ -38,16 +41,27 @@ void OpenStartOnMonitor(HMONITOR monitor)
if (pLauncher)
{
BOOL bIsVisible = FALSE;
pLauncher->lpVtbl->IsVisible(pLauncher, &bIsVisible);
hr = pLauncher->lpVtbl->IsVisible(pLauncher, &bIsVisible);
if (SUCCEEDED(hr))
{
if (!bIsVisible)
{
if (pMonitor)
if (PublishStartMenuTargetMonitorRequest(monitorRequestId, monitor))
{
pLauncher->lpVtbl->ConnectToMonitor(pLauncher, pMonitor);
if (pMonitor)
{
pLauncher->lpVtbl->ConnectToMonitor(pLauncher, pMonitor);
}
hr = pLauncher->lpVtbl->ShowStartView(pLauncher, 11, 0);
if (FAILED(hr))
{
CancelStartMenuTargetMonitorRequest(monitorRequestId);
}
else
{
ConfirmStartMenuTargetMonitorRequest(monitorRequestId);
}
}
pLauncher->lpVtbl->ShowStartView(pLauncher, 11, 0);
}
else
{
Expand Down
167 changes: 167 additions & 0 deletions ExplorerPatcher/StartMenuMonitorState.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#include "StartMenuMonitorState.h"

static SRWLOCK g_startMenuTargetMonitorLock = SRWLOCK_INIT;
static START_MENU_MONITOR_REQUEST_ID g_nextStartMenuTargetMonitorRequestId = 0;
static START_MENU_MONITOR_REQUEST_ID g_latestStartedStartMenuTargetMonitorRequestId = 0;
static START_MENU_MONITOR_REQUEST_ID g_pendingStartMenuTargetMonitorRequestId = 0;
static HMONITOR g_pendingStartMenuTargetMonitor = NULL;
static BOOL g_pendingStartMenuTargetMonitorConfirmed = FALSE;
static START_MENU_MONITOR_REQUEST_ID g_activeStartMenuTargetMonitorLifecycleId = 0;
static HMONITOR g_activeStartMenuTargetMonitor = NULL;

static START_MENU_MONITOR_REQUEST_ID AllocateStartMenuTargetMonitorRequestId(void)
{
do
{
++g_nextStartMenuTargetMonitorRequestId;
} while (!g_nextStartMenuTargetMonitorRequestId);
return g_nextStartMenuTargetMonitorRequestId;
}

START_MENU_MONITOR_REQUEST_ID BeginStartMenuTargetMonitorRequest(void)
{
AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
START_MENU_MONITOR_REQUEST_ID requestId = AllocateStartMenuTargetMonitorRequestId();
g_latestStartedStartMenuTargetMonitorRequestId = requestId;
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
return requestId;
}

BOOL PublishStartMenuTargetMonitorRequest(START_MENU_MONITOR_REQUEST_ID requestId, HMONITOR monitor)
{
BOOL published = FALSE;
AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
if (requestId && requestId == g_latestStartedStartMenuTargetMonitorRequestId)
{
g_pendingStartMenuTargetMonitorRequestId = requestId;
g_pendingStartMenuTargetMonitor = monitor;
g_pendingStartMenuTargetMonitorConfirmed = FALSE;
published = TRUE;
}
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
return published;
}

BOOL ConfirmStartMenuTargetMonitorRequest(START_MENU_MONITOR_REQUEST_ID requestId)
{
BOOL confirmed = FALSE;
AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
if (requestId && requestId == g_activeStartMenuTargetMonitorLifecycleId)
{
confirmed = TRUE;
}
else if (requestId && requestId == g_pendingStartMenuTargetMonitorRequestId)
{
g_pendingStartMenuTargetMonitorConfirmed = TRUE;
if (!g_activeStartMenuTargetMonitorLifecycleId)
{
g_activeStartMenuTargetMonitorLifecycleId = g_pendingStartMenuTargetMonitorRequestId;
g_activeStartMenuTargetMonitor = g_pendingStartMenuTargetMonitor;
g_pendingStartMenuTargetMonitorRequestId = 0;
g_pendingStartMenuTargetMonitor = NULL;
g_pendingStartMenuTargetMonitorConfirmed = FALSE;
}
confirmed = TRUE;
}
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
return confirmed;
}

BOOL CancelStartMenuTargetMonitorRequest(START_MENU_MONITOR_REQUEST_ID requestId)
{
BOOL cancelled = FALSE;
AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
if (requestId && requestId == g_pendingStartMenuTargetMonitorRequestId)
{
g_pendingStartMenuTargetMonitorRequestId = 0;
g_pendingStartMenuTargetMonitor = NULL;
g_pendingStartMenuTargetMonitorConfirmed = FALSE;
cancelled = TRUE;
}
if (requestId && requestId == g_activeStartMenuTargetMonitorLifecycleId)
{
g_activeStartMenuTargetMonitorLifecycleId = 0;
g_activeStartMenuTargetMonitor = NULL;
cancelled = TRUE;
}
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
return cancelled;
}

START_MENU_MONITOR_REQUEST_ID AcquireStartMenuTargetMonitor(HMONITOR defaultMonitor, HMONITOR* monitor)
{
AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
if (!g_activeStartMenuTargetMonitorLifecycleId)
{
if (g_pendingStartMenuTargetMonitorRequestId)
{
g_activeStartMenuTargetMonitorLifecycleId = g_pendingStartMenuTargetMonitorRequestId;
g_activeStartMenuTargetMonitor = g_pendingStartMenuTargetMonitor
? g_pendingStartMenuTargetMonitor
: defaultMonitor;
g_pendingStartMenuTargetMonitorRequestId = 0;
g_pendingStartMenuTargetMonitor = NULL;
g_pendingStartMenuTargetMonitorConfirmed = FALSE;
}
else
{
g_activeStartMenuTargetMonitorLifecycleId = AllocateStartMenuTargetMonitorRequestId();
g_activeStartMenuTargetMonitor = defaultMonitor;
}
}
START_MENU_MONITOR_REQUEST_ID lifecycleId = g_activeStartMenuTargetMonitorLifecycleId;
if (!g_activeStartMenuTargetMonitor)
{
g_activeStartMenuTargetMonitor = defaultMonitor;
}
*monitor = g_activeStartMenuTargetMonitor;
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
return lifecycleId;
}

BOOL UpdateStartMenuTargetMonitor(START_MENU_MONITOR_REQUEST_ID lifecycleId, HMONITOR monitor)
{
BOOL updated = FALSE;
AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
if (lifecycleId && lifecycleId == g_activeStartMenuTargetMonitorLifecycleId)
{
g_activeStartMenuTargetMonitor = monitor;
updated = TRUE;
}
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
return updated;
}

START_MENU_MONITOR_REQUEST_ID GetStartMenuTargetMonitorLifecycleId(void)
{
AcquireSRWLockShared(&g_startMenuTargetMonitorLock);
START_MENU_MONITOR_REQUEST_ID lifecycleId = g_activeStartMenuTargetMonitorLifecycleId;
if (!lifecycleId && g_pendingStartMenuTargetMonitorConfirmed)
{
lifecycleId = g_pendingStartMenuTargetMonitorRequestId;
}
ReleaseSRWLockShared(&g_startMenuTargetMonitorLock);
return lifecycleId;
}

void CompleteStartMenuTargetMonitorLifecycle(START_MENU_MONITOR_REQUEST_ID lifecycleId)
{
if (!lifecycleId)
{
return;
}

AcquireSRWLockExclusive(&g_startMenuTargetMonitorLock);
if (lifecycleId == g_activeStartMenuTargetMonitorLifecycleId)
{
g_activeStartMenuTargetMonitorLifecycleId = 0;
g_activeStartMenuTargetMonitor = NULL;
}
if (lifecycleId == g_pendingStartMenuTargetMonitorRequestId)
{
g_pendingStartMenuTargetMonitorRequestId = 0;
g_pendingStartMenuTargetMonitor = NULL;
g_pendingStartMenuTargetMonitorConfirmed = FALSE;
}
ReleaseSRWLockExclusive(&g_startMenuTargetMonitorLock);
}
25 changes: 25 additions & 0 deletions ExplorerPatcher/StartMenuMonitorState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef _H_STARTMENUMONITORSTATE_H_
#define _H_STARTMENUMONITORSTATE_H_

#include <Windows.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef ULONGLONG START_MENU_MONITOR_REQUEST_ID;

START_MENU_MONITOR_REQUEST_ID BeginStartMenuTargetMonitorRequest(void);
BOOL PublishStartMenuTargetMonitorRequest(START_MENU_MONITOR_REQUEST_ID requestId, HMONITOR monitor);
BOOL ConfirmStartMenuTargetMonitorRequest(START_MENU_MONITOR_REQUEST_ID requestId);
BOOL CancelStartMenuTargetMonitorRequest(START_MENU_MONITOR_REQUEST_ID requestId);
START_MENU_MONITOR_REQUEST_ID AcquireStartMenuTargetMonitor(HMONITOR defaultMonitor, HMONITOR* monitor);
BOOL UpdateStartMenuTargetMonitor(START_MENU_MONITOR_REQUEST_ID lifecycleId, HMONITOR monitor);
START_MENU_MONITOR_REQUEST_ID GetStartMenuTargetMonitorLifecycleId(void);
void CompleteStartMenuTargetMonitorLifecycle(START_MENU_MONITOR_REQUEST_ID lifecycleId);

#ifdef __cplusplus
}
#endif

#endif
Loading