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

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     #include <wtsapi32.h>
31     #include <cchannel.h>
32 ossman_ 1069
33 ossman_ 1071 #include "hookdll.h"
34    
35 ossman_ 1069 #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 ossman_ 1071 int g_instance_count = 0;
42 ossman_ 1069
43     #pragma data_seg ()
44    
45     #pragma comment(linker, "/section:SHAREDDATA,rws")
46    
47 ossman_ 1071 static HHOOK g_cbt_hook = NULL;
48     static HHOOK g_wndproc_hook = NULL;
49 ossman_ 1069
50 ossman_ 1071 static HINSTANCE g_instance = NULL;
51 ossman_ 1069
52 ossman_ 1071 static HANDLE g_mutex = NULL;
53 ossman_ 1069
54 ossman_ 1071 static HANDLE g_vchannel = NULL;
55 ossman_ 1069
56 ossman_ 1071 static void
57     debug(char *format, ...)
58 ossman_ 1069 {
59 ossman_ 1071 va_list argp;
60     char buf[256];
61 ossman_ 1069
62 ossman_ 1071 sprintf(buf, "DEBUG1,");
63 ossman_ 1069
64 ossman_ 1071 va_start(argp, format);
65     _vsnprintf(buf + sizeof("DEBUG1,") - 1, sizeof(buf) - sizeof("DEBUG1,") + 1, format, argp);
66     va_end(argp);
67 ossman_ 1069
68 ossman_ 1071 vchannel_write(buf);
69 ossman_ 1069 }
70    
71 ossman_ 1071 static LRESULT CALLBACK
72     wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
73 ossman_ 1069 {
74 ossman_ 1071 HWND hwnd = ((CWPSTRUCT *) details)->hwnd;
75     UINT msg = ((CWPSTRUCT *) details)->message;
76     WPARAM wparam = ((CWPSTRUCT *) details)->wParam;
77     LPARAM lparam = ((CWPSTRUCT *) details)->lParam;
78 ossman_ 1069
79 ossman_ 1071 LONG style = GetWindowLong(hwnd, GWL_STYLE);
80     WINDOWPOS *wp = (WINDOWPOS *) lparam;
81     RECT rect;
82 ossman_ 1069
83 ossman_ 1071 if (code < 0)
84     goto end;
85 ossman_ 1069
86 ossman_ 1071 switch (msg)
87     {
88 ossman_ 1069
89 ossman_ 1071 case WM_WINDOWPOSCHANGED:
90     if (style & WS_CHILD)
91     break;
92 ossman_ 1069
93    
94 ossman_ 1071 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 ossman_ 1069
100 ossman_ 1071 // FIXME: SETSTATE
101 ossman_ 1069
102 ossman_ 1071 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 ossman_ 1069
113    
114 ossman_ 1071 if (wp->flags & SWP_HIDEWINDOW)
115     vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);
116 ossman_ 1069
117    
118 ossman_ 1071 if (!(style & WS_VISIBLE))
119     break;
120 ossman_ 1069
121 ossman_ 1071 if (wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE)
122     break;
123 ossman_ 1069
124 ossman_ 1071 if (!GetWindowRect(hwnd, &rect))
125     {
126     debug("GetWindowRect failed!\n");
127     break;
128     }
129 ossman_ 1069
130 ossman_ 1071 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 ossman_ 1069
135 ossman_ 1071 break;
136 ossman_ 1069
137    
138 ossman_ 1071 /* 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 ossman_ 1069
150 ossman_ 1071 if (!(style & WS_VISIBLE))
151     break;
152 ossman_ 1069
153 ossman_ 1071 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 ossman_ 1069
159 ossman_ 1071 break;
160 ossman_ 1069
161    
162    
163    
164 ossman_ 1071 case WM_DESTROY:
165     if (style & WS_CHILD)
166     break;
167 ossman_ 1069
168 ossman_ 1071 vchannel_write("DESTROY1,0x%p,0x%x", hwnd, 0);
169 ossman_ 1069
170 ossman_ 1071 break;
171 ossman_ 1069
172    
173 ossman_ 1071 default:
174     break;
175     }
176    
177     end:
178     return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
179 ossman_ 1069 }
180    
181 ossman_ 1071 static LRESULT CALLBACK
182     cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
183 ossman_ 1069 {
184 ossman_ 1071 char title[150];
185 ossman_ 1069
186 ossman_ 1071 if (code < 0)
187     goto end;
188 ossman_ 1069
189 ossman_ 1071 switch (code)
190     {
191     case HCBT_MINMAX:
192     {
193     int show;
194 ossman_ 1069
195 ossman_ 1071 show = LOWORD(lparam);
196 ossman_ 1069
197 ossman_ 1071 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 ossman_ 1069
205 ossman_ 1071 GetWindowText((HWND) wparam, title, sizeof(title));
206 ossman_ 1069
207 ossman_ 1071 /* FIXME: Strip title of dangerous characters */
208 ossman_ 1069
209 ossman_ 1071 vchannel_write("SETSTATE1,0x%p,%s,0x%x,0x%x",
210     (HWND) wparam, title, show, 0);
211     break;
212     }
213 ossman_ 1069
214 ossman_ 1071 default:
215     break;
216     }
217 ossman_ 1069
218 ossman_ 1071 end:
219     return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
220 ossman_ 1069 }
221    
222 ossman_ 1071 int
223     vchannel_open()
224 ossman_ 1069 {
225 ossman_ 1071 g_vchannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE,
226     WTS_CURRENT_SESSION, CHANNELNAME);
227 ossman_ 1069
228 ossman_ 1071 if (g_vchannel == NULL)
229     return 0;
230     else
231     return 1;
232     }
233 ossman_ 1069
234 ossman_ 1071 int
235     vchannel_close()
236     {
237     BOOL result;
238 ossman_ 1069
239 ossman_ 1071 result = WTSVirtualChannelClose(g_vchannel);
240 ossman_ 1069
241 ossman_ 1071 g_vchannel = NULL;
242 ossman_ 1069
243 ossman_ 1071 if (result)
244     return 1;
245     else
246     return 0;
247     }
248 ossman_ 1069
249 ossman_ 1071 int
250     vchannel_is_open()
251     {
252     if (g_vchannel == NULL)
253     return 0;
254     else
255     return 1;
256     }
257 ossman_ 1069
258 ossman_ 1071 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 ossman_ 1069
267 ossman_ 1071 if (!vchannel_is_open())
268     return 1;
269 ossman_ 1069
270 ossman_ 1071 va_start(argp, format);
271     size = _vsnprintf(buf, sizeof(buf), format, argp);
272     va_end(argp);
273 ossman_ 1069
274 ossman_ 1071 if (size >= sizeof(buf))
275     return 0;
276 ossman_ 1069
277 ossman_ 1071 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 ossman_ 1069
282 ossman_ 1071 if (result)
283     return 1;
284     else
285     return 0;
286 ossman_ 1069 }
287    
288 ossman_ 1071 DLL_EXPORT void
289     SetHooks(void)
290 ossman_ 1069 {
291 ossman_ 1071 if (!g_cbt_hook)
292     g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
293 ossman_ 1069
294 ossman_ 1071 if (!g_wndproc_hook)
295     g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
296 ossman_ 1069 }
297    
298 ossman_ 1071 DLL_EXPORT void
299     RemoveHooks(void)
300 ossman_ 1069 {
301 ossman_ 1071 if (g_cbt_hook)
302     UnhookWindowsHookEx(g_cbt_hook);
303 ossman_ 1069
304 ossman_ 1071 if (g_wndproc_hook)
305     UnhookWindowsHookEx(g_wndproc_hook);
306 ossman_ 1069 }
307    
308 ossman_ 1071 DLL_EXPORT int
309     GetInstanceCount()
310 ossman_ 1069 {
311 ossman_ 1071 return g_instance_count;
312 ossman_ 1069 }
313    
314 ossman_ 1071 BOOL APIENTRY
315     DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
316 ossman_ 1069 {
317 ossman_ 1071 switch (ul_reason_for_call)
318     {
319     case DLL_PROCESS_ATTACH:
320     // remember our instance handle
321     g_instance = hinstDLL;
322 ossman_ 1069
323 ossman_ 1071 g_mutex = CreateMutex(NULL, FALSE, "Local\\Seamless");
324     if (!g_mutex)
325     return FALSE;
326 ossman_ 1069
327 ossman_ 1071 WaitForSingleObject(g_mutex, INFINITE);
328     ++g_instance_count;
329     ReleaseMutex(g_mutex);
330 ossman_ 1069
331 ossman_ 1071 vchannel_open();
332 ossman_ 1069
333 ossman_ 1071 break;
334 ossman_ 1069
335 ossman_ 1071 case DLL_THREAD_ATTACH:
336     break;
337 ossman_ 1069
338 ossman_ 1071 case DLL_THREAD_DETACH:
339     break;
340 ossman_ 1069
341 ossman_ 1071 case DLL_PROCESS_DETACH:
342     WaitForSingleObject(g_mutex, INFINITE);
343     --g_instance_count;
344     ReleaseMutex(g_mutex);
345 ossman_ 1069
346 ossman_ 1071 vchannel_close();
347 ossman_ 1069
348 ossman_ 1071 CloseHandle(g_mutex);
349 ossman_ 1069
350 ossman_ 1071 break;
351     }
352 ossman_ 1069
353 ossman_ 1071 return TRUE;
354 ossman_ 1069 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26