modified porting-tools/rdesktop-core-tester/activex.cpp

modified   porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp
    And from the chrysalis out came... the caterpillar. MissTosca stops just short of being demonstrable. I'll keep working on it, but the Google Summer of Code is, for all intent and purposes, over. The matter is in the hands of my judges now. Wish me luck

modified   rdesktop/iso.c
modified   rdesktop/proto.h
modified   rdesktop/rdesktop.h
modified   rdesktop/rdp.c
    Very minor fixes

modified   rdesktop/tcp.c
    Use asynchronous I/O and alertable waits to allow aborting the protocol thread ASAP

svn path=/trunk/; revision=23627
This commit is contained in:
Michele Cicciotti 2006-08-20 21:02:10 +00:00
parent 9cb66d7953
commit aabf06072b
7 changed files with 2217 additions and 995 deletions

View file

@ -5,16 +5,6 @@
#include "rdesktop/rdesktop.h"
#include "rdesktop/proto.h"
template<class T, class U> T aligndown(const T& X, const U& align)
{
return X & ~(T(align) - 1);
}
template<class T, class U> T alignup(const T& X, const U& align)
{
return aligndown(X + (align - 1), align);
}
extern "C"
{
/* ==== BEGIN POOP ==== */
@ -199,897 +189,6 @@ extern "C"
HDC hdcBuffer;
UINT wmZMouseWheel;
static
HBITMAP
win32_create_dib(LONG width, LONG height, WORD bitcount, const BYTE * data)
{
struct b_
{
BITMAPINFO bmi;
RGBQUAD colormap[256 - ARRAYSIZE(RTL_FIELD_TYPE(BITMAPINFO, bmiColors))];
}
b;
b.bmi.bmiHeader.biSize = sizeof(b.bmi.bmiHeader);
b.bmi.bmiHeader.biWidth = width;
b.bmi.bmiHeader.biHeight = height;
b.bmi.bmiHeader.biPlanes = 1;
b.bmi.bmiHeader.biBitCount = bitcount;
b.bmi.bmiHeader.biCompression = BI_RGB;
b.bmi.bmiHeader.biSizeImage = 0;
b.bmi.bmiHeader.biXPelsPerMeter = 0;
b.bmi.bmiHeader.biYPelsPerMeter = 0;
if(bitcount > 8)
{
b.bmi.bmiHeader.biClrUsed = 0;
b.bmi.bmiHeader.biClrImportant = 0;
}
else
{
b.bmi.bmiHeader.biClrUsed = 2 << bitcount;
b.bmi.bmiHeader.biClrImportant = 2 << bitcount;
// TODO: palette
}
HBITMAP hbm = CreateDIBitmap(hdcBuffer, &b.bmi.bmiHeader, CBM_INIT, data, &b.bmi, DIB_RGB_COLORS);
if(hbm == NULL)
error("CreateDIBitmap %dx%dx%d failed\n", width, height, bitcount);
return hbm;
}
static
uint8 *
win32_convert_scanlines(int width, int height, int bitcount, int fromalign, int toalign, const uint8 * data, uint8 ** buffer)
{
// TBD: profile & optimize the most common cases
assert(width > 0);
assert(height);
assert(bitcount && bitcount <= 32);
assert(fromalign <= toalign);
assert(data);
assert(buffer);
bool flipped = height < 0;
if(flipped)
height = - height;
int bytesperrow = alignup(width * bitcount, 8) / 8;
int fromstride = alignup(bytesperrow, fromalign);
int tostride = alignup(bytesperrow, toalign);
assert(fromstride <= tostride);
int datasize = tostride * height;
uint8 * dibits = new(malloc(datasize)) uint8;
if(dibits == NULL)
return NULL;
const uint8 * src = data;
uint8 * dest = dibits;
const int pad = tostride - fromstride;
assert(pad < 4);
__assume(pad < 4);
if(flipped)
{
dest += (height - 1) * tostride;
tostride = - tostride;
}
for(int i = 0; i < height; ++ i)
{
memcpy(dest, src, fromstride);
memset(dest + fromstride, 0, pad);
src += fromstride;
dest += tostride;
}
*buffer = dibits;
return dibits;
}
void
ui_resize_window(RDPCLIENT * This)
{
// EVENT: OnRemoteDesktopSizeChange
// TODO: resize buffer
SetWindowPos(hwnd, NULL, 0, 0, This->width, This->height, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE);
}
int
ui_select(RDPCLIENT * This, SOCKET rdp_socket)
{
return 1; // TODO: return 0 for user quit. Or just kill this silly function
}
void
ui_move_pointer(RDPCLIENT * This, int x, int y)
{
POINT point;
point.x = x;
point.y = y;
ClientToScreen(hwnd, &point);
SetCursorPos(point.x, point.y);
}
HCURSOR hcursor;
HBITMAP
ui_create_bitmap(RDPCLIENT * This, int width, int height, uint8 * data)
{
return win32_create_dib(width, height, This->server_depth, data);
}
void
ui_destroy_bitmap(RDPCLIENT * This, HBITMAP bmp)
{
DeleteObject(bmp);
}
HGLYPH
ui_create_glyph(RDPCLIENT * This, int width, int height, const uint8 * data)
{
uint8 * databuf = NULL;
uint8 * databits = win32_convert_scanlines(width, height, 1, 1, 2, data, &databuf);
if(databits == NULL)
return NULL;
HBITMAP hbm = CreateBitmap(width, height, 1, 1, databits);
if(databuf)
free(databuf);
const uint8 * p = data;
int stride = alignup(alignup(width, 8) / 8, 1);
printf("glyph %p\n", hbm);
for(int i = 0; i < height; ++ i, p += stride)
{
for(int j = 0; j < width; ++ j)
{
int B = p[j / 8];
int b = 8 - j % 8 - 1;
if(B & (1 << b))
fputs("##", stdout);
else
fputs("..", stdout);
}
fputc('\n', stdout);
}
fputc('\n', stdout);
return hbm;
}
void
ui_destroy_glyph(RDPCLIENT * This, HGLYPH glyph)
{
DeleteObject(glyph);
}
HCURSOR
ui_create_cursor(RDPCLIENT * This, unsigned int x, unsigned int y, int width, int height,
uint8 * andmask, uint8 * xormask)
{
uint8 * andbuf = NULL;
uint8 * xorbuf = NULL;
uint8 * andbits = win32_convert_scanlines(width, - height, 1, 2, 4, andmask, &andbuf);
if(andbits == NULL)
return NULL;
uint8 * xorbits = win32_convert_scanlines(width, height, 24, 2, 4, xormask, &xorbuf);
if(xorbits == NULL)
{
free(andbits);
return NULL;
}
HBITMAP hbmMask = CreateBitmap(width, height, 1, 1, andbits);
HBITMAP hbmColor = win32_create_dib(width, height, 24, xorbits);
ICONINFO iconinfo;
iconinfo.fIcon = FALSE;
iconinfo.xHotspot = x;
iconinfo.yHotspot = y;
iconinfo.hbmMask = hbmMask;
iconinfo.hbmColor = hbmColor;
HICON icon = CreateIconIndirect(&iconinfo);
if(icon == NULL)
error("CreateIconIndirect %dx%d failed\n", width, height);
if(andbuf)
free(andbuf);
if(xorbuf)
free(xorbuf);
DeleteObject(hbmMask);
DeleteObject(hbmColor);
return icon;
}
void
ui_set_cursor(RDPCLIENT * This, HCURSOR cursor)
{
hcursor = cursor;
}
void
ui_destroy_cursor(RDPCLIENT * This, HCURSOR cursor)
{
DestroyIcon(cursor);
}
void
ui_set_null_cursor(RDPCLIENT * This)
{
hcursor = NULL;
}
HCOLOURMAP
ui_create_colourmap(RDPCLIENT * This, COLOURMAP * colours)
{
// TODO
// TODO: kill HCOLOURMAP/COLOURMAP, use HPALETTE/LOGPALETTE
return 0;
}
void
ui_destroy_colourmap(RDPCLIENT * This, HCOLOURMAP map)
{
// TODO: see above
}
void
ui_set_colourmap(RDPCLIENT * This, HCOLOURMAP map)
{
// TODO
}
RECT rcClip; // TODO: initialize
void
ui_set_clip(RDPCLIENT * This, int x, int y, int cx, int cy)
{
rcClip.left = x;
rcClip.top = y;
rcClip.right = x + cx + 1;
rcClip.bottom = y + cy + 1;
HRGN hrgn = CreateRectRgnIndirect(&rcClip);
SelectClipRgn(hdcBuffer, hrgn);
DeleteObject(hrgn);
}
void
ui_reset_clip(RDPCLIENT * This)
{
rcClip.left = 0;
rcClip.top = 0;
rcClip.right = This->width + 1;
rcClip.bottom = This->height + 1;
SelectClipRgn(hdcBuffer, NULL);
}
void
ui_bell(RDPCLIENT * This)
{
MessageBeep(MB_OK); // TODO? use Beep() on remote sessions?
}
static
void
win32_repaint_rect(RDPCLIENT * This, const RECT * lprc)
{
RECT rcDamage;
IntersectRect(&rcDamage, lprc, &rcClip);
#if 0
HDC hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(NULL_PEN));
SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
Rectangle(hdc, rcDamage.left, rcDamage.top, rcDamage.right + 1, rcDamage.bottom + 1);
ReleaseDC(hwnd, hdc);
Sleep(200);
#endif
InvalidateRect(hwnd, &rcDamage, FALSE);
}
static
void
win32_repaint_area(RDPCLIENT * This, int x, int y, int cx, int cy)
{
RECT rcDamage;
rcDamage.left = x;
rcDamage.top = y;
rcDamage.right = x + cx;
rcDamage.bottom = y + cy;
win32_repaint_rect(This, &rcDamage);
}
static
void
win32_repaint_poly(RDPCLIENT * This, POINT * point, int npoints, int linewidth)
{
RECT rcDamage;
rcDamage.left = MAXLONG;
rcDamage.top = MAXLONG;
rcDamage.right = 0;
rcDamage.bottom = 0;
for(int i = 0; i < npoints; ++ i)
{
if(point[i].x < rcDamage.left)
rcDamage.left = point[i].x;
if(point[i].y < rcDamage.top)
rcDamage.top = point[i].y;
if(point[i].x > rcDamage.right)
rcDamage.right = point[i].x;
if(point[i].y > rcDamage.bottom)
rcDamage.bottom = point[i].y;
}
InflateRect(&rcDamage, linewidth, linewidth);
win32_repaint_rect(This, &rcDamage);
}
static
void
win32_repaint_whole(RDPCLIENT * This)
{
InvalidateRgn(hwnd, NULL, FALSE);
}
static
HBRUSH
win32_create_brush(RDPCLIENT * This, BRUSH * brush, COLORREF fgcolour)
{
if(brush == NULL)
return (HBRUSH)GetStockObject(NULL_BRUSH);
switch(brush->style)
{
case BS_SOLID:
case BS_NULL:
case BS_HATCHED:
case BS_PATTERN:
case BS_PATTERN8X8:
break;
default:
return NULL;
}
switch(brush->style)
{
case BS_SOLID:
return CreateSolidBrush(fgcolour);
case BS_HATCHED:
return CreateHatchBrush(brush->pattern[0], fgcolour);
case BS_NULL:
return (HBRUSH)GetStockObject(NULL_BRUSH);
case BS_PATTERN:
case BS_PATTERN8X8:
{
uint16 pattern[8];
for(size_t i = 0; i < 8; ++ i)
pattern[i] = brush->pattern[i];
HBITMAP hpattern = CreateBitmap(8, 8, 1, 1, pattern);
HBRUSH hbr = CreatePatternBrush(hpattern);
DeleteObject(hpattern);
return hbr;
}
DEFAULT_UNREACHABLE;
}
}
void
ui_paint_bitmap(RDPCLIENT * This, int x, int y, int cx, int cy, int width, int height, uint8 * data)
{
assert(This->server_depth >= 8);
assert(rcClip.left == 0 && rcClip.top == 0 && rcClip.right == This->width + 1 && rcClip.bottom == This->height + 1);
GdiFlush();
// TBD: we can cache these values
int Bpp = alignup(This->server_depth, 8) / 8;
int tostride = alignup(This->width * Bpp, 4);
int fromstride = alignup(width * Bpp, 4);
int sizex = cx * Bpp;
const uint8 * src = data;
uint8 * dst = (uint8 *)pBuffer + (This->height - y - cy) * tostride + x * Bpp;
for(int i = 0; i < cy; ++ i)
{
memcpy(dst, src, sizex);
src += fromstride;
dst += tostride;
}
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_destblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy)
{
int dcsave = SaveDC(hdcBuffer);
SelectObject(hdcBuffer, GetStockObject(BLACK_BRUSH));
PatBlt(hdcBuffer, x, y, cx, cy, MAKELONG(0, opcode));
RestoreDC(hdcBuffer, dcsave);
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_patblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
HBRUSH hbr = win32_create_brush(This, brush, fgcolour);
int dcsave = SaveDC(hdcBuffer);
SetBkColor(hdcBuffer, bgcolour);
SetTextColor(hdcBuffer, fgcolour);
SetBrushOrgEx(hdcBuffer, brush->xorigin, brush->yorigin, NULL);
SelectObject(hdcBuffer, hbr);
PatBlt(hdcBuffer, x, y, cx, cy, MAKELONG(0, opcode));
RestoreDC(hdcBuffer, dcsave);
DeleteObject(hbr);
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_screenblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* src */ int srcx, int srcy)
{
BitBlt(hdcBuffer, x, y, cx, cy, hdcBuffer, srcx, srcy, MAKELONG(0, opcode));
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_memblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* src */ HBITMAP src, int srcx, int srcy)
{
HDC hdcSrc = CreateCompatibleDC(hdcBuffer);
HGDIOBJ hOld = SelectObject(hdcSrc, src);
BitBlt(hdcBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode));
SelectObject(hdcSrc, hOld);
DeleteDC(hdcSrc);
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_triblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* src */ HBITMAP src, int srcx, int srcy,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
// TODO
HDC hdcSrc = CreateCompatibleDC(hdcBuffer);
HGDIOBJ hOld = SelectObject(hdcSrc, src);
//SELECT_BRUSH(brush, bgcolour, fgcolour);
BitBlt(hdcBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode));
//RESET_BRUSH();
SelectObject(hdcSrc, hOld);
DeleteDC(hdcSrc);
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_line(RDPCLIENT * This, uint8 opcode,
/* dest */ int startx, int starty, int endx, int endy,
/* pen */ PEN * pen)
{
HPEN hpen = CreatePen(pen->style, pen->width, pen->colour);
int dcsave = SaveDC(hdcBuffer);
SetROP2(hdcBuffer, opcode);
SelectObject(hdcBuffer, hpen);
MoveToEx(hdcBuffer, startx, starty, NULL);
LineTo(hdcBuffer, endx, endy);
RestoreDC(hdcBuffer, dcsave);
DeleteObject(hpen);
RECT rcDamage;
if(startx < endx)
{
rcDamage.left = startx;
rcDamage.right = endx;
}
else
{
rcDamage.left = endx;
rcDamage.right = startx;
}
if(starty < endy)
{
rcDamage.top = starty;
rcDamage.bottom = endy;
}
else
{
rcDamage.top = endy;
rcDamage.bottom = starty;
}
InflateRect(&rcDamage, pen->width, pen->width);
win32_repaint_rect(This, &rcDamage);
}
void
ui_rect(RDPCLIENT * This,
/* dest */ int x, int y, int cx, int cy,
/* brush */ int colour)
{
HBRUSH hbr = CreateSolidBrush(colour);
int dcsave = SaveDC(hdcBuffer);
SelectObject(hdcBuffer, hbr);
SelectObject(hdcBuffer, GetStockObject(NULL_PEN));
Rectangle(hdcBuffer, x, y, x + cx + 1, y + cy + 1);
RestoreDC(hdcBuffer, dcsave);
DeleteObject(hbr);
win32_repaint_area(This, x, y, cx, cy);
}
void
ui_polygon(RDPCLIENT * This, uint8 opcode,
/* mode */ uint8 fillmode,
/* dest */ POINT * point, int npoints,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
HBRUSH hbr = win32_create_brush(This, brush, fgcolour);
int dcsave = SaveDC(hdcBuffer);
SetBkColor(hdcBuffer, bgcolour);
SetTextColor(hdcBuffer, fgcolour);
SetPolyFillMode(hdcBuffer, fillmode);
SelectObject(hdcBuffer, hbr);
Polygon(hdcBuffer, point, npoints);
RestoreDC(hdcBuffer, dcsave);
win32_repaint_poly(This, point, npoints, 0);
}
void
ui_polyline(RDPCLIENT * This, uint8 opcode,
/* dest */ POINT * points, int npoints,
/* pen */ PEN * pen)
{
POINT last = points[0];
for(int i = 1; i < npoints; ++ i)
{
points[i].x += last.x;
points[i].y += last.y;
last = points[i];
}
HPEN hpen = CreatePen(pen->style, pen->width, pen->colour);
int dcsave = SaveDC(hdcBuffer);
SetROP2(hdcBuffer, opcode);
SelectObject(hdcBuffer, hpen);
Polyline(hdcBuffer, points, npoints);
RestoreDC(hdcBuffer, dcsave);
DeleteObject(hpen);
win32_repaint_poly(This, points, npoints, pen->width);
}
void
ui_ellipse(RDPCLIENT * This, uint8 opcode,
/* mode */ uint8 fillmode,
/* dest */ int x, int y, int cx, int cy,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
// TODO
win32_repaint_area(This, x, y, cx, cy);
}
// TBD: optimize text drawing
void
ui_draw_glyph(RDPCLIENT * This, int mixmode,
/* dest */ int x, int y, int cx, int cy,
/* src */ HGLYPH glyph, int srcx, int srcy,
int bgcolour, int fgcolour)
{
HBITMAP hbmGlyph = (HBITMAP)glyph;
HDC hdcGlyph = CreateCompatibleDC(hdcBuffer);
HGDIOBJ hOld = SelectObject(hdcGlyph, hbmGlyph);
int dcsave = SaveDC(hdcBuffer);
switch(mixmode)
{
case MIX_TRANSPARENT:
{
/*
ROP is DSPDxax:
- where the glyph (S) is white, D is set to the foreground color (P)
- where the glyph (S) is black, D is left untouched
This paints a transparent glyph in the specified color
*/
HBRUSH hbr = CreateSolidBrush(fgcolour);
SelectObject(hdcBuffer, hbr);
BitBlt(hdcBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, MAKELONG(0, 0xe2));
DeleteObject(hbr);
}
break;
case MIX_OPAQUE:
{
/* Curiously, glyphs are inverted (white-on-black) */
SetBkColor(hdcBuffer, fgcolour);
SetTextColor(hdcBuffer, bgcolour);
BitBlt(hdcBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, SRCCOPY);
}
break;
}
RestoreDC(hdcBuffer, dcsave);
SelectObject(hdcGlyph, hOld);
DeleteDC(hdcGlyph);
win32_repaint_area(This, x, y, cx, cy);
}
// TBD: a clean-up would be nice, too...
#define DO_GLYPH(ttext,idx) \
{\
glyph = cache_get_font (This, font, ttext[idx]);\
if (!(flags & TEXT2_IMPLICIT_X))\
{\
xyoffset = ttext[++idx];\
if ((xyoffset & 0x80))\
{\
if (flags & TEXT2_VERTICAL)\
y += ttext[idx+1] | (ttext[idx+2] << 8);\
else\
x += ttext[idx+1] | (ttext[idx+2] << 8);\
idx += 2;\
}\
else\
{\
if (flags & TEXT2_VERTICAL)\
y += xyoffset;\
else\
x += xyoffset;\
}\
}\
if (glyph != NULL)\
{\
ui_draw_glyph (This, mixmode, x + (short) glyph->offset,\
y + (short) glyph->baseline,\
glyph->width, glyph->height,\
glyph->pixmap, 0, 0, bgcolour, fgcolour);\
if (flags & TEXT2_IMPLICIT_X)\
x += glyph->width;\
}\
}
void
ui_draw_text(RDPCLIENT * This, uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
int clipx, int clipy, int clipcx, int clipcy,
int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
int bgcolour, int fgcolour, uint8 * text, uint8 length)
{
FONTGLYPH * glyph;
int i, j, xyoffset;
DATABLOB *entry;
HBRUSH hbr = CreateSolidBrush(bgcolour);
HGDIOBJ holdbrush = SelectObject(hdcBuffer, hbr);
HGDIOBJ holdpen = SelectObject(hdcBuffer, GetStockObject(NULL_PEN));
if (boxcx > 1)
Rectangle(hdcBuffer, boxx, boxy, boxx + boxcx + 1, boxy + boxcy + 1);
else if (mixmode == MIX_OPAQUE)
Rectangle(hdcBuffer, clipx, clipy, clipx + clipcx + 1, clipy + clipcy + 1);
SelectObject(hdcBuffer, holdpen);
SelectObject(hdcBuffer, holdbrush);
DeleteObject(hbr);
if(boxcx > 1)
win32_repaint_area(This, boxx, boxy, boxcx, boxcy);
else
win32_repaint_area(This, clipx, clipy, clipcx, clipcy);
/* Paint text, character by character */
for (i = 0; i < length;)
{
switch (text[i])
{
case 0xff:
/* At least two bytes needs to follow */
if (i + 3 > length)
{
warning("Skipping short 0xff command:");
for (j = 0; j < length; j++)
fprintf(stderr, "%02x ", text[j]);
fprintf(stderr, "\n");
i = length = 0;
break;
}
cache_put_text(This, text[i + 1], text, text[i + 2]);
i += 3;
length -= i;
/* this will move pointer from start to first character after FF command */
text = &(text[i]);
i = 0;
break;
case 0xfe:
/* At least one byte needs to follow */
if (i + 2 > length)
{
warning("Skipping short 0xfe command:");
for (j = 0; j < length; j++)
fprintf(stderr, "%02x ", text[j]);
fprintf(stderr, "\n");
i = length = 0;
break;
}
entry = cache_get_text(This, text[i + 1]);
if (entry->data != NULL)
{
if ((((uint8 *) (entry->data))[1] == 0)
&& (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
{
if (flags & TEXT2_VERTICAL)
y += text[i + 2];
else
x += text[i + 2];
}
for (j = 0; j < entry->size; j++)
DO_GLYPH(((uint8 *) (entry->data)), j);
}
if (i + 2 < length)
i += 3;
else
i += 2;
length -= i;
/* this will move pointer from start to first character after FE command */
text = &(text[i]);
i = 0;
break;
default:
DO_GLYPH(text, i);
i++;
break;
}
}
}
void
ui_desktop_save(RDPCLIENT * This, uint32 offset, int x, int y, int cx, int cy)
{
GdiFlush();
int Bpp = alignup(This->server_depth, 8) / 8;
int stride = alignup(This->width * Bpp, 4);
uint8 * data = (uint8 *)pBuffer + x * Bpp + (This->height - y - cy) * stride;
cache_put_desktop(This, offset * Bpp, cx, cy, stride, Bpp, data);
}
void
ui_desktop_restore(RDPCLIENT * This, uint32 offset, int x, int y, int cx, int cy)
{
// TBD: we can cache these values
int Bpp = alignup(This->server_depth, 8) / 8;
int tostride = alignup(This->width * Bpp, 4);
int fromstride = cx * Bpp;
const uint8 * src = cache_get_desktop(This, offset, cx, cy, Bpp);
uint8 * dst = (uint8 *)pBuffer + x * Bpp + (This->height - y - cy) * tostride;
GdiFlush();
for(int i = 0; i < cy; ++ i)
{
memcpy(dst, src, fromstride);
src += fromstride;
dst += tostride;
}
win32_repaint_area(This, x, y, cx, cy);
}
int nSavedDC;
void
ui_begin_update(RDPCLIENT * This)
{
nSavedDC = SaveDC(hdcBuffer);
}
void
ui_end_update(RDPCLIENT * This)
{
RestoreDC(hdcBuffer, nSavedDC);
}
int event_pubkey(RDPCLIENT * This, const unsigned char * key, size_t key_size)
{
return True;
}
void event_logon(RDPCLIENT * This)
{
}
};
static
@ -1193,7 +292,7 @@ mstsc_WndProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam)
case WM_SETCURSOR:
if(LOWORD(lparam) == HTCLIENT)
{
SetCursor(hcursor);
//SetCursor(hcursor);
return TRUE;
}
@ -1291,10 +390,12 @@ mstsc_ProtocolIOThread
SelectObject(hdcBuffer, hbmBuffer);
#if 0
rcClip.left = 0;
rcClip.top = 0;
rcClip.right = This->width + 1;
rcClip.bottom = This->height + 1;
#endif
BOOL deactivated;
uint32 ext_disc_reason;
@ -1507,7 +608,7 @@ int wmain()
This->rdp.current_status = 1;
hcursor = NULL;
//hcursor = NULL;
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));

