/[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 1073 by ossman_, Thu Mar 9 12:26:31 2006 UTC revision 1165 by ossman_, Mon Mar 20 12:28:03 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            if (!GetWindowRect(hwnd, &rect))
85            {
86                    debug("GetWindowRect failed!\n");
87                    return;
88            }
89    
90            WaitForSingleObject(g_mutex, INFINITE);
91            blocked_hwnd = g_block_move_hwnd;
92            serial = g_block_move_serial;
93            memcpy(&blocked, &g_block_move, sizeof(RECT));
94            ReleaseMutex(g_mutex);
95    
96            if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
97                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
98                    vchannel_write("ACK", "%u", serial);
99            else
100                    vchannel_write("POSITION", "0x%p,%d,%d,%d,%d,0x%x",
101                                   hwnd,
102                                   rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
103                                   0);
104    }
105    
106    static void
107    update_zorder(HWND hwnd)
108    {
109            HWND behind;
110            HWND block_hwnd, block_behind;
111            unsigned int serial;
112    
113            WaitForSingleObject(g_mutex, INFINITE);
114            serial = g_blocked_zchange_serial;
115            block_hwnd = g_blocked_zchange[0];
116            block_behind = g_blocked_zchange[1];
117            ReleaseMutex(g_mutex);
118    
119            behind = GetNextWindow(hwnd, GW_HWNDPREV);
120            while (behind)
121            {
122                    LONG style;
123    
124                    style = GetWindowLong(behind, GWL_STYLE);
125    
126                    if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
127                            break;
128    
129                    behind = GetNextWindow(behind, GW_HWNDPREV);
130            }
131    
132            if ((hwnd == block_hwnd) && (behind == block_behind))
133                    vchannel_write("ACK", "%u", serial);
134            else
135                    vchannel_write("ZCHANGE", "0x%p,0x%p,0x%x", hwnd, behind, 0);
136    }
137    
138  static LRESULT CALLBACK  static LRESULT CALLBACK
139  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
140  {  {
141          HWND hwnd = ((CWPSTRUCT *) details)->hwnd;          HWND hwnd, parent;
142          UINT msg = ((CWPSTRUCT *) details)->message;          UINT msg;
143          WPARAM wparam = ((CWPSTRUCT *) details)->wParam;          WPARAM wparam;
144          LPARAM lparam = ((CWPSTRUCT *) details)->lParam;          LPARAM lparam;
145    
146          LONG style = GetWindowLong(hwnd, GWL_STYLE);          LONG style;
         WINDOWPOS *wp = (WINDOWPOS *) lparam;  
         RECT rect;  
147    
148          if (code < 0)          if (code < 0)
149                  goto end;                  goto end;
150    
151          switch (msg)          hwnd = ((CWPSTRUCT *) details)->hwnd;
152            msg = ((CWPSTRUCT *) details)->message;
153            wparam = ((CWPSTRUCT *) details)->wParam;
154            lparam = ((CWPSTRUCT *) details)->lParam;
155    
156            style = GetWindowLong(hwnd, GWL_STYLE);
157    
158            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
159               but they exist nonetheless. */
160            if ((style & WS_CHILD) && !(style & WS_POPUP))
161                    goto end;
162    
163            if (style & WS_POPUP)
164          {          {
165                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
166                    if (!parent)
167                            parent = (HWND) - 1;
168            }
169            else
170                    parent = NULL;
171    
172            switch (msg)
173            {
174                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
175                          if (style & WS_CHILD)                          {
176                                  break;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
177    
178                                    if (wp->flags & SWP_SHOWWINDOW)
179                                    {
180                                            unsigned short title[150];
181                                            int state;
182    
183                          if (wp->flags & SWP_SHOWWINDOW)                                          vchannel_write("CREATE", "0x%p,0x%p,0x%x", hwnd, parent, 0);
                         {  
                                 // FIXME: Now, just like create!  
                                 debug("SWP_SHOWWINDOW for %p!", hwnd);  
                                 vchannel_write("CREATE1,0x%p,0x%x", hwnd, 0);  
184    
185                                  // FIXME: SETSTATE                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
186    
187                                  if (!GetWindowRect(hwnd, &rect))                                          vchannel_write("TITLE", "0x%x,%s,0x%x", hwnd,
188                                  {                                                         vchannel_strfilter_unicode(title), 0);
189                                          debug("GetWindowRect failed!\n");  
190                                          break;                                          if (style & WS_MAXIMIZE)
191                                                    state = 2;
192                                            else if (style & WS_MINIMIZE)
193                                                    state = 1;
194                                            else
195                                                    state = 0;
196    
197                                            update_position(hwnd);
198    
199                                            vchannel_write("STATE", "0x%p,0x%x,0x%x", hwnd, state, 0);
200                                  }                                  }
                                 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);  
                         }  
201    
202                                    if (wp->flags & SWP_HIDEWINDOW)
203                                            vchannel_write("DESTROY", "0x%p,0x%x", hwnd, 0);
204    
205                          if (wp->flags & SWP_HIDEWINDOW)                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
206                                  vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                                          break;
207    
208                                    if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
209                                            update_position(hwnd);
210    
                         if (!(style & WS_VISIBLE))  
211                                  break;                                  break;
212                            }
213    
214                          if (wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE)                  case WM_SIZE:
215                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
216                                  break;                                  break;
217                            update_position(hwnd);
218                            break;
219    
220                          if (!GetWindowRect(hwnd, &rect))                  case WM_MOVE:
221                          {                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
                                 debug("GetWindowRect failed!\n");  
222                                  break;                                  break;
223                          }                          update_position(hwnd);
224                            break;
225    
226                          vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",                  case WM_DESTROY:
227                                         hwnd,                          if (!(style & WS_VISIBLE))
228                                         rect.left, rect.top,                                  break;
229                                         rect.right - rect.left, rect.bottom - rect.top, 0);                          vchannel_write("DESTROY", "0x%p,0x%x", hwnd, 0);
230                            break;
231    
232                    default:
233                          break;                          break;
234            }
235    
236          end:
237            return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
238    }
239    
240                          /* Note: WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED are  static LRESULT CALLBACK
241                             strange. Sometimes, for example when bringing up the  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
242                             Notepad About dialog, only an WM_WINDOWPOSCHANGING is  {
243                             sent. In some other cases, for exmaple when opening          HWND hwnd, parent;
244                             Format->Text in Notepad, both events are sent. Also, for          UINT msg;
245                             some reason, when closing the Notepad About dialog, an          WPARAM wparam;
246                             WM_WINDOWPOSCHANGING event is sent which looks just like          LPARAM lparam;
                            the event that was sent when the About dialog was opened...  */  
                 case WM_WINDOWPOSCHANGING:  
                         if (style & WS_CHILD)  
                                 break;  
