/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ServerExe/main.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/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1177 - (show annotations)
Tue Mar 21 14:42:25 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 9295 byte(s)
Support for window groups and modal windows.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Seamless windows - Remote server executable
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 <windows.h>
26 #include <stdio.h>
27 #include <wtsapi32.h>
28 #include <cchannel.h>
29
30 #include "vchannel.h"
31
32 #include "resource.h"
33
34 #define APP_NAME "SeamlessRDP Shell"
35
36 #ifndef WM_WTSSESSION_CHANGE
37 #define WM_WTSSESSION_CHANGE 0x02B1
38 #endif
39 #ifndef WTS_REMOTE_CONNECT
40 #define WTS_REMOTE_CONNECT 0x3
41 #endif
42
43 /* Global data */
44 static HINSTANCE g_instance;
45 static HWND g_hwnd;
46
47 typedef void (*set_hooks_proc_t) ();
48 typedef void (*remove_hooks_proc_t) ();
49 typedef int (*get_instance_count_proc_t) ();
50
51 typedef void (*move_window_proc_t) (unsigned int serial, HWND hwnd, int x, int y, int width,
52 int height);
53 typedef void (*zchange_proc_t) (unsigned int serial, HWND hwnd, HWND behind);
54 typedef void (*focus_proc_t) (unsigned int serial, HWND hwnd);
55 typedef void (*set_state_proc_t) (unsigned int serial, HWND hwnd, int state);
56
57 static move_window_proc_t g_move_window_fn = NULL;
58 static zchange_proc_t g_zchange_fn = NULL;
59 static focus_proc_t g_focus_fn = NULL;
60 static set_state_proc_t g_set_state_fn = NULL;
61
62 static void
63 message(const char *text)
64 {
65 MessageBox(GetDesktopWindow(), text, "SeamlessRDP Shell", MB_OK);
66 }
67
68 static char *
69 get_token(char **s)
70 {
71 char *comma, *head;
72 head = *s;
73
74 if (!head)
75 return NULL;
76
77 comma = strchr(head, ',');
78 if (comma)
79 {
80 *comma = '\0';
81 *s = comma + 1;
82 }
83 else
84 {
85 *s = NULL;
86 }
87
88 return head;
89 }
90
91 static BOOL CALLBACK
92 enum_cb(HWND hwnd, LPARAM lparam)
93 {
94 RECT rect;
95 unsigned short title[150];
96 LONG styles;
97 int state;
98 HWND parent;
99 DWORD pid;
100 int flags;
101
102 styles = GetWindowLong(hwnd, GWL_STYLE);
103
104 if (!(styles & WS_VISIBLE))
105 return TRUE;
106
107 if (styles & WS_POPUP)
108 parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
109 else
110 parent = NULL;
111
112 GetWindowThreadProcessId(hwnd, &pid);
113
114 flags = 0;
115 if (styles & DS_MODALFRAME)
116 flags |= SEAMLESS_CREATE_MODAL;
117
118 vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x", (long) hwnd, (long) pid,
119 (long) parent, flags);
120
121 if (!GetWindowRect(hwnd, &rect))
122 {
123 debug("GetWindowRect failed!");
124 return TRUE;
125 }
126
127 vchannel_write("POSITION", "0x%p,%d,%d,%d,%d,0x%x",
128 hwnd,
129 rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
130
131 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
132
133 vchannel_write("TITLE", "0x%x,%s,0x%x", hwnd, vchannel_strfilter_unicode(title), 0);
134
135 if (styles & WS_MAXIMIZE)
136 state = 2;
137 else if (styles & WS_MINIMIZE)
138 state = 1;
139 else
140 state = 0;
141
142 vchannel_write("STATE", "0x%p,0x%x,0x%x", hwnd, state, 0);
143
144 return TRUE;
145 }
146
147 static void
148 do_sync(void)
149 {
150 vchannel_block();
151
152 vchannel_write("SYNCBEGIN", "0x0");
153
154 EnumWindows(enum_cb, 0);
155
156 vchannel_write("SYNCEND", "0x0");
157
158 vchannel_unblock();
159 }
160
161 static void
162 do_state(unsigned int serial, HWND hwnd, int state)
163 {
164 g_set_state_fn(serial, hwnd, state);
165 }
166
167 static void
168 do_position(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
169 {
170 g_move_window_fn(serial, hwnd, x, y, width, height);
171 }
172
173 static void
174 do_zchange(unsigned int serial, HWND hwnd, HWND behind)
175 {
176 g_zchange_fn(serial, hwnd, behind);
177 }
178
179 static void
180 do_focus(unsigned int serial, HWND hwnd)
181 {
182 g_focus_fn(serial, hwnd);
183 }
184
185 static void
186 process_cmds(void)
187 {
188 char line[VCHANNEL_MAX_LINE];
189 int size;
190
191 char *p, *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
192
193 while ((size = vchannel_read(line, sizeof(line))) >= 0)
194 {
195 p = line;
196
197 tok1 = get_token(&p);
198 tok2 = get_token(&p);
199 tok3 = get_token(&p);
200 tok4 = get_token(&p);
201 tok5 = get_token(&p);
202 tok6 = get_token(&p);
203 tok7 = get_token(&p);
204 tok8 = get_token(&p);
205
206 if (strcmp(tok1, "SYNC") == 0)
207 do_sync();
208 else if (strcmp(tok1, "STATE") == 0)
209 do_state(strtoul(tok2, NULL, 0), (HWND) strtoul(tok3, NULL, 0),
210 strtol(tok4, NULL, 0));
211 else if (strcmp(tok1, "POSITION") == 0)
212 do_position(strtoul(tok2, NULL, 0), (HWND) strtoul(tok3, NULL, 0),
213 strtol(tok4, NULL, 0), strtol(tok5, NULL, 0), strtol(tok6, NULL,
214 0),
215 strtol(tok7, NULL, 0));
216 else if (strcmp(tok1, "ZCHANGE") == 0)
217 do_zchange(strtoul(tok2, NULL, 0), (HWND) strtoul(tok3, NULL, 0),
218 (HWND) strtoul(tok4, NULL, 0));
219 else if (strcmp(tok1, "FOCUS") == 0)
220 do_focus(strtoul(tok2, NULL, 0), (HWND) strtoul(tok3, NULL, 0));
221 }
222 }
223
224 static LRESULT CALLBACK
225 wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
226 {
227 if (message == WM_WTSSESSION_CHANGE)
228 {
229 if (wparam == WTS_REMOTE_CONNECT)
230 {
231 /* These get reset on each reconnect */
232 SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);
233 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
234 vchannel_write("HELLO", "0x%08x", 1);
235 }
236 }
237
238 return DefWindowProc(hwnd, message, wparam, lparam);
239 }
240
241 static BOOL
242 register_class(void)
243 {
244 WNDCLASSEX wcx;
245
246 memset(&wcx, 0, sizeof(wcx));
247
248 wcx.cbSize = sizeof(wcx);
249 wcx.lpfnWndProc = wndproc;
250 wcx.hInstance = g_instance;
251 wcx.lpszClassName = "SeamlessClass";
252
253 return RegisterClassEx(&wcx);
254 }
255
256 static BOOL
257 create_wnd(void)
258 {
259 if (!register_class())
260 return FALSE;
261
262 g_hwnd = CreateWindow("SeamlessClass",
263 "Seamless Window",
264 WS_OVERLAPPEDWINDOW,
265 CW_USEDEFAULT,
266 CW_USEDEFAULT,
267 CW_USEDEFAULT,
268 CW_USEDEFAULT, (HWND) NULL, (HMENU) NULL, g_instance, (LPVOID) NULL);
269
270 if (!g_hwnd)
271 return FALSE;
272
273 return TRUE;
274 }
275
276 int WINAPI
277 WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow)
278 {
279 HMODULE hookdll;
280
281 set_hooks_proc_t set_hooks_fn;
282 remove_hooks_proc_t remove_hooks_fn;
283 get_instance_count_proc_t instance_count_fn;
284
285 g_instance = instance;
286
287 hookdll = LoadLibrary("seamlessrdp.dll");
288 if (!hookdll)
289 {
290 message("Could not load hook DLL. Unable to continue.");
291 return -1;
292 }
293
294 set_hooks_fn = (set_hooks_proc_t) GetProcAddress(hookdll, "SetHooks");
295 remove_hooks_fn = (remove_hooks_proc_t) GetProcAddress(hookdll, "RemoveHooks");
296 instance_count_fn = (get_instance_count_proc_t) GetProcAddress(hookdll, "GetInstanceCount");
297 g_move_window_fn = (move_window_proc_t) GetProcAddress(hookdll, "SafeMoveWindow");
298 g_zchange_fn = (zchange_proc_t) GetProcAddress(hookdll, "SafeZChange");
299 g_focus_fn = (focus_proc_t) GetProcAddress(hookdll, "SafeFocus");
300 g_set_state_fn = (set_state_proc_t) GetProcAddress(hookdll, "SafeSetState");
301
302 if (!set_hooks_fn || !remove_hooks_fn || !instance_count_fn || !g_move_window_fn
303 || !g_zchange_fn || !g_focus_fn || !g_set_state_fn)
304 {
305 FreeLibrary(hookdll);
306 message("Hook DLL doesn't contain the correct functions. Unable to continue.");
307 return -1;
308 }
309
310 /* Check if the DLL is already loaded */
311 if (instance_count_fn() != 1)
312 {
313 FreeLibrary(hookdll);
314 message("Another running instance of Seamless RDP detected.");
315 return -1;
316 }
317
318 if (!create_wnd())
319 {
320 FreeLibrary(hookdll);
321 message("Couldn't create a window to catch events.");
322 return -1;
323 }
324
325 WTSRegisterSessionNotification(g_hwnd, NOTIFY_FOR_THIS_SESSION);
326
327 vchannel_open();
328
329 vchannel_write("HELLO", "0x%08x", 0);
330
331 set_hooks_fn();
332
333 /* Since we don't see the entire desktop we must resize windows
334 immediatly. */
335 SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);
336
337 /* Disable screen saver since we cannot catch its windows. */
338 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
339
340 if (strlen(cmdline) == 0)
341 {
342 message("No command line specified.");
343 return -1;
344 }
345 else
346 {
347 BOOL result;
348 DWORD exitcode;
349 PROCESS_INFORMATION proc_info;
350 STARTUPINFO startup_info;
351 MSG msg;
352
353 memset(&startup_info, 0, sizeof(STARTUPINFO));
354 startup_info.cb = sizeof(STARTUPINFO);
355
356 result = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0,
357 NULL, NULL, &startup_info, &proc_info);
358
359 if (result)
360 {
361 do
362 {
363 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
364 {
365 TranslateMessage(&msg);
366 DispatchMessage(&msg);
367 }
368 process_cmds();
369 Sleep(100);
370 GetExitCodeProcess(proc_info.hProcess, &exitcode);
371 }
372 while (exitcode == STILL_ACTIVE);
373
374 // Release handles
375 CloseHandle(proc_info.hProcess);
376 CloseHandle(proc_info.hThread);
377 }
378 else
379 {
380 // CreateProcess failed.
381 char msg[256];
382 _snprintf(msg, sizeof(msg),
383 "Unable to launch the requested application:\n%s", cmdline);
384 message(msg);
385 }
386 }
387
388 WTSUnRegisterSessionNotification(g_hwnd);
389
390 remove_hooks_fn();
391
392 FreeLibrary(hookdll);
393
394 vchannel_close();
395
396 return 1;
397 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26