View file

@ -228,9 +228,7 @@ iso_reconnect(RDPCLIENT * This, char *server, char *cookie)
BOOL
iso_disconnect(RDPCLIENT * This)
{
if(!iso_send_msg(This, ISO_PDU_DR))
return False;
iso_send_msg(This, ISO_PDU_DR);
return tcp_disconnect(This);
}

View file

@ -310,8 +310,9 @@ unsigned int seamless_send_zchange(RDPCLIENT * This, unsigned long id, unsigned
unsigned int seamless_send_focus(RDPCLIENT * This, unsigned long id, unsigned long flags);
/* events */
int event_pubkey(RDPCLIENT * This, const unsigned char * key, size_t key_size);
BOOL event_pubkey(RDPCLIENT * This, unsigned char * key, unsigned int key_size);
void event_logon(RDPCLIENT * This);
BOOL event_redirect(RDPCLIENT * This, uint32 flags, uint32 server_len, wchar_t * server, uint32 cookie_len, char * cookie, uint32 username_len, wchar_t * username, uint32 domain_len, wchar_t * domain, uint32 password_len, wchar_t * password);
/* *INDENT-OFF* */
#ifdef __cplusplus

View file

@ -303,6 +303,7 @@ struct rdpclient
SOCKET sock;
struct stream in;
struct stream out;
long connection_timeout;
}
tcp;
};

