/[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 1158 - (show annotations)
Fri Mar 17 13:11:20 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 8728 byte(s)
Encapsulate ZCHANGE and FOCUS requests into safe wrappers to avoid loops.
Setting focus also needed a hack because it killed off menus.

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26