/[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 1160 - (show annotations)
Fri Mar 17 16:23:08 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 8752 byte(s)
Break loops caused by STATE.

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(HWND hwnd, int state)
153 {
154 g_set_state_fn(hwnd, state);
155 }
156
157 static void
158 do_position(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(HWND hwnd, HWND behind)
165 {
166 g_zchange_fn(hwnd, behind);
167 }
168
169 static void
170 do_focus(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((HWND) strtoul(tok2, NULL, 0), strtol(tok3, NULL, 0));
200 else if (strcmp(tok1, "POSITION") == 0)
201 do_position((HWND) strtoul(tok2, NULL, 0), strtol(tok3, NULL, 0),
202 strtol(tok4, NULL, 0), strtol(tok5, NULL, 0), strtol(tok6, NULL,
203 0));
204 else if (strcmp(tok1, "ZCHANGE") == 0)
205 do_zchange((HWND) strtoul(tok2, NULL, 0), (HWND) strtoul(tok3, NULL, 0));
206 else if (strcmp(tok1, "FOCUS") == 0)
207 do_focus((HWND) strtoul(tok2, NULL, 0));
208 }
209 }
210
211 static LRESULT CALLBACK
212 wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
213 {
214 if (message == WM_WTSSESSION_CHANGE)
215 {
216 if (wparam == WTS_REMOTE_CONNECT)
217 {
218 /* These get reset on each reconnect */
219 SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);
220 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
221 vchannel_write("HELLO,0x%08x", 1);
222 }
223 }
224
225 return DefWindowProc(hwnd, message, wparam, lparam);
226 }
227
228 static BOOL
229 register_class(void)
230 {
231 WNDCLASSEX wcx;
232
233 memset(&wcx, 0, sizeof(wcx));
234
235 wcx.cbSize = sizeof(wcx);
236 wcx.lpfnWndProc = wndproc;
237 wcx.hInstance = g_instance;
238 wcx.lpszClassName = "SeamlessClass";
239
240 return RegisterClassEx(&wcx);
241 }
242
243 static BOOL
244 create_wnd(void)
245 {
246 if (!register_class())
247 return FALSE;
248
249 g_hwnd = CreateWindow("SeamlessClass",
250 "Seamless Window",
251 WS_OVERLAPPEDWINDOW,
252 CW_USEDEFAULT,
253 CW_USEDEFAULT,
254 CW_USEDEFAULT,
255 CW_USEDEFAULT, (HWND) NULL, (HMENU) NULL, g_instance, (LPVOID) NULL);
256
257 if (!g_hwnd)
258 return FALSE;
259
260 return TRUE;
261 }
262
263 int WINAPI
264 WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow)
265 {
266 HMODULE hookdll;
267
268 set_hooks_proc_t set_hooks_fn;
269 remove_hooks_proc_t remove_hooks_fn;
270 get_instance_count_proc_t instance_count_fn;
271
272 g_instance = instance;
273
274 hookdll = LoadLibrary("seamlessrdp.dll");
275 if (!hookdll)
276 {
277 message("Could not load hook DLL. Unable to continue.");
278 return -1;
279 }
280
281 set_hooks_fn = (set_hooks_proc_t) GetProcAddress(hookdll, "SetHooks");
282 remove_hooks_fn = (remove_hooks_proc_t) GetProcAddress(hookdll, "RemoveHooks");
283 instance_count_fn = (get_instance_count_proc_t) GetProcAddress(hookdll, "GetInstanceCount");
284 g_move_window_fn = (move_window_proc_t) GetProcAddress(hookdll, "SafeMoveWindow");
285 g_zchange_fn = (zchange_proc_t) GetProcAddress(hookdll, "SafeZChange");
286 g_focus_fn = (focus_proc_t) GetProcAddress(hookdll, "SafeFocus");
287 g_set_state_fn = (set_state_proc_t) GetProcAddress(hookdll, "SafeSetState");
288
289 if (!set_hooks_fn || !remove_hooks_fn || !instance_count_fn || !g_move_window_fn
290 || !g_zchange_fn || !g_focus_fn || !g_set_state_fn)
291 {
292 FreeLibrary(hookdll);
293 message("Hook DLL doesn't contain the correct functions. Unable to continue.");
294 return -1;
295 }
296
297 /* Check if the DLL is already loaded */
298 if (instance_count_fn() != 1)
299 {
300 FreeLibrary(hookdll);
301 message("Another running instance of Seamless RDP detected.");
302 return -1;
303 }
304
305 if (!create_wnd())
306 {
307 FreeLibrary(hookdll);
308 message("Couldn't create a window to catch events.");
309 return -1;
310 }
311
312 WTSRegisterSessionNotification(g_hwnd, NOTIFY_FOR_THIS_SESSION);
313
314 vchannel_open();
315
316 vchannel_write("HELLO,0x%08x", 0);
317
318 set_hooks_fn();
319
320 /* Since we don't see the entire desktop we must resize windows
321 immediatly. */
322 SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);
323
324 /* Disable screen saver since we cannot catch its windows. */
325 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
326
327 if (strlen(cmdline) == 0)
328 {
329 message("No command line specified.");
330 return -1;
331 }
332 else
333 {
334 BOOL result;
335 DWORD exitcode;
336 PROCESS_INFORMATION proc_info;
337 STARTUPINFO startup_info;
338 MSG msg;
339
340 memset(&startup_info, 0, sizeof(STARTUPINFO));
341 startup_info.cb = sizeof(STARTUPINFO);
342
343 result = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0,
344 NULL, NULL, &startup_info, &proc_info);
345
346 if (result)
347 {
348 do
349 {
350 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
351 {
352 TranslateMessage(&msg);
353 DispatchMessage(&msg);
354 }
355 process_cmds();
356 Sleep(100);
357 GetExitCodeProcess(proc_info.hProcess, &exitcode);
358 }
359 while (exitcode == STILL_ACTIVE);
360
361 // Release handles
362 CloseHandle(proc_info.hProcess);
363 CloseHandle(proc_info.hThread);
364 }
365 else
366 {
367 // CreateProcess failed.
368 char msg[256];
369 _snprintf(msg, sizeof(msg),
370 "Unable to launch the requested application:\n%s", cmdline);
371 message(msg);
372 }
373 }
374
375 WTSUnRegisterSessionNotification(g_hwnd);
376
377 remove_hooks_fn();
378
379 FreeLibrary(hookdll);
380
381 vchannel_close();
382
383 return 1;
384 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26