static int uv__get_process_title() { WCHAR title_w[MAX_TITLE_LENGTH]; int length; if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) { return -1; } /* Find out what the size of the buffer is that we need */ length = uv_utf16_to_utf8(title_w, -1, NULL, 0); if (!length) { return -1; } assert(!process_title); process_title = (char*)malloc(length); if (!process_title) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } /* Do utf16 -> utf8 conversion here */ if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) { free(process_title); return -1; } return 0; }
int uv_exepath(char* buffer, size_t* size) { int retVal; size_t utf16Size; wchar_t* utf16Buffer; if (!buffer || !size) { return -1; } utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * *size); if (!utf16Buffer) { retVal = -1; goto done; } /* Get the path as UTF-16 */ utf16Size = GetModuleFileNameW(NULL, utf16Buffer, *size - 1); if (utf16Size <= 0) { /* uv__set_sys_error(loop, GetLastError()); */ retVal = -1; goto done; } utf16Buffer[utf16Size] = L'\0'; /* Convert to UTF-8 */ *size = uv_utf16_to_utf8(utf16Buffer, utf16Size, buffer, *size); if (!*size) { /* uv__set_sys_error(loop, GetLastError()); */ retVal = -1; goto done; } buffer[*size] = '\0'; retVal = 0; done: if (utf16Buffer) { free(utf16Buffer); } return retVal; }
uv_err_t uv_cwd(char* buffer, size_t size) { uv_err_t err; size_t utf8Size; wchar_t* utf16Buffer = NULL; if (!buffer || !size) { err.code = UV_EINVAL; goto done; } utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * size); if (!utf16Buffer) { err.code = UV_ENOMEM; goto done; } if (!_wgetcwd(utf16Buffer, size - 1)) { err = uv__new_sys_error(_doserrno); goto done; } utf16Buffer[size - 1] = L'\0'; /* Convert to UTF-8 */ utf8Size = uv_utf16_to_utf8(utf16Buffer, -1, buffer, size); if (utf8Size == 0) { err = uv__new_sys_error(GetLastError()); goto done; } buffer[utf8Size] = '\0'; err = uv_ok_; done: if (utf16Buffer) { free(utf16Buffer); } return err; }
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 fs__readlink(uv_fs_t* req, const char* path) { int result = -1; BOOL rv; HANDLE symlink; void* buffer = NULL; DWORD bytes_returned; REPARSE_DATA_BUFFER* reparse_data; int utf8size; symlink = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (INVALID_HANDLE_VALUE == symlink) { result = -1; SET_REQ_LAST_ERROR(req, GetLastError()); goto done; } buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!buffer) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } rv = DeviceIoControl(symlink, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytes_returned, NULL); if (!rv) { result = -1; SET_REQ_LAST_ERROR(req, GetLastError()); goto done; } reparse_data = buffer; if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK) { result = -1; /* something is seriously wrong */ SET_REQ_LAST_ERROR(req, GetLastError()); goto done; } utf8size = uv_utf16_to_utf8(reparse_data->SymbolicLinkReparseBuffer.PathBuffer + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)), reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t), NULL, 0); if (!utf8size) { result = -1; SET_REQ_LAST_ERROR(req, GetLastError()); goto done; } req->ptr = malloc(utf8size + 1); if (!req->ptr) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } req->flags |= UV_FS_FREE_PTR; utf8size = uv_utf16_to_utf8(reparse_data->SymbolicLinkReparseBuffer.PathBuffer + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)), reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t), req->ptr, utf8size); if (!utf8size) { result = -1; SET_REQ_LAST_ERROR(req, GetLastError()); goto done; } ((char*)req->ptr)[utf8size] = '\0'; result = 0; done: if (buffer) { free(buffer); } if (symlink != INVALID_HANDLE_VALUE) { CloseHandle(symlink); } SET_REQ_RESULT(req, result); }
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, int* count) { unsigned long size = 0; IP_ADAPTER_ADDRESSES* adapter_addresses; IP_ADAPTER_ADDRESSES* adapter_address; uv_interface_address_t* address; struct sockaddr* sock_addr; int length; char* name; /* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */ /* with Windows XP */ IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size) != ERROR_BUFFER_OVERFLOW) { return uv__new_sys_error(GetLastError()); } adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(size); if (!adapter_addresses) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapter_addresses, &size) != ERROR_SUCCESS) { return uv__new_sys_error(GetLastError()); } /* Count the number of interfaces */ *count = 0; for (adapter_address = adapter_addresses; adapter_address != NULL; adapter_address = adapter_address->Next) { if (adapter_address->OperStatus != IfOperStatusUp) continue; unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) adapter_address->FirstUnicastAddress; while (unicast_address) { (*count)++; unicast_address = unicast_address->Next; } } *addresses = (uv_interface_address_t*) malloc(*count * sizeof(uv_interface_address_t)); if (!(*addresses)) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } address = *addresses; for (adapter_address = adapter_addresses; adapter_address != NULL; adapter_address = adapter_address->Next) { if (adapter_address->OperStatus != IfOperStatusUp) continue; name = NULL; unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) adapter_address->FirstUnicastAddress; while (unicast_address) { sock_addr = unicast_address->Address.lpSockaddr; if (sock_addr->sa_family == AF_INET6) { address->address.address6 = *((struct sockaddr_in6 *)sock_addr); } else { address->address.address4 = *((struct sockaddr_in *)sock_addr); } address->is_internal = adapter_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? 1 : 0; if (!name) { /* Convert FriendlyName to utf8 */ length = uv_utf16_to_utf8(adapter_address->FriendlyName, -1, NULL, 0); if (length) { name = (char*)malloc(length); if (!name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf16_to_utf8(adapter_address->FriendlyName, -1, name, length)) { free(name); name = NULL; } } } assert(name); address->name = name; unicast_address = unicast_address->Next; address++; } } free(adapter_addresses); return uv_ok_; }
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi; DWORD sppi_size; SYSTEM_INFO system_info; DWORD cpu_count, i, r; ULONG result_size; size_t size; uv_err_t err; uv_cpu_info_t* cpu_info; *cpu_infos = NULL; *count = 0; uv__once_init(); GetSystemInfo(&system_info); cpu_count = system_info.dwNumberOfProcessors; size = cpu_count * sizeof(uv_cpu_info_t); *cpu_infos = (uv_cpu_info_t*) malloc(size); if (*cpu_infos == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto out; } memset(*cpu_infos, 0, size); sppi_size = sizeof(*sppi) * cpu_count; sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(sppi_size); if (!sppi) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } r = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, sppi_size, &result_size); if (r != ERROR_SUCCESS || result_size != sppi_size) { err = uv__new_sys_error(GetLastError()); goto out; } for (i = 0; i < cpu_count; i++) { WCHAR key_name[128]; HKEY processor_key; DWORD cpu_speed; DWORD cpu_speed_size = sizeof(cpu_speed); WCHAR cpu_brand[256]; DWORD cpu_brand_size = sizeof(cpu_brand); _snwprintf(key_name, ARRAY_SIZE(key_name), L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", i); r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key_name, 0, KEY_QUERY_VALUE, &processor_key); if (r != ERROR_SUCCESS) { err = uv__new_sys_error(GetLastError()); goto out; } if (RegQueryValueExW(processor_key, L"~MHz", NULL, NULL, (BYTE*) &cpu_speed, &cpu_speed_size) != ERROR_SUCCESS) { err = uv__new_sys_error(GetLastError()); RegCloseKey(processor_key); goto out; } if (RegQueryValueExW(processor_key, L"ProcessorNameString", NULL, NULL, (BYTE*) &cpu_brand, &cpu_brand_size) != ERROR_SUCCESS) { err = uv__new_sys_error(GetLastError()); RegCloseKey(processor_key); goto out; } RegCloseKey(processor_key); cpu_info = &(*cpu_infos)[i]; cpu_info->speed = cpu_speed; cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000; cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart - sppi[i].IdleTime.QuadPart) / 10000; cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000; cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000; cpu_info->cpu_times.nice = 0; size = uv_utf16_to_utf8(cpu_brand, cpu_brand_size / sizeof(WCHAR), NULL, 0); if (size == 0) { err = uv__new_sys_error(GetLastError()); goto out; } /* Allocate 1 extra byte for the null terminator. */ cpu_info->model = (char*) malloc(size + 1); if (cpu_info->model == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto out; } if (uv_utf16_to_utf8(cpu_brand, cpu_brand_size / sizeof(WCHAR), cpu_info->model, size) == 0) { err = uv__new_sys_error(GetLastError()); goto out; } /* Ensure that cpu_info->model is null terminated. */ cpu_info->model[size] = '\0'; (*count)++; } err = uv_ok_; out: if (sppi) { free(sppi); } if (err.code != UV_OK && *cpu_infos != NULL) { int i; for (i = 0; i < *count; i++) { /* This is safe because the cpu_infos memory area is zeroed out */ /* immediately after allocating it. */ free((*cpu_infos)[i].model); } free(*cpu_infos); *cpu_infos = NULL; *count = 0; } return err; }
/* * Called from uv_run when complete. Call user specified callback * then free returned addrinfo * Returned addrinfo strings are converted from UTF-16 to UTF-8. * * 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. */ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* handle, uv_req_t* req) { int addrinfo_len = 0; int name_len = 0; size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo)); struct addrinfoW* addrinfow_ptr; struct addrinfo* addrinfo_ptr; char* alloc_ptr = NULL; char* cur_ptr = NULL; uv_err_code uv_ret; /* release input parameter memory */ if (handle->alloc != NULL) { free(handle->alloc); handle->alloc = NULL; } uv_ret = uv_translate_eai_error(handle->retcode); if (handle->retcode == 0) { /* convert addrinfoW to addrinfo */ /* first calculate required length */ addrinfow_ptr = handle->res; while (addrinfow_ptr != NULL) { addrinfo_len += addrinfo_struct_len + ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); if (addrinfow_ptr->ai_canonname != NULL) { name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0); if (name_len == 0) { uv_ret = uv_translate_sys_error(GetLastError()); goto complete; } addrinfo_len += ALIGNED_SIZE(name_len); } addrinfow_ptr = addrinfow_ptr->ai_next; } /* allocate memory for addrinfo results */ alloc_ptr = (char*)malloc(addrinfo_len); /* do conversions */ if (alloc_ptr != NULL) { cur_ptr = alloc_ptr; addrinfow_ptr = handle->res; while (addrinfow_ptr != NULL) { /* copy addrinfo struct data */ assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len); addrinfo_ptr = (struct addrinfo*)cur_ptr; addrinfo_ptr->ai_family = addrinfow_ptr->ai_family; addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype; addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol; addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags; addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen; addrinfo_ptr->ai_canonname = NULL; addrinfo_ptr->ai_addr = NULL; addrinfo_ptr->ai_next = NULL; cur_ptr += addrinfo_struct_len; /* copy sockaddr */ if (addrinfo_ptr->ai_addrlen > 0) { assert(cur_ptr + addrinfo_ptr->ai_addrlen <= alloc_ptr + addrinfo_len); memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen); addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr; cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen); } /* convert canonical name to UTF-8 */ if (addrinfow_ptr->ai_canonname != NULL) { name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0); assert(name_len > 0); assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len); name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, cur_ptr, name_len); assert(name_len > 0); addrinfo_ptr->ai_canonname = cur_ptr; cur_ptr += ALIGNED_SIZE(name_len); } assert(cur_ptr <= alloc_ptr + addrinfo_len); /* set next ptr */ addrinfow_ptr = addrinfow_ptr->ai_next; if (addrinfow_ptr != NULL) { addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr; } } } else { uv_ret = UV_ENOMEM; } } /* return memory to system */ if (handle->res != NULL) { FreeAddrInfoW(handle->res); handle->res = NULL; } complete: /* finally do callback with converted result */ handle->getaddrinfo_cb(handle, uv_ret, (struct addrinfo*)alloc_ptr); uv_unref(loop); }
/* * Called from uv_run when complete. Call user specified callback * then free returned addrinfo * Returned addrinfo strings are converted from UTF-16 to UTF-8. * * 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. */ static void uv__getaddrinfo_done(struct uv__work* w, int status) { uv_getaddrinfo_t* req; int addrinfo_len = 0; int name_len = 0; size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo)); struct addrinfoW* addrinfow_ptr; struct addrinfo* addrinfo_ptr; char* alloc_ptr = NULL; char* cur_ptr = NULL; req = container_of(w, uv_getaddrinfo_t, work_req); /* release input parameter memory */ if (req->alloc != NULL) { free(req->alloc); req->alloc = NULL; } if (status == UV_ECANCELED) { assert(req->retcode == 0); req->retcode = UV_EAI_CANCELED; if (req->res != NULL) { FreeAddrInfoW(req->res); req->res = NULL; } goto complete; } if (req->retcode == 0) { /* convert addrinfoW to addrinfo */ /* first calculate required length */ addrinfow_ptr = req->res; while (addrinfow_ptr != NULL) { addrinfo_len += addrinfo_struct_len + ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); if (addrinfow_ptr->ai_canonname != NULL) { name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0); if (name_len == 0) { req->retcode = uv_translate_sys_error(GetLastError()); goto complete; } addrinfo_len += ALIGNED_SIZE(name_len); } addrinfow_ptr = addrinfow_ptr->ai_next; } /* allocate memory for addrinfo results */ alloc_ptr = (char*)malloc(addrinfo_len); /* do conversions */ if (alloc_ptr != NULL) { cur_ptr = alloc_ptr; addrinfow_ptr = req->res; while (addrinfow_ptr != NULL) { /* copy addrinfo struct data */ assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len); addrinfo_ptr = (struct addrinfo*)cur_ptr; addrinfo_ptr->ai_family = addrinfow_ptr->ai_family; addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype; addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol; addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags; addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen; addrinfo_ptr->ai_canonname = NULL; addrinfo_ptr->ai_addr = NULL; addrinfo_ptr->ai_next = NULL; cur_ptr += addrinfo_struct_len; /* copy sockaddr */ if (addrinfo_ptr->ai_addrlen > 0) { assert(cur_ptr + addrinfo_ptr->ai_addrlen <= alloc_ptr + addrinfo_len); memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen); addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr; cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen); } /* convert canonical name to UTF-8 */ if (addrinfow_ptr->ai_canonname != NULL) { name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0); assert(name_len > 0); assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len); name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, cur_ptr, name_len); assert(name_len > 0); addrinfo_ptr->ai_canonname = cur_ptr; cur_ptr += ALIGNED_SIZE(name_len); } assert(cur_ptr <= alloc_ptr + addrinfo_len); /* set next ptr */ addrinfow_ptr = addrinfow_ptr->ai_next; if (addrinfow_ptr != NULL) { addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr; } } } else { req->retcode = UV_EAI_MEMORY; } } /* return memory to system */ if (req->res != NULL) { FreeAddrInfoW(req->res); req->res = NULL; } complete: uv__req_unregister(req->loop, req); /* finally do callback with converted result */ req->getaddrinfo_cb(req, req->retcode, (struct addrinfo*)alloc_ptr); }
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); } }