Blame src/win/util.c

Packit Service 7c31a4
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service 7c31a4
 * of this software and associated documentation files (the "Software"), to
Packit Service 7c31a4
 * deal in the Software without restriction, including without limitation the
Packit Service 7c31a4
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service 7c31a4
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service 7c31a4
 * furnished to do so, subject to the following conditions:
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The above copyright notice and this permission notice shall be included in
Packit Service 7c31a4
 * all copies or substantial portions of the Software.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 7c31a4
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 7c31a4
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service 7c31a4
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service 7c31a4
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service 7c31a4
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service 7c31a4
 * IN THE SOFTWARE.
Packit Service 7c31a4
 */
Packit Service 7c31a4
Packit Service 7c31a4
#include <assert.h>
Packit Service 7c31a4
#include <direct.h>
Packit Service 7c31a4
#include <limits.h>
Packit Service 7c31a4
#include <stdio.h>
Packit Service 7c31a4
#include <string.h>
Packit Service 7c31a4
#include <time.h>
Packit Service 7c31a4
#include <wchar.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include "uv.h"
Packit Service 7c31a4
#include "internal.h"
Packit Service 7c31a4
Packit Service e2ebee
/* clang-format off */
Packit Service 7c31a4
#include <winsock2.h>
Packit Service 7c31a4
#include <winperf.h>
Packit Service 7c31a4
#include <iphlpapi.h>
Packit Service 7c31a4
#include <psapi.h>
Packit Service 7c31a4
#include <tlhelp32.h>
Packit Service 7c31a4
#include <windows.h>
Packit Service e2ebee
/* clang-format on */
Packit Service 7c31a4
#include <userenv.h>
Packit Service 7c31a4
#include <math.h>
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Max title length; the only thing MSDN tells us about the maximum length
Packit Service 7c31a4
 * of the console title is that it is smaller than 64K. However in practice
Packit Service 7c31a4
 * it is much smaller, and there is no way to figure out what the exact length
Packit Service 7c31a4
 * of the title is or can be, at least not on XP. To make it even more
Packit Service 7c31a4
 * annoying, GetConsoleTitle fails when the buffer to be read into is bigger
Packit Service 7c31a4
 * than the actual maximum length. So we make a conservative guess here;
Packit Service 7c31a4
 * just don't put the novel you're writing in the title, unless the plot
Packit Service 7c31a4
 * survives truncation.
Packit Service 7c31a4
 */
Packit Service 7c31a4
#define MAX_TITLE_LENGTH 8192
Packit Service 7c31a4
Packit Service 7c31a4
/* The number of nanoseconds in one second. */
Packit Service 7c31a4
#define UV__NANOSEC 1000000000
Packit Service 7c31a4
Packit Service 7c31a4
/* Max user name length, from iphlpapi.h */
Packit Service 7c31a4
#ifndef UNLEN
Packit Service 7c31a4
# define UNLEN 256
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/* A RtlGenRandom() by any other name... */
Packit Service 7c31a4
extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength);
Packit Service 7c31a4
Packit Service 7c31a4
/* Cached copy of the process title, plus a mutex guarding it. */
Packit Service 7c31a4
static char *process_title;
Packit Service 7c31a4
static CRITICAL_SECTION process_title_lock;
Packit Service 7c31a4
Packit Service e2ebee
/* Frequency of the high-resolution clock. */
Packit Service e2ebee
static uint64_t hrtime_frequency_ = 0;
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * One-time initialization code for functionality defined in util.c.
Packit Service 7c31a4
 */
