/[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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1109 by ossman_, Fri Mar 10 15:12:28 2006 UTC revision 1439 by astrand, Thu Mar 6 15:11:53 2008 UTC
# Line 4  Line 4 
4    
5     Based on code copyright (C) 2004-2005 Martin Wickett     Based on code copyright (C) 2004-2005 Martin Wickett
6    
7     Copyright (C) Peter Åstrand <astrand@cendio.se> 2005-2006     Copyright 2005-2008 Peter Åstrand <astrand@cendio.se> for Cendio AB
8     Copyright (C) Pierre Ossman <ossman@cendio.se> 2006     Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
9    
10     This program is free software; you can redistribute it and/or modify     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     it under the terms of the GNU General Public License as published by
# Line 22  Line 22 
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */  */
24    
25    #include <assert.h>
26  #include <stdio.h>  #include <stdio.h>
27  #include <stdarg.h>  #include <stdarg.h>
28    
# Line 32  Line 33 
33    
34  #define DLL_EXPORT __declspec(dllexport)  #define DLL_EXPORT __declspec(dllexport)
35    
36    #ifdef __GNUC__
37    #define SHARED __attribute__((section ("SHAREDDATA"), shared))
38    #else
39    #define SHARED
40    #endif
41    
42  // Shared DATA  // Shared DATA
43  #pragma data_seg ( "SHAREDDATA" )  #pragma data_seg ( "SHAREDDATA" )
44    
45  // this is the total number of processes this dll is currently attached to  // this is the total number of processes this dll is currently attached to
46  int g_instance_count = 0;  int g_instance_count SHARED = 0;
47    
48    // blocks for locally generated events
49    HWND g_block_move_hwnd SHARED = NULL;
50    unsigned int g_block_move_serial SHARED = 0;
51    RECT g_block_move SHARED = { 0, 0, 0, 0 };
52    
53    unsigned int g_blocked_zchange_serial SHARED = 0;
54    HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
55    
56    unsigned int g_blocked_focus_serial SHARED = 0;
57    HWND g_blocked_focus SHARED = NULL;
58    
59    unsigned int g_blocked_state_serial SHARED = 0;
60    HWND g_blocked_state_hwnd SHARED = NULL;
61    int g_blocked_state SHARED = -1;
62    
63  #pragma data_seg ()  #pragma data_seg ()
64    
65  #pragma comment(linker, "/section:SHAREDDATA,rws")  #pragma comment(linker, "/section:SHAREDDATA,rws")
66    
67    #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
68    static UINT g_wm_seamless_focus;
69    
70  static HHOOK g_cbt_hook = NULL;  static HHOOK g_cbt_hook = NULL;
71  static HHOOK g_wndproc_hook = NULL;  static HHOOK g_wndproc_hook = NULL;
72    static HHOOK g_wndprocret_hook = NULL;
73    
74  static HINSTANCE g_instance = NULL;  static HINSTANCE g_instance = NULL;
75    
76  static HANDLE g_mutex = NULL;  static HANDLE g_mutex = NULL;
77    
78    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            if (!owner && !(exstyle & WS_EX_TOOLWINDOW))
105            {
106                    /* display taskbar icon */
107                    result = NULL;
108            }
109            else
110            {
111                    /* no taskbar icon */
112                    if (owner)
113                            result = owner;
114                    else
115                            result = (HWND) - 1;
116            }
117    
118            return result;
119    }
120    
121  static void  static void
122  update_position(HWND hwnd)  update_position(HWND hwnd)
123  {  {
124          RECT rect;          RECT rect, blocked;
125            HWND blocked_hwnd;
126            unsigned int serial;
127    
128            WaitForSingleObject(g_mutex, INFINITE);
129            blocked_hwnd = g_block_move_hwnd;
130            serial = g_block_move_serial;
131            memcpy(&blocked, &g_block_move, sizeof(RECT));
132            ReleaseMutex(g_mutex);
133    
134            vchannel_block();
135    
136          if (!GetWindowRect(hwnd, &rect))          if (!GetWindowRect(hwnd, &rect))
137          {          {
138                  debug("GetWindowRect failed!\n");                  debug("GetWindowRect failed!\n");
139                  return;                  goto end;
140          }          }
141    
142          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",          if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
143                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
144                    goto end;
145    
146            vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
147                         hwnd,                         hwnd,
148                         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);                         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
149    
150          end:
151            vchannel_unblock();
152    }
153    
154    static void
155    update_zorder(HWND hwnd)
156    {
157            HWND behind;
158            HWND block_hwnd, block_behind;
159            unsigned int serial;
160    
161            WaitForSingleObject(g_mutex, INFINITE);
162            serial = g_blocked_zchange_serial;
163            block_hwnd = g_blocked_zchange[0];
164            block_behind = g_blocked_zchange[1];
165            ReleaseMutex(g_mutex);
166    
167            vchannel_block();
168    
169            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                    vchannel_write("ACK", "%u", serial);
184            else
185                    vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, 0);
186    
187            vchannel_unblock();
188    }
189    
190    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  static LRESULT CALLBACK  static LRESULT CALLBACK
357  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
358  {  {
359          HWND hwnd, parent;          HWND hwnd;
360          UINT msg;          UINT msg;
361          WPARAM wparam;          WPARAM wparam;
362          LPARAM lparam;          LPARAM lparam;
# Line 85  wndproc_hook_proc(int code, WPARAM cur_t Line 373  wndproc_hook_proc(int code, WPARAM cur_t
373    
374          style = GetWindowLong(hwnd, GWL_STYLE);          style = GetWindowLong(hwnd, GWL_STYLE);
375    
376          /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,          if (!is_toplevel(hwnd)) {
            but they exist nonetheless. */  
         if ((style & WS_CHILD) && !(style & WS_POPUP))  
377                  goto end;                  goto end;
   
         if (style & WS_POPUP)  
         {  
                 parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);  
                 if (!parent)  
                         parent = (HWND) - 1;  
378          }          }
         else  
                 parent = NULL;  
379    
380          switch (msg)          switch (msg)
381          {          {
   
382                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
383                          {                          {
384                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
385    
386                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
387                                  {                                  {
388                                          char title[150];                                          unsigned short title[150];
389                                          int state;                                          int state;
390                                            DWORD pid;
391                                          vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);                                          int flags;
392                                            HICON icon;
393                                          GetWindowText(hwnd, title, sizeof(title));  
394                                            GetWindowThreadProcessId(hwnd, &pid);
395                                          /* FIXME: Strip title of dangerous characters */  
396                                            flags = 0;
397                                          vchannel_write("TITLE,0x%x,%s,0x%x", hwnd, title, 0);                                          if (style & DS_MODALFRAME)
398                                                    flags |= SEAMLESS_CREATE_MODAL;
399    
400                                            vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
401                                                           (long) hwnd, (long) pid, (long) get_parent(hwnd),
402                                                           flags);
403    
404                                            GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
405    
406                                            vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
407                                                           vchannel_strfilter_unicode(title), 0);
408    
409                                            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                                          if (style & WS_MAXIMIZE)                                          if (style & WS_MAXIMIZE)
424                                                  state = 2;                                                  state = 2;
# Line 126  wndproc_hook_proc(int code, WPARAM cur_t Line 427  wndproc_hook_proc(int code, WPARAM cur_t
427                                          else                                          else
428                                                  state = 0;                                                  state = 0;
429    
                                         vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);  
   
430                                          update_position(hwnd);                                          update_position(hwnd);
431    
432                                          /* FIXME: Figure out z order */                                          vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
433                                                           state, 0);
434                                  }                                  }
435    
436                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
437                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
438    
439                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
440                                          break;                                          break;
# Line 142  wndproc_hook_proc(int code, WPARAM cur_t Line 442  wndproc_hook_proc(int code, WPARAM cur_t
442                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
443                                          update_position(hwnd);                                          update_position(hwnd);
444    
445                                  if (!(wp->flags & SWP_NOZORDER))                                  break;
446                                  {                          }
                                         vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",  
                                                        hwnd,  
                                                        wp->flags & SWP_NOACTIVATE ? wp->  
                                                        hwndInsertAfter : 0, 0);  
                                 }  
