From f4353c2a62f016c7544dda713ed5ed23d9e4b30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 21 Jul 2011 01:56:48 -0400 Subject: [PATCH] libfreerdp-core: encoding of capability sets --- include/freerdp/settings.h | 17 +- libfreerdp-core/capabilities.c | 528 +++++++++++++++++++++++++++++++-- libfreerdp-core/capabilities.h | 11 +- libfreerdp-core/settings.c | 12 + 4 files changed, 542 insertions(+), 26 deletions(-) diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index acd2c4c70..733418ee8 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -172,12 +172,16 @@ struct rdp_settings boolean suppress_output; boolean desktop_resize; + boolean frame_marker; + boolean bitmap_cache_v3; + uint8 order_support[32]; boolean color_pointer; boolean sound_beeps; boolean fast_path_input; + boolean auto_reconnection; boolean offscreen_bitmap_cache; uint16 offscreen_bitmap_cache_size; @@ -194,13 +198,18 @@ struct rdp_settings boolean draw_gdi_plus; boolean draw_gdi_plus_cache; + boolean large_pointer; + + boolean surface_commands; + uint32 multifrag_max_request_size; + + boolean desktop_composition; + + boolean frame_acknowledge; + boolean remote_app; char app_name[64]; - int bitmap_cache; - int bitmap_cache_persist_enable; - int bitmap_cache_precache; - int bitmap_compression; int desktop_save; int polygon_ellipse_orders; int off_screen_bitmaps; diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index 5274c8210..ab091de62 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -59,6 +59,32 @@ void rdp_read_capability_set_header(STREAM* s, uint16* length, uint16* type) stream_read_uint16(s, *length); /* lengthCapability */ } +void rdp_write_capability_set_header(STREAM* s, uint16 length, uint16 type) +{ + stream_write_uint16(s, type); /* capabilitySetType */ + stream_write_uint16(s, length); /* lengthCapability */ +} + +uint8* rdp_capability_set_start(STREAM* s) +{ + uint8* header; + + stream_get_mark(s, header); + stream_seek(s, CAPSET_HEADER_LENGTH); + + return header; +} + +void rdp_capability_set_finish(STREAM* s, uint8* header, uint16 type) +{ + uint16 length; + + length = s->p - header; + stream_set_mark(s, header); + rdp_write_capability_set_header(s, length, type); + stream_set_mark(s, header + length); +} + /** * Read general capability set.\n * @msdn{cc240549} @@ -100,7 +126,32 @@ void rdp_read_general_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_general_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 extraFlags; + header = rdp_capability_set_start(s); + + extraFlags = LONG_CREDENTIALS_SUPPORTED | NO_BITMAP_COMPRESSION_HDR; + + if (settings->auto_reconnection) + extraFlags |= AUTORECONNECT_SUPPORTED; + + if (settings->fast_path_input) + extraFlags |= FASTPATH_OUTPUT_SUPPORTED; + + stream_write_uint16(s, 0); /* osMajorType (2 bytes) */ + stream_write_uint16(s, 0); /* osMinorType (2 bytes) */ + stream_write_uint16(s, CAPS_PROTOCOL_VERSION); /* protocolVersion (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ + stream_write_uint16(s, 0); /* generalCompressionTypes (2 bytes) */ + stream_write_uint16(s, 0); /* extraFlags (2 bytes) */ + stream_write_uint16(s, 0); /* updateCapabilityFlag (2 bytes) */ + stream_write_uint16(s, 0); /* remoteUnshareFlag (2 bytes) */ + stream_write_uint16(s, 0); /* generalCompressionLevel (2 bytes) */ + stream_write_uint8(s, settings->refresh_rect); /* refreshRectSupport (1 byte) */ + stream_write_uint8(s, settings->suppress_output); /* suppressOutputSupport (1 byte) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_GENERAL); } /** @@ -145,7 +196,34 @@ void rdp_read_bitmap_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_bitmap_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint8 drawingFlags; + uint16 preferredBitsPerPixel; + header = rdp_capability_set_start(s); + + drawingFlags = 0; + + if (settings->rdp_version > 5) + preferredBitsPerPixel = settings->color_depth; + else + preferredBitsPerPixel = 8; + + stream_write_uint16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */ + stream_write_uint16(s, 1); /* receive1BitPerPixel (2 bytes) */ + stream_write_uint16(s, 1); /* receive4BitsPerPixel (2 bytes) */ + stream_write_uint16(s, 1); /* receive8BitsPerPixel (2 bytes) */ + stream_write_uint16(s, settings->width); /* desktopWidth (2 bytes) */ + stream_write_uint16(s, settings->height); /* desktopHeight (2 bytes) */ + stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ + stream_write_uint16(s, settings->desktop_resize); /* desktopResizeFlag (2 bytes) */ + stream_write_uint16(s, 1); /* bitmapCompressionFlag (2 bytes) */ + stream_write_uint8(s, 0); /* highColorFlags (1 byte) */ + stream_write_uint8(s, drawingFlags); /* drawingFlags (1 byte) */ + stream_write_uint16(s, 1); /* multipleRectangleSupport (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsB (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP); } /** @@ -196,7 +274,44 @@ void rdp_read_order_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_order_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 orderFlags; + uint16 orderSupportExFlags; + header = rdp_capability_set_start(s); + + orderFlags = NEGOTIATE_ORDER_SUPPORT | + ZERO_BOUNDS_DELTA_SUPPORT | + COLOR_INDEX_SUPPORT | + ORDER_FLAGS_EXTRA_SUPPORT; + + orderSupportExFlags = 0; + + if (settings->frame_marker) + orderSupportExFlags |= CACHE_BITMAP_V3_SUPPORT; + + if (settings->bitmap_cache_v3) + orderSupportExFlags |= ALTSEC_FRAME_MARKER_SUPPORT; + + stream_write_zero(s, 16); /* terminalDescriptor (16 bytes) */ + stream_write_uint32(s, 0); /* pad4OctetsA (4 bytes) */ + stream_write_uint16(s, 1); /* desktopSaveXGranularity (2 bytes) */ + stream_write_uint16(s, 20); /* desktopSaveYGranularity (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ + stream_write_uint16(s, 1); /* maximumOrderLevel (2 bytes) */ + stream_write_uint16(s, 0); /* numberFonts (2 bytes) */ + stream_write_uint16(s, orderFlags); /* orderFlags (2 bytes) */ + stream_write(s, settings->order_support, 32); /* orderSupport (32 bytes) */ + stream_write_uint16(s, 0); /* textFlags (2 bytes) */ + stream_write_uint16(s, orderSupportExFlags); /* orderSupportExFlags (2 bytes) */ + stream_write_uint32(s, 0); /* pad4OctetsB (4 bytes) */ + stream_write_uint32(s, 230400); /* desktopSaveSize (4 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsC (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsD (2 bytes) */ + stream_write_uint16(s, 0); /* textANSICodePage (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsE (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_ORDER); } /** @@ -231,7 +346,34 @@ void rdp_read_bitmap_cache_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_bitmap_cache_capability_set(STREAM* s, rdpSettings* settings) { + int bpp; + uint16 size; + uint8* header; + header = rdp_capability_set_start(s); + + bpp = (settings->color_depth + 7) / 8; + + stream_write_uint32(s, 0); /* pad1 (4 bytes) */ + stream_write_uint32(s, 0); /* pad2 (4 bytes) */ + stream_write_uint32(s, 0); /* pad3 (4 bytes) */ + stream_write_uint32(s, 0); /* pad4 (4 bytes) */ + stream_write_uint32(s, 0); /* pad5 (4 bytes) */ + stream_write_uint32(s, 0); /* pad6 (4 bytes) */ + + size = bpp * 256; + stream_write_uint16(s, 200); /* Cache0Entries (2 bytes) */ + stream_write_uint16(s, size); /* Cache0MaximumCellSize (2 bytes) */ + + size = bpp * 1024; + stream_write_uint16(s, 600); /* Cache1Entries (2 bytes) */ + stream_write_uint16(s, size); /* Cache1MaximumCellSize (2 bytes) */ + + size = bpp * 4096; + stream_write_uint16(s, 1000); /* Cache2Entries (2 bytes) */ + stream_write_uint16(s, size); /* Cache2MaximumCellSize (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE); } /** @@ -258,7 +400,16 @@ void rdp_read_control_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_control_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint16(s, 0); /* controlFlags (2 bytes) */ + stream_write_uint16(s, 0); /* remoteDetachFlag (2 bytes) */ + stream_write_uint16(s, 2); /* controlInterest (2 bytes) */ + stream_write_uint16(s, 2); /* detachInterest (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_CONTROL); } /** @@ -285,7 +436,16 @@ void rdp_read_window_activation_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_window_activation_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint16(s, 0); /* helpKeyFlag (2 bytes) */ + stream_write_uint16(s, 0); /* helpKeyIndexFlag (2 bytes) */ + stream_write_uint16(s, 0); /* helpExtendedKeyFlag (2 bytes) */ + stream_write_uint16(s, 0); /* windowManagerKeyFlag (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_ACTIVATION); } /** @@ -318,7 +478,18 @@ void rdp_read_pointer_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_pointer_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 colorPointerFlag; + header = rdp_capability_set_start(s); + + colorPointerFlag = (settings->color_pointer) ? True : False; + + stream_write_uint16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */ + stream_write_uint16(s, 20); /* colorPointerCacheSize (2 bytes) */ + stream_write_uint16(s, 20); /* pointerCacheSize (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_POINTER); } /** @@ -343,7 +514,14 @@ void rdp_read_share_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_share_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint16(s, 0); /* nodeId (2 bytes) */ + stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_SHARE); } /** @@ -368,7 +546,14 @@ void rdp_read_color_cache_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_color_cache_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint16(s, 6); /* colorTableCacheSize (2 bytes) */ + stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_COLOR_CACHE); } /** @@ -397,7 +582,17 @@ void rdp_read_sound_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_sound_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 soundFlags; + header = rdp_capability_set_start(s); + + soundFlags = (settings->sound_beeps) ? SOUND_BEEPS_FLAG : 0; + + stream_write_uint16(s, soundFlags); /* soundFlags (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_SOUND); } /** @@ -410,17 +605,13 @@ void rdp_write_sound_capability_set(STREAM* s, rdpSettings* settings) void rdp_read_input_capability_set(STREAM* s, rdpSettings* settings) { uint16 inputFlags; - uint32 keyboardLayout; - uint32 keyboardType; - uint32 keyboardSubType; - uint32 keyboardFunctionKeys; stream_read_uint16(s, inputFlags); /* inputFlags (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */ - stream_read_uint32(s, keyboardLayout); /* keyboardLayout (4 bytes) */ - stream_read_uint32(s, keyboardType); /* keyboardType (4 bytes) */ - stream_read_uint32(s, keyboardSubType); /* keyboardSubType (4 bytes) */ - stream_read_uint32(s, keyboardFunctionKeys); /* keyboardFunctionKeys (4 bytes) */ + stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout (4 bytes) */ + stream_read_uint32(s, settings->kbd_type); /* keyboardType (4 bytes) */ + stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType (4 bytes) */ + stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKeys (4 bytes) */ stream_seek(s, 64); /* imeFileName (64 bytes) */ if ((inputFlags & INPUT_FLAG_FASTPATH_INPUT) || (inputFlags & INPUT_FLAG_FASTPATH_INPUT2)) @@ -439,7 +630,28 @@ void rdp_read_input_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_input_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 inputFlags; + header = rdp_capability_set_start(s); + + inputFlags = INPUT_FLAG_SCANCODES | INPUT_FLAG_MOUSEX | INPUT_FLAG_UNICODE; + + if (settings->fast_path_input) + { + inputFlags |= INPUT_FLAG_FASTPATH_INPUT; + inputFlags |= INPUT_FLAG_FASTPATH_INPUT2; + } + + stream_write_uint16(s, inputFlags); /* inputFlags (2 bytes) */ + stream_write_uint16(s, 0); /* pad2OctetsA (2 bytes) */ + stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout (4 bytes) */ + stream_write_uint32(s, settings->kbd_type); /* keyboardType (4 bytes) */ + stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType (4 bytes) */ + stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKeys (4 bytes) */ + stream_write_zero(s, 64); /* imeFileName (64 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_INPUT); } /** @@ -464,7 +676,14 @@ void rdp_read_font_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_font_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint16(s, FONTSUPPORT_FONTLIST); /* fontSupportFlags (2 bytes) */ + stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_FONT); } /** @@ -488,7 +707,35 @@ void rdp_read_brush_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_brush_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint32(s, BRUSH_COLOR_FULL); /* brushSupportLevel (4 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_BRUSH); +} + +/** + * Read cache definition (glyph).\n + * @msdn{cc240566} + * @param s stream + */ +void rdp_read_cache_definition(STREAM* s, uint16* numEntries, uint16* maxCellSize) +{ + stream_read_uint16(s, *numEntries); /* cacheEntries (2 bytes) */ + stream_read_uint16(s, *maxCellSize); /* cacheMaximumCellSize (2 bytes) */ +} + +/** + * Write cache definition (glyph).\n + * @msdn{cc240566} + * @param s stream + */ +void rdp_write_cache_definition(STREAM* s, uint16 numEntries, uint16 maxCellSize) +{ + stream_write_uint16(s, numEntries); /* cacheEntries (2 bytes) */ + stream_write_uint16(s, maxCellSize); /* cacheMaximumCellSize (2 bytes) */ } /** @@ -515,7 +762,27 @@ void rdp_read_glyph_cache_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_glyph_cache_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + /* glyphCache (40 bytes) */ + rdp_write_cache_definition(s, 254, 4); + rdp_write_cache_definition(s, 254, 4); + rdp_write_cache_definition(s, 254, 8); + rdp_write_cache_definition(s, 254, 8); + rdp_write_cache_definition(s, 254, 16); + rdp_write_cache_definition(s, 254, 32); + rdp_write_cache_definition(s, 254, 64); + rdp_write_cache_definition(s, 254, 256); + rdp_write_cache_definition(s, 64, 2048); + + rdp_write_cache_definition(s, 64, 2048); /* fragCache */ + + stream_write_uint16(s, GLYPH_SUPPORT_FULL); /* glyphSupportLevel (2 bytes) */ + stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_GLYPH_CACHE); } /** @@ -548,7 +815,15 @@ void rdp_read_offscreen_bitmap_cache_capability_set(STREAM* s, rdpSettings* sett void rdp_write_offscreen_bitmap_cache_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_read_uint32(s, settings->offscreen_bitmap_cache); /* offscreenSupportLevel (4 bytes) */ + stream_write_uint16(s, settings->offscreen_bitmap_cache_size); /* offscreenCacheSize (2 bytes) */ + stream_write_uint16(s, settings->offscreen_bitmap_cache_entries); /* offscreenCacheEntries (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_OFFSCREEN_CACHE); } /** @@ -579,7 +854,29 @@ void rdp_read_bitmap_cache_host_support_capability_set(STREAM* s, rdpSettings* s void rdp_write_bitmap_cache_host_support_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint8(s, BITMAP_CACHE_V2); /* cacheVersion (1 byte) */ + stream_write_uint8(s, 0); /* pad1 (1 byte) */ + stream_write_uint16(s, 0); /* pad2 (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT); +} + +void rdp_write_bitmap_cache_cell_info(STREAM* s, uint16 numEntries, boolean persistent) +{ + uint32 info; + + /** + * numEntries is in the first 31 bits, while the last bit (k) + * is used to indicate a persistent bitmap cache. + */ + + info = numEntries & persistent; + + stream_write_uint32(s, info); } /** @@ -611,7 +908,27 @@ void rdp_read_bitmap_cache_v2_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_bitmap_cache_v2_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 cacheFlags; + header = rdp_capability_set_start(s); + + cacheFlags = ALLOW_CACHE_WAITING_LIST_FLAG; + + if (settings->persistent_bitmap_cache) + cacheFlags |= PERSISTENT_KEYS_EXPECTED_FLAG; + + stream_write_uint16(s, cacheFlags); /* cacheFlags (2 bytes) */ + stream_write_uint8(s, 0); /* pad2 (1 byte) */ + stream_write_uint8(s, 5); /* numCellCaches (1 byte) */ + rdp_write_bitmap_cache_cell_info(s, 600, 0); /* bitmapCache0CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, 600, 0); /* bitmapCache1CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, 2048, 0); /* bitmapCache2CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, 4096, 0); /* bitmapCache3CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, 2048, 0); /* bitmapCache4CellInfo (4 bytes) */ + stream_write_zero(s, 12); /* pad3 (12 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2); } /** @@ -636,7 +953,14 @@ void rdp_read_virtual_channel_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_virtual_channel_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint32(s, VCCAPS_COMPR_SC); /* flags (4 bytes) */ + stream_write_uint32(s, 0); /* VCChunkSize (4 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_VIRTUAL_CHANNEL); } /** @@ -670,7 +994,42 @@ void rdp_read_draw_nine_grid_cache_capability_set(STREAM* s, rdpSettings* settin void rdp_write_draw_nine_grid_cache_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint32 drawNineGridSupportLevel; + header = rdp_capability_set_start(s); + + drawNineGridSupportLevel = (settings->draw_nine_grid) ? DRAW_NINEGRID_SUPPORTED : DRAW_NINEGRID_NO_SUPPORT; + + stream_read_uint32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */ + stream_read_uint16(s, settings->draw_nine_grid_cache_size); /* drawNineGridCacheSize (2 bytes) */ + stream_read_uint16(s, settings->draw_nine_grid_cache_entries); /* drawNineGridCacheEntries (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_NINE_GRID_CACHE); +} + +void rdp_write_gdiplus_cache_entries(STREAM* s, uint16 gce, uint16 bce, uint16 pce, uint16 ice, uint16 ace) +{ + stream_write_uint16(s, gce); /* gdipGraphicsCacheEntries (2 bytes) */ + stream_write_uint16(s, bce); /* gdipBrushCacheEntries (2 bytes) */ + stream_write_uint16(s, pce); /* gdipPenCacheEntries (2 bytes) */ + stream_write_uint16(s, ice); /* gdipImageCacheEntries (2 bytes) */ + stream_write_uint16(s, ace); /* gdipImageAttributesCacheEntries (2 bytes) */ +} + +void rdp_write_gdiplus_cache_chunk_size(STREAM* s, uint16 gccs, uint16 obccs, uint16 opccs, uint16 oiaccs) +{ + stream_write_uint16(s, gccs); /* gdipGraphicsCacheChunkSize (2 bytes) */ + stream_write_uint16(s, obccs); /* gdipObjectBrushCacheChunkSize (2 bytes) */ + stream_write_uint16(s, opccs); /* gdipObjectPenCacheChunkSize (2 bytes) */ + stream_write_uint16(s, oiaccs); /* gdipObjectImageAttributesCacheChunkSize (2 bytes) */ +} + +void rdp_write_gdiplus_image_cache_properties(STREAM* s, uint16 oiccs, uint16 oicts, uint16 oicms) +{ + stream_write_uint16(s, oiccs); /* gdipObjectImageCacheChunkSize (2 bytes) */ + stream_write_uint16(s, oicts); /* gdipObjectImageCacheTotalSize (2 bytes) */ + stream_write_uint16(s, oicms); /* gdipObjectImageCacheMaxSize (2 bytes) */ } /** @@ -680,7 +1039,7 @@ void rdp_write_draw_nine_grid_cache_capability_set(STREAM* s, rdpSettings* setti * @param settings settings */ -void rdp_read_draw_gdi_plus_cache_capability_set(STREAM* s, rdpSettings* settings) +void rdp_read_draw_gdiplus_cache_capability_set(STREAM* s, rdpSettings* settings) { uint32 drawGDIPlusSupportLevel; uint32 drawGdiplusCacheLevel; @@ -706,9 +1065,25 @@ void rdp_read_draw_gdi_plus_cache_capability_set(STREAM* s, rdpSettings* setting * @param settings settings */ -void rdp_write_draw_gdi_plus_cache_capability_set(STREAM* s, rdpSettings* settings) +void rdp_write_draw_gdiplus_cache_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint32 drawGDIPlusSupportLevel; + uint32 drawGdiplusCacheLevel; + header = rdp_capability_set_start(s); + + drawGDIPlusSupportLevel = (settings->draw_gdi_plus) ? DRAW_GDIPLUS_SUPPORTED : DRAW_GDIPLUS_DEFAULT; + drawGdiplusCacheLevel = (settings->draw_gdi_plus) ? DRAW_GDIPLUS_CACHE_LEVEL_ONE : DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT; + + stream_write_uint32(s, drawGDIPlusSupportLevel); /* drawGDIPlusSupportLevel (4 bytes) */ + stream_write_uint32(s, 0); /* GdipVersion (4 bytes) */ + stream_write_uint32(s, drawGdiplusCacheLevel); /* drawGdiplusCacheLevel (4 bytes) */ + rdp_write_gdiplus_cache_entries(s, 10, 5, 5, 10, 2); /* GdipCacheEntries (10 bytes) */ + rdp_write_gdiplus_cache_chunk_size(s, 512, 2048, 1024, 64); /* GdipCacheChunkSize (8 bytes) */ + rdp_write_gdiplus_image_cache_properties(s, 4096, 256, 128); /* GdipImageCacheProperties (6 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_GDI_PLUS); } /** @@ -724,11 +1099,7 @@ void rdp_read_remote_programs_capability_set(STREAM* s, rdpSettings* settings) stream_read_uint32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ - if (railSupportLevel & RAIL_LEVEL_SUPPORTED) - { - - } - else + if ((railSupportLevel & RAIL_LEVEL_SUPPORTED) == 0) { if (settings->remote_app == True) { @@ -747,7 +1118,17 @@ void rdp_read_remote_programs_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_remote_programs_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint32 railSupportLevel = 0; + header = rdp_capability_set_start(s); + + if (settings->remote_app) + railSupportLevel = RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED; + + stream_read_uint32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL); } /** @@ -759,9 +1140,9 @@ void rdp_write_remote_programs_capability_set(STREAM* s, rdpSettings* settings) void rdp_read_window_list_capability_set(STREAM* s, rdpSettings* settings) { - stream_seek_uint32(s); /* WndSupportLevel (4 bytes) */ - stream_seek_uint8(s); /* NumIconCaches (1 byte) */ - stream_seek_uint16(s); /* NumIconCacheEntries (2 bytes) */ + stream_seek_uint32(s); /* wndSupportLevel (4 bytes) */ + stream_seek_uint8(s); /* numIconCaches (1 byte) */ + stream_seek_uint16(s); /* numIconCacheEntries (2 bytes) */ } /** @@ -773,7 +1154,18 @@ void rdp_read_window_list_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_window_list_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint32 wndSupportLevel; + header = rdp_capability_set_start(s); + + wndSupportLevel = WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX; + + stream_write_uint32(s, wndSupportLevel); /* wndSupportLevel (4 bytes) */ + stream_write_uint8(s, 3); /* numIconCaches (1 byte) */ + stream_write_uint16(s, 12); /* numIconCacheEntries (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW); } /** @@ -785,7 +1177,7 @@ void rdp_write_window_list_capability_set(STREAM* s, rdpSettings* settings) void rdp_read_desktop_composition_capability_set(STREAM* s, rdpSettings* settings) { - stream_seek_uint16(s); /* CompDeskSupportLevel (2 bytes) */ + stream_seek_uint16(s); /* compDeskSupportLevel (2 bytes) */ } /** @@ -797,7 +1189,16 @@ void rdp_read_desktop_composition_capability_set(STREAM* s, rdpSettings* setting void rdp_write_desktop_composition_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 compDeskSupportLevel; + header = rdp_capability_set_start(s); + + compDeskSupportLevel = (settings->desktop_composition) ? COMPDESK_SUPPORTED : COMPDESK_NOT_SUPPORTED; + + stream_write_uint16(s, compDeskSupportLevel); /* compDeskSupportLevel (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_COMP_DESK); } /** @@ -809,7 +1210,7 @@ void rdp_write_desktop_composition_capability_set(STREAM* s, rdpSettings* settin void rdp_read_multifragment_update_capability_set(STREAM* s, rdpSettings* settings) { - stream_seek_uint32(s); /* MaxRequestSize (4 bytes) */ + stream_read_uint32(s, settings->multifrag_max_request_size); /* MaxRequestSize (4 bytes) */ } /** @@ -821,7 +1222,13 @@ void rdp_read_multifragment_update_capability_set(STREAM* s, rdpSettings* settin void rdp_write_multifragment_update_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + stream_write_uint32(s, settings->multifrag_max_request_size); /* MaxRequestSize (4 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_MULTI_FRAGMENT_UPDATE); } /** @@ -845,7 +1252,16 @@ void rdp_read_large_pointer_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_large_pointer_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint16 largePointerSupportFlags; + header = rdp_capability_set_start(s); + + largePointerSupportFlags = (settings->large_pointer) ? LARGE_POINTER_FLAG_96x96 : 0; + + stream_write_uint16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER); } /** @@ -859,6 +1275,8 @@ void rdp_read_surface_commands_capability_set(STREAM* s, rdpSettings* settings) { stream_seek_uint32(s); /* cmdFlags (4 bytes) */ stream_seek_uint32(s); /* reserved (4 bytes) */ + + settings->surface_commands = True; } /** @@ -870,7 +1288,19 @@ void rdp_read_surface_commands_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_surface_commands_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + uint32 cmdFlags; + header = rdp_capability_set_start(s); + + cmdFlags = SURFCMDS_FRAME_MARKER | + SURFCMDS_SET_SURFACE_BITS | + SURFCMDS_STREAM_SURFACE_BITS; + + stream_write_uint32(s, cmdFlags); /* cmdFlags (4 bytes) */ + stream_write_uint32(s, 0); /* reserved (4 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_SURFACE_COMMANDS); } /** @@ -908,7 +1338,41 @@ void rdp_read_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings) void rdp_write_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings) { + uint8* header; + header = rdp_capability_set_start(s); + + + + rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS); +} + +/** + * Read frame acknowledge capability set.\n + * @param s stream + * @param settings settings + */ + +void rdp_read_frame_acknowledge_capability_set(STREAM* s, rdpSettings* settings) +{ + stream_seek_uint32(s); /* (4 bytes) */ +} + +/** + * Write frame acknowledge capability set.\n + * @param s stream + * @param settings settings + */ + +void rdp_write_frame_acknowledge_capability_set(STREAM* s, rdpSettings* settings) +{ + uint8* header; + + header = rdp_capability_set_start(s); + + stream_write_uint32(s, 2); /* (4 bytes) */ + + rdp_capability_set_finish(s, header, CAPSET_TYPE_FRAME_ACKNOWLEDGE); } void rdp_read_demand_active(STREAM* s, rdpSettings* settings) @@ -1018,7 +1482,7 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) break; case CAPSET_TYPE_DRAW_GDI_PLUS: - rdp_read_draw_gdi_plus_cache_capability_set(s, settings); + rdp_read_draw_gdiplus_cache_capability_set(s, settings); break; case CAPSET_TYPE_RAIL: @@ -1049,6 +1513,10 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) rdp_read_bitmap_codecs_capability_set(s, settings); break; + case CAPSET_TYPE_FRAME_ACKNOWLEDGE: + rdp_read_frame_acknowledge_capability_set(s, settings); + break; + default: break; } @@ -1061,6 +1529,24 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) } } +void rdp_write_confirm_active(STREAM* s, rdpSettings* settings) +{ + uint16 numberCapabilities; + uint16 lengthSourceDescriptor; + uint16 lengthCombinedCapabilities; + + lengthSourceDescriptor = sizeof(SOURCE_DESCRIPTOR); + + stream_write_uint32(s, settings->share_id); /* shareId (4 bytes) */ + stream_write_uint16(s, 0x03EA); /* originatorId (2 bytes) */ + stream_write_uint16(s, sizeof(SOURCE_DESCRIPTOR));/* lengthSourceDescriptor (2 bytes) */ + /* lengthCombinedCapabilities (2 bytes) */ + stream_write(s, SOURCE_DESCRIPTOR, lengthSourceDescriptor); /* sourceDescriptor */ + /* numberCapabilities (2 bytes) */ + stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ + /* capabilitySets */ +} + void rdp_read_deactivate_all(STREAM* s, rdpSettings* settings) { printf("Deactivate All PDU\n"); diff --git a/libfreerdp-core/capabilities.h b/libfreerdp-core/capabilities.h index 55741d2ba..74faca573 100644 --- a/libfreerdp-core/capabilities.h +++ b/libfreerdp-core/capabilities.h @@ -52,11 +52,18 @@ #define CAPSET_TYPE_LARGE_POINTER 0x001B #define CAPSET_TYPE_SURFACE_COMMANDS 0x001C #define CAPSET_TYPE_BITMAP_CODECS 0x001D +#define CAPSET_TYPE_FRAME_ACKNOWLEDGE 0x001E #define CAPSET_HEADER_LENGTH 4 +#define SOURCE_DESCRIPTOR "MSTSC" + +/* Capabilities Protocol Version */ +#define CAPS_PROTOCOL_VERSION 0x0200 + /* General Capability Flags */ #define FASTPATH_OUTPUT_SUPPORTED 0x0001 +#define NO_BITMAP_COMPRESSION_HDR 0x0400 #define LONG_CREDENTIALS_SUPPORTED 0x0004 #define AUTORECONNECT_SUPPORTED 0x0008 #define ENC_SALTED_CHECKSUM 0x0010 @@ -74,7 +81,7 @@ #define ORDER_FLAGS_EXTRA_SUPPORT 0x0080 /* Extended Order Flags */ -#define CACHE_BITMAP_REV3_SUPPORT 0x0002 +#define CACHE_BITMAP_V3_SUPPORT 0x0002 #define ALTSEC_FRAME_MARKER_SUPPORT 0x0004 /* Order Support */ @@ -171,6 +178,8 @@ #define SURFCMDS_STREAM_SURFACE_BITS 0x00000040 void rdp_read_demand_active(STREAM* s, rdpSettings* settings); +void rdp_write_confirm_active(STREAM* s, rdpSettings* settings); + void rdp_read_deactivate_all(STREAM* s, rdpSettings* settings); #endif /* __CAPABILITIES_H */ diff --git a/libfreerdp-core/settings.c b/libfreerdp-core/settings.c index 6bbf05877..76a63aa8c 100644 --- a/libfreerdp-core/settings.c +++ b/libfreerdp-core/settings.c @@ -77,6 +77,18 @@ rdpSettings* settings_new() settings->order_support[NEG_INDEX_INDEX] = True; settings->color_pointer = True; + settings->large_pointer = True; + + settings->draw_gdi_plus = True; + + settings->frame_marker = False; + settings->bitmap_cache_v3 = False; + + settings->offscreen_bitmap_cache_size = 7680; + settings->offscreen_bitmap_cache_entries = 100; + + settings->draw_nine_grid_cache_size = 2560; + settings->draw_nine_grid_cache_entries = 256; settings->client_dir = xmalloc(strlen(client_dll)); strcpy(settings->client_dir, client_dll);