static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; stream_seek_BYTE(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*) realloc(message->rects, message->num_rects * sizeof(RFX_RECT)); else message->rects = (RFX_RECT*) malloc(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); } }
BOOL rdp_read_share_data_header(STREAM* s, UINT16* length, BYTE* type, UINT32* share_id, BYTE *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_BYTE(s); /* pad1 (1 byte) */ stream_seek_BYTE(s); /* streamId (1 byte) */ stream_read_UINT16(s, *length); /* uncompressedLength (2 bytes) */ stream_read_BYTE(s, *type); /* pduType2, Data PDU Type (1 byte) */ stream_read_BYTE(s, *compressed_type); /* compressedType (1 byte) */ stream_read_UINT16(s, *compressed_len); /* compressedLength (2 bytes) */ return TRUE; }
BOOL 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_BYTE(s); /* pad2Octets (1 byte) */ return TRUE; }
static BOOL 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_BYTE(s); /* cLastBlockConfirmed */ stream_seek_UINT16(s); /* wVersion */ stream_seek_BYTE(s); /* bPad */ if (rdpsnd->context.num_client_formats > 0) { rdpsnd->context.client_formats = (rdpsndFormat*) malloc(rdpsnd->context.num_client_formats * sizeof(rdpsndFormat)); ZeroMemory(rdpsnd->context.client_formats, sizeof(rdpsndFormat)); for (i = 0; i < rdpsnd->context.num_client_formats; i++) { if (stream_get_left(s) < 18) { free(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; }
static void wts_write_drdynvc_header(wStream *s, BYTE Cmd, UINT32 ChannelId) { BYTE* bm; int cbChId; stream_get_mark(s, bm); stream_seek_BYTE(s); cbChId = wts_write_variable_uint(s, ChannelId); *bm = ((Cmd & 0x0F) << 4) | cbChId; }
/* * 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) { BYTE length1; stream_seek_BYTE(s); stream_read_BYTE(s, length1); stream_rewind(s, 2); return ((length1 & 0x80) != 0 ? 3 : 2); }
BOOL nego_read_request(rdpNego* nego, STREAM* s) { BYTE li; BYTE c; BYTE type; tpkt_read_header(s); if(!tpdu_read_connection_request(s, &li)) return FALSE; 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_BYTE(s, c); if (c != '\x0D') continue; stream_peek_BYTE(s, c); if (c != '\x0A') continue; stream_seek_BYTE(s); break; } } if (stream_get_left(s) >= 8) { /* rdpNegData (optional) */ stream_read_BYTE(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_BYTE(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; }
static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; if (stream_get_left(s) < 3) { DEBUG_WARN("RfxMessageRegion packet too small"); return FALSE; } stream_seek_BYTE(s); /* regionFlags (1 byte) */ stream_read_UINT16(s, message->num_rects); /* numRects (2 bytes) */ if (message->num_rects < 1) { DEBUG_WARN("no rects."); return TRUE; } if (stream_get_left(s) < 8 * message->num_rects) { DEBUG_WARN("RfxMessageRegion packet too small for num_rects=%d", message->num_rects); return FALSE; } if (message->rects != NULL) message->rects = (RFX_RECT*) realloc(message->rects, message->num_rects * sizeof(RFX_RECT)); else message->rects = (RFX_RECT*) malloc(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); } return TRUE; }
void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { stream_read_UINT16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_UINT16(s, pointer_color->xPos); /* xPos (2 bytes) */ stream_read_UINT16(s, pointer_color->yPos); /* yPos (2 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) */ /** * There does not seem to be any documentation on why * xPos / yPos can be larger than width / height * so it is missing in documentation or a bug in implementation * 2.2.9.1.1.4.4 Color Pointer Update (TS_COLORPOINTERATTRIBUTE) */ if (pointer_color->xPos >= pointer_color->width) pointer_color->xPos = 0; if (pointer_color->yPos >= pointer_color->height) pointer_color->yPos = 0; if (pointer_color->lengthXorMask > 0) { pointer_color->xorMaskData = (BYTE*) malloc(pointer_color->lengthXorMask); stream_read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask); } if (pointer_color->lengthAndMask > 0) { pointer_color->andMaskData = (BYTE*) malloc(pointer_color->lengthAndMask); stream_read(s, pointer_color->andMaskData, pointer_color->lengthAndMask); } if (stream_get_left(s) > 0) stream_seek_BYTE(s); /* pad (1 byte) */ }
BOOL WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ BYTE* Buffer, /* __in */ UINT32 Length, /* __out */ UINT32* pBytesWritten) { rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; wts_data_item* item; wStream* s; int cbLen; int cbChId; int first; UINT32 written; if (channel == NULL) return FALSE; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { item = (wts_data_item*) malloc(sizeof(wts_data_item)); ZeroMemory(item, sizeof(wts_data_item)); item->buffer = malloc(Length); item->length = Length; CopyMemory(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 = (wts_data_item*) malloc(sizeof(wts_data_item)); ZeroMemory(item, sizeof(wts_data_item)); item->buffer = malloc(channel->client->settings->VirtualChannelChunkSize); stream_attach(s, item->buffer, channel->client->settings->VirtualChannelChunkSize); stream_seek_BYTE(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; }
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input) { char* s = NULL; mode_t m; UINT64 size; int status; char* fullpath; struct STAT st; struct timeval tv[2]; UINT64 LastWriteTime; UINT32 FileAttributes; UINT32 FileNameLength; m = 0; 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; #ifndef WIN32 /* TODO on win32 */ 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); } #endif 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 */ /* http://msdn.microsoft.com/en-us/library/cc241371.aspx */ if (Length) stream_read_BYTE(input, file->delete_pending); else file->delete_pending = 1; break; case FileRenameInformation: /* http://msdn.microsoft.com/en-us/library/cc232085.aspx */ stream_seek_BYTE(input); /* ReplaceIfExists */ stream_seek_BYTE(input); /* RootDirectory */ stream_read_UINT32(input, FileNameLength); status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(input), FileNameLength / 2, &s, 0, NULL, NULL); if (status < 1) s = (char*) calloc(1, 1); fullpath = drive_file_combine_fullpath(file->basepath, s); free(s); /* TODO rename does not work on win32 */ if (rename(file->fullpath, fullpath) == 0) { DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath); drive_file_set_fullpath(file, fullpath); } else { DEBUG_WARN("rename %s to %s failed, errno = %d", file->fullpath, fullpath, errno); free(fullpath); return FALSE; } break; default: DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); return FALSE; } return TRUE; }
static void* rdpsnd_server_thread_func(void* arg) { void* fd; STREAM* s; void* buffer; BYTE 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, (int) bytes_returned); if (WTSVirtualChannelRead(rdpsnd->rdpsnd_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == FALSE) break; } stream_read_BYTE(s, msgType); stream_seek_BYTE(s); /* bPad */ stream_read_UINT16(s, BodySize); if (BodySize + 4 > (int) 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; }
BOOL gcc_read_client_core_data(STREAM* s, rdpSettings* settings, UINT16 blockLength) { char* str; UINT32 version; UINT32 color_depth; UINT16 colorDepth = 0; UINT16 postBeta2ColorDepth = 0; UINT16 highColorDepth = 0; UINT16 supportedColorDepths = 0; UINT16 earlyCapabilityFlags = 0; UINT32 serverSelectedProtocol = 0; /* Length of all required fields, until imeFileName */ if (blockLength < 128) return FALSE; stream_read_UINT32(s, version); /* version */ settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7); stream_read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */ stream_read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */ stream_read_UINT16(s, colorDepth); /* ColorDepth */ stream_seek_UINT16(s); /* SASSequence (Secure Access Sequence) */ stream_read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */ stream_read_UINT32(s, settings->ClientBuild); /* ClientBuild */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), 32 / 2, &str, 0, NULL, NULL); stream_seek(s, 32); sprintf_s(settings->ClientHostname, 31, "%s", str); settings->ClientHostname[31] = 0; free(str); stream_read_UINT32(s, settings->KeyboardType); /* KeyboardType */ stream_read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */ stream_read_UINT32(s, settings->KeyboardFunctionKey); /* 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; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), 64 / 2, &str, 0, NULL, NULL); stream_seek(s, 64); sprintf_s(settings->ClientProductId, 32, "%s", str); free(str); blockLength -= 64; if (blockLength < 1) break; stream_read_BYTE(s, settings->PerformanceFlags); /* connectionType */ blockLength -= 1; if (blockLength < 1) break; stream_seek_BYTE(s); /* pad1octet */ blockLength -= 1; if (blockLength < 4) break; stream_read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol */ blockLength -= 4; if (settings->SelectedProtocol != serverSelectedProtocol) return FALSE; } while (0); if (highColorDepth > 0) { color_depth = highColorDepth; } else if (postBeta2ColorDepth > 0) { switch (postBeta2ColorDepth) { case RNS_UD_COLOR_4BPP: color_depth = 4; break; case RNS_UD_COLOR_8BPP: color_depth = 8; break; case RNS_UD_COLOR_16BPP_555: color_depth = 15; break; case RNS_UD_COLOR_16BPP_565: color_depth = 16; break; case RNS_UD_COLOR_24BPP: color_depth = 24; break; default: return FALSE; } } else { switch (colorDepth) { case RNS_UD_COLOR_4BPP: color_depth = 4; break; case RNS_UD_COLOR_8BPP: color_depth = 8; break; default: return FALSE; } } /* * If we are in server mode, accept client's color depth only if * it is smaller than ours. This is what Windows server does. */ if (color_depth < settings->ColorDepth || !settings->ServerMode) settings->ColorDepth = color_depth; return TRUE; }
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 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 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); }