/[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 1134 - (show annotations)
Wed Mar 15 13:19:54 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 7257 byte(s)
Get window titles in unicode and send them over the channel in UTF-8. This
also meant that we had to catch WM_SETTEXT after it was handled (so that we
can use GetWindowTextW()).

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26