/[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

Annotation of /sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1160 - (hide annotations)
Fri Mar 17 16:23:08 2006 UTC (18 years, 3 months ago) by ossman_
File MIME type: text/plain
File size: 10384 byte(s)
Break loops caused by STATE.

1 ossman_ 1071 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Seamless windows - Remote server hook DLL
4 ossman_ 1069
5 ossman_ 1071 Based on code copyright (C) 2004-2005 Martin Wickett
6    
7     Copyright (C) Peter Åstrand <astrand@cendio.se> 2005-2006
8     Copyright (C) Pierre Ossman <ossman@cendio.se> 2006
9    
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14    
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     GNU General Public License for more details.
19    
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23     */
24    
25 ossman_ 1069 #include <stdio.h>
26     #include <stdarg.h>
27    
28 ossman_ 1071 #include <windows.h>
29     #include <winuser.h>
30 ossman_ 1069
31 ossman_ 1073 #include "../vchannel.h"
32 ossman_ 1071
33 ossman_ 1069 #define DLL_EXPORT __declspec(dllexport)
34    
35 ossman_ 1145 #ifdef __GNUC__
36     #define SHARED __attribute__((section ("SHAREDDATA"), shared))
37     #else
38     #define SHARED
39     #endif
40    
41 ossman_ 1069 // Shared DATA
42     #pragma data_seg ( "SHAREDDATA" )
43    
44     // this is the total number of processes this dll is currently attached to
45 ossman_ 1145 int g_instance_count SHARED = 0;
46 ossman_ 1069
47 ossman_ 1145 // blocks for locally generated events
48     RECT g_block_move SHARED = { 0, 0, 0, 0 };
49 ossman_ 1158 HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
50     HWND g_blocked_focus SHARED = NULL;
51 ossman_ 1160 int g_blocked_state SHARED = -1;
52 ossman_ 1145
53 ossman_ 1069 #pragma data_seg ()
54    
55     #pragma comment(linker, "/section:SHAREDDATA,rws")
56    
57 ossman_ 1153 #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
58     static UINT g_wm_seamless_focus;
59    
60 ossman_ 1071 static HHOOK g_cbt_hook = NULL;
61     static HHOOK g_wndproc_hook = NULL;
62 ossman_ 1134 static HHOOK g_wndprocret_hook = NULL;
63 ossman_ 1069
64 ossman_ 1071 static HINSTANCE g_instance = NULL;
65 ossman_ 1069
66 ossman_ 1071 static HANDLE g_mutex = NULL;
67 ossman_ 1069
68 ossman_ 1081 static void
69     update_position(HWND hwnd)
70     {
71 ossman_ 1145 RECT rect, blocked;
72 ossman_ 1081
73     if (!GetWindowRect(hwnd, &rect))
74     {
75     debug("GetWindowRect failed!\n");
76     return;
77     }
78    
79 ossman_ 1145 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 astrand 1091 vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",
88 ossman_ 1081 hwnd,
89     rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
90     }
91    
92 ossman_ 1071 static LRESULT CALLBACK
93     wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
94 ossman_ 1069 {
95 ossman_ 1097 HWND hwnd, parent;
96 ossman_ 1079 UINT msg;
97     WPARAM wparam;
98     LPARAM lparam;
99 ossman_ 1069
100 ossman_ 1079 LONG style;
101 ossman_ 1069
102 ossman_ 1071 if (code < 0)
103     goto end;
104 ossman_ 1069
105 ossman_ 1079 hwnd = ((CWPSTRUCT *) details)->hwnd;
106     msg = ((CWPSTRUCT *) details)->message;
107     wparam = ((CWPSTRUCT *) details)->wParam;
108     lparam = ((CWPSTRUCT *) details)->lParam;
109    
110     style = GetWindowLong(hwnd, GWL_STYLE);
111    
112 ossman_ 1082 /* 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 ossman_ 1079 goto end;
116    
117 ossman_ 1097 if (style & WS_POPUP)
118 ossman_ 1109 {
119 ossman_ 1097 parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
120 ossman_ 1109 if (!parent)
121     parent = (HWND) - 1;
122     }
123 ossman_ 1097 else
124     parent = NULL;
125    
126 ossman_ 1071 switch (msg)
127     {
128     case WM_WINDOWPOSCHANGED:
129 ossman_ 1079 {
130     WINDOWPOS *wp = (WINDOWPOS *) lparam;
131 ossman_ 1069
132 ossman_ 1079 if (wp->flags & SWP_SHOWWINDOW)
133     {
134 ossman_ 1134 unsigned short title[150];
135 ossman_ 1099 int state;
136    
137 ossman_ 1097 vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);
138 ossman_ 1069
139 ossman_ 1134 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
140 ossman_ 1069
141 ossman_ 1113 vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,
142 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
143 ossman_ 1099
144     if (style & WS_MAXIMIZE)
145     state = 2;
146     else if (style & WS_MINIMIZE)
147     state = 1;
148     else
149     state = 0;
150    
151 ossman_ 1081 update_position(hwnd);
152 ossman_ 1099
153 ossman_ 1131 vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);
154 ossman_ 1079 }
155 ossman_ 1069
156 ossman_ 1079 if (wp->flags & SWP_HIDEWINDOW)
157 astrand 1091 vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
158 ossman_ 1079
159 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
160 ossman_ 1079 break;
161    
162 ossman_ 1080 if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
163 ossman_ 1081 update_position(hwnd);
164 ossman_ 1079
165     if (!(wp->flags & SWP_NOZORDER))
166 ossman_ 1080 {
167 ossman_ 1158 HWND block_hwnd, block_behind;
168     WaitForSingleObject(g_mutex, INFINITE);
169     block_hwnd = g_blocked_zchange[0];
170     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 ossman_ 1080 }
182 ossman_ 1069
183 ossman_ 1071 break;
184 ossman_ 1079 }
185 ossman_ 1069
186 ossman_ 1081 case WM_SIZE:
187 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
188 ossman_ 1083 break;
189 ossman_ 1081 update_position(hwnd);
190     break;
191    
192     case WM_MOVE:
193 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
194 ossman_ 1083 break;
195 ossman_ 1081 update_position(hwnd);
196     break;
197    
198 ossman_ 1134 case WM_DESTROY:
199     if (!(style & WS_VISIBLE))
200     break;
201     vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
202     break;
203    
204     default:
205     break;
206     }
207    
208     end:
209     return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
210     }
211    
212     static LRESULT CALLBACK
213     wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
214     {
215     HWND hwnd, parent;
216     UINT msg;
217     WPARAM wparam;
218     LPARAM lparam;
219    
220     LONG style;
221    
222     if (code < 0)
223     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 ossman_ 1158 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 ossman_ 1134 switch (msg)
247     {
248 ossman_ 1102 case WM_SETTEXT:
249 ossman_ 1113 {
250 ossman_ 1134 unsigned short title[150];
251 ossman_ 1113 if (!(style & WS_VISIBLE))
252     break;
253 ossman_ 1134 /* We cannot use the string in lparam because
254     we need unicode. */
255     GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
256 ossman_ 1113 vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,
257 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
258 ossman_ 1102 break;
259 ossman_ 1113 }
260 ossman_ 1102
261 ossman_ 1071 default:
262     break;
263     }
264    
265 ossman_ 1153 if (msg == g_wm_seamless_focus)
266 ossman_ 1158 {
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 ossman_ 1153
273 ossman_ 1071 end:
274 ossman_ 1134 return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
275 ossman_ 1069 }
276    
277 ossman_ 1071 static LRESULT CALLBACK
278     cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
279 ossman_ 1069 {
280 ossman_ 1071 if (code < 0)
281     goto end;
282 ossman_ 1069
283 ossman_ 1071 switch (code)
284     {
285     case HCBT_MINMAX:
286     {
287 ossman_ 1160 int show, state, blocked;
288 ossman_ 1069
289 ossman_ 1160 WaitForSingleObject(g_mutex, INFINITE);
290     blocked = g_blocked_state;
291     ReleaseMutex(g_mutex);
292    
293 ossman_ 1071 show = LOWORD(lparam);
294 ossman_ 1069
295 ossman_ 1128 if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
296     || (show == SW_RESTORE))
297 ossman_ 1079 state = 0;
298 ossman_ 1106 else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
299 ossman_ 1079 state = 1;
300 ossman_ 1106 else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
301 ossman_ 1079 state = 2;
302 ossman_ 1100 else
303 ossman_ 1106 {
304     debug("Unexpected show: %d", show);
305 ossman_ 1100 break;
306 ossman_ 1106 }
307 ossman_ 1160
308     if (blocked != state)
309     vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state,
310     0);
311    
312 ossman_ 1071 break;
313     }
314 ossman_ 1069
315 ossman_ 1071 default:
316     break;
317     }
318 ossman_ 1069
319 ossman_ 1071 end:
320     return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
321 ossman_ 1069 }
322    
323 ossman_ 1071 DLL_EXPORT void
324     SetHooks(void)
325 ossman_ 1069 {
326 ossman_ 1071 if (!g_cbt_hook)
327     g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
328 ossman_ 1069
329 ossman_ 1071 if (!g_wndproc_hook)
330     g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
331 ossman_ 1134
332     if (!g_wndprocret_hook)
333     g_wndprocret_hook =
334     SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
335 ossman_ 1069 }
336    
337 ossman_ 1071 DLL_EXPORT void
338     RemoveHooks(void)
339 ossman_ 1069 {
340 ossman_ 1071 if (g_cbt_hook)
341     UnhookWindowsHookEx(g_cbt_hook);
342 ossman_ 1069
343 ossman_ 1071 if (g_wndproc_hook)
344     UnhookWindowsHookEx(g_wndproc_hook);
345 ossman_ 1134
346     if (g_wndprocret_hook)
347     UnhookWindowsHookEx(g_wndprocret_hook);
348 ossman_ 1069 }
349    
350 ossman_ 1145 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 ossman_ 1158 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 ossman_ 1160 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 ossman_ 1071 DLL_EXPORT int
422     GetInstanceCount()
423 ossman_ 1069 {
424 ossman_ 1071 return g_instance_count;
425 ossman_ 1069 }
426    
427 ossman_ 1071 BOOL APIENTRY
428     DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
429 ossman_ 1069 {
430 ossman_ 1071 switch (ul_reason_for_call)
431     {
432     case DLL_PROCESS_ATTACH:
433     // remember our instance handle
434     g_instance = hinstDLL;
435 ossman_ 1069
436 ossman_ 1073 g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL");
437 ossman_ 1071 if (!g_mutex)
438     return FALSE;
439 ossman_ 1069
440 ossman_ 1071 WaitForSingleObject(g_mutex, INFINITE);
441     ++g_instance_count;
442     ReleaseMutex(g_mutex);
443 ossman_ 1069
444 ossman_ 1153 g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
445    
446 ossman_ 1071 vchannel_open();
447 ossman_ 1069
448 ossman_ 1071 break;
449 ossman_ 1069
450 ossman_ 1071 case DLL_THREAD_ATTACH:
451     break;
452 ossman_ 1069
453 ossman_ 1071 case DLL_THREAD_DETACH:
454     break;
455 ossman_ 1069
456 ossman_ 1071 case DLL_PROCESS_DETACH:
457     WaitForSingleObject(g_mutex, INFINITE);
458     --g_instance_count;
459     ReleaseMutex(g_mutex);
460 ossman_ 1069
461 ossman_ 1071 vchannel_close();
462 ossman_ 1069
463 ossman_ 1071 CloseHandle(g_mutex);
464 ossman_ 1069
465 ossman_ 1071 break;
466     }
467 ossman_ 1069
468 ossman_ 1071 return TRUE;
469 ossman_ 1069 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26