/[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 1162 by ossman_, Mon Mar 20 09:36:23 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    RECT g_block_move SHARED = { 0, 0, 0, 0 };
50    HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
51    HWND g_blocked_focus SHARED = NULL;
52    HWND g_blocked_state_hwnd SHARED = NULL;
53    int g_blocked_state SHARED = -1;
54    
55  #pragma data_seg ()  #pragma data_seg ()
56    
57  #pragma comment(linker, "/section:SHAREDDATA,rws")  #pragma comment(linker, "/section:SHAREDDATA,rws")
58    
59    #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
60    static UINT g_wm_seamless_focus;
61    
62  static HHOOK g_cbt_hook = NULL;  static HHOOK g_cbt_hook = NULL;
63  static HHOOK g_wndproc_hook = NULL;  static HHOOK g_wndproc_hook = NULL;
64    static HHOOK g_wndprocret_hook = NULL;
65    
66  static HINSTANCE g_instance = NULL;  static HINSTANCE g_instance = NULL;
67    
# Line 52  static HANDLE g_mutex = NULL; Line 70  static HANDLE g_mutex = NULL;
70  static void  static void
71  update_position(HWND hwnd)  update_position(HWND hwnd)
72  {  {
73          RECT rect;          RECT rect, blocked;
74            HWND blocked_hwnd;
75    
76          if (!GetWindowRect(hwnd, &rect))          if (!GetWindowRect(hwnd, &rect))
77          {          {
# Line 60  update_position(HWND hwnd) Line 79  update_position(HWND hwnd)
79                  return;                  return;
80          }          }
81    
82            WaitForSingleObject(g_mutex, INFINITE);
83            blocked_hwnd = hwnd;
84            memcpy(&blocked, &g_block_move, sizeof(RECT));
85            ReleaseMutex(g_mutex);
86    
87            if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
88                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
89                    return;
90    
91          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",
92                         hwnd,                         hwnd,
93                         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);
94  }  }
95    
96    static void
97    update_zorder(HWND hwnd)
98    {
99            HWND behind;
100            HWND block_hwnd, block_behind;
101    
102            WaitForSingleObject(g_mutex, INFINITE);
103            block_hwnd = g_blocked_zchange[0];
104            block_behind = g_blocked_zchange[1];
105            ReleaseMutex(g_mutex);
106    
107            behind = GetNextWindow(hwnd, GW_HWNDPREV);
108            while (behind)
109            {
110                    LONG style;
111    
112                    style = GetWindowLong(behind, GWL_STYLE);
113    
114                    if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
115                            break;
116    
117                    behind = GetNextWindow(behind, GW_HWNDPREV);
118            }
119    
120            if ((hwnd == block_hwnd) && (behind == block_behind))
121                    return;
122    
123            vchannel_write("ZCHANGE,0x%p,0x%p,0x%x", hwnd, behind, 0);
124    }
125    
126  static LRESULT CALLBACK  static LRESULT CALLBACK
127  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
128  {  {
129          HWND hwnd;          HWND hwnd, parent;
130          UINT msg;          UINT msg;
131          WPARAM wparam;          WPARAM wparam;
132          LPARAM lparam;          LPARAM lparam;
# Line 90  wndproc_hook_proc(int code, WPARAM cur_t Line 148  wndproc_hook_proc(int code, WPARAM cur_t
148          if ((style & WS_CHILD) && !(style & WS_POPUP))          if ((style & WS_CHILD) && !(style & WS_POPUP))
149                  goto end;                  goto end;
150    
151          switch (msg)          if (style & WS_POPUP)
152          {          {
153                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
154                    if (!parent)
155                            parent = (HWND) - 1;
156            }
157            else
158                    parent = NULL;
159    
160            switch (msg)
161            {
162                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
163                          {                          {
164                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
165    
166                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
167                                  {                                  {
168                                          // FIXME: Now, just like create!                                          unsigned short title[150];
169                                          debug("SWP_SHOWWINDOW for %p!", hwnd);                                          int state;
                                         vchannel_write("CREATE,0x%p,0x%x", hwnd, 0);  
170    
171                                          // FIXME: SETSTATE                                          vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);
172    
173                                            GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
174    
175                                            vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,
176                                                           vchannel_strfilter_unicode(title), 0);
177    
178                                            if (style & WS_MAXIMIZE)
179                                                    state = 2;
180                                            else if (style & WS_MINIMIZE)
181                                                    state = 1;
182                                            else
183                                                    state = 0;
184    
185                                          update_position(hwnd);                                          update_position(hwnd);
186    
187                                            vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);
188                                  }                                  }
189    
190                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
191                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
192    
193                                  if (!(style & WS_VISIBLE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
194                                          break;                                          break;
195    
196                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
197                                          update_position(hwnd);                                          update_position(hwnd);
198    
                                 if (!(wp->flags & SWP_NOZORDER))  
                                 {  
                                         vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",  
                                                        hwnd,  
                                                        wp->flags & SWP_NOACTIVATE ? wp->  
                                                        hwndInsertAfter : 0, 0);  
                                 }  
   
199                                  break;                                  break;
200                          }                          }
201    
202                  case WM_SIZE:                  case WM_SIZE:
203                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
204                                  break;                                  break;
205                          update_position(hwnd);                          update_position(hwnd);
206                          break;                          break;
207    
208                  case WM_MOVE:                  case WM_MOVE:
209                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
210                                  break;                                  break;
211                          update_position(hwnd);                          update_position(hwnd);
212                          break;                          break;
# Line 155  wndproc_hook_proc(int code, WPARAM cur_t Line 226  wndproc_hook_proc(int code, WPARAM cur_t
226  }  }
227    
228  static LRESULT CALLBACK  static LRESULT CALLBACK
229    wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
230    {
231            HWND hwnd, parent;
232            UINT msg;
233            WPARAM wparam;
234            LPARAM lparam;
235    
236            LONG style;
237    
238            if (code < 0)
239                    goto end;
240    
241            hwnd = ((CWPRETSTRUCT *) details)->hwnd;
242            msg = ((CWPRETSTRUCT *) details)->message;
243            wparam = ((CWPRETSTRUCT *) details)->wParam;
244            lparam = ((CWPRETSTRUCT *) details)->lParam;
245    
246            style = GetWindowLong(hwnd, GWL_STYLE);
247    
248            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
249               but they exist nonetheless. */
250            if ((style & WS_CHILD) && !(style & WS_POPUP))
251                    goto end;
252    
253            if (style & WS_POPUP)
254            {
255                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
256                    if (!parent)
257                            parent = (HWND) - 1;
258            }
259            else
260                    parent = NULL;
261    
262            switch (msg)
263            {
264                    case WM_WINDOWPOSCHANGED:
265                            {
266                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
267    
268                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
269                                            break;
270    
271                                    if (!(wp->flags & SWP_NOZORDER))
272                                            update_zorder(hwnd);
273    
274                                    break;
275                            }
276    
277    
278                    case WM_SETTEXT:
279                            {
280                                    unsigned short title[150];
281                                    if (!(style & WS_VISIBLE))
282                                            break;
283                                    /* We cannot use the string in lparam because
284                                       we need unicode. */
285                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
286                                    vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,
287                                                   vchannel_strfilter_unicode(title), 0);
288                                    break;
289                            }
290    
291                    default:
292                            break;
293            }
294    
295            if (msg == g_wm_seamless_focus)
296            {
297                    /* FIXME: SetActiveWindow() kills menus. Need to find a clean
298                       way to solve this. */
299                    if ((GetActiveWindow() != hwnd) && !parent)
300                            SetActiveWindow(hwnd);
301            }
302    
303          end:
304            return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
305    }
306    
307    static LRESULT CALLBACK
308  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
309  {  {
310          if (code < 0)          if (code < 0)
# Line 164  cbt_hook_proc(int code, WPARAM wparam, L Line 314  cbt_hook_proc(int code, WPARAM wparam, L
314          {          {
315                  case HCBT_MINMAX:                  case HCBT_MINMAX:
316                          {                          {
317                                  int show, state;                                  int show, state, blocked;
318                                    HWND blocked_hwnd;
319    
320                                    WaitForSingleObject(g_mutex, INFINITE);
321                                    blocked_hwnd = g_blocked_state_hwnd;
322                                    blocked = g_blocked_state;
323                                    ReleaseMutex(g_mutex);
324    
325                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
326    
327                                  if (show == SW_SHOWNORMAL)                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
328                                        || (show == SW_RESTORE))
329                                          state = 0;                                          state = 0;
330                                  else if (show == SW_SHOWMINIMIZED)                                  else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
331                                          state = 1;                                          state = 1;
332                                  else if (show == SW_SHOWMAXIMIZED)                                  else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
333                                          state = 2;                                          state = 2;
334                                  vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);                                  else
335                                    {
336                                            debug("Unexpected show: %d", show);
337                                            break;
338                                    }
339    
340                                    if ((blocked_hwnd != (HWND) wparam) || (blocked != state))
341                                            vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state,
342                                                           0);
343    
344                                  break;                                  break;
345                          }                          }
346    
# Line 194  SetHooks(void) Line 360  SetHooks(void)
360    
361          if (!g_wndproc_hook)          if (!g_wndproc_hook)
362                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
363    
364            if (!g_wndprocret_hook)
365                    g_wndprocret_hook =
366                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
367  }  }
368    
369  DLL_EXPORT void  DLL_EXPORT void
# Line 204  RemoveHooks(void) Line 374  RemoveHooks(void)
374    
375          if (g_wndproc_hook)          if (g_wndproc_hook)
376                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
377    
378            if (g_wndprocret_hook)
379                    UnhookWindowsHookEx(g_wndprocret_hook);
380    }
381    
382    DLL_EXPORT void
383    SafeMoveWindow(HWND hwnd, int x, int y, int width, int height)
384    {
385            WaitForSingleObject(g_mutex, INFINITE);
386            g_block_move_hwnd = hwnd;
387            g_block_move.left = x;
388            g_block_move.top = y;
389            g_block_move.right = x + width;
390            g_block_move.bottom = y + height;
391            ReleaseMutex(g_mutex);
392    
393            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
394    
395            WaitForSingleObject(g_mutex, INFINITE);
396            g_block_move_hwnd = NULL;
397            memset(&g_block_move, 0, sizeof(RECT));
398            ReleaseMutex(g_mutex);
399    }
400    
401    DLL_EXPORT void
402    SafeZChange(HWND hwnd, HWND behind)
403    {
404            WaitForSingleObject(g_mutex, INFINITE);
405            g_blocked_zchange[0] = hwnd;
406            g_blocked_zchange[1] = behind;
407            ReleaseMutex(g_mutex);
408    
409            if (behind == NULL)
410                    behind = HWND_TOP;
411    
412            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
413    
414            WaitForSingleObject(g_mutex, INFINITE);
415            g_blocked_zchange[0] = NULL;
416            g_blocked_zchange[1] = NULL;
417            ReleaseMutex(g_mutex);
418    }
419    
420    DLL_EXPORT void
421    SafeFocus(HWND hwnd)
422    {
423            WaitForSingleObject(g_mutex, INFINITE);
424            g_blocked_focus = hwnd;
425            ReleaseMutex(g_mutex);
426    
427            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
428    
429            WaitForSingleObject(g_mutex, INFINITE);
430            g_blocked_focus = NULL;
431            ReleaseMutex(g_mutex);
432    }
433    
434    DLL_EXPORT void
435    SafeSetState(HWND hwnd, int state)
436    {
437            WaitForSingleObject(g_mutex, INFINITE);
438            g_blocked_state_hwnd = hwnd;
439            g_blocked_state = state;
440            ReleaseMutex(g_mutex);
441    
442            if (state == 0)
443                    ShowWindow(hwnd, SW_RESTORE);
444            else if (state == 1)
445                    ShowWindow(hwnd, SW_MINIMIZE);
446            else if (state == 2)
447                    ShowWindow(hwnd, SW_MAXIMIZE);
448            else
449                    debug("Invalid state %d sent.", state);
450    
451            WaitForSingleObject(g_mutex, INFINITE);
452            g_blocked_state_hwnd = NULL;
453            g_blocked_state = -1;
454            ReleaseMutex(g_mutex);
455  }  }
456    
457  DLL_EXPORT int  DLL_EXPORT int
# Line 229  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 477  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
477                          ++g_instance_count;                          ++g_instance_count;
478                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
479    
480                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
481    
482                          vchannel_open();                          vchannel_open();
483    
484                          break;                          break;

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

  ViewVC Help
Powered by ViewVC 1.1.26