boolean rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id, uint8 *compressed_type, uint16 *compressed_len) { if (stream_get_left(s) < 12) return false; /* Share Data Header */ stream_read_uint32(s, *share_id); /* shareId (4 bytes) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint8(s); /* streamId (1 byte) */ stream_read_uint16(s, *length); /* uncompressedLength (2 bytes) */ stream_read_uint8(s, *type); /* pduType2, Data PDU Type (1 byte) */ if (*type & 0x80) { stream_read_uint8(s, *compressed_type); /* compressedType (1 byte) */ stream_read_uint16(s, *compressed_len); /* compressedLength (2 bytes) */ } else { stream_seek(s, 3); *compressed_type = 0; *compressed_len = 0; } return true; }
void rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id) { /* Share Data Header */ stream_read_uint32(s, *share_id); /* shareId (4 bytes) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint8(s); /* streamId (1 byte) */ stream_read_uint16(s, *length); /* uncompressedLength (2 bytes) */ stream_read_uint8(s, *type); /* pduType2, Data PDU Type (1 byte) */ stream_seek_uint8(s); /* compressedType (1 byte) */ stream_seek_uint16(s); /* compressedLength (2 bytes) */ }
void rdp_read_bitmap_cache_v2_capability_set(STREAM* s, rdpSettings* settings) { stream_seek_uint16(s); /* cacheFlags (2 bytes) */ stream_seek_uint8(s); /* pad2 (1 byte) */ stream_seek_uint8(s); /* numCellCaches (1 byte) */ stream_seek(s, 4); /* bitmapCache0CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache1CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache2CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache3CellInfo (4 bytes) */ stream_seek(s, 4); /* bitmapCache4CellInfo (4 bytes) */ stream_seek(s, 12); /* pad3 (12 bytes) */ }
boolean rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s) { stream_seek_uint16(s); /* pad2Octets (2 bytes) */ rdp_recv_server_redirection_pdu(rdp, s); stream_seek_uint8(s); /* pad2Octets (1 byte) */ return true; }
void rdp_read_bitmap_capability_set(STREAM* s, rdpSettings* settings) { uint8 drawingFlags; uint16 desktopWidth; uint16 desktopHeight; uint16 desktopResizeFlag; uint16 preferredBitsPerPixel; stream_read_uint16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */ stream_seek_uint16(s); /* receive1BitPerPixel (2 bytes) */ stream_seek_uint16(s); /* receive4BitsPerPixel (2 bytes) */ stream_seek_uint16(s); /* receive8BitsPerPixel (2 bytes) */ stream_read_uint16(s, desktopWidth); /* desktopWidth (2 bytes) */ stream_read_uint16(s, desktopHeight); /* desktopHeight (2 bytes) */ stream_seek_uint16(s); /* pad2Octets (2 bytes) */ stream_read_uint16(s, desktopResizeFlag); /* desktopResizeFlag (2 bytes) */ stream_seek_uint16(s); /* bitmapCompressionFlag (2 bytes) */ stream_seek_uint8(s); /* highColorFlags (1 byte) */ stream_read_uint8(s, drawingFlags); /* drawingFlags (1 byte) */ stream_seek_uint16(s); /* multipleRectangleSupport (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsB (2 bytes) */ if (desktopResizeFlag == False) settings->desktop_resize = False; }
static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; stream_seek_uint8(s); /* regionFlags (1 byte) */ stream_read_uint16(s, message->num_rects); /* numRects (2 bytes) */ if (message->num_rects < 1) { DEBUG_WARN("no rects."); return; } if (message->rects != NULL) message->rects = (RFX_RECT*) xrealloc(message->rects, message->num_rects * sizeof(RFX_RECT)); else message->rects = (RFX_RECT*) xmalloc(message->num_rects * sizeof(RFX_RECT)); /* rects */ for (i = 0; i < message->num_rects; i++) { /* RFX_RECT */ stream_read_uint16(s, message->rects[i].x); /* x (2 bytes) */ stream_read_uint16(s, message->rects[i].y); /* y (2 bytes) */ stream_read_uint16(s, message->rects[i].width); /* width (2 bytes) */ stream_read_uint16(s, message->rects[i].height); /* height (2 bytes) */ DEBUG_RFX("rect %d (%d %d %d %d).", i, message->rects[i].x, message->rects[i].y, message->rects[i].width, message->rects[i].height); } }
static boolean rdpsnd_server_recv_formats(rdpsnd_server* rdpsnd, STREAM* s) { int i; if (stream_get_left(s) < 20) return false; stream_seek_uint32(s); /* dwFlags */ stream_seek_uint32(s); /* dwVolume */ stream_seek_uint32(s); /* dwPitch */ stream_seek_uint16(s); /* wDGramPort */ stream_read_uint16(s, rdpsnd->context.num_client_formats); /* wNumberOfFormats */ stream_seek_uint8(s); /* cLastBlockConfirmed */ stream_seek_uint16(s); /* wVersion */ stream_seek_uint8(s); /* bPad */ if (rdpsnd->context.num_client_formats > 0) { rdpsnd->context.client_formats = xzalloc(rdpsnd->context.num_client_formats * sizeof(rdpsndFormat)); for (i = 0; i < rdpsnd->context.num_client_formats; i++) { if (stream_get_left(s) < 18) { xfree(rdpsnd->context.client_formats); rdpsnd->context.client_formats = NULL; return false; } stream_read_uint16(s, rdpsnd->context.client_formats[i].wFormatTag); stream_read_uint16(s, rdpsnd->context.client_formats[i].nChannels); stream_read_uint32(s, rdpsnd->context.client_formats[i].nSamplesPerSec); stream_seek_uint32(s); /* nAvgBytesPerSec */ stream_read_uint16(s, rdpsnd->context.client_formats[i].nBlockAlign); stream_read_uint16(s, rdpsnd->context.client_formats[i].wBitsPerSample); stream_read_uint16(s, rdpsnd->context.client_formats[i].cbSize); if (rdpsnd->context.client_formats[i].cbSize > 0) { stream_seek(s, rdpsnd->context.client_formats[i].cbSize); } } } return true; }
/* * The fastpath header may be two or three bytes long. * This function assumes that at least two bytes are available in the stream * and doesn't touch third byte. */ uint16 fastpath_header_length(STREAM* s) { uint8 length1; stream_seek_uint8(s); stream_read_uint8(s, length1); stream_rewind(s, 2); return ((length1 & 0x80) != 0 ? 3 : 2); }
static void wts_write_drdynvc_header(STREAM *s, uint8 Cmd, uint32 ChannelId) { uint8* bm; int cbChId; stream_get_mark(s, bm); stream_seek_uint8(s); cbChId = wts_write_variable_uint(s, ChannelId); *bm = ((Cmd & 0x0F) << 4) | cbChId; }
void rdp_read_bitmap_cache_host_support_capability_set(STREAM* s, rdpSettings* settings) { uint8 cacheVersion; stream_read_uint8(s, cacheVersion); /* cacheVersion (1 byte) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint16(s); /* pad2 (2 bytes) */ if (cacheVersion & BITMAP_CACHE_V2) settings->persistent_bitmap_cache = True; }
boolean nego_read_request(rdpNego* nego, STREAM* s) { uint8 li; uint8 c; uint8 type; tpkt_read_header(s); li = tpdu_read_connection_request(s); if (li != stream_get_left(s) + 6) { printf("Incorrect TPDU length indicator.\n"); return false; } if (stream_get_left(s) > 8) { /* Optional routingToken or cookie, ending with CR+LF */ while (stream_get_left(s) > 0) { stream_read_uint8(s, c); if (c != '\x0D') continue; stream_peek_uint8(s, c); if (c != '\x0A') continue; stream_seek_uint8(s); break; } } if (stream_get_left(s) >= 8) { /* rdpNegData (optional) */ stream_read_uint8(s, type); /* Type */ if (type != TYPE_RDP_NEG_REQ) { printf("Incorrect negotiation request type %d\n", type); return false; } nego_process_negotiation_request(nego, s); } return true; }
static void wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, uint32 length) { uint16 Version; if (length < 3) return; stream_seek_uint8(channel->receive_data); /* Pad (1 byte) */ stream_read_uint16(channel->receive_data, Version); DEBUG_DVC("Version: %d", Version); channel->vcm->drdynvc_state = DRDYNVC_STATE_READY; }
void rdp_read_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings) { uint8 bitmapCodecCount; uint16 codecPropertiesLength; stream_read_uint8(s, bitmapCodecCount); /* bitmapCodecCount (1 byte) */ while (bitmapCodecCount > 0) { stream_seek(s, 16); /* codecGUID (16 bytes) */ stream_seek_uint8(s); /* codecID (1 byte) */ stream_read_uint16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */ stream_seek(s, codecPropertiesLength); /* codecProperties */ bitmapCodecCount--; } }
static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; uint8 msgType; uint16 BodySize; if (rdpsnd->expectingWave) { rdpsnd_process_message_wave(rdpsnd, data_in); stream_free(data_in); return; } stream_read_uint8(data_in, msgType); /* msgType */ stream_seek_uint8(data_in); /* bPad */ stream_read_uint16(data_in, BodySize); DEBUG_SVC("msgType %d BodySize %d", msgType, BodySize); switch (msgType) { case SNDC_FORMATS: rdpsnd_process_message_formats(rdpsnd, data_in); break; case SNDC_TRAINING: rdpsnd_process_message_training(rdpsnd, data_in); break; case SNDC_WAVE: rdpsnd_process_message_wave_info(rdpsnd, data_in, BodySize); break; case SNDC_CLOSE: rdpsnd_process_message_close(rdpsnd); break; case SNDC_SETVOLUME: rdpsnd_process_message_setvolume(rdpsnd, data_in); break; default: DEBUG_WARN("unknown msgType %d", msgType); break; } stream_free(data_in); }
void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { stream_read_uint16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_uint32(s, pointer_color->hotSpot); /* hotSpot (4 bytes) */ stream_read_uint16(s, pointer_color->width); /* width (2 bytes) */ stream_read_uint16(s, pointer_color->height); /* height (2 bytes) */ stream_read_uint16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */ stream_read_uint16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */ if (pointer_color->lengthXorMask > 0) { pointer_color->xorMaskData = (uint8*) xmalloc(pointer_color->lengthXorMask); stream_read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask); } if (pointer_color->lengthAndMask > 0) { pointer_color->andMaskData = (uint8*) xmalloc(pointer_color->lengthAndMask); stream_read(s, pointer_color->andMaskData, pointer_color->lengthAndMask); } stream_seek_uint8(s); /* pad (1 byte) */ }
static void* rdpsnd_server_thread_func(void* arg) { void* fd; STREAM* s; void* buffer; uint8 msgType; uint16 BodySize; uint32 bytes_returned = 0; rdpsnd_server* rdpsnd = (rdpsnd_server*) arg; freerdp_thread* thread = rdpsnd->rdpsnd_channel_thread; if (WTSVirtualChannelQuery(rdpsnd->rdpsnd_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == true) { fd = *((void**)buffer); WTSFreeMemory(buffer); thread->signals[thread->num_signals++] = wait_obj_new_with_fd(fd); } s = stream_new(4096); rdpsnd_server_send_formats(rdpsnd, s); while (1) { freerdp_thread_wait(thread); if (freerdp_thread_is_stopped(thread)) break; stream_set_pos(s, 0); if (WTSVirtualChannelRead(rdpsnd->rdpsnd_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == false) { if (bytes_returned == 0) break; stream_check_size(s, bytes_returned); if (WTSVirtualChannelRead(rdpsnd->rdpsnd_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == false) break; } stream_read_uint8(s, msgType); stream_seek_uint8(s); /* bPad */ stream_read_uint16(s, BodySize); if (BodySize + 4 > bytes_returned) continue; switch (msgType) { case SNDC_FORMATS: if (rdpsnd_server_recv_formats(rdpsnd, s)) { IFCALL(rdpsnd->context.Activated, &rdpsnd->context); } break; default: break; } } stream_free(s); freerdp_thread_quit(thread); return 0; }
/* 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); } }
boolean disk_file_set_information(DISK_FILE* file, uint32 FsInformationClass, uint32 Length, STREAM* input) { char* s; mode_t m; uint64 size; char* fullpath; struct stat st; UNICONV* uniconv; struct timeval tv[2]; uint64 LastWriteTime; uint32 FileAttributes; uint32 FileNameLength; switch (FsInformationClass) { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ stream_seek_uint64(input); /* CreationTime */ stream_seek_uint64(input); /* LastAccessTime */ stream_read_uint64(input, LastWriteTime); stream_seek_uint64(input); /* ChangeTime */ stream_read_uint32(input, FileAttributes); if (fstat(file->fd, &st) != 0) return false; tv[0].tv_sec = st.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); tv[1].tv_usec = 0; futimes(file->fd, tv); if (FileAttributes > 0) { m = st.st_mode; if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0) m |= S_IWUSR; else m &= ~S_IWUSR; if (m != st.st_mode) fchmod(file->fd, st.st_mode); } break; case FileEndOfFileInformation: /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ stream_read_uint64(input, size); if (ftruncate(file->fd, size) != 0) return false; break; case FileDispositionInformation: /* http://msdn.microsoft.com/en-us/library/cc232098.aspx */ stream_read_uint8(input, file->delete_pending); break; case FileRenameInformation: /* http://msdn.microsoft.com/en-us/library/cc232085.aspx */ stream_seek_uint8(input); /* ReplaceIfExists */ stream_seek_uint8(input); /* RootDirectory */ stream_read_uint32(input, FileNameLength); uniconv = freerdp_uniconv_new(); s = freerdp_uniconv_in(uniconv, stream_get_tail(input), FileNameLength); freerdp_uniconv_free(uniconv); fullpath = disk_file_combine_fullpath(file->basepath, s); xfree(s); if (rename(file->fullpath, fullpath) == 0) { DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath); disk_file_set_fullpath(file, fullpath); } else { DEBUG_WARN("rename %s to %s failed", file->fullpath, fullpath); free(fullpath); return false; } break; default: DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); return false; } return true; }
boolean WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ uint8* Buffer, /* __in */ uint32 Length, /* __out */ uint32* pBytesWritten) { rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; wts_data_item* item; STREAM* s; int cbLen; int cbChId; int first; uint32 written; if (channel == NULL) return false; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { item = xnew(wts_data_item); item->buffer = xmalloc(Length); item->length = Length; memcpy(item->buffer, Buffer, Length); wts_queue_send_item(channel, item); } else if (channel->vcm->drdynvc_channel == NULL || channel->vcm->drdynvc_state != DRDYNVC_STATE_READY) { DEBUG_DVC("drdynvc not ready"); return false; } else { s = stream_new(0); first = true; while (Length > 0) { item = xnew(wts_data_item); item->buffer = xmalloc(channel->client->settings->vc_chunk_size); stream_attach(s, item->buffer, channel->client->settings->vc_chunk_size); stream_seek_uint8(s); cbChId = wts_write_variable_uint(s, channel->channel_id); if (first && (Length > (uint32) stream_get_left(s))) { cbLen = wts_write_variable_uint(s, Length); item->buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId; } else { item->buffer[0] = (DATA_PDU << 4) | cbChId; } first = false; written = stream_get_left(s); if (written > Length) written = Length; stream_write(s, Buffer, written); item->length = stream_get_length(s); stream_detach(s); Length -= written; Buffer += written; wts_queue_send_item(channel->vcm->drdynvc_channel, item); } stream_free(s); } if (pBytesWritten != NULL) *pBytesWritten = Length; return true; }
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); }
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, boolean user_loggedon) { STREAM* data_out; DEVICE* device; LIST_ITEM* item; uint32 count; uint8 c; int data_len; int i; int count_pos; int pos; 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_uint8(data_out, c); if (c > 0x7F) stream_write_uint8(data_out, '_'); else stream_seek_uint8(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); }
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; uint8 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_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 * 10 * sizeof(uint32)); else context->quants = (uint32*) xmalloc(context->num_quants * 10 * sizeof(uint32)); quants = context->quants; /* quantVals */ for (i = 0; i < context->num_quants; 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); 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); } }
boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 blockLength) { uint32 version; uint16 colorDepth = 0; uint16 postBeta2ColorDepth = 0; uint16 highColorDepth = 0; uint16 supportedColorDepths = 0; uint16 earlyCapabilityFlags = 0; uint32 serverSelectedProtocol = 0; char* str; /* Length of all required fields, until imeFileName */ if (blockLength < 128) return false; stream_read_uint32(s, version); /* version */ settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7); stream_read_uint16(s, settings->width); /* desktopWidth */ stream_read_uint16(s, settings->height); /* desktopHeight */ stream_read_uint16(s, colorDepth); /* colorDepth */ stream_seek_uint16(s); /* SASSequence (Secure Access Sequence) */ stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout */ stream_read_uint32(s, settings->client_build); /* clientBuild */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32); stream_seek(s, 32); snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str); xfree(str); stream_read_uint32(s, settings->kbd_type); /* keyboardType */ stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType */ stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */ stream_seek(s, 64); /* imeFileName */ blockLength -= 128; /** * The following fields are all optional. If one field is present, all of the preceding * fields MUST also be present. If one field is not present, all of the subsequent fields * MUST NOT be present. * We must check the bytes left before reading each field. */ do { if (blockLength < 2) break; stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */ blockLength -= 2; if (blockLength < 2) break; stream_seek_uint16(s); /* clientProductID */ blockLength -= 2; if (blockLength < 4) break; stream_seek_uint32(s); /* serialNumber */ blockLength -= 4; if (blockLength < 2) break; stream_read_uint16(s, highColorDepth); /* highColorDepth */ blockLength -= 2; if (blockLength < 2) break; stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */ blockLength -= 2; if (blockLength < 2) break; stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */ blockLength -= 2; if (blockLength < 64) break; str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); stream_seek(s, 64); snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str); xfree(str); blockLength -= 64; if (blockLength < 1) break; stream_read_uint8(s, settings->performance_flags); /* connectionType */ blockLength -= 1; if (blockLength < 1) break; stream_seek_uint8(s); /* pad1octet */ blockLength -= 1; if (blockLength < 4) break; stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */ blockLength -= 4; if (settings->selected_protocol != serverSelectedProtocol) return false; } while (0); if (highColorDepth > 0) settings->color_depth = highColorDepth; else if (postBeta2ColorDepth > 0) { switch (postBeta2ColorDepth) { case RNS_UD_COLOR_4BPP: settings->color_depth = 4; break; case RNS_UD_COLOR_8BPP: settings->color_depth = 8; break; case RNS_UD_COLOR_16BPP_555: settings->color_depth = 15; break; case RNS_UD_COLOR_16BPP_565: settings->color_depth = 16; break; case RNS_UD_COLOR_24BPP: settings->color_depth = 24; break; default: return false; } } else { switch (colorDepth) { case RNS_UD_COLOR_4BPP: settings->color_depth = 4; break; case RNS_UD_COLOR_8BPP: settings->color_depth = 8; break; default: return false; } } return true; }