channels/rdpgfx: fix parsing of pdus in an array

This commit is contained in:
Marc-André Moreau 2014-06-04 21:35:31 -04:00
parent eda172c894
commit f194a7b156
5 changed files with 84 additions and 79 deletions

View File

@ -139,11 +139,6 @@ int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16)
return 1;
}
void rdpgfx_copy_rect16(RDPGFX_RECT16* dst, RDPGFX_RECT16* src)
{
CopyMemory(dst, src, sizeof(RDPGFX_RECT16));
}
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
{
Stream_Read_UINT8(s, color32->B); /* B (1 byte) */

View File

@ -36,7 +36,6 @@ int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16);
void rdpgfx_copy_rect16(RDPGFX_RECT16* dst, RDPGFX_RECT16* src);
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);

View File

@ -63,7 +63,7 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
header.flags = 0;
header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
pdu.capsSetCount = 2;
pdu.capsSetCount = 1;
pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
capsSet = &capsSets[0];
@ -172,6 +172,7 @@ int rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_
int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
int pad;
UINT32 index;
MONITOR_DEF* monitor;
RDPGFX_RESET_GRAPHICS_PDU pdu;
@ -197,7 +198,8 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s
Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */
}
/* pad (total size is 340 bytes) */
pad = 340 - (RDPGFX_HEADER_SIZE + 12 + (pdu.monitorCount * 20));
Stream_Seek(s, pad); /* pad (total size is 340 bytes) */
fprintf(stderr, "RdpGfxRecvResetGraphicsPdu: width: %d height: %d count: %d\n",
pdu.width, pdu.height, pdu.monitorCount);
@ -367,6 +369,7 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream
Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */
pdu.bitmapData = Stream_Pointer(s);
Stream_Seek(s, pdu.bitmapDataLength);
fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X "
"destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d\n",
@ -376,19 +379,22 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream
cmd.surfaceId = pdu.surfaceId;
cmd.codecId = pdu.codecId;
cmd.codecContextId = 0;
cmd.pixelFormat = pdu.pixelFormat;
rdpgfx_copy_rect16(&(cmd.destRect), &(pdu.destRect));
cmd.bitmapDataLength = pdu.bitmapDataLength;
cmd.bitmapData = pdu.bitmapData;
cmd.contextId = 0;
cmd.format = pdu.pixelFormat;
cmd.left = pdu.destRect.left;
cmd.top = pdu.destRect.top;
cmd.right = pdu.destRect.right;
cmd.bottom = pdu.destRect.bottom;
cmd.width = cmd.right - cmd.left + 1;
cmd.height = cmd.bottom - cmd.top + 1;
cmd.length = pdu.bitmapDataLength;
cmd.data = pdu.bitmapData;
if (context && context->SurfaceCommand)
{
context->SurfaceCommand(context, &cmd);
}
rdpgfx_decode(gfx, &cmd);
return 1;
}
@ -407,6 +413,7 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream
Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */
pdu.bitmapData = Stream_Pointer(s);
Stream_Seek(s, pdu.bitmapDataLength);
fprintf(stderr, "RdpGfxRecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X "
"codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d\n",
@ -414,19 +421,22 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream
cmd.surfaceId = pdu.surfaceId;
cmd.codecId = pdu.codecId;
cmd.codecContextId = pdu.codecContextId;
cmd.pixelFormat = pdu.pixelFormat;
ZeroMemory(&(cmd.destRect), sizeof(RDPGFX_RECT16));
cmd.bitmapDataLength = pdu.bitmapDataLength;
cmd.bitmapData = pdu.bitmapData;
cmd.contextId = pdu.codecContextId;
cmd.format = pdu.pixelFormat;
cmd.left = 0;
cmd.top = 0;
cmd.right = 0;
cmd.bottom = 0;
cmd.width = 0;
cmd.height = 0;
cmd.length = pdu.bitmapDataLength;
cmd.data = pdu.bitmapData;
if (context && context->SurfaceCommand)
{
context->SurfaceCommand(context, &cmd);
}
rdpgfx_decode(gfx, &cmd);
return 1;
}
@ -632,8 +642,11 @@ int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt
int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
int status;
int beg, end;
RDPGFX_HEADER header;
beg = Stream_GetPosition(s);
rdpgfx_read_header(s, &header);
#if 1
@ -716,7 +729,19 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
break;
}
return 0;
end = Stream_GetPosition(s);
if (end != (beg + header.pduLength))
{
fprintf(stderr, "Unexpected pdu end: Actual: %d, Expected: %d\n",
end, (beg + header.pduLength));
exit(0);
Stream_SetPosition(s, (beg + header.pduLength));
}
return status;
}
static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
@ -740,7 +765,10 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
s = Stream_New(pDstData, DstSize);
status = rdpgfx_recv_pdu(callback, s);
while (Stream_GetPosition(s) < Stream_Length(s))
{
status = rdpgfx_recv_pdu(callback, s);
}
Stream_Free(s, TRUE);

