BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream *s) { BYTE* mark; UINT16 length; UINT16 channelId; /* If the MCS message channel has been joined... */ if (rdp->mcs->messageChannelId != 0) { /* Process any MCS message channel PDUs. */ Stream_GetPointer(s, mark); if (rdp_read_header(rdp, s, &length, &channelId)) { if (channelId == rdp->mcs->messageChannelId) { if (rdp_recv_message_channel_pdu(rdp, s) == 0) return TRUE; } } Stream_SetPointer(s, mark); } return FALSE; }
BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s) { BYTE* m; BOOL ret; TS_AM_MEDIA_TYPE mediatype; Stream_GetPointer(s, m); ret = tsmf_codec_parse_media_type(&mediatype, s); Stream_SetPointer(s, m); if (ret) { ITSMFDecoder* decoder = tsmf_load_decoder(decoder_name, &mediatype); if (!decoder) { WLog_WARN(TAG, "Format not supported by decoder %s", decoder_name); ret = FALSE; } else { decoder->Free(decoder); } } return ret; }
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); }
static void wts_write_drdynvc_header(wStream* s, BYTE Cmd, UINT32 ChannelId) { BYTE* bm; int cbChId; Stream_GetPointer(s, bm); Stream_Seek_UINT8(s); cbChId = wts_write_variable_uint(s, ChannelId); *bm = ((Cmd & 0x0F) << 4) | cbChId; }
BOOL tsmf_codec_check_media_type(wStream *s) { BYTE *m; BOOL ret; TS_AM_MEDIA_TYPE mediatype; Stream_GetPointer(s, m); ret = tsmf_codec_parse_media_type(&mediatype, s); Stream_SetPointer(s, m); return ret; }
BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData) { if (Stream_GetRemainingLength(s) < 18) return FALSE; Stream_Read_UINT16(s, bitmapData->destLeft); Stream_Read_UINT16(s, bitmapData->destTop); Stream_Read_UINT16(s, bitmapData->destRight); Stream_Read_UINT16(s, bitmapData->destBottom); Stream_Read_UINT16(s, bitmapData->width); Stream_Read_UINT16(s, bitmapData->height); Stream_Read_UINT16(s, bitmapData->bitsPerPixel); Stream_Read_UINT16(s, bitmapData->flags); Stream_Read_UINT16(s, bitmapData->bitmapLength); if (bitmapData->flags & BITMAP_COMPRESSION) { if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR)) { Stream_Read_UINT16(s, bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ Stream_Read_UINT16(s, bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ Stream_Read_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */ Stream_Read_UINT16(s, bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ bitmapData->bitmapLength = bitmapData->cbCompMainBodySize; } bitmapData->compressed = TRUE; Stream_GetPointer(s, bitmapData->bitmapDataStream); Stream_Seek(s, bitmapData->bitmapLength); } else { if (Stream_GetRemainingLength(s) < bitmapData->bitmapLength) return FALSE; bitmapData->compressed = FALSE; Stream_GetPointer(s, bitmapData->bitmapDataStream); Stream_Seek(s, bitmapData->bitmapLength); } return TRUE; }
BOOL 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. */ if (rdp_recv_out_of_sequence_pdu(rdp, s) != TRUE) return FALSE; return TRUE; } if (rdp->disconnect) return TRUE; if (!rdp_send_confirm_active(rdp)) return FALSE; input_register_client_callbacks(rdp->input); /** * 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) { IFCALL(rdp->update->DesktopResize, rdp->update->context); } rdp->state = CONNECTION_STATE_FINALIZATION; update_reset_state(rdp->update); return rdp_client_connect_finalize(rdp); }
int update_recv_surfcmds(rdpUpdate* update, UINT32 size, wStream* s) { BYTE* mark; UINT16 cmdType; UINT32 cmdLength = 0; while (size > 2) { Stream_GetPointer(s, mark); Stream_Read_UINT16(s, cmdType); size -= 2; switch (cmdType) { case CMDTYPE_SET_SURFACE_BITS: case CMDTYPE_STREAM_SURFACE_BITS: if (update_recv_surfcmd_surface_bits(update, s, &cmdLength) < 0) return -1; break; case CMDTYPE_FRAME_MARKER: if (update_recv_surfcmd_frame_marker(update, s, &cmdLength) < 0) return -1; break; default: WLog_ERR(TAG, "unknown cmdType 0x%X", cmdType); return -1; } size -= cmdLength; if (update->dump_rfx) { /* TODO: treat return values */ pcap_add_record(update->pcap_rfx, mark, cmdLength + 2); pcap_flush(update->pcap_rfx); } } return 0; }
void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { int allocated_formats = 8; BYTE* end_mark; CLIPRDR_FORMAT_NAME* format_name; Stream_GetPointer(s, end_mark); end_mark += length; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) malloc(sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); cliprdr->num_format_names = 0; while (Stream_GetRemainingLength(s) >= 6) { BYTE* p; int name_len; if (cliprdr->num_format_names >= allocated_formats) { allocated_formats *= 2; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) realloc(cliprdr->format_names, sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); } format_name = &cliprdr->format_names[cliprdr->num_format_names++]; Stream_Read_UINT32(s, format_name->id); format_name->name = NULL; format_name->length = 0; for (p = Stream_Pointer(s), name_len = 0; p + 1 < end_mark; p += 2, name_len += 2) { if (*((unsigned short*) p) == 0) break; } format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), name_len / 2, &format_name->name, 0, NULL, NULL); Stream_Seek(s, name_len + 2); } }
BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s) { BYTE* mark; UINT16 length; UINT16 channelId; /* If the MCS message channel has been joined... */ if (rdp->mcs->messageChannelId != 0) { /* Process any MCS message channel PDUs. */ Stream_GetPointer(s, mark); if (rdp_read_header(rdp, s, &length, &channelId)) { if (channelId == rdp->mcs->messageChannelId) { UINT16 securityFlags = 0; if (!rdp_read_security_header(s, &securityFlags, &length)) return FALSE; if (securityFlags & SEC_ENCRYPT) { if (!rdp_decrypt(rdp, s, length, securityFlags)) { WLog_ERR(TAG, "rdp_decrypt failed"); return FALSE; } } if (rdp_recv_message_channel_pdu(rdp, s, securityFlags) == 0) return TRUE; } } Stream_SetPointer(s, mark); } return FALSE; }
void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int server_format_count; int server_version; int i; wStream* output_stream; int output_body_size; unsigned char* output_stream_end; /* Get associated client data */ guac_client* client = rdpsnd->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Get audio stream from client data */ guac_audio_stream* audio = rdp_client->audio; /* Format header */ Stream_Seek(input_stream, 14); Stream_Read_UINT16(input_stream, server_format_count); Stream_Seek_UINT8(input_stream); Stream_Read_UINT16(input_stream, server_version); Stream_Seek_UINT8(input_stream); /* Initialize Client Audio Formats and Version PDU */ output_stream = Stream_New(NULL, 24); Stream_Write_UINT8(output_stream, SNDC_FORMATS); Stream_Write_UINT8(output_stream, 0); /* Fill in body size later */ Stream_Seek_UINT16(output_stream); /* offset = 0x02 */ /* Flags, volume, and pitch */ Stream_Write_UINT32(output_stream, TSSNDCAPS_ALIVE); Stream_Write_UINT32(output_stream, 0); Stream_Write_UINT32(output_stream, 0); /* Datagram port (UDP) */ Stream_Write_UINT16(output_stream, 0); /* Fill in format count later */ Stream_Seek_UINT16(output_stream); /* offset = 0x12 */ /* Version and padding */ Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 6); Stream_Write_UINT8(output_stream, 0); /* Check each server format, respond if supported and audio is enabled */ if (audio != NULL) { for (i=0; i < server_format_count; i++) { unsigned char* format_start; int format_tag; int channels; int rate; int bps; int body_size; /* Remember position in stream */ Stream_GetPointer(input_stream, format_start); /* Read format */ Stream_Read_UINT16(input_stream, format_tag); Stream_Read_UINT16(input_stream, channels); Stream_Read_UINT32(input_stream, rate); Stream_Seek_UINT32(input_stream); Stream_Seek_UINT16(input_stream); Stream_Read_UINT16(input_stream, bps); /* Skip past extra data */ Stream_Read_UINT16(input_stream, body_size); Stream_Seek(input_stream, body_size); /* If PCM, accept */ if (format_tag == WAVE_FORMAT_PCM) { /* If can fit another format, accept it */ if (rdpsnd->format_count < GUAC_RDP_MAX_FORMATS) { /* Add channel */ int current = rdpsnd->format_count++; rdpsnd->formats[current].rate = rate; rdpsnd->formats[current].channels = channels; rdpsnd->formats[current].bps = bps; /* Log format */ guac_client_log(client, GUAC_LOG_INFO, "Accepted format: %i-bit PCM with %i channels at " "%i Hz", bps, channels, rate); /* Ensure audio stream is configured to use accepted * format */ guac_audio_stream_reset(audio, NULL, rate, channels, bps); /* Queue format for sending as accepted */ Stream_EnsureRemainingCapacity(output_stream, 18 + body_size); Stream_Write(output_stream, format_start, 18 + body_size); /* * BEWARE that using Stream_EnsureRemainingCapacity means * that any pointers returned via Stream_GetPointer on * output_stream are invalid. */ } /* Otherwise, log that we dropped one */ else guac_client_log(client, GUAC_LOG_INFO, "Dropped valid format: %i-bit PCM with %i " "channels at %i Hz", bps, channels, rate); } } } /* Otherwise, ignore all supported formats as we do not intend to actually * receive audio */ else guac_client_log(client, GUAC_LOG_DEBUG, "Audio explicitly disabled. Ignoring supported formats."); /* Calculate size of PDU */ output_body_size = Stream_GetPosition(output_stream) - 4; Stream_GetPointer(output_stream, output_stream_end); /* Set body size */ Stream_SetPosition(output_stream, 0x02); Stream_Write_UINT16(output_stream, output_body_size); /* Set format count */ Stream_SetPosition(output_stream, 0x12); Stream_Write_UINT16(output_stream, rdpsnd->format_count); /* Reposition cursor at end (necessary for message send) */ Stream_SetPointer(output_stream, output_stream_end); /* Send accepted formats */ pthread_mutex_lock(&(rdp_client->rdp_lock)); svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream); /* If version greater than 6, must send Quality Mode PDU */ if (server_version >= 6) { /* Always send High Quality for now */ output_stream = Stream_New(NULL, 8); Stream_Write_UINT8(output_stream, SNDC_QUALITYMODE); Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 4); Stream_Write_UINT16(output_stream, HIGH_QUALITY); Stream_Write_UINT16(output_stream, 0); svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream); } pthread_mutex_unlock(&(rdp_client->rdp_lock)); }
static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpecedBlockType) { BOOL rc; int i, close_cnt; int pos; BYTE quant; RFX_TILE* tile; UINT32* quants; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_PROCESS_WORK_PARAM* params = NULL; void *pmem; if (*pExpecedBlockType != WBT_EXTENSION) { WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__); return FALSE; } *pExpecedBlockType = WBT_FRAME_END; if (Stream_GetRemainingLength(s) < 14) { WLog_ERR(TAG, "RfxMessageTileSet packet too small"); return FALSE; } Stream_Read_UINT16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { WLog_ERR(TAG, "invalid subtype, expected CBT_TILESET."); return FALSE; } Stream_Seek_UINT16(s); /* idx (2 bytes), must be set to 0x0000 */ Stream_Seek_UINT16(s); /* properties (2 bytes) */ Stream_Read_UINT8(s, context->numQuant); /* numQuant (1 byte) */ Stream_Seek_UINT8(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->numQuant < 1) { WLog_ERR(TAG, "no quantization value."); return FALSE; } Stream_Read_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ if (message->numTiles < 1) { WLog_ERR(TAG, "no tiles."); return FALSE; } Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (!(pmem = realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)))) return FALSE; quants = context->quants = (UINT32*) pmem; /* quantVals */ if (Stream_GetRemainingLength(s) < (size_t) (context->numQuant * 5)) { WLog_ERR(TAG, "RfxMessageTileSet packet too small for num_quants=%d", context->numQuant); return FALSE; } for (i = 0; i < context->numQuant; i++) { /* RFX_CODEC_QUANT */ Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); WLog_Print(context->priv->log, WLOG_DEBUG, "quant %d (%d %d %d %d %d %d %d %d %d %d).", i, context->quants[i * 10], context->quants[i * 10 + 1], context->quants[i * 10 + 2], context->quants[i * 10 + 3], context->quants[i * 10 + 4], context->quants[i * 10 + 5], context->quants[i * 10 + 6], context->quants[i * 10 + 7], context->quants[i * 10 + 8], context->quants[i * 10 + 9]); } if (!(message->tiles = (RFX_TILE**) calloc(message->numTiles, sizeof(RFX_TILE*)))) { message->numTiles = 0; return FALSE; } if (context->priv->UseThreads) { work_objects = (PTP_WORK*) calloc(message->numTiles, sizeof(PTP_WORK)); params = (RFX_TILE_PROCESS_WORK_PARAM*) calloc(message->numTiles, sizeof(RFX_TILE_PROCESS_WORK_PARAM)); if (!work_objects) { free(params); return FALSE; } if (!params) { free(work_objects); return FALSE; } } /* tiles */ close_cnt = 0; rc = TRUE; for (i = 0; i < message->numTiles; i++) { if (!(tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool))) { WLog_ERR(TAG, "RfxMessageTileSet failed to get tile from object pool"); rc = FALSE; break; } message->tiles[i] = tile; /* RFX_TILE */ if (Stream_GetRemainingLength(s) < 6) { WLog_ERR(TAG, "RfxMessageTileSet packet too small to read tile %d/%d", i, message->numTiles); rc = FALSE; break; } Stream_Read_UINT16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */ if (Stream_GetRemainingLength(s) < blockLen - 6) { WLog_ERR(TAG, "RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->numTiles, blockLen); rc = FALSE; break; } pos = Stream_GetPosition(s) - 6 + blockLen; if (blockType != CBT_TILE) { WLog_ERR(TAG, "unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); rc = FALSE; break; } Stream_Read_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */ Stream_Read_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */ Stream_Read_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */ Stream_Read_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */ Stream_Read_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */ Stream_Read_UINT16(s, tile->YLen); /* YLen (2 bytes) */ Stream_Read_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */ Stream_Read_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */ Stream_GetPointer(s, tile->YData); Stream_Seek(s, tile->YLen); Stream_GetPointer(s, tile->CbData); Stream_Seek(s, tile->CbLen); Stream_GetPointer(s, tile->CrData); Stream_Seek(s, tile->CrLen); tile->x = tile->xIdx * 64; tile->y = tile->yIdx * 64; if (context->priv->UseThreads) { assert(params); params[i].context = context; params[i].tile = message->tiles[i]; if (!(work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv))) { WLog_ERR(TAG, "CreateThreadpoolWork failed."); rc = FALSE; break; } SubmitThreadpoolWork(work_objects[i]); close_cnt = i + 1; } else { rfx_decode_rgb(context, tile, tile->data, 64 * 4); } Stream_SetPosition(s, pos); } if (context->priv->UseThreads) { for (i = 0; i < close_cnt; i++) { WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); CloseThreadpoolWork(work_objects[i]); } free(work_objects); free(params); } for (i = 0; i < message->numTiles; i++) { if (!(tile = message->tiles[i])) continue; tile->YLen = tile->CbLen = tile->CrLen = 0; tile->YData = tile->CbData = tile->CrData = NULL; } return rc; }