447    
448                    case WM_SETICON:
449                            if (!(style & WS_VISIBLE))
450                                  break;                                  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                  case WM_SIZE:                  case WM_SIZE:
476                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
477                                  break;                                  break;
# Line 165  wndproc_hook_proc(int code, WPARAM cur_t Line 484  wndproc_hook_proc(int code, WPARAM cur_t
484                          update_position(hwnd);                          update_position(hwnd);
485                          break;                          break;
486    
                 case WM_SETTEXT:  
                         if (!(style & WS_VISIBLE))  
                                 break;  
                         /* FIXME: Strip title of dangerous characters */  
                         vchannel_write("TITLE,0x%p,%s,0x%x", hwnd, (char *) lparam, 0);  
                         break;  
   
487                  case WM_DESTROY:                  case WM_DESTROY:
488                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE))
489                                  break;                                  break;
490                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
491                          break;                          break;
492    
493                  default:                  default:
# Line 187  wndproc_hook_proc(int code, WPARAM cur_t Line 499  wndproc_hook_proc(int code, WPARAM cur_t
499  }  }
500    
501  static LRESULT CALLBACK  static LRESULT CALLBACK
502    wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
503    {
504            HWND hwnd;
505            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            if (!is_toplevel(hwnd)) {
522                    goto end;
523            }
524    
525            switch (msg)
526            {
527                    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                    case WM_SETTEXT:
542                            {
543                                    unsigned short title[150];
544                                    if (!(style & WS_VISIBLE))
545                                            break;
546                                    /* We cannot use the string in lparam because
547                                       we need unicode. */
548                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
549                                    vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
550                                                   vchannel_strfilter_unicode(title), 0);
551                                    break;
552                            }
553    
554                    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                    default:
572                            break;
573            }
574    
575            if (msg == g_wm_seamless_focus)
576            {
577                    /* FIXME: SetForegroundWindow() kills menus. Need to find a
578                       clean way to solve this. */
579                    if ((GetForegroundWindow() != hwnd) && !get_parent(hwnd))
580                            SetForegroundWindow(hwnd);
581    
582                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
583            }
584    
585          end:
586            return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
587    }
588    
589    static LRESULT CALLBACK
590  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
591  {  {
592          if (code < 0)          if (code < 0)
# Line 196  cbt_hook_proc(int code, WPARAM wparam, L Line 596  cbt_hook_proc(int code, WPARAM wparam, L
596          {          {
597                  case HCBT_MINMAX:                  case HCBT_MINMAX:
598                          {                          {
599                                  int show, state;                                  int show, state, blocked;
600                                    HWND hwnd, blocked_hwnd;
601                                    unsigned int serial;
602                                    LONG style;
603    
604                                    WaitForSingleObject(g_mutex, INFINITE);
605                                    blocked_hwnd = g_blocked_state_hwnd;
606                                    serial = g_blocked_state_serial;
607                                    blocked = g_blocked_state;
608                                    ReleaseMutex(g_mutex);
609    
610                                    hwnd = (HWND) wparam;
611    
612                                    style = GetWindowLong(hwnd, GWL_STYLE);
613    
614                                    if (!(style & WS_VISIBLE))
615                                            break;
616    
617                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
618    
619                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL))                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
620                                        || (show == SW_RESTORE))
621                                          state = 0;                                          state = 0;
622                                  else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))                                  else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
623                                          state = 1;                                          state = 1;
# Line 211  cbt_hook_proc(int code, WPARAM wparam, L Line 628  cbt_hook_proc(int code, WPARAM wparam, L
628                                          debug("Unexpected show: %d", show);                                          debug("Unexpected show: %d", show);
629                                          break;                                          break;
630                                  }                                  }
631                                  vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);  
632                                    if ((blocked_hwnd == hwnd) && (blocked == state))
633                                            vchannel_write("ACK", "%u", serial);
634                                    else
635                                            vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
636                                                           hwnd, state, 0);
637    
638                                  break;                                  break;
639                          }                          }
640    
# Line 231  SetHooks(void) Line 654  SetHooks(void)
654    
655          if (!g_wndproc_hook)          if (!g_wndproc_hook)
656                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
657    
658            if (!g_wndprocret_hook)
659                    g_wndprocret_hook =
660                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
661  }  }
662    
663  DLL_EXPORT void  DLL_EXPORT void
# Line 241  RemoveHooks(void) Line 668  RemoveHooks(void)
668    
669          if (g_wndproc_hook)          if (g_wndproc_hook)
670                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
671    
672            if (g_wndprocret_hook)
673                    UnhookWindowsHookEx(g_wndprocret_hook);
674    }
675    
676    DLL_EXPORT void
677    SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
678    {
679            RECT rect;
680    
681            WaitForSingleObject(g_mutex, INFINITE);
682            g_block_move_hwnd = hwnd;
683            g_block_move_serial = serial;
684            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            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            WaitForSingleObject(g_mutex, INFINITE);
701            g_block_move_hwnd = NULL;
702            memset(&g_block_move, 0, sizeof(RECT));
703            ReleaseMutex(g_mutex);
704    }
705    
706    DLL_EXPORT void
707    SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
708    {
709            WaitForSingleObject(g_mutex, INFINITE);
710            g_blocked_zchange_serial = serial;
711            g_blocked_zchange[0] = hwnd;
712            g_blocked_zchange[1] = behind;
713            ReleaseMutex(g_mutex);
714    
715            if (behind == NULL)
716                    behind = HWND_TOP;
717    
718            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    SafeFocus(unsigned int serial, HWND hwnd)
728    {
729            WaitForSingleObject(g_mutex, INFINITE);
730            g_blocked_focus_serial = serial;
731            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    DLL_EXPORT void
742    SafeSetState(unsigned int serial, HWND hwnd, int state)
743    {
744            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                    return;
763            }
764    
765            WaitForSingleObject(g_mutex, INFINITE);
766            g_blocked_state_hwnd = hwnd;
767            g_blocked_state_serial = serial;
768            g_blocked_state = state;
769            ReleaseMutex(g_mutex);
770    
771            vchannel_unblock();
772    
773            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            g_blocked_state_hwnd = NULL;
784            g_blocked_state = -1;
785            ReleaseMutex(g_mutex);
786  }  }
787    
788  DLL_EXPORT int  DLL_EXPORT int
# Line 266  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 808  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
808                          ++g_instance_count;                          ++g_instance_count;
809                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
810    
811                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
812    
813                          vchannel_open();                          vchannel_open();
814    
815                          break;                          break;
# Line 277  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 821  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
821                          break;                          break;
822    
823                  case DLL_PROCESS_DETACH:                  case DLL_PROCESS_DETACH:
824                            vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0);
825    
826                          WaitForSingleObject(g_mutex, INFINITE);                          WaitForSingleObject(g_mutex, INFINITE);
827                          --g_instance_count;                          --g_instance_count;
828                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);

Legend:
Removed from v.1109  
changed lines
  Added in v.1439

  ViewVC Help
Powered by ViewVC 1.1.26