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