96aea63a9fd5a7d404a7e0fb901d13ff8fa7e749
[platform/upstream/freerdp.git] / server / shadow / shadow_client.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/file.h>
25 #include <winpr/path.h>
26 #include <winpr/synch.h>
27 #include <winpr/thread.h>
28 #include <winpr/sysinfo.h>
29
30 #include <freerdp/log.h>
31
32 #include "shadow.h"
33
34 #define TAG CLIENT_TAG("shadow")
35
36 void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
37 {
38         rdpSettings* settings;
39         rdpShadowServer* server;
40
41         server = (rdpShadowServer*) peer->ContextExtra;
42         client->server = server;
43         client->subsystem = server->subsystem;
44
45         settings = peer->settings;
46
47         settings->ColorDepth = 32;
48         settings->NSCodec = TRUE;
49         settings->RemoteFxCodec = TRUE;
50         settings->BitmapCacheV3Enabled = TRUE;
51         settings->FrameMarkerCommandEnabled = TRUE;
52         settings->SurfaceFrameMarkerEnabled = TRUE;
53
54         settings->RdpSecurity = TRUE;
55         settings->TlsSecurity = TRUE;
56         settings->NlaSecurity = FALSE;
57
58         settings->CertificateFile = _strdup(server->CertificateFile);
59         settings->PrivateKeyFile = _strdup(server->PrivateKeyFile);
60
61         settings->RdpKeyFile = _strdup(settings->PrivateKeyFile);
62
63         client->inLobby = TRUE;
64         client->mayView = server->mayView;
65         client->mayInteract = server->mayInteract;
66
67         InitializeCriticalSectionAndSpinCount(&(client->lock), 4000);
68
69         region16_init(&(client->invalidRegion));
70
71         client->vcm = WTSOpenServerA((LPSTR) peer->context);
72
73         client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
74
75         client->encoder = shadow_encoder_new(client);
76
77         ArrayList_Add(server->clients, (void*) client);
78 }
79
80 void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
81 {
82         rdpShadowServer* server = client->server;
83
84         ArrayList_Remove(server->clients, (void*) client);
85
86         DeleteCriticalSection(&(client->lock));
87
88         region16_uninit(&(client->invalidRegion));
89
90         WTSCloseServer((HANDLE) client->vcm);
91
92         CloseHandle(client->StopEvent);
93
94         if (client->lobby)
95         {
96                 shadow_surface_free(client->lobby);
97                 client->lobby = NULL;
98         }
99
100         if (client->encoder)
101         {
102                 shadow_encoder_free(client->encoder);
103                 client->encoder = NULL;
104         }
105 }
106
107 void shadow_client_message_free(wMessage* message)
108 {
109         if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
110         {
111                 SHADOW_MSG_IN_REFRESH_OUTPUT* wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
112
113                 free(wParam->rects);
114                 free(wParam);
115         }
116         else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
117         {
118                 SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
119                 free(wParam);
120         }
121 }
122
123 BOOL shadow_client_capabilities(freerdp_peer* peer)
124 {
125         return TRUE;
126 }
127
128 BOOL shadow_client_post_connect(freerdp_peer* peer)
129 {
130         int width, height;
131         rdpSettings* settings;
132         rdpShadowClient* client;
133         rdpShadowSurface* lobby;
134         rdpShadowServer* server;
135         RECTANGLE_16 invalidRect;
136
137         client = (rdpShadowClient*) peer->context;
138         settings = peer->settings;
139         server = client->server;
140
141         if (!server->shareSubRect)
142         {
143                 width = server->screen->width;
144                 height = server->screen->height;
145         }
146         else
147         {
148                 width = server->subRect.right - server->subRect.left;
149                 height = server->subRect.bottom - server->subRect.top;
150         }
151
152         settings->DesktopWidth = width;
153         settings->DesktopHeight = height;
154
155         if (settings->ColorDepth == 24)
156                 settings->ColorDepth = 16; /* disable 24bpp */
157
158         WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)",
159                         peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
160
161         peer->update->DesktopResize(peer->update->context);
162
163         shadow_client_channels_post_connect(client);
164
165         invalidRect.left = 0;
166         invalidRect.top = 0;
167         invalidRect.right = width;
168         invalidRect.bottom = height;
169
170         region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect);
171
172         lobby = client->lobby = shadow_surface_new(client->server, 0, 0, width, height);
173
174         if (!client->lobby)
175                 return FALSE;
176
177         freerdp_image_fill(lobby->data, PIXEL_FORMAT_XRGB32, lobby->scanline,
178                         0, 0, lobby->width, lobby->height, 0x3BB9FF);
179
180         region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect);
181
182         return TRUE;
183 }
184
185 void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
186 {
187         wMessage message = { 0 };
188         SHADOW_MSG_IN_REFRESH_OUTPUT* wParam;
189         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
190
191         wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT));
192
193         if (!wParam)
194                 return;
195
196         wParam->numRects = (UINT32) count;
197
198         if (wParam->numRects)
199         {
200                 wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16));
201
202                 if (!wParam->rects)
203                         return;
204         }
205
206         CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
207
208         message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
209         message.wParam = (void*) wParam;
210         message.lParam = NULL;
211         message.context = (void*) client;
212         message.Free = shadow_client_message_free;
213
214         MessageQueue_Dispatch(MsgPipe->In, &message);
215 }
216
217 void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
218 {
219         wMessage message = { 0 };
220         SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam;
221         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
222
223         wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT));
224
225         if (!wParam)
226                 return;
227
228         wParam->allow = (UINT32) allow;
229
230         if (area)
231                 CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
232
233         message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
234         message.wParam = (void*) wParam;
235         message.lParam = NULL;
236         message.context = (void*) client;
237         message.Free = shadow_client_message_free;
238
239         MessageQueue_Dispatch(MsgPipe->In, &message);
240 }
241
242 BOOL shadow_client_activate(freerdp_peer* peer)
243 {
244         rdpShadowClient* client;
245
246         client = (rdpShadowClient*) peer->context;
247
248         client->activated = TRUE;
249         client->inLobby = client->mayView ? FALSE : TRUE;
250
251         shadow_encoder_reset(client->encoder);
252
253         shadow_client_refresh_rect(client, 0, NULL);
254
255         return TRUE;
256 }
257
258 void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
259 {
260         SURFACE_FRAME* frame;
261         wListDictionary* frameList;
262
263         frameList = client->encoder->frameList;
264         frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
265
266         if (frame)
267         {
268                 ListDictionary_Remove(frameList, (void*) (size_t) frameId);
269                 free(frame);
270         }
271 }
272
273 int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id)
274 {
275         SURFACE_FRAME_MARKER surfaceFrameMarker;
276         rdpContext* context = (rdpContext*) client;
277         rdpUpdate* update = context->update;
278
279         surfaceFrameMarker.frameAction = action;
280         surfaceFrameMarker.frameId = id;
281
282         IFCALL(update->SurfaceFrameMarker, context, &surfaceFrameMarker);
283
284         return 1;
285 }
286
287 int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
288 {
289         int i;
290         BOOL first;
291         BOOL last;
292         wStream* s;
293         int nSrcStep;
294         BYTE* pSrcData;
295         int numMessages;
296         UINT32 frameId = 0;
297         rdpUpdate* update;
298         rdpContext* context;
299         rdpSettings* settings;
300         rdpShadowServer* server;
301         rdpShadowEncoder* encoder;
302         SURFACE_BITS_COMMAND cmd;
303
304         context = (rdpContext*) client;
305         update = context->update;
306         settings = context->settings;
307
308         server = client->server;
309         encoder = client->encoder;
310
311         pSrcData = surface->data;
312         nSrcStep = surface->scanline;
313
314         if (server->shareSubRect)
315         {
316                 int subX, subY;
317                 int subWidth, subHeight;
318
319                 subX = server->subRect.left;
320                 subY = server->subRect.top;
321                 subWidth = server->subRect.right - server->subRect.left;
322                 subHeight = server->subRect.bottom - server->subRect.top;
323
324                 nXSrc -= subX;
325                 nYSrc -= subY;
326                 pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
327         }
328
329         if (encoder->frameAck)
330                 frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
331
332         if (settings->RemoteFxCodec)
333         {
334                 RFX_RECT rect;
335                 RFX_MESSAGE* messages;
336
337                 s = encoder->bs;
338
339                 rect.x = nXSrc;
340                 rect.y = nYSrc;
341                 rect.width = nWidth;
342                 rect.height = nHeight;
343
344                 messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
345                                 surface->width, surface->height, nSrcStep, &numMessages,
346                                 settings->MultifragMaxRequestSize);
347
348                 cmd.codecID = settings->RemoteFxCodecId;
349
350                 cmd.destLeft = 0;
351                 cmd.destTop = 0;
352                 cmd.destRight = surface->width;
353                 cmd.destBottom = surface->height;
354
355                 cmd.bpp = 32;
356                 cmd.width = surface->width;
357                 cmd.height = surface->height;
358
359                 for (i = 0; i < numMessages; i++)
360                 {
361                         Stream_SetPosition(s, 0);
362                         rfx_write_message(encoder->rfx, s, &messages[i]);
363                         rfx_message_free(encoder->rfx, &messages[i]);
364
365                         cmd.bitmapDataLength = Stream_GetPosition(s);
366                         cmd.bitmapData = Stream_Buffer(s);
367
368                         first = (i == 0) ? TRUE : FALSE;
369                         last = ((i + 1) == numMessages) ? TRUE : FALSE;
370
371                         if (!encoder->frameAck)
372                                 IFCALL(update->SurfaceBits, update->context, &cmd);
373                         else
374                                 IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
375                 }
376
377                 free(messages);
378         }
379         else if (settings->NSCodec)
380         {
381                 NSC_MESSAGE* messages;
382
383                 s = encoder->bs;
384
385                 messages = nsc_encode_messages(encoder->nsc, pSrcData,
386                                 nXSrc, nYSrc, nWidth, nHeight, nSrcStep,
387                                 &numMessages, settings->MultifragMaxRequestSize);
388
389                 cmd.bpp = 32;
390                 cmd.codecID = settings->NSCodecId;
391
392                 for (i = 0; i < numMessages; i++)
393                 {
394                         Stream_SetPosition(s, 0);
395
396                         nsc_write_message(encoder->nsc, s, &messages[i]);
397                         nsc_message_free(encoder->nsc, &messages[i]);
398
399                         cmd.destLeft = messages[i].x;
400                         cmd.destTop = messages[i].y;
401                         cmd.destRight = messages[i].x + messages[i].width;
402                         cmd.destBottom = messages[i].y + messages[i].height;
403                         cmd.width = messages[i].width;
404                         cmd.height = messages[i].height;
405
406                         cmd.bitmapDataLength = Stream_GetPosition(s);
407                         cmd.bitmapData = Stream_Buffer(s);
408
409                         first = (i == 0) ? TRUE : FALSE;
410                         last = ((i + 1) == numMessages) ? TRUE : FALSE;
411
412                         if (!encoder->frameAck)
413                                 IFCALL(update->SurfaceBits, update->context, &cmd);
414                         else
415                                 IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
416                 }
417
418                 free(messages);
419         }
420
421         return 1;
422 }
423
424 int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
425 {
426         BYTE* data;
427         BYTE* buffer;
428         int i, j, k;
429         wStream* s;
430         wStream* ts;
431         int e, lines;
432         int rows, cols;
433         int nSrcStep;
434         BYTE* pSrcData;
435         rdpUpdate* update;
436         rdpContext* context;
437         rdpSettings* settings;
438         int MaxRegionWidth;
439         int MaxRegionHeight;
440         BITMAP_DATA* bitmapData;
441         BITMAP_UPDATE bitmapUpdate;
442         rdpShadowServer* server;
443         rdpShadowEncoder* encoder;
444
445         context = (rdpContext*) client;
446         update = context->update;
447         settings = context->settings;
448
449         server = client->server;
450         encoder = client->encoder;
451
452         pSrcData = surface->data;
453         nSrcStep = surface->scanline;
454
455         MaxRegionWidth = 64 * 4;
456         MaxRegionHeight = 64 * 1;
457
458         if ((nXSrc % 4) != 0)
459         {
460                 nWidth += (nXSrc % 4);
461                 nXSrc -= (nXSrc % 4);
462         }
463
464         if ((nYSrc % 4) != 0)
465         {
466                 nHeight += (nYSrc % 4);
467                 nYSrc -= (nYSrc % 4);
468         }
469
470         if ((nWidth * nHeight) > (MaxRegionWidth * MaxRegionHeight))
471         {
472                 int nXSrcSub;
473                 int nYSrcSub;
474                 int nWidthSub;
475                 int nHeightSub;
476                 rows = (nWidth + (MaxRegionWidth - (nWidth % MaxRegionWidth))) / MaxRegionWidth;
477                 cols = (nHeight + (MaxRegionHeight - (nHeight % MaxRegionHeight))) / MaxRegionHeight;
478
479                 for (i = 0; i < rows; i++)
480                 {
481                         for (j = 0; j < cols; j++)
482                         {
483                                 nXSrcSub = nXSrc + (i * MaxRegionWidth);
484                                 nYSrcSub = nYSrc + (j * MaxRegionHeight);
485
486                                 nWidthSub = (i < (rows - 1)) ? MaxRegionWidth : nWidth - (i * MaxRegionWidth);
487                                 nHeightSub = (j < (cols - 1)) ? MaxRegionHeight : nHeight - (j * MaxRegionHeight);
488
489                                 if ((nWidthSub * nHeightSub) > 0)
490                                 {
491                                         shadow_client_send_bitmap_update(client, surface, nXSrcSub, nYSrcSub, nWidthSub, nHeightSub);
492                                 }
493                         }
494                 }
495
496                 return 1;
497         }
498
499         rows = (nWidth + (64 - (nWidth % 64))) / 64;
500         cols = (nHeight + (64 - (nHeight % 64))) / 64;
501
502         k = 0;
503         bitmapUpdate.count = bitmapUpdate.number = rows * cols;
504         bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number);
505         bitmapUpdate.rectangles = bitmapData;
506
507         if (!bitmapData)
508                 return -1;
509
510         if ((nWidth % 4) != 0)
511         {
512                 nXSrc -= (nWidth % 4);
513                 nWidth += (nWidth % 4);
514         }
515
516         if ((nHeight % 4) != 0)
517         {
518                 nYSrc -= (nHeight % 4);
519                 nHeight += (nHeight % 4);
520         }
521
522         for (i = 0; i < rows; i++)
523         {
524                 for (j = 0; j < cols; j++)
525                 {
526                         nWidth = (i < (rows - 1)) ? 64 : nWidth - (i * 64);
527                         nHeight = (j < (cols - 1)) ? 64 : nHeight - (j * 64);
528
529                         bitmapData[k].bitsPerPixel = 16;
530                         bitmapData[k].width = nWidth;
531                         bitmapData[k].height = nHeight;
532                         bitmapData[k].destLeft = nXSrc + (i * 64);
533                         bitmapData[k].destTop = nYSrc + (j * 64);
534                         bitmapData[k].destRight = bitmapData[k].destLeft + nWidth - 1;
535                         bitmapData[k].destBottom = bitmapData[k].destTop + nHeight - 1;
536                         bitmapData[k].compressed = TRUE;
537
538                         if (((nWidth * nHeight) > 0) && (nWidth >= 4) && (nHeight >= 4))
539                         {
540                                 UINT32 srcFormat = PIXEL_FORMAT_RGB32;
541
542                                 e = nWidth % 4;
543
544                                 if (e != 0)
545                                         e = 4 - e;
546
547                                 s = encoder->bs;
548                                 ts = encoder->bts;
549
550                                 Stream_SetPosition(s, 0);
551                                 Stream_SetPosition(ts, 0);
552
553                                 data = surface->data;
554                                 data = &data[(bitmapData[k].destTop * nSrcStep) +
555                                              (bitmapData[k].destLeft * 4)];
556
557                                 srcFormat = PIXEL_FORMAT_RGB32;
558
559                                 if (settings->ColorDepth > 24)
560                                 {
561                                         int dstSize;
562
563                                         buffer = encoder->grid[k];
564
565                                         buffer = freerdp_bitmap_compress_planar(encoder->planar,
566                                                         data, srcFormat, nWidth, nHeight, nSrcStep, buffer, &dstSize);
567
568                                         bitmapData[k].bitmapDataStream = buffer;
569                                         bitmapData[k].bitmapLength = dstSize;
570
571                                         bitmapData[k].bitsPerPixel = 32;
572                                         bitmapData[k].cbScanWidth = nWidth * 4;
573                                         bitmapData[k].cbUncompressedSize = nWidth * nHeight * 4;
574                                 }
575                                 else
576                                 {
577                                         int bytesPerPixel = 2;
578                                         UINT32 dstFormat = PIXEL_FORMAT_RGB16;
579
580                                         if (settings->ColorDepth == 15)
581                                         {
582                                                 bytesPerPixel = 2;
583                                                 dstFormat = PIXEL_FORMAT_RGB15;
584                                         }
585                                         else if (settings->ColorDepth == 24)
586                                         {
587                                                 bytesPerPixel = 3;
588                                                 dstFormat = PIXEL_FORMAT_XRGB32;
589                                         }
590
591                                         buffer = encoder->grid[k];
592
593                                         freerdp_image_copy(buffer, dstFormat, -1, 0, 0, nWidth, nHeight,
594                                                         data, srcFormat, nSrcStep, 0, 0, NULL);
595
596                                         lines = freerdp_bitmap_compress((char*) buffer, nWidth, nHeight, s,
597                                                         settings->ColorDepth, 64 * 64 * 4, nHeight - 1, ts, e);
598
599                                         Stream_SealLength(s);
600
601                                         bitmapData[k].bitmapDataStream = Stream_Buffer(s);
602                                         bitmapData[k].bitmapLength = Stream_Length(s);
603
604                                         buffer = encoder->grid[k];
605                                         CopyMemory(buffer, bitmapData[k].bitmapDataStream, bitmapData[k].bitmapLength);
606                                         bitmapData[k].bitmapDataStream = buffer;
607
608                                         bitmapData[k].bitsPerPixel = settings->ColorDepth;
609                                         bitmapData[k].cbScanWidth = nWidth * bytesPerPixel;
610                                         bitmapData[k].cbUncompressedSize = nWidth * nHeight * bytesPerPixel;
611                                 }
612
613                                 bitmapData[k].cbCompFirstRowSize = 0;
614                                 bitmapData[k].cbCompMainBodySize = bitmapData[k].bitmapLength;
615
616                                 k++;
617                         }
618                 }
619         }
620
621         bitmapUpdate.count = bitmapUpdate.number = k;
622
623         IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
624
625         free(bitmapData);
626
627         return 1;
628 }
629
630 int shadow_client_send_surface_update(rdpShadowClient* client)
631 {
632         int status = -1;
633         int nXSrc, nYSrc;
634         int nWidth, nHeight;
635         rdpContext* context;
636         rdpSettings* settings;
637         rdpShadowServer* server;
638         rdpShadowSurface* surface;
639         rdpShadowEncoder* encoder;
640         REGION16 invalidRegion;
641         RECTANGLE_16 surfaceRect;
642         const RECTANGLE_16* extents;
643
644         context = (rdpContext*) client;
645         settings = context->settings;
646         server = client->server;
647         encoder = client->encoder;
648
649         surface = client->inLobby ? client->lobby : server->surface;
650
651         EnterCriticalSection(&(client->lock));
652
653         region16_init(&invalidRegion);
654         region16_copy(&invalidRegion, &(client->invalidRegion));
655         region16_clear(&(client->invalidRegion));
656
657         LeaveCriticalSection(&(client->lock));
658
659         surfaceRect.left = 0;
660         surfaceRect.top = 0;
661         surfaceRect.right = surface->width;
662         surfaceRect.bottom = surface->height;
663
664         region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
665
666         if (server->shareSubRect)
667         {
668                 region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
669         }
670
671         if (region16_is_empty(&invalidRegion))
672         {
673                 region16_uninit(&invalidRegion);
674                 return 1;
675         }
676
677         extents = region16_extents(&invalidRegion);
678
679         nXSrc = extents->left - 0;
680         nYSrc = extents->top - 0;
681         nWidth = extents->right - extents->left;
682         nHeight = extents->bottom - extents->top;
683
684         //WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
685         //      nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
686
687         if (settings->RemoteFxCodec || settings->NSCodec)
688         {
689                 if (settings->RemoteFxCodec)
690                         shadow_encoder_prepare(encoder, SHADOW_CODEC_REMOTEFX);
691                 else if (settings->NSCodec)
692                         shadow_encoder_prepare(encoder, SHADOW_CODEC_NSCODEC);
693
694                 status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
695         }
696         else
697         {
698                 shadow_encoder_prepare(encoder, SHADOW_CODEC_BITMAP);
699
700                 status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
701         }
702
703         region16_uninit(&invalidRegion);
704
705         return status;
706 }
707
708 int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
709 {
710         int index;
711         int numRects = 0;
712         const RECTANGLE_16* rects;
713
714         EnterCriticalSection(&(client->lock));
715
716         rects = region16_rects(region, &numRects);
717
718         for (index = 0; index < numRects; index++)
719         {
720                 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
721         }
722
723         LeaveCriticalSection(&(client->lock));
724
725         return 1;
726 }
727
728 void* shadow_client_thread(rdpShadowClient* client)
729 {
730         DWORD status;
731         DWORD nCount;
732         HANDLE events[32];
733         HANDLE StopEvent;
734         HANDLE ClientEvent;
735         HANDLE ChannelEvent;
736         HANDLE UpdateEvent;
737         freerdp_peer* peer;
738         rdpContext* context;
739         rdpSettings* settings;
740         rdpShadowServer* server;
741         rdpShadowScreen* screen;
742         rdpShadowEncoder* encoder;
743         rdpShadowSubsystem* subsystem;
744
745         server = client->server;
746         screen = server->screen;
747         encoder = client->encoder;
748         subsystem = server->subsystem;
749
750         context = (rdpContext*) client;
751         peer = context->peer;
752         settings = peer->settings;
753
754         peer->Capabilities = shadow_client_capabilities;
755         peer->PostConnect = shadow_client_post_connect;
756         peer->Activate = shadow_client_activate;
757
758         shadow_input_register_callbacks(peer->input);
759
760         peer->Initialize(peer);
761
762         peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect;
763         peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
764         peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge;
765
766         StopEvent = client->StopEvent;
767         UpdateEvent = subsystem->updateEvent;
768         ClientEvent = peer->GetEventHandle(peer);
769         ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
770
771         while (1)
772         {
773                 nCount = 0;
774                 events[nCount++] = StopEvent;
775                 events[nCount++] = UpdateEvent;
776                 events[nCount++] = ClientEvent;
777                 events[nCount++] = ChannelEvent;
778
779                 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
780
781                 if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
782                 {
783                         if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
784                         {
785                                 EnterSynchronizationBarrier(&(subsystem->barrier), 0);
786                         }
787
788                         break;
789                 }
790
791                 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
792                 {
793                         if (client->activated)
794                         {
795                                 int index;
796                                 int numRects = 0;
797                                 const RECTANGLE_16* rects;
798
799                                 rects = region16_rects(&(subsystem->invalidRegion), &numRects);
800
801                                 for (index = 0; index < numRects; index++)
802                                 {
803                                         region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
804                                 }
805
806                                 shadow_client_send_surface_update(client);
807                         }
808
809                         EnterSynchronizationBarrier(&(subsystem->barrier), 0);
810
811                         while (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0);
812                 }
813
814                 if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
815                 {
816                         if (!peer->CheckFileDescriptor(peer))
817                         {
818                                 WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
819                                 break;
820                         }
821                 }
822
823                 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
824                 {
825                         if (WTSVirtualChannelManagerCheckFileDescriptor(client->vcm) != TRUE)
826                         {
827                                 WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
828                                 break;
829                         }
830                 }
831         }
832
833         peer->Disconnect(peer);
834         
835         freerdp_peer_context_free(peer);
836         freerdp_peer_free(peer);
837
838         ExitThread(0);
839
840         return NULL;
841 }
842
843 void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
844 {
845         rdpShadowClient* client;
846         rdpShadowServer* server;
847
848         server = (rdpShadowServer*) listener->info;
849
850         peer->ContextExtra = (void*) server;
851         peer->ContextSize = sizeof(rdpShadowClient);
852         peer->ContextNew = (psPeerContextNew) shadow_client_context_new;
853         peer->ContextFree = (psPeerContextFree) shadow_client_context_free;
854         freerdp_peer_context_new(peer);
855
856         client = (rdpShadowClient*) peer->context;
857
858         client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
859                         shadow_client_thread, client, 0, NULL);
860 }