/[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 1080 by ossman_, Thu Mar 9 15:57:10 2006 UTC revision 1177 by ossman_, Tue Mar 21 14:42:25 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    
75  static HANDLE g_mutex = NULL;  static HANDLE g_mutex = NULL;
76    
77    static void
78    update_position(HWND hwnd)
79    {
80            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))
93            {
94                    debug("GetWindowRect failed!\n");
95                    goto end;
96            }
97    
98            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%p,%d,%d,%d,%d,0x%x",
103                           hwnd,
104                           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%p,0x%p,0x%x", hwnd, behind, 0);
142    
143            vchannel_unblock();
144    }
145    
146  static LRESULT CALLBACK  static LRESULT CALLBACK
147  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
148  {  {
149          HWND hwnd;          HWND hwnd, parent;
150          UINT msg;          UINT msg;
151          WPARAM wparam;          WPARAM wparam;
152          LPARAM lparam;          LPARAM lparam;
# Line 69  wndproc_hook_proc(int code, WPARAM cur_t Line 163  wndproc_hook_proc(int code, WPARAM cur_t
163    
164          style = GetWindowLong(hwnd, GWL_STYLE);          style = GetWindowLong(hwnd, GWL_STYLE);
165    
166          if (style & WS_CHILD)          /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
167               but they exist nonetheless. */
168            if ((style & WS_CHILD) && !(style & WS_POPUP))
169                  goto end;                  goto end;
170    
171          switch (msg)          if (style & WS_POPUP)
172          {          {
173                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
174                    if (!parent)
175                            parent = (HWND) - 1;
176            }
177            else
178                    parent = NULL;
179    
180            switch (msg)
181            {
182                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
183                          {                          {
                                 RECT rect;  
184                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
185    
186                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
187                                  {                                  {
188                                          // FIXME: Now, just like create!                                          unsigned short title[150];
189                                          debug("SWP_SHOWWINDOW for %p!", hwnd);                                          int state;
190                                          vchannel_write("CREATE1,0x%p,0x%x", hwnd, 0);                                          DWORD pid;
191                                            int flags;
192                                          // FIXME: SETSTATE  
193                                            GetWindowThreadProcessId(hwnd, &pid);
194                                          if (!GetWindowRect(hwnd, &rect))  
195                                          {                                          flags = 0;
196                                                  debug("GetWindowRect failed!\n");                                          if (style & DS_MODALFRAME)
197                                                  break;                                                  flags |= SEAMLESS_CREATE_MODAL;
198                                          }  
199                                          vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",                                          vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
200                                                         hwnd,                                                         (long) hwnd, (long) pid, (long) parent,
201                                                         rect.left, rect.top,                                                         flags);
202                                                         rect.right - rect.left,  
203                                                         rect.bottom - rect.top, 0);                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
204    
205                                            vchannel_write("TITLE", "0x%x,%s,0x%x", hwnd,
206                                                           vchannel_strfilter_unicode(title), 0);
207    
208                                            if (style & WS_MAXIMIZE)
209                                                    state = 2;
210                                            else if (style & WS_MINIMIZE)
211                                                    state = 1;
212                                            else
213                                                    state = 0;
214    
215                                            update_position(hwnd);
216    
217                                            vchannel_write("STATE", "0x%p,0x%x,0x%x", hwnd, state, 0);
218                                  }                                  }
219    
220                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
221                                          vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY", "0x%p,0x%x", hwnd, 0);
222    
223                                  if (!(style & WS_VISIBLE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
224                                          break;                                          break;
225    
226                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
227                                  {                                          update_position(hwnd);
                                         if (!GetWindowRect(hwnd, &rect))  
                                         {  
                                                 debug("GetWindowRect failed!\n");  
                                                 break;  
                                         }  
   
                                         vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",  
                                                        hwnd,  
                                                        rect.left, rect.top,  
                                                        rect.right - rect.left,  
                                                        rect.bottom - rect.top, 0);  
                                 }  
   
                                 if (!(wp->flags & SWP_NOZORDER))  
                                 {  
                                         vchannel_write("ZCHANGE1,0x%p,0x%p,0x%x",  
                                                        hwnd,  
                                                        wp->flags & SWP_NOACTIVATE ? wp->  
                                                        hwndInsertAfter : 0, 0);  
                                 }  
228    
229                                  break;                                  break;
230                          }                          }
231    
232                    case WM_SIZE:
233                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
234                                    break;
235                            update_position(hwnd);
236                            break;
237    
238                    case WM_MOVE:
239                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
240                                    break;
241                            update_position(hwnd);
242                            break;
243    
244                  case WM_DESTROY:                  case WM_DESTROY:
245                          vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                          if (!(style & WS_VISIBLE))
246                                    break;
247                            vchannel_write("DESTROY", "0x%p,0x%x", hwnd, 0);
248                          break;                          break;
249    
250                  default:                  default:
# Line 145  wndproc_hook_proc(int code, WPARAM cur_t Line 256  wndproc_hook_proc(int code, WPARAM cur_t
256  }  }
257    
258  static LRESULT CALLBACK  static LRESULT CALLBACK
259  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
260  {  {
261          char title[150];          HWND hwnd, parent;
262            UINT msg;
263            WPARAM wparam;
264            LPARAM lparam;
265    
266            LONG style;
267    
268          if (code < 0)          if (code < 0)
269                  goto end;                  goto end;
270    
271            hwnd = ((CWPRETSTRUCT *) details)->hwnd;
272            msg = ((CWPRETSTRUCT *) details)->message;
273            wparam = ((CWPRETSTRUCT *) details)->wParam;
274            lparam = ((CWPRETSTRUCT *) details)->lParam;
275    
276            style = GetWindowLong(hwnd, GWL_STYLE);
277    
278            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
279               but they exist nonetheless. */
280            if ((style & WS_CHILD) && !(style & WS_POPUP))
281                    goto end;
282    
283            if (style & WS_POPUP)
284            {
285                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
286                    if (!parent)
287                            parent = (HWND) - 1;
288            }
289            else
290                    parent = NULL;
291    
292            switch (msg)
293            {
294                    case WM_WINDOWPOSCHANGED:
295                            {
296                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
297    
298                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
299                                            break;
300    
301                                    if (!(wp->flags & SWP_NOZORDER))
302                                            update_zorder(hwnd);
303    
304                                    break;
305                            }
306    
307    
308                    case WM_SETTEXT:
309                            {
310                                    unsigned short title[150];
311                                    if (!(style & WS_VISIBLE))
312                                            break;
313                                    /* We cannot use the string in lparam because
314                                       we need unicode. */
315                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
316                                    vchannel_write("TITLE", "0x%p,%s,0x%x", hwnd,
317                                                   vchannel_strfilter_unicode(title), 0);
318                                    break;
319                            }
320    
321                    default:
322                            break;
323            }
324    
325            if (msg == g_wm_seamless_focus)
326            {
327                    /* FIXME: SetActiveWindow() kills menus. Need to find a clean
328                       way to solve this. */
329                    if ((GetActiveWindow() != hwnd) && !parent)
330                            SetActiveWindow(hwnd);
331    
332                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
333            }
334    
335          end:
336            return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
337    }
338    
339    static LRESULT CALLBACK
340    cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
341    {
342            if (code < 0)
343                    goto end;
344    
345          switch (code)          switch (code)
346          {          {
347                  case HCBT_MINMAX:                  case HCBT_MINMAX:
348                          {                          {
349                                  int show, state;                                  int show, state, blocked;
350                                    HWND blocked_hwnd;
351                                    unsigned int serial;
352    
353                                    WaitForSingleObject(g_mutex, INFINITE);
354                                    blocked_hwnd = g_blocked_state_hwnd;
355                                    serial = g_blocked_state_serial;
356                                    blocked = g_blocked_state;
357                                    ReleaseMutex(g_mutex);
358    
359                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
360    
361                                  if ((show == SW_SHOWMINIMIZED) || (show == SW_MINIMIZE))                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
362                                        || (show == SW_RESTORE))
363                                            state = 0;
364                                    else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
365                                            state = 1;
366                                    else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
367                                            state = 2;
368                                    else
369                                  {                                  {
370                                          MessageBox(0,                                          debug("Unexpected show: %d", show);
371                                                     "Minimizing windows is not allowed in this version. Sorry!",                                          break;
                                                    "SeamlessRDP", MB_OK);  
                                         return 1;  
372                                  }                                  }
373    
374                                  GetWindowText((HWND) wparam, title, sizeof(title));                                  if ((blocked_hwnd == (HWND) wparam) && (blocked == state))
375                                            vchannel_write("ACK", "%u", serial);
376                                  /* FIXME: Strip title of dangerous characters */                                  else
377                                            vchannel_write("STATE", "0x%p,0x%x,0x%x", (HWND) wparam,
378                                                           state, 0);
379    
                                 if (show == SW_SHOWNORMAL)  
                                         state = 0;  
                                 else if (show == SW_SHOWMINIMIZED)  
                                         state = 1;  
                                 else if (show == SW_SHOWMAXIMIZED)  
                                         state = 2;  
                                 vchannel_write("SETSTATE1,0x%p,%s,0x%x,0x%x",  
                                                (HWND) wparam, title, state, 0);  
380                                  break;                                  break;
381                          }                          }
382    
# Line 199  SetHooks(void) Line 396  SetHooks(void)
396    
397          if (!g_wndproc_hook)          if (!g_wndproc_hook)
398                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
399    
400            if (!g_wndprocret_hook)
401                    g_wndprocret_hook =
402                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
403  }  }
404    
405  DLL_EXPORT void  DLL_EXPORT void
# Line 209  RemoveHooks(void) Line 410  RemoveHooks(void)
410    
411          if (g_wndproc_hook)          if (g_wndproc_hook)
412                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
413    
414            if (g_wndprocret_hook)
415                    UnhookWindowsHookEx(g_wndprocret_hook);
416    }
417    
418    DLL_EXPORT void
419    SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
420    {
421            RECT rect;
422    
423            WaitForSingleObject(g_mutex, INFINITE);
424            g_block_move_hwnd = hwnd;
425            g_block_move_serial = serial;
426            g_block_move.left = x;
427            g_block_move.top = y;
428            g_block_move.right = x + width;
429            g_block_move.bottom = y + height;
430            ReleaseMutex(g_mutex);
431    
432            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
433    
434            vchannel_write("ACK", "%u", serial);
435    
436            if (!GetWindowRect(hwnd, &rect))
437                    debug("GetWindowRect failed!\n");
438            else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
439                     || (rect.bottom != y + height))
440                    update_position(hwnd);
441    
442            WaitForSingleObject(g_mutex, INFINITE);
443            g_block_move_hwnd = NULL;
444            memset(&g_block_move, 0, sizeof(RECT));
445            ReleaseMutex(g_mutex);
446    }
447    
448    DLL_EXPORT void
449    SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
450    {
451            WaitForSingleObject(g_mutex, INFINITE);
452            g_blocked_zchange_serial = serial;
453            g_blocked_zchange[0] = hwnd;
454            g_blocked_zchange[1] = behind;
455            ReleaseMutex(g_mutex);
456    
457            if (behind == NULL)
458                    behind = HWND_TOP;
459    
460            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
461    
462            WaitForSingleObject(g_mutex, INFINITE);
463            g_blocked_zchange[0] = NULL;
464            g_blocked_zchange[1] = NULL;
465            ReleaseMutex(g_mutex);
466    }
467    
468    DLL_EXPORT void
469    SafeFocus(unsigned int serial, HWND hwnd)
470    {
471            WaitForSingleObject(g_mutex, INFINITE);
472            g_blocked_focus_serial = serial;
473            g_blocked_focus = hwnd;
474            ReleaseMutex(g_mutex);
475    
476            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
477    
478            WaitForSingleObject(g_mutex, INFINITE);
479            g_blocked_focus = NULL;
480            ReleaseMutex(g_mutex);
481    }
482    
483    DLL_EXPORT void
484    SafeSetState(unsigned int serial, HWND hwnd, int state)
485    {
486            LONG style;
487            int curstate;
488    
489            vchannel_block();
490    
491            style = GetWindowLong(hwnd, GWL_STYLE);
492    
493            if (style & WS_MAXIMIZE)
494                    curstate = 2;
495            else if (style & WS_MINIMIZE)
496                    curstate = 1;
497            else
498                    curstate = 0;
499    
500            if (state == curstate)
501            {
502                    vchannel_write("ACK", "%u", serial);
503                    vchannel_unblock();
504                    return;
505            }
506    
507            WaitForSingleObject(g_mutex, INFINITE);
508            g_blocked_state_hwnd = hwnd;
509            g_blocked_state_serial = serial;
510            g_blocked_state = state;
511            ReleaseMutex(g_mutex);
512    
513            vchannel_unblock();
514    
515            if (state == 0)
516                    ShowWindow(hwnd, SW_RESTORE);
517            else if (state == 1)
518                    ShowWindow(hwnd, SW_MINIMIZE);
519            else if (state == 2)
520                    ShowWindow(hwnd, SW_MAXIMIZE);
521            else
522                    debug("Invalid state %d sent.", state);
523    
524            WaitForSingleObject(g_mutex, INFINITE);
525            g_blocked_state_hwnd = NULL;
526            g_blocked_state = -1;
527            ReleaseMutex(g_mutex);
528  }  }
529    
530  DLL_EXPORT int  DLL_EXPORT int
# Line 234  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 550  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
550                          ++g_instance_count;                          ++g_instance_count;
551                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
552    
553                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
554    
555                          vchannel_open();                          vchannel_open();
556    
557                          break;                          break;

Legend:
Removed from v.1080  
changed lines
  Added in v.1177

  ViewVC Help
Powered by ViewVC 1.1.26