void *thread_vchannel_process (void * arg) { struct stream* s = NULL; int rv; int length; int total_length; signal(SIGCHLD, handler); cliprdr_send_ready(); cliprdr_send_capability(); while(running){ make_stream(s); init_stream(s, 1600); rv = vchannel_receive(cliprdr_channel, s->data, &length, &total_length); if( rv == ERROR ) { log_message(l_config, LOG_LEVEL_ERROR, "vchannel_cliprdr[thread_vchannel_process]: " "Invalid message"); vchannel_close(cliprdr_channel); pthread_exit ((void*)1); } switch(rv) { case ERROR: log_message(l_config, LOG_LEVEL_ERROR, "vchannel_cliprdr[thread_vchannel_process]: " "Invalid message"); break; case STATUS_CONNECTED: log_message(l_config, LOG_LEVEL_DEBUG, "vchannel_cliprdr[thread_vchannel_process]: " "Status connected"); break; case STATUS_DISCONNECTED: log_message(l_config, LOG_LEVEL_DEBUG, "vchannel_cliprdr[thread_vchannel_process]: " "Status disconnected"); running = 0; // Send a dummy event in order to unblock XNextEvent function send_dummy_event(); break; default: if (length == 0) { running = false; send_dummy_event(); pthread_exit (0); } cliprdr_process_message(s, length, total_length); break; } free_stream(s); } pthread_exit (0); }
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // remember our instance handle g_instance = hinstDLL; g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL"); if (!g_mutex) return FALSE; WaitForSingleObject(g_mutex, INFINITE); ++g_instance_count; ReleaseMutex(g_mutex); g_wm_seamless_focus_request = RegisterWindowMessage(FOCUS_REQUEST_MSG_NAME); g_wm_seamless_focus_release = RegisterWindowMessage(FOCUS_RELEASE_MSG_NAME); g_internal_window = get_internal_window(); vchannel_open(); getScreenSize(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0); WaitForSingleObject(g_mutex, INFINITE); --g_instance_count; ReleaseMutex(g_mutex); vchannel_close(); CloseHandle(g_mutex); break; } return TRUE; }
void SeamlessChannel_uninit() { vchannel_close(); WaitForSingleObject(g_mutex_orders, INFINITE); if (g_last_state_order) { free(g_last_state_order); g_last_state_order = NULL; } if (g_last_position_order) { free(g_last_position_order); g_last_position_order = NULL; } if (g_last_destroy_order) { free(g_last_destroy_order); g_last_destroy_order = NULL; } if (g_last_zchange_order) { free(g_last_zchange_order); g_last_zchange_order = NULL; } if (g_last_focus_order) { free(g_last_focus_order); g_last_focus_order = NULL; } ReleaseMutex(g_mutex_orders); CloseHandle(g_mutex_orders); g_mutex_orders = NULL; WaitForSingleObject(g_mutex_focus, INFINITE); ReleaseMutex(g_mutex_focus); CloseHandle(g_mutex_focus); g_mutex_focus = NULL; }
int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow) { int success = 0; HANDLE helper = NULL; HMODULE hookdll = NULL; SYSTEM_INFO si; set_hooks_proc_t set_hooks_fn; remove_hooks_proc_t remove_hooks_fn; get_instance_count_proc_t instance_count_fn; int check_counter; if (strlen(cmdline) == 0) { message("No command line specified."); return -1; } if (vchannel_open()) { message("Unable to set up the virtual channel."); return -1; } GetSystemInfo(&si); switch (si.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: hookdll = LoadLibrary("seamlessrdp32.dll"); break; case PROCESSOR_ARCHITECTURE_AMD64: hookdll = LoadLibrary("seamlessrdp64.dll"); break; default: message("Unsupported processor architecture."); break; } if (!hookdll) { message("Could not load hook DLL. Unable to continue."); goto close_vchannel; } 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"); g_set_state_fn = (set_state_proc_t) GetProcAddress(hookdll, "SafeSetState"); if (!set_hooks_fn || !remove_hooks_fn || !instance_count_fn || !g_move_window_fn || !g_zchange_fn || !g_focus_fn || !g_set_state_fn) { message ("Hook DLL doesn't contain the correct functions. Unable to continue."); goto close_hookdll; } /* Check if the DLL is already loaded */ switch (instance_count_fn()) { case 0: message("Hook DLL failed to initialize."); goto close_hookdll; break; case 1: break; default: message("Another running instance of Seamless RDP detected."); goto close_hookdll; } helper = launch_helper(); ProcessIdToSessionId(GetCurrentProcessId(), &g_session_id); build_startup_procs(); g_connected = is_connected(); g_desktop_hidden = is_desktop_hidden(); vchannel_write("HELLO", "0x%08x", g_desktop_hidden ? SEAMLESS_HELLO_HIDDEN : 0); set_hooks_fn(); /* Since we don't see the entire desktop we must resize windows immediatly. */ SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0); /* Disable screen saver since we cannot catch its windows. */ SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); /* We don't want windows denying requests to activate windows. */ SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0); if (!launch_app(cmdline)) { // CreateProcess failed. char msg[256]; _snprintf(msg, sizeof(msg), "Unable to launch the requested application:\n%s", cmdline); message(msg); goto unhook; } check_counter = 5; while (check_counter-- || !should_terminate()) { BOOL connected; MSG msg; connected = is_connected(); if (connected && !g_connected) { int flags; /* These get reset on each reconnect */ SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0); SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0); flags = SEAMLESS_HELLO_RECONNECT; if (g_desktop_hidden) flags |= SEAMLESS_HELLO_HIDDEN; vchannel_write("HELLO", "0x%08x", flags); } g_connected = connected; if (check_counter < 0) { BOOL hidden; hidden = is_desktop_hidden(); if (hidden && !g_desktop_hidden) vchannel_write("HIDE", "0x%08x", 0); else if (!hidden && g_desktop_hidden) vchannel_write("UNHIDE", "0x%08x", 0); g_desktop_hidden = hidden; check_counter = 5; } while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } process_cmds(); Sleep(100); } success = 1; unhook: remove_hooks_fn(); free_startup_procs(); if (helper) { // Terminate seamlessrdphook32.exe kill_15_9(helper, "SeamlessRDPHook", HELPER_TIMEOUT); } close_hookdll: FreeLibrary(hookdll); close_vchannel: vchannel_close(); // Logoff the user. This is necessary because the session may // have started processes that are not included in Microsofts // list of processes to ignore. Typically ieuser.exe. // FIXME: Only do this if WTSQuerySessionInformation indicates // that we are the initial program. ExitWindows(0, 0); if (success) return 1; else return -1; }
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved) { HANDLE filemapping = NULL; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // remember our instance handle g_instance = hinstDLL; g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL"); filemapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shared_variables), "Local\\SeamlessRDPData"); if (filemapping) { /* From MSDN: The initial contents of the pages in a file mapping object backed by the paging file are 0 (zero)." */ g_shdata = MapViewOfFile(filemapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); } if (g_mutex && filemapping && g_shdata && vchannel_open() == 0) { WaitForSingleObject(g_mutex, INFINITE); ++g_shdata->instance_count; ReleaseMutex(g_mutex); g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (vchannel_is_open()) { vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0); vchannel_close(); } if (g_mutex) { WaitForSingleObject(g_mutex, INFINITE); if (g_shdata) { --g_shdata->instance_count; UnmapViewOfFile(g_shdata); } ReleaseMutex(g_mutex); CloseHandle(g_mutex); } if (filemapping) { CloseHandle(filemapping); } break; } return TRUE; }