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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1145 - (show annotations)
Thu Mar 16 13:24:18 2006 UTC (18 years, 3 months ago) by ossman_
File MIME type: text/plain
File size: 8176 byte(s)
Prevent moves we do ourself from generating a POSITION. We do this by storing
the coordinate we're moving to in a shared variable. Since SetWindowPos is
synchronous, we know that the variable will have valid data when the hook
is called.

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26