void uv_process_pipe_connect_req(uv_pipe_t* handle, uv_connect_t* req) { assert(handle->type == UV_NAMED_PIPE); if (req->cb) { if (REQ_SUCCESS(req)) { uv_pipe_connection_init(handle); ((uv_connect_cb)req->cb)(req, 0); } else { LOOP->last_error = GET_REQ_UV_ERROR(req); ((uv_connect_cb)req->cb)(req, -1); } } DECREASE_PENDING_REQ_COUNT(handle); }
void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req) { uv_buf_t buf; assert(handle->type == UV_TTY); buf = handle->read_line_buffer; handle->flags &= ~UV_HANDLE_READ_PENDING; handle->read_line_buffer = uv_null_buf_; if (!REQ_SUCCESS(req)) { /* Read was not successful */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_TTY_RAW)) { /* Real error */ handle->flags &= ~UV_HANDLE_READING; loop->last_error = GET_REQ_UV_ERROR(req); handle->read_cb((uv_stream_t*) handle, -1, buf); } else { /* The read was cancelled, or whatever we don't care */ uv_set_sys_error(loop, WSAEWOULDBLOCK); /* maps to UV_EAGAIN */ handle->read_cb((uv_stream_t*) handle, 0, buf); } } else { /* Read successful */ /* TODO: read unicode, convert to utf-8 */ DWORD bytes = req->overlapped.InternalHigh; if (bytes == 0) { uv_set_sys_error(loop, WSAEWOULDBLOCK); /* maps to UV_EAGAIN */ } handle->read_cb((uv_stream_t*) handle, bytes, buf); } /* Wait for more input events. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { uv_tty_queue_read(loop, handle); } DECREASE_PENDING_REQ_COUNT(handle); }
void uv_process_pipe_write_req(uv_pipe_t* handle, uv_write_t* req) { assert(handle->type == UV_NAMED_PIPE); handle->write_queue_size -= req->queued_bytes; if (req->cb) { if (!REQ_SUCCESS(req)) { LOOP->last_error = GET_REQ_UV_ERROR(req); ((uv_write_cb)req->cb)(req, -1); } else { ((uv_write_cb)req->cb)(req, 0); } } handle->write_reqs_pending--; if (handle->write_reqs_pending == 0 && handle->flags & UV_HANDLE_SHUTTING) { uv_want_endgame((uv_handle_t*)handle); } DECREASE_PENDING_REQ_COUNT(handle); }
void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req) { /* Shortcut for handle->last_input_record.Event.KeyEvent. */ #define KEV handle->last_input_record.Event.KeyEvent DWORD records_left, records_read; uv_buf_t buf; off_t buf_used; assert(handle->type == UV_TTY); handle->flags &= ~UV_HANDLE_READ_PENDING; if (!(handle->flags & UV_HANDLE_READING) || !(handle->flags & UV_HANDLE_TTY_RAW)) { goto out; } if (!REQ_SUCCESS(req)) { /* An error occurred while waiting for the event. */ if ((handle->flags & UV_HANDLE_READING)) { handle->flags &= ~UV_HANDLE_READING; loop->last_error = GET_REQ_UV_ERROR(req); handle->read_cb((uv_stream_t*)handle, -1, uv_null_buf_); } goto out; } /* Fetch the number of events */ if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) { handle->flags &= ~UV_HANDLE_READING; uv_set_sys_error(loop, GetLastError()); handle->read_cb((uv_stream_t*)handle, -1, uv_null_buf_); goto out; } /* Windows sends a lot of events that we're not interested in, so buf */ /* will be allocated on demand, when there's actually something to emit. */ buf = uv_null_buf_; buf_used = 0; while ((records_left > 0 || handle->last_key_len > 0) && (handle->flags & UV_HANDLE_READING)) { if (handle->last_key_len == 0) { /* Read the next input record */ if (!ReadConsoleInputW(handle->handle, &handle->last_input_record, 1, &records_read)) { uv_set_sys_error(loop, GetLastError()); handle->flags &= ~UV_HANDLE_READING; handle->read_cb((uv_stream_t*) handle, -1, buf); goto out; } records_left--; /* Ignore events that are not keyboard events */ if (handle->last_input_record.EventType != KEY_EVENT) { continue; } /* Ignore keyup events, unless the left alt key was held and a valid */ /* unicode character was emitted. */ if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) || KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) { continue; } /* Ignore keypresses to numpad number keys if the left alt is held */ /* because the user is composing a character, or windows simulating */ /* this. */ if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) && !(KEV.dwControlKeyState & ENHANCED_KEY) && (KEV.wVirtualKeyCode == VK_INSERT || KEV.wVirtualKeyCode == VK_END || KEV.wVirtualKeyCode == VK_DOWN || KEV.wVirtualKeyCode == VK_NEXT || KEV.wVirtualKeyCode == VK_LEFT || KEV.wVirtualKeyCode == VK_CLEAR || KEV.wVirtualKeyCode == VK_RIGHT || KEV.wVirtualKeyCode == VK_HOME || KEV.wVirtualKeyCode == VK_UP || KEV.wVirtualKeyCode == VK_PRIOR || KEV.wVirtualKeyCode == VK_NUMPAD0 || KEV.wVirtualKeyCode == VK_NUMPAD1 || KEV.wVirtualKeyCode == VK_NUMPAD2 || KEV.wVirtualKeyCode == VK_NUMPAD3 || KEV.wVirtualKeyCode == VK_NUMPAD4 || KEV.wVirtualKeyCode == VK_NUMPAD5 || KEV.wVirtualKeyCode == VK_NUMPAD6 || KEV.wVirtualKeyCode == VK_NUMPAD7 || KEV.wVirtualKeyCode == VK_NUMPAD8 || KEV.wVirtualKeyCode == VK_NUMPAD9)) { continue; } if (KEV.uChar.UnicodeChar != 0) { int prefix_len, char_len; /* Character key pressed */ if (KEV.uChar.UnicodeChar >= 0xD800 && KEV.uChar.UnicodeChar < 0xDC00) { /* UTF-16 high surrogate */ handle->last_utf16_high_surrogate = KEV.uChar.UnicodeChar; continue; } /* Prefix with \u033 if alt was held, but alt was not used as part */ /* a compose sequence. */ if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) { handle->last_key[0] = '\033'; prefix_len = 1; } else { prefix_len = 0; } if (KEV.uChar.UnicodeChar >= 0xDC00 && KEV.uChar.UnicodeChar < 0xE000) { /* UTF-16 surrogate pair */ WCHAR utf16_buffer[2] = { handle->last_utf16_high_surrogate, KEV.uChar.UnicodeChar}; char_len = WideCharToMultiByte(CP_UTF8, 0, utf16_buffer, 2, &handle->last_key[prefix_len], sizeof handle->last_key, NULL, NULL); } else { /* Single UTF-16 character */ char_len = WideCharToMultiByte(CP_UTF8, 0, &KEV.uChar.UnicodeChar, 1, &handle->last_key[prefix_len], sizeof handle->last_key, NULL, NULL); } /* Whatever happened, the last character wasn't a high surrogate. */ handle->last_utf16_high_surrogate = 0; /* If the utf16 character(s) couldn't be converted something must */ /* be wrong. */ if (!char_len) { uv_set_sys_error(loop, GetLastError()); handle->flags &= ~UV_HANDLE_READING; handle->read_cb((uv_stream_t*) handle, -1, buf); goto out; } handle->last_key_len = (unsigned char) (prefix_len + char_len); handle->last_key_offset = 0; continue; } else { /* Function key pressed */ const char* vt100; size_t prefix_len, vt100_len; vt100 = get_vt100_fn_key(KEV.wVirtualKeyCode, !!(KEV.dwControlKeyState & SHIFT_PRESSED), !!(KEV.dwControlKeyState & ( LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)), &vt100_len); /* If we were unable to map to a vt100 sequence, just ignore. */ if (!vt100) { continue; } /* Prefix with \x033 when the alt key was held. */ if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { handle->last_key[0] = '\033'; prefix_len = 1; } else { prefix_len = 0; } /* Copy the vt100 sequence to the handle buffer. */ assert(prefix_len + vt100_len < sizeof handle->last_key); memcpy(&handle->last_key[prefix_len], vt100, vt100_len); handle->last_key_len = (unsigned char) (prefix_len + vt100_len); handle->last_key_offset = 0; continue; } } else { /* Copy any bytes left from the last keypress to the user buffer. */ if (handle->last_key_offset < handle->last_key_len) { /* Allocate a buffer if needed */ if (buf_used == 0) { buf = handle->alloc_cb((uv_handle_t*) handle, 1024); } buf.base[buf_used++] = handle->last_key[handle->last_key_offset++]; /* If the buffer is full, emit it */ if (buf_used == buf.len) { handle->read_cb((uv_stream_t*) handle, buf_used, buf); buf = uv_null_buf_; buf_used = 0; } continue; } /* Apply dwRepeat from the last input record. */ if (--KEV.wRepeatCount > 0) { handle->last_key_offset = 0; continue; } handle->last_key_len = 0; continue; } } /* Send the buffer back to the user */ if (buf_used > 0) { handle->read_cb((uv_stream_t*) handle, buf_used, buf); } out: /* Wait for more input events. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { uv_tty_queue_read(loop, handle); } DECREASE_PENDING_REQ_COUNT(handle); #undef KEV }
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; char* filename = NULL; int utf8size; DWORD offset = 0; assert(req->type == UV_FS_EVENT_REQ); assert(handle->req_pending); handle->req_pending = 0; file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset); if (REQ_SUCCESS(req)) { if (req->overlapped.InternalHigh > 0) { do { file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset); /* * Fire the event only if we were asked to watch a directory, * or if the filename filter matches. */ if (handle->is_path_dir || _wcsnicmp(handle->filew, file_info->FileName, file_info->FileNameLength / sizeof(wchar_t)) == 0) { /* Convert the filename to utf8. */ utf8size = uv_utf16_to_utf8(file_info->FileName, file_info->FileNameLength / sizeof(wchar_t), NULL, 0); if (utf8size) { filename = (char*)malloc(utf8size + 1); if (!filename) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } utf8size = uv_utf16_to_utf8(file_info->FileName, file_info->FileNameLength / sizeof(wchar_t), filename, utf8size); if (utf8size) { filename[utf8size] = L'\0'; } else { free(filename); filename = NULL; } } switch (file_info->Action) { case FILE_ACTION_ADDED: case FILE_ACTION_REMOVED: case FILE_ACTION_RENAMED_OLD_NAME: case FILE_ACTION_RENAMED_NEW_NAME: handle->cb(handle, filename, UV_RENAME, 0); break; case FILE_ACTION_MODIFIED: handle->cb(handle, filename, UV_CHANGE, 0); break; } free(filename); filename = NULL; } offset = file_info->NextEntryOffset; } while(offset); } else { handle->cb(handle, NULL, UV_CHANGE, 0); } } else { loop->last_error = GET_REQ_UV_ERROR(req); handle->cb(handle, NULL, 0, -1); } if (!(handle->flags & UV_HANDLE_CLOSING)) { uv_fs_event_queue_readdirchanges(loop, handle); } else { uv_want_endgame(loop, (uv_handle_t*)handle); } }