/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1439 - (hide annotations)
Thu Mar 6 15:11:53 2008 UTC (16 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 17998 byte(s)
Yet another try at get_parent. The previous implementation incorrectly
returned -1 for many transient windows, which made them transient for
the root window rather than the application window at the X11 side.

With this implementation, the transient test case in
seamlessrdp-channel.txt passes.

1 ossman_ 1071 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Seamless windows - Remote server hook DLL
4 ossman_ 1069
5 ossman_ 1071 Based on code copyright (C) 2004-2005 Martin Wickett
6    
7 astrand 1437 Copyright 2005-2008 Peter Åstrand <astrand@cendio.se> for Cendio AB
8     Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 ossman_ 1071
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14    
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     GNU General Public License for more details.
19    
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23     */
24    
25 ossman_ 1412 #include <assert.h>
26 ossman_ 1069 #include <stdio.h>
27     #include <stdarg.h>
28    
29 ossman_ 1071 #include <windows.h>
30     #include <winuser.h>
31 ossman_ 1069
32 ossman_ 1073 #include "../vchannel.h"
33 ossman_ 1071
34 ossman_ 1069 #define DLL_EXPORT __declspec(dllexport)
35    
36 ossman_ 1145 #ifdef __GNUC__
37     #define SHARED __attribute__((section ("SHAREDDATA"), shared))
38     #else
39     #define SHARED
40     #endif
41    
42 ossman_ 1069 // Shared DATA
43     #pragma data_seg ( "SHAREDDATA" )
44    
45     // this is the total number of processes this dll is currently attached to
46 ossman_ 1145 int g_instance_count SHARED = 0;
47 ossman_ 1069
48 ossman_ 1145 // blocks for locally generated events
49 ossman_ 1161 HWND g_block_move_hwnd SHARED = NULL;
50 ossman_ 1165 unsigned int g_block_move_serial SHARED = 0;
51 ossman_ 1145 RECT g_block_move SHARED = { 0, 0, 0, 0 };
52 ossman_ 1165
53     unsigned int g_blocked_zchange_serial SHARED = 0;
54 ossman_ 1158 HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
55 ossman_ 1165
56     unsigned int g_blocked_focus_serial SHARED = 0;
57 ossman_ 1158 HWND g_blocked_focus SHARED = NULL;
58 ossman_ 1165
59     unsigned int g_blocked_state_serial SHARED = 0;
60 ossman_ 1161 HWND g_blocked_state_hwnd SHARED = NULL;
61 ossman_ 1160 int g_blocked_state SHARED = -1;
62 ossman_ 1145
63 ossman_ 1069 #pragma data_seg ()
64    
65     #pragma comment(linker, "/section:SHAREDDATA,rws")
66    
67 ossman_ 1153 #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
68     static UINT g_wm_seamless_focus;
69    
70 ossman_ 1071 static HHOOK g_cbt_hook = NULL;
71     static HHOOK g_wndproc_hook = NULL;
72 ossman_ 1134 static HHOOK g_wndprocret_hook = NULL;
73 ossman_ 1069
74 ossman_ 1071 static HINSTANCE g_instance = NULL;
75 ossman_ 1069
76 ossman_ 1071 static HANDLE g_mutex = NULL;
77 ossman_ 1069
78 astrand 1437 static BOOL is_toplevel(HWND hwnd)
79     {
80     BOOL toplevel;
81     HWND parent;
82     parent = GetAncestor(hwnd, GA_PARENT);
83    
84     /* According to MS: "A window that has no parent, or whose
85     parent is the desktop window, is called a top-level
86     window." See http://msdn2.microsoft.com/en-us/library/ms632597(VS.85).aspx. */
87     toplevel = (!parent || parent == GetDesktopWindow());
88     return toplevel;
89     }
90    
91     /* Determine the "parent" field for the CREATE response. */
92     static HWND
93     get_parent(HWND hwnd)
94     {
95     HWND result;
96     HWND owner;
97     LONG exstyle;
98    
99     /* Use the same logic to determine if the window should be
100     "transient" (ie have no task icon) as MS uses. This is documented at
101     http://msdn2.microsoft.com/en-us/library/bb776822.aspx */
102     owner = GetWindow(hwnd, GW_OWNER);
103     exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
104 astrand 1439 if (!owner && !(exstyle & WS_EX_TOOLWINDOW))
105     {
106 astrand 1437 /* display taskbar icon */
107 astrand 1439 result = NULL;
108     }
109     else
110     {
111 astrand 1437 /* no taskbar icon */
112 astrand 1439 if (owner)
113     result = owner;
114     else
115     result = (HWND) - 1;
116 astrand 1437 }
117    
118     return result;
119     }
120    
121 ossman_ 1081 static void
122     update_position(HWND hwnd)
123     {
124 ossman_ 1145 RECT rect, blocked;
125 ossman_ 1161 HWND blocked_hwnd;
126 ossman_ 1165 unsigned int serial;
127 ossman_ 1081
128 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
129 ossman_ 1165 blocked_hwnd = g_block_move_hwnd;
130     serial = g_block_move_serial;
131 ossman_ 1145 memcpy(&blocked, &g_block_move, sizeof(RECT));
132     ReleaseMutex(g_mutex);
133    
134 ossman_ 1167 vchannel_block();
135    
136     if (!GetWindowRect(hwnd, &rect))
137     {
138     debug("GetWindowRect failed!\n");
139     goto end;
140     }
141    
142 ossman_ 1161 if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
143 ossman_ 1145 && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
144 ossman_ 1167 goto end;
145    
146 ossman_ 1186 vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
147 ossman_ 1167 hwnd,
148     rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
149    
150     end:
151     vchannel_unblock();
152 ossman_ 1081 }
153    
154 ossman_ 1162 static void
155     update_zorder(HWND hwnd)
156     {
157     HWND behind;
158     HWND block_hwnd, block_behind;
159 ossman_ 1165 unsigned int serial;
160 ossman_ 1162
161     WaitForSingleObject(g_mutex, INFINITE);
162 ossman_ 1165 serial = g_blocked_zchange_serial;
163 ossman_ 1162 block_hwnd = g_blocked_zchange[0];
164     block_behind = g_blocked_zchange[1];
165     ReleaseMutex(g_mutex);
166    
167 ossman_ 1167 vchannel_block();
168    
169 ossman_ 1162 behind = GetNextWindow(hwnd, GW_HWNDPREV);
170     while (behind)
171     {
172     LONG style;
173    
174     style = GetWindowLong(behind, GWL_STYLE);
175    
176     if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
177     break;
178    
179     behind = GetNextWindow(behind, GW_HWNDPREV);
180     }
181    
182     if ((hwnd == block_hwnd) && (behind == block_behind))
183 ossman_ 1165 vchannel_write("ACK", "%u", serial);
184     else
185 ossman_ 1186 vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, 0);
186 ossman_ 1167
187     vchannel_unblock();
188 ossman_ 1162 }
189    
190 ossman_ 1412 static HICON
191     get_icon(HWND hwnd, int large)
192     {
193     HICON icon;
194    
195     if (!SendMessageTimeout(hwnd, WM_GETICON, large ? ICON_BIG : ICON_SMALL,
196     0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
197     return NULL;
198    
199     if (icon)
200     return icon;
201    
202     /*
203     * Modern versions of Windows uses the voodoo value of 2 instead of 0
204     * for the small icons.
205     */
206     if (!large)
207     {
208     if (!SendMessageTimeout(hwnd, WM_GETICON, 2,
209     0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
210     return NULL;
211     }
212    
213     if (icon)
214     return icon;
215    
216     icon = (HICON) GetClassLong(hwnd, large ? GCL_HICON : GCL_HICONSM);
217    
218     if (icon)
219     return icon;
220    
221     return NULL;
222     }
223    
224     static int
225     extract_icon(HICON icon, char *buffer, int maxlen)
226     {
227     ICONINFO info;
228     HDC hdc;
229     BITMAP mask_bmp, color_bmp;
230     BITMAPINFO bmi;
231     int size, i;
232     char *mask_buf, *color_buf;
233     char *o, *m, *c;
234     int ret = -1;
235    
236     assert(buffer);
237     assert(maxlen > 0);
238    
239     if (!GetIconInfo(icon, &info))
240     goto fail;
241    
242     if (!GetObject(info.hbmMask, sizeof(BITMAP), &mask_bmp))
243     goto free_bmps;
244     if (!GetObject(info.hbmColor, sizeof(BITMAP), &color_bmp))
245     goto free_bmps;
246    
247     if (mask_bmp.bmWidth != color_bmp.bmWidth)
248     goto free_bmps;
249     if (mask_bmp.bmHeight != color_bmp.bmHeight)
250     goto free_bmps;
251    
252     if ((mask_bmp.bmWidth * mask_bmp.bmHeight * 4) > maxlen)
253     goto free_bmps;
254    
255     size = (mask_bmp.bmWidth + 3) / 4 * 4;
256     size *= mask_bmp.bmHeight;
257     size *= 4;
258    
259     mask_buf = malloc(size);
260     if (!mask_buf)
261     goto free_bmps;
262     color_buf = malloc(size);
263     if (!color_buf)
264     goto free_mbuf;
265    
266     memset(&bmi, 0, sizeof(BITMAPINFO));
267    
268     bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
269     bmi.bmiHeader.biWidth = mask_bmp.bmWidth;
270     bmi.bmiHeader.biHeight = -mask_bmp.bmHeight;
271     bmi.bmiHeader.biPlanes = 1;
272     bmi.bmiHeader.biBitCount = 32;
273     bmi.bmiHeader.biCompression = BI_RGB;
274     bmi.bmiHeader.biSizeImage = size;
275    
276     hdc = CreateCompatibleDC(NULL);
277     if (!hdc)
278     goto free_cbuf;
279    
280     if (!GetDIBits(hdc, info.hbmMask, 0, mask_bmp.bmHeight, mask_buf, &bmi, DIB_RGB_COLORS))
281     goto del_dc;
282     if (!GetDIBits(hdc, info.hbmColor, 0, color_bmp.bmHeight, color_buf, &bmi, DIB_RGB_COLORS))
283     goto del_dc;
284    
285     o = buffer;
286     m = mask_buf;
287     c = color_buf;
288     for (i = 0; i < size / 4; i++)
289     {
290     o[0] = c[2];
291     o[1] = c[1];
292     o[2] = c[0];
293    
294     o[3] = ((int) (unsigned char) m[0] + (unsigned char) m[1] +
295     (unsigned char) m[2]) / 3;
296     o[3] = 0xff - o[3];
297    
298     o += 4;
299     m += 4;
300     c += 4;
301     }
302    
303     ret = size;
304    
305     del_dc:
306     DeleteDC(hdc);
307    
308     free_cbuf:
309     free(color_buf);
310     free_mbuf:
311     free(mask_buf);
312    
313     free_bmps:
314     DeleteObject(info.hbmMask);
315     DeleteObject(info.hbmColor);
316    
317     fail:
318     return ret;
319     }
320    
321     #define ICON_CHUNK 400
322    
323     static void
324     update_icon(HWND hwnd, HICON icon, int large)
325     {
326     int i, j, size, chunks;
327     char buf[32 * 32 * 4];
328     char asciibuf[ICON_CHUNK * 2 + 1];
329    
330     size = extract_icon(icon, buf, sizeof(buf));
331     if (size <= 0)
332     return;
333    
334     if ((!large && size != 16 * 16 * 4) || (large && size != 32 * 32 * 4))
335     {
336     debug("Unexpected icon size.");
337     return;
338     }
339    
340     chunks = (size + ICON_CHUNK - 1) / ICON_CHUNK;
341     for (i = 0; i < chunks; i++)
342     {
343     for (j = 0; j < ICON_CHUNK; j++)
344     {
345     if (i * ICON_CHUNK + j >= size)
346     break;
347     sprintf(asciibuf + j * 2, "%02x",
348     (int) (unsigned char) buf[i * ICON_CHUNK + j]);
349     }
350    
351     vchannel_write("SETICON", "0x%08lx,%d,RGBA,%d,%d,%s", hwnd, i,
352     large ? 32 : 16, large ? 32 : 16, asciibuf);
353     }
354     }
355    
356 ossman_ 1071 static LRESULT CALLBACK
357     wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
358 ossman_ 1069 {
359 astrand 1437 HWND hwnd;
360 ossman_ 1079 UINT msg;
361     WPARAM wparam;
362     LPARAM lparam;
363 ossman_ 1069
364 ossman_ 1079 LONG style;
365 ossman_ 1069
366 ossman_ 1071 if (code < 0)
367     goto end;
368 ossman_ 1069
369 ossman_ 1079 hwnd = ((CWPSTRUCT *) details)->hwnd;
370     msg = ((CWPSTRUCT *) details)->message;
371     wparam = ((CWPSTRUCT *) details)->wParam;
372     lparam = ((CWPSTRUCT *) details)->lParam;
373    
374     style = GetWindowLong(hwnd, GWL_STYLE);
375    
376 astrand 1437 if (!is_toplevel(hwnd)) {
377 ossman_ 1079 goto end;
378 astrand 1437 }
379 ossman_ 1079
380 ossman_ 1071 switch (msg)
381     {
382     case WM_WINDOWPOSCHANGED:
383 ossman_ 1079 {
384     WINDOWPOS *wp = (WINDOWPOS *) lparam;
385 ossman_ 1069
386 ossman_ 1079 if (wp->flags & SWP_SHOWWINDOW)
387     {
388 ossman_ 1134 unsigned short title[150];
389 ossman_ 1099 int state;
390 ossman_ 1177 DWORD pid;
391     int flags;
392 ossman_ 1412 HICON icon;
393 ossman_ 1099
394 ossman_ 1177 GetWindowThreadProcessId(hwnd, &pid);
395 ossman_ 1069
396 ossman_ 1177 flags = 0;
397     if (style & DS_MODALFRAME)
398     flags |= SEAMLESS_CREATE_MODAL;
399    
400     vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
401 astrand 1437 (long) hwnd, (long) pid, (long) get_parent(hwnd),
402 ossman_ 1177 flags);
403    
404 ossman_ 1134 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
405 ossman_ 1069
406 ossman_ 1186 vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
407 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
408 ossman_ 1099
409 ossman_ 1412 icon = get_icon(hwnd, 1);
410     if (icon)
411     {
412     update_icon(hwnd, icon, 1);
413     DeleteObject(icon);
414     }
415    
416     icon = get_icon(hwnd, 0);
417     if (icon)
418     {
419     update_icon(hwnd, icon, 0);
420     DeleteObject(icon);
421     }
422    
423 ossman_ 1099 if (style & WS_MAXIMIZE)
424     state = 2;
425     else if (style & WS_MINIMIZE)
426     state = 1;
427     else
428     state = 0;
429    
430 ossman_ 1081 update_position(hwnd);
431 ossman_ 1099
432 ossman_ 1186 vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
433     state, 0);
434 ossman_ 1079 }
435 ossman_ 1069
436 ossman_ 1079 if (wp->flags & SWP_HIDEWINDOW)
437 ossman_ 1186 vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
438 ossman_ 1079
439 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
440 ossman_ 1079 break;
441    
442 ossman_ 1080 if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
443 ossman_ 1081 update_position(hwnd);
444 ossman_ 1079
445 ossman_ 1071 break;
446 ossman_ 1079 }
447 ossman_ 1069
448 ossman_ 1412 case WM_SETICON:
449     if (!(style & WS_VISIBLE))
450     break;
451    
452     switch (wparam)
453     {
454     case ICON_BIG:
455     if (lparam)
456     update_icon(hwnd, (HICON) lparam, 1);
457     else
458     vchannel_write("DELICON", "0x%08lx,RGBA,32,32",
459     hwnd);
460     break;
461     case ICON_SMALL:
462     case 2:
463     if (lparam)
464     update_icon(hwnd, (HICON) lparam, 0);
465     else
466     vchannel_write("DELICON", "0x%08lx,RGBA,16,16",
467     hwnd);
468     break;
469     default:
470     debug("Weird icon size %d", (int) wparam);
471     }
472    
473     break;
474    
475 ossman_ 1081 case WM_SIZE:
476 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
477 ossman_ 1083 break;
478 ossman_ 1081 update_position(hwnd);
479     break;
480    
481     case WM_MOVE:
482 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
483 ossman_ 1083 break;
484 ossman_ 1081 update_position(hwnd);
485     break;
486    
487 ossman_ 1134 case WM_DESTROY:
488     if (!(style & WS_VISIBLE))
489     break;
490 ossman_ 1186 vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
491 ossman_ 1134 break;
492    
493     default:
494     break;
495     }
496    
497     end:
498     return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
499     }
500    
501     static LRESULT CALLBACK
502     wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
503     {
504 astrand 1437 HWND hwnd;
505 ossman_ 1134 UINT msg;
506     WPARAM wparam;
507     LPARAM lparam;
508    
509     LONG style;
510    
511     if (code < 0)
512     goto end;
513    
514     hwnd = ((CWPRETSTRUCT *) details)->hwnd;
515     msg = ((CWPRETSTRUCT *) details)->message;
516     wparam = ((CWPRETSTRUCT *) details)->wParam;
517     lparam = ((CWPRETSTRUCT *) details)->lParam;
518    
519     style = GetWindowLong(hwnd, GWL_STYLE);
520    
521 astrand 1437 if (!is_toplevel(hwnd)) {
522 ossman_ 1134 goto end;
523 astrand 1437 }
524 ossman_ 1134
525     switch (msg)
526     {
527 ossman_ 1162 case WM_WINDOWPOSCHANGED:
528     {
529     WINDOWPOS *wp = (WINDOWPOS *) lparam;
530    
531     if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
532     break;
533    
534     if (!(wp->flags & SWP_NOZORDER))
535     update_zorder(hwnd);
536    
537     break;
538     }
539    
540    
541 ossman_ 1102 case WM_SETTEXT:
542 ossman_ 1113 {
543 ossman_ 1134 unsigned short title[150];
544 ossman_ 1113 if (!(style & WS_VISIBLE))
545     break;
546 ossman_ 1134 /* We cannot use the string in lparam because
547     we need unicode. */
548     GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
549 ossman_ 1186 vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
550 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
551 ossman_ 1102 break;
552 ossman_ 1113 }
553 ossman_ 1102
554 ossman_ 1412 case WM_SETICON:
555     {
556     HICON icon;
557    
558     /*
559     * Somehow, we never get WM_SETICON for the small icon.
560     * So trigger a read of it every time the large one is
561     * changed.
562     */
563     icon = get_icon(hwnd, 0);
564     if (icon)
565     {
566     update_icon(hwnd, icon, 0);
567     DeleteObject(icon);
568     }
569     }
570    
571 ossman_ 1071 default:
572     break;
573     }
574    
575 ossman_ 1153 if (msg == g_wm_seamless_focus)
576 ossman_ 1158 {
577 ossman_ 1185 /* FIXME: SetForegroundWindow() kills menus. Need to find a
578     clean way to solve this. */
579 astrand 1437 if ((GetForegroundWindow() != hwnd) && !get_parent(hwnd))
580 ossman_ 1185 SetForegroundWindow(hwnd);
581 ossman_ 1165
582     vchannel_write("ACK", "%u", g_blocked_focus_serial);
583 ossman_ 1158 }
584 ossman_ 1153
585 ossman_ 1071 end:
586 ossman_ 1134 return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
587 ossman_ 1069 }
588    
589 ossman_ 1071 static LRESULT CALLBACK
590     cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
591 ossman_ 1069 {
592 ossman_ 1071 if (code < 0)
593     goto end;
594 ossman_ 1069
595 ossman_ 1071 switch (code)
596     {
597     case HCBT_MINMAX:
598     {
599 ossman_ 1160 int show, state, blocked;
600 ossman_ 1230 HWND hwnd, blocked_hwnd;
601 ossman_ 1165 unsigned int serial;
602 ossman_ 1230 LONG style;
603 ossman_ 1069
604 ossman_ 1160 WaitForSingleObject(g_mutex, INFINITE);
605 ossman_ 1161 blocked_hwnd = g_blocked_state_hwnd;
606 ossman_ 1165 serial = g_blocked_state_serial;
607 ossman_ 1160 blocked = g_blocked_state;
608     ReleaseMutex(g_mutex);
609    
610 ossman_ 1230 hwnd = (HWND) wparam;
611    
612     style = GetWindowLong(hwnd, GWL_STYLE);
613    
614     if (!(style & WS_VISIBLE))
615     break;
616    
617 ossman_ 1071 show = LOWORD(lparam);
618 ossman_ 1069
619 ossman_ 1128 if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
620     || (show == SW_RESTORE))
621 ossman_ 1079 state = 0;
622 ossman_ 1106 else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
623 ossman_ 1079 state = 1;
624 ossman_ 1106 else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
625 ossman_ 1079 state = 2;
626 ossman_ 1100 else
627 ossman_ 1106 {
628     debug("Unexpected show: %d", show);
629 ossman_ 1100 break;
630 ossman_ 1106 }
631 ossman_ 1160
632 ossman_ 1230 if ((blocked_hwnd == hwnd) && (blocked == state))
633 ossman_ 1165 vchannel_write("ACK", "%u", serial);
634     else
635 ossman_ 1186 vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
636 ossman_ 1230 hwnd, state, 0);
637 ossman_ 1160
638 ossman_ 1071 break;
639     }
640 ossman_ 1069
641 ossman_ 1071 default:
642     break;
643     }
644 ossman_ 1069
645 ossman_ 1071 end:
646     return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
647 ossman_ 1069 }
648    
649 ossman_ 1071 DLL_EXPORT void
650     SetHooks(void)
651 ossman_ 1069 {
652 ossman_ 1071 if (!g_cbt_hook)
653     g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
654 ossman_ 1069
655 ossman_ 1071 if (!g_wndproc_hook)
656     g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
657 ossman_ 1134
658     if (!g_wndprocret_hook)
659     g_wndprocret_hook =
660     SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
661 ossman_ 1069 }
662    
663 ossman_ 1071 DLL_EXPORT void
664     RemoveHooks(void)
665 ossman_ 1069 {
666 ossman_ 1071 if (g_cbt_hook)
667     UnhookWindowsHookEx(g_cbt_hook);
668 ossman_ 1069
669 ossman_ 1071 if (g_wndproc_hook)
670     UnhookWindowsHookEx(g_wndproc_hook);
671 ossman_ 1134
672     if (g_wndprocret_hook)
673     UnhookWindowsHookEx(g_wndprocret_hook);
674 ossman_ 1069 }
675    
676 ossman_ 1145 DLL_EXPORT void
677 ossman_ 1165 SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
678 ossman_ 1145 {
679 ossman_ 1165 RECT rect;
680    
681 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
682 ossman_ 1161 g_block_move_hwnd = hwnd;
683 ossman_ 1165 g_block_move_serial = serial;
684 ossman_ 1145 g_block_move.left = x;
685     g_block_move.top = y;
686     g_block_move.right = x + width;
687     g_block_move.bottom = y + height;
688     ReleaseMutex(g_mutex);
689    
690     SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
691    
692 ossman_ 1167 vchannel_write("ACK", "%u", serial);
693    
694     if (!GetWindowRect(hwnd, &rect))
695     debug("GetWindowRect failed!\n");
696     else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
697     || (rect.bottom != y + height))
698     update_position(hwnd);
699    
700 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
701 ossman_ 1161 g_block_move_hwnd = NULL;
702 ossman_ 1145 memset(&g_block_move, 0, sizeof(RECT));
703     ReleaseMutex(g_mutex);
704     }
705    
706 ossman_ 1158 DLL_EXPORT void
707 ossman_ 1165 SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
708 ossman_ 1158 {
709     WaitForSingleObject(g_mutex, INFINITE);
710 ossman_ 1165 g_blocked_zchange_serial = serial;
711 ossman_ 1158 g_blocked_zchange[0] = hwnd;
712     g_blocked_zchange[1] = behind;
713     ReleaseMutex(g_mutex);
714    
715 ossman_ 1162 if (behind == NULL)
716     behind = HWND_TOP;
717    
718 ossman_ 1158 SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
719    
720     WaitForSingleObject(g_mutex, INFINITE);
721     g_blocked_zchange[0] = NULL;
722     g_blocked_zchange[1] = NULL;
723     ReleaseMutex(g_mutex);
724     }
725    
726     DLL_EXPORT void
727 ossman_ 1165 SafeFocus(unsigned int serial, HWND hwnd)
728 ossman_ 1158 {
729     WaitForSingleObject(g_mutex, INFINITE);
730 ossman_ 1165 g_blocked_focus_serial = serial;
731 ossman_ 1158 g_blocked_focus = hwnd;
732     ReleaseMutex(g_mutex);
733    
734     SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
735    
736     WaitForSingleObject(g_mutex, INFINITE);
737     g_blocked_focus = NULL;
738     ReleaseMutex(g_mutex);
739     }
740    
741 ossman_ 1160 DLL_EXPORT void
742 ossman_ 1165 SafeSetState(unsigned int serial, HWND hwnd, int state)
743 ossman_ 1160 {
744 ossman_ 1165 LONG style;
745     int curstate;
746    
747     vchannel_block();
748    
749     style = GetWindowLong(hwnd, GWL_STYLE);
750    
751     if (style & WS_MAXIMIZE)
752     curstate = 2;
753     else if (style & WS_MINIMIZE)
754     curstate = 1;
755     else
756     curstate = 0;
757    
758     if (state == curstate)
759     {
760     vchannel_write("ACK", "%u", serial);
761     vchannel_unblock();
762 ossman_ 1167 return;
763 ossman_ 1165 }
764    
765 ossman_ 1160 WaitForSingleObject(g_mutex, INFINITE);
766 ossman_ 1161 g_blocked_state_hwnd = hwnd;
767 ossman_ 1165 g_blocked_state_serial = serial;
768 ossman_ 1160 g_blocked_state = state;
769     ReleaseMutex(g_mutex);
770    
771 ossman_ 1165 vchannel_unblock();
772    
773 ossman_ 1160 if (state == 0)
774     ShowWindow(hwnd, SW_RESTORE);
775     else if (state == 1)
776     ShowWindow(hwnd, SW_MINIMIZE);
777     else if (state == 2)
778     ShowWindow(hwnd, SW_MAXIMIZE);
779     else
780     debug("Invalid state %d sent.", state);
781    
782     WaitForSingleObject(g_mutex, INFINITE);
783 ossman_ 1161 g_blocked_state_hwnd = NULL;
784 ossman_ 1160 g_blocked_state = -1;
785     ReleaseMutex(g_mutex);
786     }
787    
788 ossman_ 1071 DLL_EXPORT int
789     GetInstanceCount()
790 ossman_ 1069 {
791 ossman_ 1071 return g_instance_count;
792 ossman_ 1069 }
793    
794 ossman_ 1071 BOOL APIENTRY
795     DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
796 ossman_ 1069 {
797 ossman_ 1071 switch (ul_reason_for_call)
798     {
799     case DLL_PROCESS_ATTACH:
800     // remember our instance handle
801     g_instance = hinstDLL;
802 ossman_ 1069
803 ossman_ 1073 g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL");
804 ossman_ 1071 if (!g_mutex)
805     return FALSE;
806 ossman_ 1069
807 ossman_ 1071 WaitForSingleObject(g_mutex, INFINITE);
808     ++g_instance_count;
809     ReleaseMutex(g_mutex);
810 ossman_ 1069
811 ossman_ 1153 g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
812    
813 ossman_ 1071 vchannel_open();
814 ossman_ 1069
815 ossman_ 1071 break;
816 ossman_ 1069
817 ossman_ 1071 case DLL_THREAD_ATTACH:
818     break;
819 ossman_ 1069
820 ossman_ 1071 case DLL_THREAD_DETACH:
821     break;
822 ossman_ 1069
823 ossman_ 1071 case DLL_PROCESS_DETACH:
824 ossman_ 1233 vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0);
825    
826 ossman_ 1071 WaitForSingleObject(g_mutex, INFINITE);
827     --g_instance_count;
828     ReleaseMutex(g_mutex);
829 ossman_ 1069
830 ossman_ 1071 vchannel_close();
831 ossman_ 1069
832 ossman_ 1071 CloseHandle(g_mutex);
833 ossman_ 1069
834 ossman_ 1071 break;
835     }
836 ossman_ 1069
837 ossman_ 1071 return TRUE;
838 ossman_ 1069 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26