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