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