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