/[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 1071 - (show annotations)
Thu Mar 9 12:00:15 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 7180 byte(s)
Big cleanup and reindentation of the code.

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 #include <wtsapi32.h>
31 #include <cchannel.h>
32
33 #include "hookdll.h"
34
35 #define DLL_EXPORT __declspec(dllexport)
36
37 // Shared DATA
38 #pragma data_seg ( "SHAREDDATA" )
39
40 // this is the total number of processes this dll is currently attached to
41 int g_instance_count = 0;
42
43 #pragma data_seg ()
44
45 #pragma comment(linker, "/section:SHAREDDATA,rws")
46
47 static HHOOK g_cbt_hook = NULL;
48 static HHOOK g_wndproc_hook = NULL;
49
50 static HINSTANCE g_instance = NULL;
51
52 static HANDLE g_mutex = NULL;
53
54 static HANDLE g_vchannel = NULL;
55
56 static void
57 debug(char *format, ...)
58 {
59 va_list argp;
60 char buf[256];
61
62 sprintf(buf, "DEBUG1,");
63
64 va_start(argp, format);
65 _vsnprintf(buf + sizeof("DEBUG1,") - 1, sizeof(buf) - sizeof("DEBUG1,") + 1, format, argp);
66 va_end(argp);
67
68 vchannel_write(buf);
69 }
70
71 static LRESULT CALLBACK
72 wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
73 {
74 HWND hwnd = ((CWPSTRUCT *) details)->hwnd;
75 UINT msg = ((CWPSTRUCT *) details)->message;
76 WPARAM wparam = ((CWPSTRUCT *) details)->wParam;
77 LPARAM lparam = ((CWPSTRUCT *) details)->lParam;
78
79 LONG style = GetWindowLong(hwnd, GWL_STYLE);
80 WINDOWPOS *wp = (WINDOWPOS *) lparam;
81 RECT rect;
82
83 if (code < 0)
84 goto end;
85
86 switch (msg)
87 {
88
89 case WM_WINDOWPOSCHANGED:
90 if (style & WS_CHILD)
91 break;
92
93
94 if (wp->flags & SWP_SHOWWINDOW)
95 {
96 // FIXME: Now, just like create!
97 debug("SWP_SHOWWINDOW for %p!", hwnd);
98 vchannel_write("CREATE1,0x%p,0x%x", hwnd, 0);
99
100 // FIXME: SETSTATE
101
102 if (!GetWindowRect(hwnd, &rect))
103 {
104 debug("GetWindowRect failed!\n");
105 break;
106 }
107 vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",
108 hwnd,
109 rect.left, rect.top,
110 rect.right - rect.left, rect.bottom - rect.top, 0);
111 }
112
113
114 if (wp->flags & SWP_HIDEWINDOW)
115 vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);
116
117
118 if (!(style & WS_VISIBLE))
119 break;
120
121 if (wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE)
122 break;
123
124 if (!GetWindowRect(hwnd, &rect))
125 {
126 debug("GetWindowRect failed!\n");
127 break;
128 }
129
130 vchannel_write("POSITION1,0x%p,%d,%d,%d,%d,0x%x",
131 hwnd,
132 rect.left, rect.top,
133 rect.right - rect.left, rect.bottom - rect.top, 0);
134
135 break;
136
137
138 /* Note: WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED are
139 strange. Sometimes, for example when bringing up the
140 Notepad About dialog, only an WM_WINDOWPOSCHANGING is
141 sent. In some other cases, for exmaple when opening
142 Format->Text in Notepad, both events are sent. Also, for
143 some reason, when closing the Notepad About dialog, an
144 WM_WINDOWPOSCHANGING event is sent which looks just like
145 the event that was sent when the About dialog was opened... */
146 case WM_WINDOWPOSCHANGING:
147 if (style & WS_CHILD)
148 break;
149
150 if (!(style & WS_VISIBLE))
151 break;
152
153 if (!(wp->flags & SWP_NOZORDER))
154 vchannel_write("ZCHANGE1,0x%p,0x%p,0x%x",
155 hwnd,
156 wp->flags & SWP_NOACTIVATE ? wp->hwndInsertAfter : 0,
157 0);
158
159 break;
160
161
162
163
164 case WM_DESTROY:
165 if (style & WS_CHILD)
166 break;
167
168 vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);
169
170 break;
171
172
173 default:
174 break;
175 }
176
177 end:
178 return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
179 }
180
181 static LRESULT CALLBACK
182 cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
183 {
184 char title[150];
185
186 if (code < 0)
187 goto end;
188
189 switch (code)
190 {
191 case HCBT_MINMAX:
192 {
193 int show;
194
195 show = LOWORD(lparam);
196
197 if ((show == SW_SHOWMINIMIZED) || (show == SW_MINIMIZE))
198 {
199 MessageBox(0,
200 "Minimizing windows is not allowed in this version. Sorry!",
201 "SeamlessRDP", MB_OK);
202 return 1;
203 }
204
205 GetWindowText((HWND) wparam, title, sizeof(title));
206
207 /* FIXME: Strip title of dangerous characters */
208
209 vchannel_write("SETSTATE1,0x%p,%s,0x%x,0x%x",
210 (HWND) wparam, title, show, 0);
211 break;
212 }
213
214 default:
215 break;
216 }
217
218 end:
219 return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
220 }
221
222 int
223 vchannel_open()
224 {
225 g_vchannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE,
226 WTS_CURRENT_SESSION, CHANNELNAME);
227
228 if (g_vchannel == NULL)
229 return 0;
230 else
231 return 1;
232 }
233
234 int
235 vchannel_close()
236 {
237 BOOL result;
238
239 result = WTSVirtualChannelClose(g_vchannel);
240
241 g_vchannel = NULL;
242
243 if (result)
244 return 1;
245 else
246 return 0;
247 }
248
249 int
250 vchannel_is_open()
251 {
252 if (g_vchannel == NULL)
253 return 0;
254 else
255 return 1;
256 }
257
258 int
259 vchannel_write(char *format, ...)
260 {
261 BOOL result;
262 va_list argp;
263 char buf[1024];
264 int size;
265 ULONG bytes_written;
266
267 if (!vchannel_is_open())
268 return 1;
269
270 va_start(argp, format);
271 size = _vsnprintf(buf, sizeof(buf), format, argp);
272 va_end(argp);
273
274 if (size >= sizeof(buf))
275 return 0;
276
277 WaitForSingleObject(g_mutex, INFINITE);
278 result = WTSVirtualChannelWrite(g_vchannel, buf, (ULONG) strlen(buf), &bytes_written);
279 result = WTSVirtualChannelWrite(g_vchannel, "\n", (ULONG) 1, &bytes_written);
280 ReleaseMutex(g_mutex);
281
282 if (result)
283 return 1;
284 else
285 return 0;
286 }
287
288 DLL_EXPORT void
289 SetHooks(void)
290 {
291 if (!g_cbt_hook)
292 g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
293
294 if (!g_wndproc_hook)
295 g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
296 }
297
298 DLL_EXPORT void
299 RemoveHooks(void)
300 {
301 if (g_cbt_hook)
302 UnhookWindowsHookEx(g_cbt_hook);
303
304 if (g_wndproc_hook)
305 UnhookWindowsHookEx(g_wndproc_hook);
306 }
307
308 DLL_EXPORT int
309 GetInstanceCount()
310 {
311 return g_instance_count;
312 }
313
314 BOOL APIENTRY
315 DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
316 {
317 switch (ul_reason_for_call)
318 {
319 case DLL_PROCESS_ATTACH:
320 // remember our instance handle
321 g_instance = hinstDLL;
322
323 g_mutex = CreateMutex(NULL, FALSE, "Local\\Seamless");
324 if (!g_mutex)
325 return FALSE;
326
327 WaitForSingleObject(g_mutex, INFINITE);
328 ++g_instance_count;
329 ReleaseMutex(g_mutex);
330
331 vchannel_open();
332
333 break;
334
335 case DLL_THREAD_ATTACH:
336 break;
337
338 case DLL_THREAD_DETACH:
339 break;
340
341 case DLL_PROCESS_DETACH:
342 WaitForSingleObject(g_mutex, INFINITE);
343 --g_instance_count;
344 ReleaseMutex(g_mutex);
345
346 vchannel_close();
347
348 CloseHandle(g_mutex);
349
350 break;
351 }
352
353 return TRUE;
354 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26