/[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 1153 - (show annotations)
Fri Mar 17 09:55:35 2006 UTC (18 years, 3 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 /* -*- 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 #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
55 static UINT g_wm_seamless_focus;
56
57 static HHOOK g_cbt_hook = NULL;
58 static HHOOK g_wndproc_hook = NULL;
59 static HHOOK g_wndprocret_hook = NULL;
60
61 static HINSTANCE g_instance = NULL;
62
63 static HANDLE g_mutex = NULL;
64
65 static void
66 update_position(HWND hwnd)
67 {
68 RECT rect, blocked;
69
70 if (!GetWindowRect(hwnd, &rect))
71 {
72 debug("GetWindowRect failed!\n");
73 return;
74 }
75
76 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 vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",
85 hwnd,
86 rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
87 }
88
89 static LRESULT CALLBACK
90 wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
91 {
92 HWND hwnd, parent;
93 UINT msg;
94 WPARAM wparam;
95 LPARAM lparam;
96
97 LONG style;
98
99 if (code < 0)
100 goto end;
101
102 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 /* 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 goto end;
113
114 if (style & WS_POPUP)
115 {
116 parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
117 if (!parent)
118 parent = (HWND) - 1;
119 }
120 else
121 parent = NULL;
122
123 switch (msg)
124 {
125
126 case WM_WINDOWPOSCHANGED:
127 {
128 WINDOWPOS *wp = (WINDOWPOS *) lparam;
129
130 if (wp->flags & SWP_SHOWWINDOW)
131 {
132 unsigned short title[150];
133 int state;
134
135 vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);
136
137 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
138
139 vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,
140 vchannel_strfilter_unicode(title), 0);
141
142 if (style & WS_MAXIMIZE)
143 state = 2;
144 else if (style & WS_MINIMIZE)
145 state = 1;
146 else
147 state = 0;
148
149 update_position(hwnd);
150
151 vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);
152 }
153
154 if (wp->flags & SWP_HIDEWINDOW)
155 vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);
156
157 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
158 break;
159
160 if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
161 update_position(hwnd);
162
163 if (!(wp->flags & SWP_NOZORDER))
164 {
165 vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",
166 hwnd,
167 wp->flags & SWP_NOACTIVATE ? wp->
168 hwndInsertAfter : 0, 0);
169 }
170
171 break;
172 }
173
174 case WM_SIZE:
175 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
176 break;
177 update_position(hwnd);
178 break;
179
180 case WM_MOVE:
181 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
182 break;
183 update_position(hwnd);
184 break;
185
186 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 case WM_SETTEXT:
228 {
229 unsigned short title[150];
230 if (!(style & WS_VISIBLE))
231 break;
232 /* We cannot use the string in lparam because
233 we need unicode. */
234 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
235 vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,
236 vchannel_strfilter_unicode(title), 0);
237 break;
238 }
239
240 default:
241 break;
242 }
243
244 if (msg == g_wm_seamless_focus)
245 SetFocus(hwnd);
246
247 end:
248 return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
249 }
250
251 static LRESULT CALLBACK
252 cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
253 {
254 if (code < 0)
255 goto end;
256
257 switch (code)
258 {
259 case HCBT_MINMAX:
260 {
261 int show, state;
262
263 show = LOWORD(lparam);
264
265 if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
266 || (show == SW_RESTORE))
267 state = 0;
268 else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
269 state = 1;
270 else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
271 state = 2;
272 else
273 {
274 debug("Unexpected show: %d", show);
275 break;
276 }
277 vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);
278 break;
279 }
280
281 default:
282 break;
283 }
284
285 end:
286 return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
287 }
288
289 DLL_EXPORT void
290 SetHooks(void)
291 {
292 if (!g_cbt_hook)
293 g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
294
295 if (!g_wndproc_hook)
296 g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
297
298 if (!g_wndprocret_hook)
299 g_wndprocret_hook =
300 SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
301 }
302
303 DLL_EXPORT void
304 RemoveHooks(void)
305 {
306 if (g_cbt_hook)
307 UnhookWindowsHookEx(g_cbt_hook);
308
309 if (g_wndproc_hook)
310 UnhookWindowsHookEx(g_wndproc_hook);
311
312 if (g_wndprocret_hook)
313 UnhookWindowsHookEx(g_wndprocret_hook);
314 }
315
316 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 DLL_EXPORT int
334 GetInstanceCount()
335 {
336 return g_instance_count;
337 }
338
339 BOOL APIENTRY
340 DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
341 {
342 switch (ul_reason_for_call)
343 {
344 case DLL_PROCESS_ATTACH:
345 // remember our instance handle
346 g_instance = hinstDLL;
347
348 g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL");
349 if (!g_mutex)
350 return FALSE;
351
352 WaitForSingleObject(g_mutex, INFINITE);
353 ++g_instance_count;
354 ReleaseMutex(g_mutex);
355
356 g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
357
358 vchannel_open();
359
360 break;
361
362 case DLL_THREAD_ATTACH:
363 break;
364
365 case DLL_THREAD_DETACH:
366 break;
367
368 case DLL_PROCESS_DETACH:
369 WaitForSingleObject(g_mutex, INFINITE);
370 --g_instance_count;
371 ReleaseMutex(g_mutex);
372
373 vchannel_close();
374
375 CloseHandle(g_mutex);
376
377 break;
378 }
379
380 return TRUE;
381 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26