Packit Service 7c31a4
void uv__util_init(void) {
Packit Service 7c31a4
  LARGE_INTEGER perf_frequency;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Initialize process title access mutex. */
Packit Service 7c31a4
  InitializeCriticalSection(&process_title_lock);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Retrieve high-resolution timer frequency
Packit Service 7c31a4
   * and precompute its reciprocal.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (QueryPerformanceFrequency(&perf_frequency)) {
Packit Service e2ebee
    hrtime_frequency_ = perf_frequency.QuadPart;
Packit Service 7c31a4
  } else {
Packit Service e2ebee
    uv_fatal_error(GetLastError(), "QueryPerformanceFrequency");
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_exepath(char* buffer, size_t* size_ptr) {
Packit Service 7c31a4
  int utf8_len, utf16_buffer_len, utf16_len;
Packit Service 7c31a4
  WCHAR* utf16_buffer;
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (*size_ptr > 32768) {
Packit Service 7c31a4
    /* Windows paths can never be longer than this. */
Packit Service 7c31a4
    utf16_buffer_len = 32768;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    utf16_buffer_len = (int) *size_ptr;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  utf16_buffer = (WCHAR*) uv__malloc(sizeof(WCHAR) * utf16_buffer_len);
Packit Service 7c31a4
  if (!utf16_buffer) {
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Get the path as UTF-16. */
Packit Service 7c31a4
  utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
Packit Service 7c31a4
  if (utf16_len <= 0) {
Packit Service 7c31a4
    err = GetLastError();
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* utf16_len contains the length, *not* including the terminating null. */
Packit Service 7c31a4
  utf16_buffer[utf16_len] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to UTF-8 */
Packit Service 7c31a4
  utf8_len = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                 0,
Packit Service 7c31a4
                                 utf16_buffer,
Packit Service 7c31a4
                                 -1,
Packit Service 7c31a4
                                 buffer,
Packit Service 7c31a4
                                 (int) *size_ptr,
Packit Service 7c31a4
                                 NULL,
Packit Service 7c31a4
                                 NULL);
Packit Service 7c31a4
  if (utf8_len == 0) {
Packit Service 7c31a4
    err = GetLastError();
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(utf16_buffer);
Packit Service 7c31a4
Packit Service 7c31a4
  /* utf8_len *does* include the terminating null at this point, but the
Packit Service 7c31a4
   * returned size shouldn't. */
Packit Service 7c31a4
  *size_ptr = utf8_len - 1;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
Packit Service 7c31a4
 error:
Packit Service 7c31a4
  uv__free(utf16_buffer);
Packit Service 7c31a4
  return uv_translate_sys_error(err);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_cwd(char* buffer, size_t* size) {
Packit Service 7c31a4
  DWORD utf16_len;
Packit Service 7c31a4
  WCHAR *utf16_buffer;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (buffer == NULL || size == NULL) {
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  utf16_len = GetCurrentDirectoryW(0, NULL);
Packit Service 7c31a4
  if (utf16_len == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
  utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR));
Packit Service 7c31a4
  if (utf16_buffer == NULL) {
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer);
Packit Service 7c31a4
  if (utf16_len == 0) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* utf16_len contains the length, *not* including the terminating null. */
Packit Service 7c31a4
  utf16_buffer[utf16_len] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
  /* The returned directory should not have a trailing slash, unless it points
Packit Service 7c31a4
   * at a drive root, like c:\. Remove it if needed. */
Packit Service 7c31a4
  if (utf16_buffer[utf16_len - 1] == L'\\' &&
Packit Service 7c31a4
      !(utf16_len == 3 && utf16_buffer[1] == L':')) {
Packit Service 7c31a4
    utf16_len--;
Packit Service 7c31a4
    utf16_buffer[utf16_len] = L'\0';
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check how much space we need */
Packit Service 7c31a4
  r = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                          0,
Packit Service 7c31a4
                          utf16_buffer,
Packit Service 7c31a4
                          -1,
Packit Service 7c31a4
                          NULL,
Packit Service 7c31a4
                          0,
Packit Service 7c31a4
                          NULL,
Packit Service 7c31a4
                          NULL);
Packit Service 7c31a4
  if (r == 0) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  } else if (r > (int) *size) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    *size = r;
Packit Service 7c31a4
    return UV_ENOBUFS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to UTF-8 */
Packit Service 7c31a4
  r = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                          0,
Packit Service 7c31a4
                          utf16_buffer,
Packit Service 7c31a4
                          -1,
Packit Service 7c31a4
                          buffer,
Packit Service 7c31a4
                          *size > INT_MAX ? INT_MAX : (int) *size,
Packit Service 7c31a4
                          NULL,
Packit Service 7c31a4
                          NULL);
Packit Service 7c31a4
  uv__free(utf16_buffer);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  *size = r - 1;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_chdir(const char* dir) {
Packit Service 7c31a4
  WCHAR *utf16_buffer;
Packit Service 7c31a4
  size_t utf16_len, new_utf16_len;
Packit Service 7c31a4
  WCHAR drive_letter, env_var[4];
Packit Service 7c31a4
Packit Service 7c31a4
  if (dir == NULL) {
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  utf16_len = MultiByteToWideChar(CP_UTF8,
Packit Service 7c31a4
                                  0,
Packit Service 7c31a4
                                  dir,
Packit Service 7c31a4
                                  -1,
Packit Service 7c31a4
                                  NULL,
Packit Service 7c31a4
                                  0);
Packit Service 7c31a4
  if (utf16_len == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
  utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR));
Packit Service 7c31a4
  if (utf16_buffer == NULL) {
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (MultiByteToWideChar(CP_UTF8,
Packit Service 7c31a4
                          0,
Packit Service 7c31a4
                          dir,
Packit Service 7c31a4
                          -1,
Packit Service 7c31a4
                          utf16_buffer,
Packit Service 7c31a4
                          utf16_len) == 0) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!SetCurrentDirectoryW(utf16_buffer)) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Windows stores the drive-local path in an "hidden" environment variable,
Packit Service 7c31a4
   * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
Packit Service 7c31a4
   * this, so we'll have to do it. */
Packit Service 7c31a4
  new_utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer);
Packit Service 7c31a4
  if (new_utf16_len > utf16_len ) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    utf16_buffer = uv__malloc(new_utf16_len * sizeof(WCHAR));
Packit Service 7c31a4
    if (utf16_buffer == NULL) {
Packit Service 7c31a4
      /* When updating the environment variable fails, return UV_OK anyway.
Packit Service 7c31a4
       * We did successfully change current working directory, only updating
Packit Service 7c31a4
       * hidden env variable failed. */
Packit Service 7c31a4
      return 0;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    new_utf16_len = GetCurrentDirectoryW(new_utf16_len, utf16_buffer);
Packit Service 7c31a4
  }
Packit Service 7c31a4
  if (utf16_len == 0) {
Packit Service 7c31a4
    uv__free(utf16_buffer);
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* The returned directory should not have a trailing slash, unless it points
Packit Service 7c31a4
   * at a drive root, like c:\. Remove it if needed. */
Packit Service 7c31a4
  if (utf16_buffer[utf16_len - 1] == L'\\' &&
Packit Service 7c31a4
      !(utf16_len == 3 && utf16_buffer[1] == L':')) {
Packit Service 7c31a4
    utf16_len--;
Packit Service 7c31a4
    utf16_buffer[utf16_len] = L'\0';
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (utf16_len < 2 || utf16_buffer[1] != L':') {
Packit Service 7c31a4
    /* Doesn't look like a drive letter could be there - probably an UNC path.
Packit Service 7c31a4
     * TODO: Need to handle win32 namespaces like \\?\C:\ ? */
Packit Service 7c31a4
    drive_letter = 0;
Packit Service 7c31a4
  } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
Packit Service 7c31a4
    drive_letter = utf16_buffer[0];
Packit Service 7c31a4
  } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
Packit Service 7c31a4
    /* Convert to uppercase. */
Packit Service 7c31a4
    drive_letter = utf16_buffer[0] - L'a' + L'A';
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* Not valid. */
Packit Service 7c31a4
    drive_letter = 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (drive_letter != 0) {
Packit Service 7c31a4
    /* Construct the environment variable name and set it. */
Packit Service 7c31a4
    env_var[0] = L'=';
Packit Service 7c31a4
    env_var[1] = drive_letter;
Packit Service 7c31a4
    env_var[2] = L':';
Packit Service 7c31a4
    env_var[3] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
    SetEnvironmentVariableW(env_var, utf16_buffer);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(utf16_buffer);
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_loadavg(double avg[3]) {
Packit Service 7c31a4
  /* Can't be implemented */
Packit Service 7c31a4
  avg[0] = avg[1] = avg[2] = 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_get_free_memory(void) {
Packit Service 7c31a4
  MEMORYSTATUSEX memory_status;
Packit Service 7c31a4
  memory_status.dwLength = sizeof(memory_status);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!GlobalMemoryStatusEx(&memory_status)) {
Packit Service 7c31a4
     return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return (uint64_t)memory_status.ullAvailPhys;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_get_total_memory(void) {
Packit Service 7c31a4
  MEMORYSTATUSEX memory_status;
Packit Service 7c31a4
  memory_status.dwLength = sizeof(memory_status);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!GlobalMemoryStatusEx(&memory_status)) {
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return (uint64_t)memory_status.ullTotalPhys;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_get_constrained_memory(void) {
Packit Service 7c31a4
  return 0;  /* Memory constraints are unknown. */
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uv_pid_t uv_os_getpid(void) {
Packit Service 7c31a4
  return GetCurrentProcessId();
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uv_pid_t uv_os_getppid(void) {
Packit Service 7c31a4
  int parent_pid = -1;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  PROCESSENTRY32 pe;
Packit Service 7c31a4
  DWORD current_pid = GetCurrentProcessId();
Packit Service 7c31a4
Packit Service 7c31a4
  pe.dwSize = sizeof(PROCESSENTRY32);
Packit Service 7c31a4
  handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Packit Service 7c31a4
Packit Service 7c31a4
  if (Process32First(handle, &pe)) {
Packit Service 7c31a4
    do {
Packit Service 7c31a4
      if (pe.th32ProcessID == current_pid) {
Packit Service 7c31a4
        parent_pid = pe.th32ParentProcessID;
Packit Service 7c31a4
        break;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    } while( Process32Next(handle, &pe);;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  return parent_pid;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
char** uv_setup_args(int argc, char** argv) {
Packit Service 7c31a4
  return argv;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv__process_title_cleanup(void) {
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_set_process_title(const char* title) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
  int length;
Packit Service 7c31a4
  WCHAR* title_w = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__once_init();
Packit Service 7c31a4
Packit Service 7c31a4
  /* Find out how big the buffer for the wide-char title must be */
Packit Service 7c31a4
  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
Packit Service 7c31a4
  if (!length) {
Packit Service 7c31a4
    err = GetLastError();
Packit Service 7c31a4
    goto done;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to wide-char string */
Packit Service 7c31a4
  title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length);
Packit Service 7c31a4
  if (!title_w) {
Packit Service 7c31a4
    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);
Packit Service 7c31a4
  if (!length) {
Packit Service 7c31a4
    err = GetLastError();
Packit Service 7c31a4
    goto done;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* If the title must be truncated insert a \0 terminator there */
Packit Service 7c31a4
  if (length > MAX_TITLE_LENGTH) {
Packit Service 7c31a4
    title_w[MAX_TITLE_LENGTH - 1] = L'\0';
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!SetConsoleTitleW(title_w)) {
Packit Service 7c31a4
    err = GetLastError();
Packit Service 7c31a4
    goto done;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  EnterCriticalSection(&process_title_lock);
Packit Service 7c31a4
  uv__free(process_title);
Packit Service 7c31a4
  process_title = uv__strdup(title);
Packit Service 7c31a4
  LeaveCriticalSection(&process_title_lock);
Packit Service 7c31a4
Packit Service 7c31a4
  err = 0;
Packit Service 7c31a4
Packit Service 7c31a4
done:
Packit Service 7c31a4
  uv__free(title_w);
Packit Service 7c31a4
  return uv_translate_sys_error(err);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int uv__get_process_title(void) {
Packit Service 7c31a4
  WCHAR title_w[MAX_TITLE_LENGTH];
Packit Service 7c31a4
Packit Service 7c31a4
  if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0)
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_get_process_title(char* buffer, size_t size) {
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
Packit Service 7c31a4
  if (buffer == NULL || size == 0)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__once_init();
Packit Service 7c31a4
Packit Service 7c31a4
  EnterCriticalSection(&process_title_lock);
Packit Service 7c31a4
  /*
Packit Service 7c31a4
   * If the process_title was never read before nor explicitly set,
Packit Service 7c31a4
   * we must query it with getConsoleTitleW
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (!process_title && uv__get_process_title() == -1) {
Packit Service 7c31a4
    LeaveCriticalSection(&process_title_lock);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  assert(process_title);
Packit Service 7c31a4
  len = strlen(process_title) + 1;
Packit Service 7c31a4
Packit Service 7c31a4
  if (size < len) {
Packit Service 7c31a4
    LeaveCriticalSection(&process_title_lock);
Packit Service 7c31a4
    return UV_ENOBUFS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memcpy(buffer, process_title, len);
Packit Service 7c31a4
  LeaveCriticalSection(&process_title_lock);
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_hrtime(void) {
Packit Service 7c31a4
  uv__once_init();
Packit Service 7c31a4
  return uv__hrtime(UV__NANOSEC);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service e2ebee
uint64_t uv__hrtime(unsigned int scale) {
Packit Service 7c31a4
  LARGE_INTEGER counter;
Packit Service e2ebee
  double scaled_freq;
Packit Service e2ebee
  double result;
Packit Service 7c31a4
Packit Service e2ebee
  assert(hrtime_frequency_ != 0);
Packit Service e2ebee
  assert(scale != 0);
Packit Service 7c31a4
  if (!QueryPerformanceCounter(&counter)) {
Packit Service e2ebee
    uv_fatal_error(GetLastError(), "QueryPerformanceCounter");
Packit Service 7c31a4
  }
Packit Service e2ebee
  assert(counter.QuadPart != 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Because we have no guarantee about the order of magnitude of the
Packit Service 7c31a4
   * performance counter interval, integer math could cause this computation
Packit Service 7c31a4
   * to overflow. Therefore we resort to floating point math.
Packit Service 7c31a4
   */
Packit Service e2ebee
  scaled_freq = (double) hrtime_frequency_ / scale;
Packit Service e2ebee
  result = (double) counter.QuadPart / scaled_freq;
Packit Service e2ebee
  return (uint64_t) result;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_resident_set_memory(size_t* rss) {
Packit Service 7c31a4
  HANDLE current_process;
Packit Service 7c31a4
  PROCESS_MEMORY_COUNTERS pmc;
Packit Service 7c31a4
Packit Service 7c31a4
  current_process = GetCurrentProcess();
Packit Service 7c31a4
Packit Service 7c31a4
  if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  *rss = pmc.WorkingSetSize;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_uptime(double* uptime) {
Packit Service 7c31a4
  BYTE stack_buffer[4096];
Packit Service 7c31a4
  BYTE* malloced_buffer = NULL;
Packit Service 7c31a4
  BYTE* buffer = (BYTE*) stack_buffer;
Packit Service 7c31a4
  size_t buffer_size = sizeof(stack_buffer);
Packit Service 7c31a4
  DWORD data_size;
Packit Service 7c31a4
Packit Service 7c31a4
  PERF_DATA_BLOCK* data_block;
Packit Service 7c31a4
  PERF_OBJECT_TYPE* object_type;
Packit Service 7c31a4
  PERF_COUNTER_DEFINITION* counter_definition;
Packit Service 7c31a4
Packit Service 7c31a4
  DWORD i;
Packit Service 7c31a4
Packit Service 7c31a4
  for (;;) {
Packit Service 7c31a4
    LONG result;
Packit Service 7c31a4
Packit Service 7c31a4
    data_size = (DWORD) buffer_size;
Packit Service 7c31a4
    result = RegQueryValueExW(HKEY_PERFORMANCE_DATA,
Packit Service 7c31a4
                              L"2",
Packit Service 7c31a4
                              NULL,
Packit Service 7c31a4
                              NULL,
Packit Service 7c31a4
                              buffer,
Packit Service 7c31a4
                              &data_size);
Packit Service 7c31a4
    if (result == ERROR_SUCCESS) {
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    } else if (result != ERROR_MORE_DATA) {
Packit Service 7c31a4
      *uptime = 0;
Packit Service 7c31a4
      return uv_translate_sys_error(result);
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    buffer_size *= 2;
Packit Service 7c31a4
    /* Don't let the buffer grow infinitely. */
Packit Service 7c31a4
    if (buffer_size > 1 << 20) {
Packit Service 7c31a4
      goto internalError;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    uv__free(malloced_buffer);
Packit Service 7c31a4
Packit Service 7c31a4
    buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size);
Packit Service 7c31a4
    if (malloced_buffer == NULL) {
Packit Service 7c31a4
      *uptime = 0;
Packit Service 7c31a4
      return UV_ENOMEM;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (data_size < sizeof(*data_block))
Packit Service 7c31a4
    goto internalError;
Packit Service 7c31a4
Packit Service 7c31a4
  data_block = (PERF_DATA_BLOCK*) buffer;
Packit Service 7c31a4
Packit Service 7c31a4
  if (wmemcmp(data_block->Signature, L"PERF", 4) != 0)
Packit Service 7c31a4
    goto internalError;
Packit Service 7c31a4
Packit Service 7c31a4
  if (data_size < data_block->HeaderLength + sizeof(*object_type))
Packit Service 7c31a4
    goto internalError;
Packit Service 7c31a4
Packit Service 7c31a4
  object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength);
Packit Service 7c31a4
Packit Service 7c31a4
  if (object_type->NumInstances != PERF_NO_INSTANCES)
Packit Service 7c31a4
    goto internalError;
Packit Service 7c31a4
Packit Service 7c31a4
  counter_definition = (PERF_COUNTER_DEFINITION*) (buffer +
Packit Service 7c31a4
      data_block->HeaderLength + object_type->HeaderLength);
Packit Service 7c31a4
  for (i = 0; i < object_type->NumCounters; i++) {
Packit Service 7c31a4
    if ((BYTE*) counter_definition + sizeof(*counter_definition) >
Packit Service 7c31a4
        buffer + data_size) {
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (counter_definition->CounterNameTitleIndex == 674 &&
Packit Service 7c31a4
        counter_definition->CounterSize == sizeof(uint64_t)) {
Packit Service 7c31a4
      if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size ||
Packit Service 7c31a4
          !(counter_definition->CounterType & PERF_OBJECT_TIMER)) {
Packit Service 7c31a4
        goto internalError;
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
Packit Service 7c31a4
                        counter_definition->CounterOffset;
Packit Service 7c31a4
        uint64_t value = *((uint64_t*) address);
Packit Service 7c31a4
        *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /
Packit Service 7c31a4
                        (double) object_type->PerfFreq.QuadPart);
Packit Service 7c31a4
        uv__free(malloced_buffer);
Packit Service 7c31a4
        return 0;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    counter_definition = (PERF_COUNTER_DEFINITION*)
Packit Service 7c31a4
        ((BYTE*) counter_definition + counter_definition->ByteLength);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* If we get here, the uptime value was not found. */
Packit Service 7c31a4
  uv__free(malloced_buffer);
Packit Service 7c31a4
  *uptime = 0;
Packit Service 7c31a4
  return UV_ENOSYS;
Packit Service 7c31a4
Packit Service 7c31a4
 internalError:
Packit Service 7c31a4
  uv__free(malloced_buffer);
Packit Service 7c31a4
  *uptime = 0;
Packit Service 7c31a4
  return UV_EIO;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
Packit Service 7c31a4
  uv_cpu_info_t* cpu_infos;
Packit Service 7c31a4
  SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
Packit Service 7c31a4
  DWORD sppi_size;
Packit Service 7c31a4
  SYSTEM_INFO system_info;
Packit Service 7c31a4
  DWORD cpu_count, i;
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
  ULONG result_size;
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
  uv_cpu_info_t* cpu_info;
Packit Service 7c31a4
Packit Service 7c31a4
  cpu_infos = NULL;
Packit Service 7c31a4
  cpu_count = 0;
Packit Service 7c31a4
  sppi = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__once_init();
Packit Service 7c31a4
Packit Service 7c31a4
  GetSystemInfo(&system_info);
Packit Service 7c31a4
  cpu_count = system_info.dwNumberOfProcessors;
Packit Service 7c31a4
Packit Service 7c31a4
  cpu_infos = uv__calloc(cpu_count, sizeof *cpu_infos);
Packit Service 7c31a4
  if (cpu_infos == NULL) {
Packit Service 7c31a4
    err = ERROR_OUTOFMEMORY;
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  sppi_size = cpu_count * sizeof(*sppi);
Packit Service 7c31a4
  sppi = uv__malloc(sppi_size);
Packit Service 7c31a4
  if (sppi == NULL) {
Packit Service 7c31a4
    err = ERROR_OUTOFMEMORY;
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
Packit Service 7c31a4
                                     sppi,
Packit Service 7c31a4
                                     sppi_size,
Packit Service 7c31a4
                                     &result_size);
Packit Service 7c31a4
  if (!NT_SUCCESS(status)) {
Packit Service 7c31a4
    err = pRtlNtStatusToDosError(status);
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  assert(result_size == sppi_size);
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < cpu_count; i++) {
Packit Service 7c31a4
    WCHAR key_name[128];
Packit Service 7c31a4
    HKEY processor_key;
Packit Service 7c31a4
    DWORD cpu_speed;
Packit Service 7c31a4
    DWORD cpu_speed_size = sizeof(cpu_speed);
Packit Service 7c31a4
    WCHAR cpu_brand[256];
Packit Service 7c31a4
    DWORD cpu_brand_size = sizeof(cpu_brand);
Packit Service 7c31a4
    size_t len;
Packit Service 7c31a4
Packit Service 7c31a4
    len = _snwprintf(key_name,
Packit Service 7c31a4
                     ARRAY_SIZE(key_name),
Packit Service 7c31a4
                     L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
Packit Service 7c31a4
                     i);
Packit Service 7c31a4
Packit Service 7c31a4
    assert(len > 0 && len < ARRAY_SIZE(key_name));
Packit Service 7c31a4
Packit Service 7c31a4
    err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
Packit Service 7c31a4
                        key_name,
Packit Service 7c31a4
                        0,
Packit Service 7c31a4
                        KEY_QUERY_VALUE,
Packit Service 7c31a4
                        &processor_key);
Packit Service 7c31a4
    if (err != ERROR_SUCCESS) {
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    err = RegQueryValueExW(processor_key,
Packit Service 7c31a4
                           L"~MHz",
Packit Service 7c31a4
                           NULL,
Packit Service 7c31a4
                           NULL,
Packit Service 7c31a4
                           (BYTE*)&cpu_speed,
Packit Service 7c31a4
                           &cpu_speed_size);
Packit Service 7c31a4
    if (err != ERROR_SUCCESS) {
Packit Service 7c31a4
      RegCloseKey(processor_key);
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    err = RegQueryValueExW(processor_key,
Packit Service 7c31a4
                           L"ProcessorNameString",
Packit Service 7c31a4
                           NULL,
Packit Service 7c31a4
                           NULL,
Packit Service 7c31a4
                           (BYTE*)&cpu_brand,
Packit Service 7c31a4
                           &cpu_brand_size);
Packit Service 7c31a4
    RegCloseKey(processor_key);
Packit Service 7c31a4
    if (err != ERROR_SUCCESS)
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
Packit Service 7c31a4
    cpu_info = &cpu_infos[i];
Packit Service 7c31a4
    cpu_info->speed = cpu_speed;
Packit Service 7c31a4
    cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
Packit Service 7c31a4
    cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
Packit Service 7c31a4
        sppi[i].IdleTime.QuadPart) / 10000;
Packit Service 7c31a4
    cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
Packit Service 7c31a4
    cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
Packit Service 7c31a4
    cpu_info->cpu_times.nice = 0;
Packit Service 7c31a4
Packit Service 7c31a4
    uv__convert_utf16_to_utf8(cpu_brand,
Packit Service 7c31a4
                              cpu_brand_size / sizeof(WCHAR),
Packit Service 7c31a4
                              &(cpu_info->model));
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(sppi);
Packit Service 7c31a4
Packit Service 7c31a4
  *cpu_count_ptr = cpu_count;
Packit Service 7c31a4
  *cpu_infos_ptr = cpu_infos;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
Packit Service 7c31a4
 error:
Packit Service 7c31a4
  if (cpu_infos != NULL) {
Packit Service 7c31a4
    /* This is safe because the cpu_infos array is zeroed on allocation. */
Packit Service 7c31a4
    for (i = 0; i < cpu_count; i++)
Packit Service 7c31a4
      uv__free(cpu_infos[i].model);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(cpu_infos);
Packit Service 7c31a4
  uv__free(sppi);
Packit Service 7c31a4
Packit Service 7c31a4
  return uv_translate_sys_error(err);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int is_windows_version_or_greater(DWORD os_major,
Packit Service 7c31a4
                                         DWORD os_minor,
Packit Service 7c31a4
                                         WORD service_pack_major,
Packit Service 7c31a4
                                         WORD service_pack_minor) {
Packit Service 7c31a4
  OSVERSIONINFOEX osvi;
Packit Service 7c31a4
  DWORDLONG condition_mask = 0;
Packit Service 7c31a4
  int op = VER_GREATER_EQUAL;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Initialize the OSVERSIONINFOEX structure. */
Packit Service 7c31a4
  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
Packit Service 7c31a4
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
Packit Service 7c31a4
  osvi.dwMajorVersion = os_major;
Packit Service 7c31a4
  osvi.dwMinorVersion = os_minor;
Packit Service 7c31a4
  osvi.wServicePackMajor = service_pack_major;
Packit Service 7c31a4
  osvi.wServicePackMinor = service_pack_minor;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Initialize the condition mask. */
Packit Service 7c31a4
  VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op);
Packit Service 7c31a4
  VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op);
Packit Service 7c31a4
  VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op);
Packit Service 7c31a4
  VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Perform the test. */
Packit Service 7c31a4
  return (int) VerifyVersionInfo(
Packit Service 7c31a4
    &osvi,
Packit Service 7c31a4
    VER_MAJORVERSION | VER_MINORVERSION |
Packit Service 7c31a4
    VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
Packit Service 7c31a4
    condition_mask);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int address_prefix_match(int family,
Packit Service 7c31a4
                                struct sockaddr* address,
Packit Service 7c31a4
                                struct sockaddr* prefix_address,
Packit Service 7c31a4
                                int prefix_len) {
Packit Service 7c31a4
  uint8_t* address_data;
Packit Service 7c31a4
  uint8_t* prefix_address_data;
Packit Service 7c31a4
  int i;
Packit Service 7c31a4
Packit Service 7c31a4
  assert(address->sa_family == family);
Packit Service 7c31a4
  assert(prefix_address->sa_family == family);
Packit Service 7c31a4
Packit Service 7c31a4
  if (family == AF_INET6) {
Packit Service 7c31a4
    address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr);
Packit Service 7c31a4
    prefix_address_data =
Packit Service 7c31a4
      (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr);
Packit Service 7c31a4
    prefix_address_data =
Packit Service 7c31a4
      (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < prefix_len >> 3; i++) {
Packit Service 7c31a4
    if (address_data[i] != prefix_address_data[i])
Packit Service 7c31a4
      return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (prefix_len % 8)
Packit Service 7c31a4
    return prefix_address_data[i] ==
Packit Service 7c31a4
      (address_data[i] & (0xff << (8 - prefix_len % 8)));
Packit Service 7c31a4
Packit Service 7c31a4
  return 1;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
Packit Service 7c31a4
    int* count_ptr) {
Packit Service 7c31a4
  IP_ADAPTER_ADDRESSES* win_address_buf;
Packit Service 7c31a4
  ULONG win_address_buf_size;
Packit Service 7c31a4
  IP_ADAPTER_ADDRESSES* adapter;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_interface_address_t* uv_address_buf;
Packit Service 7c31a4
  char* name_buf;
Packit Service 7c31a4
  size_t uv_address_buf_size;
Packit Service 7c31a4
  uv_interface_address_t* uv_address;
Packit Service 7c31a4
Packit Service 7c31a4
  int count;
Packit Service 7c31a4
Packit Service 7c31a4
  int is_vista_or_greater;
Packit Service 7c31a4
  ULONG flags;
Packit Service 7c31a4
Packit Service 7c31a4
  *addresses_ptr = NULL;
Packit Service 7c31a4
  *count_ptr = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
Packit Service 7c31a4
  if (is_vista_or_greater) {
Packit Service 7c31a4
    flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
Packit Service 7c31a4
      GAA_FLAG_SKIP_DNS_SERVER;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* We need at least XP SP1. */
Packit Service 7c31a4
    if (!is_windows_version_or_greater(5, 1, 1, 0))
Packit Service 7c31a4
      return UV_ENOTSUP;
Packit Service 7c31a4
Packit Service 7c31a4
    flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
Packit Service 7c31a4
      GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
  /* Fetch the size of the adapters reported by windows, and then get the list
Packit Service 7c31a4
   * itself. */
Packit Service 7c31a4
  win_address_buf_size = 0;
Packit Service 7c31a4
  win_address_buf = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  for (;;) {
Packit Service 7c31a4
    ULONG r;
Packit Service 7c31a4
Packit Service 7c31a4
    /* If win_address_buf is 0, then GetAdaptersAddresses will fail with.
Packit Service 7c31a4
     * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in
Packit Service 7c31a4
     * win_address_buf_size. */
Packit Service 7c31a4
    r = GetAdaptersAddresses(AF_UNSPEC,
Packit Service 7c31a4
                             flags,
Packit Service 7c31a4
                             NULL,
Packit Service 7c31a4
                             win_address_buf,
Packit Service 7c31a4
                             &win_address_buf_size);
Packit Service 7c31a4
Packit Service 7c31a4
    if (r == ERROR_SUCCESS)
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    uv__free(win_address_buf);
Packit Service 7c31a4
Packit Service 7c31a4
    switch (r) {
Packit Service 7c31a4
      case ERROR_BUFFER_OVERFLOW:
Packit Service 7c31a4
        /* This happens when win_address_buf is NULL or too small to hold all
Packit Service 7c31a4
         * adapters. */
Packit Service 7c31a4
        win_address_buf = uv__malloc(win_address_buf_size);
Packit Service 7c31a4
        if (win_address_buf == NULL)
Packit Service 7c31a4
          return UV_ENOMEM;
Packit Service 7c31a4
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
Packit Service 7c31a4
      case ERROR_NO_DATA: {
Packit Service 7c31a4
        /* No adapters were found. */
Packit Service 7c31a4
        uv_address_buf = uv__malloc(1);
Packit Service 7c31a4
        if (uv_address_buf == NULL)
Packit Service 7c31a4
          return UV_ENOMEM;
Packit Service 7c31a4
Packit Service 7c31a4
        *count_ptr = 0;
Packit Service 7c31a4
        *addresses_ptr = uv_address_buf;
Packit Service 7c31a4
Packit Service 7c31a4
        return 0;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      case ERROR_ADDRESS_NOT_ASSOCIATED:
Packit Service 7c31a4
        return UV_EAGAIN;
Packit Service 7c31a4
Packit Service 7c31a4
      case ERROR_INVALID_PARAMETER:
Packit Service 7c31a4
        /* MSDN says:
Packit Service 7c31a4
         *   "This error is returned for any of the following conditions: the
Packit Service 7c31a4
         *   SizePointer parameter is NULL, the Address parameter is not
Packit Service 7c31a4
         *   AF_INET, AF_INET6, or AF_UNSPEC, or the address information for
Packit Service 7c31a4
         *   the parameters requested is greater than ULONG_MAX."
Packit Service 7c31a4
         * Since the first two conditions are not met, it must be that the
Packit Service 7c31a4
         * adapter data is too big.
Packit Service 7c31a4
         */
Packit Service 7c31a4
        return UV_ENOBUFS;
Packit Service 7c31a4
Packit Service 7c31a4
      default:
Packit Service 7c31a4
        /* Other (unspecified) errors can happen, but we don't have any special
Packit Service 7c31a4
         * meaning for them. */
Packit Service 7c31a4
        assert(r != ERROR_SUCCESS);
Packit Service 7c31a4
        return uv_translate_sys_error(r);
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Count the number of enabled interfaces and compute how much space is
Packit Service 7c31a4
   * needed to store their info. */
Packit Service 7c31a4
  count = 0;
Packit Service 7c31a4
  uv_address_buf_size = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  for (adapter = win_address_buf;
Packit Service 7c31a4
       adapter != NULL;
Packit Service 7c31a4
       adapter = adapter->Next) {
Packit Service 7c31a4
    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
Packit Service 7c31a4
    int name_size;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Interfaces that are not 'up' should not be reported. Also skip
Packit Service 7c31a4
     * interfaces that have no associated unicast address, as to avoid
Packit Service 7c31a4
     * allocating space for the name for this interface. */
Packit Service 7c31a4
    if (adapter->OperStatus != IfOperStatusUp ||
Packit Service 7c31a4
        adapter->FirstUnicastAddress == NULL)
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Compute the size of the interface name. */
Packit Service 7c31a4
    name_size = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                    0,
Packit Service 7c31a4
                                    adapter->FriendlyName,
Packit Service 7c31a4
                                    -1,
Packit Service 7c31a4
                                    NULL,
Packit Service 7c31a4
                                    0,
Packit Service 7c31a4
                                    NULL,
Packit Service 7c31a4
                                    FALSE);
Packit Service 7c31a4
    if (name_size <= 0) {
Packit Service 7c31a4
      uv__free(win_address_buf);
Packit Service 7c31a4
      return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
    }
Packit Service 7c31a4
    uv_address_buf_size += name_size;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Count the number of addresses associated with this interface, and
Packit Service 7c31a4
     * compute the size. */
Packit Service 7c31a4
    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
Packit Service 7c31a4
                           adapter->FirstUnicastAddress;
Packit Service 7c31a4
         unicast_address != NULL;
Packit Service 7c31a4
         unicast_address = unicast_address->Next) {
Packit Service 7c31a4
      count++;
Packit Service 7c31a4
      uv_address_buf_size += sizeof(uv_interface_address_t);
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Allocate space to store interface data plus adapter names. */
Packit Service 7c31a4
  uv_address_buf = uv__malloc(uv_address_buf_size);
Packit Service 7c31a4
  if (uv_address_buf == NULL) {
Packit Service 7c31a4
    uv__free(win_address_buf);
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Compute the start of the uv_interface_address_t array, and the place in
Packit Service 7c31a4
   * the buffer where the interface names will be stored. */
Packit Service 7c31a4
  uv_address = uv_address_buf;
Packit Service 7c31a4
  name_buf = (char*) (uv_address_buf + count);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Fill out the output buffer. */
Packit Service 7c31a4
  for (adapter = win_address_buf;
Packit Service 7c31a4
       adapter != NULL;
Packit Service 7c31a4
       adapter = adapter->Next) {
Packit Service 7c31a4
    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
Packit Service 7c31a4
    int name_size;
Packit Service 7c31a4
    size_t max_name_size;
Packit Service 7c31a4
Packit Service 7c31a4
    if (adapter->OperStatus != IfOperStatusUp ||
Packit Service 7c31a4
        adapter->FirstUnicastAddress == NULL)
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Convert the interface name to UTF8. */
Packit Service 7c31a4
    max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
Packit Service 7c31a4
    if (max_name_size > (size_t) INT_MAX)
Packit Service 7c31a4
      max_name_size = INT_MAX;
Packit Service 7c31a4
    name_size = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                    0,
Packit Service 7c31a4
                                    adapter->FriendlyName,
Packit Service 7c31a4
                                    -1,
Packit Service 7c31a4
                                    name_buf,
Packit Service 7c31a4
                                    (int) max_name_size,
Packit Service 7c31a4
                                    NULL,
Packit Service 7c31a4
                                    FALSE);
Packit Service 7c31a4
    if (name_size <= 0) {
Packit Service 7c31a4
      uv__free(win_address_buf);
Packit Service 7c31a4
      uv__free(uv_address_buf);
Packit Service 7c31a4
      return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    /* Add an uv_interface_address_t element for every unicast address. */
Packit Service 7c31a4
    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
Packit Service 7c31a4
                           adapter->FirstUnicastAddress;
Packit Service 7c31a4
         unicast_address != NULL;
Packit Service 7c31a4
         unicast_address = unicast_address->Next) {
Packit Service 7c31a4
      struct sockaddr* sa;
Packit Service 7c31a4
      ULONG prefix_len;
Packit Service 7c31a4
Packit Service 7c31a4
      sa = unicast_address->Address.lpSockaddr;
Packit Service 7c31a4
Packit Service 7c31a4
      /* XP has no OnLinkPrefixLength field. */
Packit Service 7c31a4
      if (is_vista_or_greater) {
Packit Service 7c31a4
        prefix_len =
Packit Service 7c31a4
          ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength;
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        /* Prior to Windows Vista the FirstPrefix pointed to the list with
Packit Service 7c31a4
         * single prefix for each IP address assigned to the adapter.
Packit Service 7c31a4
         * Order of FirstPrefix does not match order of FirstUnicastAddress,
Packit Service 7c31a4
         * so we need to find corresponding prefix.
Packit Service 7c31a4
         */
Packit Service 7c31a4
        IP_ADAPTER_PREFIX* prefix;
Packit Service 7c31a4
        prefix_len = 0;
Packit Service 7c31a4
Packit Service 7c31a4
        for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {
Packit Service 7c31a4
          /* We want the longest matching prefix. */
Packit Service 7c31a4
          if (prefix->Address.lpSockaddr->sa_family != sa->sa_family ||
Packit Service 7c31a4
              prefix->PrefixLength <= prefix_len)
Packit Service 7c31a4
            continue;
Packit Service 7c31a4
Packit Service 7c31a4
          if (address_prefix_match(sa->sa_family, sa,
Packit Service 7c31a4
              prefix->Address.lpSockaddr, prefix->PrefixLength)) {
Packit Service 7c31a4
            prefix_len = prefix->PrefixLength;
Packit Service 7c31a4
          }
Packit Service 7c31a4
        }
Packit Service 7c31a4
Packit Service 7c31a4
        /* If there is no matching prefix information, return a single-host
Packit Service 7c31a4
         * subnet mask (e.g. 255.255.255.255 for IPv4).
Packit Service 7c31a4
         */
Packit Service 7c31a4
        if (!prefix_len)
Packit Service 7c31a4
          prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      memset(uv_address, 0, sizeof *uv_address);
Packit Service 7c31a4
Packit Service 7c31a4
      uv_address->name = name_buf;
Packit Service 7c31a4
Packit Service 7c31a4
      if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) {
Packit Service 7c31a4
        memcpy(uv_address->phys_addr,
Packit Service 7c31a4
               adapter->PhysicalAddress,
Packit Service 7c31a4
               sizeof(uv_address->phys_addr));
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      uv_address->is_internal =
Packit Service 7c31a4
          (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
Packit Service 7c31a4
Packit Service 7c31a4
      if (sa->sa_family == AF_INET6) {
Packit Service 7c31a4
        uv_address->address.address6 = *((struct sockaddr_in6 *) sa);
Packit Service 7c31a4
Packit Service 7c31a4
        uv_address->netmask.netmask6.sin6_family = AF_INET6;
Packit Service 7c31a4
        memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3);
Packit Service 7c31a4
        /* This check ensures that we don't write past the size of the data. */
Packit Service 7c31a4
        if (prefix_len % 8) {
Packit Service 7c31a4
          uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] =
Packit Service 7c31a4
              0xff << (8 - prefix_len % 8);
Packit Service 7c31a4
        }
Packit Service 7c31a4
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        uv_address->address.address4 = *((struct sockaddr_in *) sa);
Packit Service 7c31a4
Packit Service 7c31a4
        uv_address->netmask.netmask4.sin_family = AF_INET;
Packit Service 7c31a4
        uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ?
Packit Service 7c31a4
            htonl(0xffffffff << (32 - prefix_len)) : 0;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      uv_address++;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    name_buf += name_size;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(win_address_buf);
Packit Service 7c31a4
Packit Service 7c31a4
  *addresses_ptr = uv_address_buf;
Packit Service 7c31a4
  *count_ptr = count;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_free_interface_addresses(uv_interface_address_t* addresses,
Packit Service 7c31a4
    int count) {
Packit Service 7c31a4
  uv__free(addresses);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_getrusage(uv_rusage_t *uv_rusage) {
Packit Service 7c31a4
  FILETIME createTime, exitTime, kernelTime, userTime;
Packit Service 7c31a4
  SYSTEMTIME kernelSystemTime, userSystemTime;
Packit Service 7c31a4
  PROCESS_MEMORY_COUNTERS memCounters;
Packit Service 7c31a4
  IO_COUNTERS ioCounters;
Packit Service 7c31a4
  int ret;
Packit Service 7c31a4
Packit Service 7c31a4
  ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
Packit Service 7c31a4
  if (ret == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);
Packit Service 7c31a4
  if (ret == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ret = FileTimeToSystemTime(&userTime, &userSystemTime);
Packit Service 7c31a4
  if (ret == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ret = GetProcessMemoryInfo(GetCurrentProcess(),
Packit Service 7c31a4
                             &memCounters,
Packit Service 7c31a4
                             sizeof(memCounters));
Packit Service 7c31a4
  if (ret == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
Packit Service 7c31a4
  if (ret == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memset(uv_rusage, 0, sizeof(*uv_rusage));
Packit Service 7c31a4
Packit Service 7c31a4
  uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
Packit Service 7c31a4
                               userSystemTime.wMinute * 60 +
Packit Service 7c31a4
                               userSystemTime.wSecond;
Packit Service 7c31a4
  uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 +
Packit Service 7c31a4
                               kernelSystemTime.wMinute * 60 +
Packit Service 7c31a4
                               kernelSystemTime.wSecond;
Packit Service 7c31a4
  uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
Packit Service 7c31a4
  uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;
Packit Service 7c31a4
  uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_homedir(char* buffer, size_t* size) {
Packit Service 7c31a4
  uv_passwd_t pwd;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check if the USERPROFILE environment variable is set first. The task of
Packit Service 7c31a4
     performing input validation on buffer and size is taken care of by
Packit Service 7c31a4
     uv_os_getenv(). */
Packit Service 7c31a4
  r = uv_os_getenv("USERPROFILE", buffer, size);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Don't return an error if USERPROFILE was not found. */
Packit Service 7c31a4
  if (r != UV_ENOENT)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  /* USERPROFILE is not set, so call uv__getpwuid_r() */
Packit Service 7c31a4
  r = uv__getpwuid_r(&pwd);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0) {
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  len = strlen(pwd.homedir);
Packit Service 7c31a4
Packit Service 7c31a4
  if (len >= *size) {
Packit Service 7c31a4
    *size = len + 1;
Packit Service 7c31a4
    uv_os_free_passwd(&pwd);
Packit Service 7c31a4
    return UV_ENOBUFS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memcpy(buffer, pwd.homedir, len + 1);
Packit Service 7c31a4
  *size = len;
Packit Service 7c31a4
  uv_os_free_passwd(&pwd);
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_tmpdir(char* buffer, size_t* size) {
Packit Service 7c31a4
  wchar_t *path;
Packit Service 7c31a4
  DWORD bufsize;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
Packit Service 7c31a4
  if (buffer == NULL || size == NULL || *size == 0)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  len = 0;
Packit Service 7c31a4
  len = GetTempPathW(0, NULL);
Packit Service 7c31a4
  if (len == 0) {
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
  /* Include space for terminating null char. */
Packit Service 7c31a4
  len += 1;
Packit Service 7c31a4
  path = uv__malloc(len * sizeof(wchar_t));
Packit Service 7c31a4
  if (path == NULL) {
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  len  = GetTempPathW(len, path);
Packit Service 7c31a4
Packit Service 7c31a4
  if (len == 0) {
Packit Service 7c31a4
    uv__free(path);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* The returned directory should not have a trailing slash, unless it points
Packit Service 7c31a4
   * at a drive root, like c:\. Remove it if needed. */
Packit Service 7c31a4
  if (path[len - 1] == L'\\' &&
Packit Service 7c31a4
      !(len == 3 && path[1] == L':')) {
Packit Service 7c31a4
    len--;
Packit Service 7c31a4
    path[len] = L'\0';
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check how much space we need */
Packit Service 7c31a4
  bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0) {
Packit Service 7c31a4
    uv__free(path);
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  } else if (bufsize > *size) {
Packit Service 7c31a4
    uv__free(path);
Packit Service 7c31a4
    *size = bufsize;
Packit Service 7c31a4
    return UV_ENOBUFS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to UTF-8 */
Packit Service 7c31a4
  bufsize = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                0,
Packit Service 7c31a4
                                path,
Packit Service 7c31a4
                                -1,
Packit Service 7c31a4
                                buffer,
Packit Service 7c31a4
                                *size,
Packit Service 7c31a4
                                NULL,
Packit Service 7c31a4
                                NULL);
Packit Service 7c31a4
  uv__free(path);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0)
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  *size = bufsize - 1;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_os_free_passwd(uv_passwd_t* pwd) {
Packit Service 7c31a4
  if (pwd == NULL)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(pwd->username);
Packit Service 7c31a4
  uv__free(pwd->homedir);
Packit Service 7c31a4
  pwd->username = NULL;
Packit Service 7c31a4
  pwd->homedir = NULL;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Converts a UTF-16 string into a UTF-8 one. The resulting string is
Packit Service 7c31a4
 * null-terminated.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
Packit Service 7c31a4
 * be specified.
Packit Service 7c31a4
 */
Packit Service 7c31a4
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
Packit Service 7c31a4
  DWORD bufsize;
Packit Service 7c31a4
Packit Service 7c31a4
  if (utf16 == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check how much space we need */
Packit Service 7c31a4
  bufsize = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                0,
Packit Service 7c31a4
                                utf16,
Packit Service 7c31a4
                                utf16len,
Packit Service 7c31a4
                                NULL,
Packit Service 7c31a4
                                0,
Packit Service 7c31a4
                                NULL,
Packit Service 7c31a4
                                NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0)
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  /* Allocate the destination buffer adding an extra byte for the terminating
Packit Service 7c31a4
   * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so
Packit Service 7c31a4
   * we do it ourselves always, just in case. */
Packit Service 7c31a4
  *utf8 = uv__malloc(bufsize + 1);
Packit Service 7c31a4
Packit Service 7c31a4
  if (*utf8 == NULL)
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to UTF-8 */
Packit Service 7c31a4
  bufsize = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                0,
Packit Service 7c31a4
                                utf16,
Packit Service 7c31a4
                                utf16len,
Packit Service 7c31a4
                                *utf8,
Packit Service 7c31a4
                                bufsize,
Packit Service 7c31a4
                                NULL,
Packit Service 7c31a4
                                NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0) {
Packit Service 7c31a4
    uv__free(*utf8);
Packit Service 7c31a4
    *utf8 = NULL;
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  (*utf8)[bufsize] = '\0';
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Converts a UTF-8 string into a UTF-16 one. The resulting string is
Packit Service 7c31a4
 * null-terminated.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * If utf8 is null terminated, utf8len can be set to -1, otherwise it must
Packit Service 7c31a4
 * be specified.
Packit Service 7c31a4
 */
Packit Service 7c31a4
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
Packit Service 7c31a4
  int bufsize;
Packit Service 7c31a4
Packit Service 7c31a4
  if (utf8 == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check how much space we need */
Packit Service 7c31a4
  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0)
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  /* Allocate the destination buffer adding an extra byte for the terminating
Packit Service 7c31a4
   * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
Packit Service 7c31a4
   * we do it ourselves always, just in case. */
Packit Service 7c31a4
  *utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1));
Packit Service 7c31a4
Packit Service 7c31a4
  if (*utf16 == NULL)
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to UTF-16 */
Packit Service 7c31a4
  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0) {
Packit Service 7c31a4
    uv__free(*utf16);
Packit Service 7c31a4
    *utf16 = NULL;
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  (*utf16)[bufsize] = L'\0';
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv__getpwuid_r(uv_passwd_t* pwd) {
Packit Service 7c31a4
  HANDLE token;
Packit Service 7c31a4
  wchar_t username[UNLEN + 1];
Packit Service 7c31a4
  wchar_t *path;
Packit Service 7c31a4
  DWORD bufsize;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (pwd == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Get the home directory using GetUserProfileDirectoryW() */
Packit Service 7c31a4
  if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  bufsize = 0;
Packit Service 7c31a4
  GetUserProfileDirectoryW(token, NULL, &bufsize);
Packit Service 7c31a4
  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
Packit Service 7c31a4
    r = GetLastError();
Packit Service 7c31a4
    CloseHandle(token);
Packit Service 7c31a4
    return uv_translate_sys_error(r);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  path = uv__malloc(bufsize * sizeof(wchar_t));
Packit Service 7c31a4
  if (path == NULL) {
Packit Service 7c31a4
    CloseHandle(token);
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
Packit Service 7c31a4
    r = GetLastError();
Packit Service 7c31a4
    CloseHandle(token);
Packit Service 7c31a4
    uv__free(path);
Packit Service 7c31a4
    return uv_translate_sys_error(r);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(token);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Get the username using GetUserNameW() */
Packit Service 7c31a4
  bufsize = ARRAY_SIZE(username);
Packit Service 7c31a4
  if (!GetUserNameW(username, &bufsize)) {
Packit Service 7c31a4
    r = GetLastError();
Packit Service 7c31a4
    uv__free(path);
Packit Service 7c31a4
Packit Service 7c31a4
    /* This should not be possible */
Packit Service 7c31a4
    if (r == ERROR_INSUFFICIENT_BUFFER)
Packit Service 7c31a4
      return UV_ENOMEM;
Packit Service 7c31a4
Packit Service 7c31a4
    return uv_translate_sys_error(r);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  pwd->homedir = NULL;
Packit Service 7c31a4
  r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir);
Packit Service 7c31a4
  uv__free(path);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  pwd->username = NULL;
Packit Service 7c31a4
  r = uv__convert_utf16_to_utf8(username, -1, &pwd->username);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0) {
Packit Service 7c31a4
    uv__free(pwd->homedir);
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  pwd->shell = NULL;
Packit Service 7c31a4
  pwd->uid = -1;
Packit Service 7c31a4
  pwd->gid = -1;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_get_passwd(uv_passwd_t* pwd) {
Packit Service 7c31a4
  return uv__getpwuid_r(pwd);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_environ(uv_env_item_t** envitems, int* count) {
Packit Service 7c31a4
  wchar_t* env;
Packit Service 7c31a4
  wchar_t* penv;
Packit Service 7c31a4
  int i, cnt;
Packit Service 7c31a4
  uv_env_item_t* envitem;
Packit Service 7c31a4
Packit Service 7c31a4
  *envitems = NULL;
Packit Service 7c31a4
  *count = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  env = GetEnvironmentStringsW();
Packit Service 7c31a4
  if (env == NULL)
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
Packit Service 7c31a4
  for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++);
Packit Service 7c31a4
Packit Service 7c31a4
  *envitems = uv__calloc(i, sizeof(**envitems));
Packit Service 7c31a4
  if (*envitems == NULL) {
Packit Service 7c31a4
    FreeEnvironmentStringsW(env);
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  penv = env;
Packit Service 7c31a4
  cnt = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  while (*penv != L'\0' && cnt < i) {
Packit Service 7c31a4
    char* buf;
Packit Service 7c31a4
    char* ptr;
Packit Service 7c31a4
Packit Service 7c31a4
    if (uv__convert_utf16_to_utf8(penv, -1, &buf) != 0)
Packit Service 7c31a4
      goto fail;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Using buf + 1 here because we know that `buf` has length at least 1,
Packit Service 7c31a4
     * and some special environment variables on Windows start with a = sign. */
Packit Service 7c31a4
    ptr = strchr(buf + 1, '=');
Packit Service 7c31a4
    if (ptr == NULL) {
Packit Service 7c31a4
      uv__free(buf);
Packit Service 7c31a4
      goto do_continue;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    *ptr = '\0';
Packit Service 7c31a4
Packit Service 7c31a4
    envitem = &(*envitems)[cnt];
Packit Service 7c31a4
    envitem->name = buf;
Packit Service 7c31a4
    envitem->value = ptr + 1;
Packit Service 7c31a4
Packit Service 7c31a4
    cnt++;
Packit Service 7c31a4
Packit Service 7c31a4
  do_continue:
Packit Service 7c31a4
    penv += wcslen(penv) + 1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  FreeEnvironmentStringsW(env);
Packit Service 7c31a4
Packit Service 7c31a4
  *count = cnt;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
Packit Service 7c31a4
fail:
Packit Service 7c31a4
  FreeEnvironmentStringsW(env);
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < cnt; i++) {
Packit Service 7c31a4
    envitem = &(*envitems)[cnt];
Packit Service 7c31a4
    uv__free(envitem->name);
Packit Service 7c31a4
  }
Packit Service 7c31a4
  uv__free(*envitems);
Packit Service 7c31a4
Packit Service 7c31a4
  *envitems = NULL;
Packit Service 7c31a4
  *count = 0;
Packit Service 7c31a4
  return UV_ENOMEM;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
Packit Service 7c31a4
  wchar_t fastvar[512];
Packit Service 7c31a4
  wchar_t* var;
Packit Service 7c31a4
  DWORD varlen;
Packit Service 7c31a4
  wchar_t* name_w;
Packit Service 7c31a4
  DWORD bufsize;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  var = fastvar;
Packit Service 7c31a4
  varlen = ARRAY_SIZE(fastvar);
Packit Service 7c31a4
Packit Service 7c31a4
  for (;;) {
Packit Service 7c31a4
    SetLastError(ERROR_SUCCESS);
Packit Service 7c31a4
    len = GetEnvironmentVariableW(name_w, var, varlen);
Packit Service 7c31a4
Packit Service 7c31a4
    if (len < varlen)
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Try repeatedly because we might have been preempted by another thread
Packit Service 7c31a4
     * modifying the environment variable just as we're trying to read it.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    if (var != fastvar)
Packit Service 7c31a4
      uv__free(var);
Packit Service 7c31a4
Packit Service 7c31a4
    varlen = 1 + len;
Packit Service 7c31a4
    var = uv__malloc(varlen * sizeof(*var));
Packit Service 7c31a4
Packit Service 7c31a4
    if (var == NULL) {
Packit Service 7c31a4
      r = UV_ENOMEM;
Packit Service 7c31a4
      goto fail;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(name_w);
Packit Service 7c31a4
  name_w = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  if (len == 0) {
Packit Service 7c31a4
    r = GetLastError();
Packit Service 7c31a4
    if (r != ERROR_SUCCESS) {
Packit Service 7c31a4
      r = uv_translate_sys_error(r);
Packit Service 7c31a4
      goto fail;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check how much space we need */
Packit Service 7c31a4
  bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0) {
Packit Service 7c31a4
    r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
    goto fail;
Packit Service 7c31a4
  } else if (bufsize > *size) {
Packit Service 7c31a4
    *size = bufsize;
Packit Service 7c31a4
    r = UV_ENOBUFS;
Packit Service 7c31a4
    goto fail;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Convert to UTF-8 */
Packit Service 7c31a4
  bufsize = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                0,
Packit Service 7c31a4
                                var,
Packit Service 7c31a4
                                -1,
Packit Service 7c31a4
                                buffer,
Packit Service 7c31a4
                                *size,
Packit Service 7c31a4
                                NULL,
Packit Service 7c31a4
                                NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufsize == 0) {
Packit Service 7c31a4
    r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
    goto fail;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  *size = bufsize - 1;
Packit Service 7c31a4
  r = 0;
Packit Service 7c31a4
Packit Service 7c31a4
fail:
Packit Service 7c31a4
Packit Service 7c31a4
  if (name_w != NULL)
Packit Service 7c31a4
    uv__free(name_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (var != fastvar)
Packit Service 7c31a4
    uv__free(var);
Packit Service 7c31a4
Packit Service 7c31a4
  return r;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_setenv(const char* name, const char* value) {
Packit Service 7c31a4
  wchar_t* name_w;
Packit Service 7c31a4
  wchar_t* value_w;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (name == NULL || value == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv__convert_utf8_to_utf16(value, -1, &value_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0) {
Packit Service 7c31a4
    uv__free(name_w);
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  r = SetEnvironmentVariableW(name_w, value_w);
Packit Service 7c31a4
  uv__free(name_w);
Packit Service 7c31a4
  uv__free(value_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r == 0)
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_unsetenv(const char* name) {
Packit Service 7c31a4
  wchar_t* name_w;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (name == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  r = SetEnvironmentVariableW(name_w, NULL);
Packit Service 7c31a4
  uv__free(name_w);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r == 0)
Packit Service 7c31a4
    return uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_gethostname(char* buffer, size_t* size) {
Packit Service 7c31a4
  char buf[UV_MAXHOSTNAMESIZE];
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
Packit Service 7c31a4
  if (buffer == NULL || size == NULL || *size == 0)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__once_init(); /* Initialize winsock */
Packit Service 7c31a4
Packit Service 7c31a4
  if (gethostname(buf, sizeof(buf)) != 0)
Packit Service 7c31a4
    return uv_translate_sys_error(WSAGetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
Packit Service 7c31a4
  len = strlen(buf);
Packit Service 7c31a4
Packit Service 7c31a4
  if (len >= *size) {
Packit Service 7c31a4
    *size = len + 1;
Packit Service 7c31a4
    return UV_ENOBUFS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memcpy(buffer, buf, len + 1);
Packit Service 7c31a4
  *size = len;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (pid == 0)
Packit Service 7c31a4
    *handle = GetCurrentProcess();
Packit Service 7c31a4
  else
Packit Service 7c31a4
    *handle = OpenProcess(access, FALSE, pid);
Packit Service 7c31a4
Packit Service 7c31a4
  if (*handle == NULL) {
Packit Service 7c31a4
    r = GetLastError();
Packit Service 7c31a4
Packit Service 7c31a4
    if (r == ERROR_INVALID_PARAMETER)
Packit Service 7c31a4
      return UV_ESRCH;
Packit Service 7c31a4
    else
Packit Service 7c31a4
      return uv_translate_sys_error(r);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_getpriority(uv_pid_t pid, int* priority) {
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (priority == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  r = GetPriorityClass(handle);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r == 0) {
Packit Service 7c31a4
    r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* Map Windows priority classes to Unix nice values. */
Packit Service 7c31a4
    if (r == REALTIME_PRIORITY_CLASS)
Packit Service 7c31a4
      *priority = UV_PRIORITY_HIGHEST;
Packit Service 7c31a4
    else if (r == HIGH_PRIORITY_CLASS)
Packit Service 7c31a4
      *priority = UV_PRIORITY_HIGH;
Packit Service 7c31a4
    else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
Packit Service 7c31a4
      *priority = UV_PRIORITY_ABOVE_NORMAL;
Packit Service 7c31a4
    else if (r == NORMAL_PRIORITY_CLASS)
Packit Service 7c31a4
      *priority = UV_PRIORITY_NORMAL;
Packit Service 7c31a4
    else if (r == BELOW_NORMAL_PRIORITY_CLASS)
Packit Service 7c31a4
      *priority = UV_PRIORITY_BELOW_NORMAL;
Packit Service 7c31a4
    else  /* IDLE_PRIORITY_CLASS */
Packit Service 7c31a4
      *priority = UV_PRIORITY_LOW;
Packit Service 7c31a4
Packit Service 7c31a4
    r = 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  return r;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_setpriority(uv_pid_t pid, int priority) {
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  int priority_class;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Map Unix nice values to Windows priority classes. */
Packit Service 7c31a4
  if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  else if (priority < UV_PRIORITY_HIGH)
Packit Service 7c31a4
    priority_class = REALTIME_PRIORITY_CLASS;
Packit Service 7c31a4
  else if (priority < UV_PRIORITY_ABOVE_NORMAL)
Packit Service 7c31a4
    priority_class = HIGH_PRIORITY_CLASS;
Packit Service 7c31a4
  else if (priority < UV_PRIORITY_NORMAL)
Packit Service 7c31a4
    priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
Packit Service 7c31a4
  else if (priority < UV_PRIORITY_BELOW_NORMAL)
Packit Service 7c31a4
    priority_class = NORMAL_PRIORITY_CLASS;
Packit Service 7c31a4
  else if (priority < UV_PRIORITY_LOW)
Packit Service 7c31a4
    priority_class = BELOW_NORMAL_PRIORITY_CLASS;
Packit Service 7c31a4
  else
Packit Service 7c31a4
    priority_class = IDLE_PRIORITY_CLASS;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r != 0)
Packit Service 7c31a4
    return r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (SetPriorityClass(handle, priority_class) == 0)
Packit Service 7c31a4
    r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  return r;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_os_uname(uv_utsname_t* buffer) {
Packit Service 7c31a4
  /* Implementation loosely based on
Packit Service 7c31a4
     https://github.com/gagern/gnulib/blob/master/lib/uname.c */
Packit Service 7c31a4
  OSVERSIONINFOW os_info;
Packit Service 7c31a4
  SYSTEM_INFO system_info;
Packit Service 7c31a4
  HKEY registry_key;
Packit Service 7c31a4
  WCHAR product_name_w[256];
Packit Service 7c31a4
  DWORD product_name_w_size;
Packit Service 7c31a4
  int version_size;
Packit Service 7c31a4
  int processor_level;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  if (buffer == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__once_init();
Packit Service 7c31a4
  os_info.dwOSVersionInfoSize = sizeof(os_info);
Packit Service 7c31a4
  os_info.szCSDVersion[0] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
  /* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()
Packit Service 7c31a4
     if RtlGetVersion() is not available. */
Packit Service 7c31a4
  if (pRtlGetVersion) {
Packit Service 7c31a4
    pRtlGetVersion(&os_info);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* Silence GetVersionEx() deprecation warning. */
Packit Service e2ebee
    #ifdef _MSC_VER
Packit Service 7c31a4
    #pragma warning(suppress : 4996)
Packit Service e2ebee
    #endif
Packit Service 7c31a4
    if (GetVersionExW(&os_info) == 0) {
Packit Service 7c31a4
      r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Populate the version field. */
Packit Service 7c31a4
  version_size = 0;
Packit Service 7c31a4
  r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
Packit Service 7c31a4
                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
Packit Service 7c31a4
                    0,
Packit Service 7c31a4
                    KEY_QUERY_VALUE,
Packit Service 7c31a4
                    &registry_key);
Packit Service 7c31a4
Packit Service 7c31a4
  if (r == ERROR_SUCCESS) {
Packit Service 7c31a4
    product_name_w_size = sizeof(product_name_w);
Packit Service 7c31a4
    r = RegGetValueW(registry_key,
Packit Service 7c31a4
                     NULL,
Packit Service 7c31a4
                     L"ProductName",
Packit Service 7c31a4
                     RRF_RT_REG_SZ,
Packit Service 7c31a4
                     NULL,
Packit Service 7c31a4
                     (PVOID) product_name_w,
Packit Service 7c31a4
                     &product_name_w_size);
Packit Service 7c31a4
    RegCloseKey(registry_key);
Packit Service 7c31a4
Packit Service 7c31a4
    if (r == ERROR_SUCCESS) {
Packit Service 7c31a4
      version_size = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                         0,
Packit Service 7c31a4
                                         product_name_w,
Packit Service 7c31a4
                                         -1,
Packit Service 7c31a4
                                         buffer->version,
Packit Service 7c31a4
                                         sizeof(buffer->version),
Packit Service 7c31a4
                                         NULL,
Packit Service 7c31a4
                                         NULL);
Packit Service 7c31a4
      if (version_size == 0) {
Packit Service 7c31a4
        r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
        goto error;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Append service pack information to the version if present. */
Packit Service 7c31a4
  if (os_info.szCSDVersion[0] != L'\0') {
Packit Service 7c31a4
    if (version_size > 0)
Packit Service 7c31a4
      buffer->version[version_size - 1] = ' ';
Packit Service 7c31a4
Packit Service 7c31a4
    if (WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                            0,
Packit Service 7c31a4
                            os_info.szCSDVersion,
Packit Service 7c31a4
                            -1,
Packit Service 7c31a4
                            buffer->version + version_size,
Packit Service 7c31a4
                            sizeof(buffer->version) - version_size,
Packit Service 7c31a4
                            NULL,
Packit Service 7c31a4
                            NULL) == 0) {
Packit Service 7c31a4
      r = uv_translate_sys_error(GetLastError());
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Populate the sysname field. */
Packit Service 7c31a4
#ifdef __MINGW32__
Packit Service 7c31a4
  r = snprintf(buffer->sysname,
Packit Service 7c31a4
               sizeof(buffer->sysname),
Packit Service 7c31a4
               "MINGW32_NT-%u.%u",
Packit Service 7c31a4
               (unsigned int) os_info.dwMajorVersion,
Packit Service 7c31a4
               (unsigned int) os_info.dwMinorVersion);
Packit Service e2ebee
  assert((size_t)r < sizeof(buffer->sysname));
Packit Service 7c31a4
#else
Packit Service 7c31a4
  uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  /* Populate the release field. */
Packit Service 7c31a4
  r = snprintf(buffer->release,
Packit Service 7c31a4
               sizeof(buffer->release),
Packit Service 7c31a4
               "%d.%d.%d",
Packit Service 7c31a4
               (unsigned int) os_info.dwMajorVersion,
Packit Service 7c31a4
               (unsigned int) os_info.dwMinorVersion,
Packit Service 7c31a4
               (unsigned int) os_info.dwBuildNumber);
Packit Service e2ebee
  assert((size_t)r < sizeof(buffer->release));
Packit Service 7c31a4
Packit Service 7c31a4
  /* Populate the machine field. */
Packit Service 7c31a4
  GetSystemInfo(&system_info);
Packit Service 7c31a4
Packit Service 7c31a4
  switch (system_info.wProcessorArchitecture) {
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_AMD64:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_IA64:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_INTEL:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));
Packit Service 7c31a4
Packit Service 7c31a4
      if (system_info.wProcessorLevel > 3) {
Packit Service 7c31a4
        processor_level = system_info.wProcessorLevel < 6 ?
Packit Service 7c31a4
                          system_info.wProcessorLevel : 6;
Packit Service 7c31a4
        buffer->machine[1] = '0' + processor_level;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_MIPS:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_ALPHA:
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_ALPHA64:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_PPC:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_SHX:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    case PROCESSOR_ARCHITECTURE_ARM:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
    default:
Packit Service 7c31a4
      uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));
Packit Service 7c31a4
      break;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
Packit Service 7c31a4
error:
Packit Service 7c31a4
  buffer->sysname[0] = '\0';
Packit Service 7c31a4
  buffer->release[0] = '\0';
Packit Service 7c31a4
  buffer->version[0] = '\0';
Packit Service 7c31a4
  buffer->machine[0] = '\0';
Packit Service 7c31a4
  return r;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_gettimeofday(uv_timeval64_t* tv) {
Packit Service 7c31a4
  /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */
Packit Service 7c31a4
  const uint64_t epoch = (uint64_t) 116444736000000000ULL;
Packit Service 7c31a4
  FILETIME file_time;
Packit Service 7c31a4
  ULARGE_INTEGER ularge;
Packit Service 7c31a4
Packit Service 7c31a4
  if (tv == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  GetSystemTimeAsFileTime(&file_time);
Packit Service 7c31a4
  ularge.LowPart = file_time.dwLowDateTime;
Packit Service 7c31a4
  ularge.HighPart = file_time.dwHighDateTime;
Packit Service 7c31a4
  tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L);
Packit Service 7c31a4
  tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv__random_rtlgenrandom(void* buf, size_t buflen) {
Packit Service 7c31a4
  if (buflen == 0)
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
Packit Service 7c31a4
  if (SystemFunction036(buf, buflen) == FALSE)
Packit Service 7c31a4
    return UV_EIO;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void uv_sleep(unsigned int msec) {
Packit Service 7c31a4
  Sleep(msec);
Packit Service 7c31a4
}