From 86a68f0c0f5888a34f0e0edb7c50a37631be7f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 13 Aug 2014 17:48:57 -0400 Subject: [PATCH] shadow: start Windows Desktop Sharing API support --- include/freerdp/assistance.h | 3 + libfreerdp/common/assistance.c | 2 +- server/shadow/Win/win_dxgi.h | 2 +- server/shadow/Win/win_shadow.c | 8 +- server/shadow/Win/win_shadow.h | 11 ++ server/shadow/Win/win_wds.c | 273 +++++++++++++++++++++++++++++++++ server/shadow/Win/win_wds.h | 13 +- 7 files changed, 307 insertions(+), 5 deletions(-) diff --git a/include/freerdp/assistance.h b/include/freerdp/assistance.h index 20b183b3b..050f93363 100644 --- a/include/freerdp/assistance.h +++ b/include/freerdp/assistance.h @@ -59,6 +59,9 @@ extern "C" { FREERDP_API BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size); FREERDP_API char* freerdp_assistance_bin_to_hex_string(const BYTE* data, int size); +FREERDP_API int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file); +FREERDP_API int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file); + FREERDP_API char* freerdp_assistance_generate_pass_stub(DWORD flags); FREERDP_API char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass); FREERDP_API BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize); diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index 5b27afe89..e0e8ae914 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -388,7 +388,7 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) passStub = (char*) malloc(15); if (!passStub) - return -1; + return NULL; /** * PassStub generation: diff --git a/server/shadow/Win/win_dxgi.h b/server/shadow/Win/win_dxgi.h index 42c42bfbb..1dcdf7ac8 100644 --- a/server/shadow/Win/win_dxgi.h +++ b/server/shadow/Win/win_dxgi.h @@ -20,7 +20,7 @@ #define FREERDP_SHADOW_SERVER_WIN_DXGI_H #if _WIN32_WINNT >= 0x0602 -#define WITH_DXGI_1_2 1 +//#define WITH_DXGI_1_2 1 #endif #ifdef WITH_DXGI_1_2 diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index 14db194cc..77adf2a88 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -357,7 +357,9 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem) DeleteDC(hdc); -#ifdef WITH_DXGI_1_2 +#if defined(WITH_WDS_API) + status = win_shadow_wds_init(subsystem); +#elif defined(WITH_DXGI_1_2) status = win_shadow_dxgi_init(subsystem); #endif @@ -389,7 +391,9 @@ int win_shadow_subsystem_uninit(winShadowSubsystem* subsystem) if (!subsystem) return -1; -#ifdef WITH_DXGI_1_2 +#if defined(WITH_WDS_API) + win_shadow_wds_uninit(subsystem); +#elif defined(WITH_DXGI_1_2) win_shadow_dxgi_uninit(subsystem); #endif diff --git a/server/shadow/Win/win_shadow.h b/server/shadow/Win/win_shadow.h index e31444fbc..d224acd40 100644 --- a/server/shadow/Win/win_shadow.h +++ b/server/shadow/Win/win_shadow.h @@ -19,6 +19,8 @@ #ifndef FREERDP_SHADOW_SERVER_WIN_H #define FREERDP_SHADOW_SERVER_WIN_H +#include + #include typedef struct win_shadow_subsystem winShadowSubsystem; @@ -29,6 +31,7 @@ typedef struct win_shadow_subsystem winShadowSubsystem; #include #include +#include "win_wds.h" #include "win_dxgi.h" struct win_shadow_subsystem @@ -39,6 +42,14 @@ struct win_shadow_subsystem int width; int height; +#ifdef WITH_WDS_API + rdpAssistanceFile* pAssistanceFile; + _IRDPSessionEvents* pSessionEvents; + IRDPSRAPISharingSession* pSharingSession; + IRDPSRAPIInvitation* pInvitation; + IRDPSRAPIInvitationManager* pInvitationMgr; +#endif + #ifdef WITH_DXGI_1_2 UINT pendingFrames; BYTE* MetadataBuffer; diff --git a/server/shadow/Win/win_wds.c b/server/shadow/Win/win_wds.c index e35e68c3d..90615c0aa 100644 --- a/server/shadow/Win/win_wds.c +++ b/server/shadow/Win/win_wds.c @@ -25,3 +25,276 @@ #include "win_wds.h" +#undef DEFINE_GUID +#define INITGUID + +#include + +DEFINE_GUID(CLSID_RDPSession,0x9B78F0E6,0x3E05,0x4A5B,0xB2,0xE8,0xE7,0x43,0xA8,0x95,0x6B,0x65); +DEFINE_GUID(DIID__IRDPSessionEvents,0x98a97042,0x6698,0x40e9,0x8e,0xfd,0xb3,0x20,0x09,0x90,0x00,0x4b); +DEFINE_GUID(IID_IRDPSRAPISharingSession,0xeeb20886,0xe470,0x4cf6,0x84,0x2b,0x27,0x39,0xc0,0xec,0x5c,0xfb); + +static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_QueryInterface( + __RPC__in _IRDPSessionEvents * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject) +{ + GUID* pGuid = (GUID*) riid; + + printf("Shadow_IRDPSessionEvents_QueryInterface\n"); + + printf("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", + pGuid->Data1, pGuid->Data2, pGuid->Data3, + pGuid->Data4[0], pGuid->Data4[1], + pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], + pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); + + if (!IsEqualIID(riid, &DIID__IRDPSessionEvents)) + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + *ppvObject = This; + This->lpVtbl->AddRef(This); + + return S_OK; +} + +static ULONG STDMETHODCALLTYPE Shadow_IRDPSessionEvents_AddRef( + __RPC__in _IRDPSessionEvents * This) +{ + printf("Shadow_IRDPSessionEvents_AddRef\n"); + return 1; +} + +static ULONG STDMETHODCALLTYPE Shadow_IRDPSessionEvents_Release( + __RPC__in _IRDPSessionEvents * This) +{ + printf("Shadow_IRDPSessionEvents_Release\n"); + return 0; +} + +static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_GetTypeInfoCount( + __RPC__in _IRDPSessionEvents * This, + /* [out] */ __RPC__out UINT *pctinfo) +{ + printf("Shadow_IRDPSessionEvents_GetTypeInfoCount\n"); + *pctinfo = 1; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_GetTypeInfo( + __RPC__in _IRDPSessionEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo) +{ + printf("Shadow_IRDPSessionEvents_GetTypeInfo\n"); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_GetIDsOfNames( + __RPC__in _IRDPSessionEvents * This, + /* [in] */ __RPC__in REFIID riid, + /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames, + /* [range][in] */ __RPC__in_range(0,16384) UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId) +{ + printf("Shadow_IRDPSessionEvents_GetIDsOfNames\n"); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_Invoke( + _IRDPSessionEvents * This, + /* [annotation][in] */ + _In_ DISPID dispIdMember, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][in] */ + _In_ LCID lcid, + /* [annotation][in] */ + _In_ WORD wFlags, + /* [annotation][out][in] */ + _In_ DISPPARAMS *pDispParams, + /* [annotation][out] */ + _Out_opt_ VARIANT *pVarResult, + /* [annotation][out] */ + _Out_opt_ EXCEPINFO *pExcepInfo, + /* [annotation][out] */ + _Out_opt_ UINT *puArgErr) +{ + printf("Shadow_IRDPSessionEvents_Invoke\n"); + return S_OK; +} + +static _IRDPSessionEventsVtbl Shadow_IRDPSessionEventsVtbl = +{ + /* IUnknown */ + Shadow_IRDPSessionEvents_QueryInterface, + Shadow_IRDPSessionEvents_AddRef, + Shadow_IRDPSessionEvents_Release, + + /* IDispatch */ + Shadow_IRDPSessionEvents_GetTypeInfoCount, + Shadow_IRDPSessionEvents_GetTypeInfo, + Shadow_IRDPSessionEvents_GetIDsOfNames, + Shadow_IRDPSessionEvents_Invoke +}; + +static _IRDPSessionEvents Shadow_IRDPSessionEvents = +{ + &Shadow_IRDPSessionEventsVtbl +}; + +int win_shadow_wds_init(winShadowSubsystem* subsystem) +{ + int status; + HRESULT hr; + DWORD dwCookie; + IUnknown* pUnknown; + BSTR bstrAuthString; + BSTR bstrGroupName; + BSTR bstrPassword; + BSTR bstrConnectionString; + IConnectionPoint* pCP; + IConnectionPointContainer* pCPC; + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + if (FAILED(hr)) + { + fprintf(stderr, "CoInitialize() failure\n"); + return -1; + } + + hr = CoCreateInstance(&CLSID_RDPSession, NULL, CLSCTX_ALL, + &IID_IRDPSRAPISharingSession, (void**) &(subsystem->pSharingSession)); + + if (FAILED(hr)) + { + fprintf(stderr, "CoCreateInstance(IRDPSRAPISharingSession) failure: 0x%08X\n", hr); + return -1; + } + + pUnknown = (IUnknown*) subsystem->pSharingSession; + hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IConnectionPointContainer, (void**) &pCPC); + + if (FAILED(hr)) + { + fprintf(stderr, "QueryInterface(IID_IConnectionPointContainer) failure: 0x%08X\n", hr); + return -1; + } + + pCPC->lpVtbl->FindConnectionPoint(pCPC, &DIID__IRDPSessionEvents, &pCP); + + if (FAILED(hr)) + { + fprintf(stderr, "IConnectionPointContainer::FindConnectionPoint(_IRDPSessionEvents) failure: 0x%08X\n", hr); + return -1; + } + + hr = pCP->lpVtbl->Advise(pCP, (IUnknown*) &Shadow_IRDPSessionEvents, &dwCookie); + + if (FAILED(hr)) + { + fprintf(stderr, "IConnectionPoint::Advise(Shadow_IRDPSessionEvents) failure: 0x%08X\n", hr); + return -1; + } + + hr = subsystem->pSharingSession->lpVtbl->Open(subsystem->pSharingSession); + + if (FAILED(hr)) + { + fprintf(stderr, "IRDPSRAPISharingSession::Open() failure: 0x%08X\n", hr); + return -1; + } + + hr = subsystem->pSharingSession->lpVtbl->get_Invitations(subsystem->pSharingSession, + &(subsystem->pInvitationMgr)); + + if (FAILED(hr)) + { + fprintf(stderr, "IRDPSRAPISharingSession::get_Invitations() failure\n"); + return -1; + } + + bstrAuthString = SysAllocString(L"Shadow"); + bstrGroupName = SysAllocString(L"ShadowGroup"); + bstrPassword = SysAllocString(L"Shadow123!"); + + hr = subsystem->pInvitationMgr->lpVtbl->CreateInvitation(subsystem->pInvitationMgr, bstrAuthString, + bstrGroupName, bstrPassword, 5, &(subsystem->pInvitation)); + + SysFreeString(bstrAuthString); + SysFreeString(bstrGroupName); + SysFreeString(bstrPassword); + + if (FAILED(hr)) + { + fprintf(stderr, "IRDPSRAPIInvitationManager::CreateInvitation() failure: 0x%08X\n", hr); + return -1; + } + + subsystem->pInvitation->lpVtbl->get_ConnectionString(subsystem->pInvitation, &bstrConnectionString); + + if (FAILED(hr)) + { + fprintf(stderr, "IRDPSRAPIInvitation::get_ConnectionString() failure: 0x%08X\n", hr); + return -1; + } + + subsystem->pAssistanceFile = freerdp_assistance_file_new(); + + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) bstrConnectionString, ((UINT32*) bstrConnectionString)[-1], + &(subsystem->pAssistanceFile->ConnectionString2), 0, NULL, NULL); + + status = freerdp_assistance_parse_connection_string2(subsystem->pAssistanceFile); + + if (status < 0) + return -1; + + printf("ConnectionString: %s\n", subsystem->pAssistanceFile->ConnectionString2); + + printf("RemoteAssistanceSessionId: %s\n", subsystem->pAssistanceFile->RASessionId); + printf("RemoteAssistanceRCTicket: %s\n", subsystem->pAssistanceFile->RCTicket); + printf("RemoteAssistancePassStub: %s\n", subsystem->pAssistanceFile->PassStub); + printf("RemoteAssistanceMachineAddress: %s\n", subsystem->pAssistanceFile->MachineAddress); + printf("RemoteAssistanceMachinePort: %s\n", subsystem->pAssistanceFile->MachinePort); + + return 1; +} + +int win_shadow_wds_uninit(winShadowSubsystem* subsystem) +{ + printf("win_shadow_wds_uninit\n"); + + if (subsystem->pSharingSession) + { + subsystem->pSharingSession->lpVtbl->Close(subsystem->pSharingSession); + subsystem->pSharingSession->lpVtbl->Release(subsystem->pSharingSession); + subsystem->pSharingSession = NULL; + } + + if (subsystem->pInvitationMgr) + { + subsystem->pInvitationMgr->lpVtbl->Release(subsystem->pInvitationMgr); + subsystem->pInvitationMgr = NULL; + } + + if (subsystem->pInvitation) + { + subsystem->pInvitation->lpVtbl->Release(subsystem->pInvitation); + subsystem->pInvitation = NULL; + } + + if (subsystem->pAssistanceFile) + { + freerdp_assistance_file_free(subsystem->pAssistanceFile); + subsystem->pAssistanceFile = NULL; + } + + return 1; +} diff --git a/server/shadow/Win/win_wds.h b/server/shadow/Win/win_wds.h index f0f06a8fa..346885586 100644 --- a/server/shadow/Win/win_wds.h +++ b/server/shadow/Win/win_wds.h @@ -19,11 +19,22 @@ #ifndef FREERDP_SHADOW_SERVER_WIN_WDS_H #define FREERDP_SHADOW_SERVER_WIN_WDS_H +#define WITH_WDS_API 1 + +#ifndef CINTERFACE +#define CINTERFACE +#endif + +#include + +#include "win_shadow.h" + #ifdef __cplusplus extern "C" { #endif - +int win_shadow_wds_init(winShadowSubsystem* subsystem); +int win_shadow_wds_uninit(winShadowSubsystem* subsystem); #ifdef __cplusplus }