/[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 1153 - (hide annotations)
Fri Mar 17 09:55:35 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 8370 byte(s)
Handle FOCUS. We need to do this via an extra message because a process is
only allowed to focus its own windows.

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    
50 ossman_ 1069 #pragma data_seg ()
51    
52     #pragma comment(linker, "/section:SHAREDDATA,rws")
53    
54 ossman_ 1153 #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
55     static UINT g_wm_seamless_focus;
56    
57 ossman_ 1071 static HHOOK g_cbt_hook = NULL;
58     static HHOOK g_wndproc_hook = NULL;
59 ossman_ 1134 static HHOOK g_wndprocret_hook = NULL;
60 ossman_ 1069
61 ossman_ 1071 static HINSTANCE g_instance = NULL;
62 ossman_ 1069
63 ossman_ 1071 static HANDLE g_mutex = NULL;
64 ossman_ 1069
65 ossman_ 1081 static void
66     update_position(HWND hwnd)
67     {
68 ossman_ 1145 RECT rect, blocked;
69 ossman_ 1081
70     if (!GetWindowRect(hwnd, &rect))
71     {
72     debug("GetWindowRect failed!\n");
73     return;
74     }
75    
76 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
77     memcpy(&blocked, &g_block_move, sizeof(RECT));
78     ReleaseMutex(g_mutex);
79    
80     if ((rect.left == blocked.left) && (rect.top == blocked.top)
81     && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
82     return;
83    
84 astrand 1091 vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",
85 ossman_ 1081 hwnd,
86     rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
87     }
88    
89 ossman_ 1071 static LRESULT CALLBACK
90     wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
91 ossman_ 1069 {
92 ossman_ 1097 HWND hwnd, parent;
93 ossman_ 1079 UINT msg;
94     WPARAM wparam;
95     LPARAM lparam;
96 ossman_ 1069
97 ossman_ 1079 LONG style;
98 ossman_ 1069
99 ossman_ 1071 if (code < 0)
100     goto end;
101 ossman_ 1069
102 ossman_ 1079 hwnd = ((CWPSTRUCT *) details)->hwnd;
103     msg = ((CWPSTRUCT *) details)->message;
104     wparam = ((CWPSTRUCT *) details)->wParam;
105     lparam = ((CWPSTRUCT *) details)->lParam;
106    
107     style = GetWindowLong(hwnd, GWL_STYLE);
108    
109 ossman_ 1082 /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
110     but they exist nonetheless. */
111     if ((style & WS_CHILD) && !(style & WS_POPUP))
112 ossman_ 1079 goto end;
113    
114 ossman_ 1097 if (style & WS_POPUP)
115 ossman_ 1109 {
116 ossman_ 1097 parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
117 ossman_ 1109 if (!parent)
118     parent = (HWND) - 1;
119     }
120 ossman_ 1097 else
121     parent = NULL;
122    
123 ossman_ 1071 switch (msg)
124     {
125 ossman_ 1069
126 ossman_ 1071 case WM_WINDOWPOSCHANGED:
127 ossman_ 1079 {
128     WINDOWPOS *wp = (WINDOWPOS *) lparam;
129 ossman_ 1069
130 ossman_ 1079 if (wp->flags & SWP_SHOWWINDOW)
131     {
132 ossman_ 1134 unsigned short title[150];
133 ossman_ 1099 int state;
134    
135 ossman_ 1097 vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);
136 ossman_ 1069
137 ossman_ 1134 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
138 ossman_ 1069
139 ossman_ 1113 vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,
140 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
141 ossman_ 1099
142     if (style & WS_MAXIMIZE)
143     state = 2;
144     else if (style & WS_MINIMIZE)
145     state = 1;
146     else
147     state = 0;
148    
149 ossman_ 1081 update_position(hwnd);
150 ossman_ 1099
151 ossman_ 1131 vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);
152 ossman_ 1079 }
153 ossman_ 1069
154 ossman_ 1079 if (wp->flags & SWP_HIDEWINDOW)
155 astrand 1091 vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
156 ossman_ 1079
157 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
158 ossman_ 1079 break;
159    
160 ossman_ 1080 if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
161 ossman_ 1081 update_position(hwnd);
162 ossman_ 1079
163     if (!(wp->flags & SWP_NOZORDER))
164 ossman_ 1080 {
165 astrand 1091 vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",
166 ossman_ 1079 hwnd,
167     wp->flags & SWP_NOACTIVATE ? wp->
168     hwndInsertAfter : 0, 0);
169 ossman_ 1080 }
170 ossman_ 1069
171 ossman_ 1071 break;
172 ossman_ 1079 }
173 ossman_ 1069
174 ossman_ 1081 case WM_SIZE:
175 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
176 ossman_ 1083 break;
177 ossman_ 1081 update_position(hwnd);
178     break;
179    
180     case WM_MOVE:
181 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
182 ossman_ 1083 break;
183 ossman_ 1081 update_position(hwnd);
184     break;
185    
186 ossman_ 1134 case WM_DESTROY:
187     if (!(style & WS_VISIBLE))
188     break;
189     vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
190     break;
191    
192     default:
193     break;
194     }
195    
196     end:
197     return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
198     }
199    
200     static LRESULT CALLBACK
201     wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
202     {
203     HWND hwnd, parent;
204     UINT msg;
205     WPARAM wparam;
206     LPARAM lparam;
207    
208     LONG style;
209    
210     if (code < 0)
211     goto end;
212    
213     hwnd = ((CWPRETSTRUCT *) details)->hwnd;
214     msg = ((CWPRETSTRUCT *) details)->message;
215     wparam = ((CWPRETSTRUCT *) details)->wParam;
216     lparam = ((CWPRETSTRUCT *) details)->lParam;
217    
218     style = GetWindowLong(hwnd, GWL_STYLE);
219    
220     /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
221     but they exist nonetheless. */
222     if ((style & WS_CHILD) && !(style & WS_POPUP))
223     goto end;
224    
225     switch (msg)
226     {
227 ossman_ 1102 case WM_SETTEXT:
228 ossman_ 1113 {
229 ossman_ 1134 unsigned short title[150];
230 ossman_ 1113 if (!(style & WS_VISIBLE))
231     break;
232 ossman_ 1134 /* We cannot use the string in lparam because
233     we need unicode. */
234     GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
235 ossman_ 1113 vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,
236 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
237 ossman_ 1102 break;
238 ossman_ 1113 }
239 ossman_ 1102
240 ossman_ 1071 default:
241     break;
242     }
243    
244 ossman_ 1153 if (msg == g_wm_seamless_focus)
245     SetFocus(hwnd);
246    
247 ossman_ 1071 end:
248 ossman_ 1134 return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
249 ossman_ 1069 }
250    
251 ossman_ 1071 static LRESULT CALLBACK
252     cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
253 ossman_ 1069 {
254 ossman_ 1071 if (code < 0)
255     goto end;
256 ossman_ 1069
257 ossman_ 1071 switch (code)
258     {
259     case HCBT_MINMAX:
260     {
261 ossman_ 1079 int show, state;
262 ossman_ 1069
263 ossman_ 1071 show = LOWORD(lparam);
264 ossman_ 1069
265 ossman_ 1128 if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
266     || (show == SW_RESTORE))
267 ossman_ 1079 state = 0;
268 ossman_ 1106 else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
269 ossman_ 1079 state = 1;
270 ossman_ 1106 else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
271 ossman_ 1079 state = 2;
272 ossman_ 1100 else
273 ossman_ 1106 {
274     debug("Unexpected show: %d", show);
275 ossman_ 1100 break;
276 ossman_ 1106 }
277 ossman_ 1096 vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);
278 ossman_ 1071 break;
279     }
280 ossman_ 1069
281 ossman_ 1071 default:
282     break;
283     }
284 ossman_ 1069
285 ossman_ 1071 end:
286     return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
287 ossman_ 1069 }
288    
289 ossman_ 1071 DLL_EXPORT void
290     SetHooks(void)
291 ossman_ 1069 {
292 ossman_ 1071 if (!g_cbt_hook)
293     g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
294 ossman_ 1069
295 ossman_ 1071 if (!g_wndproc_hook)
296     g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
297 ossman_ 1134
298     if (!g_wndprocret_hook)
299     g_wndprocret_hook =
300     SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
301 ossman_ 1069 }
302    
303 ossman_ 1071 DLL_EXPORT void
304     RemoveHooks(void)
305 ossman_ 1069 {
306 ossman_ 1071 if (g_cbt_hook)
307     UnhookWindowsHookEx(g_cbt_hook);
308 ossman_ 1069
309 ossman_ 1071 if (g_wndproc_hook)
310     UnhookWindowsHookEx(g_wndproc_hook);
311 ossman_ 1134
312     if (g_wndprocret_hook)
313     UnhookWindowsHookEx(g_wndprocret_hook);
314 ossman_ 1069 }
315    
316 ossman_ 1145 DLL_EXPORT void
317     SafeMoveWindow(HWND hwnd, int x, int y, int width, int height)
318     {
319     WaitForSingleObject(g_mutex, INFINITE);
320     g_block_move.left = x;
321     g_block_move.top = y;
322     g_block_move.right = x + width;
323     g_block_move.bottom = y + height;
324     ReleaseMutex(g_mutex);
325    
326     SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
327    
328     WaitForSingleObject(g_mutex, INFINITE);
329     memset(&g_block_move, 0, sizeof(RECT));
330     ReleaseMutex(g_mutex);
331     }
332    
333 ossman_ 1071 DLL_EXPORT int
334     GetInstanceCount()
335 ossman_ 1069 {
336 ossman_ 1071 return g_instance_count;
337 ossman_ 1069 }
338    
339 ossman_ 1071 BOOL APIENTRY
340     DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
341 ossman_ 1069 {
342 ossman_ 1071 switch (ul_reason_for_call)
343     {
344     case DLL_PROCESS_ATTACH:
345     // remember our instance handle
346     g_instance = hinstDLL;
347 ossman_ 1069
348 ossman_ 1073 g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL");
349 ossman_ 1071 if (!g_mutex)
350     return FALSE;
351 ossman_ 1069
352 ossman_ 1071 WaitForSingleObject(g_mutex, INFINITE);
353     ++g_instance_count;
354     ReleaseMutex(g_mutex);
355 ossman_ 1069
356 ossman_ 1153 g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
357    
358 ossman_ 1071 vchannel_open();
359 ossman_ 1069
360 ossman_ 1071 break;
361 ossman_ 1069
362 ossman_ 1071 case DLL_THREAD_ATTACH:
363     break;
364 ossman_ 1069
365 ossman_ 1071 case DLL_THREAD_DETACH:
366     break;
367 ossman_ 1069
368 ossman_ 1071 case DLL_PROCESS_DETACH:
369     WaitForSingleObject(g_mutex, INFINITE);
370     --g_instance_count;
371     ReleaseMutex(g_mutex);
372 ossman_ 1069
373 ossman_ 1071 vchannel_close();
374 ossman_ 1069
375 ossman_ 1071 CloseHandle(g_mutex);
376 ossman_ 1069
377 ossman_ 1071 break;
378     }
379 ossman_ 1069
380 ossman_ 1071 return TRUE;
381 ossman_ 1069 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26