diff --git a/dll/AxHost/RdpAxHostWnd.cpp b/dll/AxHost/RdpAxHostWnd.cpp new file mode 100644 index 0000000..b35f8da --- /dev/null +++ b/dll/AxHost/RdpAxHostWnd.cpp @@ -0,0 +1,754 @@ + +#include +#include + +#include "../MsRdpEx.h" +#include "../DpiHelper.h" +#include "RdpComBase.h" +#include "RdpEventSink.h" +#include "RdpOleSite.h" + +static HWND GetParentWindowHandle() +{ + char buffer[32]; + HWND hWndParent = 0; + + if (GetEnvironmentVariableA("MSRDPEX_PARENT_WINDOW_HANDLE", buffer, sizeof(buffer)) > 0) + { + hWndParent = (HWND)_strtoui64(buffer, NULL, 0); + } + + return hWndParent; +} + +#define RdpAxHostWnd_ConnectMsgId (WM_APP+0x101) + +#define SYSCOMMAND_SMART_SIZING_ID 0xF001 +#define SYSCOMMAND_ZOOM_LEVEL_50_ID 0xF0A0 +#define SYSCOMMAND_ZOOM_LEVEL_75_ID 0xF0A1 +#define SYSCOMMAND_ZOOM_LEVEL_100_ID 0xF0A2 +#define SYSCOMMAND_ZOOM_LEVEL_125_ID 0xF0A3 +#define SYSCOMMAND_ZOOM_LEVEL_150_ID 0xF0A4 +#define SYSCOMMAND_ZOOM_LEVEL_175_ID 0xF0A5 +#define SYSCOMMAND_ZOOM_LEVEL_200_ID 0xF0A6 +#define SYSCOMMAND_ZOOM_LEVEL_250_ID 0xF0A7 +#define SYSCOMMAND_ZOOM_LEVEL_300_ID 0xF0A8 + +#define ToMenuCheckFlag(_condition) ((_condition) ? MF_CHECKED : MF_UNCHECKED) + +class CRdpAxHostWnd : public IUnknown +{ +public: + + CRdpAxHostWnd::CRdpAxHostWnd() + { + m_connected = false; + m_desktopWidth = 1024; + m_desktopHeight = 768; + + ZeroMemory(m_hostname, sizeof(m_hostname)); + ZeroMemory(m_username, sizeof(m_username)); + ZeroMemory(m_domain, sizeof(m_domain)); + ZeroMemory(m_password, sizeof(m_password)); + + m_stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + m_pOleClientSite = new CRdpOleClientSite((IUnknown*)this); + m_pOleClientSite->AddRef(); + + m_pOleInPlaceSiteEx = new CRdpOleInPlaceSiteEx((IUnknown*)this); + m_pOleInPlaceSiteEx->AddRef(); + } + + CRdpAxHostWnd::~CRdpAxHostWnd() + { + Uninit(); + + if (m_stopEvent) { + CloseHandle(m_stopEvent); + m_stopEvent = NULL; + } + } + + STDMETHODIMP CRdpAxHostWnd::Uninit() + { + HRESULT hr = S_OK; + + if (m_eventSink) + { + IConnectionPoint* pConnectionPoint = NULL; + IConnectionPointContainer* pConnectionPointContainer = NULL; + + if (m_rdpClient) + { + hr = m_rdpClient->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnectionPointContainer); + + if (SUCCEEDED(hr)) { + hr = pConnectionPointContainer->FindConnectionPoint(DIID_IMsTscAxEvents, &pConnectionPoint); + + if (SUCCEEDED(hr)) { + pConnectionPoint->Unadvise(m_dwAdviseCookie); + } + } + + SafeRelease(pConnectionPoint); + SafeRelease(pConnectionPointContainer); + } + + SafeRelease(m_eventSink); + } + + SafeRelease(m_pOleInPlaceActiveObject); + SafeRelease(m_pOleObject); + SafeRelease(m_rdpClient); + SafeRelease(m_pOleInPlaceSiteEx); + SafeRelease(m_pOleClientSite); + SafeRelease(m_pOleInPlaceObject); + + return S_OK; + } + + STDMETHODIMP CRdpAxHostWnd::QueryInterface(REFIID riid, void** ppv) + { + HRESULT hr = S_OK; + + if (!ppv) + return E_INVALIDARG; + + *ppv = NULL; + + if (riid == IID_IUnknown) { + *ppv = this; + } + else if (riid == IID_IOleClientSite) { + *ppv = (void*)m_pOleClientSite; + } + else if (riid == IID_IOleInPlaceSiteEx) { + *ppv = (void*)m_pOleInPlaceSiteEx; + } + + if (nullptr != *ppv) { + ((IUnknown*)*ppv)->AddRef(); + } + else { + hr = E_NOINTERFACE; + } + + return hr; + } + + STDMETHODIMP_(ULONG) CRdpAxHostWnd::AddRef(void) + { + return InterlockedIncrement(&m_refCount); + } + + STDMETHODIMP_(ULONG) CRdpAxHostWnd::Release(void) + { + ULONG refCount = InterlockedDecrement(&m_refCount); + + if (refCount != 0) { + return refCount; + } + + delete this; + return 0; + } + + static LRESULT CALLBACK CRdpAxHostWnd::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CRdpAxHostWnd* pRdpAxHostWnd = (CRdpAxHostWnd*) GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if (pRdpAxHostWnd) { + return pRdpAxHostWnd->WndProc(hWnd, uMsg, wParam, lParam); + } + else { + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + } + + LRESULT CALLBACK CRdpAxHostWnd::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + HWND hWndObject = NULL; + + MsRdpEx_LogPrint(DEBUG, "CRdpAxHostWnd::WndProc %s (%d)", MsRdpEx_GetWindowMessageName(uMsg), uMsg); + + switch (uMsg) + { + case WM_DESTROY: + SetEvent(m_stopEvent); + break; + + case WM_ACTIVATEAPP: + if (m_pOleInPlaceActiveObject) + { + m_pOleInPlaceActiveObject->OnFrameWindowActivate((BOOL)wParam); + } + break; + + case WM_SETFOCUS: + if (m_pOleInPlaceActiveObject) + { + m_pOleInPlaceActiveObject->GetWindow(&hWndObject); + SetFocus(hWndObject); + } + break; + + case WM_PALETTECHANGED: + case WM_QUERYNEWPALETTE: + case WM_SYSCOLORCHANGE: + if (m_pOleInPlaceActiveObject) + { + m_pOleInPlaceActiveObject->GetWindow(&hWndObject); + SendMessage(hWndObject, uMsg, wParam, lParam); + } + return 1; + break; + + case WM_SIZE: + { + RECT rect; + int width = LOWORD(lParam); + int height = HIWORD(lParam); + + rect.left = 0; + rect.top = 0; + rect.right = width; + rect.bottom = height; + + if (m_pOleInPlaceObject) + { + m_pOleInPlaceObject->SetObjectRects(&rect, &rect); + } + + if (m_pOleInPlaceActiveObject) + { + m_pOleInPlaceActiveObject->GetWindow(&hWndObject); + SendMessage(hWndObject, WM_SIZE, wParam, lParam); + } + return 0; + } + break; + + case RdpAxHostWnd_ConnectMsgId: + this->Connect(); + break; + + case WM_SYSCOMMAND: + if (wParam == SYSCOMMAND_SMART_SIZING_ID) + { + m_smartSizing = !m_smartSizing; + + if (m_smartSizing) + { + m_zoomLevel = 100; + VARIANT varZoomLevel; + VariantInit(&varZoomLevel); + varZoomLevel.vt = VT_UI4; + varZoomLevel.ulVal = m_zoomLevel; + IMsRdpExtendedSettings* pExtendedSettings = NULL; + m_rdpClient->QueryInterface(IID_IMsRdpExtendedSettings, (void**)&pExtendedSettings); + pExtendedSettings->put_Property(CComBSTR(L"ZoomLevel"), &varZoomLevel); + VariantClear(&varZoomLevel); + SafeRelease(pExtendedSettings); + } + + IMsRdpClientAdvancedSettings8* pAdvancedSettings = NULL; + HRESULT hr = m_rdpClient->get_AdvancedSettings9(&pAdvancedSettings); + pAdvancedSettings->put_SmartSizing(ToVariantBool(m_smartSizing)); + SafeRelease(pAdvancedSettings); + + this->UpdateMenu(); + } + else if ((wParam >= SYSCOMMAND_ZOOM_LEVEL_50_ID) && (wParam <= SYSCOMMAND_ZOOM_LEVEL_300_ID)) + { + m_zoomLevel = 100; + + switch (wParam) + { + case SYSCOMMAND_ZOOM_LEVEL_50_ID: + m_zoomLevel = 50; + break; + case SYSCOMMAND_ZOOM_LEVEL_75_ID: + m_zoomLevel = 75; + break; + case SYSCOMMAND_ZOOM_LEVEL_100_ID: + m_zoomLevel = 100; + break; + case SYSCOMMAND_ZOOM_LEVEL_125_ID: + m_zoomLevel = 125; + break; + case SYSCOMMAND_ZOOM_LEVEL_150_ID: + m_zoomLevel = 150; + break; + case SYSCOMMAND_ZOOM_LEVEL_175_ID: + m_zoomLevel = 175; + break; + case SYSCOMMAND_ZOOM_LEVEL_200_ID: + m_zoomLevel = 200; + break; + case SYSCOMMAND_ZOOM_LEVEL_250_ID: + m_zoomLevel = 250; + break; + case SYSCOMMAND_ZOOM_LEVEL_300_ID: + m_zoomLevel = 300; + break; + } + + m_smartSizing = false; + + this->UpdateMenu(); + + IMsRdpClientAdvancedSettings8* pAdvancedSettings = NULL; + HRESULT hr = m_rdpClient->get_AdvancedSettings9(&pAdvancedSettings); + pAdvancedSettings->put_SmartSizing(ToVariantBool(m_smartSizing)); + SafeRelease(pAdvancedSettings); + + VARIANT varZoomLevel; + VariantInit(&varZoomLevel); + varZoomLevel.vt = VT_UI4; + varZoomLevel.ulVal = m_zoomLevel; + IMsRdpExtendedSettings* pExtendedSettings = NULL; + m_rdpClient->QueryInterface(IID_IMsRdpExtendedSettings, (void**)&pExtendedSettings); + pExtendedSettings->put_Property(CComBSTR(L"ZoomLevel"), &varZoomLevel); + VariantClear(&varZoomLevel); + SafeRelease(pExtendedSettings); + } + else + { + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + break; + + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); + break; + } + + return 0; + } + + STDMETHODIMP CRdpAxHostWnd::CreateAxControl() + { + HRESULT hr; + IClassFactory* pClassFactory = NULL; + IConnectionPoint* pConnectionPoint = NULL; + IConnectionPointContainer* pConnectionPointContainer = NULL; + + hr = MsRdpEx_DllGetClassObject(CLSID_MsRdpClientNotSafeForScripting, IID_IClassFactory, (void**) &pClassFactory); + + if (FAILED(hr)) { + return hr; + } + + hr = pClassFactory->CreateInstance(NULL, IID_IMsRdpClient, (void**) &m_rdpClient); + + SafeRelease(pClassFactory); + + if (FAILED(hr)) { + return hr; + } + + hr = m_rdpClient->QueryInterface(IID_IConnectionPointContainer, (void**) &pConnectionPointContainer); + + if (FAILED(hr)) { + return hr; + } + + hr = pConnectionPointContainer->FindConnectionPoint(DIID_IMsTscAxEvents, &pConnectionPoint); + + if (FAILED(hr)) { + return hr; + } + + SafeRelease(pConnectionPointContainer); + + m_eventSink = new CRdpEventSink(m_hWndParent); + m_eventSink->AddRef(); + + hr = pConnectionPoint->Advise((IUnknown*)m_eventSink, &m_dwAdviseCookie); + + if (FAILED(hr)) { + return hr; + } + + SafeRelease(pConnectionPoint); + + hr = m_rdpClient->QueryInterface(IID_IOleObject, (void**)&m_pOleObject); + + if (FAILED(hr)) { + return hr; + } + + hr = m_rdpClient->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&m_pOleInPlaceActiveObject); + + if (FAILED(hr)) { + return hr; + } + + hr = m_rdpClient->QueryInterface(IID_IOleInPlaceObject, (void**)&m_pOleInPlaceObject); + + if (FAILED(hr)) { + return hr; + } + + hr = m_pOleObject->SetClientSite(m_pOleClientSite); + + if (FAILED(hr)) { + return hr; + } + + m_rdpClient->AddRef(); + + return S_OK; + } + + STDMETHODIMP CRdpAxHostWnd::CreateAxWindow(HWND hWndParent, HINSTANCE hInstance) + { + HRESULT hr = S_OK; + WNDCLASSEX wndClass; + LPWSTR lpClassName = L"MsRdpEx_AxHostWnd"; + LPWSTR lpWindowName = L"Remote Desktop Client Active Host"; + + ZeroMemory(&wndClass, sizeof(WNDCLASSEX)); + wndClass.cbSize = sizeof(WNDCLASSEX); + wndClass.style = 0; + wndClass.lpfnWndProc = CRdpAxHostWnd::StaticWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = hInstance; + wndClass.hIcon = NULL; + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = lpClassName; + wndClass.hIconSm = NULL; + + if (!RegisterClassEx(&wndClass)) { + DWORD lastError = GetLastError(); + if (lastError != ERROR_CLASS_ALREADY_EXISTS) { + return E_FAIL; + } + } + + DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE; + DWORD dwExStyle = 0; + + if (hWndParent) + { + dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + dwExStyle = 0; + } + + HMENU hMenu = NULL; + int windowX = 0; + int windowY = 0; + int windowWidth = m_desktopWidth; + int windowHeight = m_desktopHeight; + RECT windowRect = { windowX, windowY, windowWidth, windowHeight }; + + m_hWnd = CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, + windowX, windowY, windowWidth, windowHeight, hWndParent, hMenu, hInstance, (void*)this); + + if (!m_hWnd) { + return E_FAIL; + } + + SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this); + + m_pOleInPlaceSiteEx->SetWindow(m_hWnd); + + hr = m_pOleObject->DoVerb(OLEIVERB_PRIMARY, NULL, m_pOleClientSite, 0, m_hWnd, &windowRect); + + if (FAILED(hr)) { + return E_FAIL; + } + + this->CreateMenu(); + + ShowWindow(m_hWnd, SW_SHOWNORMAL); + + return hr; + } + + STDMETHODIMP CRdpAxHostWnd::CreateMenu() + { + HMENU hSysMenu = ::GetSystemMenu(m_hWnd, FALSE); + + // Create Zoom submenu + HMENU hZoomMenu = CreatePopupMenu(); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 50), SYSCOMMAND_ZOOM_LEVEL_50_ID, _T("50%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 75), SYSCOMMAND_ZOOM_LEVEL_75_ID, _T("75%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 100), SYSCOMMAND_ZOOM_LEVEL_100_ID, _T("100%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 125), SYSCOMMAND_ZOOM_LEVEL_125_ID, _T("125%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 150), SYSCOMMAND_ZOOM_LEVEL_150_ID, _T("150%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 175), SYSCOMMAND_ZOOM_LEVEL_175_ID, _T("175%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 200), SYSCOMMAND_ZOOM_LEVEL_200_ID, _T("200%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 250), SYSCOMMAND_ZOOM_LEVEL_250_ID, _T("250%")); + ::AppendMenu(hZoomMenu, MF_STRING | ToMenuCheckFlag(m_zoomLevel == 300), SYSCOMMAND_ZOOM_LEVEL_300_ID, _T("300%")); + + // Add Zoom submenu to the system menu + ::AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL); + ::AppendMenu(hSysMenu, MF_POPUP, (UINT_PTR)hZoomMenu, _T("Zoom")); + + ::AppendMenu(hSysMenu, MF_STRING | ToMenuCheckFlag(m_smartSizing), SYSCOMMAND_SMART_SIZING_ID, _T("Smart Sizing")); + + return S_OK; + } + + STDMETHODIMP CRdpAxHostWnd::UpdateMenu() + { + HMENU hSysMenu = ::GetSystemMenu(m_hWnd, FALSE); + + ::CheckMenuItem(hSysMenu, SYSCOMMAND_SMART_SIZING_ID, + MF_BYCOMMAND | ToMenuCheckFlag(m_smartSizing)); + + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_50_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 50) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_75_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 75) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_100_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 100) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_125_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 125) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_150_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 150) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_175_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 175) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_200_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 200) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_250_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 250) && !m_smartSizing)); + ::CheckMenuItem(hSysMenu, SYSCOMMAND_ZOOM_LEVEL_300_ID, + MF_BYCOMMAND | ToMenuCheckFlag((m_zoomLevel == 300) && !m_smartSizing)); + + return S_OK; + } + + STDMETHODIMP CRdpAxHostWnd::Connect() + { + HRESULT hr = S_OK; + + IMsRdpClientAdvancedSettings8* pAdvancedSettings = NULL; + hr = m_rdpClient->get_AdvancedSettings9(&pAdvancedSettings); + + if (FAILED(hr)) + return E_FAIL; + + pAdvancedSettings->put_EnableCredSspSupport(ToVariantBool(m_credsspSupport)); + pAdvancedSettings->put_SmartSizing(ToVariantBool(m_smartSizing)); + SafeRelease(pAdvancedSettings); + + m_rdpClient->put_ColorDepth(32); + m_rdpClient->put_DesktopWidth(m_desktopWidth); + m_rdpClient->put_DesktopHeight(m_desktopHeight); + + m_rdpClient->put_Server(CComBSTR(m_hostname)); + m_rdpClient->put_UserName(CComBSTR(m_username)); + m_rdpClient->put_Domain(CComBSTR(m_domain)); + + IMsTscNonScriptable* pMsTscNonScriptable = NULL; + hr = m_rdpClient->QueryInterface(IID_IMsTscNonScriptable, (void**)&pMsTscNonScriptable); + + if (FAILED(hr)) + return E_FAIL; + + hr = pMsTscNonScriptable->put_ClearTextPassword(CComBSTR(m_password)); + + SafeRelease(pMsTscNonScriptable); + + if (FAILED(hr)) + return E_FAIL; + + // required for rdclientax.dll + VARIANT varRequestUseNewOutputPresenter; + VariantInit(&varRequestUseNewOutputPresenter); + varRequestUseNewOutputPresenter.vt = VT_BOOL; + varRequestUseNewOutputPresenter.ulVal = VARIANT_TRUE; + IMsRdpExtendedSettings* pExtendedSettings = NULL; + m_rdpClient->QueryInterface(IID_IMsRdpExtendedSettings, (void**)&pExtendedSettings); + pExtendedSettings->put_Property(CComBSTR(L"RequestUseNewOutputPresenter"), &varRequestUseNewOutputPresenter); + VariantClear(&varRequestUseNewOutputPresenter); + SafeRelease(pExtendedSettings); + + hr = m_rdpClient->Connect(); + + return hr; + } + + STDMETHODIMP CRdpAxHostWnd::AdjustWindowSize() + { + HWND hWnd = m_hWnd; + RECT windowRect; + DWORD dwStyle = (DWORD)::GetWindowLongPtr(hWnd, GWL_STYLE); + DWORD dwStyleEx = (DWORD)::GetWindowLongPtr(hWnd, GWL_EXSTYLE); + + uint32_t dpiX = 0; + uint32_t dpiY = 0; + HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); + MsRdpEx_GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + + ::GetWindowRect(hWnd, &windowRect); + MsRdpEx_AdjustWindowRectExForDpi(&windowRect, dwStyle, FALSE, dwStyleEx, dpiX); + + int windowPosX = 0; + int windowPosY = 0; + int windowWidth = windowRect.right - windowRect.left; + int windowHeight = windowRect.bottom - windowRect.top; + + ::SetWindowPos(hWnd, NULL, windowPosX, windowPosY, windowWidth, windowHeight, SWP_FRAMECHANGED); + + return S_OK; + } + + STDMETHODIMP CRdpAxHostWnd::LoadRdpFile() + { + MsRdpEx_ArrayListIt* it = NULL; + MsRdpEx_RdpFileEntry* entry = NULL; + MsRdpEx_RdpFile* rdpFile = MsRdpEx_RdpFile_New(); + char* filename = MsRdpEx_GetRdpFilenameFromCommandLine(); + + if (!filename) + return S_FALSE; + + if (!MsRdpEx_RdpFile_Load(rdpFile, filename)) + return S_FALSE; + + it = MsRdpEx_ArrayList_It(rdpFile->entries, MSRDPEX_ITERATOR_FLAG_EXCLUSIVE); + + while (!MsRdpEx_ArrayListIt_Done(it)) + { + VARIANT value; + VariantInit(&value); + + entry = (MsRdpEx_RdpFileEntry*)MsRdpEx_ArrayListIt_Next(it); + + if (MsRdpEx_RdpFileEntry_IsMatch(entry, 's', "full address")) { + strcpy_s(m_hostname, sizeof(m_hostname) - 1, entry->value); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 'i', "desktopwidth")) { + if (MsRdpEx_RdpFileEntry_GetIntValue(entry, &value)) { + m_desktopWidth = value.intVal; + } + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 'i', "desktopheight")) { + if (MsRdpEx_RdpFileEntry_GetIntValue(entry, &value)) { + m_desktopHeight = value.intVal; + } + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 'i', "smart sizing")) { + MsRdpEx_RdpFileEntry_GetBoolValue(entry, &m_smartSizing); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 'i', "EnableCredSspSupport")) { + MsRdpEx_RdpFileEntry_GetBoolValue(entry, &m_credsspSupport); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 's', "username")) { + strcpy_s(m_username, sizeof(m_username) - 1, entry->value); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 's', "domain")) { + strcpy_s(m_domain, sizeof(m_domain) - 1, entry->value); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 's', "TargetUserName")) { + strcpy_s(m_username, sizeof(m_username) - 1, entry->value); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 's', "TargetDomain")) { + strcpy_s(m_domain, sizeof(m_domain) - 1, entry->value); + } + else if (MsRdpEx_RdpFileEntry_IsMatch(entry, 's', "ClearTextPassword")) { + strcpy_s(m_password, sizeof(m_password) - 1, entry->value); + } + } + + MsRdpEx_ArrayListIt_Finish(it); + + MsRdpEx_RdpFile_Free(rdpFile); + free(filename); + + return S_OK; + } + + HWND CRdpAxHostWnd::GetWindowHandle() { + return m_hWnd; + } + + HANDLE CRdpAxHostWnd::GetStopEvent() { + return m_stopEvent; + } + + bool m_connected = false; + char m_hostname[256]; + char m_username[256]; + char m_domain[256]; + char m_password[256]; + bool m_credsspSupport = true; + int m_desktopWidth = 1024; + int m_desktopHeight = 768; + int m_zoomLevel = 100; + bool m_smartSizing = false; + HANDLE m_stopEvent = NULL; + +private: + LONG m_refCount = 0; + HWND m_hWnd = NULL; + HWND m_hWndParent = NULL; + DWORD m_dwAdviseCookie = 0; + IMsRdpClient9* m_rdpClient = NULL; + CRdpEventSink* m_eventSink = NULL; + CRdpOleClientSite* m_pOleClientSite = NULL; + CRdpOleInPlaceSiteEx* m_pOleInPlaceSiteEx = NULL; + IOleObject* m_pOleObject = NULL; + IOleInPlaceObject* m_pOleInPlaceObject = NULL; + IOleInPlaceActiveObject* m_pOleInPlaceActiveObject = NULL; +}; + +int MsRdpEx_AxHost_WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + int nCmdShow) +{ + MSG msg; + HRESULT hr; + + MsRdpEx_Load(); + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + if (FAILED(hr)) { + return -1; + } + + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_STANDARD_CLASSES; + InitCommonControlsEx(&icex); + + HWND hParentWnd = GetParentWindowHandle(); + + CRdpAxHostWnd rdpWindow; + + rdpWindow.LoadRdpFile(); + rdpWindow.CreateAxControl(); + rdpWindow.CreateAxWindow(hParentWnd, hInstance); + + if (!hParentWnd) { + rdpWindow.AdjustWindowSize(); + } + + HWND hRdpWnd = rdpWindow.GetWindowHandle(); + PostMessage(hRdpWnd, RdpAxHostWnd_ConnectMsgId, 0, 0); + + while (GetMessage(&msg, NULL, 0, 0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (WaitForSingleObject(rdpWindow.GetStopEvent(), 0) == WAIT_OBJECT_0) + break; + } + + MsRdpEx_Unload(); + + CoUninitialize(); + + return 0; +} diff --git a/dll/AxHost/RdpAxHostWnd.h b/dll/AxHost/RdpAxHostWnd.h new file mode 100644 index 0000000..df8207a --- /dev/null +++ b/dll/AxHost/RdpAxHostWnd.h @@ -0,0 +1,12 @@ +#ifndef MSRDPEX_AX_HOST_H +#define MSRDPEX_AX_HOST_H + +#include + +int MsRdpEx_AxHost_WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + int nCmdShow); + +#endif /* MSRDPEX_AX_HOST_H */ \ No newline at end of file diff --git a/dll/AxHost/RdpComBase.h b/dll/AxHost/RdpComBase.h new file mode 100644 index 0000000..7aa78da --- /dev/null +++ b/dll/AxHost/RdpComBase.h @@ -0,0 +1,21 @@ +#ifndef MSRDPEX_COM_HELPER_H +#define MSRDPEX_COM_HELPER_H + +#include + +#include +#include +#include + +#ifndef SafeRelease +#define SafeRelease(_x) { if ((_x) != nullptr) { (_x)->Release(); (_x) = nullptr; } } +#endif + +#ifndef ToVariantBool +#define ToVariantBool(_b) ((_b) ? VARIANT_TRUE : VARIANT_FALSE) +#endif + +#include "../com/mstscax.tlh" +using namespace MSTSCLib; + +#endif /* MSRDPEX_COM_HELPER_H */ \ No newline at end of file diff --git a/dll/AxHost/RdpEventSink.cpp b/dll/AxHost/RdpEventSink.cpp new file mode 100644 index 0000000..7f60975 --- /dev/null +++ b/dll/AxHost/RdpEventSink.cpp @@ -0,0 +1,174 @@ + +#include "RdpEventSink.h" + +// IUnknown methods +STDMETHODIMP CRdpEventSink::QueryInterface(REFIID riid, void** ppv) +{ + HRESULT hr = S_OK; + + if (!ppv) + return E_INVALIDARG; + + *ppv = NULL; + + if (riid == IID_IUnknown) { + *ppv = this; + } + else if (riid == IID_IDispatch) { + *ppv = this; + } + else if (riid == DIID_IMsTscAxEvents) { + *ppv = this; + } + + if (nullptr != *ppv) { + ((IUnknown*)*ppv)->AddRef(); + } + else { + hr = E_NOINTERFACE; + } + + return hr; +} + +STDMETHODIMP_(ULONG) CRdpEventSink::AddRef(void) +{ + return InterlockedIncrement(&m_refCount); +} + +STDMETHODIMP_(ULONG) CRdpEventSink::Release(void) +{ + ULONG refCount = InterlockedDecrement(&m_refCount); + + if (refCount != 0) { + return refCount; + } + + delete this; + return 0; +} + +// IDispatch methods +STDMETHODIMP CRdpEventSink::GetTypeInfoCount(UINT* pctinfo) +{ + *pctinfo = 0; + return S_OK; +} + +STDMETHODIMP CRdpEventSink::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CRdpEventSink::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, + LCID lcid, DISPID* rgDispId) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CRdpEventSink::Invoke(DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS* pDispParams, VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, UINT* puArgErr) +{ + HRESULT hr = E_NOTIMPL; + + switch (dispIdMember) + { + case IMsTscAxEvents_OnConnectingId: + hr = OnConnecting(); + break; + + case IMsTscAxEvents_OnConnectedId: + hr = OnConnected(); + break; + + case IMsTscAxEvents_OnLoginCompleteId: + hr = OnLoginComplete(); + break; + + case IMsTscAxEvents_OnDisconnectedId: + hr = OnDisconnected(pDispParams->rgvarg->lVal); + break; + + case IMsTscAxEvents_OnEnterFullScreenModeId: + hr = OnEnterFullScreenMode(); + break; + + case IMsTscAxEvents_OnLeaveFullScreenModeId: + hr = OnLeaveFullScreenMode(); + break; + + case IMsTscAxEvents_OnRemoteDesktopSizeChangeId: + hr = OnRemoteDesktopSizeChange(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal); + break; + + case IMsTscAxEvents_OnRequestContainerMinimizeId: + hr = OnRequestContainerMinimize(); + break; + + case IMsTscAxEvents_OnConfirmCloseId: + hr = OnConfirmClose(pDispParams->rgvarg[0].pboolVal); + break; + } + + return hr; +} + +// IMsTscAxEvents methods +STDMETHODIMP CRdpEventSink::OnConnecting() +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnConnected() +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnLoginComplete() +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnDisconnected(long discReason) +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnEnterFullScreenMode() +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnLeaveFullScreenMode() +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnRemoteDesktopSizeChange(long width, long height) +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnRequestContainerMinimize() +{ + return S_OK; +} + +STDMETHODIMP CRdpEventSink::OnConfirmClose(VARIANT_BOOL* pfAllowClose) +{ + *pfAllowClose = VARIANT_TRUE; + return S_OK; +} + +CRdpEventSink::CRdpEventSink(HWND hWndParent) +{ + m_refCount = 0; + m_hWndParent = hWndParent; +} + +CRdpEventSink::~CRdpEventSink() +{ + +} diff --git a/dll/AxHost/RdpEventSink.h b/dll/AxHost/RdpEventSink.h new file mode 100644 index 0000000..b2059e7 --- /dev/null +++ b/dll/AxHost/RdpEventSink.h @@ -0,0 +1,79 @@ +#ifndef MSRDPEX_EVENT_SINK_H +#define MSRDPEX_EVENT_SINK_H + +#include + +#include "RdpComBase.h" + +#define IMsTscAxEvents_OnConnectingId 0x00000001 +#define IMsTscAxEvents_OnConnectedId 0x00000002 +#define IMsTscAxEvents_OnLoginCompleteId 0x00000003 +#define IMsTscAxEvents_OnDisconnectedId 0x00000004 +#define IMsTscAxEvents_OnEnterFullScreenModeId 0x00000005 +#define IMsTscAxEvents_OnLeaveFullScreenModeId 0x00000006 +#define IMsTscAxEvents_OnChannelReceivedDataId 0x00000007 +#define IMsTscAxEvents_OnRequestGoFullScreenId 0x00000008 +#define IMsTscAxEvents_OnRequestLeaveFullScreenId 0x00000009 +#define IMsTscAxEvents_OnFatalErrorId 0x0000000a +#define IMsTscAxEvents_OnWarningId 0x0000000b +#define IMsTscAxEvents_OnRemoteDesktopSizeChangeId 0x0000000c +#define IMsTscAxEvents_OnIdleTimeoutNotificationId 0x0000000d +#define IMsTscAxEvents_OnRequestContainerMinimizeId 0x0000000e +#define IMsTscAxEvents_OnConfirmCloseId 0x0000000f +#define IMsTscAxEvents_OnReceivedTSPublicKeyId 0x00000010 +#define IMsTscAxEvents_OnAutoReconnectingId 0x00000011 +#define IMsTscAxEvents_OnAuthenticationWarningDisplayedId 0x00000012 +#define IMsTscAxEvents_OnAuthenticationWarningDismissedId 0x00000013 +#define IMsTscAxEvents_OnRemoteProgramResultId 0x00000014 +#define IMsTscAxEvents_OnRemoteProgramDisplayedId 0x00000015 +#define IMsTscAxEvents_OnRemoteWindowDisplayedId 0x00000016 +#define IMsTscAxEvents_OnLogonErrorId 0x00000017 +#define IMsTscAxEvents_OnFocusReleasedId 0x00000018 +#define IMsTscAxEvents_OnUserNameAcquiredId 0x00000019 +#define IMsTscAxEvents_OnMouseInputModeChangedId 0x0000001a +#define IMsTscAxEvents_OnServiceMessageReceivedId 0x0000001b +#define IMsTscAxEvents_OnConnectionBarPullDownId 0x0000001c +#define IMsTscAxEvents_OnNetworkStatusChangedId 0x0000001d +#define IMsTscAxEvents_OnDevicesButtonPressedId 0x0000001e +#define IMsTscAxEvents_OnAutoReconnectedId 0x0000001f +#define IMsTscAxEvents_OnAutoReconnecting2Id 0x00000020 + +class CRdpEventSink : public IMsTscAxEvents +{ +public: + // Constructor and Destructor + CRdpEventSink(HWND hWndParent); + virtual ~CRdpEventSink(); + + // IUnknown methods + STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override; + STDMETHOD_(ULONG, AddRef)(void) override; + STDMETHOD_(ULONG, Release)(void) override; + + // IDispatch methods + STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) override; + STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override; + STDMETHOD(GetIDsOfNames)(REFIID riid, + LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override; + STDMETHOD(Invoke)(DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS* pDispParams, VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, UINT* puArgErr) override; + + // IMsTscAxEvents methods + STDMETHOD(OnConnecting)(void); + STDMETHOD(OnConnected)(void); + STDMETHOD(OnLoginComplete)(void); + STDMETHOD(OnDisconnected)(long discReason); + STDMETHOD(OnEnterFullScreenMode)(void); + STDMETHOD(OnLeaveFullScreenMode)(void); + STDMETHOD(OnRemoteDesktopSizeChange)(long width, long height); + STDMETHOD(OnRequestContainerMinimize)(void); + STDMETHOD(OnConfirmClose)(VARIANT_BOOL* pfAllowClose); + +private: + ULONG m_refCount; + HWND m_hWndParent; +}; + +#endif /* MSRDPEX_EVENT_SINK_H */ \ No newline at end of file diff --git a/dll/AxHost/RdpOleSite.cpp b/dll/AxHost/RdpOleSite.cpp new file mode 100644 index 0000000..80c155d --- /dev/null +++ b/dll/AxHost/RdpOleSite.cpp @@ -0,0 +1,248 @@ + +#include "RdpOleSite.h" + +CRdpOleClientSite::CRdpOleClientSite(IUnknown* pUnkOuter) +{ + m_refCount = 0; + m_pUnkOuter = pUnkOuter; + m_pUnkOuter->AddRef(); +} + +CRdpOleClientSite::~CRdpOleClientSite() +{ + SafeRelease(m_pUnkOuter); +} + +// IUnknown methods +STDMETHODIMP CRdpOleClientSite::QueryInterface(REFIID riid, void** ppv) +{ + HRESULT hr = S_OK; + + if (!ppv) + return E_INVALIDARG; + + *ppv = NULL; + + if (riid == IID_IUnknown) { + *ppv = static_cast(this); + } + else if (riid == IID_IOleClientSite) { + *ppv = static_cast(this); + } + else if (m_pUnkOuter) { + return m_pUnkOuter->QueryInterface(riid, ppv); + } + else { + hr = E_NOINTERFACE; + } + + if (*ppv) { + AddRef(); + } + + return hr; +} + +STDMETHODIMP_(ULONG) CRdpOleClientSite::AddRef() +{ + return InterlockedIncrement(&m_refCount); +} + +STDMETHODIMP_(ULONG) CRdpOleClientSite::Release() +{ + ULONG refCount = InterlockedDecrement(&m_refCount); + if (refCount == 0) { + delete this; + } + return refCount; +} + +// IOleClientSite methods +STDMETHODIMP CRdpOleClientSite::SaveObject() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleClientSite::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) +{ + *ppmk = NULL; + return E_NOTIMPL; +} + +STDMETHODIMP CRdpOleClientSite::GetContainer(IOleContainer** ppContainer) +{ + *ppContainer = NULL; + return E_NOTIMPL; +} + +STDMETHODIMP CRdpOleClientSite::ShowObject() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleClientSite::OnShowWindow(BOOL fShow) +{ + return S_OK; +} + +STDMETHODIMP CRdpOleClientSite::RequestNewObjectLayout() +{ + return E_NOTIMPL; +} + +CRdpOleInPlaceSiteEx::CRdpOleInPlaceSiteEx(IUnknown* pUnkOuter) + : m_refCount(0), m_hWnd(0) +{ + m_pUnkOuter = pUnkOuter; + m_pUnkOuter->AddRef(); +} + +CRdpOleInPlaceSiteEx::~CRdpOleInPlaceSiteEx() +{ + SafeRelease(m_pUnkOuter); +} + +// IUnknown methods +STDMETHODIMP CRdpOleInPlaceSiteEx::QueryInterface(REFIID riid, void** ppv) +{ + HRESULT hr = S_OK; + + if (!ppv) return E_INVALIDARG; + *ppv = NULL; + + if (riid == IID_IUnknown) { + *ppv = static_cast(this); + } + else if (riid == IID_IOleWindow || riid == IID_IOleInPlaceSite || riid == IID_IOleInPlaceSiteEx) { + *ppv = static_cast(this); + } + else if (m_pUnkOuter) { + return m_pUnkOuter->QueryInterface(riid, ppv); + } + else { + hr = E_NOINTERFACE; + } + + if (*ppv) { + AddRef(); + } + + return hr; +} + +STDMETHODIMP_(ULONG) CRdpOleInPlaceSiteEx::AddRef() +{ + return InterlockedIncrement(&m_refCount); +} + +STDMETHODIMP_(ULONG) CRdpOleInPlaceSiteEx::Release() +{ + ULONG refCount = InterlockedDecrement(&m_refCount); + if (refCount == 0) { + delete this; + } + return refCount; +} + +// IOleWindow methods +STDMETHODIMP CRdpOleInPlaceSiteEx::GetWindow(HWND* phwnd) +{ + *phwnd = m_hWnd; + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::ContextSensitiveHelp(BOOL fEnterMode) +{ + return S_OK; +} + +// IOleInPlaceSite methods +STDMETHODIMP CRdpOleInPlaceSiteEx::CanInPlaceActivate() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::OnInPlaceActivate() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::OnUIActivate() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, + LPRECT lprcPosRect, LPRECT lprcClipRect, + LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + RECT rect; + + *ppFrame = NULL; + *ppDoc = NULL; + lpFrameInfo = NULL; + + if (GetClientRect(m_hWnd, &rect)) + { + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + SetRect(lprcClipRect, 0, 0, width, height); + SetRect(lprcPosRect, 0, 0, width, height); + } + + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::Scroll(SIZE scrollExtant) +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::OnUIDeactivate(BOOL fUndoable) +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::OnInPlaceDeactivate() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::DiscardUndoState() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::DeactivateAndUndo() +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::OnPosRectChange(LPCRECT lprcPosRect) +{ + return S_OK; +} + +// IOleInPlaceSiteEx methods +STDMETHODIMP CRdpOleInPlaceSiteEx::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags) +{ + *pfNoRedraw = TRUE; + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::OnInPlaceDeactivateEx(BOOL fNoRedraw) +{ + return S_OK; +} + +STDMETHODIMP CRdpOleInPlaceSiteEx::RequestUIActivate() +{ + return S_OK; +} + +// additional methods +STDMETHODIMP CRdpOleInPlaceSiteEx::SetWindow(HWND hWnd) +{ + m_hWnd = hWnd; + return S_OK; +} diff --git a/dll/AxHost/RdpOleSite.h b/dll/AxHost/RdpOleSite.h new file mode 100644 index 0000000..4de02e8 --- /dev/null +++ b/dll/AxHost/RdpOleSite.h @@ -0,0 +1,76 @@ +#ifndef MSRDPEX_OLE_SITE_H +#define MSRDPEX_OLE_SITE_H + +#include + +#include "RdpComBase.h" + +class CRdpOleClientSite : public IOleClientSite { +public: + // Constructor and Destructor + CRdpOleClientSite(IUnknown* pUnkOuter); + virtual ~CRdpOleClientSite(); + + // IUnknown methods + STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override; + STDMETHOD_(ULONG, AddRef)() override; + STDMETHOD_(ULONG, Release)() override; + + // IOleClientSite methods + STDMETHOD(SaveObject)() override; + STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override; + STDMETHOD(GetContainer)(IOleContainer** ppContainer) override; + STDMETHOD(ShowObject)() override; + STDMETHOD(OnShowWindow)(BOOL fShow) override; + STDMETHOD(RequestNewObjectLayout)() override; + +private: + ULONG m_refCount; + IUnknown* m_pUnkOuter; +}; + +class CRdpOleInPlaceSiteEx : public IOleInPlaceSiteEx { +public: + // Constructor and Destructor + CRdpOleInPlaceSiteEx(IUnknown* pUnkOuter); + virtual ~CRdpOleInPlaceSiteEx(); + + // IUnknown methods + STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override; + STDMETHOD_(ULONG, AddRef)() override; + STDMETHOD_(ULONG, Release)() override; + + // IOleWindow methods + STDMETHOD(GetWindow)(HWND* phwnd) override; + STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override; + + // IOleInPlaceSite methods + STDMETHOD(CanInPlaceActivate)() override; + STDMETHOD(OnInPlaceActivate)() override; + STDMETHOD(OnUIActivate)() override; + STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, + IOleInPlaceUIWindow** ppDoc, + LPRECT lprcPosRect, LPRECT lprcClipRect, + LPOLEINPLACEFRAMEINFO lpFrameInfo) override; + STDMETHOD(Scroll)(SIZE scrollExtant) override; + STDMETHOD(OnUIDeactivate)(BOOL fUndoable) override; + STDMETHOD(OnInPlaceDeactivate)() override; + STDMETHOD(DiscardUndoState)() override; + STDMETHOD(DeactivateAndUndo)() override; + STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect) override; + + // IOleInPlaceSiteEx methods + STDMETHOD(OnInPlaceActivateEx)(BOOL* pfNoRedraw, DWORD dwFlags) override; + STDMETHOD(OnInPlaceDeactivateEx)(BOOL fNoRedraw) override; + STDMETHOD(RequestUIActivate)() override; + + // Additional methods specific to your implementation + STDMETHOD(SetWindow)(HWND hWnd); + +private: + ULONG m_refCount; + HWND m_hWnd; + IUnknown* m_pUnkOuter; +}; + +#endif /* MSRDPEX_OLE_SITE_H */ \ No newline at end of file diff --git a/dll/AxHost/RdpWinMain.cpp b/dll/AxHost/RdpWinMain.cpp new file mode 100644 index 0000000..f58b569 --- /dev/null +++ b/dll/AxHost/RdpWinMain.cpp @@ -0,0 +1,53 @@ +#include +#include + +#include "RdpAxHostWnd.h" +#include "RdpWinMain.h" + +static LPWSTR ProcessAxHostCommandLine(LPWSTR lpCmdLine, bool* axHost) +{ + *axHost = false; + LPCWSTR cmdArg = L"/axhost"; + WCHAR* cmdLine = _wcsdup(lpCmdLine); + WCHAR* found = wcsstr(cmdLine, cmdArg); + + if (found != NULL) { + *axHost = true; + memmove(found, found + wcslen(cmdArg), + (wcslen(found + wcslen(cmdArg)) + 1) * sizeof(WCHAR)); + } + + return cmdLine; +} + +int WINAPI MsRdpEx_WinMain( + _In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nShowCmd, + const char* axName) +{ + HRESULT hr; + int exitCode = 0; + bool axHost = false; + + LPWSTR cmdLine = ProcessAxHostCommandLine(lpCmdLine, &axHost); + + if (axHost) + { + MsRdpEx_SetEnv("MSRDPEX_AXNAME", axName); + exitCode = MsRdpEx_AxHost_WinMain(hInstance, hPrevInstance, cmdLine, nShowCmd); + } + else + { + hr = MsRdpEx_LaunchProcess(-1, NULL, NULL, axName); + + if (FAILED(hr)) { + exitCode = -1; + } + } + + free(cmdLine); + + return exitCode; +} diff --git a/dll/AxHost/RdpWinMain.h b/dll/AxHost/RdpWinMain.h new file mode 100644 index 0000000..07596c1 --- /dev/null +++ b/dll/AxHost/RdpWinMain.h @@ -0,0 +1,13 @@ +#ifndef MSRDPEX_WIN_MAIN_H +#define MSRDPEX_WIN_MAIN_H + +#include + +int MsRdpEx_WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + int nCmdShow, + const char* axName); + +#endif /* MSRDPEX_WIN_MAIN_H */ diff --git a/dll/CMakeLists.txt b/dll/CMakeLists.txt index 1da2e98..d8aa8eb 100644 --- a/dll/CMakeLists.txt +++ b/dll/CMakeLists.txt @@ -38,6 +38,8 @@ set(MSRDPEX_SOURCES HashTable.c Environment.c NameResolver.c + DpiHelper.cpp + DpiHelper.h Sspi.cpp Stream.cpp Detours.cpp @@ -62,13 +64,28 @@ set(MSRDPEX_SOURCES TSObjects.cpp TSObjects.h MsRdpEx.cpp - MsRdpEx.h) + MsRdpEx.h + AxDll.cpp) + +set(MSRDPEX_AXHOST_SOURCE_DIR "${CMAKE_SOURCE_DIR}/dll/AxHost") +include_directories(${AXHOST_SOURCE_DIR}) + +set(MSRDPEX_AXHOST_SOURCES + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpAxHostWnd.cpp" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpAxHostWnd.h" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpEventSink.cpp" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpEventSink.h" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpOleSite.cpp" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpOleSite.h" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpComBase.h" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpWinMain.cpp" + "${MSRDPEX_AXHOST_SOURCE_DIR}/RdpWinMain.h") add_library(MsRdpEx_Dll SHARED ${MSRDPEX_SOURCES} ${MSRDPEX_HEADERS} ${MSRDPEX_RESOURCES} - AxDll.cpp + ${MSRDPEX_AXHOST_SOURCES} MsRdpEx.def) set(MSRDPEX_LIBS @@ -80,7 +97,8 @@ set(MSRDPEX_LIBS ws2_32.lib secur32.lib credui.lib - advapi32.lib) + advapi32.lib + comctl32.lib) target_link_libraries(MsRdpEx_Dll ${MSRDPEX_LIBS}) diff --git a/dll/DpiHelper.cpp b/dll/DpiHelper.cpp new file mode 100644 index 0000000..461c708 --- /dev/null +++ b/dll/DpiHelper.cpp @@ -0,0 +1,251 @@ + +#include "DpiHelper.h" + +#include + +/** + * High DPI Reference: + * https://msdn.microsoft.com/en-us/library/windows/desktop/hh447398/ + * + * Display Scaling in Windows 10: + * https://blogs.technet.microsoft.com/askcore/2015/12/08/display-scaling-in-windows-10/ + * + * Display Scaling changes for the Windows 10 Anniversary Update: + * https://blogs.technet.microsoft.com/askcore/2016/08/16/display-scaling-changes-for-the-windows-10-anniversary-update/ + */ + +static int g_RefCount = 0; +static DpiHelper* g_Dpi = NULL; + +float DpiHelper_GetScaleFactor(int dpi) +{ + return MulDiv(100, dpi, USER_DEFAULT_SCREEN_DPI) / (float) 100; +} + +int DpiHelper_ScaleValue(int value, int dpi) +{ + return MulDiv(value, dpi, USER_DEFAULT_SCREEN_DPI); +} + +DpiHelper* DpiHelper_New() +{ + DpiHelper* ctx; + + ctx = (DpiHelper*) calloc(1, sizeof(DpiHelper)); + + if (!ctx) + return NULL; + + ctx->hShCore = LoadLibraryA("shcore.dll"); + ctx->hUser32 = LoadLibraryA("user32.dll"); + + if (ctx->hShCore) + { + ctx->GetScaleFactorForDevice = (fnGetScaleFactorForDevice) + GetProcAddress(ctx->hShCore, "GetScaleFactorForDevice"); + + ctx->RegisterScaleChangeNotifications = (fnRegisterScaleChangeNotifications) + GetProcAddress(ctx->hShCore, "RegisterScaleChangeNotifications"); + + ctx->RevokeScaleChangeNotifications = (fnRevokeScaleChangeNotifications) + GetProcAddress(ctx->hShCore, "RevokeScaleChangeNotifications"); + + ctx->GetScaleFactorForMonitor = (fnGetScaleFactorForMonitor) + GetProcAddress(ctx->hShCore, "GetScaleFactorForMonitor"); + + ctx->RegisterScaleChangeEvent = (fnRegisterScaleChangeEvent) + GetProcAddress(ctx->hShCore, "RegisterScaleChangeEvent"); + + ctx->UnregisterScaleChangeEvent = (fnUnregisterScaleChangeEvent) + GetProcAddress(ctx->hShCore, "UnregisterScaleChangeEvent"); + + ctx->SetProcessDpiAwareness = (fnSetProcessDpiAwareness) + GetProcAddress(ctx->hShCore, "SetProcessDpiAwareness"); + + ctx->GetProcessDpiAwareness = (fnGetProcessDpiAwareness) + GetProcAddress(ctx->hShCore, "GetProcessDpiAwareness"); + + ctx->GetDpiForMonitor = (fnGetDpiForMonitor) + GetProcAddress(ctx->hShCore, "GetDpiForMonitor"); + + ctx->GetDpiForShellUIComponent = (fnGetDpiForShellUIComponent) + GetProcAddress(ctx->hShCore, "GetDpiForShellUIComponent"); + + ctx->AdjustWindowRectExForDpi = (fnAdjustWindowRectExForDpi) + GetProcAddress(ctx->hUser32, "AdjustWindowRectExForDpi"); + + ctx->EnableNonClientDpiScaling = (fnEnableNonClientDpiScaling) + GetProcAddress(ctx->hUser32, "EnableNonClientDpiScaling"); + } + + return ctx; +} + +void DpiHelper_Free(DpiHelper* ctx) +{ + if (!ctx) + return; + + if (ctx->hShCore) + { + FreeLibrary(ctx->hShCore); + ctx->hShCore = NULL; + } + + if (ctx->hUser32) + { + FreeLibrary(ctx->hUser32); + ctx->hUser32 = NULL; + } + + free(ctx); +} + +DpiHelper* DpiHelper_Get() +{ + if (!g_Dpi) + g_Dpi = DpiHelper_New(); + + g_RefCount++; + + return g_Dpi; +} + +void DpiHelper_Release() +{ + g_RefCount--; + + if (g_RefCount < 0) + g_RefCount = 0; + + if (g_Dpi && (g_RefCount < 1)) + { + DpiHelper_Free(g_Dpi); + g_Dpi = NULL; + } +} + +DEVICE_SCALE_FACTOR MsRdpEx_GetScaleFactorForDevice(DISPLAY_DEVICE_TYPE deviceType) +{ + if (g_Dpi && g_Dpi->GetScaleFactorForDevice) + return g_Dpi->GetScaleFactorForDevice(deviceType); + + return SCALE_100_PERCENT; +} + +HRESULT MsRdpEx_RegisterScaleChangeNotifications(DISPLAY_DEVICE_TYPE displayDevice, HWND hwndNotify, uint32_t uMsgNotify, + DWORD* pdwCookie) +{ + if (g_Dpi && g_Dpi->RegisterScaleChangeNotifications) + return g_Dpi->RegisterScaleChangeNotifications(displayDevice, hwndNotify, uMsgNotify, pdwCookie); + + return S_FALSE; +} + +HRESULT MsRdpEx_RevokeScaleChangeNotifications(DISPLAY_DEVICE_TYPE displayDevice, DWORD dwCookie) +{ + if (g_Dpi && g_Dpi->RevokeScaleChangeNotifications) + return g_Dpi->RevokeScaleChangeNotifications(displayDevice, dwCookie); + + return S_FALSE; +} + +HRESULT MsRdpEx_GetScaleFactorForMonitor(HMONITOR hMonitor, DEVICE_SCALE_FACTOR* pScale) +{ + if (g_Dpi && g_Dpi->GetScaleFactorForMonitor) + return g_Dpi->GetScaleFactorForMonitor(hMonitor, pScale); + + return S_FALSE; +} + +HRESULT MsRdpEx_RegisterScaleChangeEvent(HANDLE hEvent, DWORD_PTR* pdwCookie) +{ + if (g_Dpi && g_Dpi->RegisterScaleChangeEvent) + return g_Dpi->RegisterScaleChangeEvent(hEvent, pdwCookie); + + return S_FALSE; +} + +HRESULT MsRdpEx_UnregisterScaleChangeEvent(DWORD_PTR dwCookie) +{ + if (g_Dpi && g_Dpi->UnregisterScaleChangeEvent) + return g_Dpi->UnregisterScaleChangeEvent(dwCookie); + + return S_FALSE; +} + +HRESULT MsRdpEx_SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value) +{ + if (g_Dpi && g_Dpi->SetProcessDpiAwareness) + return g_Dpi->SetProcessDpiAwareness(value); + + return S_FALSE; +} + +HRESULT MsRdpEx_GetProcessDpiAwareness(HANDLE hProcess, PROCESS_DPI_AWARENESS* value) +{ + if (g_Dpi && g_Dpi->GetProcessDpiAwareness) + return g_Dpi->GetProcessDpiAwareness(hProcess, value); + + return S_FALSE; +} + +HRESULT MsRdpEx_GetDpiForMonitor(HMONITOR hMonitor, MONITOR_DPI_TYPE dpiType, uint32_t* dpiX, uint32_t* dpiY) +{ + HDC hDC; + int logPixelsX = 96; + int logPixelsY = 96; + + if (g_Dpi && g_Dpi->GetDpiForMonitor) + { + return g_Dpi->GetDpiForMonitor(hMonitor, dpiType, dpiX, dpiY); + } + else + { + hDC = GetDC(NULL); + + if (hDC) + { + logPixelsX = GetDeviceCaps(hDC, LOGPIXELSX); + logPixelsY = GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(NULL, hDC); + } + + *dpiX = logPixelsX; + *dpiY = logPixelsY; + + return S_OK; + } + + return S_FALSE; +} + +uint32_t MsRdpEx_GetDpiForShellUIComponent(SHELL_UI_COMPONENT component) +{ + if (g_Dpi && g_Dpi->GetDpiForShellUIComponent) + return g_Dpi->GetDpiForShellUIComponent(component); + + return 0; +} + +BOOL MsRdpEx_AdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi) +{ + if (g_Dpi && g_Dpi->AdjustWindowRectExForDpi) + { + return g_Dpi->AdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); + } + else + { + return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); + } + + return FALSE; +} + +BOOL MsRdpEx_EnableNonClientDpiScaling(HWND hwnd) +{ + if (g_Dpi && g_Dpi->EnableNonClientDpiScaling) + return g_Dpi->EnableNonClientDpiScaling(hwnd); + + return FALSE; +} diff --git a/dll/DpiHelper.h b/dll/DpiHelper.h new file mode 100644 index 0000000..21b969f --- /dev/null +++ b/dll/DpiHelper.h @@ -0,0 +1,126 @@ +#ifndef MSRDPEX_DPI_HELPER_H +#define MSRDPEX_DPI_HELPER_H + +#include + +#include + +#ifndef SCALING_ENUMS_DECLARED + +typedef enum +{ + DEVICE_PRIMARY = 0, + DEVICE_IMMERSIVE = 1, +} DISPLAY_DEVICE_TYPE; + +typedef enum +{ + SCF_VALUE_NONE = 0x00, + SCF_SCALE = 0x01, + SCF_PHYSICAL = 0x02, +} SCALE_CHANGE_FLAGS; + +DEFINE_ENUM_FLAG_OPERATORS(SCALE_CHANGE_FLAGS); + +#define SCALING_ENUMS_DECLARED +#endif + +#ifndef DPI_ENUMS_DECLARED + +typedef enum PROCESS_DPI_AWARENESS +{ + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +typedef enum MONITOR_DPI_TYPE +{ + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; + +#define DPI_ENUMS_DECLARED +#endif + +#ifndef SHELL_UI_COMPONENT_ENUMS_DECLARED + +typedef enum +{ + SHELL_UI_COMPONENT_TASKBARS = 0, + SHELL_UI_COMPONENT_NOTIFICATIONAREA = 1, + SHELL_UI_COMPONENT_DESKBAND = 2, +} SHELL_UI_COMPONENT; + +#define SHELL_UI_COMPONENT_ENUMS_DECLARED +#endif + +#define WM_DPICHANGED 0x02E0 +#define WM_GETDPISCALEDSIZE 0x02E4 + +typedef DEVICE_SCALE_FACTOR(WINAPI * fnGetScaleFactorForDevice)(DISPLAY_DEVICE_TYPE deviceType); +typedef HRESULT(WINAPI * fnRegisterScaleChangeNotifications)(DISPLAY_DEVICE_TYPE displayDevice, HWND hwndNotify, + uint32_t uMsgNotify, DWORD* pdwCookie); +typedef HRESULT(WINAPI * fnRevokeScaleChangeNotifications)(DISPLAY_DEVICE_TYPE displayDevice, DWORD dwCookie); +typedef HRESULT(WINAPI * fnGetScaleFactorForMonitor)(HMONITOR hMonitor, DEVICE_SCALE_FACTOR* pScale); +typedef HRESULT(WINAPI * fnRegisterScaleChangeEvent)(HANDLE hEvent, DWORD_PTR* pdwCookie); +typedef HRESULT(WINAPI * fnUnregisterScaleChangeEvent)(DWORD_PTR dwCookie); +typedef HRESULT(WINAPI * fnSetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value); +typedef HRESULT(WINAPI * fnGetProcessDpiAwareness)(HANDLE hProcess, PROCESS_DPI_AWARENESS* value); +typedef HRESULT(WINAPI * fnGetDpiForMonitor)(HMONITOR hMonitor, MONITOR_DPI_TYPE dpiType, uint32_t* dpiX, + uint32_t* dpiY); +typedef uint32_t(WINAPI * fnGetDpiForShellUIComponent)(SHELL_UI_COMPONENT component); +typedef BOOL(WINAPI * fnAdjustWindowRectExForDpi)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, + UINT dpi); +typedef BOOL(WINAPI * fnEnableNonClientDpiScaling)(HWND hwnd); + +struct dpi_helper +{ + HMODULE hShCore; + HMODULE hUser32; + fnGetScaleFactorForDevice GetScaleFactorForDevice; + fnRegisterScaleChangeNotifications RegisterScaleChangeNotifications; + fnRevokeScaleChangeNotifications RevokeScaleChangeNotifications; + fnGetScaleFactorForMonitor GetScaleFactorForMonitor; + fnRegisterScaleChangeEvent RegisterScaleChangeEvent; + fnUnregisterScaleChangeEvent UnregisterScaleChangeEvent; + fnSetProcessDpiAwareness SetProcessDpiAwareness; + fnGetProcessDpiAwareness GetProcessDpiAwareness; + fnGetDpiForMonitor GetDpiForMonitor; + fnGetDpiForShellUIComponent GetDpiForShellUIComponent; + fnAdjustWindowRectExForDpi AdjustWindowRectExForDpi; + fnEnableNonClientDpiScaling EnableNonClientDpiScaling; +}; +typedef struct dpi_helper DpiHelper; + +#ifdef __cplusplus +extern "C" { +#endif + +DpiHelper* DpiHelper_Get(); +void DpiHelper_Release(); + +float DpiHelper_GetScaleFactor(int dpi); +int DpiHelper_ScaleValue(int value, int dpi); + +DEVICE_SCALE_FACTOR MsRdpEx_GetScaleFactorForDevice(DISPLAY_DEVICE_TYPE deviceType); +HRESULT MsRdpEx_RegisterScaleChangeNotifications(DISPLAY_DEVICE_TYPE displayDevice, HWND hwndNotify, uint32_t uMsgNotify, + DWORD* pdwCookie); +HRESULT MsRdpEx_RevokeScaleChangeNotifications(DISPLAY_DEVICE_TYPE displayDevice, DWORD dwCookie); +HRESULT MsRdpEx_GetScaleFactorForMonitor(HMONITOR hMonitor, DEVICE_SCALE_FACTOR* pScale); +HRESULT MsRdpEx_RegisterScaleChangeEvent(HANDLE hEvent, DWORD_PTR* pdwCookie); +HRESULT MsRdpEx_UnregisterScaleChangeEvent(DWORD_PTR dwCookie); +HRESULT MsRdpEx_SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value); +HRESULT MsRdpEx_GetProcessDpiAwareness(HANDLE hProcess, PROCESS_DPI_AWARENESS* value); +HRESULT MsRdpEx_GetDpiForMonitor(HMONITOR hMonitor, MONITOR_DPI_TYPE dpiType, uint32_t* dpiX, uint32_t* dpiY); +uint32_t MsRdpEx_GetDpiForShellUIComponent(SHELL_UI_COMPONENT component); +BOOL MsRdpEx_AdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi); +BOOL MsRdpEx_EnableNonClientDpiScaling(HWND hwnd); + +#ifdef __cplusplus +} +#endif + +#endif /* MSRDPEX_DPI_HELPER_H */ diff --git a/dll/MsRdpEx.cpp b/dll/MsRdpEx.cpp index 71bcc83..3f517f2 100644 --- a/dll/MsRdpEx.cpp +++ b/dll/MsRdpEx.cpp @@ -74,6 +74,11 @@ HRESULT STDAPICALLTYPE DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* p return hr; } +HRESULT STDAPICALLTYPE MsRdpEx_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ + return DllGetClassObject(rclsid, riid, ppv); +} + HRESULT DllRegisterServer() { MsRdpEx_LogPrint(DEBUG, "DllRegisterServer"); diff --git a/dll/MsRdpEx.def b/dll/MsRdpEx.def index 7257e31..6d5690f 100644 --- a/dll/MsRdpEx.def +++ b/dll/MsRdpEx.def @@ -24,4 +24,5 @@ EXPORTS MsRdpEx_LaunchProcess MsRdpExProcess_CreateInstance MsRdpEx_GetArgumentVector - MsRdpEx_FreeArgumentVector \ No newline at end of file + MsRdpEx_FreeArgumentVector + MsRdpEx_WinMain \ No newline at end of file diff --git a/exe/msrdcex/msrdcex.cpp b/exe/msrdcex/msrdcex.cpp index f2cb82e..9da8f60 100644 --- a/exe/msrdcex/msrdcex.cpp +++ b/exe/msrdcex/msrdcex.cpp @@ -1,51 +1,5 @@ -#include -LRESULT CALLBACK WrapperMsgWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case 0x401: // WM_QUIT - PostQuitMessage(uMsg); - break; - - case 0x402: // Connect button - PostQuitMessage(uMsg); - break; - - case WM_DESTROY: - PostQuitMessage(0); - return 0; - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -HWND CreateWrapperMsgWindow(HINSTANCE hInstance) -{ - WNDCLASS wc = { 0 }; - wc.lpfnWndProc = WrapperMsgWindowProc; - wc.hInstance = hInstance; - wc.lpszClassName = L"MsRdpEx_WrapperMsgWindow"; - - if (!RegisterClass(&wc)) { - return NULL; - } - - HWND hWndMsg = CreateWindowEx(0, - L"MsRdpEx_WrapperMsgWindow", - L"MsRdpEx_WrapperMsgWindow", - 0, 0, 0, 0, 0, HWND_MESSAGE, - NULL, hInstance, NULL); - - return hWndMsg; -} - -BOOL MsRdpEx_SetMsgWindowHandle(HWND hWndMsg) -{ - char buffer[32]; - _ui64toa((unsigned long long)hWndMsg, buffer, 10); - return SetEnvironmentVariableA("MSRDPEX_HWNDMSG", buffer) > 0; -} +#include "../dll/AxHost/RdpWinMain.h" int WINAPI wWinMain( _In_ HINSTANCE hInstance, @@ -53,68 +7,5 @@ int WINAPI wWinMain( _In_ LPWSTR lpCmdLine, _In_ int nShowCmd) { - HRESULT hr; - char mstsc_args[2048]; - char msrdc_args[2048]; - IMsRdpExProcess* mstsc = NULL; - IMsRdpExProcess* msrdc = NULL; - - if (__argc >= 2) - { - // we launched msrdc with command-line arguments - hr = MsRdpEx_LaunchProcess(-1, NULL, NULL, "msrdc"); - return 0; - } - - MsRdpEx_InitPaths(MSRDPEX_ALL_PATHS); - - HWND hWndMsg = CreateWrapperMsgWindow(hInstance); - - MsRdpEx_SetMsgWindowHandle(hWndMsg); - - const char* mstsc_exe = MsRdpEx_GetPath(MSRDPEX_MSTSC_EXE_PATH); - const char* msrdc_exe = MsRdpEx_GetPath(MSRDPEX_MSRDC_EXE_PATH); - const char* default_rdp = MsRdpEx_GetPath(MSRDPEX_DEFAULT_RDP_PATH); - - hr = MsRdpExProcess_CreateInstance((LPVOID*)&mstsc); - - sprintf_s(mstsc_args, sizeof(mstsc_args) - 1, "\"%s\"", - mstsc_exe); - - mstsc->AddRef(); - mstsc->SetFileName(mstsc_exe); - mstsc->SetArguments(mstsc_args); - hr = mstsc->StartWithInfo(); - - MSG msg = { 0 }; - - while (GetMessage(&msg, hWndMsg, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - int exitCode = (int)msg.wParam; - - mstsc->Stop(0); - mstsc->Release(); - mstsc = NULL; - - if (exitCode == 0x402) - { - hr = MsRdpExProcess_CreateInstance((LPVOID*)&msrdc); - - sprintf_s(msrdc_args, sizeof(msrdc_args) - 1, "\"%s\" \"%s\"", - msrdc_exe, default_rdp); - - msrdc->AddRef(); - msrdc->SetFileName(msrdc_exe); - msrdc->SetArguments(msrdc_args); - msrdc->StartWithInfo(); - msrdc->Wait(INFINITE); - msrdc->Release(); - msrdc = NULL; - } - - return 0; + return MsRdpEx_WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd, "msrdc"); } diff --git a/exe/mstscex/mstscex.cpp b/exe/mstscex/mstscex.cpp index 1a09964..ee91747 100644 --- a/exe/mstscex/mstscex.cpp +++ b/exe/mstscex/mstscex.cpp @@ -1,4 +1,5 @@ -#include + +#include "../dll/AxHost/RdpWinMain.h" int WINAPI wWinMain( _In_ HINSTANCE hInstance, @@ -6,9 +7,5 @@ int WINAPI wWinMain( _In_ LPWSTR lpCmdLine, _In_ int nShowCmd) { - HRESULT hr; - - hr = MsRdpEx_LaunchProcess(-1, NULL, NULL, "mstsc"); - - return 0; + return MsRdpEx_WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd, "mstsc"); } diff --git a/include/MsRdpEx/MsRdpEx.h b/include/MsRdpEx/MsRdpEx.h index b756820..05664da 100644 --- a/include/MsRdpEx/MsRdpEx.h +++ b/include/MsRdpEx/MsRdpEx.h @@ -172,6 +172,8 @@ void MsRdpEx_SetPcapFilePath(const char* pcapFilePath); void MsRdpEx_Load(); void MsRdpEx_Unload(); +HRESULT STDAPICALLTYPE MsRdpEx_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv); + #ifdef __cplusplus } #endif