Hi, today I’ll brief you about some common mistakes when reading the TS_ICON_INFO structure. This structure is defined in section 126.96.36.199.3 of [MS-RDPERP].
I’ve been working on a case lately that (I can tell the sin but not the sinner) will be a good example for this post.
It happens that the Icons that were shown on the taskbar after successfully creating a RAIL session were both “upside down” AND “with wrong coloring”.
These effects together with “truncated icons” are usually related to either or all of these 3 situations:
1) CbColorTable and ColorTable are expected but the Bpp is not 1, 4 nor 8.
2) The RGB being used is 565 instead of 555.
3) The data from the bitmap is being read upside down.
CbColorTable and ColorTable are expected but the Bpp is not 1, 4 nor 8.
[MS-RDPERP] 188.8.131.52.3 Icon Info (TS_ICON_INFO) defines the following structure:
CacheEntry (2 bytes): An unsigned 16-bit integer. The index within an icon cache at which this icon MUST be stored at the client. The index is unique within a given CacheId (see following description). The maximum value of CacheEntry is negotiated between server and client through the NumIconCacheEntries field of the Window List Capability Set during the connection establishment phase.
CacheId (1 byte): An unsigned 8-bit integer. The index of the icon cache at which this icon MUST be stored at the client. If the value is 0xFFFF, the icon SHOULD NOT be cached. The CacheId is unique within a remote session.
The maximum value of CacheId is negotiated between server and client through the NumIconCaches field of the Window List Capability Set while establishing the connection.
Bpp (1 byte): An unsigned 8-bit integer. The color depth of the icon. Valid values are as follows:
Width (2 bytes): An unsigned 16-bit integer. The width, in pixels, of the icon.
Height (2 bytes): An unsigned 16-bit integer. The height, in pixels, of the icon.
CbColorTable (2 bytes): An unsigned 16-bit integer. The size, in bytes, of the color table data. This field is ONLY present if the bits per pixel (Bpp) value is 1, 4, or 8.
CbBitsMask (2 bytes): An unsigned 16-bit integer. The size, in bytes, of the icon's one-bit color-depth mask image.
CbBitsColor (2 bytes): An unsigned 16-bit integer. The size, in bytes, of the icon's color image.
BitsMask (variable): The image data for the 1-bpp bitmap. The length, in bytes, of this field is equal to the value of CbBitsMask. This field is optional.
ColorTable (variable): The image data for the color bitmap. The length, in bytes, of this field is equal to the value of CbColorTable. This field is only present if the Bpp value is 1, 4, or 8.
BitsColor (variable): The image data for the icon's color image. The length, in bytes, of this field is equal to the value of CbBitsColor. This field is optional.
As you can see in the highlighted information, CbColorTable’s 2 bytes are only present if the Bpp is equals to 1, 4 or 8. With higher color depths, these two properties are not present in the structure.
If assumed present, then the CbBitsMask 2 bytes are read as the ColorTable size, the CbBitsColor 2 bytes are read as the BitsMask size and the first 2 bytes of the BitsMask are read as the BitsColor size.
You can probably imagine that after this skewed data is read, the tables will be interpreted with the wrong data thus garbage like icons will appear. It may resemble the icon to some extent, but it will certainly not be it.
The RGB being used is 565 instead of 555
When using 16 Bpp, it is very important to make sure that we use RGB555 and not RGB565.
Microsoft BITAMAPINFOHEADER structure (http://msdn.microsoft.com/en-us/library/dd183376(v=VS.85).aspx ) defines this very clearly:
“The value for blue is in the least significant five bits, followed by five bits each for green and red. The most significant bit is not used”
Using the wrong scheme will, of course, result on the wrong coloring of the icon since RGB565 uses six bits for the green component.
The data from the bitmap is being read upside down
This is usually an easy to recognize error.
Whenever your icon is looking upside down, you can be almost certain that you are reading the structure top to bottom instead of bottom to top or vice-versa.
When reading a BITMAPINFO (http://msdn.microsoft.com/en-us/library/dd183375(v=VS.85).aspx) structure, it is necessary to rely on the value of the “height” property to be able to figure out if the bitmap should be read in one direction or another. This is the excerpt:
“A DIB consists of two distinct parts: a BITMAPINFO structure describing the dimensions and colors of the bitmap, and an array of bytes defining the pixels of the bitmap. The bits in the array are packed together, but each scan line must be padded with zeroes to end on a LONG data-type boundary. If the height of the bitmap is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If the height is negative, the bitmap is a top-down DIB and its origin is the upper left corner. “
I hope to have helped you prevent these mistakes or at least I have provided you with an explanation of why you have found these issues when reading the bitmaps.
I wish you the best of the reads!