1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  *
4  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
5  * Copyright 2017 Armin Novak <armin.novak@thincast.com>
6  * Copyright 2017 Thincast Technologies GmbH
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <winpr/crt.h>
26 #include <winpr/file.h>
27 #include <winpr/path.h>
28 #include <winpr/synch.h>
29 #include <winpr/thread.h>
30 #include <winpr/sysinfo.h>
31 #include <winpr/interlocked.h>
32 
33 #include <freerdp/log.h>
34 
35 #include "shadow.h"
36 
37 #define TAG CLIENT_TAG("shadow")
38 
39 struct _SHADOW_GFX_STATUS
40 {
41 	BOOL gfxOpened;
42 	BOOL gfxSurfaceCreated;
43 };
44 typedef struct _SHADOW_GFX_STATUS SHADOW_GFX_STATUS;
45 
shadow_client_rdpgfx_new_surface(rdpShadowClient * client)46 static INLINE BOOL shadow_client_rdpgfx_new_surface(rdpShadowClient* client)
47 {
48 	UINT error = CHANNEL_RC_OK;
49 	RDPGFX_CREATE_SURFACE_PDU createSurface;
50 	RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU surfaceToOutput;
51 	RdpgfxServerContext* context = client->rdpgfx;
52 	rdpSettings* settings = ((rdpContext*)client)->settings;
53 	createSurface.width = settings->DesktopWidth;
54 	createSurface.height = settings->DesktopHeight;
55 	createSurface.pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
56 	createSurface.surfaceId = 0;
57 	surfaceToOutput.outputOriginX = 0;
58 	surfaceToOutput.outputOriginY = 0;
59 	surfaceToOutput.surfaceId = 0;
60 	surfaceToOutput.reserved = 0;
61 	IFCALLRET(context->CreateSurface, error, context, &createSurface);
62 
63 	if (error)
64 	{
65 		WLog_ERR(TAG, "CreateSurface failed with error %" PRIu32 "", error);
66 		return FALSE;
67 	}
68 
69 	IFCALLRET(context->MapSurfaceToOutput, error, context, &surfaceToOutput);
70 
71 	if (error)
72 	{
73 		WLog_ERR(TAG, "MapSurfaceToOutput failed with error %" PRIu32 "", error);
74 		return FALSE;
75 	}
76 
77 	return TRUE;
78 }
79 
shadow_client_rdpgfx_release_surface(rdpShadowClient * client)80 static INLINE BOOL shadow_client_rdpgfx_release_surface(rdpShadowClient* client)
81 {
82 	UINT error = CHANNEL_RC_OK;
83 	RDPGFX_DELETE_SURFACE_PDU pdu;
84 	RdpgfxServerContext* context = client->rdpgfx;
85 	pdu.surfaceId = 0;
86 	IFCALLRET(context->DeleteSurface, error, context, &pdu);
87 
88 	if (error)
89 	{
90 		WLog_ERR(TAG, "DeleteSurface failed with error %" PRIu32 "", error);
91 		return FALSE;
92 	}
93 
94 	return TRUE;
95 }
96 
shadow_client_rdpgfx_reset_graphic(rdpShadowClient * client)97 static INLINE BOOL shadow_client_rdpgfx_reset_graphic(rdpShadowClient* client)
98 {
99 	UINT error = CHANNEL_RC_OK;
100 	RDPGFX_RESET_GRAPHICS_PDU pdu;
101 	RdpgfxServerContext* context = client->rdpgfx;
102 	rdpSettings* settings = ((rdpContext*)client)->settings;
103 	pdu.width = settings->DesktopWidth;
104 	pdu.height = settings->DesktopHeight;
105 	pdu.monitorCount = client->subsystem->numMonitors;
106 	pdu.monitorDefArray = client->subsystem->monitors;
107 	IFCALLRET(context->ResetGraphics, error, context, &pdu);
108 
109 	if (error)
110 	{
111 		WLog_ERR(TAG, "ResetGraphics failed with error %" PRIu32 "", error);
112 		return FALSE;
113 	}
114 
115 	return TRUE;
116 }
117 
shadow_client_free_queued_message(void * obj)118 static INLINE void shadow_client_free_queued_message(void* obj)
119 {
120 	wMessage* message = (wMessage*)obj;
121 
122 	if (message->Free)
123 	{
124 		message->Free(message);
125 		message->Free = NULL;
126 	}
127 }
128 
shadow_client_context_new(freerdp_peer * peer,rdpShadowClient * client)129 static BOOL shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
130 {
131 	const char bind_address[] = "bind-address,";
132 	rdpSettings* settings;
133 	rdpShadowServer* server;
134 	const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL };
135 	server = (rdpShadowServer*)peer->ContextExtra;
136 	client->server = server;
137 	client->subsystem = server->subsystem;
138 	settings = peer->settings;
139 	settings->ColorDepth = 32;
140 	settings->NSCodec = TRUE;
141 	settings->RemoteFxCodec = TRUE;
142 	settings->BitmapCacheV3Enabled = TRUE;
143 	settings->FrameMarkerCommandEnabled = TRUE;
144 	settings->SurfaceFrameMarkerEnabled = TRUE;
145 	settings->SupportGraphicsPipeline = TRUE;
146 	settings->GfxH264 = FALSE;
147 	settings->DrawAllowSkipAlpha = TRUE;
148 	settings->DrawAllowColorSubsampling = TRUE;
149 	settings->DrawAllowDynamicColorFidelity = TRUE;
150 	settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
151 
152 	if (!(settings->CertificateFile = _strdup(server->CertificateFile)))
153 		goto fail_cert_file;
154 
155 	if (!(settings->PrivateKeyFile = _strdup(server->PrivateKeyFile)))
156 		goto fail_privkey_file;
157 
158 	if (!(settings->RdpKeyFile = _strdup(settings->PrivateKeyFile)))
159 		goto fail_rdpkey_file;
160 
161 	if (server->ipcSocket && (strncmp(bind_address, server->ipcSocket,
162 	                                  strnlen(bind_address, sizeof(bind_address))) != 0))
163 	{
164 		settings->LyncRdpMode = TRUE;
165 		settings->CompressionEnabled = FALSE;
166 	}
167 
168 	client->inLobby = TRUE;
169 	client->mayView = server->mayView;
170 	client->mayInteract = server->mayInteract;
171 
172 	if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
173 		goto fail_client_lock;
174 
175 	region16_init(&(client->invalidRegion));
176 	client->vcm = WTSOpenServerA((LPSTR)peer->context);
177 
178 	if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
179 		goto fail_open_server;
180 
181 	if (!(client->MsgQueue = MessageQueue_New(&cb)))
182 		goto fail_message_queue;
183 
184 	if (!(client->encoder = shadow_encoder_new(client)))
185 		goto fail_encoder_new;
186 
187 	if (ArrayList_Add(server->clients, (void*)client) >= 0)
188 		return TRUE;
189 
190 	shadow_encoder_free(client->encoder);
191 	client->encoder = NULL;
192 fail_encoder_new:
193 	MessageQueue_Free(client->MsgQueue);
194 	client->MsgQueue = NULL;
195 fail_message_queue:
196 	WTSCloseServer((HANDLE)client->vcm);
197 	client->vcm = NULL;
198 fail_open_server:
199 	DeleteCriticalSection(&(client->lock));
200 fail_client_lock:
201 	free(settings->RdpKeyFile);
202 	settings->RdpKeyFile = NULL;
203 fail_rdpkey_file:
204 	free(settings->PrivateKeyFile);
205 	settings->PrivateKeyFile = NULL;
206 fail_privkey_file:
207 	free(settings->CertificateFile);
208 	settings->CertificateFile = NULL;
209 fail_cert_file:
210 	return FALSE;
211 }
212 
shadow_client_context_free(freerdp_peer * peer,rdpShadowClient * client)213 static void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
214 {
215 	rdpShadowServer* server = client->server;
216 	WINPR_UNUSED(peer);
217 	ArrayList_Remove(server->clients, (void*)client);
218 
219 	if (client->encoder)
220 	{
221 		shadow_encoder_free(client->encoder);
222 		client->encoder = NULL;
223 	}
224 
225 	/* Clear queued messages and free resource */
226 	MessageQueue_Clear(client->MsgQueue);
227 	MessageQueue_Free(client->MsgQueue);
228 	WTSCloseServer((HANDLE)client->vcm);
229 	client->vcm = NULL;
230 	region16_uninit(&(client->invalidRegion));
231 	DeleteCriticalSection(&(client->lock));
232 }
233 
shadow_client_mark_invalid(rdpShadowClient * client,int numRects,const RECTANGLE_16 * rects)234 static INLINE void shadow_client_mark_invalid(rdpShadowClient* client, int numRects,
235                                               const RECTANGLE_16* rects)
236 {
237 	int index;
238 	RECTANGLE_16 screenRegion;
239 	rdpSettings* settings = ((rdpContext*)client)->settings;
240 	EnterCriticalSection(&(client->lock));
241 
242 	/* Mark client invalid region. No rectangle means full screen */
243 	if (numRects > 0)
244 	{
245 		for (index = 0; index < numRects; index++)
246 		{
247 			region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
248 		}
249 	}
250 	else
251 	{
252 		screenRegion.left = 0;
253 		screenRegion.top = 0;
254 		screenRegion.right = settings->DesktopWidth;
255 		screenRegion.bottom = settings->DesktopHeight;
256 		region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &screenRegion);
257 	}
258 
259 	LeaveCriticalSection(&(client->lock));
260 }
261 
262 /**
263  * Function description
264  * Recalculate client desktop size and update to rdpSettings
265  *
266  * @return TRUE if width/height changed.
267  */
shadow_client_recalc_desktop_size(rdpShadowClient * client)268 static INLINE BOOL shadow_client_recalc_desktop_size(rdpShadowClient* client)
269 {
270 	int width, height;
271 	rdpShadowServer* server = client->server;
272 	rdpSettings* settings = client->context.settings;
273 	RECTANGLE_16 viewport = { 0, 0, server->surface->width, server->surface->height };
274 
275 	if (server->shareSubRect)
276 	{
277 		rectangles_intersection(&viewport, &(server->subRect), &viewport);
278 	}
279 
280 	width = viewport.right - viewport.left;
281 	height = viewport.bottom - viewport.top;
282 
283 	if (settings->DesktopWidth != (UINT32)width || settings->DesktopHeight != (UINT32)height)
284 	{
285 		settings->DesktopWidth = width;
286 		settings->DesktopHeight = height;
287 		return TRUE;
288 	}
289 
290 	return FALSE;
291 }
292 
shadow_client_capabilities(freerdp_peer * peer)293 static BOOL shadow_client_capabilities(freerdp_peer* peer)
294 {
295 	rdpShadowSubsystem* subsystem;
296 	rdpShadowClient* client;
297 	BOOL ret = TRUE;
298 	client = (rdpShadowClient*)peer->context;
299 	subsystem = client->server->subsystem;
300 	IFCALLRET(subsystem->ClientCapabilities, ret, subsystem, client);
301 
302 	if (!ret)
303 		WLog_WARN(TAG, "subsystem->ClientCapabilities failed");
304 
305 	/* Recalculate desktop size regardless whether previous call fail
306 	 * or not. Make sure we send correct width/height to client */
307 	(void)shadow_client_recalc_desktop_size(client);
308 	return ret;
309 }
310 
shadow_client_post_connect(freerdp_peer * peer)311 static BOOL shadow_client_post_connect(freerdp_peer* peer)
312 {
313 	int authStatus;
314 	rdpSettings* settings;
315 	rdpShadowClient* client;
316 	rdpShadowServer* server;
317 	rdpShadowSubsystem* subsystem;
318 	client = (rdpShadowClient*)peer->context;
319 	settings = peer->settings;
320 	server = client->server;
321 	subsystem = server->subsystem;
322 
323 	if (settings->ColorDepth == 24)
324 		settings->ColorDepth = 16; /* disable 24bpp */
325 
326 	if (settings->MultifragMaxRequestSize < 0x3F0000)
327 		settings->NSCodec = FALSE; /* NSCodec compressor does not support fragmentation yet */
328 
329 	WLog_INFO(TAG, "Client from %s is activated (%" PRIu32 "x%" PRIu32 "@%" PRIu32 ")",
330 	          peer->hostname, settings->DesktopWidth, settings->DesktopHeight,
331 	          settings->ColorDepth);
332 
333 	/* Resize client if necessary */
334 	if (shadow_client_recalc_desktop_size(client))
335 	{
336 		peer->update->DesktopResize(peer->update->context);
337 		WLog_INFO(TAG, "Client from %s is resized (%" PRIu32 "x%" PRIu32 "@%" PRIu32 ")",
338 		          peer->hostname, settings->DesktopWidth, settings->DesktopHeight,
339 		          settings->ColorDepth);
340 	}
341 
342 	if (shadow_client_channels_post_connect(client) != CHANNEL_RC_OK)
343 		return FALSE;
344 
345 	shadow_client_mark_invalid(client, 0, NULL);
346 	authStatus = -1;
347 
348 	if (settings->Username && settings->Password)
349 		settings->AutoLogonEnabled = TRUE;
350 
351 	if (server->authentication && !settings->NlaSecurity)
352 	{
353 		if (subsystem->Authenticate)
354 		{
355 			authStatus = subsystem->Authenticate(subsystem, client, settings->Username,
356 			                                     settings->Domain, settings->Password);
357 		}
358 
359 		if (authStatus < 0)
360 		{
361 			WLog_ERR(TAG, "client authentication failure: %d", authStatus);
362 			return FALSE;
363 		}
364 	}
365 
366 	if (subsystem->ClientConnect)
367 	{
368 		return subsystem->ClientConnect(subsystem, client);
369 	}
370 
371 	return TRUE;
372 }
373 
374 /* Convert rects in sub rect coordinate to client/surface coordinate */
shadow_client_convert_rects(rdpShadowClient * client,RECTANGLE_16 * dst,const RECTANGLE_16 * src,UINT32 numRects)375 static INLINE void shadow_client_convert_rects(rdpShadowClient* client, RECTANGLE_16* dst,
376                                                const RECTANGLE_16* src, UINT32 numRects)
377 {
378 	if (client->server->shareSubRect)
379 	{
380 		UINT32 i = 0;
381 		UINT16 offsetX = client->server->subRect.left;
382 		UINT16 offsetY = client->server->subRect.top;
383 
384 		for (i = 0; i < numRects; i++)
385 		{
386 			dst[i].left = src[i].left + offsetX;
387 			dst[i].right = src[i].right + offsetX;
388 			dst[i].top = src[i].top + offsetY;
389 			dst[i].bottom = src[i].bottom + offsetY;
390 		}
391 	}
392 	else
393 	{
394 		if (src != dst)
395 		{
396 			CopyMemory(dst, src, numRects * sizeof(RECTANGLE_16));
397 		}
398 	}
399 }
400 
shadow_client_refresh_request(rdpShadowClient * client)401 static BOOL shadow_client_refresh_request(rdpShadowClient* client)
402 {
403 	wMessage message = { 0 };
404 	wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
405 	message.id = SHADOW_MSG_IN_REFRESH_REQUEST_ID;
406 	message.wParam = NULL;
407 	message.lParam = NULL;
408 	message.context = (void*)client;
409 	message.Free = NULL;
410 	return MessageQueue_Dispatch(MsgPipe->In, &message);
411 }
412 
shadow_client_refresh_rect(rdpContext * context,BYTE count,const RECTANGLE_16 * areas)413 static BOOL shadow_client_refresh_rect(rdpContext* context, BYTE count, const RECTANGLE_16* areas)
414 {
415 	rdpShadowClient* client = (rdpShadowClient*)context;
416 	RECTANGLE_16* rects;
417 
418 	/* It is invalid if we have area count but no actual area */
419 	if (count && !areas)
420 		return FALSE;
421 
422 	if (count)
423 	{
424 		rects = (RECTANGLE_16*)calloc(count, sizeof(RECTANGLE_16));
425 
426 		if (!rects)
427 		{
428 			return FALSE;
429 		}
430 
431 		shadow_client_convert_rects(client, rects, areas, count);
432 		shadow_client_mark_invalid(client, count, rects);
433 		free(rects);
434 	}
435 	else
436 	{
437 		shadow_client_mark_invalid(client, 0, NULL);
438 	}
439 
440 	return shadow_client_refresh_request(client);
441 }
442 
shadow_client_suppress_output(rdpContext * context,BYTE allow,const RECTANGLE_16 * area)443 static BOOL shadow_client_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
444 {
445 	rdpShadowClient* client = (rdpShadowClient*)context;
446 	RECTANGLE_16 region;
447 	client->suppressOutput = allow ? FALSE : TRUE;
448 
449 	if (allow)
450 	{
451 		if (area)
452 		{
453 			shadow_client_convert_rects(client, &region, area, 1);
454 			shadow_client_mark_invalid(client, 1, &region);
455 		}
456 		else
457 		{
458 			shadow_client_mark_invalid(client, 0, NULL);
459 		}
460 	}
461 
462 	return shadow_client_refresh_request(client);
463 }
464 
shadow_client_activate(freerdp_peer * peer)465 static BOOL shadow_client_activate(freerdp_peer* peer)
466 {
467 	rdpSettings* settings = peer->settings;
468 	rdpShadowClient* client = (rdpShadowClient*)peer->context;
469 
470 	if (settings->ClientDir && (strcmp(settings->ClientDir, "librdp") == 0))
471 	{
472 		/* Hack for Mac/iOS/Android Microsoft RDP clients */
473 		settings->RemoteFxCodec = FALSE;
474 		settings->NSCodec = FALSE;
475 		settings->NSCodecAllowSubsampling = FALSE;
476 		settings->SurfaceFrameMarkerEnabled = FALSE;
477 	}
478 
479 	client->activated = TRUE;
480 	client->inLobby = client->mayView ? FALSE : TRUE;
481 
482 	if (shadow_encoder_reset(client->encoder) < 0)
483 	{
484 		WLog_ERR(TAG, "Failed to reset encoder");
485 		return FALSE;
486 	}
487 
488 	/* Update full screen in next update */
489 	return shadow_client_refresh_rect(&client->context, 0, NULL);
490 }
491 
shadow_client_logon(freerdp_peer * peer,SEC_WINNT_AUTH_IDENTITY * identity,BOOL automatic)492 static BOOL shadow_client_logon(freerdp_peer* peer, SEC_WINNT_AUTH_IDENTITY* identity,
493                                 BOOL automatic)
494 {
495 	char* user = NULL;
496 	char* domain = NULL;
497 	char* password = NULL;
498 	rdpSettings* settings = peer->settings;
499 
500 	if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
501 	{
502 		if (identity->User)
503 			ConvertFromUnicode(CP_UTF8, 0, identity->User, identity->UserLength, &user, 0, NULL,
504 			                   NULL);
505 
506 		if (identity->Domain)
507 			ConvertFromUnicode(CP_UTF8, 0, identity->Domain, identity->DomainLength, &domain, 0,
508 			                   NULL, NULL);
509 
510 		if (identity->Password)
511 			ConvertFromUnicode(CP_UTF8, 0, identity->Password, identity->PasswordLength, &user, 0,
512 			                   NULL, NULL);
513 	}
514 	else
515 	{
516 		if (identity->User)
517 			user = _strdup((char*)identity->User);
518 
519 		if (identity->Domain)
520 			domain = _strdup((char*)identity->Domain);
521 
522 		if (identity->Password)
523 			password = _strdup((char*)identity->Password);
524 	}
525 
526 	if ((identity->User && !user) || (identity->Domain && !domain) ||
527 	    (identity->Password && !password))
528 	{
529 		free(user);
530 		free(domain);
531 		free(password);
532 		return FALSE;
533 	}
534 
535 	if (user)
536 	{
537 		free(settings->Username);
538 		settings->Username = user;
539 		user = NULL;
540 	}
541 
542 	if (domain)
543 	{
544 		free(settings->Domain);
545 		settings->Domain = domain;
546 		domain = NULL;
547 	}
548 
549 	if (password)
550 	{
551 		free(settings->Password);
552 		settings->Password = password;
553 		password = NULL;
554 	}
555 
556 	free(user);
557 	free(domain);
558 	free(password);
559 	return TRUE;
560 }
561 
shadow_client_common_frame_acknowledge(rdpShadowClient * client,UINT32 frameId)562 static INLINE void shadow_client_common_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
563 {
564 	/*
565 	 * Record the last client acknowledged frame id to
566 	 * calculate how much frames are in progress.
567 	 * Some rdp clients (win7 mstsc) skips frame ACK if it is
568 	 * inactive, we should not expect ACK for each frame.
569 	 * So it is OK to calculate inflight frame count according to
570 	 * a latest acknowledged frame id.
571 	 */
572 	client->encoder->lastAckframeId = frameId;
573 }
574 
shadow_client_surface_frame_acknowledge(rdpContext * context,UINT32 frameId)575 static BOOL shadow_client_surface_frame_acknowledge(rdpContext* context, UINT32 frameId)
576 {
577 	rdpShadowClient* client = (rdpShadowClient*)context;
578 	shadow_client_common_frame_acknowledge(client, frameId);
579 	/*
580 	 * Reset queueDepth for legacy none RDPGFX acknowledge
581 	 */
582 	client->encoder->queueDepth = QUEUE_DEPTH_UNAVAILABLE;
583 	return TRUE;
584 }
585 
586 static UINT
shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext * context,const RDPGFX_FRAME_ACKNOWLEDGE_PDU * frameAcknowledge)587 shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext* context,
588                                        const RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge)
589 {
590 	rdpShadowClient* client = (rdpShadowClient*)context->custom;
591 	shadow_client_common_frame_acknowledge(client, frameAcknowledge->frameId);
592 	client->encoder->queueDepth = frameAcknowledge->queueDepth;
593 	return CHANNEL_RC_OK;
594 }
595 
shadow_are_caps_filtered(const rdpSettings * settings,UINT32 caps)596 static BOOL shadow_are_caps_filtered(const rdpSettings* settings, UINT32 caps)
597 {
598 	const UINT32 filter = settings->GfxCapsFilter;
599 	const UINT32 capList[] = {
600 		RDPGFX_CAPVERSION_8,   RDPGFX_CAPVERSION_81,  RDPGFX_CAPVERSION_10,
601 		RDPGFX_CAPVERSION_101, RDPGFX_CAPVERSION_102, RDPGFX_CAPVERSION_103,
602 		RDPGFX_CAPVERSION_104, RDPGFX_CAPVERSION_105, RDPGFX_CAPVERSION_106
603 	};
604 	UINT32 x;
605 
606 	for (x = 0; x < ARRAYSIZE(capList); x++)
607 	{
608 		if (caps == capList[x])
609 			return (filter & (1 << x)) != 0;
610 	}
611 
612 	return TRUE;
613 }
614 
shadow_client_caps_test_version(RdpgfxServerContext * context,BOOL h264,const RDPGFX_CAPSET * capsSets,UINT32 capsSetCount,UINT32 capsVersion,UINT * rc)615 static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, BOOL h264,
616                                             const RDPGFX_CAPSET* capsSets, UINT32 capsSetCount,
617                                             UINT32 capsVersion, UINT* rc)
618 {
619 	UINT32 flags = 0;
620 	UINT32 index;
621 	rdpSettings* settings;
622 	settings = context->rdpcontext->settings;
623 
624 	if (shadow_are_caps_filtered(settings, capsVersion))
625 		return FALSE;
626 
627 	for (index = 0; index < capsSetCount; index++)
628 	{
629 		const RDPGFX_CAPSET* currentCaps = &capsSets[index];
630 
631 		if (currentCaps->version == capsVersion)
632 		{
633 			RDPGFX_CAPSET caps = *currentCaps;
634 			RDPGFX_CAPS_CONFIRM_PDU pdu;
635 			pdu.capsSet = &caps;
636 
637 			if (settings)
638 			{
639 				flags = pdu.capsSet->flags;
640 				settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
641 
642 				if (h264)
643 					settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 =
644 					    !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
645 				else
646 				{
647 					settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE;
648 					pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
649 				}
650 			}
651 
652 			*rc = context->CapsConfirm(context, &pdu);
653 			return TRUE;
654 		}
655 	}
656 
657 	return FALSE;
658 }
659 
660 /**
661  * Function description
662  *
663  * @return 0 on success, otherwise a Win32 error code
664  */
shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext * context,const RDPGFX_CAPS_ADVERTISE_PDU * capsAdvertise)665 static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
666                                                 const RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise)
667 {
668 	UINT16 index;
669 	UINT rc = ERROR_INTERNAL_ERROR;
670 	BOOL h264 = FALSE;
671 	rdpSettings* settings = context->rdpcontext->settings;
672 	UINT32 flags = 0;
673 	rdpShadowClient* client = (rdpShadowClient*)context->custom;
674 
675 #ifdef WITH_GFX_H264
676 	if (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0)
677 		h264 = TRUE;
678 
679 #endif
680 
681 	/* Request full screen update for new gfx channel */
682 	if (!shadow_client_refresh_rect(&client->context, 0, NULL))
683 		return rc;
684 
685 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
686 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc))
687 		return rc;
688 
689 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
690 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc))
691 		return rc;
692 
693 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
694 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc))
695 		return rc;
696 
697 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
698 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc))
699 		return rc;
700 
701 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
702 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc))
703 		return rc;
704 
705 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
706 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc))
707 		return rc;
708 
709 	if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets,
710 	                                    capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc))
711 		return rc;
712 
713 	if (!shadow_are_caps_filtered(settings, RDPGFX_CAPVERSION_81))
714 	{
715 		for (index = 0; index < capsAdvertise->capsSetCount; index++)
716 		{
717 			const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
718 
719 			if (currentCaps->version == RDPGFX_CAPVERSION_81)
720 			{
721 				RDPGFX_CAPSET caps = *currentCaps;
722 				RDPGFX_CAPS_CONFIRM_PDU pdu;
723 				pdu.capsSet = &caps;
724 
725 				if (settings)
726 				{
727 					flags = pdu.capsSet->flags;
728 					settings->GfxAVC444v2 = settings->GfxAVC444 = FALSE;
729 					settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
730 					settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
731 #ifndef WITH_GFX_H264
732 					settings->GfxH264 = FALSE;
733 					pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
734 #else
735 					if (h264)
736 						settings->GfxH264 = (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED);
737 					else
738 						settings->GfxH264 = FALSE;
739 #endif
740 				}
741 
742 				return context->CapsConfirm(context, &pdu);
743 			}
744 		}
745 	}
746 
747 	if (!shadow_are_caps_filtered(settings, RDPGFX_CAPVERSION_8))
748 	{
749 		for (index = 0; index < capsAdvertise->capsSetCount; index++)
750 		{
751 			const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
752 
753 			if (currentCaps->version == RDPGFX_CAPVERSION_8)
754 			{
755 				RDPGFX_CAPSET caps = *currentCaps;
756 				RDPGFX_CAPS_CONFIRM_PDU pdu;
757 				pdu.capsSet = &caps;
758 
759 				if (settings)
760 				{
761 					flags = pdu.capsSet->flags;
762 					settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
763 					settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
764 				}
765 
766 				return context->CapsConfirm(context, &pdu);
767 			}
768 		}
769 	}
770 
771 	return CHANNEL_RC_UNSUPPORTED_VERSION;
772 }
773 
rdpgfx_estimate_h264_avc420(RDPGFX_AVC420_BITMAP_STREAM * havc420)774 static INLINE UINT32 rdpgfx_estimate_h264_avc420(RDPGFX_AVC420_BITMAP_STREAM* havc420)
775 {
776 	/* H264 metadata + H264 stream. See rdpgfx_write_h264_avc420 */
777 	return sizeof(UINT32) /* numRegionRects */
778 	       + 10           /* regionRects + quantQualityVals */
779 	             * havc420->meta.numRegionRects +
780 	       havc420->length;
781 }
782 
783 /**
784  * Function description
785  *
786  * @return TRUE on success
787  */
shadow_client_send_surface_gfx(rdpShadowClient * client,const BYTE * pSrcData,int nSrcStep,int nXSrc,int nYSrc,int nWidth,int nHeight)788 static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE* pSrcData,
789                                            int nSrcStep, int nXSrc, int nYSrc, int nWidth,
790                                            int nHeight)
791 {
792 	UINT error = CHANNEL_RC_OK;
793 	rdpContext* context = (rdpContext*)client;
794 	rdpSettings* settings;
795 	rdpShadowEncoder* encoder;
796 	RDPGFX_SURFACE_COMMAND cmd;
797 	RDPGFX_START_FRAME_PDU cmdstart;
798 	RDPGFX_END_FRAME_PDU cmdend;
799 	SYSTEMTIME sTime;
800 
801 	if (!context || !pSrcData)
802 		return FALSE;
803 
804 	settings = context->settings;
805 	encoder = client->encoder;
806 
807 	if (!settings || !encoder)
808 		return FALSE;
809 
810 	cmdstart.frameId = shadow_encoder_create_frame_id(encoder);
811 	GetSystemTime(&sTime);
812 	cmdstart.timestamp =
813 	    sTime.wHour << 22 | sTime.wMinute << 16 | sTime.wSecond << 10 | sTime.wMilliseconds;
814 	cmdend.frameId = cmdstart.frameId;
815 	cmd.surfaceId = 0;
816 	cmd.codecId = 0;
817 	cmd.contextId = 0;
818 	cmd.format = PIXEL_FORMAT_BGRX32;
819 	cmd.left = nXSrc;
820 	cmd.top = nYSrc;
821 	cmd.right = cmd.left + nWidth;
822 	cmd.bottom = cmd.top + nHeight;
823 	cmd.width = nWidth;
824 	cmd.height = nHeight;
825 	cmd.length = 0;
826 	cmd.data = NULL;
827 	cmd.extra = NULL;
828 
829 	if (settings->GfxAVC444 || settings->GfxAVC444v2)
830 	{
831 		RDPGFX_AVC444_BITMAP_STREAM avc444;
832 		RECTANGLE_16 regionRect;
833 		RDPGFX_H264_QUANT_QUALITY quantQualityVal;
834 		BYTE version = settings->GfxAVC444v2 ? 2 : 1;
835 
836 		if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0)
837 		{
838 			WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_AVC444");
839 			return FALSE;
840 		}
841 
842 		if (avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight, version,
843 		                    &avc444.LC, &avc444.bitstream[0].data, &avc444.bitstream[0].length,
844 		                    &avc444.bitstream[1].data, &avc444.bitstream[1].length) < 0)
845 		{
846 			WLog_ERR(TAG, "avc420_compress failed for avc444");
847 			return FALSE;
848 		}
849 
850 		regionRect.left = cmd.left;
851 		regionRect.top = cmd.top;
852 		regionRect.right = cmd.right;
853 		regionRect.bottom = cmd.bottom;
854 		quantQualityVal.qp = encoder->h264->QP;
855 		quantQualityVal.r = 0;
856 		quantQualityVal.p = 0;
857 		quantQualityVal.qualityVal = 100 - quantQualityVal.qp;
858 		avc444.bitstream[0].meta.numRegionRects = 1;
859 		avc444.bitstream[0].meta.regionRects = &regionRect;
860 		avc444.bitstream[0].meta.quantQualityVals = &quantQualityVal;
861 		avc444.bitstream[1].meta.numRegionRects = 1;
862 		avc444.bitstream[1].meta.regionRects = &regionRect;
863 		avc444.bitstream[1].meta.quantQualityVals = &quantQualityVal;
864 		avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]);
865 		cmd.codecId = settings->GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444;
866 		cmd.extra = (void*)&avc444;
867 		IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
868 		          &cmdend);
869 
870 		if (error)
871 		{
872 			WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
873 			return FALSE;
874 		}
875 	}
876 	else if (settings->GfxH264)
877 	{
878 		RDPGFX_AVC420_BITMAP_STREAM avc420;
879 		RECTANGLE_16 regionRect;
880 		RDPGFX_H264_QUANT_QUALITY quantQualityVal;
881 
882 		if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC420) < 0)
883 		{
884 			WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_AVC420");
885 			return FALSE;
886 		}
887 
888 		if (avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
889 		                    &avc420.data, &avc420.length) < 0)
890 		{
891 			WLog_ERR(TAG, "avc420_compress failed");
892 			return FALSE;
893 		}
894 
895 		cmd.codecId = RDPGFX_CODECID_AVC420;
896 		cmd.extra = (void*)&avc420;
897 		regionRect.left = cmd.left;
898 		regionRect.top = cmd.top;
899 		regionRect.right = cmd.right;
900 		regionRect.bottom = cmd.bottom;
901 		quantQualityVal.qp = encoder->h264->QP;
902 		quantQualityVal.r = 0;
903 		quantQualityVal.p = 0;
904 		quantQualityVal.qualityVal = 100 - quantQualityVal.qp;
905 		avc420.meta.numRegionRects = 1;
906 		avc420.meta.regionRects = &regionRect;
907 		avc420.meta.quantQualityVals = &quantQualityVal;
908 		IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
909 		          &cmdend);
910 
911 		if (error)
912 		{
913 			WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
914 			return FALSE;
915 		}
916 	}
917 
918 	return TRUE;
919 }
920 
921 /**
922  * Function description
923  *
924  * @return TRUE on success
925  */
shadow_client_send_surface_bits(rdpShadowClient * client,BYTE * pSrcData,int nSrcStep,int nXSrc,int nYSrc,int nWidth,int nHeight)926 static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcData, int nSrcStep,
927                                             int nXSrc, int nYSrc, int nWidth, int nHeight)
928 {
929 	BOOL ret = TRUE;
930 	size_t i;
931 	BOOL first;
932 	BOOL last;
933 	wStream* s;
934 	size_t numMessages;
935 	UINT32 frameId = 0;
936 	rdpUpdate* update;
937 	rdpContext* context = (rdpContext*)client;
938 	rdpSettings* settings;
939 	rdpShadowEncoder* encoder;
940 	SURFACE_BITS_COMMAND cmd = { 0 };
941 
942 	if (!context || !pSrcData)
943 		return FALSE;
944 
945 	update = context->update;
946 	settings = context->settings;
947 	encoder = client->encoder;
948 
949 	if (!update || !settings || !encoder)
950 		return FALSE;
951 
952 	if (encoder->frameAck)
953 		frameId = shadow_encoder_create_frame_id(encoder);
954 
955 	if (settings->RemoteFxCodec)
956 	{
957 		RFX_RECT rect;
958 		RFX_MESSAGE* messages;
959 		RFX_RECT* messageRects = NULL;
960 
961 		if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
962 		{
963 			WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
964 			return FALSE;
965 		}
966 
967 		s = encoder->bs;
968 		rect.x = nXSrc;
969 		rect.y = nYSrc;
970 		rect.width = nWidth;
971 		rect.height = nHeight;
972 
973 		if (!(messages = rfx_encode_messages_ex(
974 		          encoder->rfx, &rect, 1, pSrcData, settings->DesktopWidth, settings->DesktopHeight,
975 		          nSrcStep, &numMessages, settings->MultifragMaxRequestSize)))
976 		{
977 			WLog_ERR(TAG, "rfx_encode_messages_ex failed");
978 			return FALSE;
979 		}
980 
981 		cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
982 		cmd.bmp.codecID = settings->RemoteFxCodecId;
983 		cmd.destLeft = 0;
984 		cmd.destTop = 0;
985 		cmd.destRight = settings->DesktopWidth;
986 		cmd.destBottom = settings->DesktopHeight;
987 		cmd.bmp.bpp = 32;
988 		cmd.bmp.flags = 0;
989 		cmd.bmp.width = settings->DesktopWidth;
990 		cmd.bmp.height = settings->DesktopHeight;
991 		cmd.skipCompression = TRUE;
992 
993 		if (numMessages > 0)
994 			messageRects = messages[0].rects;
995 
996 		for (i = 0; i < numMessages; i++)
997 		{
998 			Stream_SetPosition(s, 0);
999 
1000 			if (!rfx_write_message(encoder->rfx, s, &messages[i]))
1001 			{
1002 				while (i < numMessages)
1003 				{
1004 					rfx_message_free(encoder->rfx, &messages[i++]);
1005 				}
1006 
1007 				WLog_ERR(TAG, "rfx_write_message failed");
1008 				ret = FALSE;
1009 				break;
1010 			}
1011 
1012 			rfx_message_free(encoder->rfx, &messages[i]);
1013 			cmd.bmp.bitmapDataLength = Stream_GetPosition(s);
1014 			cmd.bmp.bitmapData = Stream_Buffer(s);
1015 			first = (i == 0) ? TRUE : FALSE;
1016 			last = ((i + 1) == numMessages) ? TRUE : FALSE;
1017 
1018 			if (!encoder->frameAck)
1019 				IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1020 			else
1021 				IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last,
1022 				          frameId);
1023 
1024 			if (!ret)
1025 			{
1026 				WLog_ERR(TAG, "Send surface bits(RemoteFxCodec) failed");
1027 				break;
1028 			}
1029 		}
1030 
1031 		free(messageRects);
1032 		free(messages);
1033 	}
1034 	else if (settings->NSCodec)
1035 	{
1036 		if (shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC) < 0)
1037 		{
1038 			WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_NSCODEC");
1039 			return FALSE;
1040 		}
1041 
1042 		s = encoder->bs;
1043 		Stream_SetPosition(s, 0);
1044 		pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
1045 		nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
1046 		cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
1047 		cmd.bmp.bpp = 32;
1048 		cmd.bmp.codecID = settings->NSCodecId;
1049 		cmd.destLeft = nXSrc;
1050 		cmd.destTop = nYSrc;
1051 		cmd.destRight = cmd.destLeft + nWidth;
1052 		cmd.destBottom = cmd.destTop + nHeight;
1053 		cmd.bmp.width = nWidth;
1054 		cmd.bmp.height = nHeight;
1055 		cmd.bmp.bitmapDataLength = Stream_GetPosition(s);
1056 		cmd.bmp.bitmapData = Stream_Buffer(s);
1057 		first = TRUE;
1058 		last = TRUE;
1059 
1060 		if (!encoder->frameAck)
1061 			IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1062 		else
1063 			IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last, frameId);
1064 
1065 		if (!ret)
1066 		{
1067 			WLog_ERR(TAG, "Send surface bits(NSCodec) failed");
1068 		}
1069 	}
1070 
1071 	return ret;
1072 }
1073 
1074 /**
1075  * Function description
1076  *
1077  * @return TRUE on success
1078  */
shadow_client_send_bitmap_update(rdpShadowClient * client,BYTE * pSrcData,int nSrcStep,int nXSrc,int nYSrc,int nWidth,int nHeight)1079 static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrcData, int nSrcStep,
1080                                              int nXSrc, int nYSrc, int nWidth, int nHeight)
1081 {
1082 	BOOL ret = TRUE;
1083 	BYTE* data;
1084 	BYTE* buffer;
1085 	size_t k;
1086 	int yIdx, xIdx;
1087 	int rows, cols;
1088 	UINT32 DstSize;
1089 	UINT32 SrcFormat;
1090 	BITMAP_DATA* bitmap;
1091 	rdpUpdate* update;
1092 	rdpContext* context = (rdpContext*)client;
1093 	rdpSettings* settings;
1094 	UINT32 maxUpdateSize;
1095 	UINT32 totalBitmapSize;
1096 	UINT32 updateSizeEstimate;
1097 	BITMAP_DATA* bitmapData;
1098 	BITMAP_UPDATE bitmapUpdate;
1099 	rdpShadowEncoder* encoder;
1100 
1101 	if (!context || !pSrcData)
1102 		return FALSE;
1103 
1104 	update = context->update;
1105 	settings = context->settings;
1106 	encoder = client->encoder;
1107 
1108 	if (!update || !settings || !encoder)
1109 		return FALSE;
1110 
1111 	maxUpdateSize = settings->MultifragMaxRequestSize;
1112 
1113 	if (settings->ColorDepth < 32)
1114 	{
1115 		if (shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED) < 0)
1116 		{
1117 			WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_INTERLEAVED");
1118 			return FALSE;
1119 		}
1120 	}
1121 	else
1122 	{
1123 		if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1124 		{
1125 			WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_PLANAR");
1126 			return FALSE;
1127 		}
1128 	}
1129 
1130 	SrcFormat = PIXEL_FORMAT_BGRX32;
1131 
1132 	if ((nXSrc % 4) != 0)
1133 	{
1134 		nWidth += (nXSrc % 4);
1135 		nXSrc -= (nXSrc % 4);
1136 	}
1137 
1138 	if ((nYSrc % 4) != 0)
1139 	{
1140 		nHeight += (nYSrc % 4);
1141 		nYSrc -= (nYSrc % 4);
1142 	}
1143 
1144 	rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
1145 	cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
1146 	k = 0;
1147 	totalBitmapSize = 0;
1148 	bitmapUpdate.count = bitmapUpdate.number = rows * cols;
1149 
1150 	if (!(bitmapData = (BITMAP_DATA*)calloc(bitmapUpdate.number, sizeof(BITMAP_DATA))))
1151 		return FALSE;
1152 
1153 	bitmapUpdate.rectangles = bitmapData;
1154 
1155 	if ((nWidth % 4) != 0)
1156 	{
1157 		nWidth += (4 - (nWidth % 4));
1158 	}
1159 
1160 	if ((nHeight % 4) != 0)
1161 	{
1162 		nHeight += (4 - (nHeight % 4));
1163 	}
1164 
1165 	for (yIdx = 0; yIdx < rows; yIdx++)
1166 	{
1167 		for (xIdx = 0; xIdx < cols; xIdx++)
1168 		{
1169 			bitmap = &bitmapData[k];
1170 			bitmap->width = 64;
1171 			bitmap->height = 64;
1172 			bitmap->destLeft = nXSrc + (xIdx * 64);
1173 			bitmap->destTop = nYSrc + (yIdx * 64);
1174 
1175 			if ((INT64)(bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
1176 				bitmap->width = (UINT32)(nXSrc + nWidth) - bitmap->destLeft;
1177 
1178 			if ((INT64)(bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
1179 				bitmap->height = (UINT32)(nYSrc + nHeight) - bitmap->destTop;
1180 
1181 			bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
1182 			bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
1183 			bitmap->compressed = TRUE;
1184 
1185 			if ((bitmap->width < 4) || (bitmap->height < 4))
1186 				continue;
1187 
1188 			if (settings->ColorDepth < 32)
1189 			{
1190 				int bitsPerPixel = settings->ColorDepth;
1191 				int bytesPerPixel = (bitsPerPixel + 7) / 8;
1192 				DstSize = 64 * 64 * 4;
1193 				buffer = encoder->grid[k];
1194 				interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width,
1195 				                     bitmap->height, pSrcData, SrcFormat, nSrcStep,
1196 				                     bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
1197 				bitmap->bitmapDataStream = buffer;
1198 				bitmap->bitmapLength = DstSize;
1199 				bitmap->bitsPerPixel = bitsPerPixel;
1200 				bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
1201 				bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
1202 			}
1203 			else
1204 			{
1205 				UINT32 dstSize;
1206 				buffer = encoder->grid[k];
1207 				data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
1208 				buffer =
1209 				    freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width,
1210 				                                   bitmap->height, nSrcStep, buffer, &dstSize);
1211 				bitmap->bitmapDataStream = buffer;
1212 				bitmap->bitmapLength = dstSize;
1213 				bitmap->bitsPerPixel = 32;
1214 				bitmap->cbScanWidth = bitmap->width * 4;
1215 				bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
1216 			}
1217 
1218 			bitmap->cbCompFirstRowSize = 0;
1219 			bitmap->cbCompMainBodySize = bitmap->bitmapLength;
1220 			totalBitmapSize += bitmap->bitmapLength;
1221 			k++;
1222 		}
1223 	}
1224 
1225 	bitmapUpdate.count = bitmapUpdate.number = k;
1226 	updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16;
1227 
1228 	if (updateSizeEstimate > maxUpdateSize)
1229 	{
1230 		UINT32 i, j;
1231 		UINT32 updateSize;
1232 		UINT32 newUpdateSize;
1233 		BITMAP_DATA* fragBitmapData = NULL;
1234 
1235 		if (k > 0)
1236 			fragBitmapData = (BITMAP_DATA*)calloc(k, sizeof(BITMAP_DATA));
1237 
1238 		if (!fragBitmapData)
1239 		{
1240 			WLog_ERR(TAG, "Failed to allocate memory for fragBitmapData");
1241 			ret = FALSE;
1242 			goto out;
1243 		}
1244 
1245 		bitmapUpdate.rectangles = fragBitmapData;
1246 		i = j = 0;
1247 		updateSize = 1024;
1248 
1249 		while (i < k)
1250 		{
1251 			newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
1252 
1253 			if (newUpdateSize < maxUpdateSize)
1254 			{
1255 				CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
1256 				updateSize = newUpdateSize;
1257 			}
1258 
1259 			if ((newUpdateSize >= maxUpdateSize) || (i + 1) >= k)
1260 			{
1261 				bitmapUpdate.count = bitmapUpdate.number = j;
1262 				IFCALLRET(update->BitmapUpdate, ret, context, &bitmapUpdate);
1263 
1264 				if (!ret)
1265 				{
1266 					WLog_ERR(TAG, "BitmapUpdate failed");
1267 					break;
1268 				}
1269 
1270 				updateSize = 1024;
1271 				j = 0;
1272 			}
1273 		}
1274 
1275 		free(fragBitmapData);
1276 	}
1277 	else
1278 	{
1279 		IFCALLRET(update->BitmapUpdate, ret, context, &bitmapUpdate);
1280 
1281 		if (!ret)
1282 		{
1283 			WLog_ERR(TAG, "BitmapUpdate failed");
1284 		}
1285 	}
1286 
1287 out:
1288 	free(bitmapData);
1289 	return ret;
1290 }
1291 
1292 /**
1293  * Function description
1294  *
1295  * @return TRUE on success (or nothing need to be updated)
1296  */
shadow_client_send_surface_update(rdpShadowClient * client,SHADOW_GFX_STATUS * pStatus)1297 static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
1298 {
1299 	BOOL ret = TRUE;
1300 	int nXSrc, nYSrc;
1301 	int nWidth, nHeight;
1302 	rdpContext* context = (rdpContext*)client;
1303 	rdpSettings* settings;
1304 	rdpShadowServer* server;
1305 	rdpShadowSurface* surface;
1306 	REGION16 invalidRegion;
1307 	RECTANGLE_16 surfaceRect;
1308 	const RECTANGLE_16* extents;
1309 	BYTE* pSrcData;
1310 	int nSrcStep;
1311 	UINT32 index;
1312 	UINT32 numRects = 0;
1313 	const RECTANGLE_16* rects;
1314 
1315 	if (!context || !pStatus)
1316 		return FALSE;
1317 
1318 	settings = context->settings;
1319 	server = client->server;
1320 
1321 	if (!settings || !server)
1322 		return FALSE;
1323 
1324 	surface = client->inLobby ? server->lobby : server->surface;
1325 
1326 	if (!surface)
1327 		return FALSE;
1328 
1329 	EnterCriticalSection(&(client->lock));
1330 	region16_init(&invalidRegion);
1331 	region16_copy(&invalidRegion, &(client->invalidRegion));
1332 	region16_clear(&(client->invalidRegion));
1333 	LeaveCriticalSection(&(client->lock));
1334 
1335 	EnterCriticalSection(&surface->lock);
1336 	rects = region16_rects(&(surface->invalidRegion), &numRects);
1337 
1338 	for (index = 0; index < numRects; index++)
1339 		region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
1340 
1341 	surfaceRect.left = 0;
1342 	surfaceRect.top = 0;
1343 	surfaceRect.right = surface->width;
1344 	surfaceRect.bottom = surface->height;
1345 	region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
1346 
1347 	if (server->shareSubRect)
1348 	{
1349 		region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
1350 	}
1351 
1352 	if (region16_is_empty(&invalidRegion))
1353 	{
1354 		/* No image region need to be updated. Success */
1355 		goto out;
1356 	}
1357 
1358 	extents = region16_extents(&invalidRegion);
1359 	nXSrc = extents->left;
1360 	nYSrc = extents->top;
1361 	nWidth = extents->right - extents->left;
1362 	nHeight = extents->bottom - extents->top;
1363 	pSrcData = surface->data;
1364 	nSrcStep = surface->scanline;
1365 
1366 	/* Move to new pSrcData / nXSrc / nYSrc according to sub rect */
1367 	if (server->shareSubRect)
1368 	{
1369 		int subX, subY;
1370 		subX = server->subRect.left;
1371 		subY = server->subRect.top;
1372 		nXSrc -= subX;
1373 		nYSrc -= subY;
1374 		pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
1375 	}
1376 
1377 	// WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d
1378 	// bottom: %d", 	nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
1379 
1380 	if (settings->SupportGraphicsPipeline && settings->GfxH264 && pStatus->gfxOpened)
1381 	{
1382 		/* GFX/h264 always full screen encoded */
1383 		nWidth = settings->DesktopWidth;
1384 		nHeight = settings->DesktopHeight;
1385 
1386 		/* Create primary surface if have not */
1387 		if (!pStatus->gfxSurfaceCreated)
1388 		{
1389 			/* Only init surface when we have h264 supported */
1390 			if (!(ret = shadow_client_rdpgfx_reset_graphic(client)))
1391 				goto out;
1392 
1393 			if (!(ret = shadow_client_rdpgfx_new_surface(client)))
1394 				goto out;
1395 
1396 			pStatus->gfxSurfaceCreated = TRUE;
1397 		}
1398 
1399 		ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, 0, 0, nWidth, nHeight);
1400 	}
1401 	else if (settings->RemoteFxCodec || settings->NSCodec)
1402 	{
1403 		ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, nXSrc, nYSrc, nWidth,
1404 		                                      nHeight);
1405 	}
1406 	else
1407 	{
1408 		ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, nXSrc, nYSrc, nWidth,
1409 		                                       nHeight);
1410 	}
1411 
1412 out:
1413 	LeaveCriticalSection(&surface->lock);
1414 	region16_uninit(&invalidRegion);
1415 	return ret;
1416 }
1417 
1418 /**
1419  * Function description
1420  * Notify client for resize. The new desktop width/height
1421  * should have already been updated in rdpSettings.
1422  *
1423  * @return TRUE on success
1424  */
shadow_client_send_resize(rdpShadowClient * client,SHADOW_GFX_STATUS * pStatus)1425 static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
1426 {
1427 	rdpContext* context = (rdpContext*)client;
1428 	rdpSettings* settings;
1429 	freerdp_peer* peer;
1430 
1431 	if (!context || !pStatus)
1432 		return FALSE;
1433 
1434 	peer = context->peer;
1435 	settings = context->settings;
1436 
1437 	if (!peer || !settings)
1438 		return FALSE;
1439 
1440 	/**
1441 	 * Unset client activated flag to avoid sending update message during
1442 	 * resize. DesktopResize will reactive the client and
1443 	 * shadow_client_activate would be invoked later.
1444 	 */
1445 	client->activated = FALSE;
1446 
1447 	/* Close Gfx surfaces */
1448 	if (pStatus->gfxSurfaceCreated)
1449 	{
1450 		if (!shadow_client_rdpgfx_release_surface(client))
1451 			return FALSE;
1452 
1453 		pStatus->gfxSurfaceCreated = FALSE;
1454 	}
1455 
1456 	/* Send Resize */
1457 	if (!peer->update->DesktopResize(peer->update->context))
1458 	{
1459 		WLog_ERR(TAG, "DesktopResize failed");
1460 		return FALSE;
1461 	}
1462 
1463 	/* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */
1464 	EnterCriticalSection(&(client->lock));
1465 	region16_clear(&(client->invalidRegion));
1466 	LeaveCriticalSection(&(client->lock));
1467 	WLog_INFO(TAG, "Client from %s is resized (%" PRIu32 "x%" PRIu32 "@%" PRIu32 ")",
1468 	          peer->hostname, settings->DesktopWidth, settings->DesktopHeight,
1469 	          settings->ColorDepth);
1470 	return TRUE;
1471 }
1472 
1473 /**
1474  * Function description
1475  * Mark invalid region for client
1476  *
1477  * @return TRUE on success
1478  */
shadow_client_surface_update(rdpShadowClient * client,REGION16 * region)1479 static BOOL shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
1480 {
1481 	UINT32 numRects = 0;
1482 	const RECTANGLE_16* rects;
1483 	rects = region16_rects(region, &numRects);
1484 	shadow_client_mark_invalid(client, numRects, rects);
1485 	return TRUE;
1486 }
1487 
1488 /**
1489  * Function description
1490  * Only union invalid region from server surface
1491  *
1492  * @return TRUE on success
1493  */
shadow_client_no_surface_update(rdpShadowClient * client,SHADOW_GFX_STATUS * pStatus)1494 static INLINE BOOL shadow_client_no_surface_update(rdpShadowClient* client,
1495                                                    SHADOW_GFX_STATUS* pStatus)
1496 {
1497 	rdpShadowServer* server;
1498 	rdpShadowSurface* surface;
1499 	WINPR_UNUSED(pStatus);
1500 	server = client->server;
1501 	surface = client->inLobby ? server->lobby : server->surface;
1502 	return shadow_client_surface_update(client, &(surface->invalidRegion));
1503 }
1504 
shadow_client_subsystem_process_message(rdpShadowClient * client,wMessage * message)1505 static int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
1506 {
1507 	rdpContext* context = (rdpContext*)client;
1508 	rdpUpdate* update = context->update;
1509 
1510 	/* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */
1511 
1512 	switch (message->id)
1513 	{
1514 		case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
1515 		{
1516 			POINTER_POSITION_UPDATE pointerPosition;
1517 			SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg =
1518 			    (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*)message->wParam;
1519 			pointerPosition.xPos = msg->xPos;
1520 			pointerPosition.yPos = msg->yPos;
1521 
1522 			if (client->server->shareSubRect)
1523 			{
1524 				pointerPosition.xPos -= client->server->subRect.left;
1525 				pointerPosition.yPos -= client->server->subRect.top;
1526 			}
1527 
1528 			if (client->activated)
1529 			{
1530 				if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
1531 				{
1532 					IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
1533 					client->pointerX = msg->xPos;
1534 					client->pointerY = msg->yPos;
1535 				}
1536 			}
1537 
1538 			break;
1539 		}
1540 
1541 		case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
1542 		{
1543 			POINTER_NEW_UPDATE pointerNew;
1544 			POINTER_COLOR_UPDATE* pointerColor;
1545 			POINTER_CACHED_UPDATE pointerCached;
1546 			SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg =
1547 			    (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*)message->wParam;
1548 			ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE));
1549 			pointerNew.xorBpp = 24;
1550 			pointerColor = &(pointerNew.colorPtrAttr);
1551 			pointerColor->cacheIndex = 0;
1552 			pointerColor->xPos = msg->xHot;
1553 			pointerColor->yPos = msg->yHot;
1554 			pointerColor->width = msg->width;
1555 			pointerColor->height = msg->height;
1556 			pointerColor->lengthAndMask = msg->lengthAndMask;
1557 			pointerColor->lengthXorMask = msg->lengthXorMask;
1558 			pointerColor->xorMaskData = msg->xorMaskData;
1559 			pointerColor->andMaskData = msg->andMaskData;
1560 			pointerCached.cacheIndex = pointerColor->cacheIndex;
1561 
1562 			if (client->activated)
1563 			{
1564 				IFCALL(update->pointer->PointerNew, context, &pointerNew);
1565 				IFCALL(update->pointer->PointerCached, context, &pointerCached);
1566 			}
1567 
1568 			break;
1569 		}
1570 
1571 		case SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES_ID:
1572 		{
1573 			SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES* msg =
1574 			    (SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES*)message->wParam;
1575 
1576 			if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
1577 			{
1578 				client->rdpsnd->src_format = msg->audio_format;
1579 				IFCALL(client->rdpsnd->SendSamples, client->rdpsnd, msg->buf, msg->nFrames,
1580 				       msg->wTimestamp);
1581 			}
1582 
1583 			break;
1584 		}
1585 
1586 		case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
1587 		{
1588 			SHADOW_MSG_OUT_AUDIO_OUT_VOLUME* msg =
1589 			    (SHADOW_MSG_OUT_AUDIO_OUT_VOLUME*)message->wParam;
1590 
1591 			if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
1592 			{
1593 				IFCALL(client->rdpsnd->SetVolume, client->rdpsnd, msg->left, msg->right);
1594 			}
1595 
1596 			break;
1597 		}
1598 
1599 		default:
1600 			WLog_ERR(TAG, "Unknown message id: %" PRIu32 "", message->id);
1601 			break;
1602 	}
1603 
1604 	shadow_client_free_queued_message(message);
1605 	return 1;
1606 }
1607 
shadow_client_thread(LPVOID arg)1608 static DWORD WINAPI shadow_client_thread(LPVOID arg)
1609 {
1610 	rdpShadowClient* client = (rdpShadowClient*)arg;
1611 	DWORD status;
1612 	DWORD nCount;
1613 	wMessage message;
1614 	wMessage pointerPositionMsg;
1615 	wMessage pointerAlphaMsg;
1616 	wMessage audioVolumeMsg;
1617 	HANDLE events[32];
1618 	HANDLE ChannelEvent;
1619 	void* UpdateSubscriber;
1620 	HANDLE UpdateEvent;
1621 	freerdp_peer* peer;
1622 	rdpContext* context;
1623 	rdpSettings* settings;
1624 	rdpShadowServer* server;
1625 	rdpShadowSubsystem* subsystem;
1626 	wMessageQueue* MsgQueue = client->MsgQueue;
1627 	/* This should only be visited in client thread */
1628 	SHADOW_GFX_STATUS gfxstatus;
1629 	gfxstatus.gfxOpened = FALSE;
1630 	gfxstatus.gfxSurfaceCreated = FALSE;
1631 	server = client->server;
1632 	subsystem = server->subsystem;
1633 	context = (rdpContext*)client;
1634 	peer = context->peer;
1635 	settings = peer->settings;
1636 	peer->Capabilities = shadow_client_capabilities;
1637 	peer->PostConnect = shadow_client_post_connect;
1638 	peer->Activate = shadow_client_activate;
1639 	peer->Logon = shadow_client_logon;
1640 	shadow_input_register_callbacks(peer->input);
1641 	peer->Initialize(peer);
1642 	peer->update->RefreshRect = shadow_client_refresh_rect;
1643 	peer->update->SuppressOutput = shadow_client_suppress_output;
1644 	peer->update->SurfaceFrameAcknowledge = shadow_client_surface_frame_acknowledge;
1645 
1646 	if ((!client->vcm) || (!subsystem->updateEvent))
1647 		goto out;
1648 
1649 	UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
1650 
1651 	if (!UpdateSubscriber)
1652 		goto out;
1653 
1654 	UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
1655 	ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
1656 
1657 	while (1)
1658 	{
1659 		nCount = 0;
1660 		events[nCount++] = UpdateEvent;
1661 		{
1662 			DWORD tmp = peer->GetEventHandles(peer, &events[nCount], 64 - nCount);
1663 
1664 			if (tmp == 0)
1665 			{
1666 				WLog_ERR(TAG, "Failed to get FreeRDP transport event handles");
1667 				goto fail;
1668 			}
1669 
1670 			nCount += tmp;
1671 		}
1672 		events[nCount++] = ChannelEvent;
1673 		events[nCount++] = MessageQueue_Event(MsgQueue);
1674 		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1675 
1676 		if (status == WAIT_FAILED)
1677 			goto fail;
1678 
1679 		if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
1680 		{
1681 			/* The UpdateEvent means to start sending current frame. It is
1682 			 * triggered from subsystem implementation and it should ensure
1683 			 * that the screen and primary surface meta data (width, height,
1684 			 * scanline, invalid region, etc) is not changed until it is reset
1685 			 * (at shadow_multiclient_consume). As best practice, subsystem
1686 			 * implementation should invoke shadow_subsystem_frame_update which
1687 			 * triggers the event and then wait for completion */
1688 			if (client->activated && !client->suppressOutput)
1689 			{
1690 				/* Send screen update or resize to this client */
1691 
1692 				/* Check resize */
1693 				if (shadow_client_recalc_desktop_size(client))
1694 				{
1695 					/* Screen size changed, do resize */
1696 					if (!shadow_client_send_resize(client, &gfxstatus))
1697 					{
1698 						WLog_ERR(TAG, "Failed to send resize message");
1699 						break;
1700 					}
1701 				}
1702 				else
1703 				{
1704 					/* Send frame */
1705 					if (!shadow_client_send_surface_update(client, &gfxstatus))
1706 					{
1707 						WLog_ERR(TAG, "Failed to send surface update");
1708 						break;
1709 					}
1710 				}
1711 			}
1712 			else
1713 			{
1714 				/* Our client don't receive graphic updates. Just save the invalid region */
1715 				if (!shadow_client_no_surface_update(client, &gfxstatus))
1716 				{
1717 					WLog_ERR(TAG, "Failed to handle surface update");
1718 					break;
1719 				}
1720 			}
1721 
1722 			/*
1723 			 * The return value of shadow_multiclient_consume is whether or not
1724 			 * the subscriber really consumes the event. It's not cared currently.
1725 			 */
1726 			(void)shadow_multiclient_consume(UpdateSubscriber);
1727 		}
1728 
1729 		if (!peer->CheckFileDescriptor(peer))
1730 		{
1731 			WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
1732 			goto fail;
1733 		}
1734 		else
1735 		{
1736 			if (WTSVirtualChannelManagerIsChannelJoined(client->vcm, "drdynvc"))
1737 			{
1738 				switch (WTSVirtualChannelManagerGetDrdynvcState(client->vcm))
1739 				{
1740 					/* Dynamic channel status may have been changed after processing */
1741 					case DRDYNVC_STATE_NONE:
1742 
1743 						/* Call this routine to Initialize drdynvc channel */
1744 						if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
1745 						{
1746 							WLog_ERR(TAG, "Failed to initialize drdynvc channel");
1747 							goto fail;
1748 						}
1749 
1750 						break;
1751 
1752 					case DRDYNVC_STATE_READY:
1753 						if (client->audin &&
1754 						    !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
1755 						{
1756 							if (!IFCALLRESULT(FALSE, client->audin->Open, client->audin))
1757 							{
1758 								WLog_ERR(TAG, "Failed to initialize audin channel");
1759 								goto fail;
1760 							}
1761 						}
1762 
1763 						/* Init RDPGFX dynamic channel */
1764 						if (settings->SupportGraphicsPipeline && client->rdpgfx &&
1765 						    !gfxstatus.gfxOpened)
1766 						{
1767 							client->rdpgfx->FrameAcknowledge =
1768 							    shadow_client_rdpgfx_frame_acknowledge;
1769 							client->rdpgfx->CapsAdvertise = shadow_client_rdpgfx_caps_advertise;
1770 
1771 							if (!client->rdpgfx->Open(client->rdpgfx))
1772 							{
1773 								WLog_WARN(TAG, "Failed to open GraphicsPipeline");
1774 								settings->SupportGraphicsPipeline = FALSE;
1775 							}
1776 
1777 							gfxstatus.gfxOpened = TRUE;
1778 							WLog_INFO(TAG, "Gfx Pipeline Opened");
1779 						}
1780 
1781 						break;
1782 
1783 					default:
1784 						break;
1785 				}
1786 			}
1787 		}
1788 
1789 		if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
1790 		{
1791 			if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
1792 			{
1793 				WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
1794 				goto fail;
1795 			}
1796 		}
1797 
1798 		if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
1799 		{
1800 			/* Drain messages. Pointer update could be accumulated. */
1801 			pointerPositionMsg.id = 0;
1802 			pointerPositionMsg.Free = NULL;
1803 			pointerAlphaMsg.id = 0;
1804 			pointerAlphaMsg.Free = NULL;
1805 			audioVolumeMsg.id = 0;
1806 			audioVolumeMsg.Free = NULL;
1807 
1808 			while (MessageQueue_Peek(MsgQueue, &message, TRUE))
1809 			{
1810 				if (message.id == WMQ_QUIT)
1811 				{
1812 					break;
1813 				}
1814 
1815 				switch (message.id)
1816 				{
1817 					case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
1818 						/* Abandon previous message */
1819 						shadow_client_free_queued_message(&pointerPositionMsg);
1820 						CopyMemory(&pointerPositionMsg, &message, sizeof(wMessage));
1821 						break;
1822 
1823 					case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
1824 						/* Abandon previous message */
1825 						shadow_client_free_queued_message(&pointerAlphaMsg);
1826 						CopyMemory(&pointerAlphaMsg, &message, sizeof(wMessage));
1827 						break;
1828 
1829 					case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
1830 						/* Abandon previous message */
1831 						shadow_client_free_queued_message(&audioVolumeMsg);
1832 						CopyMemory(&audioVolumeMsg, &message, sizeof(wMessage));
1833 						break;
1834 
1835 					default:
1836 						shadow_client_subsystem_process_message(client, &message);
1837 						break;
1838 				}
1839 			}
1840 
1841 			if (message.id == WMQ_QUIT)
1842 			{
1843 				/* Release stored message */
1844 				shadow_client_free_queued_message(&pointerPositionMsg);
1845 				shadow_client_free_queued_message(&pointerAlphaMsg);
1846 				shadow_client_free_queued_message(&audioVolumeMsg);
1847 				goto fail;
1848 			}
1849 			else
1850 			{
1851 				/* Process accumulated messages if needed */
1852 				if (pointerPositionMsg.id)
1853 				{
1854 					shadow_client_subsystem_process_message(client, &pointerPositionMsg);
1855 				}
1856 
1857 				if (pointerAlphaMsg.id)
1858 				{
1859 					shadow_client_subsystem_process_message(client, &pointerAlphaMsg);
1860 				}
1861 
1862 				if (audioVolumeMsg.id)
1863 				{
1864 					shadow_client_subsystem_process_message(client, &audioVolumeMsg);
1865 				}
1866 			}
1867 		}
1868 	}
1869 
1870 fail:
1871 
1872 	/* Free channels early because we establish channels in post connect */
1873 	if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
1874 	{
1875 		if (!IFCALLRESULT(FALSE, client->audin->Close, client->audin))
1876 		{
1877 			WLog_WARN(TAG, "AUDIN shutdown failure!");
1878 		}
1879 	}
1880 
1881 	if (gfxstatus.gfxOpened)
1882 	{
1883 		if (gfxstatus.gfxSurfaceCreated)
1884 		{
1885 			if (!shadow_client_rdpgfx_release_surface(client))
1886 				WLog_WARN(TAG, "GFX release surface failure!");
1887 		}
1888 
1889 		(void)client->rdpgfx->Close(client->rdpgfx);
1890 	}
1891 
1892 	shadow_client_channels_free(client);
1893 
1894 	if (UpdateSubscriber)
1895 	{
1896 		shadow_multiclient_release_subscriber(UpdateSubscriber);
1897 		UpdateSubscriber = NULL;
1898 	}
1899 
1900 	if (peer->connected && subsystem->ClientDisconnect)
1901 	{
1902 		subsystem->ClientDisconnect(subsystem, client);
1903 	}
1904 
1905 out:
1906 	peer->Disconnect(peer);
1907 	freerdp_peer_context_free(peer);
1908 	freerdp_peer_free(peer);
1909 	ExitThread(0);
1910 	return 0;
1911 }
1912 
shadow_client_accepted(freerdp_listener * listener,freerdp_peer * peer)1913 BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
1914 {
1915 	rdpShadowClient* client;
1916 	rdpShadowServer* server;
1917 
1918 	if (!listener || !peer)
1919 		return FALSE;
1920 
1921 	server = (rdpShadowServer*)listener->info;
1922 	peer->ContextExtra = (void*)server;
1923 	peer->ContextSize = sizeof(rdpShadowClient);
1924 	peer->ContextNew = (psPeerContextNew)shadow_client_context_new;
1925 	peer->ContextFree = (psPeerContextFree)shadow_client_context_free;
1926 	peer->settings = freerdp_settings_clone(server->settings);
1927 
1928 	if (!freerdp_peer_context_new(peer))
1929 		return FALSE;
1930 
1931 	client = (rdpShadowClient*)peer->context;
1932 
1933 	if (!(client->thread = CreateThread(NULL, 0, shadow_client_thread, client, 0, NULL)))
1934 	{
1935 		freerdp_peer_context_free(peer);
1936 		return FALSE;
1937 	}
1938 	else
1939 	{
1940 		/* Close the thread handle to make it detached. */
1941 		CloseHandle(client->thread);
1942 		client->thread = NULL;
1943 	}
1944 
1945 	return TRUE;
1946 }
1947 
shadow_msg_out_addref(wMessage * message)1948 static void shadow_msg_out_addref(wMessage* message)
1949 {
1950 	SHADOW_MSG_OUT* msg = (SHADOW_MSG_OUT*)message->wParam;
1951 	InterlockedIncrement(&(msg->refCount));
1952 }
1953 
shadow_msg_out_release(wMessage * message)1954 static void shadow_msg_out_release(wMessage* message)
1955 {
1956 	SHADOW_MSG_OUT* msg = (SHADOW_MSG_OUT*)message->wParam;
1957 
1958 	if (InterlockedDecrement(&(msg->refCount)) <= 0)
1959 	{
1960 		if (msg->Free)
1961 			msg->Free(message->id, msg);
1962 	}
1963 }
1964 
shadow_client_dispatch_msg(rdpShadowClient * client,wMessage * message)1965 static BOOL shadow_client_dispatch_msg(rdpShadowClient* client, wMessage* message)
1966 {
1967 	if (!client || !message)
1968 		return FALSE;
1969 
1970 	/* Add reference when it is posted */
1971 	shadow_msg_out_addref(message);
1972 
1973 	if (MessageQueue_Dispatch(client->MsgQueue, message))
1974 		return TRUE;
1975 	else
1976 	{
1977 		/* Release the reference since post failed */
1978 		shadow_msg_out_release(message);
1979 		return FALSE;
1980 	}
1981 }
1982 
shadow_client_post_msg(rdpShadowClient * client,void * context,UINT32 type,SHADOW_MSG_OUT * msg,void * lParam)1983 BOOL shadow_client_post_msg(rdpShadowClient* client, void* context, UINT32 type,
1984                             SHADOW_MSG_OUT* msg, void* lParam)
1985 {
1986 	wMessage message = { 0 };
1987 	message.context = context;
1988 	message.id = type;
1989 	message.wParam = (void*)msg;
1990 	message.lParam = lParam;
1991 	message.Free = shadow_msg_out_release;
1992 	return shadow_client_dispatch_msg(client, &message);
1993 }
1994 
shadow_client_boardcast_msg(rdpShadowServer * server,void * context,UINT32 type,SHADOW_MSG_OUT * msg,void * lParam)1995 int shadow_client_boardcast_msg(rdpShadowServer* server, void* context, UINT32 type,
1996                                 SHADOW_MSG_OUT* msg, void* lParam)
1997 {
1998 	wMessage message = { 0 };
1999 	rdpShadowClient* client = NULL;
2000 	int count = 0;
2001 	int index = 0;
2002 	message.context = context;
2003 	message.id = type;
2004 	message.wParam = (void*)msg;
2005 	message.lParam = lParam;
2006 	message.Free = shadow_msg_out_release;
2007 	/* First add reference as we reference it in this function.
2008 	 * Therefore it would not be free'ed during post. */
2009 	shadow_msg_out_addref(&message);
2010 	ArrayList_Lock(server->clients);
2011 
2012 	for (index = 0; index < ArrayList_Count(server->clients); index++)
2013 	{
2014 		client = (rdpShadowClient*)ArrayList_GetItem(server->clients, index);
2015 
2016 		if (shadow_client_dispatch_msg(client, &message))
2017 		{
2018 			count++;
2019 		}
2020 	}
2021 
2022 	ArrayList_Unlock(server->clients);
2023 	/* Release the reference for this function */
2024 	shadow_msg_out_release(&message);
2025 	return count;
2026 }
2027 
shadow_client_boardcast_quit(rdpShadowServer * server,int nExitCode)2028 int shadow_client_boardcast_quit(rdpShadowServer* server, int nExitCode)
2029 {
2030 	wMessageQueue* queue = NULL;
2031 	int count = 0;
2032 	int index = 0;
2033 	ArrayList_Lock(server->clients);
2034 
2035 	for (index = 0; index < ArrayList_Count(server->clients); index++)
2036 	{
2037 		queue = ((rdpShadowClient*)ArrayList_GetItem(server->clients, index))->MsgQueue;
2038 
2039 		if (MessageQueue_PostQuit(queue, nExitCode))
2040 		{
2041 			count++;
2042 		}
2043 	}
2044 
2045 	ArrayList_Unlock(server->clients);
2046 	return count;
2047 }
2048