void uv_process_pipe_connect_req(uv_loop_t* loop, 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 { uv__set_sys_error(loop, GET_REQ_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; uv__set_sys_error(loop, GET_REQ_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); }
static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { unsigned char mask_events; int err; if (req == &handle->poll_req_1) { handle->submitted_events_1 = 0; mask_events = handle->mask_events_1; } else if (req == &handle->poll_req_2) { handle->submitted_events_2 = 0; mask_events = handle->mask_events_2; } else { assert(0); return; } if (!REQ_SUCCESS(req)) { /* Error. */ if (handle->events != 0) { err = GET_REQ_ERROR(req); handle->events = 0; /* Stop the watcher */ handle->poll_cb(handle, uv_translate_sys_error(err), 0); } } else { /* Got some events. */ int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events; if (events != 0) { handle->poll_cb(handle, 0, events); } } if ((handle->events & ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { uv__slow_poll_submit_poll_req(loop, handle); } else if ((handle->flags & UV__HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { uv_want_endgame(loop, (uv_handle_t*) handle); } }
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; int err, sizew, size, result; char* filename = NULL; WCHAR* filenamew, *long_filenamew = NULL; DWORD offset = 0; assert(req->type == UV_FS_EVENT_REQ); assert(handle->req_pending); handle->req_pending = 0; /* Don't report any callbacks if: * - We're closing, just push the handle onto the endgame queue * - We are not active, just ignore the callback */ if (!uv__is_active(handle)) { if (handle->flags & UV__HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*) handle); } return; } file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset); if (REQ_SUCCESS(req)) { if (req->u.io.overlapped.InternalHigh > 0) { do { file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset); assert(!filename); assert(!long_filenamew); /* * Fire the event only if we were asked to watch a directory, * or if the filename filter matches. */ if (handle->dirw || _wcsnicmp(handle->filew, file_info->FileName, file_info->FileNameLength / sizeof(WCHAR)) == 0 || _wcsnicmp(handle->short_filew, file_info->FileName, file_info->FileNameLength / sizeof(WCHAR)) == 0) { if (handle->dirw) { /* * We attempt to resolve the long form of the file name explicitly. * We only do this for file names that might still exist on disk. * If this fails, we use the name given by ReadDirectoryChangesW. * This may be the long form or the 8.3 short name in some cases. */ if (file_info->Action != FILE_ACTION_REMOVED && file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) { /* Construct a full path to the file. */ size = wcslen(handle->dirw) + file_info->FileNameLength / sizeof(WCHAR) + 2; filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR)); if (!filenamew) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw, file_info->FileNameLength / sizeof(WCHAR), file_info->FileName); filenamew[size - 1] = L'\0'; /* Convert to long name. */ size = GetLongPathNameW(filenamew, NULL, 0); if (size) { long_filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR)); if (!long_filenamew) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } size = GetLongPathNameW(filenamew, long_filenamew, size); if (size) { long_filenamew[size] = '\0'; } else { uv__free(long_filenamew); long_filenamew = NULL; } } uv__free(filenamew); if (long_filenamew) { /* Get the file name out of the long path. */ result = uv_relative_path(long_filenamew, handle->dirw, &filenamew); uv__free(long_filenamew); if (result == 0) { long_filenamew = filenamew; sizew = -1; } else { long_filenamew = NULL; } } /* * We could not resolve the long form explicitly. * We therefore use the name given by ReadDirectoryChangesW. * This may be the long form or the 8.3 short name in some cases. */ if (!long_filenamew) { filenamew = file_info->FileName; sizew = file_info->FileNameLength / sizeof(WCHAR); } } else { /* * Removed or renamed events cannot be resolved to the long form. * We therefore use the name given by ReadDirectoryChangesW. * This may be the long form or the 8.3 short name in some cases. */ if (!long_filenamew) { filenamew = file_info->FileName; sizew = file_info->FileNameLength / sizeof(WCHAR); } } } else { /* We already have the long name of the file, so just use it. */ filenamew = handle->filew; sizew = -1; } if (filenamew) { /* Convert the filename to utf8. */ size = uv_utf16_to_utf8(filenamew, sizew, NULL, 0); if (size) { filename = (char*)uv__malloc(size + 1); if (!filename) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } size = uv_utf16_to_utf8(filenamew, sizew, filename, size); if (size) { filename[size] = '\0'; } else { uv__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; } uv__free(filename); filename = NULL; uv__free(long_filenamew); long_filenamew = NULL; } offset = file_info->NextEntryOffset; } while (offset && !(handle->flags & UV__HANDLE_CLOSING)); } else { handle->cb(handle, NULL, UV_CHANGE, 0); } } else { err = GET_REQ_ERROR(req); handle->cb(handle, NULL, 0, uv_translate_sys_error(err)); } if (!(handle->flags & UV__HANDLE_CLOSING)) { uv_fs_event_queue_readdirchanges(loop, handle); } else { uv_want_endgame(loop, (uv_handle_t*)handle); } }
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, uv_req_t* req) { DWORD bytes, avail; uv_buf_t buf; uv_ipc_frame_uv_stream ipc_frame; assert(handle->type == UV_NAMED_PIPE); handle->flags &= ~UV_HANDLE_READ_PENDING; eof_timer_stop(handle); if (!REQ_SUCCESS(req)) { /* An error occurred doing the 0-read. */ if (handle->flags & UV_HANDLE_READING) { uv_pipe_read_error_or_eof(loop, handle, GET_REQ_ERROR(req), uv_null_buf_); } } else { /* Do non-blocking reads until the buffer is empty */ while (handle->flags & UV_HANDLE_READING) { if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL)) { uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); break; } if (avail == 0) { /* There is nothing to read after all. */ break; } if (handle->ipc) { /* Use the IPC framing protocol to read the incoming data. */ if (handle->remaining_ipc_rawdata_bytes == 0) { /* We're reading a new frame. First, read the header. */ assert(avail >= sizeof(ipc_frame.header)); if (!ReadFile(handle->handle, &ipc_frame.header, sizeof(ipc_frame.header), &bytes, NULL)) { uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); break; } assert(bytes == sizeof(ipc_frame.header)); assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA | UV_IPC_TCP_CONNECTION)); if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) { assert(avail - sizeof(ipc_frame.header) >= sizeof(ipc_frame.socket_info)); /* Read the TCP socket info. */ if (!ReadFile(handle->handle, &ipc_frame.socket_info, sizeof(ipc_frame) - sizeof(ipc_frame.header), &bytes, NULL)) { uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); break; } assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header)); /* Store the pending socket info. */ assert(!handle->pending_ipc_info.socket_info); handle->pending_ipc_info.socket_info = (WSAPROTOCOL_INFOW*)malloc(sizeof(*(handle->pending_ipc_info.socket_info))); if (!handle->pending_ipc_info.socket_info) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } *(handle->pending_ipc_info.socket_info) = ipc_frame.socket_info; handle->pending_ipc_info.tcp_connection = ipc_frame.header.flags & UV_IPC_TCP_CONNECTION; } if (ipc_frame.header.flags & UV_IPC_RAW_DATA) { handle->remaining_ipc_rawdata_bytes = ipc_frame.header.raw_data_length; continue; } } else { avail = min(avail, (DWORD)handle->remaining_ipc_rawdata_bytes); } } buf = handle->alloc_cb((uv_handle_t*) handle, avail); assert(buf.len > 0); if (ReadFile(handle->handle, buf.base, buf.len, &bytes, NULL)) { /* Successful read */ if (handle->ipc) { assert(handle->remaining_ipc_rawdata_bytes >= bytes); handle->remaining_ipc_rawdata_bytes = handle->remaining_ipc_rawdata_bytes - bytes; if (handle->read2_cb) { handle->read2_cb(handle, bytes, buf, handle->pending_ipc_info.socket_info ? UV_TCP : UV_UNKNOWN_HANDLE); } else if (handle->read_cb) { handle->read_cb((uv_stream_t*)handle, bytes, buf); } if (handle->pending_ipc_info.socket_info) { free(handle->pending_ipc_info.socket_info); handle->pending_ipc_info.socket_info = NULL; } } else { handle->read_cb((uv_stream_t*)handle, bytes, buf); } /* Read again only if bytes == buf.len */ if (bytes <= buf.len) { break; } } else { uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); break; } } /* Post another 0-read if still reading and not closing. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { uv_pipe_queue_read(loop, handle); } } DECREASE_PENDING_REQ_COUNT(handle); }
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 || _wcsnicmp(handle->short_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] = '\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 { if (!(handle->flags & UV_HANDLE_CLOSING)) { handle->cb(handle, NULL, UV_CHANGE, 0); } } } else { uv__set_sys_error(loop, GET_REQ_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); } }
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; int sizew, size, result; char* filename = NULL; wchar_t* filenamew, *long_filenamew = NULL; DWORD offset = 0; assert(req->type == UV_FS_EVENT_REQ); assert(handle->req_pending); handle->req_pending = 0; /* If we're closing, don't report any callbacks, and just push the handle */ /* onto the endgame queue. */ if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*) handle); return; }; 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); assert(!filename); assert(!long_filenamew); /* * Fire the event only if we were asked to watch a directory, * or if the filename filter matches. */ if (handle->dirw || _wcsnicmp(handle->filew, file_info->FileName, file_info->FileNameLength / sizeof(wchar_t)) == 0 || _wcsnicmp(handle->short_filew, file_info->FileName, file_info->FileNameLength / sizeof(wchar_t)) == 0) { if (handle->dirw) { /* * We attempt to convert the file name to its long form for * events that still point to valid files on disk. * For removed and renamed events, we do not provide the file name. */ if (file_info->Action != FILE_ACTION_REMOVED && file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) { /* Construct a full path to the file. */ size = wcslen(handle->dirw) + file_info->FileNameLength / sizeof(wchar_t) + 2; filenamew = (wchar_t*)malloc(size * sizeof(wchar_t)); if (!filenamew) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } _snwprintf(filenamew, size, L"%s\\%s", handle->dirw, file_info->FileName); filenamew[size - 1] = L'\0'; /* Convert to long name. */ size = GetLongPathNameW(filenamew, NULL, 0); if (size) { long_filenamew = (wchar_t*)malloc(size * sizeof(wchar_t)); if (!long_filenamew) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } size = GetLongPathNameW(filenamew, long_filenamew, size); if (size) { long_filenamew[size] = '\0'; } else { free(long_filenamew); long_filenamew = NULL; } } free(filenamew); if (long_filenamew) { /* Get the file name out of the long path. */ result = uv_split_path(long_filenamew, NULL, &filenamew); free(long_filenamew); if (result == 0) { long_filenamew = filenamew; sizew = -1; } else { long_filenamew = NULL; } } /* * If we couldn't get the long name - just use the name * provided by ReadDirectoryChangesW. */ if (!long_filenamew) { filenamew = file_info->FileName; sizew = file_info->FileNameLength / sizeof(wchar_t); } } else { /* Removed or renamed callbacks don't provide filename. */ filenamew = NULL; } } else { /* We already have the long name of the file, so just use it. */ filenamew = handle->filew; sizew = -1; } if (filenamew) { /* Convert the filename to utf8. */ size = uv_utf16_to_utf8(filenamew, sizew, NULL, 0); if (size) { filename = (char*)malloc(size + 1); if (!filename) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } size = uv_utf16_to_utf8(filenamew, sizew, filename, size); if (size) { filename[size] = '\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; free(long_filenamew); long_filenamew = NULL; } offset = file_info->NextEntryOffset; } while (offset && !(handle->flags & UV_HANDLE_CLOSING)); } else { handle->cb(handle, NULL, UV_CHANGE, 0); } } else { uv__set_sys_error(loop, GET_REQ_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); } }
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; uv__set_sys_error(loop, GET_REQ_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_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { DWORD bytes, avail; uv_buf_t buf; assert(handle->type == UV_NAMED_PIPE); handle->flags &= ~UV_HANDLE_READ_PENDING; eof_timer_stop(handle); if (!REQ_SUCCESS(req)) { /* An error occurred doing the 0-read. */ if (handle->flags & UV_HANDLE_READING) { uv_pipe_read_error_or_eof(handle, GET_REQ_ERROR(req), uv_null_buf_); } } else { /* Do non-blocking reads until the buffer is empty */ while (handle->flags & UV_HANDLE_READING) { if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL)) { uv_pipe_read_error_or_eof(handle, GetLastError(), uv_null_buf_); break; } if (avail == 0) { /* There is nothing to read after all. */ break; } buf = handle->alloc_cb((uv_handle_t*) handle, avail); assert(buf.len > 0); if (ReadFile(handle->handle, buf.base, buf.len, &bytes, NULL)) { /* Successful read */ handle->read_cb((uv_stream_t*)handle, bytes, buf); /* Read again only if bytes == buf.len */ if (bytes <= buf.len) { break; } } else { uv_pipe_read_error_or_eof(handle, GetLastError(), uv_null_buf_); break; } } /* Post another 0-read if still reading and not closing. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { uv_pipe_queue_read(handle); } } DECREASE_PENDING_REQ_COUNT(handle); }