BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, STREAM* s) { rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; stream_seek_UINT16(s); /* numberEntries (2 bytes) */ stream_seek_UINT16(s); /* totalNumEntries (2 bytes) */ stream_seek_UINT16(s); /* mapFlags (2 bytes) */ stream_seek_UINT16(s); /* entrySize (2 bytes) */ return TRUE; }
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { int i; UINT16 lengthCapability; UINT16 cCapabilitiesSets; UINT16 capabilitySetType; stream_read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ stream_seek_UINT16(s); /* pad1 (2 bytes) */ DEBUG_CLIPRDR("cCapabilitiesSets %d", cCapabilitiesSets); for (i = 0; i < cCapabilitiesSets; i++) { stream_read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ stream_read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ switch (capabilitySetType) { case CB_CAPSTYPE_GENERAL: cliprdr_process_general_capability(cliprdr, s); break; default: DEBUG_WARN("unknown cliprdr capability set: %d", capabilitySetType); break; } } }
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; }
BOOL update_recv_orders(rdpUpdate* update, STREAM* s) { UINT16 numberOrders; stream_seek_UINT16(s); /* pad2OctetsA (2 bytes) */ stream_read_UINT16(s, numberOrders); /* numberOrders (2 bytes) */ stream_seek_UINT16(s); /* pad2OctetsB (2 bytes) */ while (numberOrders > 0) { if (!update_recv_order(update, s)) return FALSE; numberOrders--; } return TRUE; }
void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result) { stream_read_UINT16(s, exec_result->flags); /* flags (2 bytes) */ stream_read_UINT16(s, exec_result->execResult); /* execResult (2 bytes) */ stream_read_UINT32(s, exec_result->rawResult); /* rawResult (4 bytes) */ stream_seek_UINT16(s); /* padding (2 bytes) */ rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */ }
void update_read_synchronize(rdpUpdate* update, STREAM* s) { stream_seek_UINT16(s); /* pad2Octets (2 bytes) */ /** * The Synchronize Update is an artifact from the * T.128 protocol and should be ignored. */ }
BOOL rdp_recv_control_pdu(STREAM* s, UINT16* action) { if (stream_get_left(s) < 8) return FALSE; stream_read_UINT16(s, *action); /* action (2 bytes) */ stream_seek_UINT16(s); /* grantId (2 bytes) */ stream_seek_UINT32(s); /* controlId (4 bytes) */ return TRUE; }
BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, STREAM* s) { UINT16 messageType; rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; if (stream_get_left(s) < 4) return FALSE; stream_read_UINT16(s, messageType); /* messageType (2 bytes) */ if (messageType != SYNCMSGTYPE_SYNC) return FALSE; /* targetUser (2 bytes) */ stream_seek_UINT16(s); return TRUE; }
void update_read_palette(rdpUpdate* update, STREAM* s, PALETTE_UPDATE* palette_update) { int i; PALETTE_ENTRY* entry; stream_seek_UINT16(s); /* pad2Octets (2 bytes) */ stream_read_UINT32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */ if (palette_update->number > 256) palette_update->number = 256; /* paletteEntries */ for (i = 0; i < (int) palette_update->number; i++) { entry = &palette_update->entries[i]; stream_read_BYTE(s, entry->blue); stream_read_BYTE(s, entry->green); stream_read_BYTE(s, entry->red); } }
void update_recv_pointer(rdpUpdate* update, STREAM* s) { UINT16 messageType; rdpContext* context = update->context; rdpPointerUpdate* pointer = update->pointer; stream_read_UINT16(s, messageType); /* messageType (2 bytes) */ stream_seek_UINT16(s); /* pad2Octets (2 bytes) */ switch (messageType) { case PTR_MSG_TYPE_POSITION: update_read_pointer_position(s, &pointer->pointer_position); IFCALL(pointer->PointerPosition, context, &pointer->pointer_position); break; case PTR_MSG_TYPE_SYSTEM: update_read_pointer_system(s, &pointer->pointer_system); IFCALL(pointer->PointerSystem, context, &pointer->pointer_system); break; case PTR_MSG_TYPE_COLOR: update_read_pointer_color(s, &pointer->pointer_color); IFCALL(pointer->PointerColor, context, &pointer->pointer_color); break; case PTR_MSG_TYPE_POINTER: update_read_pointer_new(s, &pointer->pointer_new); IFCALL(pointer->PointerNew, context, &pointer->pointer_new); break; case PTR_MSG_TYPE_CACHED: update_read_pointer_cached(s, &pointer->pointer_cached); IFCALL(pointer->PointerCached, context, &pointer->pointer_cached); break; default: break; } }
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; }
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); } }