void test_stream(void) { STREAM * stream; int pos; uint32 n; uint64 n64; stream = stream_new(1); pos = stream_get_pos(stream); stream_write_uint8(stream, 0xFE); stream_check_size(stream, 14); stream_write_uint16(stream, 0x0102); stream_write_uint32(stream, 0x03040506); stream_write_uint64(stream, 0x0708091011121314LL); /* freerdp_hexdump(stream->buffer, 15); */ stream_set_pos(stream, pos); stream_seek(stream, 3); stream_read_uint32(stream, n); stream_read_uint64(stream, n64); CU_ASSERT(n == 0x03040506); CU_ASSERT(n64 == 0x0708091011121314LL); stream_free(stream); }
static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s, UINT32 *length) { int pos; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; if(stream_get_left(s) < 20) return FALSE; stream_read_UINT16(s, cmd->destLeft); stream_read_UINT16(s, cmd->destTop); stream_read_UINT16(s, cmd->destRight); stream_read_UINT16(s, cmd->destBottom); stream_read_BYTE(s, cmd->bpp); stream_seek(s, 2); /* reserved1, reserved2 */ stream_read_BYTE(s, cmd->codecID); stream_read_UINT16(s, cmd->width); stream_read_UINT16(s, cmd->height); stream_read_UINT32(s, cmd->bitmapDataLength); if(stream_get_left(s) < cmd->bitmapDataLength) return FALSE; pos = stream_get_pos(s) + cmd->bitmapDataLength; cmd->bitmapData = stream_get_tail(s); IFCALL(update->SurfaceBits, update->context, cmd); stream_set_pos(s, pos); *length = 20 + cmd->bitmapDataLength; return TRUE; }
static void rfx_compose_message_tile(RFX_CONTEXT* context, STREAM* s, BYTE* tile_data, int tile_width, int tile_height, int rowstride, const UINT32* quantVals, int quantIdxY, int quantIdxCb, int quantIdxCr, int xIdx, int yIdx) { int YLen = 0; int CbLen = 0; int CrLen = 0; int start_pos, end_pos; stream_check_size(s, 19); start_pos = stream_get_pos(s); stream_write_UINT16(s, CBT_TILE); /* BlockT.blockType */ stream_seek_UINT32(s); /* set BlockT.blockLen later */ stream_write_BYTE(s, quantIdxY); stream_write_BYTE(s, quantIdxCb); stream_write_BYTE(s, quantIdxCr); stream_write_UINT16(s, xIdx); stream_write_UINT16(s, yIdx); stream_seek(s, 6); /* YLen, CbLen, CrLen */ rfx_encode_rgb(context, tile_data, tile_width, tile_height, rowstride, quantVals + quantIdxY * 10, quantVals + quantIdxCb * 10, quantVals + quantIdxCr * 10, s, &YLen, &CbLen, &CrLen); DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", xIdx, yIdx, tile_width, tile_height, YLen, CbLen, CrLen); end_pos = stream_get_pos(s); stream_set_pos(s, start_pos + 2); stream_write_UINT32(s, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */ stream_set_pos(s, start_pos + 13); stream_write_UINT16(s, YLen); stream_write_UINT16(s, CbLen); stream_write_UINT16(s, CrLen); stream_set_pos(s, end_pos); }
static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* data_in, int in_length) { int pos; uint32 ChannelId; ChannelId = drdynvc_read_variable_uint(data_in, cbChId); pos = stream_get_pos(data_in); DEBUG_DVC("ChannelId=%d", ChannelId); return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, stream_get_tail(data_in), in_length - pos); }
void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* s) { int pos; uint32 dataLen; pos = stream_get_pos(s); dataLen = pos - 8; stream_set_pos(s, 4); stream_write_uint32(s, dataLen); stream_set_pos(s, pos); svc_plugin_send((rdpSvcPlugin*) cliprdr, s); }
void stream_extend(STREAM* stream, int request_size) { int original_size; int increased_size; int pos; pos = stream_get_pos(stream); original_size = stream->size; increased_size = (request_size > original_size ? request_size : original_size); stream->size += increased_size; stream->data = (uint8*)xrealloc(stream->data, stream->size); memset(stream->data + original_size, 0, increased_size); stream_set_pos(stream, pos); }
BOOL gcc_read_client_data_blocks(STREAM* s, rdpSettings* settings, int length) { UINT16 type; UINT16 blockLength; int pos; while (length > 0) { pos = stream_get_pos(s); gcc_read_user_data_header(s, &type, &blockLength); switch (type) { case CS_CORE: if (!gcc_read_client_core_data(s, settings, blockLength - 4)) return FALSE; break; case CS_SECURITY: if (!gcc_read_client_security_data(s, settings, blockLength - 4)) return FALSE; break; case CS_NET: if (!gcc_read_client_network_data(s, settings, blockLength - 4)) return FALSE; break; case CS_CLUSTER: if (!gcc_read_client_cluster_data(s, settings, blockLength - 4)) return FALSE; break; case CS_MONITOR: if (!gcc_read_client_monitor_data(s, settings, blockLength - 4)) return FALSE; break; default: break; } length -= blockLength; stream_set_pos(s, pos + blockLength); } return TRUE; }
static void irp_complete(IRP* irp) { int pos; DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, 12); stream_write_uint32(irp->output, irp->IoStatus); stream_set_pos(irp->output, pos); svc_plugin_send(irp->devman->plugin, irp->output); irp->output = NULL; irp_free(irp); }
static void scard_irp_complete(IRP* irp) { /* This function is (mostly) a copy of the statically-declared "irp_complete()" * function except that this function adds extra operations for the * smart card's handling of duplicate "CompletionID"s. This function needs * to be in this file so that "scard_irp_request()" can reference it. */ int pos; boolean duplicate; SCARD_DEVICE* scard = (SCARD_DEVICE*)irp->device; DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, 12); stream_write_uint32(irp->output, irp->IoStatus); stream_set_pos(irp->output, pos); /* Begin TS Client defect workaround. */ freerdp_mutex_lock(scard->CompletionIdsMutex); /* Remove from the list the item identified by the CompletionID. * The function returns whether or not it was a duplicate CompletionID. */ duplicate = scard_check_for_duplicate_id(scard, irp->CompletionId); freerdp_mutex_unlock(scard->CompletionIdsMutex); if (false == duplicate) { svc_plugin_send(irp->devman->plugin, irp->output); irp->output = NULL; } /* End TS Client defect workaround. */ /* irp_free(irp); The "irp_free()" function is statically-declared * and so is not available to be called * here. Instead, call it indirectly by calling * the IRP's "Discard()" function, * which has already been assigned * to point to "irp_free()" in "irp_new()". */ irp->Discard(irp); }
void serial_get_timeouts(SERIAL_DEVICE* serial, IRP* irp, uint32* timeout, uint32* interval_timeout) { SERIAL_TTY* tty; uint32 Length; uint32 pos; pos = stream_get_pos(irp->input); stream_read_uint32(irp->input, Length); stream_set_pos(irp->input, pos); DEBUG_SVC("length read %u", Length); tty = serial->tty; *timeout = (tty->read_total_timeout_multiplier * Length) + tty->read_total_timeout_constant; *interval_timeout = tty->read_interval_timeout; DEBUG_SVC("timeouts %u %u", *timeout, *interval_timeout); }
static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { int pos; int error; UINT32 ChannelId; STREAM* data_out; ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = stream_get_pos(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, stream_get_tail(s)); error = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) stream_get_tail(s)); data_out = stream_new(pos + 4); stream_write_BYTE(data_out, 0x10 | cbChId); stream_set_pos(s, 1); stream_copy(data_out, s, pos - 1); if (error == 0) { DEBUG_DVC("channel created"); stream_write_UINT32(data_out, 0); } else { DEBUG_DVC("no listener"); stream_write_UINT32(data_out, (UINT32)(-1)); } error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); if (error != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } return 0; }
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s) { int pos; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; stream_read_uint16(s, cmd->destLeft); stream_read_uint16(s, cmd->destTop); stream_read_uint16(s, cmd->destRight); stream_read_uint16(s, cmd->destBottom); stream_read_uint8(s, cmd->bpp); stream_seek(s, 2); /* reserved1, reserved2 */ stream_read_uint8(s, cmd->codecID); stream_read_uint16(s, cmd->width); stream_read_uint16(s, cmd->height); stream_read_uint32(s, cmd->bitmapDataLength); pos = stream_get_pos(s) + cmd->bitmapDataLength; cmd->bitmapData = stream_get_tail(s); IFCALL(update->SurfaceBits, update->context, cmd); stream_set_pos(s, pos); return 20 + cmd->bitmapDataLength; }
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length) { int pos; STREAM* s; UINT32 blockLen; UINT32 blockType; RFX_MESSAGE* message; message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); ZeroMemory(message, sizeof(RFX_MESSAGE)); s = stream_new(0); stream_attach(s, data, length); while (stream_get_left(s) > 6) { /* RFX_BLOCKT */ stream_read_UINT16(s, blockType); /* blockType (2 bytes) */ stream_read_UINT32(s, blockLen); /* blockLen (4 bytes) */ DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen); if (blockLen == 0) { DEBUG_WARN("zero blockLen"); break; } if (stream_get_left(s) < blockLen - 6) { DEBUG_WARN("rfx_process_message: packet too small for blocklen=%d", blockLen); break; } pos = stream_get_pos(s) - 6 + blockLen; if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ /* codecId (1 byte) must be set to 0x01 */ /* channelId (1 byte) must be set to 0x00 */ if (!stream_skip(s, 2)) { DEBUG_WARN("rfx_process_message: unable to skip RFX_CODEC_CHANNELT"); break; } } switch (blockType) { case WBT_SYNC: rfx_process_message_sync(context, s); break; case WBT_CODEC_VERSIONS: rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: rfx_process_message_channels(context, s); break; case WBT_CONTEXT: rfx_process_message_context(context, s); break; case WBT_FRAME_BEGIN: rfx_process_message_frame_begin(context, message, s); break; case WBT_FRAME_END: rfx_process_message_frame_end(context, message, s); break; case WBT_REGION: rfx_process_message_region(context, message, s); break; case WBT_EXTENSION: rfx_process_message_tileset(context, message, s); break; default: DEBUG_WARN("unknown blockType 0x%X", blockType); break; } stream_set_pos(s, pos); } stream_detach(s); stream_free(s); return message; }
static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; int pos; BYTE quant; UINT32* quants; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_WORK_PARAM* params = NULL; if (stream_get_left(s) < 14) { DEBUG_WARN("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) { DEBUG_WARN("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_BYTE(s, context->num_quants); /* numQuant (1 byte) */ stream_seek_BYTE(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->num_quants < 1) { DEBUG_WARN("no quantization value."); return TRUE; } stream_read_UINT16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { DEBUG_WARN("no tiles."); return TRUE; } stream_read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) context->quants = (UINT32*) realloc((void*) context->quants, context->num_quants * 10 * sizeof(UINT32)); else context->quants = (UINT32*) malloc(context->num_quants * 10 * sizeof(UINT32)); quants = context->quants; /* quantVals */ if (stream_get_left(s) < context->num_quants * 5) { DEBUG_WARN("RfxMessageTileSet packet too small for num_quants=%d", context->num_quants); return FALSE; } for (i = 0; i < context->num_quants; i++) { /* RFX_CODEC_QUANT */ stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); DEBUG_RFX("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]); } message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->num_tiles); ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->num_tiles); if (context->priv->UseThreads) { work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->num_tiles); params = (RFX_TILE_WORK_PARAM*) malloc(sizeof(RFX_TILE_WORK_PARAM) * message->num_tiles); } /* tiles */ for (i = 0; i < message->num_tiles; i++) { /* RFX_TILE */ if (stream_get_left(s) < 6) { DEBUG_WARN("RfxMessageTileSet packet too small to read tile %d/%d", i, message->num_tiles); return FALSE; } 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_get_left(s) < blockLen - 6) { DEBUG_WARN("RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->num_tiles, blockLen); return FALSE; } pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } message->tiles[i] = rfx_tile_pool_take(context); if (context->priv->UseThreads) { params[i].context = context; params[i].tile = message->tiles[i]; CopyMemory(&(params[i].s), s, sizeof(STREAM)); work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); SubmitThreadpoolWork(work_objects[i]); } else { rfx_process_message_tile(context, message->tiles[i], s); } stream_set_pos(s, pos); } if (context->priv->UseThreads) { for (i = 0; i < message->num_tiles; i++) WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); free(work_objects); free(params); } return TRUE; }
static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* s, BYTE* image_data, int width, int height, int rowstride) { int i; int size; int start_pos, end_pos; int numQuants; const UINT32* quantVals; const UINT32* quantValsPtr; int quantIdxY; int quantIdxCb; int quantIdxCr; int numTiles; int numTilesX; int numTilesY; int xIdx; int yIdx; int tilesDataSize; if (context->num_quants == 0) { numQuants = 1; quantVals = rfx_default_quantization_values; quantIdxY = 0; quantIdxCb = 0; quantIdxCr = 0; } else { numQuants = context->num_quants; quantVals = context->quants; quantIdxY = context->quant_idx_y; quantIdxCb = context->quant_idx_cb; quantIdxCr = context->quant_idx_cr; } numTilesX = (width + 63) / 64; numTilesY = (height + 63) / 64; numTiles = numTilesX * numTilesY; size = 22 + numQuants * 5; stream_check_size(s, size); start_pos = stream_get_pos(s); stream_write_UINT16(s, WBT_EXTENSION); /* CodecChannelT.blockType */ stream_seek_UINT32(s); /* set CodecChannelT.blockLen later */ stream_write_BYTE(s, 1); /* CodecChannelT.codecId */ stream_write_BYTE(s, 0); /* CodecChannelT.channelId */ stream_write_UINT16(s, CBT_TILESET); /* subtype */ stream_write_UINT16(s, 0); /* idx */ stream_write_UINT16(s, context->properties); /* properties */ stream_write_BYTE(s, numQuants); /* numQuants */ stream_write_BYTE(s, 0x40); /* tileSize */ stream_write_UINT16(s, numTiles); /* numTiles */ stream_seek_UINT32(s); /* set tilesDataSize later */ quantValsPtr = quantVals; for (i = 0; i < numQuants * 5; i++) { stream_write_BYTE(s, quantValsPtr[0] + (quantValsPtr[1] << 4)); quantValsPtr += 2; } DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, rowstride); end_pos = stream_get_pos(s); for (yIdx = 0; yIdx < numTilesY; yIdx++) { for (xIdx = 0; xIdx < numTilesX; xIdx++) { rfx_compose_message_tile(context, s, image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel, (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64, (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64, rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx); } } tilesDataSize = stream_get_pos(s) - end_pos; size += tilesDataSize; end_pos = stream_get_pos(s); stream_set_pos(s, start_pos + 2); stream_write_UINT32(s, size); /* CodecChannelT.blockLen */ stream_set_pos(s, start_pos + 18); stream_write_UINT32(s, tilesDataSize); stream_set_pos(s, end_pos); }
/* receives a list of server supported formats and returns a list of client supported formats */ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint16 wNumberOfFormats; uint16 nFormat; uint16 wVersion; STREAM* data_out; rdpsndFormat* out_formats; uint16 n_out_formats; rdpsndFormat* format; uint8* format_mark; uint8* data_mark; int pos; rdpsnd_free_supported_formats(rdpsnd); stream_seek_uint32(data_in); /* dwFlags */ stream_seek_uint32(data_in); /* dwVolume */ stream_seek_uint32(data_in); /* dwPitch */ stream_seek_uint16(data_in); /* wDGramPort */ stream_read_uint16(data_in, wNumberOfFormats); stream_read_uint8(data_in, rdpsnd->cBlockNo); /* cLastBlockConfirmed */ stream_read_uint16(data_in, wVersion); stream_seek_uint8(data_in); /* bPad */ DEBUG_SVC("wNumberOfFormats %d wVersion %d", wNumberOfFormats, wVersion); if (wNumberOfFormats < 1) { DEBUG_WARN("wNumberOfFormats is 0"); return; } out_formats = (rdpsndFormat*)xzalloc(wNumberOfFormats * sizeof(rdpsndFormat)); n_out_formats = 0; data_out = stream_new(24); stream_write_uint8(data_out, SNDC_FORMATS); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_seek_uint16(data_out); /* BodySize */ stream_write_uint32(data_out, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */ stream_write_uint32(data_out, 0xFFFFFFFF); /* dwVolume */ stream_write_uint32(data_out, 0); /* dwPitch */ stream_write_uint16_be(data_out, 0); /* wDGramPort */ stream_seek_uint16(data_out); /* wNumberOfFormats */ stream_write_uint8(data_out, 0); /* cLastBlockConfirmed */ stream_write_uint16(data_out, 6); /* wVersion */ stream_write_uint8(data_out, 0); /* bPad */ for (nFormat = 0; nFormat < wNumberOfFormats; nFormat++) { stream_get_mark(data_in, format_mark); format = &out_formats[n_out_formats]; stream_read_uint16(data_in, format->wFormatTag); stream_read_uint16(data_in, format->nChannels); stream_read_uint32(data_in, format->nSamplesPerSec); stream_seek_uint32(data_in); /* nAvgBytesPerSec */ stream_read_uint16(data_in, format->nBlockAlign); stream_read_uint16(data_in, format->wBitsPerSample); stream_read_uint16(data_in, format->cbSize); stream_get_mark(data_in, data_mark); stream_seek(data_in, format->cbSize); format->data = NULL; DEBUG_SVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d nBlockAlign=%d wBitsPerSample=%d", format->wFormatTag, format->nChannels, format->nSamplesPerSec, format->nBlockAlign, format->wBitsPerSample); if (rdpsnd->fixed_format > 0 && rdpsnd->fixed_format != format->wFormatTag) continue; if (rdpsnd->fixed_channel > 0 && rdpsnd->fixed_channel != format->nChannels) continue; if (rdpsnd->fixed_rate > 0 && rdpsnd->fixed_rate != format->nSamplesPerSec) continue; if (rdpsnd->device && rdpsnd->device->FormatSupported(rdpsnd->device, format)) { DEBUG_SVC("format supported."); stream_check_size(data_out, 18 + format->cbSize); stream_write(data_out, format_mark, 18 + format->cbSize); if (format->cbSize > 0) { format->data = xmalloc(format->cbSize); memcpy(format->data, data_mark, format->cbSize); } n_out_formats++; } } rdpsnd->n_supported_formats = n_out_formats; if (n_out_formats > 0) { rdpsnd->supported_formats = out_formats; } else { xfree(out_formats); DEBUG_WARN("no formats supported"); } pos = stream_get_pos(data_out); stream_set_pos(data_out, 2); stream_write_uint16(data_out, pos - 4); stream_set_pos(data_out, 18); stream_write_uint16(data_out, n_out_formats); stream_set_pos(data_out, pos); svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); if (wVersion >= 6) { data_out = stream_new(8); stream_write_uint8(data_out, SNDC_QUALITYMODE); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_write_uint16(data_out, 4); /* BodySize */ stream_write_uint16(data_out, HIGH_QUALITY); /* wQualityMode */ stream_write_uint16(data_out, 0); /* Reserved */ svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); } }
int drdynvc_write_data(drdynvcPlugin* drdynvc, uint32 ChannelId, char* data, uint32 data_size) { STREAM* data_out; uint32 pos = 0; uint32 cbChId; uint32 cbLen; uint32 chunk_len; int error; DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size); data_out = stream_new(CHANNEL_CHUNK_LENGTH); stream_set_pos(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); if (data_size <= CHANNEL_CHUNK_LENGTH - pos) { pos = stream_get_pos(data_out); stream_set_pos(data_out, 0); stream_write_uint8(data_out, 0x30 | cbChId); stream_set_pos(data_out, pos); stream_write(data_out, data, data_size); error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } else { /* Fragment the data */ cbLen = drdynvc_write_variable_uint(data_out, data_size); pos = stream_get_pos(data_out); stream_set_pos(data_out, 0); stream_write_uint8(data_out, 0x20 | cbChId | (cbLen << 2)); stream_set_pos(data_out, pos); chunk_len = CHANNEL_CHUNK_LENGTH - pos; stream_write(data_out, data, chunk_len); data += chunk_len; data_size -= chunk_len; error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); while (error == CHANNEL_RC_OK && data_size > 0) { data_out = stream_new(CHANNEL_CHUNK_LENGTH); stream_set_pos(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); pos = stream_get_pos(data_out); stream_set_pos(data_out, 0); stream_write_uint8(data_out, 0x30 | cbChId); stream_set_pos(data_out, pos); chunk_len = data_size; if (chunk_len > CHANNEL_CHUNK_LENGTH - pos) chunk_len = CHANNEL_CHUNK_LENGTH - pos; stream_write(data_out, data, chunk_len); data += chunk_len; data_size -= chunk_len; error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } } if (error != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } return 0; }
static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; UINT32* quants; BYTE quant; int pos; stream_read_UINT16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { DEBUG_WARN("invalid subtype, expected CBT_TILESET."); return; } stream_seek_UINT16(s); /* idx (2 bytes), must be set to 0x0000 */ stream_seek_UINT16(s); /* properties (2 bytes) */ stream_read_BYTE(s, context->num_quants); /* numQuant (1 byte) */ stream_seek_BYTE(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->num_quants < 1) { DEBUG_WARN("no quantization value."); return; } stream_read_UINT16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { DEBUG_WARN("no tiles."); return; } stream_read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) context->quants = (UINT32*) realloc((void*) context->quants, context->num_quants * 10 * sizeof(UINT32)); else context->quants = (UINT32*) malloc(context->num_quants * 10 * sizeof(UINT32)); quants = context->quants; /* quantVals */ for (i = 0; i < context->num_quants; i++) { /* RFX_CODEC_QUANT */ stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); DEBUG_RFX("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]); } message->tiles = rfx_pool_get_tiles(context->priv->pool, message->num_tiles); /* tiles */ for (i = 0; i < message->num_tiles; i++) { /* RFX_TILE */ stream_read_UINT16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ stream_read_UINT32(s, blockLen); /* blockLen (4 bytes) */ pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } rfx_process_message_tile(context, message->tiles[i], s); stream_set_pos(s, pos); } }
static uint32 handle_ListReaders(IRP* irp, tbool wide) { uint32 len, rv; SCARDCONTEXT hContext; DWORD dwReaders; char *readerList = NULL, *walker; int elemLength, dataLength; int pos, poslen1, poslen2; stream_seek(irp->input, 8); stream_read_uint32(irp->input, len); stream_seek(irp->input, 0x1c); stream_read_uint32(irp->input, len); if (len != 4) return SCARD_F_INTERNAL_ERROR; stream_read_uint32(irp->input, hContext); /* ignore rest of [MS-RDPESC] 2.2.2.4 ListReaders_Call */ rv = SCARD_S_SUCCESS; #ifdef SCARD_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; rv = SCardListReaders(hContext, NULL, (LPSTR) &readerList, &dwReaders); #else rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); readerList = xmalloc(dwReaders); rv = SCardListReaders(hContext, NULL, readerList, &dwReaders); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return rv; } /* DEBUG_SCARD("Success 0x%08x %d %d", (unsigned) hContext, (unsigned) cchReaders, (int) strlen(readerList));*/ poslen1 = stream_get_pos(irp->output); stream_seek_uint32(irp->output); stream_write_uint32(irp->output, 0x01760650); poslen2 = stream_get_pos(irp->output); stream_seek_uint32(irp->output); walker = readerList; dataLength = 0; while (1) { elemLength = strlen(walker); if (elemLength == 0) break; dataLength += sc_output_string(irp, walker, wide); walker += elemLength + 1; elemLength = strlen(walker); } dataLength += sc_output_string(irp, "\0", wide); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, poslen1); stream_write_uint32(irp->output, dataLength); stream_set_pos(irp->output, poslen2); stream_write_uint32(irp->output, dataLength); stream_set_pos(irp->output, pos); sc_output_repos(irp, dataLength); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE SCardFreeMemory(hContext, readerList); #else xfree(readerList); #endif return rv; }
int transport_check_fds(rdpTransport* transport) { int pos; int status; uint16 length; STREAM* received; wait_obj_clear(transport->recv_event); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { stream_set_pos(transport->recv_buffer, 0); if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = tpkt_read_header(transport->recv_buffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = fastpath_read_header(NULL, transport->recv_buffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); freerdp_hexdump(stream_get_head(transport->recv_buffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); if (transport->recv_callback(transport, received, transport->recv_extra) == False) status = -1; stream_free(received); if (status < 0) return status; } return 0; }
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, uint8* data, uint32 length) { int pos; STREAM* s; uint32 blockLen; uint32 blockType; RFX_MESSAGE* message; s = stream_new(0); message = xnew(RFX_MESSAGE); stream_attach(s, data, length); while (stream_get_left(s) > 6) { /* RFX_BLOCKT */ stream_read_uint16(s, blockType); /* blockType (2 bytes) */ stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen); if (blockLen == 0) { DEBUG_WARN("zero blockLen"); break; } pos = stream_get_pos(s) - 6 + blockLen; if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ /* codecId (1 byte) must be set to 0x01 */ /* channelId (1 byte) must be set to 0x00 */ stream_seek(s, 2); } switch (blockType) { case WBT_SYNC: rfx_process_message_sync(context, s); break; case WBT_CODEC_VERSIONS: rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: rfx_process_message_channels(context, s); break; case WBT_CONTEXT: rfx_process_message_context(context, s); break; case WBT_FRAME_BEGIN: rfx_process_message_frame_begin(context, message, s); break; case WBT_FRAME_END: rfx_process_message_frame_end(context, message, s); break; case WBT_REGION: rfx_process_message_region(context, message, s); break; case WBT_EXTENSION: rfx_process_message_tileset(context, message, s); break; default: DEBUG_WARN("unknown blockType 0x%X", blockType); break; } stream_set_pos(s, pos); } stream_detach(s); stream_free(s); return message; }
static void rfx_cvt_rdvh_opt_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i,j; RFX_CONTEXT_CVT_PRIV* priv; uint16 destLeft, destTop; uint16 subtype; uint32 blockLen; uint32 blockType; uint32 tilesDataSize; uint32* quants; uint8 quant; int pos; int YQidx,UQidx,VQidx; decode_st dec_st; rect_st *p_rects; uint32 *p_size; int io_err; uint16 x,y; uint32 num_tile_rects; uint32 num_tile_rects_save; uint32 num_match; uint32 num_copy_rects; rfx_cvt_rect *p_rects_dst; rfx_cvt_rect *p_rects_ext; rfx_cvt_rect *p1,*p2; int match; uint8 disp_idx; uint8 idx; RFX_RECT *p_tile_rects; uint32 num_rects_max; destLeft = message->dst_rect.left; destTop = message->dst_rect.top; priv = (RFX_CONTEXT_CVT_PRIV*) context->priv; stream_read_uint16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { DEBUG_WARN("invalid subtype, expected CBT_TILESET."); return; } stream_seek_uint16(s); /* idx (2 bytes), must be set to 0x0000 */ stream_seek_uint16(s); /* properties (2 bytes) */ stream_read_uint8(s, context->num_quants); /* numQuant (1 byte) */ stream_seek_uint8(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->num_quants < 1) { DEBUG_WARN("no quantization value."); return; } stream_read_uint16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { DEBUG_WARN("no tiles."); return; } stream_read_uint32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) context->quants = (uint32*) xrealloc((void*) context->quants, context->num_quants * 5 * sizeof(uint32)); else context->quants = (uint32*) xmalloc(context->num_quants * 5 * sizeof(uint32)); quants = context->quants; /* quantVals */ for (i = 0; i < context->num_quants; i++) { /* RFX_CODEC_QUANT */ /* Hardware takes packed Q values. */ stream_read_uint8(s, *quants++); stream_read_uint8(s, *quants++); stream_read_uint8(s, *quants++); stream_read_uint8(s, *quants++); stream_read_uint8(s, *quants++); } memset(&dec_st,0,sizeof(dec_st)); rfx_cvt_setup_decode_st(&dec_st, destLeft, destTop, context, priv->rfx_mon_layout); dec_st.dest_off_x = destLeft; dec_st.dest_off_y = destTop; disp_idx = dec_st.display_num; idx = g_idx[disp_idx]; dec_st.p_frame_data = stream_get_tail(s); dec_st.num_tiles = message->num_tiles; dec_st.p_size = (uint32*) xmalloc(dec_st.num_tiles * sizeof(uint32)); p_size = dec_st.p_size; dec_st.data_size = 0; num_tile_rects_save = 0; num_tile_rects = 0; p_rects_dst = &g_rects_tile[disp_idx][idx][0]; p_rects_ext = p_rects_dst + dec_st.num_tiles; // for extra rects when 1 tile belongs to more than 1 rects. p_tile_rects = (RFX_RECT*) xmalloc(dec_st.num_tiles * sizeof(RFX_RECT)); /* tiles */ for (i = 0; i < dec_st.num_tiles; i++) { /* RFX_TILE */ stream_read_uint16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { printf("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } /* hardware only takes 1 set of Qvalues per frame, check the first tile */ stream_read_uint8(s, YQidx); stream_read_uint8(s, UQidx); stream_read_uint8(s, VQidx); if (i == 0) { if ((YQidx > context->num_quants) || (UQidx > context->num_quants) || (VQidx > context->num_quants)) { printf("invalid Qval index.\n"); printf("YQidx=%d;UQidx=%d;VQidx=%d\n",YQidx,UQidx,VQidx); return; } for(j=0;j<5;j++) { quant = *(uint8*) (context->quants + 5 * YQidx + j); dec_st.quants[4-j] = (quant >> 4) | (quant << 4); quant = *(uint8*) (context->quants + 5 * UQidx + j); dec_st.quants[9-j] = (quant >> 4) | (quant << 4); quant = *(uint8*) (context->quants + 5 * VQidx + j); dec_st.quants[14-j] = (quant >> 4) | (quant << 4); } } stream_read_uint16(s, x); stream_read_uint16(s, y); /* save tile rectangles for comparison */ p_rects = &(g_rects_tile[disp_idx][idx][i].rect) ; p_rects->x = x*64; p_rects->y = y*64; p_rects->width = 64; p_rects->height = 64; /* get clip window ( get clips tile by tile ) */ num_match = rfx_cvt_get_clip(message, (RFX_RECT*)p_rects, p_rects_dst, p_rects_ext); if (!num_match) { printf("interesting ???\n"); p_rects_dst->clip.x = p_rects->x ; p_rects_dst->clip.y = p_rects->y ; p_rects_dst->clip.width = p_rects->width ; p_rects_dst->clip.height = p_rects->height ; p_rects_dst++; num_tile_rects_save++; } else { p_rects_dst++; p_rects_ext+=(num_match-1); } num_tile_rects_save += num_match; /* tile_rects for blit */ p_tile_rects->x = x*64; p_tile_rects->y = y*64; p_tile_rects->width = 64; p_tile_rects->height = 64; //horizontal merge tiles if (i) { if ( (p_tile_rects->y == (p_tile_rects-1)->y) && (p_tile_rects->x == (p_tile_rects-1)->x + (p_tile_rects-1)->width) ) { p_tile_rects--; p_tile_rects->width += 64; num_tile_rects--; } } p_tile_rects++; num_tile_rects++; dec_st.data_size+=blockLen; *(p_size++)=blockLen; stream_set_pos(s, pos); } dec_st.num_tile_rects = num_tile_rects; p_tile_rects -= num_tile_rects; /* check tiles need to be copied from previous frame */ num_copy_rects = 0; for(i=0;i<g_num_rects_tile[disp_idx];i++) { match = 0; for(j=0;j<num_tile_rects_save;j++) { if (rfx_cvt_rects_compare(&(g_rects_tile[disp_idx][1-idx][i]),&(g_rects_tile[disp_idx][idx][j]))) { match = 1; break; } } if (!match) { memcpy((uint8*)&(g_rects_copy[disp_idx][num_copy_rects]),(uint8*)&(g_rects_tile[disp_idx][1-idx][i]),sizeof(rfx_cvt_rect)); num_copy_rects++; } } /* update tile rects number (for next frame) */ g_num_rects_tile[disp_idx] = num_tile_rects_save; /* horizontal merge copy rects */ p1 = (rfx_cvt_rect*)&g_rects_copy[disp_idx][0]; p2 = (rfx_cvt_rect*)&g_rects_copy[disp_idx][0]; if (num_copy_rects) { dec_st.num_copy_rects = rfx_cvt_rdvh_opt_tile_merge(p1,p2,num_copy_rects); dec_st.num_copy_rects = rfx_cvt_rdvh_opt_copy_rects_optimize(p1,dec_st.num_copy_rects); } else { dec_st.num_copy_rects = 0; } dec_st.p_copy_rects = &(g_rects_copy[disp_idx][0]); /* exceed 2D command fifo depth limitation */ if (dec_st.num_copy_rects > 160) { dec_st.num_copy_rects = 1; dec_st.p_copy_rects->rect.x = 0; dec_st.p_copy_rects->rect.y = 0; dec_st.p_copy_rects->rect.width = context->width; dec_st.p_copy_rects->rect.height = context->height; dec_st.p_copy_rects->clip.x = 0; dec_st.p_copy_rects->clip.y = 0; dec_st.p_copy_rects->clip.width = context->width; dec_st.p_copy_rects->clip.height = context->height; } /* verical merge tile rects */ for(j=0;j<dec_st.num_tile_rects;j++) { for(i=j+1;i<dec_st.num_tile_rects;i++) { if ( (p_tile_rects[j].x == p_tile_rects[i].x) && ((p_tile_rects[j].y+p_tile_rects[j].height) == p_tile_rects[i].y) && (p_tile_rects[j].width == p_tile_rects[i].width) && (p_tile_rects[i].width!=0) ) { p_tile_rects[j].height +=64; p_tile_rects[i].width = 0; } } } num_tile_rects=0; for(i=0;i<dec_st.num_tile_rects;i++) { if (p_tile_rects[i].width) { if (i!=num_tile_rects) memcpy((uint8*)(p_tile_rects+num_tile_rects),(uint8*)(p_tile_rects+i),sizeof(rect_st)); num_tile_rects++; } } dec_st.num_tile_rects = num_tile_rects; /* create clip window list for tile rects */ num_rects_max = message->num_rects*dec_st.num_tile_rects; dec_st.p_tile_rects = (rfx_cvt_rect*) xmalloc(num_rects_max * sizeof(rfx_cvt_rect)); p_rects_dst = dec_st.p_tile_rects; p_rects_ext = dec_st.p_tile_rects + dec_st.num_tile_rects; /* for extra rects when 1 tile belongs to more than 1 rects. */ num_tile_rects = 0; for (i = 0; i < dec_st.num_tile_rects; i++) { num_match = rfx_cvt_get_clip(message, p_tile_rects, p_rects_dst, p_rects_ext); if (!num_match) { printf("interesting ???\n"); p_rects_dst->clip.x = p_tile_rects->x ; p_rects_dst->clip.y = p_tile_rects->y ; p_rects_dst->clip.width = p_tile_rects->width ; p_rects_dst->clip.height = p_tile_rects->height ; p_rects_dst++; num_tile_rects++; } else { p_rects_dst++; p_rects_ext+=(num_match-1); } p_tile_rects++; num_tile_rects += num_match; } p_tile_rects-=dec_st.num_tile_rects; xfree(p_tile_rects); dec_st.num_tile_rects = num_tile_rects; if (dec_st.num_tile_rects > 160) printf("******Error : too many rectangles ( %d )******\n",dec_st.num_tile_rects); g_idx[disp_idx] = 1 - idx; //Call driver io_err = ioctl(priv->fd, DEV_IOCTL_DECODING, &dec_st); if (io_err) printf("Hardware decoding failed.\n"); xfree(dec_st.p_size); xfree(dec_st.p_tile_rects); }
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, uint8* data, uint32 length, RECTANGLE_16* dst_rect) { int pos; STREAM* s; uint32 blockLen; uint32 blockType; RFX_CONTEXT_CVT_PRIV* priv; RFX_MESSAGE* message; s = stream_new(0); message = rfx_message_new(); if (dst_rect) memcpy(&message->dst_rect, dst_rect, sizeof(RECTANGLE_16)); stream_attach(s, data, length); while (stream_get_left(s) > 6) { /* RFX_BLOCKT */ stream_read_uint16(s, blockType); /* blockType (2 bytes) */ stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen); if (blockLen == 0) { DEBUG_WARN("zero blockLen"); break; } pos = stream_get_pos(s) - 6 + blockLen; if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ /* codecId (1 byte) must be set to 0x01 */ /* channelId (1 byte) must be set to 0x00 */ stream_seek(s, 2); } switch (blockType) { case WBT_SYNC: rfx_process_message_sync(context, s); break; case WBT_CODEC_VERSIONS: rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: rfx_process_message_channels(context, s); break; case WBT_CONTEXT: rfx_process_message_context(context, s); break; case WBT_FRAME_BEGIN: rfx_process_message_frame_begin(context, message, s); break; case WBT_FRAME_END: rfx_process_message_frame_end(context, message, s); break; case WBT_REGION: rfx_process_message_region(context, message, s); break; case WBT_EXTENSION: priv = (RFX_CONTEXT_CVT_PRIV*) context->priv; if (priv->rfx_op_mode == RDVH_OPT) rfx_cvt_rdvh_opt_process_message_tileset(context, message, s); else rfx_cvt_process_message_tileset(context, message, s); break; default: DEBUG_WARN("unknown blockType 0x%X", blockType); break; } stream_set_pos(s, pos); } stream_detach(s); stream_free(s); return message; }
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL user_loggedon) { int i; int pos; BYTE c; UINT32 count; int data_len; int count_pos; STREAM* data_out; DEVICE* device; LIST_ITEM* item; data_out = stream_new(256); stream_write_UINT16(data_out, RDPDR_CTYP_CORE); stream_write_UINT16(data_out, PAKID_CORE_DEVICELIST_ANNOUNCE); count_pos = stream_get_pos(data_out); count = 0; stream_seek_UINT32(data_out); /* deviceCount */ for (item = rdpdr->devman->devices->head; item; item = item->next) { device = (DEVICE*) item->data; /** * 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON * so all devices should be sent regardless of user_loggedon * 2. smartcard devices should be always sent * 3. other devices are sent only after user_loggedon */ if ((rdpdr->versionMinor == 0x0005) || (device->type == RDPDR_DTYP_SMARTCARD) || user_loggedon) { data_len = (device->data == NULL ? 0 : stream_get_length(device->data)); stream_check_size(data_out, 20 + data_len); stream_write_UINT32(data_out, device->type); /* deviceType */ stream_write_UINT32(data_out, device->id); /* deviceID */ strncpy((char*) stream_get_tail(data_out), device->name, 8); for (i = 0; i < 8; i++) { stream_peek_BYTE(data_out, c); if (c > 0x7F) stream_write_BYTE(data_out, '_'); else stream_seek_BYTE(data_out); } stream_write_UINT32(data_out, data_len); if (data_len > 0) stream_write(data_out, stream_get_data(device->data), data_len); count++; printf("registered device #%d: %s (type=%d id=%d)\n", count, device->name, device->type, device->id); } } pos = stream_get_pos(data_out); stream_set_pos(data_out, count_pos); stream_write_UINT32(data_out, count); stream_set_pos(data_out, pos); stream_seal(data_out); svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out); }
int transport_check_fds(rdpTransport** ptransport) { int pos; int status; uint16 length; STREAM* received; rdpTransport* transport = *ptransport; wait_obj_clear(transport->recv_event); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { stream_set_pos(transport->recv_buffer, 0); if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = tpkt_read_header(transport->recv_buffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->recv_buffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->recv_buffer); if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = fastpath_read_header(NULL, transport->recv_buffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); freerdp_hexdump(stream_get_head(transport->recv_buffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); if (transport->recv_callback(transport, received, transport->recv_extra) == false) status = -1; stream_free(received); if (status < 0) return status; /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ transport = *ptransport; if (transport->process_single_pdu) { /* one at a time but set event if data buffered * so the main loop will call freerdp_check_fds asap */ if (stream_get_pos(transport->recv_buffer) > 0) wait_obj_set(transport->recv_event); break; } } return 0; }
uint32 serial_tty_control(SERIAL_TTY* tty, uint32 IoControlCode, STREAM* input, STREAM* output, uint32* abort_io) { int purge_mask; uint32 result; uint32 modemstate; uint8 immediate; uint32 ret = STATUS_SUCCESS; uint32 length = 0; uint32 pos; DEBUG_SVC("in"); stream_seek(output, sizeof(uint32)); switch (IoControlCode) { case IOCTL_SERIAL_SET_BAUD_RATE: stream_read_uint32(input, tty->baud_rate); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_GET_BAUD_RATE: length = 4; stream_write_uint32(output, tty->baud_rate); DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: stream_read_uint32(input, tty->queue_in_size); stream_read_uint32(input, tty->queue_out_size); DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size); break; case IOCTL_SERIAL_SET_LINE_CONTROL: stream_read_uint8(input, tty->stop_bits); stream_read_uint8(input, tty->parity); stream_read_uint8(input, tty->word_length); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", tty->stop_bits, tty->parity, tty->word_length); break; case IOCTL_SERIAL_GET_LINE_CONTROL: DEBUG_SVC("SERIAL_GET_LINE_CONTROL"); length = 3; stream_write_uint8(output, tty->stop_bits); stream_write_uint8(output, tty->parity); stream_write_uint8(output, tty->word_length); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: DEBUG_SVC("SERIAL_IMMEDIATE_CHAR"); stream_read_uint8(input, immediate); tty_write_data(tty, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: DEBUG_SVC("SERIAL_CONFIG_SIZE"); length = 4; stream_write_uint32(output, 0); break; case IOCTL_SERIAL_GET_CHARS: DEBUG_SVC("SERIAL_GET_CHARS"); length = 6; stream_write(output, tty->chars, 6); break; case IOCTL_SERIAL_SET_CHARS: DEBUG_SVC("SERIAL_SET_CHARS"); stream_read(input, tty->chars, 6); tty_set_termios(tty); break; case IOCTL_SERIAL_GET_HANDFLOW: length = 16; tty_get_termios(tty); stream_write_uint32(output, tty->control); stream_write_uint32(output, tty->xonoff); stream_write_uint32(output, tty->onlimit); stream_write_uint32(output, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: stream_read_uint32(input, tty->control); stream_read_uint32(input, tty->xonoff); stream_read_uint32(input, tty->onlimit); stream_read_uint32(input, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); tty_set_termios(tty); break; case IOCTL_SERIAL_SET_TIMEOUTS: stream_read_uint32(input, tty->read_interval_timeout); stream_read_uint32(input, tty->read_total_timeout_multiplier); stream_read_uint32(input, tty->read_total_timeout_constant); stream_read_uint32(input, tty->write_total_timeout_multiplier); stream_read_uint32(input, tty->write_total_timeout_constant); /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section http://msdn.microsoft.com/en-us/library/ms885171.aspx */ if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX) { tty->read_interval_timeout = 0; tty->read_total_timeout_multiplier = 0; } DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); break; case IOCTL_SERIAL_GET_TIMEOUTS: DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); length = 20; stream_write_uint32(output, tty->read_interval_timeout); stream_write_uint32(output, tty->read_total_timeout_multiplier); stream_write_uint32(output, tty->read_total_timeout_constant); stream_write_uint32(output, tty->write_total_timeout_multiplier); stream_write_uint32(output, tty->write_total_timeout_constant); break; case IOCTL_SERIAL_GET_WAIT_MASK: DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask); length = 4; stream_write_uint32(output, tty->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: stream_read_uint32(input, tty->wait_mask); DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask); break; case IOCTL_SERIAL_SET_DTR: DEBUG_SVC("SERIAL_SET_DTR"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 1; break; case IOCTL_SERIAL_CLR_DTR: DEBUG_SVC("SERIAL_CLR_DTR"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 0; break; case IOCTL_SERIAL_SET_RTS: DEBUG_SVC("SERIAL_SET_RTS"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 1; break; case IOCTL_SERIAL_CLR_RTS: DEBUG_SVC("SERIAL_CLR_RTS"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 0; break; case IOCTL_SERIAL_GET_MODEMSTATUS: modemstate = 0; #ifdef TIOCMGET ioctl(tty->fd, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate); length = 4; stream_write_uint32(output, modemstate); break; case IOCTL_SERIAL_GET_COMMSTATUS: length = 18; stream_write_uint32(output, 0); /* Errors */ stream_write_uint32(output, 0); /* Hold reasons */ result = 0; #ifdef TIOCINQ ioctl(tty->fd, TIOCINQ, &result); #endif stream_write_uint32(output, result); /* Amount in in queue */ if (result) DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result); result = 0; #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &result); #endif stream_write_uint32(output, result); /* Amount in out queue */ DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result); stream_write_uint8(output, 0); /* EofReceived */ stream_write_uint8(output, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: stream_read_uint32(input, purge_mask); DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask); /* See http://msdn.microsoft.com/en-us/library/ms901431.aspx PURGE_TXCLEAR Clears the output buffer, if the driver has one. PURGE_RXCLEAR Clears the input buffer, if the driver has one. It clearly states to clear the *driver* buffer, not the port buffer */ #ifdef DEBUG_SVC if (purge_mask & SERIAL_PURGE_TXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR"); if (purge_mask & SERIAL_PURGE_RXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR"); #endif if (purge_mask & SERIAL_PURGE_TXABORT) *abort_io |= SERIAL_ABORT_IO_WRITE; if (purge_mask & SERIAL_PURGE_RXABORT) *abort_io |= SERIAL_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask); tty->event_pending = 1; length = 4; if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("WAIT end event = %X", result); stream_write_uint32(output, result); break; } ret = STATUS_PENDING; break; case IOCTL_SERIAL_SET_BREAK_ON: DEBUG_SVC("SERIAL_SET_BREAK_ON"); tcsendbreak(tty->fd, 0); break; case IOCTL_SERIAL_RESET_DEVICE: DEBUG_SVC("SERIAL_RESET_DEVICE"); break; case IOCTL_SERIAL_SET_BREAK_OFF: DEBUG_SVC("SERIAL_SET_BREAK_OFF"); break; case IOCTL_SERIAL_SET_XOFF: DEBUG_SVC("SERIAL_SET_XOFF"); break; case IOCTL_SERIAL_SET_XON: DEBUG_SVC("SERIAL_SET_XON"); tcflow(tty->fd, TCION); break; default: DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode); return STATUS_INVALID_PARAMETER; } /* Write OutputBufferLength */ pos = stream_get_pos(output); stream_set_pos(output, 16); stream_write_uint32(output, length); stream_set_pos(output, pos); return ret; }
void scard_device_control(SCARD_DEVICE* scard, IRP* irp) { uint32 output_len, input_len, ioctl_code; uint32 stream_len, result; uint32 pos, pad_len; uint32 irp_len; uint32 irp_result_pos, output_len_pos, result_pos; stream_read_uint32(irp->input, output_len); stream_read_uint32(irp->input, input_len); stream_read_uint32(irp->input, ioctl_code); stream_seek(irp->input, 20); /* padding */ // stream_seek(irp->input, 4); /* TODO: parse len, le, v1 */ // stream_seek(irp->input, 4); /* 0xcccccccc */ // stream_seek(irp->input, 4); /* rpce len */ /* [MS-RDPESC] 3.2.5.1 Sending Outgoing Messages */ stream_extend(irp->output, 2048); irp_result_pos = stream_get_pos(irp->output); stream_write_uint32(irp->output, 0x00081001); /* len 8, LE, v1 */ /* [MS-RPCE] 2.2.6.1 */ stream_write_uint32(irp->output, 0x00081001); /* len 8, LE, v1 */ stream_write_uint32(irp->output, 0xcccccccc); /* filler */ output_len_pos = stream_get_pos(irp->output); stream_seek(irp->output, 4); /* size */ stream_write_uint32(irp->output, 0x0); /* filler */ result_pos = stream_get_pos(irp->output); stream_seek(irp->output, 4); /* result */ /* body */ switch (ioctl_code) { case SCARD_IOCTL_ESTABLISH_CONTEXT: result = handle_EstablishContext(irp); break; case SCARD_IOCTL_IS_VALID_CONTEXT: result = handle_IsValidContext(irp); break; case SCARD_IOCTL_RELEASE_CONTEXT: result = handle_ReleaseContext(irp); break; case SCARD_IOCTL_LIST_READERS: result = handle_ListReaders(irp, 0); break; case SCARD_IOCTL_LIST_READERS + 4: result = handle_ListReaders(irp, 1); break; case SCARD_IOCTL_LIST_READER_GROUPS: case SCARD_IOCTL_LIST_READER_GROUPS + 4: /* typically not used unless list_readers fail */ result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_GET_STATUS_CHANGE: result = handle_GetStatusChange(irp, 0); break; case SCARD_IOCTL_GET_STATUS_CHANGE + 4: result = handle_GetStatusChange(irp, 1); break; case SCARD_IOCTL_CANCEL: result = handle_Cancel(irp); break; case SCARD_IOCTL_CONNECT: result = handle_Connect(irp, 0); break; case SCARD_IOCTL_CONNECT + 4: result = handle_Connect(irp, 1); break; case SCARD_IOCTL_RECONNECT: result = handle_Reconnect(irp); break; case SCARD_IOCTL_DISCONNECT: result = handle_Disconnect(irp); break; case SCARD_IOCTL_BEGIN_TRANSACTION: result = handle_BeginTransaction(irp); break; case SCARD_IOCTL_END_TRANSACTION: result = handle_EndTransaction(irp); break; case SCARD_IOCTL_STATE: result = handle_State(irp); break; case SCARD_IOCTL_STATUS: result = handle_Status(irp, 0); break; case SCARD_IOCTL_STATUS + 4: result = handle_Status(irp, 1); break; case SCARD_IOCTL_TRANSMIT: result = handle_Transmit(irp); break; case SCARD_IOCTL_CONTROL: result = handle_Control(irp); break; case SCARD_IOCTL_GETATTRIB: result = handle_GetAttrib(irp); break; case SCARD_IOCTL_ACCESS_STARTED_EVENT: result = handle_AccessStartedEvent(irp); break; case SCARD_IOCTL_LOCATE_CARDS_BY_ATR: result = handle_LocateCardsByATR(irp, 0); break; case SCARD_IOCTL_LOCATE_CARDS_BY_ATR + 4: result = handle_LocateCardsByATR(irp, 1); break; default: result = 0xc0000001; printf("scard unknown ioctl 0x%x\n", ioctl_code); break; } /* look for NTSTATUS errors */ if ((result & 0xc0000000) == 0xc0000000) return scard_error(scard, irp, result); /* per Ludovic Rousseau, map different usage of this particular * error code between pcsc-lite & windows */ if (result == 0x8010001F) result = 0x80100022; /* handle response packet */ pos = stream_get_pos(irp->output); stream_len = pos - irp_result_pos - 4; stream_set_pos(irp->output, output_len_pos); stream_write_uint32(irp->output, stream_len - 24); stream_set_pos(irp->output, result_pos); stream_write_uint32(irp->output, result); stream_set_pos(irp->output, pos); /* pad stream to 16 byte align */ pad_len = stream_len % 16; stream_write_zero(irp->output, pad_len); pos = stream_get_pos(irp->output); irp_len = stream_len + pad_len; stream_set_pos(irp->output, irp_result_pos); stream_write_uint32(irp->output, irp_len); stream_set_pos(irp->output, pos); #ifdef WITH_DEBUG_SCARD freerdp_hexdump(stream_get_data(irp->output), stream_get_length(irp->output)); #endif irp->IoStatus = 0; irp->Complete(irp); }
static void wts_read_drdynvc_pdu(rdpPeerChannel* channel) { UINT32 length; int value; int Cmd; int Sp; int cbChId; UINT32 ChannelId; rdpPeerChannel* dvc; length = stream_get_pos(channel->receive_data); if (length < 1) return; stream_set_pos(channel->receive_data, 0); stream_read_BYTE(channel->receive_data, value); length--; Cmd = (value & 0xf0) >> 4; Sp = (value & 0x0c) >> 2; cbChId = (value & 0x03) >> 0; if (Cmd == CAPABILITY_REQUEST_PDU) { wts_read_drdynvc_capabilities_response(channel, length); } else if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY) { value = wts_read_variable_uint(channel->receive_data, cbChId, &ChannelId); if (value == 0) return; length -= value; DEBUG_DVC("Cmd %d ChannelId %d length %d", Cmd, ChannelId, length); dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId); if (dvc) { switch (Cmd) { case CREATE_REQUEST_PDU: wts_read_drdynvc_create_response(dvc, channel->receive_data, length); break; case DATA_FIRST_PDU: wts_read_drdynvc_data_first(dvc, channel->receive_data, Sp, length); break; case DATA_PDU: wts_read_drdynvc_data(dvc, channel->receive_data, length); break; case CLOSE_REQUEST_PDU: wts_read_drdynvc_close_response(dvc); break; default: fprintf(stderr, "wts_read_drdynvc_pdu: Cmd %d not recognized.\n", Cmd); break; } } else { DEBUG_DVC("ChannelId %d not exists.", ChannelId); } } else { fprintf(stderr, "wts_read_drdynvc_pdu: received Cmd %d but channel is not ready.\n", Cmd); } }
static DWORD handle_Status(IRP *irp, tbool wide) { LONG rv; SCARDHANDLE hCard; DWORD state, protocol; DWORD readerLen = 0; DWORD atrLen = 0; char * readerName; BYTE pbAtr[MAX_ATR_SIZE]; uint32 dataLength; int pos, poslen1, poslen2; #ifdef WITH_DEBUG_SCARD int i; #endif stream_seek(irp->input, 0x24); stream_read_uint32(irp->input, readerLen); stream_read_uint32(irp->input, atrLen); stream_seek(irp->input, 0x0c); stream_read_uint32(irp->input, hCard); stream_seek(irp->input, 0x4); atrLen = MAX_ATR_SIZE; #ifdef SCARD_AUTOALLOCATE readerLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #else readerLen = 256; readerName = xmalloc(readerLen); rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success (state: 0x%08x, proto: 0x%08x)", (unsigned) state, (unsigned) protocol); DEBUG_SCARD(" Reader: \"%s\"", readerName ? readerName : "NULL"); #ifdef WITH_DEBUG_SCARD printf(" ATR: "); for (i = 0; i < atrLen; i++) printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':'); printf("\n"); #endif state = sc_map_state(state); poslen1 = stream_get_pos(irp->output); stream_write_uint32(irp->output, readerLen); stream_write_uint32(irp->output, 0x00020000); stream_write_uint32(irp->output, state); stream_write_uint32(irp->output, protocol); stream_write(irp->output, pbAtr, atrLen); if (atrLen < 32) stream_write_zero(irp->output, 32 - atrLen); stream_write_uint32(irp->output, atrLen); poslen2 = stream_get_pos(irp->output); stream_write_uint32(irp->output, readerLen); dataLength = sc_output_string(irp, readerName, wide); dataLength += sc_output_string(irp, "\0", wide); sc_output_repos(irp, dataLength); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, poslen1); stream_write_uint32(irp->output,dataLength); stream_set_pos(irp->output, poslen2); stream_write_uint32(irp->output,dataLength); stream_set_pos(irp->output, pos); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE /* SCardFreeMemory(NULL, readerName); */ free(readerName); #else xfree(readerName); #endif return rv; }
int transport_check_fds(rdpTransport** ptransport) { int pos; int status; UINT16 length; int recv_status; STREAM* received; rdpTransport* transport = *ptransport; #ifdef _WIN32 WSAResetEvent(transport->TcpIn->wsa_event); #endif ResetEvent(transport->ReceiveEvent); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->ReceiveBuffer)) > 0) { stream_set_pos(transport->ReceiveBuffer, 0); if (tpkt_verify_header(transport->ReceiveBuffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } length = tpkt_read_header(transport->ReceiveBuffer); } else if (nla_verify_header(transport->ReceiveBuffer)) { /* TSRequest */ /* Ensure the TSRequest header is available. */ if (pos <= 4) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } /* TSRequest header can be 2, 3 or 4 bytes long */ length = nla_header_length(transport->ReceiveBuffer); if (pos < length) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } length = nla_read_header(transport->ReceiveBuffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->ReceiveBuffer); if (pos < length) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } length = fastpath_read_header(NULL, transport->ReceiveBuffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); winpr_HexDump(stream_get_head(transport->ReceiveBuffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; /* Packet is not yet completely received. */ } received = transport->ReceiveBuffer; transport->ReceiveBuffer = transport_receive_pool_take(transport); stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); /** * ReceiveCallback return values: * * -1: synchronous failure * 0: synchronous success * 1: asynchronous return */ recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); transport_receive_pool_return(transport, received); if (recv_status < 0) status = -1; if (status < 0) return status; /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ transport = *ptransport; } return 0; }