Skip to content

Commit

Permalink
initial system menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc-André Moreau authored and awakecoding committed Aug 6, 2024
1 parent e0c61c7 commit e460508
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 2 deletions.
88 changes: 86 additions & 2 deletions dll/ApiHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,38 @@ BOOL Hook_StretchBlt(
return status;
}

#define SYSMENU_RDP_RANGE_FIRST_ID 7100
#define SYSMENU_RDP_SEND_CTRL_ALT_DEL_ID 7101
#define SYSMENU_RDP_SEND_CTRL_ALT_END_ID 7102
#define SYSMENU_RDP_RANGE_LAST_ID 7103

static WNDPROC Real_TscShellContainerWndProc = NULL;

LRESULT CALLBACK Hook_TscShellContainerWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT result;

CMsRdpExInstance* instance = MsRdpEx_InstanceManager_FindByTscShellContainerWnd(hWnd);

result = Real_TscShellContainerWndProc(hWnd, uMsg, wParam, lParam);

if (instance)
{
HWND hInputCaptureWnd = 0;

((IMsRdpExInstance*)instance)->GetInputWindow(&hInputCaptureWnd);

if ((uMsg == WM_SYSCOMMAND) && hInputCaptureWnd)
{
if ((wParam >= SYSMENU_RDP_RANGE_FIRST_ID) && (wParam <= SYSMENU_RDP_RANGE_LAST_ID)) {
SendMessage(hInputCaptureWnd, uMsg, wParam, lParam);
}
}
}

return result;
}

static WNDPROC Real_OPWndProc_mstscax = NULL;
static WNDPROC Real_OPWndProc_rdclientax = NULL;

Expand Down Expand Up @@ -582,7 +614,12 @@ ATOM Hook_RegisterClassExW(WNDCLASSEXW* wndClass)

MsRdpEx_LogPrint(DEBUG, "RegisterClassExW: %s", lpClassNameA);

