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