View file

@ -1340,50 +1340,81 @@ process_data_pdu(RDPCLIENT * This, STREAM s, uint32 * ext_disc_reason)
static BOOL
process_redirect_pdu(RDPCLIENT * This, STREAM s /*, uint32 * ext_disc_reason */ )
{
uint32 len;
uint32 flags;
// FIXME!!! allocate the strings used here
uint32 server_len;
wchar_t * server;
uint32 cookie_len;
char * cookie;
uint32 username_len;
wchar_t * username;
uint32 domain_len;
wchar_t * domain;
uint32 password_len;
wchar_t * password;
/* these 2 bytes are unknown, seem to be zeros */
in_uint8s(s, 2);
/* read connection flags */
in_uint32_le(s, This->redirect_flags);
in_uint32_le(s, flags);
/* read length of ip string */
in_uint32_le(s, len);
in_uint32_le(s, server_len);
/* read ip string */
rdp_in_unistr(This, s, This->redirect_server, len);
server = (wchar_t *)s->p;
in_uint8s(s, server_len);
/* read length of cookie string */
in_uint32_le(s, len);
in_uint32_le(s, cookie_len);
/* read cookie string (plain ASCII) */
in_uint8a(s, This->redirect_cookie, len);
This->redirect_cookie[len] = 0;
cookie = (char *)s->p;
in_uint8s(s, cookie_len);
/* read length of username string */
in_uint32_le(s, len);
in_uint32_le(s, username_len);
/* read username string */
rdp_in_unistr(This, s, This->redirect_username, len);
username = (wchar_t *)s->p;
in_uint8s(s, username_len);
/* read length of domain string */
in_uint32_le(s, len);
in_uint32_le(s, domain_len);
/* read domain string */
rdp_in_unistr(This, s, This->redirect_domain, len);
domain = (wchar_t *)s->p;
in_uint8s(s, domain_len);
/* read length of password string */
in_uint32_le(s, len);
in_uint32_le(s, password_len);
/* read password string */
rdp_in_unistr(This, s, This->redirect_password, len);
password = (wchar_t *)s->p;
in_uint8s(s, password_len);
This->redirect = True;
return True;
return event_redirect
(
This,
flags,
server_len,
server,
cookie_len,
cookie,
username_len,
username,
domain_len,
domain,
password_len,
password
);
}
/* Process incoming packets */

