static INLINE BOOL shadow_client_rdpgfx_new_surface(rdpShadowClient *client) { UINT error = CHANNEL_RC_OK; RDPGFX_CREATE_SURFACE_PDU createSurface; RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU surfaceToOutput; RdpgfxServerContext* context = client->rdpgfx; rdpSettings* settings = ((rdpContext*) client)->settings; createSurface.width = settings->DesktopWidth; createSurface.height = settings->DesktopHeight; createSurface.pixelFormat = PIXEL_FORMAT_XRGB_8888; createSurface.surfaceId = 0; surfaceToOutput.outputOriginX = 0; surfaceToOutput.outputOriginY = 0; surfaceToOutput.surfaceId = 0; surfaceToOutput.reserved = 0; IFCALLRET(context->CreateSurface, error, context, &createSurface); if (error) { WLog_ERR(TAG, "CreateSurface failed with error %lu", error); return FALSE; } IFCALLRET(context->MapSurfaceToOutput, error, context, &surfaceToOutput); if (error) { WLog_ERR(TAG, "MapSurfaceToOutput failed with error %lu", error); return FALSE; } return TRUE; }
BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; BOOL result = TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, orderInfo->windowId); /* windowId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_ICON) { if (!update_read_window_icon_order(s, orderInfo, &window->window_icon)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "WindowIcon"); IFCALLRET(window->WindowIcon, result, context, orderInfo, &window->window_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) { if (!update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "WindowCachedIcon"); IFCALLRET(window->WindowCachedIcon, result, context, orderInfo, &window->window_cached_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED) { update_read_window_delete_order(s, orderInfo); WLog_Print(update->log, WLOG_DEBUG, "WindowDelete"); IFCALLRET(window->WindowDelete, result, context, orderInfo); } else { if (!update_read_window_state_order(s, orderInfo, &window->window_state)) return FALSE; if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) { WLog_Print(update->log, WLOG_DEBUG, "WindowCreate"); IFCALLRET(window->WindowCreate, result, context, orderInfo, &window->window_state); } else { WLog_Print(update->log, WLOG_DEBUG, "WindowUpdate"); IFCALLRET(window->WindowUpdate, result, context, orderInfo, &window->window_state); } } return result; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, RdpgfxClientContext* context, const RDPGFX_SURFACE_COMMAND* cmd) { UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; if (!rfx_process_message(surface->codecs->rfx, cmd->data, cmd->format, cmd->length, cmd->left, cmd->top, surface->data, surface->format, surface->scanline, surface->height, &surface->invalidRegion)) { WLog_ERR(TAG, "Failed to process RemoteFX message"); return ERROR_INTERNAL_ERROR; } if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context, wStream* s) { RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU pdu; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 12) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT16(s, pdu.timeDiffSE); /* timeDiffSE (2 bytes) */ Stream_Read_UINT16(s, pdu.timeDiffEDR); /* timeDiffEDR (2 bytes) */ if (context) { IFCALLRET(context->QoeFrameAcknowledge, error, context, &pdu); if (error) WLog_ERR(TAG, "context->QoeFrameAcknowledge failed with error %u", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context, wStream* s) { RDPGFX_FRAME_ACKNOWLEDGE_PDU pdu; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 12) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, pdu.queueDepth); /* queueDepth (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ /* totalFramesDecoded (4 bytes) */ Stream_Read_UINT32(s, pdu.totalFramesDecoded); if (context) { IFCALLRET(context->FrameAcknowledge, error, context, &pdu); if (error) WLog_ERR(TAG, "context->FrameAcknowledge failed with error %u", error); } return error; }
static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 responseType, UINT16 sequenceNumber) { BOOL success = TRUE; wStream* s; UINT32 timeDelta; /* Compute the total time */ timeDelta = GetTickCountPrecise() - rdp->autodetect->bandwidthMeasureStartTime; /* Send the result PDU to the server */ s = rdp_message_channel_pdu_init(rdp); if (!s) return FALSE; WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Results PDU -> timeDelta=%u, byteCount=%u", timeDelta, rdp->autodetect->bandwidthMeasureByteCount); Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */ Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */ Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */ Stream_Write_UINT16(s, responseType); /* responseType (1 byte) */ Stream_Write_UINT32(s, timeDelta); /* timeDelta (4 bytes) */ Stream_Write_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */ IFCALLRET(rdp->autodetect->ClientBandwidthMeasureResult, success, rdp->context, rdp->autodetect); if (!success) return FALSE; return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_receive_filecontents_request(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) { CLIPRDR_FILE_CONTENTS_REQUEST request; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientFileContentsRequest"); request.msgType = CB_FILECONTENTS_REQUEST; request.msgFlags = header->msgFlags; request.dataLen = header->dataLen; if (Stream_GetRemainingLength(s) < 28) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */ Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */ Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */ Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */ Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */ Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */ Stream_Read_UINT32(s, request.clipDataId); /* clipDataId (4 bytes) */ IFCALLRET(context->ClientFileContentsRequest, error, context, &request); if (error) WLog_ERR(TAG, "ClientFileContentsRequest failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_receive_format_data_request(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) { CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientFormatDataRequest"); formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; formatDataRequest.msgFlags = header->msgFlags; formatDataRequest.dataLen = header->dataLen; if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ IFCALLRET(context->ClientFormatDataRequest, error, context, &formatDataRequest); if (error) WLog_ERR(TAG, "ClientFormatDataRequest failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 18) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToWindowPdu: surfaceId: %"PRIu16" windowId: 0x%016"PRIX64" mappedWidth: %"PRIu32" mappedHeight: %"PRIu32"", pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); if (context && context->MapSurfaceToWindow) { IFCALLRET(context->MapSurfaceToWindow, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->MapSurfaceToWindow failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 12) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.reserved); /* reserved (2 bytes) */ Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToOutputPdu: surfaceId: %"PRIu16" outputOriginX: %"PRIu32" outputOriginY: %"PRIu32"", pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); if (context) { IFCALLRET(context->MapSurfaceToOutput, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->MapSurfaceToOutput failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, const RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) { UINT status = CHANNEL_RC_OK; UINT16 index; BOOL sameSurface; UINT32 nWidth, nHeight; const RECTANGLE_16* rectSrc; RDPGFX_POINT16* destPt; RECTANGLE_16 invalidRect; gdiGfxSurface* surfaceSrc; gdiGfxSurface* surfaceDst; rdpGdi* gdi = (rdpGdi*) context->custom; rectSrc = &(surfaceToSurface->rectSrc); surfaceSrc = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); sameSurface = (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE; if (!sameSurface) surfaceDst = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); else surfaceDst = surfaceSrc; if (!surfaceSrc || !surfaceDst) return ERROR_INTERNAL_ERROR; nWidth = rectSrc->right - rectSrc->left; nHeight = rectSrc->bottom - rectSrc->top; for (index = 0; index < surfaceToSurface->destPtsCount; index++) { destPt = &surfaceToSurface->destPts[index]; if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format, surfaceSrc->scanline, rectSrc->left, rectSrc->top, NULL, FREERDP_FLIP_NONE)) return ERROR_INTERNAL_ERROR; invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + rectSrc->right; invalidRect.bottom = destPt->y + rectSrc->bottom; region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect); IFCALL(context->UpdateSurfaceArea, context, surfaceDst->surfaceId, 1, &invalidRect); } if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_delete_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_DELETE_SURFACE_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 2) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ WLog_DBG(TAG, "RecvDeleteSurfacePdu: surfaceId: %d", pdu.surfaceId); if (context) { IFCALLRET(context->DeleteSurface, error, context, &pdu); if (error) WLog_ERR(TAG, "context->DeleteSurface failed with error %u", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT read_cs_ready_message(RdpeiServerContext *context, wStream *s) { UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 10) { WLog_ERR(TAG, "Not enought data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, context->protocolFlags); Stream_Read_UINT32(s, context->clientVersion); Stream_Read_UINT16(s, context->maxTouchPoints); switch (context->clientVersion) { case RDPINPUT_PROTOCOL_V10: case RDPINPUT_PROTOCOL_V101: break; default: WLog_ERR(TAG, "unhandled RPDEI protocol version 0x%x", context->clientVersion); break; } IFCALLRET(context->onClientReady, error, context); if (error) WLog_ERR(TAG, "context->onClientReady failed with error %lu", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_START_FRAME_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 8) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ WLog_DBG(TAG, "RecvStartFramePdu: frameId: %d timestamp: 0x%04X", pdu.frameId, pdu.timestamp); if (context) { IFCALLRET(context->StartFrame, error, context, &pdu); if (error) WLog_ERR(TAG, "context->StartFrame failed with error %lu", error); } gfx->UnacknowledgedFrames++; return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_evict_cache_entry_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 2) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvEvictCacheEntryPdu: cacheSlot: %"PRIu16"", pdu.cacheSlot); if (context) { IFCALLRET(context->EvictCacheEntry, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->EvictCacheEntry failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_receive_unlock_clipdata(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) { CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientUnlockClipData"); unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = header->msgFlags; unlockClipboardData.dataLen = header->dataLen; if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ IFCALLRET(context->ClientUnlockClipboardData, error, context, &unlockClipboardData); if (error) WLog_ERR(TAG, "ClientUnlockClipboardData failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_CREATE_SURFACE_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 7) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.width); /* width (2 bytes) */ Stream_Read_UINT16(s, pdu.height); /* height (2 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* RDPGFX_PIXELFORMAT (1 byte) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvCreateSurfacePdu: surfaceId: %"PRIu16" width: %"PRIu16" height: %"PRIu16" pixelFormat: 0x%02"PRIX8"", pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); if (context) { IFCALLRET(context->CreateSurface, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->CreateSurface failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_receive_format_data_response(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) { CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientFormatDataResponse"); formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; formatDataResponse.msgFlags = header->msgFlags; formatDataResponse.dataLen = header->dataLen; formatDataResponse.requestedFormatData = NULL; if (Stream_GetRemainingLength(s) < header->dataLen) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } if (header->dataLen) { formatDataResponse.requestedFormatData = (BYTE*) malloc(header->dataLen); Stream_Read(s, formatDataResponse.requestedFormatData, header->dataLen); } IFCALLRET(context->ClientFormatDataResponse, error, context, &formatDataResponse); if (error) WLog_ERR(TAG, "ClientFormatDataResponse failed with error %lu!", error); free(formatDataResponse.requestedFormatData); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_START_FRAME_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < RDPGFX_START_FRAME_PDU_SIZE) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %"PRIu32" timestamp: 0x%08"PRIX32"", pdu.frameId, pdu.timestamp); gfx->StartDecodingTime = GetTickCountPrecise(); if (context) { IFCALLRET(context->StartFrame, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->StartFrame failed with error %"PRIu32"", error); } gfx->UnacknowledgedFrames++; return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_receive_filecontents_response(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) { CLIPRDR_FILE_CONTENTS_RESPONSE response; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientFileContentsResponse"); response.msgType = CB_FILECONTENTS_RESPONSE; response.msgFlags = header->msgFlags; response.dataLen = header->dataLen; if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */ response.cbRequested = header->dataLen - 4; response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */ IFCALLRET(context->ServerFileContentsResponse, error, context, &response); if (error) WLog_ERR(TAG, "ServerFileContentsResponse failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_DELETE_ENCODING_CONTEXT_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 6) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteEncodingContextPdu: surfaceId: %"PRIu16" codecContextId: %"PRIu32"", pdu.surfaceId, pdu.codecContextId); if (context) { IFCALLRET(context->DeleteEncodingContext, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->DeleteEncodingContext failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) { UINT error = CHANNEL_RC_OK; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; switch (cmd->codecId) { case RDPGFX_CODECID_AVC420: if ((error = rdpgfx_decode_AVC420(gfx, cmd))) { WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %"PRIu32"", error); return error; } break; case RDPGFX_CODECID_AVC444: if ((error = rdpgfx_decode_AVC444(gfx, cmd))) { WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %"PRIu32"", error); return error; } break; default: if (context) { IFCALLRET(context->SurfaceCommand, error, context, cmd); if (error) WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); } break; } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { UINT16 index; RDPGFX_POINT16* destPt; RDPGFX_CACHE_TO_SURFACE_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 6) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */ if (Stream_GetRemainingLength(s) < (size_t)(pdu.destPtsCount * 4)) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); if (!pdu.destPts) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } for (index = 0; index < pdu.destPtsCount; index++) { destPt = &(pdu.destPts[index]); if ((error = rdpgfx_read_point16(s, destPt))) { WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_read_point16 failed with error %"PRIu32"", error); free(pdu.destPts); return error; } } WLog_Print(gfx->log, WLOG_DEBUG, "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %"PRIu16" surfaceId: %"PRIu16" destPtsCount: %"PRIu16"", pdu.cacheSlot, pdu.surfaceId, pdu.destPtsCount); if (context) { IFCALLRET(context->CacheToSurface, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->CacheToSurface failed with error %"PRIu32"", error); } free(pdu.destPts); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; formatDataRequest.msgFlags = msgFlags; formatDataRequest.dataLen = dataLen; Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest); if (error) WLog_ERR(TAG, "ServerFormatDataRequest failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* context, const RDPGFX_SURFACE_COMMAND* cmd) { UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->data, cmd->format, 0, 0, 0, NULL, FREERDP_FLIP_NONE)) return ERROR_INTERNAL_ERROR; invalidRect.left = cmd->left; invalidRect.top = cmd->top; invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context, wStream* s) { UINT16 index; RDPGFX_CACHE_IMPORT_OFFER_PDU pdu; RDPGFX_CACHE_ENTRY_METADATA* cacheEntries; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 2) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } /* cacheEntriesCount (2 bytes) */ Stream_Read_UINT16(s, pdu.cacheEntriesCount); if (pdu.cacheEntriesCount <= 0) { /* According to the latest spec, capsSetCount <= 3 */ WLog_ERR(TAG, "Invalid cacheEntriesCount: %u", pdu.cacheEntriesCount); return ERROR_INVALID_DATA; } if (Stream_GetRemainingLength(s) < (pdu.cacheEntriesCount * 12)) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } pdu.cacheEntries = (RDPGFX_CACHE_ENTRY_METADATA*) calloc(pdu.cacheEntriesCount, sizeof(RDPGFX_CACHE_ENTRY_METADATA)); if (!pdu.cacheEntries) { WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } for (index = 0; index < pdu.cacheEntriesCount; index++) { cacheEntries = &(pdu.cacheEntries[index]); Stream_Read_UINT64(s, cacheEntries->cacheKey); /* cacheKey (8 bytes) */ /* bitmapLength (4 bytes) */ Stream_Read_UINT32(s, cacheEntries->bitmapLength); } if (context) { IFCALLRET(context->CacheImportOffer, error, context, &pdu); if (error) WLog_ERR(TAG, "context->CacheImportOffer failed with error %u", error); } free(pdu.cacheEntries); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, const RDPGFX_SURFACE_COMMAND* cmd) { UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; WLog_WARN(TAG, "TODO gdi_SurfaceCommand_Alpha: status: %d", status); /* fill with green for now to distinguish from the rest */ if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, 0x00FF00)) return ERROR_INTERNAL_ERROR; invalidRect.left = cmd->left; invalidRect.top = cmd->top; invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "UnlockClipData"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "not enought remaining data"); return ERROR_INVALID_DATA; } unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = flags; unlockClipboardData.dataLen = length; Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ IFCALLRET(context->ServerUnlockClipboardData, error, context, &unlockClipboardData); if (error) WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %lu!", error); return error; }
int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s) { BYTE* mark; UINT16 width; UINT16 height; width = rdp->settings->DesktopWidth; height = rdp->settings->DesktopHeight; Stream_GetPointer(s, mark); if (!rdp_recv_demand_active(rdp, s)) { UINT16 channelId; Stream_SetPointer(s, mark); rdp_recv_get_active_header(rdp, s, &channelId); /* Was Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH); * but the headers aren't always that length, * so that could result in a bad offset. */ return rdp_recv_out_of_sequence_pdu(rdp, s); } if (freerdp_shall_disconnect(rdp->instance)) return 0; if (!rdp_send_confirm_active(rdp)) return -1; if (!input_register_client_callbacks(rdp->input)) { WLog_ERR(TAG, "error registering client callbacks"); return -1; } /** * The server may request a different desktop size during Deactivation-Reactivation sequence. * In this case, the UI should be informed and do actual window resizing at this point. */ if (width != rdp->settings->DesktopWidth || height != rdp->settings->DesktopHeight) { BOOL status = TRUE; IFCALLRET(rdp->update->DesktopResize, status, rdp->update->context); if (!status) { WLog_ERR(TAG, "client desktop resize callback failed"); return -1; } } rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION); return rdp_client_connect_finalize(rdp); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_PARTICIPANT_CREATED_PDU pdu; UINT error; context = encomsp_get_client_interface(encomsp); if (!context) return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 10) { WLog_ERR(TAG, "Not enought data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ Stream_Read_UINT32(s, pdu.GroupId); /* GroupId (4 bytes) */ Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ if ((error = encomsp_read_unicode_string(s, &(pdu.FriendlyName)))) { WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %lu", error); return error; } end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) { WLog_ERR(TAG, "Not enought data!"); return ERROR_INVALID_DATA; } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) { WLog_ERR(TAG, "Not enought data!"); return ERROR_INVALID_DATA; } Stream_SetPosition(s, (beg + header->Length)); } IFCALLRET(context->ParticipantCreated, error, context, &pdu); if (error) WLog_ERR(TAG, "context->ParticipantCreated failed with error %lu", error); return error; }