2 * FreeRDP: A Remote Desktop Protocol Implementation
4 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
30 #include <freerdp/log.h>
34 #define TAG CLIENT_TAG("shadow")
36 void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
38 rdpSettings* settings;
39 rdpShadowServer* server;
41 server = (rdpShadowServer*) peer->ContextExtra;
42 client->server = server;
43 client->subsystem = server->subsystem;
45 settings = peer->settings;
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;
55 settings->DrawAllowSkipAlpha = TRUE;
56 settings->DrawAllowColorSubsampling = TRUE;
57 settings->DrawAllowDynamicColorFidelity = TRUE;
59 settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
61 settings->RdpSecurity = TRUE;
62 settings->TlsSecurity = TRUE;
63 settings->NlaSecurity = FALSE;
65 settings->CertificateFile = _strdup(server->CertificateFile);
66 settings->PrivateKeyFile = _strdup(server->PrivateKeyFile);
68 settings->RdpKeyFile = _strdup(settings->PrivateKeyFile);
70 if (server->ipcSocket)
72 settings->LyncRdpMode = TRUE;
73 settings->CompressionEnabled = FALSE;
76 client->inLobby = TRUE;
77 client->mayView = server->mayView;
78 client->mayInteract = server->mayInteract;
80 InitializeCriticalSectionAndSpinCount(&(client->lock), 4000);
82 region16_init(&(client->invalidRegion));
84 client->vcm = WTSOpenServerA((LPSTR) peer->context);
86 client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
88 client->encoder = shadow_encoder_new(client);
90 ArrayList_Add(server->clients, (void*) client);
93 void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
95 rdpShadowServer* server = client->server;
97 ArrayList_Remove(server->clients, (void*) client);
99 DeleteCriticalSection(&(client->lock));
101 region16_uninit(&(client->invalidRegion));
103 WTSCloseServer((HANDLE) client->vcm);
105 CloseHandle(client->StopEvent);
109 shadow_surface_free(client->lobby);
110 client->lobby = NULL;
115 shadow_encoder_free(client->encoder);
116 client->encoder = NULL;
120 void shadow_client_message_free(wMessage* message)
122 if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
124 SHADOW_MSG_IN_REFRESH_OUTPUT* wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
129 else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
131 SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
136 BOOL shadow_client_capabilities(freerdp_peer* peer)
141 BOOL shadow_client_post_connect(freerdp_peer* peer)
145 rdpSettings* settings;
146 rdpShadowClient* client;
147 rdpShadowServer* server;
148 RECTANGLE_16 invalidRect;
149 rdpShadowSubsystem* subsystem;
151 client = (rdpShadowClient*) peer->context;
152 settings = peer->settings;
153 server = client->server;
154 subsystem = server->subsystem;
156 if (!server->shareSubRect)
158 width = server->screen->width;
159 height = server->screen->height;
163 width = server->subRect.right - server->subRect.left;
164 height = server->subRect.bottom - server->subRect.top;
167 settings->DesktopWidth = width;
168 settings->DesktopHeight = height;
170 if (settings->ColorDepth == 24)
171 settings->ColorDepth = 16; /* disable 24bpp */
173 if (settings->MultifragMaxRequestSize < 0x3F0000)
174 settings->NSCodec = FALSE; /* NSCodec compressor does not support fragmentation yet */
176 WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)",
177 peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
179 peer->update->DesktopResize(peer->update->context);
181 shadow_client_channels_post_connect(client);
183 invalidRect.left = 0;
185 invalidRect.right = width;
186 invalidRect.bottom = height;
188 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect);
190 shadow_client_init_lobby(client);
194 if (settings->Username && settings->Password)
195 settings->AutoLogonEnabled = TRUE;
197 if (settings->AutoLogonEnabled && server->authentication)
199 if (subsystem->Authenticate)
201 authStatus = subsystem->Authenticate(subsystem,
202 settings->Username, settings->Domain, settings->Password);
206 if (server->authentication)
210 WLog_ERR(TAG, "client authentication failure: %d", authStatus);
218 void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
220 wMessage message = { 0 };
221 SHADOW_MSG_IN_REFRESH_OUTPUT* wParam;
222 wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
224 wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT));
226 if (!wParam || !areas)
233 wParam->numRects = (UINT32) count;
235 if (wParam->numRects)
237 wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16));
246 CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
248 message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
249 message.wParam = (void*) wParam;
250 message.lParam = NULL;
251 message.context = (void*) client;
252 message.Free = shadow_client_message_free;
254 MessageQueue_Dispatch(MsgPipe->In, &message);
257 void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
259 wMessage message = { 0 };
260 SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam;
261 wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
263 wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT));
268 wParam->allow = (UINT32) allow;
271 CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
273 message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
274 message.wParam = (void*) wParam;
275 message.lParam = NULL;
276 message.context = (void*) client;
277 message.Free = shadow_client_message_free;
279 MessageQueue_Dispatch(MsgPipe->In, &message);
282 BOOL shadow_client_activate(freerdp_peer* peer)
284 rdpSettings* settings = peer->settings;
285 rdpShadowClient* client = (rdpShadowClient*) peer->context;
287 if (settings->ClientDir && (strcmp(settings->ClientDir, "librdp") == 0))
289 /* Hack for Mac/iOS/Android Microsoft RDP clients */
291 settings->RemoteFxCodec = FALSE;
293 settings->NSCodec = FALSE;
294 settings->NSCodecAllowSubsampling = FALSE;
296 settings->SurfaceFrameMarkerEnabled = FALSE;
299 client->activated = TRUE;
300 client->inLobby = client->mayView ? FALSE : TRUE;
302 shadow_encoder_reset(client->encoder);
304 shadow_client_refresh_rect(client, 0, NULL);
309 void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
311 SURFACE_FRAME* frame;
312 wListDictionary* frameList;
314 frameList = client->encoder->frameList;
315 frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
319 ListDictionary_Remove(frameList, (void*) (size_t) frameId);
324 int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id)
326 SURFACE_FRAME_MARKER surfaceFrameMarker;
327 rdpContext* context = (rdpContext*) client;
328 rdpUpdate* update = context->update;
330 surfaceFrameMarker.frameAction = action;
331 surfaceFrameMarker.frameId = id;
333 IFCALL(update->SurfaceFrameMarker, context, &surfaceFrameMarker);
338 int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
350 rdpSettings* settings;
351 rdpShadowServer* server;
352 rdpShadowEncoder* encoder;
353 SURFACE_BITS_COMMAND cmd;
355 context = (rdpContext*) client;
356 update = context->update;
357 settings = context->settings;
359 server = client->server;
360 encoder = client->encoder;
362 pSrcData = surface->data;
363 nSrcStep = surface->scanline;
365 if (server->shareSubRect)
368 int subWidth, subHeight;
370 subX = server->subRect.left;
371 subY = server->subRect.top;
372 subWidth = server->subRect.right - server->subRect.left;
373 subHeight = server->subRect.bottom - server->subRect.top;
377 pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
380 if (encoder->frameAck)
381 frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
383 if (settings->RemoteFxCodec)
386 RFX_MESSAGE* messages;
388 shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX);
395 rect.height = nHeight;
397 messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
398 surface->width, surface->height, nSrcStep, &numMessages,
399 settings->MultifragMaxRequestSize);
401 cmd.codecID = settings->RemoteFxCodecId;
405 cmd.destRight = surface->width;
406 cmd.destBottom = surface->height;
409 cmd.width = surface->width;
410 cmd.height = surface->height;
412 for (i = 0; i < numMessages; i++)
414 Stream_SetPosition(s, 0);
415 rfx_write_message(encoder->rfx, s, &messages[i]);
416 rfx_message_free(encoder->rfx, &messages[i]);
418 cmd.bitmapDataLength = Stream_GetPosition(s);
419 cmd.bitmapData = Stream_Buffer(s);
421 first = (i == 0) ? TRUE : FALSE;
422 last = ((i + 1) == numMessages) ? TRUE : FALSE;
424 if (!encoder->frameAck)
425 IFCALL(update->SurfaceBits, update->context, &cmd);
427 IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
432 else if (settings->NSCodec)
434 shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC);
437 Stream_SetPosition(s, 0);
439 pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
441 nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
444 cmd.codecID = settings->NSCodecId;
445 cmd.destLeft = nXSrc;
447 cmd.destRight = cmd.destLeft + nWidth;
448 cmd.destBottom = cmd.destTop + nHeight;
450 cmd.height = nHeight;
452 cmd.bitmapDataLength = Stream_GetPosition(s);
453 cmd.bitmapData = Stream_Buffer(s);
458 if (!encoder->frameAck)
459 IFCALL(update->SurfaceBits, update->context, &cmd);
461 IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
467 int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
480 rdpSettings* settings;
481 UINT32 maxUpdateSize;
482 UINT32 totalBitmapSize;
483 UINT32 updateSizeEstimate;
484 BITMAP_DATA* bitmapData;
485 BITMAP_UPDATE bitmapUpdate;
486 rdpShadowServer* server;
487 rdpShadowEncoder* encoder;
489 context = (rdpContext*) client;
490 update = context->update;
491 settings = context->settings;
493 server = client->server;
494 encoder = client->encoder;
496 maxUpdateSize = settings->MultifragMaxRequestSize;
498 if (settings->ColorDepth < 32)
499 shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED);
501 shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR);
503 pSrcData = surface->data;
504 nSrcStep = surface->scanline;
505 SrcFormat = PIXEL_FORMAT_RGB32;
507 if ((nXSrc % 4) != 0)
509 nWidth += (nXSrc % 4);
510 nXSrc -= (nXSrc % 4);
513 if ((nYSrc % 4) != 0)
515 nHeight += (nYSrc % 4);
516 nYSrc -= (nYSrc % 4);
519 rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
520 cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
525 bitmapUpdate.count = bitmapUpdate.number = rows * cols;
526 bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number);
527 bitmapUpdate.rectangles = bitmapData;
532 if ((nWidth % 4) != 0)
534 nXSrc -= (nWidth % 4);
535 nWidth += (nWidth % 4);
538 if ((nHeight % 4) != 0)
540 nYSrc -= (nHeight % 4);
541 nHeight += (nHeight % 4);
544 for (yIdx = 0; yIdx < rows; yIdx++)
546 for (xIdx = 0; xIdx < cols; xIdx++)
548 bitmap = &bitmapData[k];
552 bitmap->destLeft = nXSrc + (xIdx * 64);
553 bitmap->destTop = nYSrc + (yIdx * 64);
555 if ((bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
556 bitmap->width = (nXSrc + nWidth) - bitmap->destLeft;
558 if ((bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
559 bitmap->height = (nYSrc + nHeight) - bitmap->destTop;
561 bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
562 bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
563 bitmap->compressed = TRUE;
565 if ((bitmap->width < 4) || (bitmap->height < 4))
568 if (settings->ColorDepth < 32)
570 int bitsPerPixel = settings->ColorDepth;
571 int bytesPerPixel = (bitsPerPixel + 7) / 8;
573 DstSize = 64 * 64 * 4;
574 buffer = encoder->grid[k];
576 interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height,
577 pSrcData, SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
579 bitmap->bitmapDataStream = buffer;
580 bitmap->bitmapLength = DstSize;
581 bitmap->bitsPerPixel = bitsPerPixel;
582 bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
583 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
589 buffer = encoder->grid[k];
590 data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
592 buffer = freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat,
593 bitmap->width, bitmap->height, nSrcStep, buffer, &dstSize);
595 bitmap->bitmapDataStream = buffer;
596 bitmap->bitmapLength = dstSize;
597 bitmap->bitsPerPixel = 32;
598 bitmap->cbScanWidth = bitmap->width * 4;
599 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
602 bitmap->cbCompFirstRowSize = 0;
603 bitmap->cbCompMainBodySize = bitmap->bitmapLength;
605 totalBitmapSize += bitmap->bitmapLength;
610 bitmapUpdate.count = bitmapUpdate.number = k;
612 updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16;
614 if (updateSizeEstimate > maxUpdateSize)
618 UINT32 newUpdateSize;
619 BITMAP_DATA* fragBitmapData;
621 fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k);
622 bitmapUpdate.rectangles = fragBitmapData;
629 newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
631 if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k))
633 CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
634 updateSize = newUpdateSize;
640 CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
641 updateSize = newUpdateSize;
644 bitmapUpdate.count = bitmapUpdate.number = j;
645 IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
651 free(fragBitmapData);
655 IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
663 int shadow_client_send_surface_update(rdpShadowClient* client)
669 rdpSettings* settings;
670 rdpShadowServer* server;
671 rdpShadowSurface* surface;
672 rdpShadowEncoder* encoder;
673 REGION16 invalidRegion;
674 RECTANGLE_16 surfaceRect;
675 const RECTANGLE_16* extents;
677 context = (rdpContext*) client;
678 settings = context->settings;
679 server = client->server;
680 encoder = client->encoder;
682 surface = client->inLobby ? client->lobby : server->surface;
684 EnterCriticalSection(&(client->lock));
686 region16_init(&invalidRegion);
687 region16_copy(&invalidRegion, &(client->invalidRegion));
688 region16_clear(&(client->invalidRegion));
690 LeaveCriticalSection(&(client->lock));
692 surfaceRect.left = 0;
694 surfaceRect.right = surface->width;
695 surfaceRect.bottom = surface->height;
697 region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
699 if (server->shareSubRect)
701 region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
704 if (region16_is_empty(&invalidRegion))
706 region16_uninit(&invalidRegion);
710 extents = region16_extents(&invalidRegion);
712 nXSrc = extents->left - 0;
713 nYSrc = extents->top - 0;
714 nWidth = extents->right - extents->left;
715 nHeight = extents->bottom - extents->top;
717 //WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
718 // nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
720 if (settings->RemoteFxCodec || settings->NSCodec)
722 status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
726 status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
729 region16_uninit(&invalidRegion);
734 int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
738 const RECTANGLE_16* rects;
740 EnterCriticalSection(&(client->lock));
742 rects = region16_rects(region, &numRects);
744 for (index = 0; index < numRects; index++)
746 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
749 LeaveCriticalSection(&(client->lock));
754 int shadow_client_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied,
755 UINT32 width, UINT32 height, POINTER_COLOR_UPDATE* pointerColor)
767 xorStep = (width * 3);
768 xorStep += (xorStep % 2);
770 andStep = ((width + 7) / 8);
771 andStep += (andStep % 2);
773 pointerColor->lengthXorMask = height * xorStep;
774 pointerColor->xorMaskData = (BYTE*) calloc(1, pointerColor->lengthXorMask);
776 if (!pointerColor->xorMaskData)
779 pointerColor->lengthAndMask = height * andStep;
780 pointerColor->andMaskData = (BYTE*) calloc(1, pointerColor->lengthAndMask);
782 if (!pointerColor->andMaskData)
785 for (y = 0; y < height; y++)
787 pSrc8 = &pixels[(width * 4) * (height - 1 - y)];
788 pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
791 andBits = &(pointerColor->andMaskData[andStep * y]);
793 for (x = 0; x < width; x++)
803 A = 0; /* pixel cannot be partially transparent */
807 /* transparent pixel: XOR = black, AND = 1 */
825 if (andPixel) *andBits |= andBit;
826 if (!(andBit >>= 1)) { andBits++; andBit = 0x80; }
833 int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
835 rdpContext* context = (rdpContext*) client;
836 rdpUpdate* update = context->update;
838 /* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */
840 if (message->id == SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID)
842 POINTER_POSITION_UPDATE pointerPosition;
843 SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) message->wParam;
845 pointerPosition.xPos = msg->xPos;
846 pointerPosition.yPos = msg->yPos;
848 if (client->activated)
850 if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
852 IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
854 client->pointerX = msg->xPos;
855 client->pointerY = msg->yPos;
861 else if (message->id == SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID)
863 POINTER_NEW_UPDATE pointerNew;
864 POINTER_COLOR_UPDATE* pointerColor;
865 POINTER_CACHED_UPDATE pointerCached;
866 SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam;
868 ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE));
870 pointerNew.xorBpp = 24;
871 pointerColor = &(pointerNew.colorPtrAttr);
873 pointerColor->cacheIndex = 0;
874 pointerColor->xPos = msg->xHot;
875 pointerColor->yPos = msg->yHot;
876 pointerColor->width = msg->width;
877 pointerColor->height = msg->height;
879 pointerCached.cacheIndex = pointerColor->cacheIndex;
881 if (client->activated)
883 shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied,
884 msg->width, msg->height, pointerColor);
886 IFCALL(update->pointer->PointerNew, context, &pointerNew);
887 IFCALL(update->pointer->PointerCached, context, &pointerCached);
889 free(pointerColor->xorMaskData);
890 free(pointerColor->andMaskData);
900 void* shadow_client_thread(rdpShadowClient* client)
912 rdpSettings* settings;
913 rdpShadowServer* server;
914 rdpShadowScreen* screen;
915 rdpShadowEncoder* encoder;
916 rdpShadowSubsystem* subsystem;
917 wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
919 server = client->server;
920 screen = server->screen;
921 encoder = client->encoder;
922 subsystem = server->subsystem;
924 context = (rdpContext*) client;
925 peer = context->peer;
926 settings = peer->settings;
928 peer->Capabilities = shadow_client_capabilities;
929 peer->PostConnect = shadow_client_post_connect;
930 peer->Activate = shadow_client_activate;
932 shadow_input_register_callbacks(peer->input);
934 peer->Initialize(peer);
936 peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect;
937 peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
938 peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge;
940 StopEvent = client->StopEvent;
941 UpdateEvent = subsystem->updateEvent;
942 ClientEvent = peer->GetEventHandle(peer);
943 ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
948 events[nCount++] = StopEvent;
949 events[nCount++] = UpdateEvent;
950 events[nCount++] = ClientEvent;
951 events[nCount++] = ChannelEvent;
952 events[nCount++] = MessageQueue_Event(MsgPipe->Out);
954 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
956 if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
958 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
960 EnterSynchronizationBarrier(&(subsystem->barrier), 0);
966 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
968 if (client->activated)
972 const RECTANGLE_16* rects;
974 rects = region16_rects(&(subsystem->invalidRegion), &numRects);
976 for (index = 0; index < numRects; index++)
978 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
981 shadow_client_send_surface_update(client);
984 EnterSynchronizationBarrier(&(subsystem->barrier), 0);
986 while (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0);
989 if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
991 if (!peer->CheckFileDescriptor(peer))
993 WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
998 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
1000 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
1002 WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
1007 if (WaitForSingleObject(MessageQueue_Event(MsgPipe->Out), 0) == WAIT_OBJECT_0)
1009 if (MessageQueue_Peek(MsgPipe->Out, &message, TRUE))
1011 if (message.id == WMQ_QUIT)
1014 shadow_client_subsystem_process_message(client, &message);
1019 peer->Disconnect(peer);
1021 freerdp_peer_context_free(peer);
1022 freerdp_peer_free(peer);
1029 void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
1031 rdpShadowClient* client;
1032 rdpShadowServer* server;
1034 server = (rdpShadowServer*) listener->info;
1036 peer->ContextExtra = (void*) server;
1037 peer->ContextSize = sizeof(rdpShadowClient);
1038 peer->ContextNew = (psPeerContextNew) shadow_client_context_new;
1039 peer->ContextFree = (psPeerContextFree) shadow_client_context_free;
1040 freerdp_peer_context_new(peer);
1042 client = (rdpShadowClient*) peer->context;
1044 client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
1045 shadow_client_thread, client, 0, NULL);