/[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 1131 by ossman_, Wed Mar 15 12:15:23 2006 UTC revision 1440 by astrand, Thu Mar 6 15:12:26 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
79    is_toplevel(HWND hwnd)
80    {
81            BOOL toplevel;
82            HWND parent;
83            parent = GetAncestor(hwnd, GA_PARENT);
84    
85            /* According to MS: "A window that has no parent, or whose
86               parent is the desktop window, is called a top-level
87               window." See http://msdn2.microsoft.com/en-us/library/ms632597(VS.85).aspx. */
88            toplevel = (!parent || parent == GetDesktopWindow());
89            return toplevel;
90    }
91    
92    /* Determine the "parent" field for the CREATE response. */
93    static HWND
94    get_parent(HWND hwnd)
95    {
96            HWND result;
97            HWND owner;
98            LONG exstyle;
99    
100            /* Use the same logic to determine if the window should be
101               "transient" (ie have no task icon) as MS uses. This is documented at
102               http://msdn2.microsoft.com/en-us/library/bb776822.aspx */
103            owner = GetWindow(hwnd, GW_OWNER);
104            exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
105            if (!owner && !(exstyle & WS_EX_TOOLWINDOW))
106            {
107                    /* display taskbar icon */
108                    result = NULL;
109            }
110            else
111            {
112                    /* no taskbar icon */
113                    if (owner)
114                            result = owner;
115                    else
116                            result = (HWND) - 1;
117            }
118    
119            return result;
120    }
121    
122  static void  static void
123  update_position(HWND hwnd)  update_position(HWND hwnd)
124  {  {
125          RECT rect;          RECT rect, blocked;
126            HWND blocked_hwnd;
127            unsigned int serial;
128    
129            WaitForSingleObject(g_mutex, INFINITE);
130            blocked_hwnd = g_block_move_hwnd;
131            serial = g_block_move_serial;
132            memcpy(&blocked, &g_block_move, sizeof(RECT));
133            ReleaseMutex(g_mutex);
134    
135            vchannel_block();
136    
137          if (!GetWindowRect(hwnd, &rect))          if (!GetWindowRect(hwnd, &rect))
138          {          {
139                  debug("GetWindowRect failed!\n");                  debug("GetWindowRect failed!\n");
140                  return;                  goto end;
141          }          }
142    
143          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",          if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
144                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
145                    goto end;
146    
147            vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
148                         hwnd,                         hwnd,
149                         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);
150    
151          end:
152            vchannel_unblock();
153    }
154    
155    static void
156    update_zorder(HWND hwnd)
157    {
158            HWND behind;
159            HWND block_hwnd, block_behind;
160            unsigned int serial;
161    
162            WaitForSingleObject(g_mutex, INFINITE);
163            serial = g_blocked_zchange_serial;
164            block_hwnd = g_blocked_zchange[0];
165            block_behind = g_blocked_zchange[1];
166            ReleaseMutex(g_mutex);
167    
168            vchannel_block();
169    
170            behind = GetNextWindow(hwnd, GW_HWNDPREV);
171            while (behind)
172            {
173                    LONG style;
174    
175                    style = GetWindowLong(behind, GWL_STYLE);
176    
177                    if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
178                            break;
179    
180                    behind = GetNextWindow(behind, GW_HWNDPREV);
181            }
182    
183            if ((hwnd == block_hwnd) && (behind == block_behind))
184                    vchannel_write("ACK", "%u", serial);
185            else
186                    vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, 0);
187    
188            vchannel_unblock();
189    }
190    
191    static HICON
192    get_icon(HWND hwnd, int large)
193    {
194            HICON icon;
195    
196            if (!SendMessageTimeout(hwnd, WM_GETICON, large ? ICON_BIG : ICON_SMALL,
197                                    0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
198                    return NULL;
199    
200            if (icon)
201                    return icon;
202    
203            /*
204             * Modern versions of Windows uses the voodoo value of 2 instead of 0
205             * for the small icons.
206             */
207            if (!large)
208            {
209                    if (!SendMessageTimeout(hwnd, WM_GETICON, 2,
210                                            0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
211                            return NULL;
212            }
213    
214            if (icon)
215                    return icon;
216    
217            icon = (HICON) GetClassLong(hwnd, large ? GCL_HICON : GCL_HICONSM);
218    
219            if (icon)
220                    return icon;
221    
222            return NULL;
223    }
224    
225    static int
226    extract_icon(HICON icon, char *buffer, int maxlen)
227    {
228            ICONINFO info;
229            HDC hdc;
230            BITMAP mask_bmp, color_bmp;
231            BITMAPINFO bmi;
232            int size, i;
233            char *mask_buf, *color_buf;
234            char *o, *m, *c;
235            int ret = -1;
236    
237            assert(buffer);
238            assert(maxlen > 0);
239    
240            if (!GetIconInfo(icon, &info))
241                    goto fail;
242    
243            if (!GetObject(info.hbmMask, sizeof(BITMAP), &mask_bmp))
244                    goto free_bmps;
245            if (!GetObject(info.hbmColor, sizeof(BITMAP), &color_bmp))
246                    goto free_bmps;
247    
248            if (mask_bmp.bmWidth != color_bmp.bmWidth)
249                    goto free_bmps;
250            if (mask_bmp.bmHeight != color_bmp.bmHeight)
251                    goto free_bmps;
252    
253            if ((mask_bmp.bmWidth * mask_bmp.bmHeight * 4) > maxlen)
254                    goto free_bmps;
255    
256            size = (mask_bmp.bmWidth + 3) / 4 * 4;
257            size *= mask_bmp.bmHeight;
258            size *= 4;
259    
260            mask_buf = malloc(size);
261            if (!mask_buf)
262                    goto free_bmps;
263            color_buf = malloc(size);
264            if (!color_buf)
265                    goto free_mbuf;
266    
267            memset(&bmi, 0, sizeof(BITMAPINFO));
268    
269            bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
270            bmi.bmiHeader.biWidth = mask_bmp.bmWidth;
271            bmi.bmiHeader.biHeight = -mask_bmp.bmHeight;
272            bmi.bmiHeader.biPlanes = 1;
273            bmi.bmiHeader.biBitCount = 32;
274            bmi.bmiHeader.biCompression = BI_RGB;
275            bmi.bmiHeader.biSizeImage = size;
276    
277            hdc = CreateCompatibleDC(NULL);
278            if (!hdc)
279                    goto free_cbuf;
280    
281            if (!GetDIBits(hdc, info.hbmMask, 0, mask_bmp.bmHeight, mask_buf, &bmi, DIB_RGB_COLORS))
282                    goto del_dc;
283            if (!GetDIBits(hdc, info.hbmColor, 0, color_bmp.bmHeight, color_buf, &bmi, DIB_RGB_COLORS))
284                    goto del_dc;
285    
286            o = buffer;
287            m = mask_buf;
288            c = color_buf;
289            for (i = 0; i < size / 4; i++)
290            {
291                    o[0] = c[2];
292                    o[1] = c[1];
293                    o[2] = c[0];
294    
295                    o[3] = ((int) (unsigned char) m[0] + (unsigned char) m[1] +
296                            (unsigned char) m[2]) / 3;
297                    o[3] = 0xff - o[3];
298    
299                    o += 4;
300                    m += 4;
301                    c += 4;
302            }
303    
304            ret = size;
305    
306          del_dc:
307            DeleteDC(hdc);
308    
309          free_cbuf:
310            free(color_buf);
311          free_mbuf:
312            free(mask_buf);
313    
314          free_bmps:
315            DeleteObject(info.hbmMask);
316            DeleteObject(info.hbmColor);
317    
318          fail:
319            return ret;
320    }
321    
322    #define ICON_CHUNK 400
323    
324    static void
325    update_icon(HWND hwnd, HICON icon, int large)
326    {
327            int i, j, size, chunks;
328            char buf[32 * 32 * 4];
329            char asciibuf[ICON_CHUNK * 2 + 1];
330    
331            size = extract_icon(icon, buf, sizeof(buf));
332            if (size <= 0)
333                    return;
334    
335            if ((!large && size != 16 * 16 * 4) || (large && size != 32 * 32 * 4))
336            {
337                    debug("Unexpected icon size.");
338                    return;
339            }
340    
341            chunks = (size + ICON_CHUNK - 1) / ICON_CHUNK;
342            for (i = 0; i < chunks; i++)
343            {
344                    for (j = 0; j < ICON_CHUNK; j++)
345                    {
346                            if (i * ICON_CHUNK + j >= size)
347                                    break;
348                            sprintf(asciibuf + j * 2, "%02x",
349                                    (int) (unsigned char) buf[i * ICON_CHUNK + j]);
350                    }
351    
352                    vchannel_write("SETICON", "0x%08lx,%d,RGBA,%d,%d,%s", hwnd, i,
353                                   large ? 32 : 16, large ? 32 : 16, asciibuf);
354            }
355  }  }
356    
357  static LRESULT CALLBACK  static LRESULT CALLBACK
358  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
359  {  {
360          HWND hwnd, parent;          HWND hwnd;
361          UINT msg;          UINT msg;
362          WPARAM wparam;          WPARAM wparam;
363          LPARAM lparam;          LPARAM lparam;
# Line 85  wndproc_hook_proc(int code, WPARAM cur_t Line 374  wndproc_hook_proc(int code, WPARAM cur_t
374    
375          style = GetWindowLong(hwnd, GWL_STYLE);          style = GetWindowLong(hwnd, GWL_STYLE);
376    
377          /* 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))  
                 goto end;  
   
         if (style & WS_POPUP)  
378          {          {
379                  parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);                  goto end;
                 if (!parent)  
                         parent = (HWND) - 1;  
380          }          }
         else  
                 parent = NULL;  
381    
382          switch (msg)          switch (msg)
383          {          {
   
384                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
385                          {                          {
386                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
387    
388                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
389                                  {                                  {
390                                          char title[150];                                          unsigned short title[150];
391                                          int state;                                          int state;
392                                            DWORD pid;
393                                          vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);                                          int flags;
394                                            HICON icon;
395                                          GetWindowText(hwnd, title, sizeof(title));  
396                                            GetWindowThreadProcessId(hwnd, &pid);
397                                          vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,  
398                                                         vchannel_strfilter(title), 0);                                          flags = 0;
399                                            if (style & DS_MODALFRAME)
400                                                    flags |= SEAMLESS_CREATE_MODAL;
401    
402                                            vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
403                                                           (long) hwnd, (long) pid,
404                                                           (long) get_parent(hwnd), flags);
405    
406                                            GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
407    
408                                            vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
409                                                           vchannel_strfilter_unicode(title), 0);
410    
411                                            icon = get_icon(hwnd, 1);
412                                            if (icon)
413                                            {
414                                                    update_icon(hwnd, icon, 1);
415                                                    DeleteObject(icon);
416                                            }
417    
418                                            icon = get_icon(hwnd, 0);
419                                            if (icon)
420                                            {
421                                                    update_icon(hwnd, icon, 0);
422                                                    DeleteObject(icon);
423                                            }
424    
425                                          if (style & WS_MAXIMIZE)                                          if (style & WS_MAXIMIZE)
426                                                  state = 2;                                                  state = 2;
# Line 127  wndproc_hook_proc(int code, WPARAM cur_t Line 431  wndproc_hook_proc(int code, WPARAM cur_t
431    
432                                          update_position(hwnd);                                          update_position(hwnd);
433    
434                                          vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);                                          vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
435                                                           state, 0);
436                                  }                                  }
437    
438                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
439                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
440    
441                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
442                                          break;                                          break;
# Line 139  wndproc_hook_proc(int code, WPARAM cur_t Line 444  wndproc_hook_proc(int code, WPARAM cur_t
444                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
445                                          update_position(hwnd);                                          update_position(hwnd);
446    
447                                  if (!(wp->flags & SWP_NOZORDER))                                  break;
448                                  {                          }
                                         vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",  
                                                        hwnd,  
                                                        wp->flags & SWP_NOACTIVATE ? wp->  
                                                        hwndInsertAfter : 0, 0);  
                                 }  
449    
450                    case WM_SETICON:
451                            if (!(style & WS_VISIBLE))
452                                  break;                                  break;
453    
454                            switch (wparam)
455                            {
456                                    case ICON_BIG:
457                                            if (lparam)
458                                                    update_icon(hwnd, (HICON) lparam, 1);
459                                            else
460                                                    vchannel_write("DELICON", "0x%08lx,RGBA,32,32",
461                                                                   hwnd);
462                                            break;
463                                    case ICON_SMALL:
464                                    case 2:
465                                            if (lparam)
466                                                    update_icon(hwnd, (HICON) lparam, 0);
467                                            else
468                                                    vchannel_write("DELICON", "0x%08lx,RGBA,16,16",
469                                                                   hwnd);
470                                            break;
471                                    default:
472                                            debug("Weird icon size %d", (int) wparam);
473                          }                          }
474    
475                            break;
476    
477                  case WM_SIZE:                  case WM_SIZE:
478                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
479                                  break;                                  break;
# Line 162  wndproc_hook_proc(int code, WPARAM cur_t Line 486  wndproc_hook_proc(int code, WPARAM cur_t
486                          update_position(hwnd);                          update_position(hwnd);
487                          break;                          break;
488    
489                    case WM_DESTROY:
490                            if (!(style & WS_VISIBLE))
491                                    break;
492                            vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
493                            break;
494    
495                    default:
496                            break;
497            }
498    
499          end:
500            return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
501    }
502    
503    static LRESULT CALLBACK
504    wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
505    {
506            HWND hwnd;
507            UINT msg;
508            WPARAM wparam;
509            LPARAM lparam;
510    
511            LONG style;
512    
513            if (code < 0)
514                    goto end;
515    
516            hwnd = ((CWPRETSTRUCT *) details)->hwnd;
517            msg = ((CWPRETSTRUCT *) details)->message;
518            wparam = ((CWPRETSTRUCT *) details)->wParam;
519            lparam = ((CWPRETSTRUCT *) details)->lParam;
520    
521            style = GetWindowLong(hwnd, GWL_STYLE);
522    
523            if (!is_toplevel(hwnd))
524            {
525                    goto end;
526            }
527    
528            switch (msg)
529            {
530                    case WM_WINDOWPOSCHANGED:
531                            {
532                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
533    
534                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
535                                            break;
536    
537                                    if (!(wp->flags & SWP_NOZORDER))
538                                            update_zorder(hwnd);
539    
540                                    break;
541                            }
542    
543    
544                  case WM_SETTEXT:                  case WM_SETTEXT:
545                          {                          {
546                                  char *title;                                  unsigned short title[150];
547                                  if (!(style & WS_VISIBLE))                                  if (!(style & WS_VISIBLE))
548                                          break;                                          break;
549                                  title = _strdup((char *) lparam);                                  /* We cannot use the string in lparam because
550                                  vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,                                     we need unicode. */
551                                                 vchannel_strfilter(title), 0);                                  GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
552                                  free(title);                                  vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
553                                                   vchannel_strfilter_unicode(title), 0);
554                                  break;                                  break;
555                          }                          }
556    
557                  case WM_DESTROY:                  case WM_SETICON:
558                          if (!(style & WS_VISIBLE))                          {
559                                  break;                                  HICON icon;
560                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);  
561                          break;                                  /*
562                                     * Somehow, we never get WM_SETICON for the small icon.
563                                     * So trigger a read of it every time the large one is
564                                     * changed.
565                                     */
566                                    icon = get_icon(hwnd, 0);
567                                    if (icon)
568                                    {
569                                            update_icon(hwnd, icon, 0);
570                                            DeleteObject(icon);
571                                    }
572                            }
573    
574                  default:                  default:
575                          break;                          break;
576          }          }
577    
578            if (msg == g_wm_seamless_focus)
579            {
580                    /* FIXME: SetForegroundWindow() kills menus. Need to find a
581                       clean way to solve this. */
582                    if ((GetForegroundWindow() != hwnd) && !get_parent(hwnd))
583                            SetForegroundWindow(hwnd);
584    
585                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
586            }
587    
588        end:        end:
589          return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);          return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
590  }  }
591    
592  static LRESULT CALLBACK  static LRESULT CALLBACK
# Line 198  cbt_hook_proc(int code, WPARAM wparam, L Line 599  cbt_hook_proc(int code, WPARAM wparam, L
599          {          {
600                  case HCBT_MINMAX:                  case HCBT_MINMAX:
601                          {                          {
602                                  int show, state;                                  int show, state, blocked;
603                                    HWND hwnd, blocked_hwnd;
604                                    unsigned int serial;
605                                    LONG style;
606    
607                                    WaitForSingleObject(g_mutex, INFINITE);
608                                    blocked_hwnd = g_blocked_state_hwnd;
609                                    serial = g_blocked_state_serial;
610                                    blocked = g_blocked_state;
611                                    ReleaseMutex(g_mutex);
612    
613                                    hwnd = (HWND) wparam;
614    
615                                    style = GetWindowLong(hwnd, GWL_STYLE);
616    
617                                    if (!(style & WS_VISIBLE))
618                                            break;
619    
620                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
621    
# Line 214  cbt_hook_proc(int code, WPARAM wparam, L Line 631  cbt_hook_proc(int code, WPARAM wparam, L
631                                          debug("Unexpected show: %d", show);                                          debug("Unexpected show: %d", show);
632                                          break;                                          break;
633                                  }                                  }
634                                  vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);  
635                                    if ((blocked_hwnd == hwnd) && (blocked == state))
636                                            vchannel_write("ACK", "%u", serial);
637                                    else
638                                            vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
639                                                           hwnd, state, 0);
640    
641                                  break;                                  break;
642                          }                          }
643    
# Line 234  SetHooks(void) Line 657  SetHooks(void)
657    
658          if (!g_wndproc_hook)          if (!g_wndproc_hook)
659                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
660    
661            if (!g_wndprocret_hook)
662                    g_wndprocret_hook =
663                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
664  }  }
665    
666  DLL_EXPORT void  DLL_EXPORT void
# Line 244  RemoveHooks(void) Line 671  RemoveHooks(void)
671    
672          if (g_wndproc_hook)          if (g_wndproc_hook)
673                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
674    
675            if (g_wndprocret_hook)
676                    UnhookWindowsHookEx(g_wndprocret_hook);
677    }
678    
679    DLL_EXPORT void
680    SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
681    {
682            RECT rect;
683    
684            WaitForSingleObject(g_mutex, INFINITE);
685            g_block_move_hwnd = hwnd;
686            g_block_move_serial = serial;
687            g_block_move.left = x;
688            g_block_move.top = y;
689            g_block_move.right = x + width;
690            g_block_move.bottom = y + height;
691            ReleaseMutex(g_mutex);
692    
693            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
694    
695            vchannel_write("ACK", "%u", serial);
696    
697            if (!GetWindowRect(hwnd, &rect))
698                    debug("GetWindowRect failed!\n");
699            else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
700                     || (rect.bottom != y + height))
701                    update_position(hwnd);
702    
703            WaitForSingleObject(g_mutex, INFINITE);
704            g_block_move_hwnd = NULL;
705            memset(&g_block_move, 0, sizeof(RECT));
706            ReleaseMutex(g_mutex);
707    }
708    
709    DLL_EXPORT void
710    SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
711    {
712            WaitForSingleObject(g_mutex, INFINITE);
713            g_blocked_zchange_serial = serial;
714            g_blocked_zchange[0] = hwnd;
715            g_blocked_zchange[1] = behind;
716            ReleaseMutex(g_mutex);
717    
718            if (behind == NULL)
719                    behind = HWND_TOP;
720    
721            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
722    
723            WaitForSingleObject(g_mutex, INFINITE);
724            g_blocked_zchange[0] = NULL;
725            g_blocked_zchange[1] = NULL;
726            ReleaseMutex(g_mutex);
727    }
728    
729    DLL_EXPORT void
730    SafeFocus(unsigned int serial, HWND hwnd)
731    {
732            WaitForSingleObject(g_mutex, INFINITE);
733            g_blocked_focus_serial = serial;
734            g_blocked_focus = hwnd;
735            ReleaseMutex(g_mutex);
736    
737            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
738    
739            WaitForSingleObject(g_mutex, INFINITE);
740            g_blocked_focus = NULL;
741            ReleaseMutex(g_mutex);
742    }
743    
744    DLL_EXPORT void
745    SafeSetState(unsigned int serial, HWND hwnd, int state)
746    {
747            LONG style;
748            int curstate;
749    
750            vchannel_block();
751    
752            style = GetWindowLong(hwnd, GWL_STYLE);
753    
754            if (style & WS_MAXIMIZE)
755                    curstate = 2;
756            else if (style & WS_MINIMIZE)
757                    curstate = 1;
758            else
759                    curstate = 0;
760    
761            if (state == curstate)
762            {
763                    vchannel_write("ACK", "%u", serial);
764                    vchannel_unblock();
765                    return;
766            }
767    
768            WaitForSingleObject(g_mutex, INFINITE);
769            g_blocked_state_hwnd = hwnd;
770            g_blocked_state_serial = serial;
771            g_blocked_state = state;
772            ReleaseMutex(g_mutex);
773    
774            vchannel_unblock();
775    
776            if (state == 0)
777                    ShowWindow(hwnd, SW_RESTORE);
778            else if (state == 1)
779                    ShowWindow(hwnd, SW_MINIMIZE);
780            else if (state == 2)
781                    ShowWindow(hwnd, SW_MAXIMIZE);
782            else
783                    debug("Invalid state %d sent.", state);
784    
785            WaitForSingleObject(g_mutex, INFINITE);
786            g_blocked_state_hwnd = NULL;
787            g_blocked_state = -1;
788            ReleaseMutex(g_mutex);
789  }  }
790    
791  DLL_EXPORT int  DLL_EXPORT int
# Line 269  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 811  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
811                          ++g_instance_count;                          ++g_instance_count;
812                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
813    
814                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
815    
816                          vchannel_open();                          vchannel_open();
817    
818                          break;                          break;
# Line 280  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 824  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
824                          break;                          break;
825    
826                  case DLL_PROCESS_DETACH:                  case DLL_PROCESS_DETACH:
827                            vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0);
828    
829                          WaitForSingleObject(g_mutex, INFINITE);                          WaitForSingleObject(g_mutex, INFINITE);
830                          --g_instance_count;                          --g_instance_count;
831                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);

Legend:
Removed from v.1131  
changed lines
  Added in v.1440

  ViewVC Help
Powered by ViewVC 1.1.26