247    
248                          if (!(style & WS_VISIBLE))          LONG style;
249                                  break;  
250            if (code < 0)
251                    goto end;
252    
253                          if (!(wp->flags & SWP_NOZORDER))          hwnd = ((CWPRETSTRUCT *) details)->hwnd;
254                                  vchannel_write("ZCHANGE1,0x%p,0x%p,0x%x",          msg = ((CWPRETSTRUCT *) details)->message;
255                                                 hwnd,          wparam = ((CWPRETSTRUCT *) details)->wParam;
256                                                 wp->flags & SWP_NOACTIVATE ? wp->hwndInsertAfter : 0,          lparam = ((CWPRETSTRUCT *) details)->lParam;
257                                                 0);  
258            style = GetWindowLong(hwnd, GWL_STYLE);
259    
260            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
261               but they exist nonetheless. */
262            if ((style & WS_CHILD) && !(style & WS_POPUP))
263                    goto end;
264    
265                          break;          if (style & WS_POPUP)
266            {
267                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
268                    if (!parent)
269                            parent = (HWND) - 1;
270            }
271            else
272                    parent = NULL;
273    
274            switch (msg)
275            {
276                    case WM_WINDOWPOSCHANGED:
277                            {
278                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
279    
280                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
281                                            break;
282    
283                                    if (!(wp->flags & SWP_NOZORDER))
284                                            update_zorder(hwnd);
285    
                 case WM_DESTROY:  
                         if (style & WS_CHILD)  
286                                  break;                                  break;
287                            }
288    
                         vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);  
   
                         break;  
