/[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 1186 - (show annotations)
Wed Mar 22 11:56:46 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 9460 byte(s)
Avoid %p since it's implementation defined.

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26