server/shadow: avoid sending pointer updates when not active, fix remdesk leak
[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->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
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         if (server->ipcSocket)
71         {
72                 settings->LyncRdpMode = TRUE;
73                 settings->CompressionEnabled = FALSE;
74         }
75
76         client->inLobby = TRUE;
77         client->mayView = server->mayView;
78         client->mayInteract = server->mayInteract;
79
80         InitializeCriticalSectionAndSpinCount(&(client->lock), 4000);
81
82         region16_init(&(client->invalidRegion));
83
84         client->vcm = WTSOpenServerA((LPSTR) peer->context);
85
86         client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
87
88         client->encoder = shadow_encoder_new(client);
89
90         ArrayList_Add(server->clients, (void*) client);
91 }
92
93 void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
94 {
95         rdpShadowServer* server = client->server;
96
97         ArrayList_Remove(server->clients, (void*) client);
98
99         DeleteCriticalSection(&(client->lock));
100
101         region16_uninit(&(client->invalidRegion));
102
103         WTSCloseServer((HANDLE) client->vcm);
104
105         CloseHandle(client->StopEvent);
106
107         if (client->lobby)
108         {
109                 shadow_surface_free(client->lobby);
110                 client->lobby = NULL;
111         }
112
113         if (client->encoder)
114         {
115                 shadow_encoder_free(client->encoder);
116                 client->encoder = NULL;
117         }
118 }
119
120 void shadow_client_message_free(wMessage* message)
121 {
122         if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
123         {
124                 SHADOW_MSG_IN_REFRESH_OUTPUT* wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
125
126                 free(wParam->rects);
127                 free(wParam);
128         }
129         else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
130         {
131                 SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
132                 free(wParam);
133         }
134 }
135
136 BOOL shadow_client_capabilities(freerdp_peer* peer)
137 {
138         return TRUE;
139 }
140
141 BOOL shadow_client_post_connect(freerdp_peer* peer)
142 {
143         int authStatus;
144         int width, height;
145         rdpSettings* settings;
146         rdpShadowClient* client;
147         rdpShadowServer* server;
148         RECTANGLE_16 invalidRect;
149         rdpShadowSubsystem* subsystem;
150
151         client = (rdpShadowClient*) peer->context;
152         settings = peer->settings;
153         server = client->server;
154         subsystem = server->subsystem;
155
156         if (!server->shareSubRect)
157         {
158                 width = server->screen->width;
159                 height = server->screen->height;
160         }
161         else
162         {
163                 width = server->subRect.right - server->subRect.left;
164                 height = server->subRect.bottom - server->subRect.top;
165         }
166
167         settings->DesktopWidth = width;
168         settings->DesktopHeight = height;
169
170         if (settings->ColorDepth == 24)
171                 settings->ColorDepth = 16; /* disable 24bpp */
172
173         if (settings->MultifragMaxRequestSize < 0x3F0000)
174                 settings->NSCodec = FALSE; /* NSCodec compressor does not support fragmentation yet */
175
176         WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)",
177                         peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
178
179         peer->update->DesktopResize(peer->update->context);
180
181         shadow_client_channels_post_connect(client);
182
183         invalidRect.left = 0;
184         invalidRect.top = 0;
185         invalidRect.right = width;
186         invalidRect.bottom = height;
187
188         region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect);
189
190         shadow_client_init_lobby(client);
191
192         authStatus = -1;
193
194         if (settings->Username && settings->Password)
195                 settings->AutoLogonEnabled = TRUE;
196
197         if (settings->AutoLogonEnabled && server->authentication)
198         {
199                 if (subsystem->Authenticate)
200                 {
201                         authStatus = subsystem->Authenticate(subsystem,
202                                         settings->Username, settings->Domain, settings->Password);
203                 }
204         }
205
206         if (server->authentication)
207         {
208                 if (authStatus < 0)
209                 {
210                         WLog_ERR(TAG, "client authentication failure: %d", authStatus);
211                         return FALSE;
212                 }
213         }
214
215         return TRUE;
216 }
217
218 void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
219 {
220         wMessage message = { 0 };
221         SHADOW_MSG_IN_REFRESH_OUTPUT* wParam;
222         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
223
224         wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT));
225
226         if (!wParam || !areas)
227         {
228                 if (wParam)
229                         free (wParam);
230                 return;
231         }
232
233         wParam->numRects = (UINT32) count;
234
235         if (wParam->numRects)
236         {
237                 wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16));
238
239                 if (!wParam->rects)
240                 {
241                         free (wParam);
242                         return;
243                 }
244         }
245
246         CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
247
248         message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
249         message.wParam = (void*) wParam;
250         message.lParam = NULL;
251         message.context = (void*) client;
252         message.Free = shadow_client_message_free;
253
254         MessageQueue_Dispatch(MsgPipe->In, &message);
255 }
256
257 void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
258 {
259         wMessage message = { 0 };
260         SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam;
261         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
262
263         wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT));
264
265         if (!wParam)
266                 return;
267
268         wParam->allow = (UINT32) allow;
269
270         if (area)
271                 CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
272
273         message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
274         message.wParam = (void*) wParam;
275         message.lParam = NULL;
276         message.context = (void*) client;
277         message.Free = shadow_client_message_free;
278
279         MessageQueue_Dispatch(MsgPipe->In, &message);
280 }
281
282 BOOL shadow_client_activate(freerdp_peer* peer)
283 {
284         rdpSettings* settings = peer->settings;
285         rdpShadowClient* client = (rdpShadowClient*) peer->context;
286
287         if (settings->ClientDir && (strcmp(settings->ClientDir, "librdp") == 0))
288         {
289                 /* Hack for Mac/iOS/Android Microsoft RDP clients */
290
291                 settings->RemoteFxCodec = FALSE;
292
293                 settings->NSCodec = FALSE;
294                 settings->NSCodecAllowSubsampling = FALSE;
295
296                 settings->SurfaceFrameMarkerEnabled = FALSE;
297         }
298
299         client->activated = TRUE;
300         client->inLobby = client->mayView ? FALSE : TRUE;
301
302         shadow_encoder_reset(client->encoder);
303
304         shadow_client_refresh_rect(client, 0, NULL);
305
306         return TRUE;
307 }
308
309 void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
310 {
311         SURFACE_FRAME* frame;
312         wListDictionary* frameList;
313
314         frameList = client->encoder->frameList;
315         frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
316
317         if (frame)
318         {
319                 ListDictionary_Remove(frameList, (void*) (size_t) frameId);
320                 free(frame);
321         }
322 }
323
324 int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id)
325 {
326         SURFACE_FRAME_MARKER surfaceFrameMarker;
327         rdpContext* context = (rdpContext*) client;
328         rdpUpdate* update = context->update;
329
330         surfaceFrameMarker.frameAction = action;
331         surfaceFrameMarker.frameId = id;
332
333         IFCALL(update->SurfaceFrameMarker, context, &surfaceFrameMarker);
334
335         return 1;
336 }
337
338 int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
339 {
340         int i;
341         BOOL first;
342         BOOL last;
343         wStream* s;
344         int nSrcStep;
345         BYTE* pSrcData;
346         int numMessages;
347         UINT32 frameId = 0;
348         rdpUpdate* update;
349         rdpContext* context;
350         rdpSettings* settings;
351         rdpShadowServer* server;
352         rdpShadowEncoder* encoder;
353         SURFACE_BITS_COMMAND cmd;
354
355         context = (rdpContext*) client;
356         update = context->update;
357         settings = context->settings;
358
359         server = client->server;
360         encoder = client->encoder;
361
362         pSrcData = surface->data;
363         nSrcStep = surface->scanline;
364
365         if (server->shareSubRect)
366         {
367                 int subX, subY;
368                 int subWidth, subHeight;
369
370                 subX = server->subRect.left;
371                 subY = server->subRect.top;
372                 subWidth = server->subRect.right - server->subRect.left;
373                 subHeight = server->subRect.bottom - server->subRect.top;
374
375                 nXSrc -= subX;
376                 nYSrc -= subY;
377                 pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
378         }
379
380         if (encoder->frameAck)
381                 frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
382
383         if (settings->RemoteFxCodec)
384         {
385                 RFX_RECT rect;
386                 RFX_MESSAGE* messages;
387
388                 shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX);
389
390                 s = encoder->bs;
391
392                 rect.x = nXSrc;
393                 rect.y = nYSrc;
394                 rect.width = nWidth;
395                 rect.height = nHeight;
396
397                 messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
398                                 surface->width, surface->height, nSrcStep, &numMessages,
399                                 settings->MultifragMaxRequestSize);
400
401                 cmd.codecID = settings->RemoteFxCodecId;
402
403                 cmd.destLeft = 0;
404                 cmd.destTop = 0;
405                 cmd.destRight = surface->width;
406                 cmd.destBottom = surface->height;
407
408                 cmd.bpp = 32;
409                 cmd.width = surface->width;
410                 cmd.height = surface->height;
411
412                 for (i = 0; i < numMessages; i++)
413                 {
414                         Stream_SetPosition(s, 0);
415                         rfx_write_message(encoder->rfx, s, &messages[i]);
416                         rfx_message_free(encoder->rfx, &messages[i]);
417
418                         cmd.bitmapDataLength = Stream_GetPosition(s);
419                         cmd.bitmapData = Stream_Buffer(s);
420
421                         first = (i == 0) ? TRUE : FALSE;
422                         last = ((i + 1) == numMessages) ? TRUE : FALSE;
423
424                         if (!encoder->frameAck)
425                                 IFCALL(update->SurfaceBits, update->context, &cmd);
426                         else
427                                 IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
428                 }
429
430                 free(messages);
431         }
432         else if (settings->NSCodec)
433         {
434                 shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC);
435
436                 s = encoder->bs;
437                 Stream_SetPosition(s, 0);
438
439                 pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
440
441                 nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
442
443                 cmd.bpp = 32;
444                 cmd.codecID = settings->NSCodecId;
445                 cmd.destLeft = nXSrc;
446                 cmd.destTop = nYSrc;
447                 cmd.destRight = cmd.destLeft + nWidth;
448                 cmd.destBottom = cmd.destTop + nHeight;
449                 cmd.width = nWidth;
450                 cmd.height = nHeight;
451
452                 cmd.bitmapDataLength = Stream_GetPosition(s);
453                 cmd.bitmapData = Stream_Buffer(s);
454
455                 first = TRUE;
456                 last = TRUE;
457
458                 if (!encoder->frameAck)
459                         IFCALL(update->SurfaceBits, update->context, &cmd);
460                 else
461                         IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
462         }
463
464         return 1;
465 }
466
467 int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
468 {
469         BYTE* data;
470         BYTE* buffer;
471         int yIdx, xIdx, k;
472         int rows, cols;
473         int nSrcStep;
474         BYTE* pSrcData;
475         UINT32 DstSize;
476         UINT32 SrcFormat;
477         BITMAP_DATA* bitmap;
478         rdpUpdate* update;
479         rdpContext* context;
480         rdpSettings* settings;
481         UINT32 maxUpdateSize;
482         UINT32 totalBitmapSize;
483         UINT32 updateSizeEstimate;
484         BITMAP_DATA* bitmapData;
485         BITMAP_UPDATE bitmapUpdate;
486         rdpShadowServer* server;
487         rdpShadowEncoder* encoder;
488
489         context = (rdpContext*) client;
490         update = context->update;
491         settings = context->settings;
492
493         server = client->server;
494         encoder = client->encoder;
495
496         maxUpdateSize = settings->MultifragMaxRequestSize;
497
498         if (settings->ColorDepth < 32)
499                 shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED);
500         else
501                 shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR);
502
503         pSrcData = surface->data;
504         nSrcStep = surface->scanline;
505         SrcFormat = PIXEL_FORMAT_RGB32;
506
507         if ((nXSrc % 4) != 0)
508         {
509                 nWidth += (nXSrc % 4);
510                 nXSrc -= (nXSrc % 4);
511         }
512
513         if ((nYSrc % 4) != 0)
514         {
515                 nHeight += (nYSrc % 4);
516                 nYSrc -= (nYSrc % 4);
517         }
518
519         rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
520         cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
521
522         k = 0;
523         totalBitmapSize = 0;
524
525         bitmapUpdate.count = bitmapUpdate.number = rows * cols;
526         bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number);
527         bitmapUpdate.rectangles = bitmapData;
528
529         if (!bitmapData)
530                 return -1;
531
532         if ((nWidth % 4) != 0)
533         {
534                 nXSrc -= (nWidth % 4);
535                 nWidth += (nWidth % 4);
536         }
537
538         if ((nHeight % 4) != 0)
539         {
540                 nYSrc -= (nHeight % 4);
541                 nHeight += (nHeight % 4);
542         }
543
544         for (yIdx = 0; yIdx < rows; yIdx++)
545         {
546                 for (xIdx = 0; xIdx < cols; xIdx++)
547                 {
548                         bitmap = &bitmapData[k];
549
550                         bitmap->width = 64;
551                         bitmap->height = 64;
552                         bitmap->destLeft = nXSrc + (xIdx * 64);
553                         bitmap->destTop = nYSrc + (yIdx * 64);
554
555                         if ((bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
556                                 bitmap->width = (nXSrc + nWidth) - bitmap->destLeft;
557
558                         if ((bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
559                                 bitmap->height = (nYSrc + nHeight) - bitmap->destTop;
560
561                         bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
562                         bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
563                         bitmap->compressed = TRUE;
564
565                         if ((bitmap->width < 4) || (bitmap->height < 4))
566                                 continue;
567
568                         if (settings->ColorDepth < 32)
569                         {
570                                 int bitsPerPixel = settings->ColorDepth;
571                                 int bytesPerPixel = (bitsPerPixel + 7) / 8;
572
573                                 DstSize = 64 * 64 * 4;
574                                 buffer = encoder->grid[k];
575
576                                 interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height,
577                                                 pSrcData, SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
578
579                                 bitmap->bitmapDataStream = buffer;
580                                 bitmap->bitmapLength = DstSize;
581                                 bitmap->bitsPerPixel = bitsPerPixel;
582                                 bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
583                                 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
584                         }
585                         else
586                         {
587                                 int dstSize;
588
589                                 buffer = encoder->grid[k];
590                                 data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
591
592                                 buffer = freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat,
593                                                 bitmap->width, bitmap->height, nSrcStep, buffer, &dstSize);
594
595                                 bitmap->bitmapDataStream = buffer;
596                                 bitmap->bitmapLength = dstSize;
597                                 bitmap->bitsPerPixel = 32;
598                                 bitmap->cbScanWidth = bitmap->width * 4;
599                                 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
600                         }
601
602                         bitmap->cbCompFirstRowSize = 0;
603                         bitmap->cbCompMainBodySize = bitmap->bitmapLength;
604
605                         totalBitmapSize += bitmap->bitmapLength;
606                         k++;
607                 }
608         }
609
610         bitmapUpdate.count = bitmapUpdate.number = k;
611
612         updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16;
613
614         if (updateSizeEstimate > maxUpdateSize)
615         {
616                 UINT32 i, j;
617                 UINT32 updateSize;
618                 UINT32 newUpdateSize;
619                 BITMAP_DATA* fragBitmapData;
620
621                 fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k);
622                 bitmapUpdate.rectangles = fragBitmapData;
623
624                 i = j = 0;
625                 updateSize = 1024;
626
627                 while (i < k)
628                 {
629                         newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
630
631                         if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k))
632                         {
633                                 CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
634                                 updateSize = newUpdateSize;
635                         }
636                         else
637                         {
638                                 if ((i + 1) >= k)
639                                 {
640                                         CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
641                                         updateSize = newUpdateSize;
642                                 }
643                                 
644                                 bitmapUpdate.count = bitmapUpdate.number = j;
645                                 IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
646                                 updateSize = 1024;
647                                 j = 0;
648                         }
649                 }
650
651                 free(fragBitmapData);
652         }
653         else
654         {
655                 IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
656         }
657
658         free(bitmapData);
659
660         return 1;
661 }
662
663 int shadow_client_send_surface_update(rdpShadowClient* client)
664 {
665         int status = -1;
666         int nXSrc, nYSrc;
667         int nWidth, nHeight;
668         rdpContext* context;
669         rdpSettings* settings;
670         rdpShadowServer* server;
671         rdpShadowSurface* surface;
672         rdpShadowEncoder* encoder;
673         REGION16 invalidRegion;
674         RECTANGLE_16 surfaceRect;
675         const RECTANGLE_16* extents;
676
677         context = (rdpContext*) client;
678         settings = context->settings;
679         server = client->server;
680         encoder = client->encoder;
681
682         surface = client->inLobby ? client->lobby : server->surface;
683
684         EnterCriticalSection(&(client->lock));
685
686         region16_init(&invalidRegion);
687         region16_copy(&invalidRegion, &(client->invalidRegion));
688         region16_clear(&(client->invalidRegion));
689
690         LeaveCriticalSection(&(client->lock));
691
692         surfaceRect.left = 0;
693         surfaceRect.top = 0;
694         surfaceRect.right = surface->width;
695         surfaceRect.bottom = surface->height;
696
697         region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
698
699         if (server->shareSubRect)
700         {
701                 region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
702         }
703
704         if (region16_is_empty(&invalidRegion))
705         {
706                 region16_uninit(&invalidRegion);
707                 return 1;
708         }
709
710         extents = region16_extents(&invalidRegion);
711
712         nXSrc = extents->left - 0;
713         nYSrc = extents->top - 0;
714         nWidth = extents->right - extents->left;
715         nHeight = extents->bottom - extents->top;
716
717         //WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
718         //      nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
719
720         if (settings->RemoteFxCodec || settings->NSCodec)
721         {
722                 status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
723         }
724         else
725         {
726                 status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
727         }
728
729         region16_uninit(&invalidRegion);
730
731         return status;
732 }
733
734 int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
735 {
736         int index;
737         int numRects = 0;
738         const RECTANGLE_16* rects;
739
740         EnterCriticalSection(&(client->lock));
741
742         rects = region16_rects(region, &numRects);
743
744         for (index = 0; index < numRects; index++)
745         {
746                 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
747         }
748
749         LeaveCriticalSection(&(client->lock));
750
751         return 1;
752 }
753
754 int shadow_client_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied,
755                 UINT32 width, UINT32 height, POINTER_COLOR_UPDATE* pointerColor)
756 {
757         UINT32 x, y;
758         BYTE* pSrc8;
759         BYTE* pDst8;
760         int xorStep;
761         int andStep;
762         UINT32 andBit;
763         BYTE* andBits;
764         UINT32 andPixel;
765         BYTE A, R, G, B;
766
767         xorStep = (width * 3);
768         xorStep += (xorStep % 2);
769
770         andStep = ((width + 7) / 8);
771         andStep += (andStep % 2);
772
773         pointerColor->lengthXorMask = height * xorStep;
774         pointerColor->xorMaskData = (BYTE*) calloc(1, pointerColor->lengthXorMask);
775
776         if (!pointerColor->xorMaskData)
777                 return -1;
778
779         pointerColor->lengthAndMask = height * andStep;
780         pointerColor->andMaskData = (BYTE*) calloc(1, pointerColor->lengthAndMask);
781
782         if (!pointerColor->andMaskData)
783                 return -1;
784
785         for (y = 0; y < height; y++)
786         {
787                 pSrc8 = &pixels[(width * 4) * (height - 1 - y)];
788                 pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
789
790                 andBit = 0x80;
791                 andBits = &(pointerColor->andMaskData[andStep * y]);
792
793                 for (x = 0; x < width; x++)
794                 {
795                         B = *pSrc8++;
796                         G = *pSrc8++;
797                         R = *pSrc8++;
798                         A = *pSrc8++;
799
800                         andPixel = 0;
801
802                         if (A < 64)
803                                 A = 0; /* pixel cannot be partially transparent */
804
805                         if (!A)
806                         {
807                                 /* transparent pixel: XOR = black, AND = 1 */
808                                 andPixel = 1;
809                                 B = G = R = 0;
810                         }
811                         else
812                         {
813                                 if (premultiplied)
814                                 {
815                                         B = (B * 0xFF ) / A;
816                                         G = (G * 0xFF ) / A;
817                                         R = (R * 0xFF ) / A;
818                                 }
819                         }
820
821                         *pDst8++ = B;
822                         *pDst8++ = G;
823                         *pDst8++ = R;
824
825                         if (andPixel) *andBits |= andBit;
826                         if (!(andBit >>= 1)) { andBits++; andBit = 0x80; }
827                 }
828         }
829
830         return 1;
831 }
832
833 int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
834 {
835         rdpContext* context = (rdpContext*) client;
836         rdpUpdate* update = context->update;
837
838         /* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */
839
840         if (message->id == SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID)
841         {
842                 POINTER_POSITION_UPDATE pointerPosition;
843                 SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) message->wParam;
844
845                 pointerPosition.xPos = msg->xPos;
846                 pointerPosition.yPos = msg->yPos;
847
848                 if (client->activated)
849                 {
850                         if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
851                         {
852                                 IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
853
854                                 client->pointerX = msg->xPos;
855                                 client->pointerY = msg->yPos;
856                         }
857                 }
858
859                 free(msg);
860         }
861         else if (message->id == SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID)
862         {
863                 POINTER_NEW_UPDATE pointerNew;
864                 POINTER_COLOR_UPDATE* pointerColor;
865                 POINTER_CACHED_UPDATE pointerCached;
866                 SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam;
867
868                 ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE));
869
870                 pointerNew.xorBpp = 24;
871                 pointerColor = &(pointerNew.colorPtrAttr);
872
873                 pointerColor->cacheIndex = 0;
874                 pointerColor->xPos = msg->xHot;
875                 pointerColor->yPos = msg->yHot;
876                 pointerColor->width = msg->width;
877                 pointerColor->height = msg->height;
878
879                 pointerCached.cacheIndex = pointerColor->cacheIndex;
880
881                 if (client->activated)
882                 {
883                         shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied,
884                                         msg->width, msg->height, pointerColor);
885
886                         IFCALL(update->pointer->PointerNew, context, &pointerNew);
887                         IFCALL(update->pointer->PointerCached, context, &pointerCached);
888
889                         free(pointerColor->xorMaskData);
890                         free(pointerColor->andMaskData);
891                 }
892
893                 free(msg->pixels);
894                 free(msg);
895         }
896
897         return 1;
898 }
899
900 void* shadow_client_thread(rdpShadowClient* client)
901 {
902         DWORD status;
903         DWORD nCount;
904         wMessage message;
905         HANDLE events[32];
906         HANDLE StopEvent;
907         HANDLE ClientEvent;
908         HANDLE ChannelEvent;
909         HANDLE UpdateEvent;
910         freerdp_peer* peer;
911         rdpContext* context;
912         rdpSettings* settings;
913         rdpShadowServer* server;
914         rdpShadowScreen* screen;
915         rdpShadowEncoder* encoder;
916         rdpShadowSubsystem* subsystem;
917         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
918
919         server = client->server;
920         screen = server->screen;
921         encoder = client->encoder;
922         subsystem = server->subsystem;
923
924         context = (rdpContext*) client;
925         peer = context->peer;
926         settings = peer->settings;
927
928         peer->Capabilities = shadow_client_capabilities;
929         peer->PostConnect = shadow_client_post_connect;
930         peer->Activate = shadow_client_activate;
931
932         shadow_input_register_callbacks(peer->input);
933
934         peer->Initialize(peer);
935
936         peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect;
937         peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
938         peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge;
939
940         StopEvent = client->StopEvent;
941         UpdateEvent = subsystem->updateEvent;
942         ClientEvent = peer->GetEventHandle(peer);
943         ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
944
945         while (1)
946         {
947                 nCount = 0;
948                 events[nCount++] = StopEvent;
949                 events[nCount++] = UpdateEvent;
950                 events[nCount++] = ClientEvent;
951                 events[nCount++] = ChannelEvent;
952                 events[nCount++] = MessageQueue_Event(MsgPipe->Out);
953
954                 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
955
956                 if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
957                 {
958                         if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
959                         {
960                                 EnterSynchronizationBarrier(&(subsystem->barrier), 0);
961                         }
962
963                         break;
964                 }
965
966                 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
967                 {
968                         if (client->activated)
969                         {
970                                 int index;
971                                 int numRects = 0;
972                                 const RECTANGLE_16* rects;
973
974                                 rects = region16_rects(&(subsystem->invalidRegion), &numRects);
975
976                                 for (index = 0; index < numRects; index++)
977                                 {
978                                         region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
979                                 }
980
981                                 shadow_client_send_surface_update(client);
982                         }
983
984                         EnterSynchronizationBarrier(&(subsystem->barrier), 0);
985
986                         while (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0);
987                 }
988
989                 if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
990                 {
991                         if (!peer->CheckFileDescriptor(peer))
992                         {
993                                 WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
994                                 break;
995                         }
996                 }
997
998                 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
999                 {
1000                         if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
1001                         {
1002                                 WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
1003                                 break;
1004                         }
1005                 }
1006
1007                 if (WaitForSingleObject(MessageQueue_Event(MsgPipe->Out), 0) == WAIT_OBJECT_0)
1008                 {
1009                         if (MessageQueue_Peek(MsgPipe->Out, &message, TRUE))
1010                         {
1011                                 if (message.id == WMQ_QUIT)
1012                                         break;
1013
1014                                 shadow_client_subsystem_process_message(client, &message);
1015                         }
1016                 }
1017         }
1018
1019         peer->Disconnect(peer);
1020         
1021         freerdp_peer_context_free(peer);
1022         freerdp_peer_free(peer);
1023
1024         ExitThread(0);
1025
1026         return NULL;
1027 }
1028
1029 void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
1030 {
1031         rdpShadowClient* client;
1032         rdpShadowServer* server;
1033
1034         server = (rdpShadowServer*) listener->info;
1035
1036         peer->ContextExtra = (void*) server;
1037         peer->ContextSize = sizeof(rdpShadowClient);
1038         peer->ContextNew = (psPeerContextNew) shadow_client_context_new;
1039         peer->ContextFree = (psPeerContextFree) shadow_client_context_free;
1040         freerdp_peer_context_new(peer);
1041
1042         client = (rdpShadowClient*) peer->context;
1043
1044         client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
1045                         shadow_client_thread, client, 0, NULL);
1046 }