289    
290                    case WM_SETTEXT:
291                            {
292                                    unsigned short title[150];
293                                    if (!(style & WS_VISIBLE))
294                                            break;
295                                    /* We cannot use the string in lparam because
296                                       we need unicode. */
297                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
298                                    vchannel_write("TITLE", "0x%p,%s,0x%x", hwnd,
299                                                   vchannel_strfilter_unicode(title), 0);
300                                    break;
301                            }
302    
303                  default:                  default:
304                          break;                          break;
305          }          }
306    
307            if (msg == g_wm_seamless_focus)
308            {
309                    /* FIXME: SetActiveWindow() kills menus. Need to find a clean
310                       way to solve this. */
311                    if ((GetActiveWindow() != hwnd) && !parent)
312                            SetActiveWindow(hwnd);
313    
314                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
315            }
316    
317        end:        end:
318          return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);          return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
319  }  }
320    
321  static LRESULT CALLBACK  static LRESULT CALLBACK
322  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
323  {  {
         char title[150];  
   
324          if (code < 0)          if (code < 0)
325                  goto end;                  goto end;
326    
# Line 171  cbt_hook_proc(int code, WPARAM wparam, L Line 328  cbt_hook_proc(int code, WPARAM wparam, L
328          {          {
329                  case HCBT_MINMAX:                  case HCBT_MINMAX:
330                          {                          {
331                                  int show;                                  int show, state, blocked;
332                                    HWND blocked_hwnd;
333                                    unsigned int serial;
334    
335                                    WaitForSingleObject(g_mutex, INFINITE);
336                                    blocked_hwnd = g_blocked_state_hwnd;
337                                    serial = g_blocked_state_serial;
338                                    blocked = g_blocked_state;
339                                    ReleaseMutex(g_mutex);
340    
341                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
342    
343                                  if ((show == SW_SHOWMINIMIZED) || (show == SW_MINIMIZE))                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
344                                        || (show == SW_RESTORE))
345                                            state = 0;
346                                    else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
347                                            state = 1;
348                                    else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
349                                            state = 2;
350                                    else
351                                  {                                  {
352                                          MessageBox(0,                                          debug("Unexpected show: %d", show);
353                                                     "Minimizing windows is not allowed in this version. Sorry!",                                          break;
                                                    "SeamlessRDP", MB_OK);  
                                         return 1;  
354                                  }                                  }
355    
356                                  GetWindowText((HWND) wparam, title, sizeof(title));                                  if ((blocked_hwnd == (HWND) wparam) && (blocked == state))
357                                            vchannel_write("ACK", "%u", serial);
358                                  /* FIXME: Strip title of dangerous characters */                                  else
359                                            vchannel_write("STATE", "0x%p,0x%x,0x%x", (HWND) wparam,
360                                                           state, 0);
361    
                                 vchannel_write("SETSTATE1,0x%p,%s,0x%x,0x%x",  
                                                (HWND) wparam, title, show, 0);  
362                                  break;                                  break;
363                          }                          }
364    
# Line 208  SetHooks(void) Line 378  SetHooks(void)
378    
379          if (!g_wndproc_hook)          if (!g_wndproc_hook)
380                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
381    
382            if (!g_wndprocret_hook)
383                    g_wndprocret_hook =
384                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
385  }  }
386    
387  DLL_EXPORT void  DLL_EXPORT void
# Line 218  RemoveHooks(void) Line 392  RemoveHooks(void)
392    
393          if (g_wndproc_hook)          if (g_wndproc_hook)
394                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
395    
396            if (g_wndprocret_hook)
397                    UnhookWindowsHookEx(g_wndprocret_hook);
398    }
399    
400    DLL_EXPORT void
401    SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
402    {
403            RECT rect;
404    
405            vchannel_block();
406    
407            if (!GetWindowRect(hwnd, &rect))
408            {
409                    vchannel_unblock();
410                    debug("GetWindowRect failed!\n");
411                    return;
412            }
413    
414            if ((rect.left == x) && (rect.top == y) && (rect.right == x + width)
415                && (rect.bottom == y + height))
416            {
417                    vchannel_write("ACK", "%u", serial);
418                    vchannel_unblock();
419            }
420    
421            WaitForSingleObject(g_mutex, INFINITE);
422            g_block_move_hwnd = hwnd;
423            g_block_move_serial = serial;
424            g_block_move.left = x;
425            g_block_move.top = y;
426            g_block_move.right = x + width;
427            g_block_move.bottom = y + height;
428            ReleaseMutex(g_mutex);
429    
430            vchannel_unblock();
431    
432            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
433    
434            WaitForSingleObject(g_mutex, INFINITE);
435            g_block_move_hwnd = NULL;
436            memset(&g_block_move, 0, sizeof(RECT));
437            ReleaseMutex(g_mutex);
438    }
439    
440    DLL_EXPORT void
441    SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
442    {
443            WaitForSingleObject(g_mutex, INFINITE);
444            g_blocked_zchange_serial = serial;
445            g_blocked_zchange[0] = hwnd;
446            g_blocked_zchange[1] = behind;
447            ReleaseMutex(g_mutex);
448    
449            if (behind == NULL)
450                    behind = HWND_TOP;
451    
452            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
453    
454            WaitForSingleObject(g_mutex, INFINITE);
455            g_blocked_zchange[0] = NULL;
456            g_blocked_zchange[1] = NULL;
457            ReleaseMutex(g_mutex);
458    }
459    
460    DLL_EXPORT void
461    SafeFocus(unsigned int serial, HWND hwnd)
462    {
463            WaitForSingleObject(g_mutex, INFINITE);
464            g_blocked_focus_serial = serial;
465            g_blocked_focus = hwnd;
466            ReleaseMutex(g_mutex);
467    
468            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
469    
470            WaitForSingleObject(g_mutex, INFINITE);
471            g_blocked_focus = NULL;
472            ReleaseMutex(g_mutex);
473    }
474    
475    DLL_EXPORT void
476    SafeSetState(unsigned int serial, HWND hwnd, int state)
477    {
478            LONG style;
479            int curstate;
480    
481            vchannel_block();
482    
483            style = GetWindowLong(hwnd, GWL_STYLE);
484    
485            if (style & WS_MAXIMIZE)
486                    curstate = 2;
487            else if (style & WS_MINIMIZE)
488                    curstate = 1;
489            else
490                    curstate = 0;
491    
492            if (state == curstate)
493            {
494                    vchannel_write("ACK", "%u", serial);
495                    vchannel_unblock();
496            }
497    
498            WaitForSingleObject(g_mutex, INFINITE);
499            g_blocked_state_hwnd = hwnd;
500            g_blocked_state_serial = serial;
501            g_blocked_state = state;
502            ReleaseMutex(g_mutex);
503    
504            vchannel_unblock();
505    
506            if (state == 0)
507                    ShowWindow(hwnd, SW_RESTORE);
508            else if (state == 1)
509                    ShowWindow(hwnd, SW_MINIMIZE);
510            else if (state == 2)
511                    ShowWindow(hwnd, SW_MAXIMIZE);
512            else
513                    debug("Invalid state %d sent.", state);
514    
515            WaitForSingleObject(g_mutex, INFINITE);
516            g_blocked_state_hwnd = NULL;
517            g_blocked_state = -1;
518            ReleaseMutex(g_mutex);
519  }  }
520    
521  DLL_EXPORT int  DLL_EXPORT int
# Line 243  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 541  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
541                          ++g_instance_count;                          ++g_instance_count;
542                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
543    
544                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
545    
546                          vchannel_open();                          vchannel_open();
547    
548                          break;                          break;

Legend:
Removed from v.1073  
changed lines
  Added in v.1165

  ViewVC Help
Powered by ViewVC 1.1.26