/[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 1160 by ossman_, Fri Mar 17 16:23:08 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    RECT g_block_move SHARED = { 0, 0, 0, 0 };
49    HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
50    HWND g_blocked_focus SHARED = NULL;
51    int g_blocked_state SHARED = -1;
52    
53  #pragma data_seg ()  #pragma data_seg ()
54    
55  #pragma comment(linker, "/section:SHAREDDATA,rws")  #pragma comment(linker, "/section:SHAREDDATA,rws")
56    
57    #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
58    static UINT g_wm_seamless_focus;
59    
60  static HHOOK g_cbt_hook = NULL;  static HHOOK g_cbt_hook = NULL;
61  static HHOOK g_wndproc_hook = NULL;  static HHOOK g_wndproc_hook = NULL;
62    static HHOOK g_wndprocret_hook = NULL;
63    
64  static HINSTANCE g_instance = NULL;  static HINSTANCE g_instance = NULL;
65    
66  static HANDLE g_mutex = NULL;  static HANDLE g_mutex = NULL;
67    
68    static void
69    update_position(HWND hwnd)
70    {
71            RECT rect, blocked;
72    
73            if (!GetWindowRect(hwnd, &rect))
74            {
75                    debug("GetWindowRect failed!\n");
76                    return;
77            }
78    
79            WaitForSingleObject(g_mutex, INFINITE);
80            memcpy(&blocked, &g_block_move, sizeof(RECT));
81            ReleaseMutex(g_mutex);
82    
83            if ((rect.left == blocked.left) && (rect.top == blocked.top)
84                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
85                    return;
86    
87            vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",
88                           hwnd,
89                           rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
90    }
91    
92  static LRESULT CALLBACK  static LRESULT CALLBACK
93  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
94  {  {
95          HWND hwnd;          HWND hwnd, parent;
96          UINT msg;          UINT msg;
97          WPARAM wparam;          WPARAM wparam;
98          LPARAM lparam;          LPARAM lparam;
# Line 69  wndproc_hook_proc(int code, WPARAM cur_t Line 109  wndproc_hook_proc(int code, WPARAM cur_t
109    
110          style = GetWindowLong(hwnd, GWL_STYLE);          style = GetWindowLong(hwnd, GWL_STYLE);
111    
112          if (style & WS_CHILD)          /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
113               but they exist nonetheless. */
114            if ((style & WS_CHILD) && !(style & WS_POPUP))
115                  goto end;                  goto end;
116    
117          switch (msg)          if (style & WS_POPUP)
118          {          {
119                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
120                    if (!parent)
121                            parent = (HWND) - 1;
122            }
123            else
124                    parent = NULL;
125    
126            switch (msg)
127            {
128                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
129                          {                          {
                                 RECT rect;  
130                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
131    
132                                  if (wp->flags & SWP_SHOWWINDOW)                                  if (wp->flags & SWP_SHOWWINDOW)
133                                  {                                  {
134                                          // FIXME: Now, just like create!                                          unsigned short title[150];
135                                          debug("SWP_SHOWWINDOW for %p!", hwnd);                                          int state;
                                         vchannel_write("CREATE1,0x%p,0x%x", hwnd, 0);  
136    
137                                          // FIXME: SETSTATE                                          vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);
138    
139                                          if (!GetWindowRect(hwnd, &rect))                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
140                                          {  
141                                                  debug("GetWindowRect failed!\n");                                          vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,
142                                                  break;                                                         vchannel_strfilter_unicode(title), 0);
143                                          }  
144                                          vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",                                          if (style & WS_MAXIMIZE)
145                                                         hwnd,                                                  state = 2;
146                                                         rect.left, rect.top,                                          else if (style & WS_MINIMIZE)
147                                                         rect.right - rect.left,                                                  state = 1;
148                                                         rect.bottom - rect.top, 0);                                          else
149                                                    state = 0;
150    
151                                            update_position(hwnd);
152    
153                                            vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);
154                                  }                                  }
155    
156                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
157                                          vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
158    
159                                  if (!(style & WS_VISIBLE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
160                                          break;                                          break;
161    
162                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
163                                  {                                          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);  
                                 }  
164    
165                                  if (!(wp->flags & SWP_NOZORDER))                                  if (!(wp->flags & SWP_NOZORDER))
166                                  {                                  {
167                                          vchannel_write("ZCHANGE1,0x%p,0x%p,0x%x",                                          HWND block_hwnd, block_behind;
168                                                         hwnd,                                          WaitForSingleObject(g_mutex, INFINITE);
169                                                         wp->flags & SWP_NOACTIVATE ? wp->                                          block_hwnd = g_blocked_zchange[0];
170                                                         hwndInsertAfter : 0, 0);                                          block_behind = g_blocked_zchange[1];
171                                            ReleaseMutex(g_mutex);
172    
173                                            if ((hwnd != block_hwnd)
174                                                || (wp->hwndInsertAfter != block_behind))
175                                            {
176                                                    vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",
177                                                                   hwnd,
178                                                                   wp->flags & SWP_NOACTIVATE ? wp->
179                                                                   hwndInsertAfter : 0, 0);
180                                            }
181                                  }                                  }
182    
183                                  break;                                  break;
184                          }                          }
185    
186                    case WM_SIZE:
187                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
188                                    break;
189                            update_position(hwnd);
190                            break;
191    
192                    case WM_MOVE:
193                            if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
194                                    break;
195                            update_position(hwnd);
196                            break;
197    
198                  case WM_DESTROY:                  case WM_DESTROY:
199                          vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);                          if (!(style & WS_VISIBLE))
200                                    break;
201                            vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
202                          break;                          break;
203    
204                  default:                  default:
# Line 145  wndproc_hook_proc(int code, WPARAM cur_t Line 210  wndproc_hook_proc(int code, WPARAM cur_t
210  }  }
211    
212  static LRESULT CALLBACK  static LRESULT CALLBACK
213  cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
214  {  {
215          char title[150];          HWND hwnd, parent;
216            UINT msg;
217            WPARAM wparam;
218            LPARAM lparam;
219    
220            LONG style;
221    
222          if (code < 0)          if (code < 0)
223                  goto end;                  goto end;
224    
225            hwnd = ((CWPRETSTRUCT *) details)->hwnd;
226            msg = ((CWPRETSTRUCT *) details)->message;
227            wparam = ((CWPRETSTRUCT *) details)->wParam;
228            lparam = ((CWPRETSTRUCT *) details)->lParam;
229    
230            style = GetWindowLong(hwnd, GWL_STYLE);
231    
232            /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
233               but they exist nonetheless. */
234            if ((style & WS_CHILD) && !(style & WS_POPUP))
235                    goto end;
236    
237            if (style & WS_POPUP)
238            {
239                    parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
240                    if (!parent)
241                            parent = (HWND) - 1;
242            }
243            else
244                    parent = NULL;
245    
246            switch (msg)
247            {
248                    case WM_SETTEXT:
249                            {
250                                    unsigned short title[150];
251                                    if (!(style & WS_VISIBLE))
252                                            break;
253                                    /* We cannot use the string in lparam because
254                                       we need unicode. */
255                                    GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
256                                    vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,
257                                                   vchannel_strfilter_unicode(title), 0);
258                                    break;
259                            }
260    
261                    default:
262                            break;
263            }
264    
265            if (msg == g_wm_seamless_focus)
266            {
267                    /* FIXME: SetActiveWindow() kills menus. Need to find a clean
268                       way to solve this. */
269                    if ((GetActiveWindow() != hwnd) && !parent)
270                            SetActiveWindow(hwnd);
271            }
272    
273          end:
274            return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
275    }
276    
277    static LRESULT CALLBACK
278    cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
279    {
280            if (code < 0)
281                    goto end;
282    
283          switch (code)          switch (code)
284          {          {
285                  case HCBT_MINMAX:                  case HCBT_MINMAX:
286                          {                          {
287                                  int show, state;                                  int show, state, blocked;
288    
289                                    WaitForSingleObject(g_mutex, INFINITE);
290                                    blocked = g_blocked_state;
291                                    ReleaseMutex(g_mutex);
292    
293                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
294    
295                                  if ((show == SW_SHOWMINIMIZED) || (show == SW_MINIMIZE))                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
296                                        || (show == SW_RESTORE))
297                                            state = 0;
298                                    else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
299                                            state = 1;
300                                    else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
301                                            state = 2;
302                                    else
303                                  {                                  {
304                                          MessageBox(0,                                          debug("Unexpected show: %d", show);
305                                                     "Minimizing windows is not allowed in this version. Sorry!",                                          break;
                                                    "SeamlessRDP", MB_OK);  
                                         return 1;  
306                                  }                                  }
307    
308                                  GetWindowText((HWND) wparam, title, sizeof(title));                                  if (blocked != state)
309                                            vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state,
310                                  /* FIXME: Strip title of dangerous characters */                                                         0);
311    
                                 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);  
312                                  break;                                  break;
313                          }                          }
314    
# Line 199  SetHooks(void) Line 328  SetHooks(void)
328    
329          if (!g_wndproc_hook)          if (!g_wndproc_hook)
330                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);                  g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
331    
332            if (!g_wndprocret_hook)
333                    g_wndprocret_hook =
334                            SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
335  }  }
336    
337  DLL_EXPORT void  DLL_EXPORT void
# Line 209  RemoveHooks(void) Line 342  RemoveHooks(void)
342    
343          if (g_wndproc_hook)          if (g_wndproc_hook)
344                  UnhookWindowsHookEx(g_wndproc_hook);                  UnhookWindowsHookEx(g_wndproc_hook);
345    
346            if (g_wndprocret_hook)
347                    UnhookWindowsHookEx(g_wndprocret_hook);
348    }
349    
350    DLL_EXPORT void
351    SafeMoveWindow(HWND hwnd, int x, int y, int width, int height)
352    {
353            WaitForSingleObject(g_mutex, INFINITE);
354            g_block_move.left = x;
355            g_block_move.top = y;
356            g_block_move.right = x + width;
357            g_block_move.bottom = y + height;
358            ReleaseMutex(g_mutex);
359    
360            SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
361    
362            WaitForSingleObject(g_mutex, INFINITE);
363            memset(&g_block_move, 0, sizeof(RECT));
364            ReleaseMutex(g_mutex);
365    }
366    
367    DLL_EXPORT void
368    SafeZChange(HWND hwnd, HWND behind)
369    {
370            if (behind == NULL)
371                    behind = HWND_TOP;
372    
373            WaitForSingleObject(g_mutex, INFINITE);
374            g_blocked_zchange[0] = hwnd;
375            g_blocked_zchange[1] = behind;
376            ReleaseMutex(g_mutex);
377    
378            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
379    
380            WaitForSingleObject(g_mutex, INFINITE);
381            g_blocked_zchange[0] = NULL;
382            g_blocked_zchange[1] = NULL;
383            ReleaseMutex(g_mutex);
384    }
385    
386    DLL_EXPORT void
387    SafeFocus(HWND hwnd)
388    {
389            WaitForSingleObject(g_mutex, INFINITE);
390            g_blocked_focus = hwnd;
391            ReleaseMutex(g_mutex);
392    
393            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
394    
395            WaitForSingleObject(g_mutex, INFINITE);
396            g_blocked_focus = NULL;
397            ReleaseMutex(g_mutex);
398    }
399    
400    DLL_EXPORT void
401    SafeSetState(HWND hwnd, int state)
402    {
403            WaitForSingleObject(g_mutex, INFINITE);
404            g_blocked_state = state;
405            ReleaseMutex(g_mutex);
406    
407            if (state == 0)
408                    ShowWindow(hwnd, SW_RESTORE);
409            else if (state == 1)
410                    ShowWindow(hwnd, SW_MINIMIZE);
411            else if (state == 2)
412                    ShowWindow(hwnd, SW_MAXIMIZE);
413            else
414                    debug("Invalid state %d sent.", state);
415    
416            WaitForSingleObject(g_mutex, INFINITE);
417            g_blocked_state = -1;
418            ReleaseMutex(g_mutex);
419  }  }
420    
421  DLL_EXPORT int  DLL_EXPORT int
# Line 234  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 441  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
441                          ++g_instance_count;                          ++g_instance_count;
442                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
443    
444                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
445    
446                          vchannel_open();                          vchannel_open();
447    
448                          break;                          break;

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

  ViewVC Help
Powered by ViewVC 1.1.26