1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 *
4 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <winpr/crt.h>
24 #include <winpr/print.h>
25 #include <freerdp/log.h>
26
27 #include "win_rdp.h"
28
29 #include "win_wds.h"
30
31 /**
32 * Windows Desktop Sharing API:
33 * http://blogs.msdn.com/b/rds/archive/2007/03/08/windows-desktop-sharing-api.aspx
34 *
35 * Windows Desktop Sharing Interfaces:
36 * http://msdn.microsoft.com/en-us/library/aa373871%28v=vs.85%29.aspx
37 *
38 * Offer Remote Assistance Sample C:
39 * http://msdn.microsoft.com/en-us/library/ms811079.aspx#remoteassistanceapi_topic2b
40 *
41 * Remote Assistance in XP: Programmatically establish an RDP session:
42 * http://www.codeproject.com/Articles/29939/Remote-Assistance-in-XP-Programmatically-establish
43 */
44
45 #undef DEFINE_GUID
46 #define INITGUID
47
48 #include <initguid.h>
49
50 #include <freerdp/assistance.h>
51
52 #define TAG SERVER_TAG("shadow.win")
53
54 DEFINE_GUID(CLSID_RDPSession, 0x9B78F0E6, 0x3E05, 0x4A5B, 0xB2, 0xE8, 0xE7, 0x43, 0xA8, 0x95, 0x6B,
55 0x65);
56 DEFINE_GUID(DIID__IRDPSessionEvents, 0x98a97042, 0x6698, 0x40e9, 0x8e, 0xfd, 0xb3, 0x20, 0x09, 0x90,
57 0x00, 0x4b);
58 DEFINE_GUID(IID_IRDPSRAPISharingSession, 0xeeb20886, 0xe470, 0x4cf6, 0x84, 0x2b, 0x27, 0x39, 0xc0,
59 0xec, 0x5c, 0xfb);
60 DEFINE_GUID(IID_IRDPSRAPIAttendee, 0xec0671b3, 0x1b78, 0x4b80, 0xa4, 0x64, 0x91, 0x32, 0x24, 0x75,
61 0x43, 0xe3);
62 DEFINE_GUID(IID_IRDPSRAPIAttendeeManager, 0xba3a37e8, 0x33da, 0x4749, 0x8d, 0xa0, 0x07, 0xfa, 0x34,
63 0xda, 0x79, 0x44);
64 DEFINE_GUID(IID_IRDPSRAPISessionProperties, 0x339b24f2, 0x9bc0, 0x4f16, 0x9a, 0xac, 0xf1, 0x65,
65 0x43, 0x3d, 0x13, 0xd4);
66 DEFINE_GUID(CLSID_RDPSRAPIApplicationFilter, 0xe35ace89, 0xc7e8, 0x427e, 0xa4, 0xf9, 0xb9, 0xda,
67 0x07, 0x28, 0x26, 0xbd);
68 DEFINE_GUID(CLSID_RDPSRAPIInvitationManager, 0x53d9c9db, 0x75ab, 0x4271, 0x94, 0x8a, 0x4c, 0x4e,
69 0xb3, 0x6a, 0x8f, 0x2b);
70
71 static ULONG Shadow_IRDPSessionEvents_RefCount = 0;
72
GetRDPSessionEventString(DISPID id)73 const char* GetRDPSessionEventString(DISPID id)
74 {
75 switch (id)
76 {
77 case DISPID_RDPSRAPI_EVENT_ON_ATTENDEE_CONNECTED:
78 return "OnAttendeeConnected";
79 break;
80
81 case DISPID_RDPSRAPI_EVENT_ON_ATTENDEE_DISCONNECTED:
82 return "OnAttendeeDisconnected";
83 break;
84
85 case DISPID_RDPSRAPI_EVENT_ON_ATTENDEE_UPDATE:
86 return "OnAttendeeUpdate";
87 break;
88
89 case DISPID_RDPSRAPI_EVENT_ON_ERROR:
90 return "OnError";
91 break;
92
93 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_CONNECTED:
94 return "OnConnectionEstablished";
95 break;
96
97 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_DISCONNECTED:
98 return "OnConnectionTerminated";
99 break;
100
101 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_AUTHENTICATED:
102 return "OnConnectionAuthenticated";
103 break;
104
105 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_CONNECTFAILED:
106 return "OnConnectionFailed";
107 break;
108
109 case DISPID_RDPSRAPI_EVENT_ON_CTRLLEVEL_CHANGE_REQUEST:
110 return "OnControlLevelChangeRequest";
111 break;
112
113 case DISPID_RDPSRAPI_EVENT_ON_GRAPHICS_STREAM_PAUSED:
114 return "OnGraphicsStreamPaused";
115 break;
116
117 case DISPID_RDPSRAPI_EVENT_ON_GRAPHICS_STREAM_RESUMED:
118 return "OnGraphicsStreamResumed";
119 break;
120
121 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_JOIN:
122 return "OnChannelJoin";
123 break;
124
125 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_LEAVE:
126 return "OnChannelLeave";
127 break;
128
129 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_DATARECEIVED:
130 return "OnChannelDataReceived";
131 break;
132
133 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_SENDCOMPLETED:
134 return "OnChannelDataSent";
135 break;
136
137 case DISPID_RDPSRAPI_EVENT_ON_APPLICATION_OPEN:
138 return "OnApplicationOpen";
139 break;
140
141 case DISPID_RDPSRAPI_EVENT_ON_APPLICATION_CLOSE:
142 return "OnApplicationClose";
143 break;
144
145 case DISPID_RDPSRAPI_EVENT_ON_APPLICATION_UPDATE:
146 return "OnApplicationUpdate";
147 break;
148
149 case DISPID_RDPSRAPI_EVENT_ON_WINDOW_OPEN:
150 return "OnWindowOpen";
151 break;
152
153 case DISPID_RDPSRAPI_EVENT_ON_WINDOW_CLOSE:
154 return "OnWindowClose";
155 break;
156
157 case DISPID_RDPSRAPI_EVENT_ON_WINDOW_UPDATE:
158 return "OnWindowUpdate";
159 break;
160
161 case DISPID_RDPSRAPI_EVENT_ON_APPFILTER_UPDATE:
162 return "OnAppFilterUpdate";
163 break;
164
165 case DISPID_RDPSRAPI_EVENT_ON_SHARED_RECT_CHANGED:
166 return "OnSharedRectChanged";
167 break;
168
169 case DISPID_RDPSRAPI_EVENT_ON_FOCUSRELEASED:
170 return "OnFocusReleased";
171 break;
172
173 case DISPID_RDPSRAPI_EVENT_ON_SHARED_DESKTOP_SETTINGS_CHANGED:
174 return "OnSharedDesktopSettingsChanged";
175 break;
176
177 case DISPID_RDPAPI_EVENT_ON_BOUNDING_RECT_CHANGED:
178 return "OnViewingSizeChanged";
179 break;
180 }
181
182 return "OnUnknown";
183 }
184
185 static HRESULT STDMETHODCALLTYPE
Shadow_IRDPSessionEvents_QueryInterface(__RPC__in _IRDPSessionEvents * This,__RPC__in REFIID riid,_COM_Outptr_ void ** ppvObject)186 Shadow_IRDPSessionEvents_QueryInterface(__RPC__in _IRDPSessionEvents* This,
187 /* [in] */ __RPC__in REFIID riid,
188 /* [annotation][iid_is][out] */
189 _COM_Outptr_ void** ppvObject)
190 {
191 *ppvObject = NULL;
192
193 if (IsEqualIID(riid, &DIID__IRDPSessionEvents) || IsEqualIID(riid, &IID_IDispatch) ||
194 IsEqualIID(riid, &IID_IUnknown))
195 {
196 *ppvObject = This;
197 }
198
199 if (!(*ppvObject))
200 return E_NOINTERFACE;
201
202 This->lpVtbl->AddRef(This);
203 return S_OK;
204 }
205
Shadow_IRDPSessionEvents_AddRef(__RPC__in _IRDPSessionEvents * This)206 static ULONG STDMETHODCALLTYPE Shadow_IRDPSessionEvents_AddRef(__RPC__in _IRDPSessionEvents* This)
207 {
208 Shadow_IRDPSessionEvents_RefCount++;
209 return Shadow_IRDPSessionEvents_RefCount;
210 }
211
Shadow_IRDPSessionEvents_Release(__RPC__in _IRDPSessionEvents * This)212 static ULONG STDMETHODCALLTYPE Shadow_IRDPSessionEvents_Release(__RPC__in _IRDPSessionEvents* This)
213 {
214 if (!Shadow_IRDPSessionEvents_RefCount)
215 return 0;
216
217 Shadow_IRDPSessionEvents_RefCount--;
218 return Shadow_IRDPSessionEvents_RefCount;
219 }
220
221 static HRESULT STDMETHODCALLTYPE
Shadow_IRDPSessionEvents_GetTypeInfoCount(__RPC__in _IRDPSessionEvents * This,__RPC__out UINT * pctinfo)222 Shadow_IRDPSessionEvents_GetTypeInfoCount(__RPC__in _IRDPSessionEvents* This,
223 /* [out] */ __RPC__out UINT* pctinfo)
224 {
225 WLog_INFO(TAG, "Shadow_IRDPSessionEvents_GetTypeInfoCount");
226 *pctinfo = 1;
227 return S_OK;
228 }
229
230 static HRESULT STDMETHODCALLTYPE
Shadow_IRDPSessionEvents_GetTypeInfo(__RPC__in _IRDPSessionEvents * This,UINT iTInfo,LCID lcid,__RPC__deref_out_opt ITypeInfo ** ppTInfo)231 Shadow_IRDPSessionEvents_GetTypeInfo(__RPC__in _IRDPSessionEvents* This,
232 /* [in] */ UINT iTInfo,
233 /* [in] */ LCID lcid,
234 /* [out] */ __RPC__deref_out_opt ITypeInfo** ppTInfo)
235 {
236 WLog_INFO(TAG, "Shadow_IRDPSessionEvents_GetTypeInfo");
237 return E_NOTIMPL;
238 }
239
240 static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_GetIDsOfNames(
241 __RPC__in _IRDPSessionEvents* This,
242 /* [in] */ __RPC__in REFIID riid,
243 /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR* rgszNames,
244 /* [range][in] */ __RPC__in_range(0, 16384) UINT cNames,
245 /* [in] */ LCID lcid,
246 /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID* rgDispId)
247 {
248 WLog_INFO(TAG, "Shadow_IRDPSessionEvents_GetIDsOfNames");
249 return E_NOTIMPL;
250 }
251
Shadow_IRDPSessionEvents_Invoke(_IRDPSessionEvents * This,_In_ DISPID dispIdMember,_In_ REFIID riid,_In_ LCID lcid,_In_ WORD wFlags,_In_ DISPPARAMS * pDispParams,_Out_opt_ VARIANT * pVarResult,_Out_opt_ EXCEPINFO * pExcepInfo,_Out_opt_ UINT * puArgErr)252 static HRESULT STDMETHODCALLTYPE Shadow_IRDPSessionEvents_Invoke(_IRDPSessionEvents* This,
253 /* [annotation][in] */
254 _In_ DISPID dispIdMember,
255 /* [annotation][in] */
256 _In_ REFIID riid,
257 /* [annotation][in] */
258 _In_ LCID lcid,
259 /* [annotation][in] */
260 _In_ WORD wFlags,
261 /* [annotation][out][in] */
262 _In_ DISPPARAMS* pDispParams,
263 /* [annotation][out] */
264 _Out_opt_ VARIANT* pVarResult,
265 /* [annotation][out] */
266 _Out_opt_ EXCEPINFO* pExcepInfo,
267 /* [annotation][out] */
268 _Out_opt_ UINT* puArgErr)
269 {
270 HRESULT hr;
271 VARIANT vr;
272 UINT uArgErr;
273 WLog_INFO(TAG, "%s (%ld)", GetRDPSessionEventString(dispIdMember), dispIdMember);
274
275 switch (dispIdMember)
276 {
277 case DISPID_RDPSRAPI_EVENT_ON_ATTENDEE_CONNECTED:
278 {
279 int level;
280 IDispatch* pDispatch;
281 IRDPSRAPIAttendee* pAttendee;
282 vr.vt = VT_DISPATCH;
283 vr.pdispVal = NULL;
284 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &vr, &uArgErr);
285
286 if (FAILED(hr))
287 {
288 WLog_ERR(TAG, "%s DispGetParam(0, VT_DISPATCH) failure: 0x%08lX",
289 GetRDPSessionEventString(dispIdMember), hr);
290 return hr;
291 }
292
293 pDispatch = vr.pdispVal;
294 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IRDPSRAPIAttendee,
295 (void**)&pAttendee);
296
297 if (FAILED(hr))
298 {
299 WLog_INFO(TAG, "%s IDispatch::QueryInterface(IRDPSRAPIAttendee) failure: 0x%08lX",
300 GetRDPSessionEventString(dispIdMember), hr);
301 return hr;
302 }
303
304 level = CTRL_LEVEL_VIEW;
305 // level = CTRL_LEVEL_INTERACTIVE;
306 hr = pAttendee->lpVtbl->put_ControlLevel(pAttendee, level);
307
308 if (FAILED(hr))
309 {
310 WLog_INFO(TAG, "%s IRDPSRAPIAttendee::put_ControlLevel() failure: 0x%08lX",
311 GetRDPSessionEventString(dispIdMember), hr);
312 return hr;
313 }
314
315 pAttendee->lpVtbl->Release(pAttendee);
316 }
317 break;
318
319 case DISPID_RDPSRAPI_EVENT_ON_ATTENDEE_DISCONNECTED:
320 break;
321
322 case DISPID_RDPSRAPI_EVENT_ON_ATTENDEE_UPDATE:
323 break;
324
325 case DISPID_RDPSRAPI_EVENT_ON_ERROR:
326 break;
327
328 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_CONNECTED:
329 break;
330
331 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_DISCONNECTED:
332 break;
333
334 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_AUTHENTICATED:
335 break;
336
337 case DISPID_RDPSRAPI_EVENT_ON_VIEWER_CONNECTFAILED:
338 break;
339
340 case DISPID_RDPSRAPI_EVENT_ON_CTRLLEVEL_CHANGE_REQUEST:
341 {
342 int level;
343 IDispatch* pDispatch;
344 IRDPSRAPIAttendee* pAttendee;
345 vr.vt = VT_INT;
346 vr.pdispVal = NULL;
347 hr = DispGetParam(pDispParams, 1, VT_INT, &vr, &uArgErr);
348
349 if (FAILED(hr))
350 {
351 WLog_INFO(TAG, "%s DispGetParam(1, VT_INT) failure: 0x%08lX",
352 GetRDPSessionEventString(dispIdMember), hr);
353 return hr;
354 }
355
356 level = vr.intVal;
357 vr.vt = VT_DISPATCH;
358 vr.pdispVal = NULL;
359 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &vr, &uArgErr);
360
361 if (FAILED(hr))
362 {
363 WLog_ERR(TAG, "%s DispGetParam(0, VT_DISPATCH) failure: 0x%08lX",
364 GetRDPSessionEventString(dispIdMember), hr);
365 return hr;
366 }
367
368 pDispatch = vr.pdispVal;
369 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IRDPSRAPIAttendee,
370 (void**)&pAttendee);
371
372 if (FAILED(hr))
373 {
374 WLog_INFO(TAG, "%s IDispatch::QueryInterface(IRDPSRAPIAttendee) failure: 0x%08lX",
375 GetRDPSessionEventString(dispIdMember), hr);
376 return hr;
377 }
378
379 hr = pAttendee->lpVtbl->put_ControlLevel(pAttendee, level);
380
381 if (FAILED(hr))
382 {
383 WLog_INFO(TAG, "%s IRDPSRAPIAttendee::put_ControlLevel() failure: 0x%08lX",
384 GetRDPSessionEventString(dispIdMember), hr);
385 return hr;
386 }
387
388 pAttendee->lpVtbl->Release(pAttendee);
389 }
390 break;
391
392 case DISPID_RDPSRAPI_EVENT_ON_GRAPHICS_STREAM_PAUSED:
393 break;
394
395 case DISPID_RDPSRAPI_EVENT_ON_GRAPHICS_STREAM_RESUMED:
396 break;
397
398 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_JOIN:
399 break;
400
401 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_LEAVE:
402 break;
403
404 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_DATARECEIVED:
405 break;
406
407 case DISPID_RDPSRAPI_EVENT_ON_VIRTUAL_CHANNEL_SENDCOMPLETED:
408 break;
409
410 case DISPID_RDPSRAPI_EVENT_ON_APPLICATION_OPEN:
411 break;
412
413 case DISPID_RDPSRAPI_EVENT_ON_APPLICATION_CLOSE:
414 break;
415
416 case DISPID_RDPSRAPI_EVENT_ON_APPLICATION_UPDATE:
417 break;
418
419 case DISPID_RDPSRAPI_EVENT_ON_WINDOW_OPEN:
420 break;
421
422 case DISPID_RDPSRAPI_EVENT_ON_WINDOW_CLOSE:
423 break;
424
425 case DISPID_RDPSRAPI_EVENT_ON_WINDOW_UPDATE:
426 break;
427
428 case DISPID_RDPSRAPI_EVENT_ON_APPFILTER_UPDATE:
429 break;
430
431 case DISPID_RDPSRAPI_EVENT_ON_SHARED_RECT_CHANGED:
432 break;
433
434 case DISPID_RDPSRAPI_EVENT_ON_FOCUSRELEASED:
435 break;
436
437 case DISPID_RDPSRAPI_EVENT_ON_SHARED_DESKTOP_SETTINGS_CHANGED:
438 break;
439
440 case DISPID_RDPAPI_EVENT_ON_BOUNDING_RECT_CHANGED:
441 break;
442 }
443
444 return S_OK;
445 }
446
447 static _IRDPSessionEventsVtbl Shadow_IRDPSessionEventsVtbl = {
448 /* IUnknown */
449 Shadow_IRDPSessionEvents_QueryInterface, Shadow_IRDPSessionEvents_AddRef,
450 Shadow_IRDPSessionEvents_Release,
451
452 /* IDispatch */
453 Shadow_IRDPSessionEvents_GetTypeInfoCount, Shadow_IRDPSessionEvents_GetTypeInfo,
454 Shadow_IRDPSessionEvents_GetIDsOfNames, Shadow_IRDPSessionEvents_Invoke
455 };
456
457 static _IRDPSessionEvents Shadow_IRDPSessionEvents = { &Shadow_IRDPSessionEventsVtbl };
458
ShadowWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)459 static LRESULT CALLBACK ShadowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
460 {
461 switch (uMsg)
462 {
463 case WM_CLOSE:
464 DestroyWindow(hwnd);
465 break;
466
467 case WM_DESTROY:
468 PostQuitMessage(0);
469 break;
470
471 default:
472 return DefWindowProc(hwnd, uMsg, wParam, lParam);
473 break;
474 }
475
476 return 0;
477 }
478
win_shadow_wds_wnd_init(winShadowSubsystem * subsystem)479 int win_shadow_wds_wnd_init(winShadowSubsystem* subsystem)
480 {
481 HMODULE hModule;
482 HINSTANCE hInstance;
483 WNDCLASSEX wndClassEx;
484 hModule = GetModuleHandle(NULL);
485 ZeroMemory(&wndClassEx, sizeof(WNDCLASSEX));
486 wndClassEx.cbSize = sizeof(WNDCLASSEX);
487 wndClassEx.style = 0;
488 wndClassEx.lpfnWndProc = ShadowWndProc;
489 wndClassEx.cbClsExtra = 0;
490 wndClassEx.cbWndExtra = 0;
491 wndClassEx.hInstance = hModule;
492 wndClassEx.hIcon = NULL;
493 wndClassEx.hCursor = NULL;
494 wndClassEx.hbrBackground = NULL;
495 wndClassEx.lpszMenuName = _T("ShadowWndMenu");
496 wndClassEx.lpszClassName = _T("ShadowWndClass");
497 wndClassEx.hIconSm = NULL;
498
499 if (!RegisterClassEx(&wndClassEx))
500 {
501 WLog_ERR(TAG, "RegisterClassEx failure");
502 return -1;
503 }
504
505 hInstance = wndClassEx.hInstance;
506 subsystem->hWnd = CreateWindowEx(0, wndClassEx.lpszClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
507 hInstance, NULL);
508
509 if (!subsystem->hWnd)
510 {
511 WLog_INFO(TAG, "CreateWindowEx failure");
512 return -1;
513 }
514
515 return 1;
516 }
517
win_shadow_wds_init(winShadowSubsystem * subsystem)518 int win_shadow_wds_init(winShadowSubsystem* subsystem)
519 {
520 int status;
521 HRESULT hr;
522 DWORD dwCookie;
523 long left, top;
524 long right, bottom;
525 long width, height;
526 IUnknown* pUnknown;
527 rdpSettings* settings;
528 BSTR bstrAuthString;
529 BSTR bstrGroupName;
530 BSTR bstrPassword;
531 BSTR bstrPropertyName;
532 VARIANT varPropertyValue;
533 rdpAssistanceFile* file;
534 IConnectionPoint* pCP;
535 IConnectionPointContainer* pCPC;
536 win_shadow_wds_wnd_init(subsystem);
537 hr = OleInitialize(NULL);
538
539 if (FAILED(hr))
540 {
541 WLog_ERR(TAG, "OleInitialize() failure");
542 return -1;
543 }
544
545 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
546
547 if (FAILED(hr))
548 {
549 WLog_ERR(TAG, "CoInitialize() failure");
550 return -1;
551 }
552
553 hr = CoCreateInstance(&CLSID_RDPSession, NULL, CLSCTX_ALL, &IID_IRDPSRAPISharingSession,
554 (void**)&(subsystem->pSharingSession));
555
556 if (FAILED(hr))
557 {
558 WLog_ERR(TAG, "CoCreateInstance(IRDPSRAPISharingSession) failure: 0x%08lX", hr);
559 return -1;
560 }
561
562 pUnknown = (IUnknown*)subsystem->pSharingSession;
563 hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IConnectionPointContainer, (void**)&pCPC);
564
565 if (FAILED(hr))
566 {
567 WLog_ERR(TAG, "QueryInterface(IID_IConnectionPointContainer) failure: 0x%08lX", hr);
568 return -1;
569 }
570
571 pCPC->lpVtbl->FindConnectionPoint(pCPC, &DIID__IRDPSessionEvents, &pCP);
572
573 if (FAILED(hr))
574 {
575 WLog_ERR(
576 TAG,
577 "IConnectionPointContainer::FindConnectionPoint(_IRDPSessionEvents) failure: 0x%08lX",
578 hr);
579 return -1;
580 }
581
582 dwCookie = 0;
583 subsystem->pSessionEvents = &Shadow_IRDPSessionEvents;
584 subsystem->pSessionEvents->lpVtbl->AddRef(subsystem->pSessionEvents);
585 hr = pCP->lpVtbl->Advise(pCP, (IUnknown*)subsystem->pSessionEvents, &dwCookie);
586
587 if (FAILED(hr))
588 {
589 WLog_ERR(TAG, "IConnectionPoint::Advise(Shadow_IRDPSessionEvents) failure: 0x%08lX", hr);
590 return -1;
591 }
592
593 hr = subsystem->pSharingSession->lpVtbl->put_ColorDepth(subsystem->pSharingSession, 32);
594
595 if (FAILED(hr))
596 {
597 WLog_ERR(TAG, "IRDPSRAPISharingSession::put_ColorDepth() failure: 0x%08lX", hr);
598 return -1;
599 }
600
601 hr = subsystem->pSharingSession->lpVtbl->GetDesktopSharedRect(subsystem->pSharingSession, &left,
602 &top, &right, &bottom);
603
604 if (FAILED(hr))
605 {
606 WLog_ERR(TAG, "IRDPSRAPISharingSession::GetDesktopSharedRect() failure: 0x%08lX", hr);
607 return -1;
608 }
609
610 width = right - left;
611 height = bottom - top;
612 WLog_INFO(
613 TAG,
614 "GetDesktopSharedRect(): left: %ld top: %ld right: %ld bottom: %ld width: %ld height: %ld",
615 left, top, right, bottom, width, height);
616 hr = subsystem->pSharingSession->lpVtbl->get_VirtualChannelManager(
617 subsystem->pSharingSession, &(subsystem->pVirtualChannelMgr));
618
619 if (FAILED(hr))
620 {
621 WLog_ERR(TAG, "IRDPSRAPISharingSession::get_VirtualChannelManager() failure: 0x%08lX", hr);
622 return -1;
623 }
624
625 hr = subsystem->pSharingSession->lpVtbl->get_ApplicationFilter(
626 subsystem->pSharingSession, &(subsystem->pApplicationFilter));
627
628 if (FAILED(hr))
629 {
630 WLog_ERR(TAG, "IRDPSRAPISharingSession::get_ApplicationFilter() failure: 0x%08lX", hr);
631 return -1;
632 }
633
634 hr = subsystem->pSharingSession->lpVtbl->get_Attendees(subsystem->pSharingSession,
635 &(subsystem->pAttendeeMgr));
636
637 if (FAILED(hr))
638 {
639 WLog_ERR(TAG, "IRDPSRAPISharingSession::get_Attendees() failure: 0x%08lX", hr);
640 return -1;
641 }
642
643 hr = subsystem->pSharingSession->lpVtbl->get_Properties(subsystem->pSharingSession,
644 &(subsystem->pSessionProperties));
645
646 if (FAILED(hr))
647 {
648 WLog_ERR(TAG, "IRDPSRAPISharingSession::get_Properties() failure: 0x%08lX", hr);
649 return -1;
650 }
651
652 bstrPropertyName = SysAllocString(L"PortId");
653 varPropertyValue.vt = VT_I4;
654 varPropertyValue.intVal = 40000;
655 hr = subsystem->pSessionProperties->lpVtbl->put_Property(subsystem->pSessionProperties,
656 bstrPropertyName, varPropertyValue);
657 SysFreeString(bstrPropertyName);
658
659 if (FAILED(hr))
660 {
661 WLog_ERR(TAG, "IRDPSRAPISessionProperties::put_Property(PortId) failure: 0x%08lX", hr);
662 return -1;
663 }
664
665 bstrPropertyName = SysAllocString(L"DrvConAttach");
666 varPropertyValue.vt = VT_BOOL;
667 varPropertyValue.boolVal = VARIANT_TRUE;
668 hr = subsystem->pSessionProperties->lpVtbl->put_Property(subsystem->pSessionProperties,
669 bstrPropertyName, varPropertyValue);
670 SysFreeString(bstrPropertyName);
671
672 if (FAILED(hr))
673 {
674 WLog_ERR(TAG, "IRDPSRAPISessionProperties::put_Property(DrvConAttach) failure: 0x%08lX",
675 hr);
676 return -1;
677 }
678
679 bstrPropertyName = SysAllocString(L"PortProtocol");
680 varPropertyValue.vt = VT_I4;
681 // varPropertyValue.intVal = 0; // AF_UNSPEC
682 varPropertyValue.intVal = 2; // AF_INET
683 // varPropertyValue.intVal = 23; // AF_INET6
684 hr = subsystem->pSessionProperties->lpVtbl->put_Property(subsystem->pSessionProperties,
685 bstrPropertyName, varPropertyValue);
686 SysFreeString(bstrPropertyName);
687
688 if (FAILED(hr))
689 {
690 WLog_ERR(TAG, "IRDPSRAPISessionProperties::put_Property(PortProtocol) failure: 0x%08lX",
691 hr);
692 return -1;
693 }
694
695 hr = subsystem->pSharingSession->lpVtbl->Open(subsystem->pSharingSession);
696
697 if (FAILED(hr))
698 {
699 WLog_ERR(TAG, "IRDPSRAPISharingSession::Open() failure: 0x%08lX", hr);
700 return -1;
701 }
702
703 hr = subsystem->pSharingSession->lpVtbl->get_Invitations(subsystem->pSharingSession,
704 &(subsystem->pInvitationMgr));
705
706 if (FAILED(hr))
707 {
708 WLog_ERR(TAG, "IRDPSRAPISharingSession::get_Invitations() failure");
709 return -1;
710 }
711
712 bstrAuthString = SysAllocString(L"Shadow");
713 bstrGroupName = SysAllocString(L"ShadowGroup");
714 bstrPassword = SysAllocString(L"Shadow123!");
715 hr = subsystem->pInvitationMgr->lpVtbl->CreateInvitation(
716 subsystem->pInvitationMgr, bstrAuthString, bstrGroupName, bstrPassword, 5,
717 &(subsystem->pInvitation));
718 SysFreeString(bstrAuthString);
719 SysFreeString(bstrGroupName);
720 SysFreeString(bstrPassword);
721
722 if (FAILED(hr))
723 {
724 WLog_ERR(TAG, "IRDPSRAPIInvitationManager::CreateInvitation() failure: 0x%08lX", hr);
725 return -1;
726 }
727
728 file = subsystem->pAssistanceFile = freerdp_assistance_file_new();
729
730 if (!file)
731 {
732 WLog_ERR(TAG, "freerdp_assistance_file_new() failed");
733 return -1;
734 }
735
736 {
737 int status1 = -1, status2 = -1;
738 char* ConnectionString2;
739 BSTR bstrConnectionString;
740 hr = subsystem->pInvitation->lpVtbl->get_ConnectionString(subsystem->pInvitation,
741 &bstrConnectionString);
742
743 if (FAILED(hr))
744 {
745 WLog_ERR(TAG, "IRDPSRAPIInvitation::get_ConnectionString() failure: 0x%08lX", hr);
746 return -1;
747 }
748
749 status1 = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)bstrConnectionString,
750 ((UINT32*)bstrConnectionString)[-1], &(ConnectionString2), 0,
751 NULL, NULL);
752 SysFreeString(bstrConnectionString);
753 status2 = freerdp_assistance_set_connection_string2(file, ConnectionString2, "Shadow123!");
754 free(ConnectionString2);
755
756 if ((status1 < 1) || (status2 < 1))
757 {
758 WLog_ERR(TAG, "failed to convert connection string");
759 return -1;
760 }
761 }
762
763 freerdp_assistance_print_file(file, WLog_Get(TAG), WLOG_INFO);
764 status = win_shadow_rdp_init(subsystem);
765
766 if (status < 0)
767 {
768 WLog_ERR(TAG, "win_shadow_rdp_init() failure: %d", status);
769 return status;
770 }
771
772 settings = subsystem->shw->settings;
773 status = freerdp_assistance_populate_settings_from_assistance_file(file, settings);
774 freerdp_set_param_string(settings, FreeRDP_Domain, "RDP");
775 freerdp_set_param_string(settings, FreeRDP_Username, "Shadow");
776 freerdp_set_param_bool(settings, FreeRDP_AutoLogonEnabled, TRUE);
777 freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, width);
778 freerdp_set_param_uint32(settings, FreeRDP_DesktopHeight, height);
779 status = win_shadow_rdp_start(subsystem);
780
781 if (status < 0)
782 {
783 WLog_ERR(TAG, "win_shadow_rdp_start() failure: %d", status);
784 return status;
785 }
786
787 return 1;
788 }
789
win_shadow_wds_uninit(winShadowSubsystem * subsystem)790 int win_shadow_wds_uninit(winShadowSubsystem* subsystem)
791 {
792 if (subsystem->pSharingSession)
793 {
794 subsystem->pSharingSession->lpVtbl->Close(subsystem->pSharingSession);
795 subsystem->pSharingSession->lpVtbl->Release(subsystem->pSharingSession);
796 subsystem->pSharingSession = NULL;
797 }
798
799 if (subsystem->pVirtualChannelMgr)
800 {
801 subsystem->pVirtualChannelMgr->lpVtbl->Release(subsystem->pVirtualChannelMgr);
802 subsystem->pVirtualChannelMgr = NULL;
803 }
804
805 if (subsystem->pApplicationFilter)
806 {
807 subsystem->pApplicationFilter->lpVtbl->Release(subsystem->pApplicationFilter);
808 subsystem->pApplicationFilter = NULL;
809 }
810
811 if (subsystem->pAttendeeMgr)
812 {
813 subsystem->pAttendeeMgr->lpVtbl->Release(subsystem->pAttendeeMgr);
814 subsystem->pAttendeeMgr = NULL;
815 }
816
817 if (subsystem->pSessionProperties)
818 {
819 subsystem->pSessionProperties->lpVtbl->Release(subsystem->pSessionProperties);
820 subsystem->pSessionProperties = NULL;
821 }
822
823 if (subsystem->pInvitationMgr)
824 {
825 subsystem->pInvitationMgr->lpVtbl->Release(subsystem->pInvitationMgr);
826 subsystem->pInvitationMgr = NULL;
827 }
828
829 if (subsystem->pInvitation)
830 {
831 subsystem->pInvitation->lpVtbl->Release(subsystem->pInvitation);
832 subsystem->pInvitation = NULL;
833 }
834
835 if (subsystem->pAssistanceFile)
836 {
837 freerdp_assistance_file_free(subsystem->pAssistanceFile);
838 subsystem->pAssistanceFile = NULL;
839 }
840
841 if (subsystem->hWnd)
842 {
843 DestroyWindow(subsystem->hWnd);
844 subsystem->hWnd = NULL;
845 }
846
847 if (subsystem->shw)
848 {
849 win_shadow_rdp_uninit(subsystem);
850 subsystem->shw = NULL;
851 }
852
853 return 1;
854 }
855