/[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 1081 by ossman_, Thu Mar 9 16:13:26 2006 UTC revision 1161 by ossman_, Fri Mar 17 16:34:46 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          vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",          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",
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  }  }
# Line 68  update_position(HWND hwnd) Line 96  update_position(HWND hwnd)
96  static LRESULT CALLBACK  static LRESULT CALLBACK
97  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
98  {  {
99          HWND hwnd;          HWND hwnd, parent;
100          UINT msg;          UINT msg;
101          WPARAM wparam;          WPARAM wparam;
102          LPARAM lparam;          LPARAM lparam;
# Line 85  wndproc_hook_proc(int code, WPARAM cur_t Line 113  wndproc_hook_proc(int code, WPARAM cur_t
113    
114          style = GetWindowLong(hwnd, GWL_STYLE);          style = GetWindowLong(hwnd, GWL_STYLE);
115    
116          if (style & WS_CHILD)          /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
117               but they exist nonetheless. */
118            if ((style & WS_CHILD) && !(style & WS_POPUP))
119                  goto end;                  goto end;
120    
121          switch (msg)          if (style & WS_POPUP)
122          {          {
123                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
124                    if (!parent)
125                            parent = (HWND) - 1;
126            }
127            else
128                    parent = NULL;
129    
130            switch (msg)
131            {
132                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
133                          {                          {
134                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
135    
136                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
137                                  {                                  {
138                                          // FIXME: Now, just like create!                                          unsigned short title[150];
139                                          debug("SWP_SHOWWINDOW for %p!", hwnd);                                          int state;
140                                          vchannel_write("CREATE1,0x%p,0x%x", hwnd, 0);  
141                                            vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);
142    
143                                          // FIXME: SETSTATE                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
144    
145                                            vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,
146                                                           vchannel_strfilter_unicode(title), 0);
147    
148                                            if (style & WS_MAXIMIZE)
149                                                    state = 2;
150                                            else if (style & WS_MINIMIZE)
151                                                    state = 1;
152                                            else
153                                                    state = 0;
154    
155                                          update_position(hwnd);                                          update_position(hwnd);
156    
157                                            vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);
158                                  }                                  }
159    
160                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
161                                          vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
162    
163                                  if (!(style & WS_VISIBLE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
164                                          break;                                          break;
165    
166                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
# Line 117  wndproc_hook_proc(int code, WPARAM cur_t Line 168  wndproc_hook_proc(int code, WPARAM cur_t
168    
169                                  if (!(wp->flags & SWP_NOZORDER))                                  if (!(wp->flags & SWP_NOZORDER))
170                                  {                                  {
171                                          vchannel_write("ZCHANGE1,0x%p,0x%p,0x%x",                                          HWND block_hwnd, block_behind;
172                                                         hwnd,                                          WaitForSingleObject(g_mutex, INFINITE);
173                                                         wp->flags & SWP_NOACTIVATE ? wp->                                          block_hwnd = g_blocked_zchange[0];
174                                                         hwndInsertAfter : 0, 0);                                          block_behind = g_blocked_zchange[1];
175                                            ReleaseMutex(g_mutex);
176    
177                                            if ((hwnd != block_hwnd)
178                                                || (wp->hwndInsertAfter != block_behind))
179                                            {
180                                                    vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",
181                                                                   hwnd,
182                                                                   wp->flags & SWP_NOACTIVATE ? wp->
183                                                                   hwndInsertAfter : 0, 0);
184                                            }
185                                  }                                  }
186    
187                                  break;                                  break;
188                          }                          }
189    
190                  case WM_SIZE:                  case WM_SIZE:
191                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
192                                    break;
193                          update_position(hwnd);                          update_position(hwnd);
194                          break;                          break;
195    
196                  case WM_MOVE:                  case WM_MOVE:
197                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
198                                    break;
199                          update_position(hwnd);                          update_position(hwnd);
200                          break;                          break;
201    
202                  case WM_DESTROY:                  case WM_DESTROY:
203                          vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                          if (!(style & WS_VISIBLE))
204                                    break;
205                            vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
206                          break;                          break;
207    
208                  default:                  default:
# Line 147  wndproc_hook_proc(int code, WPARAM cur_t Line 214  wndproc_hook_proc(int code, WPARAM cur_t
214  }  }
215    
216  static LRESULT CALLBACK  static LRESULT CALLBACK
217  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
218  {  {
219          char title[150];          HWND hwnd, parent;
220            UINT msg;
221            WPARAM wparam;
222            LPARAM lparam;
223    
224            LONG style;
225    
226            if (code < 0)
227                    goto end;
228    
229            hwnd = ((CWPRETSTRUCT *) details)->hwnd;
230            msg = ((CWPRETSTRUCT *) details)->message;
231            wparam = ((CWPRETSTRUCT *) details)->wParam;
232            lparam = ((CWPRETSTRUCT *) details)->lParam;
233    
234            style = GetWindowLong(hwnd, GWL_STYLE);
235    
236            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
237               but they exist nonetheless. */
238            if ((style & WS_CHILD) && !(style & WS_POPUP))
239                    goto end;
240    
241            if (style & WS_POPUP)
242            {
243                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
244                    if (!parent)
245                            parent = (HWND) - 1;
246            }
247            else
248                    parent = NULL;
249    
250            switch (msg)
251            {
252                    case WM_SETTEXT:
253                            {
254                                    unsigned short title[150];
255                                    if (!(style & WS_VISIBLE))
256                                            break;
257                                    /* We cannot use the string in lparam because
258                                       we need unicode. */
259                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
260                                    vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,
261                                                   vchannel_strfilter_unicode(title), 0);
262                                    break;
263                            }
264    
265                    default:
266                            break;
267            }
268    
269            if (msg == g_wm_seamless_focus)
270            {
271                    /* FIXME: SetActiveWindow() kills menus. Need to find a clean
272                       way to solve this. */
273                    if ((GetActiveWindow() != hwnd) && !parent)
274                            SetActiveWindow(hwnd);
275            }
276    
277          end:
278            return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
279    }
280    
281    static LRESULT CALLBACK
282    cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
283    {
284          if (code < 0)          if (code < 0)
285                  goto end;                  goto end;
286    
# Line 158  cbt_hook_proc(int code, WPARAM wparam, L Line 288  cbt_hook_proc(int code, WPARAM wparam, L
288          {          {
289                  case HCBT_MINMAX:                  case HCBT_MINMAX:
290                          {                          {
291                                  int show, state;                                  int show, state, blocked;
292                                    HWND blocked_hwnd;
293    
294                                    WaitForSingleObject(g_mutex, INFINITE);
295                                    blocked_hwnd = g_blocked_state_hwnd;
296                                    blocked = g_blocked_state;
297                                    ReleaseMutex(g_mutex);
298    
299                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
300    
301                                  if ((show == SW_SHOWMINIMIZED) || (show == SW_MINIMIZE))                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
302                                        || (show == SW_RESTORE))
303                                            state = 0;
304                                    else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
305                                            state = 1;
306                                    else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
307                                            state = 2;
308                                    else
309                                  {                                  {
310                                          MessageBox(0,                                          debug("Unexpected show: %d", show);
311                                                     "Minimizing windows is not allowed in this version. Sorry!",                                          break;
                                                    "SeamlessRDP", MB_OK);  
                                         return 1;  
312                                  }                                  }
313    
314                                  GetWindowText((HWND) wparam, title, sizeof(title));                                  if ((blocked_hwnd != (HWND) wparam) || (blocked != state))
315                                            vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state,
316                                  /* FIXME: Strip title of dangerous characters */                                                         0);
317    
                                 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);  
318                                  break;                                  break;
319                          }                          }
320    
# Line 201  SetHooks(void) Line 334  SetHooks(void)
334    
335          if (!g_wndproc_hook)          if (!g_wndproc_hook)
336                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
337    
338            if (!g_wndprocret_hook)
339                    g_wndprocret_hook =
340                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
341  }  }
342    
343  DLL_EXPORT void  DLL_EXPORT void
# Line 211  RemoveHooks(void) Line 348  RemoveHooks(void)
348    
349          if (g_wndproc_hook)          if (g_wndproc_hook)
350                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
351    
352            if (g_wndprocret_hook)
353                    UnhookWindowsHookEx(g_wndprocret_hook);
354    }
355    
356    DLL_EXPORT void
357    SafeMoveWindow(HWND hwnd, int x, int y, int width, int height)
358    {
359            WaitForSingleObject(g_mutex, INFINITE);
360            g_block_move_hwnd = hwnd;
361            g_block_move.left = x;
362            g_block_move.top = y;
363            g_block_move.right = x + width;
364            g_block_move.bottom = y + height;
365            ReleaseMutex(g_mutex);
366    
367            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
368    
369            WaitForSingleObject(g_mutex, INFINITE);
370            g_block_move_hwnd = NULL;
371            memset(&g_block_move, 0, sizeof(RECT));
372            ReleaseMutex(g_mutex);
373    }
374    
375    DLL_EXPORT void
376    SafeZChange(HWND hwnd, HWND behind)
377    {
378            if (behind == NULL)
379                    behind = HWND_TOP;
380    
381            WaitForSingleObject(g_mutex, INFINITE);
382            g_blocked_zchange[0] = hwnd;
383            g_blocked_zchange[1] = behind;
384            ReleaseMutex(g_mutex);
385    
386            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
387    
388            WaitForSingleObject(g_mutex, INFINITE);
389            g_blocked_zchange[0] = NULL;
390            g_blocked_zchange[1] = NULL;
391            ReleaseMutex(g_mutex);
392    }
393    
394    DLL_EXPORT void
395    SafeFocus(HWND hwnd)
396    {
397            WaitForSingleObject(g_mutex, INFINITE);
398            g_blocked_focus = hwnd;
399            ReleaseMutex(g_mutex);
400    
401            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
402    
403            WaitForSingleObject(g_mutex, INFINITE);
404            g_blocked_focus = NULL;
405            ReleaseMutex(g_mutex);
406    }
407    
408    DLL_EXPORT void
409    SafeSetState(HWND hwnd, int state)
410    {
411            WaitForSingleObject(g_mutex, INFINITE);
412            g_blocked_state_hwnd = hwnd;
413            g_blocked_state = state;
414            ReleaseMutex(g_mutex);
415    
416            if (state == 0)
417                    ShowWindow(hwnd, SW_RESTORE);
418            else if (state == 1)
419                    ShowWindow(hwnd, SW_MINIMIZE);
420            else if (state == 2)
421                    ShowWindow(hwnd, SW_MAXIMIZE);
422            else
423                    debug("Invalid state %d sent.", state);
424    
425            WaitForSingleObject(g_mutex, INFINITE);
426            g_blocked_state_hwnd = NULL;
427            g_blocked_state = -1;
428            ReleaseMutex(g_mutex);
429  }  }
430    
431  DLL_EXPORT int  DLL_EXPORT int
# Line 236  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 451  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
451                          ++g_instance_count;                          ++g_instance_count;
452                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
453    
454                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
455    
456                          vchannel_open();                          vchannel_open();
457    
458                          break;                          break;

Legend:
Removed from v.1081  
changed lines
  Added in v.1161

  ViewVC Help
Powered by ViewVC 1.1.26