wchar_t* make_program_args(char** args, int verbatim_arguments) { wchar_t* dst; wchar_t* ptr; char** arg; size_t size = 0; size_t len; int arg_count = 0; wchar_t* buffer; int arg_size; int buffer_size = 0; /* Count the required size. */ for (arg = args; *arg; arg++) { arg_size = uv_utf8_to_utf16(*arg, NULL, 0) * sizeof(wchar_t); size += arg_size; buffer_size = arg_size > buffer_size ? arg_size : buffer_size; arg_count++; } /* Adjust for potential quotes. Also assume the worst-case scenario /* that every character needs escaping, so we need twice as much space. */ size = size * 2 + arg_count * 2; dst = (wchar_t*)malloc(size); if (!dst) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } buffer = (wchar_t*)malloc(buffer_size); if (!buffer) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } ptr = dst; for (arg = args; *arg; arg++) { len = uv_utf8_to_utf16(*arg, buffer, (size_t)(size - (ptr - dst))); if (!len) { goto error; } if (verbatim_arguments) { wcscpy(ptr, buffer); ptr += len - 1; } else { ptr = quote_cmd_arg(buffer, ptr); } *ptr++ = *(arg + 1) ? L' ' : L'\0'; } free(buffer); return dst; error: free(dst); free(buffer); return NULL; }
int uv_set_process_title(const char* title) { int err; int length; WCHAR* title_w = NULL; uv__once_init(); /* Find out how big the buffer for the wide-char title must be */ length = uv_utf8_to_utf16(title, NULL, 0); if (!length) { err = GetLastError(); goto done; } /* Convert to wide-char string */ title_w = (WCHAR*)malloc(sizeof(WCHAR) * length); if (!title_w) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } length = uv_utf8_to_utf16(title, title_w, length); if (!length) { err = GetLastError(); goto done; } /* If the title must be truncated insert a \0 terminator there */ if (length > MAX_TITLE_LENGTH) { title_w[MAX_TITLE_LENGTH - 1] = L'\0'; } if (!SetConsoleTitleW(title_w)) { err = GetLastError(); goto done; } EnterCriticalSection(&process_title_lock); free(process_title); process_title = strdup(title); LeaveCriticalSection(&process_title_lock); err = 0; done: free(title_w); return uv_translate_sys_error(err); }
uv_err_t uv_chdir(const char* dir) { uv_err_t err; wchar_t* utf16Buffer = NULL; size_t utf16Size; if (!dir) { err.code = UV_EINVAL; goto done; } utf16Size = uv_utf8_to_utf16(dir, NULL, 0); if (!utf16Size) { err = uv__new_sys_error(GetLastError()); goto done; } utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * utf16Size); if (!utf16Buffer) { err.code = UV_ENOMEM; goto done; } if (!uv_utf8_to_utf16(dir, utf16Buffer, utf16Size)) { err = uv__new_sys_error(GetLastError()); goto done; } if (_wchdir(utf16Buffer) == -1) { err = uv__new_sys_error(_doserrno); goto done; } err = uv_ok_; done: if (utf16Buffer) { free(utf16Buffer); } return err; }
int uv_dlopen(const char* filename, uv_lib_t* lib) { wchar_t filename_w[32768]; lib->handle = NULL; lib->errmsg = NULL; if (!uv_utf8_to_utf16(filename, filename_w, ARRAY_SIZE(filename_w))) { return uv__dlerror(lib, GetLastError()); } lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (lib->handle == NULL) { return uv__dlerror(lib, GetLastError()); } return 0; }
uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { wchar_t filename_w[32768]; HMODULE handle; if (!uv_utf8_to_utf16(filename, filename_w, sizeof(filename_w) / sizeof(wchar_t))) { return uv__new_sys_error(GetLastError()); } handle = LoadLibraryW(filename_w); if (handle == NULL) { return uv__new_sys_error(GetLastError()); } *library = handle; return uv_ok_; }
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags) { int name_size, is_path_dir; DWORD attr, last_error; WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL; WCHAR short_path[MAX_PATH]; if (uv__is_active(handle)) return UV_EINVAL; handle->cb = cb; handle->path = uv__strdup(path); if (!handle->path) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } uv__handle_start(handle); /* Convert name to UTF16. */ name_size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(WCHAR); pathw = (WCHAR*)uv__malloc(name_size); if (!pathw) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } if (!uv_utf8_to_utf16(path, pathw, name_size / sizeof(WCHAR))) { return uv_translate_sys_error(GetLastError()); } /* Determine whether path is a file or a directory. */ attr = GetFileAttributesW(pathw); if (attr == INVALID_FILE_ATTRIBUTES) { last_error = GetLastError(); goto error; } is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; if (is_path_dir) { /* path is a directory, so that's the directory that we will watch. */ handle->dirw = pathw; dir_to_watch = pathw; } else { /* * path is a file. So we split path into dir & file parts, and * watch the dir directory. */ /* Convert to short path. */ if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) { last_error = GetLastError(); goto error; } if (uv_split_path(pathw, &dir, &handle->filew) != 0) { last_error = GetLastError(); goto error; } if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) { last_error = GetLastError(); goto error; } dir_to_watch = dir; uv__free(pathw); pathw = NULL; } handle->dir_handle = CreateFileW(dir_to_watch, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (dir) { uv__free(dir); dir = NULL; } if (handle->dir_handle == INVALID_HANDLE_VALUE) { last_error = GetLastError(); goto error; } if (CreateIoCompletionPort(handle->dir_handle, handle->loop->iocp, (ULONG_PTR)handle, 0) == NULL) { last_error = GetLastError(); goto error; } if (!handle->buffer) { handle->buffer = (char*)uv__malloc(uv_directory_watcher_buffer_size); } if (!handle->buffer) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } memset(&(handle->req.u.io.overlapped), 0, sizeof(handle->req.u.io.overlapped)); if (!ReadDirectoryChangesW(handle->dir_handle, handle->buffer, uv_directory_watcher_buffer_size, (flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, NULL, &handle->req.u.io.overlapped, NULL)) { last_error = GetLastError(); goto error; } handle->req_pending = 1; return 0; error: if (handle->path) { uv__free(handle->path); handle->path = NULL; } if (handle->filew) { uv__free(handle->filew); handle->filew = NULL; } if (handle->short_filew) { uv__free(handle->short_filew); handle->short_filew = NULL; } uv__free(pathw); if (handle->dir_handle != INVALID_HANDLE_VALUE) { CloseHandle(handle->dir_handle); handle->dir_handle = INVALID_HANDLE_VALUE; } if (handle->buffer) { uv__free(handle->buffer); handle->buffer = NULL; } return uv_translate_sys_error(last_error); }
/* * The way windows takes environment variables is different than what C does; * Windows wants a contiguous block of null-terminated strings, terminated * with an additional null. * * Windows has a few "essential" environment variables. winsock will fail * to initialize if SYSTEMROOT is not defined; some APIs make reference to * TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that * these get defined if the input environment block does not contain any * values for them. */ WCHAR* make_program_env(char** env_block) { WCHAR* dst; WCHAR* ptr; char** env; int env_len = 1 * sizeof(WCHAR); /* room for closing null */ int len; int i; DWORD var_size; env_var_t required_vars[] = { E_V("SYSTEMROOT"), E_V("SYSTEMDRIVE"), E_V("TEMP"), }; for (env = env_block; *env; env++) { check_required_vars_contains_var(required_vars, ARRAY_SIZE(required_vars), *env); env_len += (uv_utf8_to_utf16(*env, NULL, 0) * sizeof(WCHAR)); } for (i = 0; i < ARRAY_SIZE(required_vars); ++i) { if (!required_vars[i].supplied) { env_len += required_vars[i].len * sizeof(WCHAR); var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0); if (var_size == 0) { uv_fatal_error(GetLastError(), "GetEnvironmentVariableW"); } required_vars[i].value_len = (int)var_size; env_len += (int)var_size * sizeof(WCHAR); } } dst = malloc(env_len); if (!dst) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } ptr = dst; for (env = env_block; *env; env++, ptr += len) { len = uv_utf8_to_utf16(*env, ptr, (size_t)(env_len - (ptr - dst))); if (!len) { free(dst); return NULL; } } for (i = 0; i < ARRAY_SIZE(required_vars); ++i) { if (!required_vars[i].supplied) { wcscpy(ptr, required_vars[i].wide); ptr += required_vars[i].len - 1; *ptr++ = L'='; var_size = GetEnvironmentVariableW(required_vars[i].wide, ptr, required_vars[i].value_len); if (var_size == 0) { uv_fatal_error(GetLastError(), "GetEnvironmentVariableW"); } ptr += required_vars[i].value_len; } } *ptr = L'\0'; return dst; }
/* * Entry point for getaddrinfo * we convert the UTF-8 strings to UNICODE * and save the UNICODE string pointers in the handle * We also copy hints so that caller does not need to keep memory until the * callback. * return UV_OK if a callback will be made * return error code if validation fails * * To minimize allocation we calculate total size required, * and copy all structs and referenced strings into the one block. * Each size calculation is adjusted to avoid unaligned pointers. */ int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* handle, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints) { int nodesize = 0; int servicesize = 0; int hintssize = 0; char* alloc_ptr = NULL; if (handle == NULL || getaddrinfo_cb == NULL || (node == NULL && service == NULL)) { uv__set_sys_error(loop, WSAEINVAL); goto error; } uv_req_init(loop, (uv_req_t*)handle); handle->getaddrinfo_cb = getaddrinfo_cb; handle->res = NULL; handle->type = UV_GETADDRINFO; handle->loop = loop; /* calculate required memory size for all input values */ if (node != NULL) { nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(wchar_t)); if (nodesize == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } } if (service != NULL) { servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * sizeof(wchar_t)); if (servicesize == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } } if (hints != NULL) { hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); } /* allocate memory for inputs, and partition it as needed */ alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize); if (!alloc_ptr) { uv__set_sys_error(loop, WSAENOBUFS); goto error; } /* save alloc_ptr now so we can free if error */ handle->alloc = (void*)alloc_ptr; /* convert node string to UTF16 into allocated memory and save pointer in */ /* handle */ if (node != NULL) { handle->node = (wchar_t*)alloc_ptr; if (uv_utf8_to_utf16(node, (wchar_t*) alloc_ptr, nodesize / sizeof(wchar_t)) == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } alloc_ptr += nodesize; } else { handle->node = NULL; } /* convert service string to UTF16 into allocated memory and save pointer */ /* in handle */ if (service != NULL) { handle->service = (wchar_t*)alloc_ptr; if (uv_utf8_to_utf16(service, (wchar_t*) alloc_ptr, servicesize / sizeof(wchar_t)) == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } alloc_ptr += servicesize; } else { handle->service = NULL; } /* copy hints to allocated memory and save pointer in handle */ if (hints != NULL) { handle->hints = (struct addrinfoW*)alloc_ptr; handle->hints->ai_family = hints->ai_family; handle->hints->ai_socktype = hints->ai_socktype; handle->hints->ai_protocol = hints->ai_protocol; handle->hints->ai_flags = hints->ai_flags; handle->hints->ai_addrlen = 0; handle->hints->ai_canonname = NULL; handle->hints->ai_addr = NULL; handle->hints->ai_next = NULL; } else { handle->hints = NULL; } /* init request for Post handling */ uv_req_init(loop, &handle->getadddrinfo_req); handle->getadddrinfo_req.data = handle; handle->getadddrinfo_req.type = UV_GETADDRINFO_REQ; /* Ask thread to run. Treat this as a long operation */ if (QueueUserWorkItem(&getaddrinfo_thread_proc, handle, WT_EXECUTELONGFUNCTION) == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } uv_ref(loop); return 0; error: if (handle != NULL && handle->alloc != NULL) { free(handle->alloc); } return -1; }
/* * Entry point for getaddrinfo * we convert the UTF-8 strings to UNICODE * and save the UNICODE string pointers in the req * We also copy hints so that caller does not need to keep memory until the * callback. * return 0 if a callback will be made * return error code if validation fails * * To minimize allocation we calculate total size required, * and copy all structs and referenced strings into the one block. * Each size calculation is adjusted to avoid unaligned pointers. */ int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints) { int nodesize = 0; int servicesize = 0; int hintssize = 0; char* alloc_ptr = NULL; int err; if (req == NULL || getaddrinfo_cb == NULL || (node == NULL && service == NULL)) { err = WSAEINVAL; goto error; } uv_req_init(loop, (uv_req_t*)req); req->getaddrinfo_cb = getaddrinfo_cb; req->res = NULL; req->type = UV_GETADDRINFO; req->loop = loop; req->retcode = 0; /* calculate required memory size for all input values */ if (node != NULL) { nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(WCHAR)); if (nodesize == 0) { err = GetLastError(); goto error; } } if (service != NULL) { servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * sizeof(WCHAR)); if (servicesize == 0) { err = GetLastError(); goto error; } } if (hints != NULL) { hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); } /* allocate memory for inputs, and partition it as needed */ alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize); if (!alloc_ptr) { err = WSAENOBUFS; goto error; } /* save alloc_ptr now so we can free if error */ req->alloc = (void*)alloc_ptr; /* convert node string to UTF16 into allocated memory and save pointer in */ /* the reques. */ if (node != NULL) { req->node = (WCHAR*)alloc_ptr; if (uv_utf8_to_utf16(node, (WCHAR*) alloc_ptr, nodesize / sizeof(WCHAR)) == 0) { err = GetLastError(); goto error; } alloc_ptr += nodesize; } else { req->node = NULL; } /* convert service string to UTF16 into allocated memory and save pointer */ /* in the req. */ if (service != NULL) { req->service = (WCHAR*)alloc_ptr; if (uv_utf8_to_utf16(service, (WCHAR*) alloc_ptr, servicesize / sizeof(WCHAR)) == 0) { err = GetLastError(); goto error; } alloc_ptr += servicesize; } else { req->service = NULL; } /* copy hints to allocated memory and save pointer in req */ if (hints != NULL) { req->hints = (struct addrinfoW*)alloc_ptr; req->hints->ai_family = hints->ai_family; req->hints->ai_socktype = hints->ai_socktype; req->hints->ai_protocol = hints->ai_protocol; req->hints->ai_flags = hints->ai_flags; req->hints->ai_addrlen = 0; req->hints->ai_canonname = NULL; req->hints->ai_addr = NULL; req->hints->ai_next = NULL; } else { req->hints = NULL; } uv__work_submit(loop, &req->work_req, uv__getaddrinfo_work, uv__getaddrinfo_done); uv__req_register(loop, req); return 0; error: if (req != NULL && req->alloc != NULL) { free(req->alloc); } return uv_translate_sys_error(err); }
void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int errorno, nameSize; HANDLE pipeHandle = INVALID_HANDLE_VALUE; DWORD duplex_flags; uv_req_init(loop, (uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; /* Convert name to UTF16. */ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); handle->name = (WCHAR*)malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { errorno = GetLastError(); goto error; } pipeHandle = open_named_pipe(handle->name, &duplex_flags); if (pipeHandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { errorno = GetLastError(); goto error; } REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; return; } errorno = GetLastError(); goto error; } assert(pipeHandle != INVALID_HANDLE_VALUE); if (uv_set_pipe_handle(loop, (uv_pipe_t*) req->handle, pipeHandle, duplex_flags)) { errorno = GetLastError(); goto error; } SET_REQ_SUCCESS(req); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); return; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); } /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, errorno); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); return; }
/* Creates a pipe server. */ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { uv_loop_t* loop = handle->loop; int i, errorno, nameSize; uv_pipe_accept_t* req; if (handle->flags & UV_HANDLE_BOUND) { uv__set_sys_error(loop, WSAEINVAL); return -1; } if (!name) { uv__set_sys_error(loop, WSAEINVAL); return -1; } if (!(handle->flags & UV_HANDLE_PIPESERVER)) { handle->pending_instances = default_pending_pipe_instances; } handle->accept_reqs = (uv_pipe_accept_t*) malloc(sizeof(uv_pipe_accept_t) * handle->pending_instances); if (!handle->accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } for (i = 0; i < handle->pending_instances; i++) { req = &handle->accept_reqs[i]; uv_req_init(loop, (uv_req_t*) req); req->type = UV_ACCEPT; req->data = handle; req->pipeHandle = INVALID_HANDLE_VALUE; req->next_pending = NULL; } /* Convert name to UTF16. */ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); handle->name = (WCHAR*)malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { uv__set_sys_error(loop, GetLastError()); return -1; } /* * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE. * If this fails then there's already a pipe server for the given pipe name. */ handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { errorno = GetLastError(); if (errorno == ERROR_ACCESS_DENIED) { uv__set_error(loop, UV_EADDRINUSE, errorno); } else if (errorno == ERROR_PATH_NOT_FOUND || errorno == ERROR_INVALID_NAME) { uv__set_error(loop, UV_EACCES, errorno); } else { uv__set_sys_error(loop, errorno); } goto error; } if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle, 0)) { uv__set_sys_error(loop, GetLastError()); goto error; } handle->pending_accepts = NULL; handle->flags |= UV_HANDLE_PIPESERVER; handle->flags |= UV_HANDLE_BOUND; return 0; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(handle->accept_reqs[0].pipeHandle); handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE; } return -1; }
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, uv_fs_event_cb cb) { int name_size; DWORD attr, last_error; wchar_t* dir = NULL, *dir_to_watch, *filenamew; wchar_t short_path[MAX_PATH]; uv_fs_event_init_handle(loop, handle, filename, cb); /* Convert name to UTF16. */ name_size = uv_utf8_to_utf16(filename, NULL, 0) * sizeof(wchar_t); filenamew = (wchar_t*)malloc(name_size); if (!filenamew) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(filename, filenamew, name_size / sizeof(wchar_t))) { uv__set_sys_error(loop, GetLastError()); return -1; } /* Determine whether filename is a file or a directory. */ attr = GetFileAttributesW(filenamew); if (attr == INVALID_FILE_ATTRIBUTES) { last_error = GetLastError(); goto error; } handle->is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; if (handle->is_path_dir) { /* filename is a directory, so that's the directory that we will watch. */ dir_to_watch = filenamew; } else { /* * filename is a file. So we split filename into dir & file parts, and * watch the dir directory. */ /* Convert to short path. */ if (!GetShortPathNameW(filenamew, short_path, COUNTOF(short_path))) { last_error = GetLastError(); goto error; } if (uv_split_path(filenamew, &dir, &handle->filew) != 0) { last_error = GetLastError(); goto error; } if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) { last_error = GetLastError(); goto error; } dir_to_watch = dir; } handle->dir_handle = CreateFileW(dir_to_watch, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (dir) { free(dir); dir = NULL; } if (handle->dir_handle == INVALID_HANDLE_VALUE) { last_error = GetLastError(); goto error; } if (CreateIoCompletionPort(handle->dir_handle, loop->iocp, (ULONG_PTR)handle, 0) == NULL) { last_error = GetLastError(); goto error; } handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size, sizeof(DWORD)); if (!handle->buffer) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped)); if (!ReadDirectoryChangesW(handle->dir_handle, handle->buffer, uv_directory_watcher_buffer_size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, NULL, &handle->req.overlapped, NULL)) { last_error = GetLastError(); goto error; } handle->req_pending = 1; return 0; error: if (handle->filename) { free(handle->filename); handle->filename = NULL; } if (handle->filew) { free(handle->filew); handle->filew = NULL; } if (handle->short_filew) { free(handle->short_filew); handle->short_filew = NULL; } if (handle->dir_handle != INVALID_HANDLE_VALUE) { CloseHandle(handle->dir_handle); handle->dir_handle = INVALID_HANDLE_VALUE; } if (handle->buffer) { _aligned_free(handle->buffer); handle->buffer = NULL; } uv__set_sys_error(loop, last_error); return -1; }
int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { int errno, nameSize; HANDLE pipeHandle; handle->handle = INVALID_HANDLE_VALUE; uv_req_init((uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; /* Convert name to UTF16. */ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t); handle->name = (wchar_t*)malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) { errno = GetLastError(); goto error; } pipeHandle = CreateFileW(handle->name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (pipeHandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { errno = GetLastError(); goto error; } return 0; } errno = GetLastError(); goto error; } if (uv_set_pipe_handle((uv_pipe_t*)req->handle, pipeHandle)) { errno = GetLastError(); goto error; } handle->handle = pipeHandle; req->error = uv_ok_; uv_insert_pending_req((uv_req_t*) req); handle->reqs_pending++; return 0; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); } uv_set_sys_error(errno); return -1; }
void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int errno, nameSize; handle->handle = INVALID_HANDLE_VALUE; uv_req_init(loop, (uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; /* Convert name to UTF16. */ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t); handle->name = (wchar_t*)malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) { errno = GetLastError(); goto error; } if (open_named_pipe(handle) != 0) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { errno = GetLastError(); goto error; } handle->reqs_pending++; return; } errno = GetLastError(); goto error; } assert(handle->handle != INVALID_HANDLE_VALUE); /* Ensure that what we just opened is actually a pipe */ if (!GetNamedPipeInfo(handle->handle, NULL, NULL, NULL, NULL)) { errno = WSAENOTSOCK; goto error; } if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, handle->handle)) { errno = GetLastError(); goto error; } SET_REQ_SUCCESS(req); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; return; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (handle->handle != INVALID_HANDLE_VALUE) { CloseHandle(handle->handle); handle->handle = INVALID_HANDLE_VALUE; } /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, errno); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; return; }