/[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 1096 by ossman_, Fri Mar 10 12:27:38 2006 UTC revision 1230 by ossman_, Thu Apr 20 12:56:18 2006 UTC
# Line 32  Line 32 
32    
33  #define DLL_EXPORT __declspec(dllexport)  #define DLL_EXPORT __declspec(dllexport)
34    
35    #ifdef __GNUC__
36    #define SHARED __attribute__((section ("SHAREDDATA"), shared))
37    #else
38    #define SHARED
39    #endif
40    
41  // Shared DATA  // Shared DATA
42  #pragma data_seg ( "SHAREDDATA" )  #pragma data_seg ( "SHAREDDATA" )
43    
44  // 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
45  int g_instance_count = 0;  int g_instance_count SHARED = 0;
46    
47    // blocks for locally generated events
48    HWND g_block_move_hwnd SHARED = NULL;
49    unsigned int g_block_move_serial SHARED = 0;
50    RECT g_block_move SHARED = { 0, 0, 0, 0 };
51    
52    unsigned int g_blocked_zchange_serial SHARED = 0;
53    HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
54    
55    unsigned int g_blocked_focus_serial SHARED = 0;
56    HWND g_blocked_focus SHARED = NULL;
57    
58    unsigned int g_blocked_state_serial SHARED = 0;
59    HWND g_blocked_state_hwnd SHARED = NULL;
60    int g_blocked_state SHARED = -1;
61    
62  #pragma data_seg ()  #pragma data_seg ()
63    
64  #pragma comment(linker, "/section:SHAREDDATA,rws")  #pragma comment(linker, "/section:SHAREDDATA,rws")
65    
66    #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
67    static UINT g_wm_seamless_focus;
68    
69  static HHOOK g_cbt_hook = NULL;  static HHOOK g_cbt_hook = NULL;
70  static HHOOK g_wndproc_hook = NULL;  static HHOOK g_wndproc_hook = NULL;
71    static HHOOK g_wndprocret_hook = NULL;
72    
73  static HINSTANCE g_instance = NULL;  static HINSTANCE g_instance = NULL;
74    
# Line 52  static HANDLE g_mutex = NULL; Line 77  static HANDLE g_mutex = NULL;
77  static void  static void
78  update_position(HWND hwnd)  update_position(HWND hwnd)
79  {  {
80          RECT rect;          RECT rect, blocked;
81            HWND blocked_hwnd;
82            unsigned int serial;
83    
84            WaitForSingleObject(g_mutex, INFINITE);
85            blocked_hwnd = g_block_move_hwnd;
86            serial = g_block_move_serial;
87            memcpy(&blocked, &g_block_move, sizeof(RECT));
88            ReleaseMutex(g_mutex);
89    
90            vchannel_block();
91    
92          if (!GetWindowRect(hwnd, &rect))          if (!GetWindowRect(hwnd, &rect))
93          {          {
94                  debug("GetWindowRect failed!\n");                  debug("GetWindowRect failed!\n");
95                  return;                  goto end;
96          }          }
97    
98          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",          if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
99                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
100                    goto end;
101    
102            vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
103                         hwnd,                         hwnd,
104                         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);
105    
106          end:
107            vchannel_unblock();
108    }
109    
110    static void
111    update_zorder(HWND hwnd)
112    {
113            HWND behind;
114            HWND block_hwnd, block_behind;
115            unsigned int serial;
116    
117            WaitForSingleObject(g_mutex, INFINITE);
118            serial = g_blocked_zchange_serial;
119            block_hwnd = g_blocked_zchange[0];
120            block_behind = g_blocked_zchange[1];
121            ReleaseMutex(g_mutex);
122    
123            vchannel_block();
124    
125            behind = GetNextWindow(hwnd, GW_HWNDPREV);
126            while (behind)
127            {
128                    LONG style;
129    
130                    style = GetWindowLong(behind, GWL_STYLE);
131    
132                    if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
133                            break;
134    
135                    behind = GetNextWindow(behind, GW_HWNDPREV);
136            }
137    
138            if ((hwnd == block_hwnd) && (behind == block_behind))
139                    vchannel_write("ACK", "%u", serial);
140            else
141                    vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, 0);
142    
143            vchannel_unblock();
144    }
145    
146    static HWND
147    get_parent(HWND hwnd)
148    {
149            LONG style;
150            HWND parent;
151    
152            style = GetWindowLong(hwnd, GWL_STYLE);
153    
154            if (style & (WS_POPUP | DS_MODALFRAME))
155            {
156                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
157    
158                    if (parent)
159                    {
160                            style = GetWindowLong(parent, GWL_STYLE);
161                            if (((style & WS_CHILD) && !(style & WS_POPUP)) || !(style & WS_VISIBLE))
162                                    parent = NULL;
163                    }
164    
165                    if (!parent)
166                            parent = GetWindow(hwnd, GW_OWNER);
167    
168                    if (parent)
169                    {
170                            style = GetWindowLong(parent, GWL_STYLE);
171                            if (((style & WS_CHILD) && !(style & WS_POPUP)) || !(style & WS_VISIBLE))
172                                    parent = NULL;
173                    }
174    
175                    if (!parent)
176                            parent = (HWND) - 1;
177            }
178            else
179                    parent = NULL;
180    
181            return parent;
182  }  }
183    
184  static LRESULT CALLBACK  static LRESULT CALLBACK
185  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
186  {  {
187          HWND hwnd;          HWND hwnd, parent;
188          UINT msg;          UINT msg;
189          WPARAM wparam;          WPARAM wparam;
190          LPARAM lparam;          LPARAM lparam;
# Line 90  wndproc_hook_proc(int code, WPARAM cur_t Line 206  wndproc_hook_proc(int code, WPARAM cur_t
206          if ((style & WS_CHILD) && !(style & WS_POPUP))          if ((style & WS_CHILD) && !(style & WS_POPUP))
207                  goto end;                  goto end;
208    
209            parent = get_parent(hwnd);
210    
211          switch (msg)          switch (msg)
212          {          {
   
213                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
214                          {                          {
215                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
216    
217                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
218                                  {                                  {
219                                          // FIXME: Now, just like create!                                          unsigned short title[150];
220                                          debug("SWP_SHOWWINDOW for %p!", hwnd);                                          int state;
221                                          vchannel_write("CREATE,0x%p,0x%x", hwnd, 0);                                          DWORD pid;
222                                            int flags;
223                                          // FIXME: SETSTATE  
224                                            GetWindowThreadProcessId(hwnd, &pid);
225    
226                                            flags = 0;
227                                            if (style & DS_MODALFRAME)
228                                                    flags |= SEAMLESS_CREATE_MODAL;
229    
230                                            vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
231                                                           (long) hwnd, (long) pid, (long) parent,
232                                                           flags);
233    
234                                            GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
235    
236                                            vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
237                                                           vchannel_strfilter_unicode(title), 0);
238    
239                                            if (style & WS_MAXIMIZE)
240                                                    state = 2;
241                                            else if (style & WS_MINIMIZE)
242                                                    state = 1;
243                                            else
244                                                    state = 0;
245    
246                                          update_position(hwnd);                                          update_position(hwnd);
247    
248                                            vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
249                                                           state, 0);
250                                  }                                  }
251    
252                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
253                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
254    
255                                  if (!(style & WS_VISIBLE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
256                                          break;                                          break;
257    
258                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
259                                          update_position(hwnd);                                          update_position(hwnd);
260    
                                 if (!(wp->flags & SWP_NOZORDER))  
                                 {  
                                         vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",  
                                                        hwnd,  
                                                        wp->flags & SWP_NOACTIVATE ? wp->  
                                                        hwndInsertAfter : 0, 0);  
                                 }  
   
261                                  break;                                  break;
262                          }                          }
263    
264                  case WM_SIZE:                  case WM_SIZE:
265                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
266                                  break;                                  break;
267                          update_position(hwnd);                          update_position(hwnd);
268                          break;                          break;
269    
270                  case WM_MOVE:                  case WM_MOVE:
271                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
272                                  break;                                  break;
273                          update_position(hwnd);                          update_position(hwnd);
274                          break;                          break;
# Line 143  wndproc_hook_proc(int code, WPARAM cur_t Line 276  wndproc_hook_proc(int code, WPARAM cur_t
276                  case WM_DESTROY:                  case WM_DESTROY:
277                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE))
278                                  break;                                  break;
279                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
280                          break;                          break;
281    
282                  default:                  default:
# Line 155  wndproc_hook_proc(int code, WPARAM cur_t Line 288  wndproc_hook_proc(int code, WPARAM cur_t
288  }  }
289    
290  static LRESULT CALLBACK  static LRESULT CALLBACK
291    wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
292    {
293            HWND hwnd, parent;
294            UINT msg;
295            WPARAM wparam;
296            LPARAM lparam;
297    
298            LONG style;
299    
300            if (code < 0)
301                    goto end;
302    
303            hwnd = ((CWPRETSTRUCT *) details)->hwnd;
304            msg = ((CWPRETSTRUCT *) details)->message;
305            wparam = ((CWPRETSTRUCT *) details)->wParam;
306            lparam = ((CWPRETSTRUCT *) details)->lParam;
307    
308            style = GetWindowLong(hwnd, GWL_STYLE);
309    
310            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
311               but they exist nonetheless. */
312            if ((style & WS_CHILD) && !(style & WS_POPUP))
313                    goto end;
314    
315            parent = get_parent(hwnd);
316    
317            switch (msg)
318            {
319                    case WM_WINDOWPOSCHANGED:
320                            {
321                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
322    
323                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
324                                            break;
325    
326                                    if (!(wp->flags & SWP_NOZORDER))
327                                            update_zorder(hwnd);
328    
329                                    break;
330                            }
331    
332    
333                    case WM_SETTEXT:
334                            {
335                                    unsigned short title[150];
336                                    if (!(style & WS_VISIBLE))
337                                            break;
338                                    /* We cannot use the string in lparam because
339                                       we need unicode. */
340                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
341                                    vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
342                                                   vchannel_strfilter_unicode(title), 0);
343                                    break;
344                            }
345    
346                    default:
347                            break;
348            }
349    
350            if (msg == g_wm_seamless_focus)
351            {
352                    /* FIXME: SetForegroundWindow() kills menus. Need to find a
353                       clean way to solve this. */
354                    if ((GetForegroundWindow() != hwnd) && !parent)
355                            SetForegroundWindow(hwnd);
356    
357                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
358            }
359    
360          end:
361            return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
362    }
363    
364    static LRESULT CALLBACK
365  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
366  {  {
367          if (code < 0)          if (code < 0)
# Line 164  cbt_hook_proc(int code, WPARAM wparam, L Line 371  cbt_hook_proc(int code, WPARAM wparam, L
371          {          {
372                  case HCBT_MINMAX:                  case HCBT_MINMAX:
373                          {                          {
374                                  int show, state;                                  int show, state, blocked;
375                                    HWND hwnd, blocked_hwnd;
376                                    unsigned int serial;
377                                    LONG style;
378    
379                                    WaitForSingleObject(g_mutex, INFINITE);
380                                    blocked_hwnd = g_blocked_state_hwnd;
381                                    serial = g_blocked_state_serial;
382                                    blocked = g_blocked_state;
383                                    ReleaseMutex(g_mutex);
384    
385                                    hwnd = (HWND) wparam;
386    
387                                    style = GetWindowLong(hwnd, GWL_STYLE);
388    
389                                    if (!(style & WS_VISIBLE))
390                                            break;
391    
392                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
393    
394                                  if (show == SW_SHOWNORMAL)                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
395                                        || (show == SW_RESTORE))
396                                          state = 0;                                          state = 0;
397                                  else if (show == SW_SHOWMINIMIZED)                                  else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
398                                          state = 1;                                          state = 1;
399                                  else if (show == SW_SHOWMAXIMIZED)                                  else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
400                                          state = 2;                                          state = 2;
401                                  vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);                                  else
402                                    {
403                                            debug("Unexpected show: %d", show);
404                                            break;
405                                    }
406    
407                                    if ((blocked_hwnd == hwnd) && (blocked == state))
408                                            vchannel_write("ACK", "%u", serial);
409                                    else
410                                            vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
411                                                           hwnd, state, 0);
412    
413                                  break;                                  break;
414                          }                          }
415    
# Line 194  SetHooks(void) Line 429  SetHooks(void)
429    
430          if (!g_wndproc_hook)          if (!g_wndproc_hook)
431                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
432    
433            if (!g_wndprocret_hook)
434                    g_wndprocret_hook =
435                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
436  }  }
437    
438  DLL_EXPORT void  DLL_EXPORT void
# Line 204  RemoveHooks(void) Line 443  RemoveHooks(void)
443    
444          if (g_wndproc_hook)          if (g_wndproc_hook)
445                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
446    
447            if (g_wndprocret_hook)
448                    UnhookWindowsHookEx(g_wndprocret_hook);
449    }
450    
451    DLL_EXPORT void
452    SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
453    {
454            RECT rect;
455    
456            WaitForSingleObject(g_mutex, INFINITE);
457            g_block_move_hwnd = hwnd;
458            g_block_move_serial = serial;
459            g_block_move.left = x;
460            g_block_move.top = y;
461            g_block_move.right = x + width;
462            g_block_move.bottom = y + height;
463            ReleaseMutex(g_mutex);
464    
465            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
466    
467            vchannel_write("ACK", "%u", serial);
468    
469            if (!GetWindowRect(hwnd, &rect))
470                    debug("GetWindowRect failed!\n");
471            else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
472                     || (rect.bottom != y + height))
473                    update_position(hwnd);
474    
475            WaitForSingleObject(g_mutex, INFINITE);
476            g_block_move_hwnd = NULL;
477            memset(&g_block_move, 0, sizeof(RECT));
478            ReleaseMutex(g_mutex);
479    }
480    
481    DLL_EXPORT void
482    SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
483    {
484            WaitForSingleObject(g_mutex, INFINITE);
485            g_blocked_zchange_serial = serial;
486            g_blocked_zchange[0] = hwnd;
487            g_blocked_zchange[1] = behind;
488            ReleaseMutex(g_mutex);
489    
490            if (behind == NULL)
491                    behind = HWND_TOP;
492    
493            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
494    
495            WaitForSingleObject(g_mutex, INFINITE);
496            g_blocked_zchange[0] = NULL;
497            g_blocked_zchange[1] = NULL;
498            ReleaseMutex(g_mutex);
499    }
500    
501    DLL_EXPORT void
502    SafeFocus(unsigned int serial, HWND hwnd)
503    {
504            WaitForSingleObject(g_mutex, INFINITE);
505            g_blocked_focus_serial = serial;
506            g_blocked_focus = hwnd;
507            ReleaseMutex(g_mutex);
508    
509            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
510    
511            WaitForSingleObject(g_mutex, INFINITE);
512            g_blocked_focus = NULL;
513            ReleaseMutex(g_mutex);
514    }
515    
516    DLL_EXPORT void
517    SafeSetState(unsigned int serial, HWND hwnd, int state)
518    {
519            LONG style;
520            int curstate;
521    
522            vchannel_block();
523    
524            style = GetWindowLong(hwnd, GWL_STYLE);
525    
526            if (style & WS_MAXIMIZE)
527                    curstate = 2;
528            else if (style & WS_MINIMIZE)
529                    curstate = 1;
530            else
531                    curstate = 0;
532    
533            if (state == curstate)
534            {
535                    vchannel_write("ACK", "%u", serial);
536                    vchannel_unblock();
537                    return;
538            }
539    
540            WaitForSingleObject(g_mutex, INFINITE);
541            g_blocked_state_hwnd = hwnd;
542            g_blocked_state_serial = serial;
543            g_blocked_state = state;
544            ReleaseMutex(g_mutex);
545    
546            vchannel_unblock();
547    
548            if (state == 0)
549                    ShowWindow(hwnd, SW_RESTORE);
550            else if (state == 1)
551                    ShowWindow(hwnd, SW_MINIMIZE);
552            else if (state == 2)
553                    ShowWindow(hwnd, SW_MAXIMIZE);
554            else
555                    debug("Invalid state %d sent.", state);
556    
557            WaitForSingleObject(g_mutex, INFINITE);
558            g_blocked_state_hwnd = NULL;
559            g_blocked_state = -1;
560            ReleaseMutex(g_mutex);
561  }  }
562    
563  DLL_EXPORT int  DLL_EXPORT int
# Line 229  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 583  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
583                          ++g_instance_count;                          ++g_instance_count;
584                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
585    
586                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
587    
588                          vchannel_open();                          vchannel_open();
589    
590                          break;                          break;

Legend:
Removed from v.1096  
changed lines
  Added in v.1230

  ViewVC Help
Powered by ViewVC 1.1.26