View file

@ -68,18 +68,37 @@ BOOL
tcp_send(RDPCLIENT * This, STREAM s)
{
int length = (int)(s->end - s->data);
int sent, total = 0;
int total = 0;
DWORD sent;
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
while (total < length)
{
sent = send(This->tcp.sock, s->data + total, length - total, 0);
if (sent <= 0)
WriteFile((HANDLE)This->tcp.sock, s->data + total, length - total, NULL, &overlapped);
switch(WaitForSingleObjectEx((HANDLE)This->tcp.sock, INFINITE, TRUE))
{
// error("send: %s\n", strerror(errno)); // EOF
/* Success */
case WAIT_OBJECT_0:
break;
/* Timeout or error */
case WAIT_TIMEOUT:
default:
This->disconnect_reason = 772;
return False;
/* Aborted, must disconnect ASAP */
case WAIT_IO_COMPLETION:
CancelIo((HANDLE)This->tcp.sock);
break;
}
/* Wait for completion. We could hang here, but we shouldn't */
if(!GetOverlappedResult((HANDLE)This->tcp.sock, &overlapped, &sent, TRUE))
return False;
total += sent;
}
@ -91,7 +110,7 @@ STREAM
tcp_recv(RDPCLIENT * This, STREAM s, uint32 length)
{
unsigned int new_length, end_offset, p_offset;
int rcvd = 0;
DWORD rcvd = 0;
if (s == NULL)
{
@ -137,18 +156,37 @@ tcp_recv(RDPCLIENT * This, STREAM s, uint32 length)
while (length > 0)
{
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
if (!ui_select(This, This->tcp.sock))
/* User quit */
return NULL;
rcvd = recv(This->tcp.sock, s->end, length, 0);
if (rcvd < 0)
ReadFile((HANDLE)This->tcp.sock, s->end, length, NULL, &overlapped);
switch(WaitForSingleObjectEx((HANDLE)This->tcp.sock, INFINITE, TRUE))
{
// error("recv: %s\n", strerror(errno)); // EOF
/* Success */
case WAIT_OBJECT_0:
break;
/* Timeout or error */
case WAIT_TIMEOUT:
default:
This->disconnect_reason = 1028;
return NULL;
/* Aborted, must disconnect ASAP */
case WAIT_IO_COMPLETION:
CancelIo((HANDLE)This->tcp.sock);
break;
}
else if (rcvd == 0)
/* Wait for completion. We could hang here, but we shouldn't */
if(!GetOverlappedResult((HANDLE)This->tcp.sock, &overlapped, &rcvd, TRUE))
return False;
if (rcvd == 0)
{
error("Connection closed\n");
This->disconnect_reason = 2308;
@ -233,6 +271,8 @@ tcp_connect(RDPCLIENT * This, char *server)
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(This->tcp_port_rdp);
// TODO: apply connection timeout here
if (connect(This->tcp.sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
{
// error("connect: %s\n", strerror(errno)); // EOF