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