mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 17:16:04 +00:00
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:
parent
9cb66d7953
commit
aabf06072b
7 changed files with 2217 additions and 995 deletions
File diff suppressed because it is too large
Load diff
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -303,6 +303,7 @@ struct rdpclient
|
|||
SOCKET sock;
|
||||
struct stream in;
|
||||
struct stream out;
|
||||
long connection_timeout;
|
||||
}
|
||||
tcp;
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue