bool VDAgent::handle_clipboard_grab(VDAgentClipboardGrab* clipboard_grab, uint32_t size) { std::set<uint32_t> grab_formats; _grab_types.clear(); for (uint32_t i = 0; i < size / sizeof(clipboard_grab->types[0]); i++) { vd_printf("grab type %u", clipboard_grab->types[i]); uint32_t format = get_clipboard_format(clipboard_grab->types[i]); //On first supported type, open and empty the clipboard if (format && grab_formats.empty()) { if (!OpenClipboard(_hwnd)) { return false; } EmptyClipboard(); } //For all supported type set delayed rendering if (format) { _grab_types.insert(clipboard_grab->types[i]); if (grab_formats.insert(format).second) { SetClipboardData(format, NULL); } } } if (grab_formats.empty()) { vd_printf("No supported clipboard types in client grab"); return true; } CloseClipboard(); set_clipboard_owner(owner_client); return true; }
void VDAgent::write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped) { VDAgent* a = _singleton; VDIChunk* chunk; DWORD count; ASSERT(!a->_message_queue.empty()); if (err != 0) { vd_printf("vio_serial write completion error %lu", err); a->_running = false; return; } MUTEX_LOCK(a->_message_mutex); a->_write_pos += bytes; chunk = a->_message_queue.front(); count = sizeof(VDIChunk) + chunk->hdr.size - a->_write_pos; if (count == 0) { a->_message_queue.pop(); a->_write_pos = 0; delete chunk; if (!a->_message_queue.empty()) { chunk = a->_message_queue.front(); count = sizeof(VDIChunk) + chunk->hdr.size; } } if (count) { if (!WriteFileEx(a->_vio_serial, (char*)chunk + a->_write_pos, count, overlapped, write_completion) && GetLastError() != ERROR_IO_PENDING) { vd_printf("vio_serial write error %lu", GetLastError()); a->_running = false; } } MUTEX_UNLOCK(a->_message_mutex); }
DWORD WINAPI VDService::control_handler(DWORD control, DWORD event_type, LPVOID event_data, LPVOID context) { VDService* s = _singleton; DWORD ret = NO_ERROR; ASSERT(s); switch (control) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: vd_printf("Stop service"); s->_status.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(s->_status_handle, &s->_status); s->stop(); break; case SERVICE_CONTROL_INTERROGATE: vd_printf("Interrogate service"); SetServiceStatus(s->_status_handle, &s->_status); break; case SERVICE_CONTROL_SESSIONCHANGE: { DWORD session_id = ((WTSSESSION_NOTIFICATION*)event_data)->dwSessionId; vd_printf("Session %lu %s", session_id, session_events[event_type]); SetServiceStatus(s->_status_handle, &s->_status); if (event_type == WTS_CONSOLE_CONNECT) { s->_session_id = session_id; s->set_control_event(VD_CONTROL_RESTART_AGENT); } break; } default: vd_printf("Unsupported control %lu", control); ret = ERROR_CALL_NOT_IMPLEMENTED; } return ret; }
bool VDAgent::send_input() { bool ret = true; _desktop_layout->lock(); if (_pending_input) { if (KillTimer(_hwnd, VD_TIMER_ID)) { _pending_input = false; } else { vd_printf("KillTimer failed: %lu", GetLastError()); _running = false; _desktop_layout->unlock(); return false; } } if (!SendInput(1, &_input, sizeof(INPUT))) { DWORD err = GetLastError(); // Don't stop agent due to UIPI blocking, which is usually only for specific windows // of system security applications (anti-viruses etc.) if (err != ERROR_SUCCESS && err != ERROR_ACCESS_DENIED) { vd_printf("SendInput failed: %lu", err); ret = _running = false; } } _input_time = GetTickCount(); _desktop_layout->unlock(); return ret; }
void VDAgent::handle_control_event() { MUTEX_LOCK(_control_mutex); while (_control_queue.size()) { int control_command = _control_queue.front(); _control_queue.pop(); vd_printf("Control command %d", control_command); switch (control_command) { case CONTROL_STOP: _running = false; break; case CONTROL_DESKTOP_SWITCH: _desktop_switch = true; break; case CONTROL_LOGON: vd_printf("session logon"); // loading the display settings for the current session's logged on user only // after 1) we receive logon event, and 2) the desktop switched from Winlogon if (!_logon_desktop) { vd_printf("LOGON display setting"); _display_setting.load(); } else { _logon_occured = true; } break; case CONTROL_CLIPBOARD: _clipboard_tick = 0; break; default: vd_printf("Unsupported control command %u", control_command); } } MUTEX_UNLOCK(_control_mutex); }
void VDAgent::dispatch_message(VDAgentMessage* msg, uint32_t port) { bool res = true; switch (msg->type) { case VD_AGENT_MOUSE_STATE: res = handle_mouse_event((VDAgentMouseState*)msg->data); break; case VD_AGENT_MONITORS_CONFIG: res = handle_mon_config((VDAgentMonitorsConfig*)msg->data, port); break; case VD_AGENT_CLIPBOARD: handle_clipboard((VDAgentClipboard*)msg->data, msg->size - sizeof(VDAgentClipboard)); break; case VD_AGENT_CLIPBOARD_GRAB: handle_clipboard_grab((VDAgentClipboardGrab*)msg->data, msg->size); break; case VD_AGENT_CLIPBOARD_REQUEST: res = handle_clipboard_request((VDAgentClipboardRequest*)msg->data); if (!res) { VDAgentClipboard clipboard = {VD_AGENT_CLIPBOARD_NONE}; res = write_message(VD_AGENT_CLIPBOARD, sizeof(clipboard), &clipboard); } break; case VD_AGENT_CLIPBOARD_RELEASE: handle_clipboard_release(); break; case VD_AGENT_DISPLAY_CONFIG: res = handle_display_config((VDAgentDisplayConfig*)msg->data, port); break; case VD_AGENT_ANNOUNCE_CAPABILITIES: res = handle_announce_capabilities((VDAgentAnnounceCapabilities*)msg->data, msg->size); break; case VD_AGENT_FILE_XFER_START: case VD_AGENT_FILE_XFER_STATUS: case VD_AGENT_FILE_XFER_DATA: { VDAgentFileXferStatusMessage status; if (_file_xfer.dispatch(msg, &status)) { write_message(VD_AGENT_FILE_XFER_STATUS, sizeof(status), &status); } break; } case VD_AGENT_CLIENT_DISCONNECTED: vd_printf("Client disconnected, agent to be restarted"); set_control_event(CONTROL_STOP); break; case VD_AGENT_MAX_CLIPBOARD: res = handle_max_clipboard((VDAgentMaxClipboard*)msg->data, msg->size); break; default: vd_printf("Unsupported message type %u size %u", msg->type, msg->size); } if (!res) { vd_printf("handling message type %u failed: %lu", msg->type, GetLastError()); _running = false; } }
/* ================================================================================== Funtion :handle_tss_error Input :struct ctx_reg *reg < context register information > uint32_t error_code < error code> Output :void Return :void Description :default handler(10) for tss error exception ================================================================================== */ LOCAL void handle_tss_error(struct ctx_reg *reg, uint32_t error_code) { static tss_error = 0; if (tss_error++) { vd_printf("error code:%u\n", error_code); vd_printf("tss error[0x%08X]\n", error_code); for (;;); } }
LRESULT CALLBACK VDAgent::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { VDAgent* a = _singleton; switch (message) { case WM_DISPLAYCHANGE: vd_printf("Display change"); // the desktop layout needs to be updated for the mouse // position to be scaled correctly if (!a->_updating_display_config) a->_desktop_layout->get_displays(); break; case WM_TIMER: a->send_input(); break; case WM_CHANGECBCHAIN: if (a->_hwnd_next_viewer == (HWND)wparam) { a->_hwnd_next_viewer = (HWND)lparam; } else if (a->_hwnd_next_viewer) { SendMessage(a->_hwnd_next_viewer, message, wparam, lparam); } break; case WM_CLIPBOARDUPDATE: case WM_DRAWCLIPBOARD: if (a->_hwnd != GetClipboardOwner()) { a->set_clipboard_owner(a->owner_none); a->on_clipboard_grab(); } if (a->_hwnd_next_viewer) { SendMessage(a->_hwnd_next_viewer, message, wparam, lparam); } break; case WM_RENDERFORMAT: a->on_clipboard_request((UINT)wparam); break; case WM_ENDSESSION: if (wparam) { vd_printf("Session ended"); if (a->_clipboard_owner == owner_guest) { a->set_clipboard_owner(owner_none); } a->set_control_event(CONTROL_STOP); } break; case WM_WTSSESSION_CHANGE: if (wparam == WTS_SESSION_LOGON) { a->set_control_event(CONTROL_LOGON); } break; default: return DefWindowProc(hwnd, message, wparam, lparam); } return 0; }
bool VDAgent::handle_max_clipboard(VDAgentMaxClipboard *msg, uint32_t size) { if (size != sizeof(VDAgentMaxClipboard)) { vd_printf("VDAgentMaxClipboard: unexpected msg size %u (expected %lu)", size, (unsigned long)sizeof(VDAgentMaxClipboard)); return false; } vd_printf("Set max clipboard size: %d", msg->max); _max_clipboard = msg->max; return true; }
void VDAgent::on_clipboard_grab() { uint32_t types[clipboard_formats_count * VD_CLIPBOARD_FORMAT_MAX_TYPES]; int count = 0; if (!VD_AGENT_HAS_CAPABILITY(_client_caps, _client_caps_size, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) { return; } if (CountClipboardFormats() == 0) { return; } for (unsigned int i = 0; i < clipboard_formats_count; i++) { if (IsClipboardFormatAvailable(clipboard_formats[i].format)) { for (uint32_t* ptype = clipboard_formats[i].types; *ptype; ptype++) { types[count++] = *ptype; } } } if (count) { write_message(VD_AGENT_CLIPBOARD_GRAB, count * sizeof(types[0]), types); set_clipboard_owner(owner_guest); } else { UINT format = 0; while ((format = EnumClipboardFormats(format))) { vd_printf("Unsupported clipboard format %u", format); } } }
void log_version() { DWORD handle; TCHAR module_fname[MAX_PATH]; TCHAR* info_buf = NULL; try { if (!GetModuleFileName(NULL, module_fname, MAX_PATH)) { throw; } DWORD version_inf_size = GetFileVersionInfoSize(module_fname, &handle); if (version_inf_size == 0) { throw; } TCHAR* info_buf = new TCHAR[version_inf_size]; if (!GetFileVersionInfo(module_fname, handle, version_inf_size, info_buf)) { throw; } UINT size; VS_FIXEDFILEINFO* file_info; if (!VerQueryValue(info_buf, L"\\", (VOID**)&file_info, &size) || size < sizeof(VS_FIXEDFILEINFO)) { throw; } vd_printf("%ld.%ld.%ld.%ld", file_info->dwFileVersionMS >> 16, file_info->dwFileVersionMS & 0x0ffff, file_info->dwFileVersionLS >> 16, file_info->dwFileVersionLS & 0x0ffff); } catch (...) { vd_printf("get version info failed"); } delete[] info_buf; }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :initPit Input :void Output :void Return :ER < error status > Description :intialize a programmable interval timer _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ EXPORT ER initPit(void) { ER err; uint32_t fperiod; /* -------------------------------------------------------------------- */ /* register timer interrupt for irq 0 */ /* -------------------------------------------------------------------- */ err = register_int_handler(INT_IRQ0, pit_intterupt); if (err) { vd_printf("err[%d]:cannot register pit interrupt handler\n", err); return(err); } if (PIT_CLOCK < TIMER_PERIOD) { fperiod = PIT_CLOCK; TIMER_PERIOD = PIT_CLOCK; } else { fperiod = (uint32_t)(1000 / TIMER_PERIOD); } /* -------------------------------------------------------------------- */ /* set 10 ms interval */ /* -------------------------------------------------------------------- */ setPitCounter(fperiod, PIT_COUNTER0, PIT_COM_MODE_SQUAREWAVE); /* -------------------------------------------------------------------- */ /* enable irq 0 */ /* -------------------------------------------------------------------- */ reqEnableIrq(INT_IRQ0); return(E_OK); }
void VDAgent::event_dispatcher(DWORD timeout, DWORD wake_mask) { HANDLE events[] = {_control_event, _stop_event}; DWORD event_count = _stop_event ? 2 : 1; DWORD wait_ret; MSG msg; wait_ret = MsgWaitForMultipleObjectsEx(event_count, events, timeout, wake_mask, MWMO_ALERTABLE); if (wait_ret == WAIT_OBJECT_0 + event_count) { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } return; } switch (wait_ret) { case WAIT_OBJECT_0: handle_control_event(); break; case WAIT_OBJECT_0 + 1: _running = false; break; case WAIT_IO_COMPLETION: case WAIT_TIMEOUT: break; default: vd_printf("MsgWaitForMultipleObjectsEx failed: %lu %lu", wait_ret, GetLastError()); _running = false; } }
bool VDAgent::handle_clipboard(VDAgentClipboard* clipboard, uint32_t size) { HANDLE clip_data; UINT format; bool ret = false; if (_clipboard_owner != owner_client) { vd_printf("Received clipboard data from client while clipboard is not owned by client"); goto fin; } if (clipboard->type == VD_AGENT_CLIPBOARD_NONE) { goto fin; } switch (clipboard->type) { case VD_AGENT_CLIPBOARD_UTF8_TEXT: clip_data = utf8_alloc((LPCSTR)clipboard->data, size); break; case VD_AGENT_CLIPBOARD_IMAGE_PNG: case VD_AGENT_CLIPBOARD_IMAGE_BMP: { DWORD cximage_format = get_cximage_format(clipboard->type); ASSERT(cximage_format); CxImage image(clipboard->data, size, cximage_format); clip_data = image.CopyToHandle(); break; } default: vd_printf("Unsupported clipboard type %u", clipboard->type); goto fin; } format = get_clipboard_format(clipboard->type); if (format == 0) { vd_printf("Unknown clipboard format, type %u", clipboard->type); goto fin; } ret = !!SetClipboardData(format, clip_data); if (!ret) { DWORD err = GetLastError(); if (err == ERROR_NOT_ENOUGH_MEMORY) { vd_printf("Not enough memory to set clipboard data, size %u bytes", size); } else { vd_printf("SetClipboardData failed: %lu", err); } } fin: set_control_event(CONTROL_CLIPBOARD); return ret; }
void VDAgent::set_control_event(int control_command) { MUTEX_LOCK(_control_mutex); _control_queue.push(control_command); if (_control_event && !SetEvent(_control_event)) { vd_printf("SetEvent() failed: %lu", GetLastError()); } MUTEX_UNLOCK(_control_mutex); }
/* * Get memory */ LOCAL void* imalloc( size_t size, IMACB *imacb ) { QUEUE *q; void *mem; UW imask; /* If it is smaller than the minimum fragment size, allocate the minimum size to it. */ if ( size < MIN_FRAGMENT ) { size = MIN_FRAGMENT; } size = ROUND(size); DI(imask); /* Exclusive control by interrupt disable */ /* Search FreeQue */ q = searchFreeArea(size, imacb); if ( q != &imacb->freeque ) { /* There is free area: Split from FreeQue once */ removeFreeQue(q); q = q - 1; } else { /* Reserve new pages because there is no free space */ QUEUE *e; size_t n; /* Reserve pages */ EI(imask); n = PageCount(size + sizeof(QUEUE) * 2); q = GetSysMemBlk(n, imacb->mematr); if ( q == NULL ) { goto err_ret; /* Insufficient memory */ } DI(imask); /* Register on AreaQue */ e = (QUEUE*)((VB*)q + n * pagesz) - 1; insertAreaQue(&imacb->areaque, e); insertAreaQue(&imacb->areaque, q); setAreaFlag(q, AREA_TOP); setAreaFlag(e, AREA_END); } /* Allocate memory */ mem = mem_alloc(q, size, imacb); EI(imask); return mem; err_ret: #ifdef DEBUG TM_DEBUG_PRINT(("imalloc error\n")); #endif vd_printf("error imalloc\n"); return NULL; }
void VDAgent::handle_clipboard_release() { if (_clipboard_owner != owner_client) { vd_printf("Received clipboard release from client while clipboard is not owned by client"); return; } set_control_event(CONTROL_CLIPBOARD); set_clipboard_owner(owner_none); }
/* ================================================================================== Funtion :handle_debug Input :struct ctx_reg *reg < context register information > Output :void Return :void Description :default handler(1) for debug exception ================================================================================== */ LOCAL void handle_debug(struct ctx_reg *reg) { static count = 0; if (!count) { vd_printf("debug\n"); count++; } }
bool VDAgent::init_vio_serial() { _vio_serial = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (_vio_serial == INVALID_HANDLE_VALUE) { vd_printf("Failed opening %ls, error %lu", VIOSERIAL_PORT_PATH, GetLastError()); return false; } return true; }
DWORD WINAPI VDAgent::event_thread_proc(LPVOID param) { HANDLE desktop_event = OpenEvent(SYNCHRONIZE, FALSE, L"WinSta0_DesktopSwitch"); if (!desktop_event) { vd_printf("OpenEvent() failed: %lu", GetLastError()); return 1; } while (_singleton->_running) { DWORD wait_ret = WaitForSingleObject(desktop_event, INFINITE); switch (wait_ret) { case WAIT_OBJECT_0: _singleton->set_control_event(CONTROL_DESKTOP_SWITCH); break; case WAIT_TIMEOUT: default: vd_printf("WaitForSingleObject(): %lu", wait_ret); } } CloseHandle(desktop_event); return 0; }
bool VDAgent::handle_announce_capabilities(VDAgentAnnounceCapabilities* announce_capabilities, uint32_t msg_size) { uint32_t caps_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(msg_size); vd_printf("Got capabilities (%d)", caps_size); for (uint32_t i = 0 ; i < caps_size; ++i) { vd_printf("%X", announce_capabilities->caps[i]); } if (caps_size != _client_caps_size) { delete[] _client_caps; _client_caps = new uint32_t[caps_size]; ASSERT(_client_caps != NULL); _client_caps_size = caps_size; } memcpy(_client_caps, announce_capabilities->caps, sizeof(_client_caps[0]) * caps_size); if (announce_capabilities->request) { return send_announce_capabilities(false); } return true; }
bool VDAgent::send_announce_capabilities(bool request) { DWORD msg_size; VDIChunk* caps_chunk; VDAgentMessage* caps_msg; VDAgentAnnounceCapabilities* caps; uint32_t caps_size; uint32_t internal_msg_size = sizeof(VDAgentAnnounceCapabilities) + VD_AGENT_CAPS_BYTES; msg_size = VD_MESSAGE_HEADER_SIZE + internal_msg_size; caps_chunk = new_chunk(msg_size); if (!caps_chunk) { return false; } caps_size = VD_AGENT_CAPS_SIZE; caps_chunk->hdr.port = VDP_CLIENT_PORT; caps_chunk->hdr.size = sizeof(VDAgentMessage) + internal_msg_size; caps_msg = (VDAgentMessage*)caps_chunk->data; caps_msg->protocol = VD_AGENT_PROTOCOL; caps_msg->type = VD_AGENT_ANNOUNCE_CAPABILITIES; caps_msg->opaque = 0; caps_msg->size = internal_msg_size; caps = (VDAgentAnnounceCapabilities*)caps_msg->data; caps->request = request; memset(caps->caps, 0, VD_AGENT_CAPS_BYTES); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_DISPLAY_CONFIG); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_CRLF); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MAX_CLIPBOARD); vd_printf("Sending capabilities:"); for (uint32_t i = 0 ; i < caps_size; ++i) { vd_printf("%X", caps->caps[i]); } enqueue_chunk(caps_chunk); return true; }
bool VDService::launch_agent() { STARTUPINFO startup_info; BOOL ret = FALSE; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); startup_info.lpDesktop = const_cast<LPTSTR>(TEXT("Winsta0\\winlogon")); ZeroMemory(&_agent_proc_info, sizeof(_agent_proc_info)); if (_system_version == SYS_VER_WIN_XP_CLASS) { if (_session_id == 0) { ret = CreateProcess(_agent_path, _agent_path, NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &_agent_proc_info); } else { for (int i = 0; i < CREATE_PROC_MAX_RETRIES; i++) { ret = create_session_process_as_user(_session_id, TRUE, NULL, NULL, _agent_path, NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &_agent_proc_info); if (ret) { vd_printf("create_session_process_as_user #%d", i); break; } Sleep(CREATE_PROC_INTERVAL_MS); } } } else if (_system_version == SYS_VER_WIN_7_CLASS) { startup_info.lpDesktop = const_cast<LPTSTR>(TEXT("Winsta0\\default")); ret = create_process_as_user(_session_id, _agent_path, _agent_path, NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &_agent_proc_info); } else { vd_printf("Not supported in this system version"); return false; } if (!ret) { vd_printf("CreateProcess() failed: %lu", GetLastError()); return false; } _agent_alive = true; return true; }
bool VDService::kill_agent() { DWORD exit_code = 0; DWORD wait_ret; HANDLE proc_handle; bool ret = true; if (!_agent_alive) { return true; } _agent_alive = false; proc_handle = _agent_proc_info.hProcess; _agent_proc_info.hProcess = 0; SetEvent(_agent_stop_event); if (GetProcessId(proc_handle)) { wait_ret = WaitForSingleObject(proc_handle, VD_AGENT_TIMEOUT); switch (wait_ret) { case WAIT_OBJECT_0: if (GetExitCodeProcess(proc_handle, &exit_code)) { ret = (exit_code != STILL_ACTIVE); } else { vd_printf("GetExitCodeProcess() failed: %lu", GetLastError()); } break; case WAIT_TIMEOUT: vd_printf("Wait timeout"); ret = false; break; case WAIT_FAILED: default: vd_printf("WaitForSingleObject() failed: %lu", GetLastError()); break; } } ResetEvent(_agent_stop_event); CloseHandle(proc_handle); CloseHandle(_agent_proc_info.hThread); ZeroMemory(&_agent_proc_info, sizeof(_agent_proc_info)); return ret; }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :page_fault_handler Input :uint32_t int_num < interrupt number > struct ctx_reg *reg < context register information > uint32_t error_code < error code > unsigned long fault_address < address at which fault occurs > Output :void Return :void Description :handler for page fault _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ EXPORT void page_fault_handler(uint32_t int_num, struct ctx_reg *reg, uint32_t error_code, unsigned long fault_address) { static int count = 0; if (1 <= count) { } else { vd_printf("page fault[0x%08X]\n", fault_address); vd_printf("error code:%u\n", error_code); vd_printf("eax:0x%08X ", reg->eax); vd_printf("ebx:0x%08X ", reg->ebx); vd_printf("ecx:0x%08X\n", reg->ecx); vd_printf("eip:0x%08X ", reg->eip); vd_printf("eflags:0x%08X ", reg->eflags); vd_printf("cs:0x%08X\n", reg->cs); vd_printf("esp:0x%08X ", reg->esp); vd_printf("ss:0x%08X\n", reg->ss); count++; } }
/* ================================================================================== Funtion :ramfs_mount Input :struct file_system_type *fs_type < file system type of ramfs > int flags < mount flags > const char *dev_name < device name to mount > void *data < mount options > Output :void Return :struct dentry* < root dentry of ramfs > Description :mount ramfs ================================================================================== */ LOCAL struct dentry* ramfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { int err; root_sb = sb_cache_alloc(fs_type, 0); if (UNLIKELY(!root_sb)) { vd_printf("ramfs_mount:error:root sb\n"); return(NULL); } vd_printf("ramfs_fill_super\n"); err = ramfs_fill_super(root_sb, NULL, 0); if (UNLIKELY(err)) { sb_cache_free(root_sb); return(NULL); } return(root_sb->s_root); }
void VDAgent::handle_chunk(VDIChunk* chunk) { //FIXME: currently assumes that multi-part msg arrives only from client port if (_in_msg_pos == 0 || chunk->hdr.port == VDP_SERVER_PORT) { if (chunk->hdr.size < sizeof(VDAgentMessage)) { return; } VDAgentMessage* msg = (VDAgentMessage*)chunk->data; if (msg->protocol != VD_AGENT_PROTOCOL) { vd_printf("Invalid protocol %u", msg->protocol); _running = false; return; } uint32_t msg_size = sizeof(VDAgentMessage) + msg->size; if (chunk->hdr.size == msg_size) { dispatch_message(msg, chunk->hdr.port); } else { ASSERT(chunk->hdr.size < msg_size); _in_msg = (VDAgentMessage*)new uint8_t[msg_size]; memcpy(_in_msg, chunk->data, chunk->hdr.size); _in_msg_pos = chunk->hdr.size; } } else { memcpy((uint8_t*)_in_msg + _in_msg_pos, chunk->data, chunk->hdr.size); _in_msg_pos += chunk->hdr.size; // update clipboard tick on each clipboard chunk for timeout setting if (_in_msg->type == VD_AGENT_CLIPBOARD && _clipboard_tick) { _clipboard_tick = GetTickCount(); } if (_in_msg_pos == sizeof(VDAgentMessage) + _in_msg->size) { if (_in_msg->type == VD_AGENT_CLIPBOARD && !_clipboard_tick) { vd_printf("Clipboard received but dropped due to timeout"); } else { dispatch_message(_in_msg, 0); } cleanup_in_msg(); } } }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :init_super_block Input :void Output :void Return :int < result > Description :initialize super block management _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ EXPORT int init_super_block(void) { super_block_cache = kmem_cache_create(super_block_cache_name, sizeof(struct super_block), 0, 0, NULL); if (UNLIKELY(!super_block_cache)) { vd_printf("error:super_block_cache\n"); return(-ENOMEM); } next_ino = 1; return(0); }
VOID VDAgent::read_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped) { VDAgent* a = _singleton; VDIChunk* chunk = (VDIChunk*)a->_read_buf; DWORD count; if (err != 0 && err != ERROR_OPERATION_ABORTED && err != ERROR_NO_SYSTEM_RESOURCES) { vd_printf("vio_serial read completion error %lu", err); a->_running = false; return; } a->_read_pos += bytes; if (a->_read_pos < sizeof(VDIChunk)) { count = sizeof(VDIChunk) - a->_read_pos; } else if (a->_read_pos == sizeof(VDIChunk)) { count = chunk->hdr.size; if (a->_read_pos + count > sizeof(a->_read_buf)) { vd_printf("chunk is too large, size %u port %u", chunk->hdr.size, chunk->hdr.port); a->_running = false; return; } } else if (a->_read_pos == sizeof(VDIChunk) + chunk->hdr.size){ a->handle_chunk(chunk); count = sizeof(VDIChunk); a->_read_pos = 0; } else { ASSERT(a->_read_pos < sizeof(VDIChunk) + chunk->hdr.size); count = sizeof(VDIChunk) + chunk->hdr.size - a->_read_pos; } if (!ReadFileEx(a->_vio_serial, a->_read_buf + a->_read_pos, count, overlapped, read_completion) && GetLastError() != ERROR_IO_PENDING) { vd_printf("vio_serial read error %lu", GetLastError()); a->_running = false; } }
// In delayed rendering, Windows requires us to SetClipboardData before we return from // handling WM_RENDERFORMAT. Therefore, we try our best by sending CLIPBOARD_REQUEST to the // agent, while waiting alertably for a while (hoping for good) for receiving CLIPBOARD data // or CLIPBOARD_RELEASE from the agent, which both will signal clipboard_event. // In case of unsupported format, wrong clipboard owner or no clipboard capability, we do nothing in // WM_RENDERFORMAT and return immediately. // FIXME: need to be handled using request queue void VDAgent::on_clipboard_request(UINT format) { uint32_t type; if (_clipboard_owner != owner_client) { vd_printf("Received render request event for format %u" "while clipboard is not owned by client", format); return; } if (!(type = get_clipboard_type(format))) { vd_printf("Unsupported clipboard format %u", format); return; } if (!VD_AGENT_HAS_CAPABILITY(_client_caps, _client_caps_size, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) { return; } VDAgentClipboardRequest request = {type}; if (!write_message(VD_AGENT_CLIPBOARD_REQUEST, sizeof(request), &request)) { return; } _clipboard_tick = GetTickCount(); while (_running && _clipboard_tick && GetTickCount() < _clipboard_tick + VD_CLIPBOARD_TIMEOUT_MS) { event_dispatcher(VD_CLIPBOARD_TIMEOUT_MS, 0); } if (_clipboard_tick) { vd_printf("Clipboard wait timeout"); _clipboard_tick = 0; } else { // reset incoming message state only upon completion (even after timeout) cleanup_in_msg(); } }