if (MsRdpEx_StringEquals(lpClassNameA, "OPWindowClass")) {
if (MsRdpEx_StringEquals(lpClassNameA, "TscShellContainerClass")) {
Real_TscShellContainerWndProc = wndClass->lpfnWndProc;
wndClass->lpszClassName = L"TscShellContainerClass";
wndClass->lpfnWndProc = Hook_TscShellContainerWndProc;
}
else if (MsRdpEx_StringEquals(lpClassNameA, "OPWindowClass")) {
if (MsRdpEx_IsAddressInRdclientAxModule(_ReturnAddress())) {
Real_OPWndProc_rdclientax = wndClass->lpfnWndProc;
wndClass->lpszClassName = L"OPWindowClass_rdclientax";
Expand Down Expand Up @@ -614,7 +651,7 @@ LRESULT CALLBACK Hook_IHWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
IMsRdpExInstance* instance = NULL;
CMsRdpExtendedSettings* pExtendedSettings = NULL;

//MsRdpEx_LogPrint(DEBUG, "IHWndProc: %s (%d)", MsRdpEx_GetWindowMessageName(uMsg), uMsg);
MsRdpEx_LogPrint(DEBUG, "IHWndProc: %s (%d)", MsRdpEx_GetWindowMessageName(uMsg), uMsg);

if (uMsg == WM_NCCREATE)
{
Expand Down Expand Up @@ -670,13 +707,60 @@ LRESULT CALLBACK Hook_IHWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
}

SetTimer(hWnd, timerEventId, mouseJigglerInterval * 1000, NULL);

if (pExtendedSettings->GetExtraSystemMenuEnabled())
{
char className[256];
HWND hParentWnd = GetAncestor(hWnd, GA_ROOT);
GetClassNameA(hParentWnd, className, sizeof(className) - 1);

if (MsRdpEx_StringEquals(className, "TscShellContainerClass"))
{
MsRdpEx_LogPrint(DEBUG, "Ancestor: %s hWnd: %p", className, hParentWnd);

HMENU hSystemMenu = GetSystemMenu(hParentWnd, FALSE);
HMENU hExtraMenu = CreateMenu();
AppendMenu(hExtraMenu, MF_STRING, SYSMENU_RDP_SEND_CTRL_ALT_DEL_ID, L"Send Ctrl+Alt+Del");
AppendMenu(hExtraMenu, MF_STRING, SYSMENU_RDP_SEND_CTRL_ALT_END_ID, L"Send Ctrl+Alt+End");

AppendMenu(hSystemMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSystemMenu, MF_POPUP, (UINT_PTR)hExtraMenu, L"Extra");

instance->AttachTscShellContainerWindow(hParentWnd);
}
}
}
}
else
{
MsRdpEx_LogPrint(DEBUG, "Failed to attach input window! hWnd: %p pUserData: %p", hWnd, pUserData);
}
}
else if (uMsg == WM_SYSCOMMAND)
{
switch (wParam)
{
case SYSMENU_RDP_SEND_CTRL_ALT_DEL_ID:
MsRdpEx_LogPrint(DEBUG, "Send Ctrl+Alt+Del");
SendMessage(hWnd, WM_KEYDOWN, (WPARAM)VK_CONTROL, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYDOWN, (WPARAM)VK_MENU, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYDOWN, (WPARAM)VK_DELETE, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYUP, (WPARAM)VK_DELETE, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYUP, (WPARAM)VK_MENU, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYUP, (WPARAM)VK_CONTROL, (LPARAM)0x0);
break;

case SYSMENU_RDP_SEND_CTRL_ALT_END_ID:
MsRdpEx_LogPrint(DEBUG, "Send Ctrl+Alt+End");
SendMessage(hWnd, WM_KEYDOWN, (WPARAM)VK_CONTROL, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYDOWN, (WPARAM)VK_MENU, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYDOWN, (WPARAM)VK_END, (LPARAM)0x01000000);
SendMessage(hWnd, WM_KEYUP, (WPARAM)VK_END, (LPARAM)0x01000000);
SendMessage(hWnd, WM_KEYUP, (WPARAM)VK_MENU, (LPARAM)0x0);
SendMessage(hWnd, WM_KEYUP, (WPARAM)VK_CONTROL, (LPARAM)0x0);
break;
}
}
else if (uMsg == WM_TIMER)
{
if (wParam == MOUSE_JIGGLER_MOVE_MOUSE_TIMER_ID)
Expand Down
1 change: 1 addition & 0 deletions dll/MsRdpClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ class CMsRdpClient : public IMsRdpClient10
m_pMsRdpExtendedSettings->LoadRdpFileFromNamedPipe(NULL);
m_pMsRdpExtendedSettings->PrepareSspiSessionIdHack();
m_pMsRdpExtendedSettings->PrepareMouseJiggler();
m_pMsRdpExtendedSettings->PrepareExtraSystemMenu();

hr = m_pMsTscAx->raw_Connect();

Expand Down
53 changes: 53 additions & 0 deletions dll/RdpInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,36 @@ class CMsRdpExInstance : public IMsRdpExInstance
return S_OK;
}

HRESULT STDMETHODCALLTYPE GetInputWindow(HWND* phInputCaptureWnd)
{
*phInputCaptureWnd = m_hInputCaptureWnd;
return S_OK;
}

HRESULT STDMETHODCALLTYPE AttachOutputWindow(HWND hOutputWnd, void* pUserData)
{
m_hOutputPresenterWnd = hOutputWnd;
return S_OK;
}

HRESULT STDMETHODCALLTYPE GetOutputWindow(HWND* phOutputPresenterWnd)
{
*phOutputPresenterWnd = m_hOutputPresenterWnd;
return S_OK;
}

HRESULT STDMETHODCALLTYPE AttachTscShellContainerWindow(HWND hTscShellContainerWnd)
{
m_hTscShellContainerWnd = hTscShellContainerWnd;
return S_OK;
}

HRESULT STDMETHODCALLTYPE GetTscShellContainerWindow(HWND* phTscShellContainerWnd)
{
*phTscShellContainerWnd = m_hTscShellContainerWnd;
return S_OK;
}

