/[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 1163 - (show annotations)
Mon Mar 20 10:31:58 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 8976 byte(s)
Add serial numbers to protocol.

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26