CVS: seamlessrdp/ServerExe/HookDll hookdll.c, 1.37, 1.38
Pierre Ossman <[email protected]> Mon, 18 Jun 2007 04:59:40 -0700
| Newsgroups | gmane.network.rdesktop.cvs |
|---|---|
| Message-ID | <[email protected]> |
--===============1074164875==
Update of /cvsroot/rdesktop/seamlessrdp/ServerExe/HookDll
In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv29416/ServerExe/HookDll
Modified Files:
hookdll.c
Log Message:
Add support for transferring window icons.
Index: hookdll.c
===================================================================
RCS file: /cvsroot/rdesktop/seamlessrdp/ServerExe/HookDll/hookdll.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -C2 -d -r1.37 -r1.38
*** hookdll.c 28 Apr 2006 07:56:57 -0000 1.37
--- hookdll.c 18 Jun 2007 11:59:38 -0000 1.38
***************
*** 5,10 ****
Based on code copyright (C) 2004-2005 Martin Wickett
! Copyright (C) Peter Åstrand <[email protected]> 2005-2006
! Copyright (C) Pierre Ossman <[email protected]> 2006
This program is free software; you can redistribute it and/or modify
--- 5,10 ----
Based on code copyright (C) 2004-2005 Martin Wickett
! Copyright 2005-2006 Peter Åstrand <[email protected]> for Cendio AB
! Copyright 2006-2007 Pierre Ossman <[email protected]> for Cendio AB
This program is free software; you can redistribute it and/or modify
***************
*** 23,26 ****
--- 23,27 ----
*/
+ #include <assert.h>
#include <stdio.h>
#include <stdarg.h>
***************
*** 182,185 ****
--- 183,352 ----
}
+ static HICON
+ get_icon(HWND hwnd, int large)
+ {
+ HICON icon;
+
+ if (!SendMessageTimeout(hwnd, WM_GETICON, large ? ICON_BIG : ICON_SMALL,
+ 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
+ return NULL;
+
+ if (icon)
+ return icon;
+
+ /*
+ * Modern versions of Windows uses the voodoo value of 2 instead of 0
+ * for the small icons.
+ */
+ if (!large)
+ {
+ if (!SendMessageTimeout(hwnd, WM_GETICON, 2,
+ 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
+ return NULL;
+ }
+
+ if (icon)
+ return icon;
+
+ icon = (HICON) GetClassLong(hwnd, large ? GCL_HICON : GCL_HICONSM);
+
+ if (icon)
+ return icon;
+
+ return NULL;
+ }
+
+ static int
+ extract_icon(HICON icon, char *buffer, int maxlen)
+ {
+ ICONINFO info;
+ HDC hdc;
+ BITMAP mask_bmp, color_bmp;
+ BITMAPINFO bmi;
+ int size, i;
+ char *mask_buf, *color_buf;
+ char *o, *m, *c;
+ int ret = -1;
+
+ assert(buffer);
+ assert(maxlen > 0);
+
+ if (!GetIconInfo(icon, &info))
+ goto fail;
+
+ if (!GetObject(info.hbmMask, sizeof(BITMAP), &mask_bmp))
+ goto free_bmps;
+ if (!GetObject(info.hbmColor, sizeof(BITMAP), &color_bmp))
+ goto free_bmps;
+
+ if (mask_bmp.bmWidth != color_bmp.bmWidth)
+ goto free_bmps;
+ if (mask_bmp.bmHeight != color_bmp.bmHeight)
+ goto free_bmps;
+
+ if ((mask_bmp.bmWidth * mask_bmp.bmHeight * 4) > maxlen)
+ goto free_bmps;
+
+ size = (mask_bmp.bmWidth + 3) / 4 * 4;
+ size *= mask_bmp.bmHeight;
+ size *= 4;
+
+ mask_buf = malloc(size);
+ if (!mask_buf)
+ goto free_bmps;
+ color_buf = malloc(size);
+ if (!color_buf)
+ goto free_mbuf;
+
+ memset(&bmi, 0, sizeof(BITMAPINFO));
+
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
+ bmi.bmiHeader.biWidth = mask_bmp.bmWidth;
+ bmi.bmiHeader.biHeight = -mask_bmp.bmHeight;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = size;
+
+ hdc = CreateCompatibleDC(NULL);
+ if (!hdc)
+ goto free_cbuf;
+
+ if (!GetDIBits(hdc, info.hbmMask, 0, mask_bmp.bmHeight, mask_buf, &bmi, DIB_RGB_COLORS))
+ goto del_dc;
+ if (!GetDIBits(hdc, info.hbmColor, 0, color_bmp.bmHeight, color_buf, &bmi, DIB_RGB_COLORS))
+ goto del_dc;
+
+ o = buffer;
+ m = mask_buf;
+ c = color_buf;
+ for (i = 0; i < size / 4; i++)
+ {
+ o[0] = c[2];
+ o[1] = c[1];
+ o[2] = c[0];
+
+ o[3] = ((int) (unsigned char) m[0] + (unsigned char) m[1] +
+ (unsigned char) m[2]) / 3;
+ o[3] = 0xff - o[3];
+
+ o += 4;
+ m += 4;
+ c += 4;
+ }
+
+ ret = size;
+
+ del_dc:
+ DeleteDC(hdc);
+
+ free_cbuf:
+ free(color_buf);
+ free_mbuf:
+ free(mask_buf);
+
+ free_bmps:
+ DeleteObject(info.hbmMask);
+ DeleteObject(info.hbmColor);
+
+ fail:
+ return ret;
+ }
+
+ #define ICON_CHUNK 400
+
+ static void
+ update_icon(HWND hwnd, HICON icon, int large)
+ {
+ int i, j, size, chunks;
+ char buf[32 * 32 * 4];
+ char asciibuf[ICON_CHUNK * 2 + 1];
+
+ size = extract_icon(icon, buf, sizeof(buf));
+ if (size <= 0)
+ return;
+
+ if ((!large && size != 16 * 16 * 4) || (large && size != 32 * 32 * 4))
+ {
+ debug("Unexpected icon size.");
+ return;
+ }
+
+ chunks = (size + ICON_CHUNK - 1) / ICON_CHUNK;
+ for (i = 0; i < chunks; i++)
+ {
+ for (j = 0; j < ICON_CHUNK; j++)
+ {
+ if (i * ICON_CHUNK + j >= size)
+ break;
+ sprintf(asciibuf + j * 2, "%02x",
+ (int) (unsigned char) buf[i * ICON_CHUNK + j]);
+ }
+
+ vchannel_write("SETICON", "0x%08lx,%d,RGBA,%d,%d,%s", hwnd, i,
+ large ? 32 : 16, large ? 32 : 16, asciibuf);
+ }
+ }
+
static LRESULT CALLBACK
wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
***************
*** 221,224 ****
--- 388,392 ----
DWORD pid;
int flags;
+ HICON icon;
GetWindowThreadProcessId(hwnd, &pid);
***************
*** 237,240 ****
--- 405,422 ----
vchannel_strfilter_unicode(title), 0);
+ icon = get_icon(hwnd, 1);
+ if (icon)
+ {
+ update_icon(hwnd, icon, 1);
+ DeleteObject(icon);
+ }
+
+ icon = get_icon(hwnd, 0);
+ if (icon)
+ {
+ update_icon(hwnd, icon, 0);
+ DeleteObject(icon);
+ }
+
if (style & WS_MAXIMIZE)
state = 2;
***************
*** 262,265 ****
--- 444,474 ----
}
+ case WM_SETICON:
+ if (!(style & WS_VISIBLE))
+ break;
+
+ switch (wparam)
+ {
+ case ICON_BIG:
+ if (lparam)
+ update_icon(hwnd, (HICON) lparam, 1);
+ else
+ vchannel_write("DELICON", "0x%08lx,RGBA,32,32",
+ hwnd);
+ break;
+ case ICON_SMALL:
+ case 2:
+ if (lparam)
+ update_icon(hwnd, (HICON) lparam, 0);
+ else
+ vchannel_write("DELICON", "0x%08lx,RGBA,16,16",
+ hwnd);
+ break;
+ default:
+ debug("Weird icon size %d", (int) wparam);
+ }
+
+ break;
+
case WM_SIZE:
if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
***************
*** 344,347 ****
--- 553,573 ----
}
+ case WM_SETICON:
+ {
+ HICON icon;
+
+ /*
+ * Somehow, we never get WM_SETICON for the small icon.
+ * So trigger a read of it every time the large one is
+ * changed.
+ */
+ icon = get_icon(hwnd, 0);
+ if (icon)
+ {
+ update_icon(hwnd, icon, 0);
+ DeleteObject(icon);
+ }
+ }
+
default:
break;
--===============1074164875==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
--===============1074164875==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
rdesktop-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rdesktop-cvs
--===============1074164875==--