server/shadow: Integrate comment from @hardening: use switch to handle different...
[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 #include <winpr/interlocked.h>
30
31 #include <freerdp/log.h>
32
33 #include "shadow.h"
34
35 #define TAG CLIENT_TAG("shadow")
36
37 static void shadow_client_free_queued_message(void *obj)
38 {
39         wMessage *message = (wMessage*)obj;
40         if (message->Free)
41         {
42                 message->Free(message);
43                 message->Free = NULL;
44         }
45 }
46
47 BOOL shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
48 {
49         rdpSettings* settings;
50         rdpShadowServer* server;
51         const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL };
52
53         server = (rdpShadowServer*) peer->ContextExtra;
54         client->server = server;
55         client->subsystem = server->subsystem;
56
57         settings = peer->settings;
58
59         settings->ColorDepth = 32;
60         settings->NSCodec = TRUE;
61         settings->RemoteFxCodec = TRUE;
62         settings->BitmapCacheV3Enabled = TRUE;
63         settings->FrameMarkerCommandEnabled = TRUE;
64         settings->SurfaceFrameMarkerEnabled = TRUE;
65         settings->SupportGraphicsPipeline = FALSE;
66
67         settings->DrawAllowSkipAlpha = TRUE;
68         settings->DrawAllowColorSubsampling = TRUE;
69         settings->DrawAllowDynamicColorFidelity = TRUE;
70
71         settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
72
73         settings->RdpSecurity = TRUE;
74         settings->TlsSecurity = TRUE;
75         settings->NlaSecurity = FALSE;
76
77         if (!(settings->CertificateFile = _strdup(server->CertificateFile)))
78                 goto fail_cert_file;
79         if (!(settings->PrivateKeyFile = _strdup(server->PrivateKeyFile)))
80                 goto fail_privkey_file;
81         if (!(settings->RdpKeyFile = _strdup(settings->PrivateKeyFile)))
82                 goto fail_rdpkey_file;
83
84
85         if (server->ipcSocket)
86         {
87                 settings->LyncRdpMode = TRUE;
88                 settings->CompressionEnabled = FALSE;
89         }
90
91         client->inLobby = TRUE;
92         client->mayView = server->mayView;
93         client->mayInteract = server->mayInteract;
94
95         if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
96                 goto fail_client_lock;
97
98         region16_init(&(client->invalidRegion));
99
100         client->vcm = WTSOpenServerA((LPSTR) peer->context);
101         if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
102                 goto fail_open_server;
103
104         if (!(client->MsgQueue = MessageQueue_New(&cb)))
105                 goto fail_message_queue;
106
107         if (!(client->encoder = shadow_encoder_new(client)))
108                 goto fail_encoder_new;
109
110         if (ArrayList_Add(server->clients, (void*) client) >= 0)
111                 return TRUE;
112
113         shadow_encoder_free(client->encoder);
114         client->encoder = NULL;
115 fail_encoder_new:
116         MessageQueue_Free(client->MsgQueue);
117         client->MsgQueue = NULL;
118 fail_message_queue:
119         WTSCloseServer((HANDLE) client->vcm);
120         client->vcm = NULL;
121 fail_open_server:
122         DeleteCriticalSection(&(client->lock));
123 fail_client_lock:
124         free(settings->RdpKeyFile);
125         settings->RdpKeyFile = NULL;
126 fail_rdpkey_file:
127         free(settings->PrivateKeyFile);
128         settings->PrivateKeyFile = NULL;
129 fail_privkey_file:
130         free(settings->CertificateFile);
131         settings->CertificateFile = NULL;
132 fail_cert_file:
133
134         return FALSE;
135 }
136
137 void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
138 {
139         rdpShadowServer* server = client->server;
140
141         ArrayList_Remove(server->clients, (void*) client);
142
143         DeleteCriticalSection(&(client->lock));
144
145         region16_uninit(&(client->invalidRegion));
146
147         WTSCloseServer((HANDLE) client->vcm);
148
149     /* Clear queued messages and free resource */
150         MessageQueue_Clear(client->MsgQueue);
151         MessageQueue_Free(client->MsgQueue);
152
153         if (client->lobby)
154         {
155                 shadow_surface_free(client->lobby);
156                 client->lobby = NULL;
157         }
158
159         if (client->encoder)
160         {
161                 shadow_encoder_free(client->encoder);
162                 client->encoder = NULL;
163         }
164 }
165
166 void shadow_client_message_free(wMessage* message)
167 {
168         switch(message->id)
169         {
170                 case SHADOW_MSG_IN_REFRESH_OUTPUT_ID:
171                         free(((SHADOW_MSG_IN_REFRESH_OUTPUT*)message->wParam)->rects);
172                         free(message->wParam);
173                         break;
174
175                 case SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID:
176                         free(message->wParam);
177                         break;
178
179                 default:
180                         WLog_ERR(TAG, "Unknown message id: %u", message->id);
181                         free(message->wParam);
182                         break;
183         }
184 }
185
186 BOOL shadow_client_capabilities(freerdp_peer* peer)
187 {
188         return TRUE;
189 }
190
191 BOOL shadow_client_post_connect(freerdp_peer* peer)
192 {
193         int authStatus;
194         int width, height;
195         rdpSettings* settings;
196         rdpShadowClient* client;
197         rdpShadowServer* server;
198         RECTANGLE_16 invalidRect;
199         rdpShadowSubsystem* subsystem;
200
201         client = (rdpShadowClient*) peer->context;
202         settings = peer->settings;
203         server = client->server;
204         subsystem = server->subsystem;
205
206         if (!server->shareSubRect)
207         {
208                 width = server->screen->width;
209                 height = server->screen->height;
210         }
211         else
212         {
213                 width = server->subRect.right - server->subRect.left;
214                 height = server->subRect.bottom - server->subRect.top;
215         }
216
217         settings->DesktopWidth = width;
218         settings->DesktopHeight = height;
219
220         if (settings->ColorDepth == 24)
221                 settings->ColorDepth = 16; /* disable 24bpp */
222
223         if (settings->MultifragMaxRequestSize < 0x3F0000)
224                 settings->NSCodec = FALSE; /* NSCodec compressor does not support fragmentation yet */
225
226         WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)",
227                         peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
228
229         peer->update->DesktopResize(peer->update->context);
230
231         shadow_client_channels_post_connect(client);
232
233         invalidRect.left = 0;
234         invalidRect.top = 0;
235         invalidRect.right = width;
236         invalidRect.bottom = height;
237
238         region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect);
239
240         shadow_client_init_lobby(client);
241
242         authStatus = -1;
243
244         if (settings->Username && settings->Password)
245                 settings->AutoLogonEnabled = TRUE;
246
247         if (settings->AutoLogonEnabled && server->authentication)
248         {
249                 if (subsystem->Authenticate)
250                 {
251                         authStatus = subsystem->Authenticate(subsystem,
252                                         settings->Username, settings->Domain, settings->Password);
253                 }
254         }
255
256         if (server->authentication)
257         {
258                 if (authStatus < 0)
259                 {
260                         WLog_ERR(TAG, "client authentication failure: %d", authStatus);
261                         return FALSE;
262                 }
263         }
264
265         return TRUE;
266 }
267
268 BOOL shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
269 {
270         wMessage message = { 0 };
271         SHADOW_MSG_IN_REFRESH_OUTPUT* wParam;
272         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
273
274         if (count && !areas)
275                 return FALSE;
276
277         if (!(wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT))))
278                 return FALSE;
279
280         wParam->numRects = (UINT32) count;
281
282         if (wParam->numRects)
283         {
284                 wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16));
285
286                 if (!wParam->rects)
287                 {
288                         free (wParam);
289                         return FALSE;
290                 }
291
292                 CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
293         }
294
295         message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
296         message.wParam = (void*) wParam;
297         message.lParam = NULL;
298         message.context = (void*) client;
299         message.Free = shadow_client_message_free;
300
301         return MessageQueue_Dispatch(MsgPipe->In, &message);
302 }
303
304 BOOL shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
305 {
306         wMessage message = { 0 };
307         SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam;
308         wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
309
310         wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT));
311         if (!wParam)
312                 return FALSE;
313
314         wParam->allow = (UINT32) allow;
315
316         if (area)
317                 CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
318
319         message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
320         message.wParam = (void*) wParam;
321         message.lParam = NULL;
322         message.context = (void*) client;
323         message.Free = shadow_client_message_free;
324
325         return MessageQueue_Dispatch(MsgPipe->In, &message);
326 }
327
328 BOOL shadow_client_activate(freerdp_peer* peer)
329 {
330         rdpSettings* settings = peer->settings;
331         rdpShadowClient* client = (rdpShadowClient*) peer->context;
332
333         if (settings->ClientDir && (strcmp(settings->ClientDir, "librdp") == 0))
334         {
335                 /* Hack for Mac/iOS/Android Microsoft RDP clients */
336
337                 settings->RemoteFxCodec = FALSE;
338
339                 settings->NSCodec = FALSE;
340                 settings->NSCodecAllowSubsampling = FALSE;
341
342                 settings->SurfaceFrameMarkerEnabled = FALSE;
343         }
344
345         client->activated = TRUE;
346         client->inLobby = client->mayView ? FALSE : TRUE;
347
348         shadow_encoder_reset(client->encoder);
349
350         return shadow_client_refresh_rect(client, 0, NULL);
351 }
352
353 BOOL shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
354 {
355         SURFACE_FRAME* frame;
356         wListDictionary* frameList;
357
358         frameList = client->encoder->frameList;
359         frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
360
361         if (frame)
362         {
363                 ListDictionary_Remove(frameList, (void*) (size_t) frameId);
364                 free(frame);
365         }
366         return TRUE;
367 }
368
369 int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id)
370 {
371         SURFACE_FRAME_MARKER surfaceFrameMarker;
372         rdpContext* context = (rdpContext*) client;
373         rdpUpdate* update = context->update;
374
375         surfaceFrameMarker.frameAction = action;
376         surfaceFrameMarker.frameId = id;
377
378         IFCALL(update->SurfaceFrameMarker, context, &surfaceFrameMarker);
379
380         return 1;
381 }
382
383 int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
384 {
385         int i;
386         BOOL first;
387         BOOL last;
388         wStream* s;
389         int nSrcStep;
390         BYTE* pSrcData;
391         int numMessages;
392         UINT32 frameId = 0;
393         rdpUpdate* update;
394         rdpContext* context;
395         rdpSettings* settings;
396         rdpShadowServer* server;
397         rdpShadowEncoder* encoder;
398         SURFACE_BITS_COMMAND cmd;
399
400         context = (rdpContext*) client;
401         update = context->update;
402         settings = context->settings;
403
404         server = client->server;
405         encoder = client->encoder;
406
407         pSrcData = surface->data;
408         nSrcStep = surface->scanline;
409
410         if (server->shareSubRect)
411         {
412                 int subX, subY;
413                 int subWidth, subHeight;
414
415                 subX = server->subRect.left;
416                 subY = server->subRect.top;
417                 subWidth = server->subRect.right - server->subRect.left;
418                 subHeight = server->subRect.bottom - server->subRect.top;
419
420                 nXSrc -= subX;
421                 nYSrc -= subY;
422                 pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
423         }
424
425         if (encoder->frameAck)
426                 frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
427
428         if (settings->RemoteFxCodec)
429         {
430                 RFX_RECT rect;
431                 RFX_MESSAGE* messages;
432                 RFX_RECT *messageRects = NULL;
433
434                 shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX);
435
436                 s = encoder->bs;
437
438                 rect.x = nXSrc;
439                 rect.y = nYSrc;
440                 rect.width = nWidth;
441                 rect.height = nHeight;
442
443                 if (!(messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
444                                 surface->width, surface->height, nSrcStep, &numMessages,
445                                 settings->MultifragMaxRequestSize)))
446                 {
447                         return 0;
448                 }
449
450                 cmd.codecID = settings->RemoteFxCodecId;
451
452                 cmd.destLeft = 0;
453                 cmd.destTop = 0;
454                 cmd.destRight = surface->width;
455                 cmd.destBottom = surface->height;
456
457                 cmd.bpp = 32;
458                 cmd.width = surface->width;
459                 cmd.height = surface->height;
460                 cmd.skipCompression = TRUE;
461
462                 if (numMessages > 0)
463                         messageRects = messages[0].rects;
464
465                 for (i = 0; i < numMessages; i++)
466                 {
467                         Stream_SetPosition(s, 0);
468                         if (!rfx_write_message(encoder->rfx, s, &messages[i]))
469                         {
470                                 while (i < numMessages)
471                                 {
472                                         rfx_message_free(encoder->rfx, &messages[i++]);
473                                 }
474                                 break;
475                         }
476                         rfx_message_free(encoder->rfx, &messages[i]);
477
478                         cmd.bitmapDataLength = Stream_GetPosition(s);
479                         cmd.bitmapData = Stream_Buffer(s);
480
481                         first = (i == 0) ? TRUE : FALSE;
482                         last = ((i + 1) == numMessages) ? TRUE : FALSE;
483
484                         if (!encoder->frameAck)
485                                 IFCALL(update->SurfaceBits, update->context, &cmd);
486                         else
487                                 IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
488                 }
489
490                 free(messageRects);
491                 free(messages);
492         }
493         else if (settings->NSCodec)
494         {
495                 shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC);
496
497                 s = encoder->bs;
498                 Stream_SetPosition(s, 0);
499
500                 pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
501
502                 nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
503
504                 cmd.bpp = 32;
505                 cmd.codecID = settings->NSCodecId;
506                 cmd.destLeft = nXSrc;
507                 cmd.destTop = nYSrc;
508                 cmd.destRight = cmd.destLeft + nWidth;
509                 cmd.destBottom = cmd.destTop + nHeight;
510                 cmd.width = nWidth;
511                 cmd.height = nHeight;
512
513                 cmd.bitmapDataLength = Stream_GetPosition(s);
514                 cmd.bitmapData = Stream_Buffer(s);
515
516                 first = TRUE;
517                 last = TRUE;
518
519                 if (!encoder->frameAck)
520                         IFCALL(update->SurfaceBits, update->context, &cmd);
521                 else
522                         IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
523         }
524
525         return 1;
526 }
527
528 int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
529 {
530         BYTE* data;
531         BYTE* buffer;
532         int yIdx, xIdx, k;
533         int rows, cols;
534         int nSrcStep;
535         BYTE* pSrcData;
536         UINT32 DstSize;
537         UINT32 SrcFormat;
538         BITMAP_DATA* bitmap;
539         rdpUpdate* update;
540         rdpContext* context;
541         rdpSettings* settings;
542         UINT32 maxUpdateSize;
543         UINT32 totalBitmapSize;
544         UINT32 updateSizeEstimate;
545         BITMAP_DATA* bitmapData;
546         BITMAP_UPDATE bitmapUpdate;
547         rdpShadowServer* server;
548         rdpShadowEncoder* encoder;
549
550         context = (rdpContext*) client;
551         update = context->update;
552         settings = context->settings;
553
554         server = client->server;
555         encoder = client->encoder;
556
557         maxUpdateSize = settings->MultifragMaxRequestSize;
558
559         if (settings->ColorDepth < 32)
560                 shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED);
561         else
562                 shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR);
563
564         pSrcData = surface->data;
565         nSrcStep = surface->scanline;
566         SrcFormat = PIXEL_FORMAT_RGB32;
567
568         if ((nXSrc % 4) != 0)
569         {
570                 nWidth += (nXSrc % 4);
571                 nXSrc -= (nXSrc % 4);
572         }
573
574         if ((nYSrc % 4) != 0)
575         {
576                 nHeight += (nYSrc % 4);
577                 nYSrc -= (nYSrc % 4);
578         }
579
580         rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
581         cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
582
583         k = 0;
584         totalBitmapSize = 0;
585
586         bitmapUpdate.count = bitmapUpdate.number = rows * cols;
587         bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number);
588         bitmapUpdate.rectangles = bitmapData;
589
590         if (!bitmapData)
591                 return -1;
592
593         if ((nWidth % 4) != 0)
594         {
595                 nXSrc -= (nWidth % 4);
596                 nWidth += (nWidth % 4);
597         }
598
599         if ((nHeight % 4) != 0)
600         {
601                 nYSrc -= (nHeight % 4);
602                 nHeight += (nHeight % 4);
603         }
604
605         for (yIdx = 0; yIdx < rows; yIdx++)
606         {
607                 for (xIdx = 0; xIdx < cols; xIdx++)
608                 {
609                         bitmap = &bitmapData[k];
610
611                         bitmap->width = 64;
612                         bitmap->height = 64;
613                         bitmap->destLeft = nXSrc + (xIdx * 64);
614                         bitmap->destTop = nYSrc + (yIdx * 64);
615
616                         if ((bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
617                                 bitmap->width = (nXSrc + nWidth) - bitmap->destLeft;
618
619                         if ((bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
620                                 bitmap->height = (nYSrc + nHeight) - bitmap->destTop;
621
622                         bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
623                         bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
624                         bitmap->compressed = TRUE;
625
626                         if ((bitmap->width < 4) || (bitmap->height < 4))
627                                 continue;
628
629                         if (settings->ColorDepth < 32)
630                         {
631                                 int bitsPerPixel = settings->ColorDepth;
632                                 int bytesPerPixel = (bitsPerPixel + 7) / 8;
633
634                                 DstSize = 64 * 64 * 4;
635                                 buffer = encoder->grid[k];
636
637                                 interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height,
638                                                 pSrcData, SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
639
640                                 bitmap->bitmapDataStream = buffer;
641                                 bitmap->bitmapLength = DstSize;
642                                 bitmap->bitsPerPixel = bitsPerPixel;
643                                 bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
644                                 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
645                         }
646                         else
647                         {
648                                 int dstSize;
649
650                                 buffer = encoder->grid[k];
651                                 data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
652
653                                 buffer = freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat,
654                                                 bitmap->width, bitmap->height, nSrcStep, buffer, &dstSize);
655
656                                 bitmap->bitmapDataStream = buffer;
657                                 bitmap->bitmapLength = dstSize;
658                                 bitmap->bitsPerPixel = 32;
659                                 bitmap->cbScanWidth = bitmap->width * 4;
660                                 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
661                         }
662
663                         bitmap->cbCompFirstRowSize = 0;
664                         bitmap->cbCompMainBodySize = bitmap->bitmapLength;
665
666                         totalBitmapSize += bitmap->bitmapLength;
667                         k++;
668                 }
669         }
670
671         bitmapUpdate.count = bitmapUpdate.number = k;
672
673         updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16;
674
675         if (updateSizeEstimate > maxUpdateSize)
676         {
677                 UINT32 i, j;
678                 UINT32 updateSize;
679                 UINT32 newUpdateSize;
680                 BITMAP_DATA* fragBitmapData;
681
682                 fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k);
683                 bitmapUpdate.rectangles = fragBitmapData;
684
685                 i = j = 0;
686                 updateSize = 1024;
687
688                 while (i < k)
689                 {
690                         newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
691
692                         if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k))
693                         {
694                                 CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
695                                 updateSize = newUpdateSize;
696                         }
697                         else
698                         {
699                                 if ((i + 1) >= k)
700                                 {
701                                         CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
702                                         updateSize = newUpdateSize;
703                                 }
704                                 
705                                 bitmapUpdate.count = bitmapUpdate.number = j;
706                                 IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
707                                 updateSize = 1024;
708                                 j = 0;
709                         }
710                 }
711
712                 free(fragBitmapData);
713         }
714         else
715         {
716                 IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
717         }
718
719         free(bitmapData);
720
721         return 1;
722 }
723
724 int shadow_client_send_surface_update(rdpShadowClient* client)
725 {
726         int status = -1;
727         int nXSrc, nYSrc;
728         int nWidth, nHeight;
729         rdpContext* context;
730         rdpSettings* settings;
731         rdpShadowServer* server;
732         rdpShadowSurface* surface;
733         rdpShadowEncoder* encoder;
734         REGION16 invalidRegion;
735         RECTANGLE_16 surfaceRect;
736         const RECTANGLE_16* extents;
737
738         context = (rdpContext*) client;
739         settings = context->settings;
740         server = client->server;
741         encoder = client->encoder;
742
743         surface = client->inLobby ? client->lobby : server->surface;
744
745         EnterCriticalSection(&(client->lock));
746
747         region16_init(&invalidRegion);
748         region16_copy(&invalidRegion, &(client->invalidRegion));
749         region16_clear(&(client->invalidRegion));
750
751         LeaveCriticalSection(&(client->lock));
752
753         surfaceRect.left = 0;
754         surfaceRect.top = 0;
755         surfaceRect.right = surface->width;
756         surfaceRect.bottom = surface->height;
757
758         region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
759
760         if (server->shareSubRect)
761         {
762                 region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
763         }
764
765         if (region16_is_empty(&invalidRegion))
766         {
767                 region16_uninit(&invalidRegion);
768                 return 1;
769         }
770
771         extents = region16_extents(&invalidRegion);
772
773         nXSrc = extents->left - 0;
774         nYSrc = extents->top - 0;
775         nWidth = extents->right - extents->left;
776         nHeight = extents->bottom - extents->top;
777
778         //WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
779         //      nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
780
781         if (settings->RemoteFxCodec || settings->NSCodec)
782         {
783                 status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
784         }
785         else
786         {
787                 status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
788         }
789
790         region16_uninit(&invalidRegion);
791
792         return status;
793 }
794
795 int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
796 {
797         int index;
798         int numRects = 0;
799         const RECTANGLE_16* rects;
800
801         EnterCriticalSection(&(client->lock));
802
803         rects = region16_rects(region, &numRects);
804
805         for (index = 0; index < numRects; index++)
806         {
807                 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
808         }
809
810         LeaveCriticalSection(&(client->lock));
811
812         return 1;
813 }
814
815 int shadow_client_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied,
816                 UINT32 width, UINT32 height, POINTER_COLOR_UPDATE* pointerColor)
817 {
818         UINT32 x, y;
819         BYTE* pSrc8;
820         BYTE* pDst8;
821         int xorStep;
822         int andStep;
823         UINT32 andBit;
824         BYTE* andBits;
825         UINT32 andPixel;
826         BYTE A, R, G, B;
827
828         xorStep = (width * 3);
829         xorStep += (xorStep % 2);
830
831         andStep = ((width + 7) / 8);
832         andStep += (andStep % 2);
833
834         pointerColor->lengthXorMask = height * xorStep;
835         pointerColor->xorMaskData = (BYTE*) calloc(1, pointerColor->lengthXorMask);
836
837         if (!pointerColor->xorMaskData)
838                 return -1;
839
840         pointerColor->lengthAndMask = height * andStep;
841         pointerColor->andMaskData = (BYTE*) calloc(1, pointerColor->lengthAndMask);
842
843         if (!pointerColor->andMaskData)
844                 return -1;
845
846         for (y = 0; y < height; y++)
847         {
848                 pSrc8 = &pixels[(width * 4) * (height - 1 - y)];
849                 pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
850
851                 andBit = 0x80;
852                 andBits = &(pointerColor->andMaskData[andStep * y]);
853
854                 for (x = 0; x < width; x++)
855                 {
856                         B = *pSrc8++;
857                         G = *pSrc8++;
858                         R = *pSrc8++;
859                         A = *pSrc8++;
860
861                         andPixel = 0;
862
863                         if (A < 64)
864                                 A = 0; /* pixel cannot be partially transparent */
865
866                         if (!A)
867                         {
868                                 /* transparent pixel: XOR = black, AND = 1 */
869                                 andPixel = 1;
870                                 B = G = R = 0;
871                         }
872                         else
873                         {
874                                 if (premultiplied)
875                                 {
876                                         B = (B * 0xFF ) / A;
877                                         G = (G * 0xFF ) / A;
878                                         R = (R * 0xFF ) / A;
879                                 }
880                         }
881
882                         *pDst8++ = B;
883                         *pDst8++ = G;
884                         *pDst8++ = R;
885
886                         if (andPixel) *andBits |= andBit;
887                         if (!(andBit >>= 1)) { andBits++; andBit = 0x80; }
888                 }
889         }
890
891         return 1;
892 }
893
894 int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
895 {
896         rdpContext* context = (rdpContext*) client;
897         rdpUpdate* update = context->update;
898
899         /* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */
900
901         switch(message->id)
902         {
903                 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
904                 {
905                         POINTER_POSITION_UPDATE pointerPosition;
906                         SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) message->wParam;
907
908                         pointerPosition.xPos = msg->xPos;
909                         pointerPosition.yPos = msg->yPos;
910
911                         if (client->activated)
912                         {
913                                 if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
914                                 {
915                                         IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
916
917                                         client->pointerX = msg->xPos;
918                                         client->pointerY = msg->yPos;
919                                 }
920                         }
921                         break;
922                 }
923                 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
924                 {
925                         POINTER_NEW_UPDATE pointerNew;
926                         POINTER_COLOR_UPDATE* pointerColor;
927                         POINTER_CACHED_UPDATE pointerCached;
928                         SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam;
929
930                         ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE));
931
932                         pointerNew.xorBpp = 24;
933                         pointerColor = &(pointerNew.colorPtrAttr);
934
935                         pointerColor->cacheIndex = 0;
936                         pointerColor->xPos = msg->xHot;
937                         pointerColor->yPos = msg->yHot;
938                         pointerColor->width = msg->width;
939                         pointerColor->height = msg->height;
940
941                         pointerCached.cacheIndex = pointerColor->cacheIndex;
942
943                         if (client->activated)
944                         {
945                                 shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied,
946                                                 msg->width, msg->height, pointerColor);
947
948                                 IFCALL(update->pointer->PointerNew, context, &pointerNew);
949                                 IFCALL(update->pointer->PointerCached, context, &pointerCached);
950
951                                 free(pointerColor->xorMaskData);
952                                 free(pointerColor->andMaskData);
953                         }
954                         break;
955                 }
956                 case SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES_ID:
957                 {
958                         SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES* msg = (SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES*) message->wParam;
959                         if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
960                         {
961                                 client->rdpsnd->src_format = msg->audio_format;
962                                 IFCALL(client->rdpsnd->SendSamples, client->rdpsnd, msg->buf, msg->nFrames, msg->wTimestamp);
963                         }
964                         break;
965                 }
966                 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
967                 {
968                         SHADOW_MSG_OUT_AUDIO_OUT_VOLUME* msg = (SHADOW_MSG_OUT_AUDIO_OUT_VOLUME*) message->wParam;
969                         if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
970                         {
971                                 IFCALL(client->rdpsnd->SetVolume, client->rdpsnd, msg->left, msg->right);
972                         }
973                         break;
974                 }
975                 default:
976                         WLog_ERR(TAG, "Unknown message id: %u", message->id);
977                         break;
978         }
979
980         shadow_client_free_queued_message(message);
981
982         return 1;
983 }
984
985 void* shadow_client_thread(rdpShadowClient* client)
986 {
987         DWORD status;
988         DWORD nCount;
989         wMessage message;
990         wMessage pointerPositionMsg;
991         wMessage pointerAlphaMsg;
992         wMessage audioVolumeMsg;
993         HANDLE events[32];
994         HANDLE ClientEvent;
995         HANDLE ChannelEvent;
996         void* UpdateSubscriber;
997         HANDLE UpdateEvent;
998         freerdp_peer* peer;
999         rdpContext* context;
1000         rdpSettings* settings;
1001         rdpShadowServer* server;
1002         rdpShadowScreen* screen;
1003         rdpShadowEncoder* encoder;
1004         rdpShadowSubsystem* subsystem;
1005         wMessageQueue* MsgQueue = client->MsgQueue;
1006
1007         server = client->server;
1008         screen = server->screen;
1009         encoder = client->encoder;
1010         subsystem = server->subsystem;
1011
1012         context = (rdpContext*) client;
1013         peer = context->peer;
1014         settings = peer->settings;
1015
1016         peer->Capabilities = shadow_client_capabilities;
1017         peer->PostConnect = shadow_client_post_connect;
1018         peer->Activate = shadow_client_activate;
1019
1020         shadow_input_register_callbacks(peer->input);
1021
1022         peer->Initialize(peer);
1023
1024         peer->update->RefreshRect = (pRefreshRect)shadow_client_refresh_rect;
1025         peer->update->SuppressOutput = (pSuppressOutput)shadow_client_suppress_output;
1026         peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)shadow_client_surface_frame_acknowledge;
1027
1028         if ((!client->vcm) || (!subsystem->updateEvent))
1029                 goto out;
1030
1031         UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
1032         if (!UpdateSubscriber)
1033                 goto out;
1034
1035         UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
1036         ClientEvent = peer->GetEventHandle(peer);
1037         ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
1038
1039         while (1)
1040         {
1041                 nCount = 0;
1042                 events[nCount++] = UpdateEvent;
1043                 events[nCount++] = ClientEvent;
1044                 events[nCount++] = ChannelEvent;
1045                 events[nCount++] = MessageQueue_Event(MsgQueue);
1046
1047                 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1048
1049                 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
1050                 {
1051                         if (client->activated)
1052                         {
1053                                 int index;
1054                                 int numRects = 0;
1055                                 const RECTANGLE_16* rects;
1056
1057                                 rects = region16_rects(&(subsystem->invalidRegion), &numRects);
1058
1059                                 for (index = 0; index < numRects; index++)
1060                                 {
1061                                         region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
1062                                 }
1063
1064                                 shadow_client_send_surface_update(client);
1065                         }
1066
1067                         /* 
1068                          * The return value of shadow_multiclient_consume is whether or not the subscriber really consumes the event.
1069                          * It's not cared currently.
1070                          */
1071                         (void)shadow_multiclient_consume(UpdateSubscriber);
1072                 }
1073
1074                 if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
1075                 {
1076                         if (!peer->CheckFileDescriptor(peer))
1077                         {
1078                                 WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
1079                                 break;
1080                         }
1081                 }
1082
1083                 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
1084                 {
1085                         if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
1086                         {
1087                                 WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
1088                                 break;
1089                         }
1090                 }
1091
1092                 if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
1093                 {
1094                         /* Drain messages. Pointer update could be accumulated. */
1095                         pointerPositionMsg.id = 0;
1096                         pointerPositionMsg.Free= NULL;
1097                         pointerAlphaMsg.id = 0;
1098                         pointerAlphaMsg.Free = NULL;
1099                         audioVolumeMsg.id = 0;
1100                         audioVolumeMsg.Free = NULL;
1101                         while (MessageQueue_Peek(MsgQueue, &message, TRUE))
1102                         {
1103                                 if (message.id == WMQ_QUIT)
1104                                 {
1105                                         break;
1106                                 }
1107
1108                                 switch(message.id)
1109                                 {
1110                                         case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
1111                                                 /* Abandon previous message */
1112                                                 shadow_client_free_queued_message(&pointerPositionMsg);
1113                                                 CopyMemory(&pointerPositionMsg, &message, sizeof(wMessage));
1114                                                 break;
1115
1116                                         case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
1117                                                 /* Abandon previous message */
1118                                                 shadow_client_free_queued_message(&pointerAlphaMsg);
1119                                                 CopyMemory(&pointerAlphaMsg, &message, sizeof(wMessage));
1120                                                 break;
1121
1122                                         case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
1123                                                 /* Abandon previous message */
1124                                                 shadow_client_free_queued_message(&audioVolumeMsg);
1125                                                 CopyMemory(&audioVolumeMsg, &message, sizeof(wMessage));
1126                                                 break;
1127
1128                                         default:
1129                                                 shadow_client_subsystem_process_message(client, &message);
1130                                                 break;
1131                                 }
1132                         }
1133
1134                         if (message.id == WMQ_QUIT)
1135                         {
1136                                 /* Release stored message */
1137                                 shadow_client_free_queued_message(&pointerPositionMsg);
1138                                 shadow_client_free_queued_message(&pointerAlphaMsg);
1139                                 shadow_client_free_queued_message(&audioVolumeMsg);
1140                                 break;
1141                         }
1142                         else
1143                         {
1144                                 /* Process accumulated messages if needed */
1145                                 if (pointerPositionMsg.id)
1146                                 {
1147                                         shadow_client_subsystem_process_message(client, &pointerPositionMsg);
1148                                 }
1149                                 if (pointerAlphaMsg.id)
1150                                 {
1151                                         shadow_client_subsystem_process_message(client, &pointerAlphaMsg);
1152                                 }
1153                                 if (audioVolumeMsg.id)
1154                                 {
1155                                         shadow_client_subsystem_process_message(client, &audioVolumeMsg);
1156                                 }
1157                         }
1158                 }
1159         }
1160
1161         /* Free channels early because we establish channels in post connect */
1162         shadow_client_channels_free(client);
1163
1164         if (UpdateSubscriber)
1165         {
1166                 shadow_multiclient_release_subscriber(UpdateSubscriber);
1167                 UpdateSubscriber = NULL;
1168         }
1169
1170 out:
1171         peer->Disconnect(peer);
1172         
1173         freerdp_peer_context_free(peer);
1174         freerdp_peer_free(peer);
1175         ExitThread(0);
1176         return NULL;
1177 }
1178
1179 BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
1180 {
1181         rdpShadowClient* client;
1182         rdpShadowServer* server;
1183
1184         server = (rdpShadowServer*) listener->info;
1185
1186         peer->ContextExtra = (void*) server;
1187         peer->ContextSize = sizeof(rdpShadowClient);
1188         peer->ContextNew = (psPeerContextNew) shadow_client_context_new;
1189         peer->ContextFree = (psPeerContextFree) shadow_client_context_free;
1190
1191         if (!freerdp_peer_context_new(peer))
1192                 return FALSE;
1193
1194         client = (rdpShadowClient*) peer->context;
1195
1196         if (!(client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
1197                         shadow_client_thread, client, 0, NULL)))
1198         {
1199                 freerdp_peer_context_free(peer);
1200                 return FALSE;
1201         }
1202
1203         return TRUE;
1204 }
1205
1206 static void shadow_msg_out_addref(wMessage* message)
1207 {
1208         SHADOW_MSG_OUT* msg = (SHADOW_MSG_OUT *)message->wParam;
1209         InterlockedIncrement(&(msg->refCount));
1210 }
1211
1212 static void shadow_msg_out_release(wMessage* message)
1213 {
1214         SHADOW_MSG_OUT* msg = (SHADOW_MSG_OUT *)message->wParam;
1215         if (InterlockedDecrement(&(msg->refCount)) <= 0)
1216         {
1217                 if (msg->Free)
1218                         msg->Free(message->id, msg);
1219         }
1220 }
1221
1222 static BOOL shadow_client_dispatch_msg(rdpShadowClient* client, wMessage* message)
1223 {
1224         /* Add reference when it is posted */
1225         shadow_msg_out_addref(message);
1226         if (MessageQueue_Dispatch(client->MsgQueue, message))
1227         {
1228                 return TRUE;
1229         }
1230         else
1231         {
1232                 /* Release the reference since post failed */
1233                 shadow_msg_out_release(message);
1234                 return FALSE;
1235         }
1236 }
1237
1238 BOOL shadow_client_post_msg(rdpShadowClient* client, void* context, UINT32 type, SHADOW_MSG_OUT* msg, void* lParam)
1239 {
1240         wMessage message = {0};
1241
1242         message.context = context;
1243         message.id = type;
1244         message.wParam = (void *)msg;
1245         message.lParam = lParam;
1246         message.Free = shadow_msg_out_release;
1247
1248         return shadow_client_dispatch_msg(client, &message);
1249 }
1250
1251 int shadow_client_boardcast_msg(rdpShadowServer* server, void* context, UINT32 type, SHADOW_MSG_OUT* msg, void* lParam)
1252 {
1253         wMessage message = {0};
1254         rdpShadowClient* client = NULL;
1255         int count = 0;
1256         int index = 0;
1257
1258         message.context = context;
1259         message.id = type;
1260         message.wParam = (void *)msg;
1261         message.lParam = lParam;
1262         message.Free = shadow_msg_out_release;
1263
1264         /* First add reference as we reference it in this function.
1265      * Therefore it would not be free'ed during post. */
1266         shadow_msg_out_addref(&message);
1267
1268         ArrayList_Lock(server->clients);
1269         for (index = 0; index < ArrayList_Count(server->clients); index++)
1270         {
1271                 client = (rdpShadowClient*)ArrayList_GetItem(server->clients, index);
1272                 if (shadow_client_dispatch_msg(client, &message))
1273                 {
1274                         count++;
1275                 }
1276         }
1277         ArrayList_Unlock(server->clients);
1278
1279     /* Release the reference for this function */
1280         shadow_msg_out_release(&message);
1281
1282         return count;
1283 }
1284
1285 int shadow_client_boardcast_quit(rdpShadowServer* server, int nExitCode)
1286 {
1287         wMessageQueue* queue = NULL;
1288         int count = 0;
1289         int index = 0;
1290
1291         ArrayList_Lock(server->clients);
1292         for (index = 0; index < ArrayList_Count(server->clients); index++)
1293         {
1294                 queue = ((rdpShadowClient*)ArrayList_GetItem(server->clients, index))->MsgQueue;
1295                 if (MessageQueue_PostQuit(queue, nExitCode))
1296                 {
1297                         count++;
1298                 }
1299         }
1300         ArrayList_Unlock(server->clients);
1301
1302         return count;
1303 }