/[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 1153 - (show annotations)
Fri Mar 17 09:55:35 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 8877 byte(s)
Handle FOCUS. We need to do this via an extra message because a process is
only allowed to focus its own windows.

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26