View File

@ -67,46 +67,32 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
BYTE* data;
UINT32 width;
UINT32 height;
XImage* image;
RDPGFX_RECT16* destRect;
destRect = &(cmd->destRect);
width = destRect->right - destRect->left + 1;
height = destRect->bottom - destRect->top + 1;
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
/* Validate that the data received is large enough */
if ((width * height * 4) <= cmd->bitmapDataLength)
data = (BYTE*) malloc(cmd->width * cmd->height * 4);
freerdp_image_flip(cmd->data, data, cmd->width, cmd->height, 32);
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, cmd->width, cmd->height, 32, 0);
XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0,
cmd->left, cmd->top, cmd->width, cmd->height);
XFree(image);
free(data);
if (!xfc->remote_app)
{
data = (BYTE*) malloc(width * height * 4);
freerdp_image_flip(cmd->bitmapData, data, width, height, 32);
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, width, height, 32, 0);
XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0,
destRect->left, destRect->top, width, height);
XFree(image);
free(data);
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
destRect->left, destRect->top, width, height, destRect->left, destRect->top);
}
//xf_gdi_surface_update_frame(xfc, destRect->left, destRect->top, width, height);
XSetClipMask(xfc->display, xfc->gc, None);
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
cmd->left, cmd->top, cmd->width, cmd->height, cmd->left, cmd->top);
}
XSetClipMask(xfc->display, xfc->gc, None);
return 1;
}
@ -115,11 +101,8 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
int i, tx, ty;
XImage* image;
RFX_MESSAGE* message;
RDPGFX_RECT16* destRect;
destRect = &(cmd->destRect);
message = rfx_process_message(xfc->rfx, cmd->bitmapData, cmd->bitmapDataLength);
message = rfx_process_message(xfc->rfx, cmd->data, cmd->length);
if (!message)
return -1;
@ -127,18 +110,16 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetClipRectangles(xfc->display, xfc->gc,
destRect->left, destRect->top,
XSetClipRectangles(xfc->display, xfc->gc, cmd->left, cmd->top,
(XRectangle*) message->rects, message->numRects, YXBanded);
/* Draw the tiles to primary surface, each is 64x64. */
for (i = 0; i < message->numTiles; i++)
{
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) message->tiles[i]->data, 64, 64, 32, 0);
tx = message->tiles[i]->x + destRect->left;
ty = message->tiles[i]->y + destRect->top;
tx = message->tiles[i]->x + cmd->left;
ty = message->tiles[i]->y + cmd->top;
XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, tx, ty, 64, 64);
XFree(image);
@ -147,12 +128,13 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
/* Copy the updated region from backstore to the window. */
for (i = 0; i < message->numRects; i++)
{
tx = message->rects[i].x + destRect->left;
ty = message->rects[i].y + destRect->top;
tx = message->rects[i].x + cmd->left;
ty = message->rects[i].y + cmd->top;
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, tx, ty, message->rects[i].width, message->rects[i].height, tx, ty);
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, tx, ty,
message->rects[i].width, message->rects[i].height, tx, ty);
}
}
@ -167,8 +149,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
int status = 1;
xfContext* xfc = (xfContext*) context->custom;
printf("xf_SurfaceCommand: context: %p xfc: %p cmd: %p\n", context, xfc, cmd);
switch (cmd->codecId)
{
case RDPGFX_CODECID_UNCOMPRESSED:

View File

@ -165,17 +165,20 @@ struct _RDPGFX_WIRE_TO_SURFACE_PDU_2
};
typedef struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 RDPGFX_WIRE_TO_SURFACE_PDU_2;
/* RDPGFX_SURFACE_COMMAND encapsulates both RDPGFX_WIRE_TO_SURFACE_PDU 1/2 */
struct _RDPGFX_SURFACE_COMMAND
{
UINT16 surfaceId;
UINT16 codecId;
UINT32 codecContextId;
RDPGFX_PIXELFORMAT pixelFormat;
RDPGFX_RECT16 destRect;
UINT32 bitmapDataLength;
BYTE* bitmapData;
UINT32 surfaceId;
UINT32 codecId;
UINT32 contextId;
UINT32 format;
UINT32 left;
UINT32 top;
UINT32 right;
UINT32 bottom;
UINT32 width;
UINT32 height;
UINT32 length;
BYTE* data;
};
typedef struct _RDPGFX_SURFACE_COMMAND RDPGFX_SURFACE_COMMAND;