--- sourceforge.net/trunk/seamlessrdp/ServerExe/main.c 2006/03/10 15:25:17 1111 +++ sourceforge.net/trunk/seamlessrdp/ServerExe/main.c 2006/03/17 13:11:20 1158 @@ -24,6 +24,8 @@ #include #include +#include +#include #include "vchannel.h" @@ -31,13 +33,29 @@ #define APP_NAME "SeamlessRDP Shell" +#ifndef WM_WTSSESSION_CHANGE +#define WM_WTSSESSION_CHANGE 0x02B1 +#endif +#ifndef WTS_REMOTE_CONNECT +#define WTS_REMOTE_CONNECT 0x3 +#endif + /* Global data */ static HINSTANCE g_instance; +static HWND g_hwnd; typedef void (*set_hooks_proc_t) (); typedef void (*remove_hooks_proc_t) (); typedef int (*get_instance_count_proc_t) (); +typedef void (*move_window_proc_t) (HWND hwnd, int x, int y, int width, int height); +typedef void (*zchange_proc_t) (HWND hwnd, HWND behind); +typedef void (*focus_proc_t) (HWND hwnd); + +static move_window_proc_t g_move_window_fn = NULL; +static zchange_proc_t g_zchange_fn = NULL; +static focus_proc_t g_focus_fn = NULL; + static void message(const char *text) { @@ -71,7 +89,7 @@ enum_cb(HWND hwnd, LPARAM lparam) { RECT rect; - char title[150]; + unsigned short title[150]; LONG styles; int state; HWND parent; @@ -98,11 +116,9 @@ hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0); - GetWindowText(hwnd, title, sizeof(title)); - - /* FIXME: Strip title of dangerous characters */ + GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title)); - vchannel_write("TITLE,0x%x,%s,0x%x", hwnd, title, 0); + vchannel_write("TITLE,0x%x,%s,0x%x", hwnd, vchannel_strfilter_unicode(title), 0); if (styles & WS_MAXIMIZE) state = 2; @@ -144,6 +160,24 @@ } static void +do_position(HWND hwnd, int x, int y, int width, int height) +{ + g_move_window_fn(hwnd, x, y, width, height); +} + +static void +do_zchange(HWND hwnd, HWND behind) +{ + g_zchange_fn(hwnd, behind); +} + +static void +do_focus(HWND hwnd) +{ + g_focus_fn(hwnd); +} + +static void process_cmds(void) { char line[VCHANNEL_MAX_LINE]; @@ -153,8 +187,6 @@ while ((size = vchannel_read(line, sizeof(line))) >= 0) { - debug("Got: %s", line); - p = line; tok1 = get_token(&p); @@ -169,10 +201,70 @@ if (strcmp(tok1, "SYNC") == 0) do_sync(); else if (strcmp(tok1, "STATE") == 0) - do_state((HWND) strtol(tok2, NULL, 0), strtol(tok3, NULL, 0)); + do_state((HWND) strtoul(tok2, NULL, 0), strtol(tok3, NULL, 0)); + else if (strcmp(tok1, "POSITION") == 0) + do_position((HWND) strtoul(tok2, NULL, 0), strtol(tok3, NULL, 0), + strtol(tok4, NULL, 0), strtol(tok5, NULL, 0), strtol(tok6, NULL, + 0)); + else if (strcmp(tok1, "ZCHANGE") == 0) + do_zchange((HWND) strtoul(tok2, NULL, 0), (HWND) strtoul(tok3, NULL, 0)); + else if (strcmp(tok1, "FOCUS") == 0) + do_focus((HWND) strtoul(tok2, NULL, 0)); } } +static LRESULT CALLBACK +wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_WTSSESSION_CHANGE) + { + if (wparam == WTS_REMOTE_CONNECT) + { + /* These get reset on each reconnect */ + SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0); + SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); + vchannel_write("HELLO,0x%08x", 1); + } + } + + return DefWindowProc(hwnd, message, wparam, lparam); +} + +static BOOL +register_class(void) +{ + WNDCLASSEX wcx; + + memset(&wcx, 0, sizeof(wcx)); + + wcx.cbSize = sizeof(wcx); + wcx.lpfnWndProc = wndproc; + wcx.hInstance = g_instance; + wcx.lpszClassName = "SeamlessClass"; + + return RegisterClassEx(&wcx); +} + +static BOOL +create_wnd(void) +{ + if (!register_class()) + return FALSE; + + g_hwnd = CreateWindow("SeamlessClass", + "Seamless Window", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, (HWND) NULL, (HMENU) NULL, g_instance, (LPVOID) NULL); + + if (!g_hwnd) + return FALSE; + + return TRUE; +} + int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow) { @@ -194,8 +286,12 @@ set_hooks_fn = (set_hooks_proc_t) GetProcAddress(hookdll, "SetHooks"); remove_hooks_fn = (remove_hooks_proc_t) GetProcAddress(hookdll, "RemoveHooks"); instance_count_fn = (get_instance_count_proc_t) GetProcAddress(hookdll, "GetInstanceCount"); + g_move_window_fn = (move_window_proc_t) GetProcAddress(hookdll, "SafeMoveWindow"); + g_zchange_fn = (zchange_proc_t) GetProcAddress(hookdll, "SafeZChange"); + g_focus_fn = (focus_proc_t) GetProcAddress(hookdll, "SafeFocus"); - if (!set_hooks_fn || !remove_hooks_fn || !instance_count_fn) + if (!set_hooks_fn || !remove_hooks_fn || !instance_count_fn || !g_move_window_fn + || !g_zchange_fn || !g_focus_fn) { FreeLibrary(hookdll); message("Hook DLL doesn't contain the correct functions. Unable to continue."); @@ -210,8 +306,19 @@ return -1; } + if (!create_wnd()) + { + FreeLibrary(hookdll); + message("Couldn't create a window to catch events."); + return -1; + } + + WTSRegisterSessionNotification(g_hwnd, NOTIFY_FOR_THIS_SESSION); + vchannel_open(); + vchannel_write("HELLO,0x%08x", 0); + set_hooks_fn(); /* Since we don't see the entire desktop we must resize windows @@ -232,6 +339,7 @@ DWORD exitcode; PROCESS_INFORMATION proc_info; STARTUPINFO startup_info; + MSG msg; memset(&startup_info, 0, sizeof(STARTUPINFO)); startup_info.cb = sizeof(STARTUPINFO); @@ -243,6 +351,11 @@ { do { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } process_cmds(); Sleep(100); GetExitCodeProcess(proc_info.hProcess, &exitcode); @@ -263,6 +376,8 @@ } } + WTSUnRegisterSessionNotification(g_hwnd); + remove_hooks_fn(); FreeLibrary(hookdll);