HRESULT STDMETHODCALLTYPE AttachExtendedSettings(CMsRdpExtendedSettings* pExtendedSettings)
{
m_pMsRdpExtendedSettings = pExtendedSettings;
Expand Down Expand Up @@ -264,6 +288,7 @@ class CMsRdpExInstance : public IMsRdpExInstance
CMsRdpClient* m_pMsRdpClient = NULL;
HWND m_hInputCaptureWnd = NULL;
HWND m_hOutputPresenterWnd = NULL;
HWND m_hTscShellContainerWnd = NULL;
MsRdpEx_OutputMirror* m_OutputMirror = NULL;
ITSPropertySet* m_pCorePropsRaw = NULL;
CMsRdpExtendedSettings* m_pMsRdpExtendedSettings = NULL;
Expand Down Expand Up @@ -509,6 +534,34 @@ CMsRdpExInstance* MsRdpEx_InstanceManager_AttachInputWindow(HWND hInputWnd, void
return found ? obj : NULL;
}

CMsRdpExInstance* MsRdpEx_InstanceManager_FindByTscShellContainerWnd(HWND hWnd)
{
MsRdpEx_InstanceManager* ctx = g_InstanceManager;

if (!ctx)
return NULL;

bool found = false;
CMsRdpExInstance* obj = NULL;
MsRdpEx_ArrayListIt* it = NULL;

it = MsRdpEx_ArrayList_It(ctx->instances, MSRDPEX_ITERATOR_FLAG_EXCLUSIVE);

while (!MsRdpEx_ArrayListIt_Done(it))
{
obj = (CMsRdpExInstance*)MsRdpEx_ArrayListIt_Next(it);

found = (obj->m_hTscShellContainerWnd == hWnd) ? true : false;

if (found)
break;
}

MsRdpEx_ArrayListIt_Finish(it);

return found ? obj : NULL;
}

CMsRdpExInstance* MsRdpEx_InstanceManager_FindBySessionId(GUID* sessionId)
{
MsRdpEx_InstanceManager* ctx = g_InstanceManager;
Expand Down
27 changes: 27 additions & 0 deletions dll/RdpSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,28 @@ HRESULT CMsRdpExtendedSettings::PrepareMouseJiggler()
return hr;
}

HRESULT CMsRdpExtendedSettings::PrepareExtraSystemMenu()
{
HRESULT hr = S_OK;
VARIANT allowBackgroundInput;
bstr_t allowBackgroundInputName = _com_util::ConvertStringToBSTR("AllowBackgroundInput");

if (!m_BaseProps) {
MsRdpEx_LogPrint(ERROR, "PrepareExtraSystemMenu - m_BaseProps is NULL!");
return E_UNEXPECTED;
}

VariantInit(&allowBackgroundInput);
hr = this->get_BaseProperty(allowBackgroundInputName, &allowBackgroundInput);

if (m_ExtraSystemMenuEnabled) {
allowBackgroundInput.boolVal = VARIANT_TRUE;
m_BaseProps->put_Property(allowBackgroundInputName, &allowBackgroundInput);
}

return hr;
}

char* CMsRdpExtendedSettings::GetKdcProxyUrl()
{
if (m_KdcProxyUrl)
Expand Down Expand Up @@ -1064,6 +1086,11 @@ uint32_t CMsRdpExtendedSettings::GetMouseJigglerMethod()
return m_MouseJigglerMethod;
}

bool CMsRdpExtendedSettings::GetExtraSystemMenuEnabled()
{
return m_ExtraSystemMenuEnabled;
}

CMsRdpExtendedSettings* CMsRdpExtendedSettings_New(IUnknown* pUnknown, IUnknown* pMsTscAx, GUID* pSessionId)
{
CMsRdpExtendedSettings* settings = new CMsRdpExtendedSettings(pUnknown, pSessionId);
Expand Down
8 changes: 8 additions & 0 deletions dotnet/Devolutions.MsRdpEx/Bindings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,16 @@ public interface IMsRdpExInstance

void AttachInputWindow(IntPtr hInputWnd, IntPtr pUserData);

void GetInputWindow(out IntPtr phInputWnd);

void AttachOutputWindow(IntPtr hOutputWnd, IntPtr pUserData);

void GetOutputWindow(out IntPtr phOutputWnd);

void AttachTscShellContainerWindow(IntPtr hTscShellContainerWnd);

void GetTscShellContainerWindow(out IntPtr phTscShellContainerWnd);

void AttachExtendedSettings(IntPtr pExtendedSettings);

[MethodImpl(MethodImplOptions.PreserveSig)]
Expand Down
6 changes: 6 additions & 0 deletions include/MsRdpEx/RdpInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ struct __declspec(novtable)
virtual HRESULT __stdcall GetCorePropsRawPtr(LPVOID* ppCorePropsRaw) = 0;
virtual HRESULT __stdcall SetCorePropsRawPtr(LPVOID pCorePropsRaw) = 0;
virtual HRESULT __stdcall AttachInputWindow(HWND hOutputWnd, void* pUserData) = 0;
virtual HRESULT __stdcall GetInputWindow(HWND* phInputCaptureWnd) = 0;
virtual HRESULT __stdcall AttachOutputWindow(HWND hOutputWnd, void* pUserData) = 0;
virtual HRESULT __stdcall GetOutputWindow(HWND* phOutputPresenterWnd) = 0;
virtual HRESULT __stdcall AttachTscShellContainerWindow(HWND hTscShellContainerWnd) = 0;
virtual HRESULT __stdcall GetTscShellContainerWindow(HWND* phTscShellContainerWnd) = 0;
virtual HRESULT __stdcall AttachExtendedSettings(CMsRdpExtendedSettings* pExtendedSettings) = 0;
virtual bool __stdcall GetExtendedSettings(CMsRdpExtendedSettings** ppExtendedSettings) = 0;
virtual bool __stdcall GetShadowBitmap(HDC* phDC, HBITMAP* phBitmap, uint8_t** pBitmapData,
Expand Down Expand Up @@ -57,6 +61,8 @@ CMsRdpExInstance* MsRdpEx_InstanceManager_FindByInputCaptureHwnd(HWND hWnd);

CMsRdpExInstance* MsRdpEx_InstanceManager_AttachInputWindow(HWND hInputWnd, void* pUserData);

CMsRdpExInstance* MsRdpEx_InstanceManager_FindByTscShellContainerWnd(HWND hWnd);

CMsRdpExInstance* MsRdpEx_InstanceManager_FindBySessionId(GUID* sessionId);

CMsRdpExtendedSettings* MsRdpEx_FindExtendedSettingsBySessionId(GUID* sessionId);
Expand Down
3 changes: 3 additions & 0 deletions include/MsRdpEx/RdpSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ class CMsRdpExtendedSettings : public IMsRdpExtendedSettings
HRESULT __stdcall GetCorePropsRawPtr(LPVOID* ppCorePropsRaw);
HRESULT __stdcall PrepareSspiSessionIdHack();
HRESULT __stdcall PrepareMouseJiggler();
HRESULT __stdcall PrepareExtraSystemMenu();
char* __stdcall GetKdcProxyUrl();
char* __stdcall GetKdcProxyName();
bool GetMouseJigglerEnabled();
uint32_t GetMouseJigglerInterval();
uint32_t GetMouseJigglerMethod();
bool GetExtraSystemMenuEnabled();

private:
GUID m_sessionId;
Expand All @@ -68,6 +70,7 @@ class CMsRdpExtendedSettings : public IMsRdpExtendedSettings
bool m_MouseJigglerEnabled = false;
uint32_t m_MouseJigglerInterval = 60;
uint32_t m_MouseJigglerMethod = 0;
bool m_ExtraSystemMenuEnabled = true;
IUnknown* m_pWTSPlugin = NULL;
};

Expand Down

0 comments on commit e460508

Please sign in to comment.