/[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 1147 - (show annotations)
Thu Mar 16 14:54:02 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 8146 byte(s)
Send a HELLO when starting up and when a client reconnects.

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26