1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci#include <assert.h>
23e66f31c5Sopenharmony_ci#include <direct.h>
24e66f31c5Sopenharmony_ci#include <limits.h>
25e66f31c5Sopenharmony_ci#include <stdio.h>
26e66f31c5Sopenharmony_ci#include <string.h>
27e66f31c5Sopenharmony_ci#include <time.h>
28e66f31c5Sopenharmony_ci#include <wchar.h>
29e66f31c5Sopenharmony_ci
30e66f31c5Sopenharmony_ci#include "uv.h"
31e66f31c5Sopenharmony_ci#include "internal.h"
32e66f31c5Sopenharmony_ci
33e66f31c5Sopenharmony_ci/* clang-format off */
34e66f31c5Sopenharmony_ci#include <sysinfoapi.h>
35e66f31c5Sopenharmony_ci#include <winsock2.h>
36e66f31c5Sopenharmony_ci#include <winperf.h>
37e66f31c5Sopenharmony_ci#include <iphlpapi.h>
38e66f31c5Sopenharmony_ci#include <psapi.h>
39e66f31c5Sopenharmony_ci#include <tlhelp32.h>
40e66f31c5Sopenharmony_ci#include <windows.h>
41e66f31c5Sopenharmony_ci/* clang-format on */
42e66f31c5Sopenharmony_ci#include <userenv.h>
43e66f31c5Sopenharmony_ci#include <math.h>
44e66f31c5Sopenharmony_ci
45e66f31c5Sopenharmony_ci/*
46e66f31c5Sopenharmony_ci * Max title length; the only thing MSDN tells us about the maximum length
47e66f31c5Sopenharmony_ci * of the console title is that it is smaller than 64K. However in practice
48e66f31c5Sopenharmony_ci * it is much smaller, and there is no way to figure out what the exact length
49e66f31c5Sopenharmony_ci * of the title is or can be, at least not on XP. To make it even more
50e66f31c5Sopenharmony_ci * annoying, GetConsoleTitle fails when the buffer to be read into is bigger
51e66f31c5Sopenharmony_ci * than the actual maximum length. So we make a conservative guess here;
52e66f31c5Sopenharmony_ci * just don't put the novel you're writing in the title, unless the plot
53e66f31c5Sopenharmony_ci * survives truncation.
54e66f31c5Sopenharmony_ci */
55e66f31c5Sopenharmony_ci#define MAX_TITLE_LENGTH 8192
56e66f31c5Sopenharmony_ci
57e66f31c5Sopenharmony_ci/* The number of nanoseconds in one second. */
58e66f31c5Sopenharmony_ci#define UV__NANOSEC 1000000000
59e66f31c5Sopenharmony_ci
60e66f31c5Sopenharmony_ci/* Max user name length, from iphlpapi.h */
61e66f31c5Sopenharmony_ci#ifndef UNLEN
62e66f31c5Sopenharmony_ci# define UNLEN 256
63e66f31c5Sopenharmony_ci#endif
64e66f31c5Sopenharmony_ci
65e66f31c5Sopenharmony_ci
66e66f31c5Sopenharmony_ci/* A RtlGenRandom() by any other name... */
67e66f31c5Sopenharmony_ciextern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength);
68e66f31c5Sopenharmony_ci
69e66f31c5Sopenharmony_ci/* Cached copy of the process title, plus a mutex guarding it. */
70e66f31c5Sopenharmony_cistatic char *process_title;
71e66f31c5Sopenharmony_cistatic CRITICAL_SECTION process_title_lock;
72e66f31c5Sopenharmony_ci
73e66f31c5Sopenharmony_ci/* Frequency of the high-resolution clock. */
74e66f31c5Sopenharmony_cistatic uint64_t hrtime_frequency_ = 0;
75e66f31c5Sopenharmony_ci
76e66f31c5Sopenharmony_ci
77e66f31c5Sopenharmony_ci/*
78e66f31c5Sopenharmony_ci * One-time initialization code for functionality defined in util.c.
79e66f31c5Sopenharmony_ci */
80e66f31c5Sopenharmony_civoid uv__util_init(void) {
81e66f31c5Sopenharmony_ci  LARGE_INTEGER perf_frequency;
82e66f31c5Sopenharmony_ci
83e66f31c5Sopenharmony_ci  /* Initialize process title access mutex. */
84e66f31c5Sopenharmony_ci  InitializeCriticalSection(&process_title_lock);
85e66f31c5Sopenharmony_ci
86e66f31c5Sopenharmony_ci  /* Retrieve high-resolution timer frequency
87e66f31c5Sopenharmony_ci   * and precompute its reciprocal.
88e66f31c5Sopenharmony_ci   */
89e66f31c5Sopenharmony_ci  if (QueryPerformanceFrequency(&perf_frequency)) {
90e66f31c5Sopenharmony_ci    hrtime_frequency_ = perf_frequency.QuadPart;
91e66f31c5Sopenharmony_ci  } else {
92e66f31c5Sopenharmony_ci    uv_fatal_error(GetLastError(), "QueryPerformanceFrequency");
93e66f31c5Sopenharmony_ci  }
94e66f31c5Sopenharmony_ci}
95e66f31c5Sopenharmony_ci
96e66f31c5Sopenharmony_ci
97e66f31c5Sopenharmony_ciint uv_exepath(char* buffer, size_t* size_ptr) {
98e66f31c5Sopenharmony_ci  size_t utf8_len, utf16_buffer_len, utf16_len;
99e66f31c5Sopenharmony_ci  WCHAR* utf16_buffer;
100e66f31c5Sopenharmony_ci  int err;
101e66f31c5Sopenharmony_ci
102e66f31c5Sopenharmony_ci  if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
103e66f31c5Sopenharmony_ci    return UV_EINVAL;
104e66f31c5Sopenharmony_ci  }
105e66f31c5Sopenharmony_ci
106e66f31c5Sopenharmony_ci  if (*size_ptr > 32768) {
107e66f31c5Sopenharmony_ci    /* Windows paths can never be longer than this. */
108e66f31c5Sopenharmony_ci    utf16_buffer_len = 32768;
109e66f31c5Sopenharmony_ci  } else {
110e66f31c5Sopenharmony_ci    utf16_buffer_len = (int) *size_ptr;
111e66f31c5Sopenharmony_ci  }
112e66f31c5Sopenharmony_ci
113e66f31c5Sopenharmony_ci  utf16_buffer = (WCHAR*) uv__malloc(sizeof(WCHAR) * utf16_buffer_len);
114e66f31c5Sopenharmony_ci  if (!utf16_buffer) {
115e66f31c5Sopenharmony_ci    return UV_ENOMEM;
116e66f31c5Sopenharmony_ci  }
117e66f31c5Sopenharmony_ci
118e66f31c5Sopenharmony_ci  /* Get the path as UTF-16. */
119e66f31c5Sopenharmony_ci  utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
120e66f31c5Sopenharmony_ci  if (utf16_len <= 0) {
121e66f31c5Sopenharmony_ci    err = GetLastError();
122e66f31c5Sopenharmony_ci    goto error;
123e66f31c5Sopenharmony_ci  }
124e66f31c5Sopenharmony_ci
125e66f31c5Sopenharmony_ci  /* Convert to UTF-8 */
126e66f31c5Sopenharmony_ci  utf8_len = *size_ptr - 1; /* Reserve space for NUL */
127e66f31c5Sopenharmony_ci  err = uv_utf16_to_wtf8(utf16_buffer, utf16_len, &buffer, &utf8_len);
128e66f31c5Sopenharmony_ci  if (err == UV_ENOBUFS) {
129e66f31c5Sopenharmony_ci    utf8_len = *size_ptr - 1;
130e66f31c5Sopenharmony_ci    err = 0;
131e66f31c5Sopenharmony_ci  }
132e66f31c5Sopenharmony_ci  *size_ptr = utf8_len;
133e66f31c5Sopenharmony_ci
134e66f31c5Sopenharmony_ci  uv__free(utf16_buffer);
135e66f31c5Sopenharmony_ci
136e66f31c5Sopenharmony_ci  return err;
137e66f31c5Sopenharmony_ci
138e66f31c5Sopenharmony_ci error:
139e66f31c5Sopenharmony_ci  uv__free(utf16_buffer);
140e66f31c5Sopenharmony_ci  return uv_translate_sys_error(err);
141e66f31c5Sopenharmony_ci}
142e66f31c5Sopenharmony_ci
143e66f31c5Sopenharmony_ci
144e66f31c5Sopenharmony_cistatic int uv__cwd(WCHAR** buf, DWORD *len) {
145e66f31c5Sopenharmony_ci  WCHAR* p;
146e66f31c5Sopenharmony_ci  DWORD n;
147e66f31c5Sopenharmony_ci  DWORD t;
148e66f31c5Sopenharmony_ci
149e66f31c5Sopenharmony_ci  t = GetCurrentDirectoryW(0, NULL);
150e66f31c5Sopenharmony_ci  for (;;) {
151e66f31c5Sopenharmony_ci    if (t == 0)
152e66f31c5Sopenharmony_ci      return uv_translate_sys_error(GetLastError());
153e66f31c5Sopenharmony_ci
154e66f31c5Sopenharmony_ci    /* |t| is the size of the buffer _including_ nul. */
155e66f31c5Sopenharmony_ci    p = uv__malloc(t * sizeof(*p));
156e66f31c5Sopenharmony_ci    if (p == NULL)
157e66f31c5Sopenharmony_ci      return UV_ENOMEM;
158e66f31c5Sopenharmony_ci
159e66f31c5Sopenharmony_ci    /* |n| is the size of the buffer _excluding_ nul but _only on success_.
160e66f31c5Sopenharmony_ci     * If |t| was too small because another thread changed the working
161e66f31c5Sopenharmony_ci     * directory, |n| is the size the buffer should be _including_ nul.
162e66f31c5Sopenharmony_ci     * It therefore follows we must resize when n >= t and fail when n == 0.
163e66f31c5Sopenharmony_ci     */
164e66f31c5Sopenharmony_ci    n = GetCurrentDirectoryW(t, p);
165e66f31c5Sopenharmony_ci    if (n > 0)
166e66f31c5Sopenharmony_ci      if (n < t)
167e66f31c5Sopenharmony_ci        break;
168e66f31c5Sopenharmony_ci
169e66f31c5Sopenharmony_ci    uv__free(p);
170e66f31c5Sopenharmony_ci    t = n;
171e66f31c5Sopenharmony_ci  }
172e66f31c5Sopenharmony_ci
173e66f31c5Sopenharmony_ci  /* The returned directory should not have a trailing slash, unless it points
174e66f31c5Sopenharmony_ci   * at a drive root, like c:\. Remove it if needed.
175e66f31c5Sopenharmony_ci   */
176e66f31c5Sopenharmony_ci  t = n - 1;
177e66f31c5Sopenharmony_ci  if (p[t] == L'\\' && !(n == 3 && p[1] == L':')) {
178e66f31c5Sopenharmony_ci    p[t] = L'\0';
179e66f31c5Sopenharmony_ci    n = t;
180e66f31c5Sopenharmony_ci  }
181e66f31c5Sopenharmony_ci
182e66f31c5Sopenharmony_ci  *buf = p;
183e66f31c5Sopenharmony_ci  *len = n;
184e66f31c5Sopenharmony_ci
185e66f31c5Sopenharmony_ci  return 0;
186e66f31c5Sopenharmony_ci}
187e66f31c5Sopenharmony_ci
188e66f31c5Sopenharmony_ci
189e66f31c5Sopenharmony_ciint uv_cwd(char* buffer, size_t* size) {
190e66f31c5Sopenharmony_ci  DWORD utf16_len;
191e66f31c5Sopenharmony_ci  WCHAR *utf16_buffer;
192e66f31c5Sopenharmony_ci  int r;
193e66f31c5Sopenharmony_ci
194e66f31c5Sopenharmony_ci  if (buffer == NULL || size == NULL) {
195e66f31c5Sopenharmony_ci    return UV_EINVAL;
196e66f31c5Sopenharmony_ci  }
197e66f31c5Sopenharmony_ci
198e66f31c5Sopenharmony_ci  r = uv__cwd(&utf16_buffer, &utf16_len);
199e66f31c5Sopenharmony_ci  if (r < 0)
200e66f31c5Sopenharmony_ci    return r;
201e66f31c5Sopenharmony_ci
202e66f31c5Sopenharmony_ci  r = uv__copy_utf16_to_utf8(utf16_buffer, utf16_len, buffer, size);
203e66f31c5Sopenharmony_ci
204e66f31c5Sopenharmony_ci  uv__free(utf16_buffer);
205e66f31c5Sopenharmony_ci
206e66f31c5Sopenharmony_ci  return r;
207e66f31c5Sopenharmony_ci}
208e66f31c5Sopenharmony_ci
209e66f31c5Sopenharmony_ci
210e66f31c5Sopenharmony_ciint uv_chdir(const char* dir) {
211e66f31c5Sopenharmony_ci  WCHAR *utf16_buffer;
212e66f31c5Sopenharmony_ci  DWORD utf16_len;
213e66f31c5Sopenharmony_ci  WCHAR drive_letter, env_var[4];
214e66f31c5Sopenharmony_ci  int r;
215e66f31c5Sopenharmony_ci
216e66f31c5Sopenharmony_ci  /* Convert to UTF-16 */
217e66f31c5Sopenharmony_ci  r = uv__convert_utf8_to_utf16(dir, &utf16_buffer);
218e66f31c5Sopenharmony_ci  if (r)
219e66f31c5Sopenharmony_ci    return r;
220e66f31c5Sopenharmony_ci
221e66f31c5Sopenharmony_ci  if (!SetCurrentDirectoryW(utf16_buffer)) {
222e66f31c5Sopenharmony_ci    uv__free(utf16_buffer);
223e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
224e66f31c5Sopenharmony_ci  }
225e66f31c5Sopenharmony_ci
226e66f31c5Sopenharmony_ci  /* uv__cwd() will return a new buffer. */
227e66f31c5Sopenharmony_ci  uv__free(utf16_buffer);
228e66f31c5Sopenharmony_ci  utf16_buffer = NULL;
229e66f31c5Sopenharmony_ci
230e66f31c5Sopenharmony_ci  /* Windows stores the drive-local path in an "hidden" environment variable,
231e66f31c5Sopenharmony_ci   * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
232e66f31c5Sopenharmony_ci   * this, so we'll have to do it. */
233e66f31c5Sopenharmony_ci  r = uv__cwd(&utf16_buffer, &utf16_len);
234e66f31c5Sopenharmony_ci  if (r == UV_ENOMEM) {
235e66f31c5Sopenharmony_ci    /* When updating the environment variable fails, return UV_OK anyway.
236e66f31c5Sopenharmony_ci     * We did successfully change current working directory, only updating
237e66f31c5Sopenharmony_ci     * hidden env variable failed. */
238e66f31c5Sopenharmony_ci    return 0;
239e66f31c5Sopenharmony_ci  }
240e66f31c5Sopenharmony_ci  if (r < 0) {
241e66f31c5Sopenharmony_ci    return r;
242e66f31c5Sopenharmony_ci  }
243e66f31c5Sopenharmony_ci
244e66f31c5Sopenharmony_ci  if (utf16_len < 2 || utf16_buffer[1] != L':') {
245e66f31c5Sopenharmony_ci    /* Doesn't look like a drive letter could be there - probably an UNC path.
246e66f31c5Sopenharmony_ci     * TODO: Need to handle win32 namespaces like \\?\C:\ ? */
247e66f31c5Sopenharmony_ci    drive_letter = 0;
248e66f31c5Sopenharmony_ci  } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
249e66f31c5Sopenharmony_ci    drive_letter = utf16_buffer[0];
250e66f31c5Sopenharmony_ci  } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
251e66f31c5Sopenharmony_ci    /* Convert to uppercase. */
252e66f31c5Sopenharmony_ci    drive_letter = utf16_buffer[0] - L'a' + L'A';
253e66f31c5Sopenharmony_ci  } else {
254e66f31c5Sopenharmony_ci    /* Not valid. */
255e66f31c5Sopenharmony_ci    drive_letter = 0;
256e66f31c5Sopenharmony_ci  }
257e66f31c5Sopenharmony_ci
258e66f31c5Sopenharmony_ci  if (drive_letter != 0) {
259e66f31c5Sopenharmony_ci    /* Construct the environment variable name and set it. */
260e66f31c5Sopenharmony_ci    env_var[0] = L'=';
261e66f31c5Sopenharmony_ci    env_var[1] = drive_letter;
262e66f31c5Sopenharmony_ci    env_var[2] = L':';
263e66f31c5Sopenharmony_ci    env_var[3] = L'\0';
264e66f31c5Sopenharmony_ci
265e66f31c5Sopenharmony_ci    SetEnvironmentVariableW(env_var, utf16_buffer);
266e66f31c5Sopenharmony_ci  }
267e66f31c5Sopenharmony_ci
268e66f31c5Sopenharmony_ci  uv__free(utf16_buffer);
269e66f31c5Sopenharmony_ci  return 0;
270e66f31c5Sopenharmony_ci}
271e66f31c5Sopenharmony_ci
272e66f31c5Sopenharmony_ci
273e66f31c5Sopenharmony_civoid uv_loadavg(double avg[3]) {
274e66f31c5Sopenharmony_ci  /* Can't be implemented */
275e66f31c5Sopenharmony_ci  avg[0] = avg[1] = avg[2] = 0;
276e66f31c5Sopenharmony_ci}
277e66f31c5Sopenharmony_ci
278e66f31c5Sopenharmony_ci
279e66f31c5Sopenharmony_ciuint64_t uv_get_free_memory(void) {
280e66f31c5Sopenharmony_ci  MEMORYSTATUSEX memory_status;
281e66f31c5Sopenharmony_ci  memory_status.dwLength = sizeof(memory_status);
282e66f31c5Sopenharmony_ci
283e66f31c5Sopenharmony_ci  if (!GlobalMemoryStatusEx(&memory_status)) {
284e66f31c5Sopenharmony_ci     return 0;
285e66f31c5Sopenharmony_ci  }
286e66f31c5Sopenharmony_ci
287e66f31c5Sopenharmony_ci  return (uint64_t)memory_status.ullAvailPhys;
288e66f31c5Sopenharmony_ci}
289e66f31c5Sopenharmony_ci
290e66f31c5Sopenharmony_ci
291e66f31c5Sopenharmony_ciuint64_t uv_get_total_memory(void) {
292e66f31c5Sopenharmony_ci  MEMORYSTATUSEX memory_status;
293e66f31c5Sopenharmony_ci  memory_status.dwLength = sizeof(memory_status);
294e66f31c5Sopenharmony_ci
295e66f31c5Sopenharmony_ci  if (!GlobalMemoryStatusEx(&memory_status)) {
296e66f31c5Sopenharmony_ci    return 0;
297e66f31c5Sopenharmony_ci  }
298e66f31c5Sopenharmony_ci
299e66f31c5Sopenharmony_ci  return (uint64_t)memory_status.ullTotalPhys;
300e66f31c5Sopenharmony_ci}
301e66f31c5Sopenharmony_ci
302e66f31c5Sopenharmony_ci
303e66f31c5Sopenharmony_ciuint64_t uv_get_constrained_memory(void) {
304e66f31c5Sopenharmony_ci  return 0;  /* Memory constraints are unknown. */
305e66f31c5Sopenharmony_ci}
306e66f31c5Sopenharmony_ci
307e66f31c5Sopenharmony_ci
308e66f31c5Sopenharmony_ciuint64_t uv_get_available_memory(void) {
309e66f31c5Sopenharmony_ci  return uv_get_free_memory();
310e66f31c5Sopenharmony_ci}
311e66f31c5Sopenharmony_ci
312e66f31c5Sopenharmony_ci
313e66f31c5Sopenharmony_ciuv_pid_t uv_os_getpid(void) {
314e66f31c5Sopenharmony_ci  return GetCurrentProcessId();
315e66f31c5Sopenharmony_ci}
316e66f31c5Sopenharmony_ci
317e66f31c5Sopenharmony_ci
318e66f31c5Sopenharmony_ciuv_pid_t uv_os_getppid(void) {
319e66f31c5Sopenharmony_ci  int parent_pid = -1;
320e66f31c5Sopenharmony_ci  HANDLE handle;
321e66f31c5Sopenharmony_ci  PROCESSENTRY32 pe;
322e66f31c5Sopenharmony_ci  DWORD current_pid = GetCurrentProcessId();
323e66f31c5Sopenharmony_ci
324e66f31c5Sopenharmony_ci  pe.dwSize = sizeof(PROCESSENTRY32);
325e66f31c5Sopenharmony_ci  handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
326e66f31c5Sopenharmony_ci
327e66f31c5Sopenharmony_ci  if (Process32First(handle, &pe)) {
328e66f31c5Sopenharmony_ci    do {
329e66f31c5Sopenharmony_ci      if (pe.th32ProcessID == current_pid) {
330e66f31c5Sopenharmony_ci        parent_pid = pe.th32ParentProcessID;
331e66f31c5Sopenharmony_ci        break;
332e66f31c5Sopenharmony_ci      }
333e66f31c5Sopenharmony_ci    } while( Process32Next(handle, &pe));
334e66f31c5Sopenharmony_ci  }
335e66f31c5Sopenharmony_ci
336e66f31c5Sopenharmony_ci  CloseHandle(handle);
337e66f31c5Sopenharmony_ci  return parent_pid;
338e66f31c5Sopenharmony_ci}
339e66f31c5Sopenharmony_ci
340e66f31c5Sopenharmony_ci
341e66f31c5Sopenharmony_cichar** uv_setup_args(int argc, char** argv) {
342e66f31c5Sopenharmony_ci  return argv;
343e66f31c5Sopenharmony_ci}
344e66f31c5Sopenharmony_ci
345e66f31c5Sopenharmony_ci
346e66f31c5Sopenharmony_civoid uv__process_title_cleanup(void) {
347e66f31c5Sopenharmony_ci}
348e66f31c5Sopenharmony_ci
349e66f31c5Sopenharmony_ci
350e66f31c5Sopenharmony_ciint uv_set_process_title(const char* title) {
351e66f31c5Sopenharmony_ci  int err;
352e66f31c5Sopenharmony_ci  int length;
353e66f31c5Sopenharmony_ci  WCHAR* title_w = NULL;
354e66f31c5Sopenharmony_ci
355e66f31c5Sopenharmony_ci  uv__once_init();
356e66f31c5Sopenharmony_ci
357e66f31c5Sopenharmony_ci  err = uv__convert_utf8_to_utf16(title, &title_w);
358e66f31c5Sopenharmony_ci  if (err)
359e66f31c5Sopenharmony_ci    return err;
360e66f31c5Sopenharmony_ci
361e66f31c5Sopenharmony_ci  /* If the title must be truncated insert a \0 terminator there */
362e66f31c5Sopenharmony_ci  length = wcslen(title_w);
363e66f31c5Sopenharmony_ci  if (length >= MAX_TITLE_LENGTH)
364e66f31c5Sopenharmony_ci    title_w[MAX_TITLE_LENGTH - 1] = L'\0';
365e66f31c5Sopenharmony_ci
366e66f31c5Sopenharmony_ci  if (!SetConsoleTitleW(title_w)) {
367e66f31c5Sopenharmony_ci    err = GetLastError();
368e66f31c5Sopenharmony_ci    goto done;
369e66f31c5Sopenharmony_ci  }
370e66f31c5Sopenharmony_ci
371e66f31c5Sopenharmony_ci  EnterCriticalSection(&process_title_lock);
372e66f31c5Sopenharmony_ci  uv__free(process_title);
373e66f31c5Sopenharmony_ci  process_title = uv__strdup(title);
374e66f31c5Sopenharmony_ci  LeaveCriticalSection(&process_title_lock);
375e66f31c5Sopenharmony_ci
376e66f31c5Sopenharmony_ci  err = 0;
377e66f31c5Sopenharmony_ci
378e66f31c5Sopenharmony_cidone:
379e66f31c5Sopenharmony_ci  uv__free(title_w);
380e66f31c5Sopenharmony_ci  return uv_translate_sys_error(err);
381e66f31c5Sopenharmony_ci}
382e66f31c5Sopenharmony_ci
383e66f31c5Sopenharmony_ci
384e66f31c5Sopenharmony_cistatic int uv__get_process_title(void) {
385e66f31c5Sopenharmony_ci  WCHAR title_w[MAX_TITLE_LENGTH];
386e66f31c5Sopenharmony_ci  DWORD wlen;
387e66f31c5Sopenharmony_ci
388e66f31c5Sopenharmony_ci  wlen = GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR));
389e66f31c5Sopenharmony_ci  if (wlen == 0)
390e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
391e66f31c5Sopenharmony_ci
392e66f31c5Sopenharmony_ci  return uv__convert_utf16_to_utf8(title_w, wlen, &process_title);
393e66f31c5Sopenharmony_ci}
394e66f31c5Sopenharmony_ci
395e66f31c5Sopenharmony_ci
396e66f31c5Sopenharmony_ciint uv_get_process_title(char* buffer, size_t size) {
397e66f31c5Sopenharmony_ci  size_t len;
398e66f31c5Sopenharmony_ci  int r;
399e66f31c5Sopenharmony_ci
400e66f31c5Sopenharmony_ci  if (buffer == NULL || size == 0)
401e66f31c5Sopenharmony_ci    return UV_EINVAL;
402e66f31c5Sopenharmony_ci
403e66f31c5Sopenharmony_ci  uv__once_init();
404e66f31c5Sopenharmony_ci
405e66f31c5Sopenharmony_ci  EnterCriticalSection(&process_title_lock);
406e66f31c5Sopenharmony_ci  /*
407e66f31c5Sopenharmony_ci   * If the process_title was never read before nor explicitly set,
408e66f31c5Sopenharmony_ci   * we must query it with getConsoleTitleW
409e66f31c5Sopenharmony_ci   */
410e66f31c5Sopenharmony_ci  if (process_title == NULL) {
411e66f31c5Sopenharmony_ci    r = uv__get_process_title();
412e66f31c5Sopenharmony_ci    if (r) {
413e66f31c5Sopenharmony_ci      LeaveCriticalSection(&process_title_lock);
414e66f31c5Sopenharmony_ci      return r;
415e66f31c5Sopenharmony_ci    }
416e66f31c5Sopenharmony_ci  }
417e66f31c5Sopenharmony_ci
418e66f31c5Sopenharmony_ci  assert(process_title);
419e66f31c5Sopenharmony_ci  len = strlen(process_title) + 1;
420e66f31c5Sopenharmony_ci
421e66f31c5Sopenharmony_ci  if (size < len) {
422e66f31c5Sopenharmony_ci    LeaveCriticalSection(&process_title_lock);
423e66f31c5Sopenharmony_ci    return UV_ENOBUFS;
424e66f31c5Sopenharmony_ci  }
425e66f31c5Sopenharmony_ci
426e66f31c5Sopenharmony_ci  memcpy(buffer, process_title, len);
427e66f31c5Sopenharmony_ci  LeaveCriticalSection(&process_title_lock);
428e66f31c5Sopenharmony_ci
429e66f31c5Sopenharmony_ci  return 0;
430e66f31c5Sopenharmony_ci}
431e66f31c5Sopenharmony_ci
432e66f31c5Sopenharmony_ci
433e66f31c5Sopenharmony_ci/* https://github.com/libuv/libuv/issues/1674 */
434e66f31c5Sopenharmony_ciint uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) {
435e66f31c5Sopenharmony_ci  FILETIME ft;
436e66f31c5Sopenharmony_ci  int64_t t;
437e66f31c5Sopenharmony_ci
438e66f31c5Sopenharmony_ci  if (ts == NULL)
439e66f31c5Sopenharmony_ci    return UV_EFAULT;
440e66f31c5Sopenharmony_ci
441e66f31c5Sopenharmony_ci  switch (clock_id) {
442e66f31c5Sopenharmony_ci    case UV_CLOCK_MONOTONIC:
443e66f31c5Sopenharmony_ci      uv__once_init();
444e66f31c5Sopenharmony_ci      t = uv__hrtime(UV__NANOSEC);
445e66f31c5Sopenharmony_ci      ts->tv_sec = t / 1000000000;
446e66f31c5Sopenharmony_ci      ts->tv_nsec = t % 1000000000;
447e66f31c5Sopenharmony_ci      return 0;
448e66f31c5Sopenharmony_ci    case UV_CLOCK_REALTIME:
449e66f31c5Sopenharmony_ci      GetSystemTimePreciseAsFileTime(&ft);
450e66f31c5Sopenharmony_ci      /* In 100-nanosecond increments from 1601-01-01 UTC because why not? */
451e66f31c5Sopenharmony_ci      t = (int64_t) ft.dwHighDateTime << 32 | ft.dwLowDateTime;
452e66f31c5Sopenharmony_ci      /* Convert to UNIX epoch, 1970-01-01. Still in 100 ns increments. */
453e66f31c5Sopenharmony_ci      t -= 116444736000000000ll;
454e66f31c5Sopenharmony_ci      /* Now convert to seconds and nanoseconds. */
455e66f31c5Sopenharmony_ci      ts->tv_sec = t / 10000000;
456e66f31c5Sopenharmony_ci      ts->tv_nsec = t % 10000000 * 100;
457e66f31c5Sopenharmony_ci      return 0;
458e66f31c5Sopenharmony_ci  }
459e66f31c5Sopenharmony_ci
460e66f31c5Sopenharmony_ci  return UV_EINVAL;
461e66f31c5Sopenharmony_ci}
462e66f31c5Sopenharmony_ci
463e66f31c5Sopenharmony_ci
464e66f31c5Sopenharmony_ciuint64_t uv_hrtime(void) {
465e66f31c5Sopenharmony_ci  uv__once_init();
466e66f31c5Sopenharmony_ci  return uv__hrtime(UV__NANOSEC);
467e66f31c5Sopenharmony_ci}
468e66f31c5Sopenharmony_ci
469e66f31c5Sopenharmony_ci
470e66f31c5Sopenharmony_ciuint64_t uv__hrtime(unsigned int scale) {
471e66f31c5Sopenharmony_ci  LARGE_INTEGER counter;
472e66f31c5Sopenharmony_ci  double scaled_freq;
473e66f31c5Sopenharmony_ci  double result;
474e66f31c5Sopenharmony_ci
475e66f31c5Sopenharmony_ci  assert(hrtime_frequency_ != 0);
476e66f31c5Sopenharmony_ci  assert(scale != 0);
477e66f31c5Sopenharmony_ci  if (!QueryPerformanceCounter(&counter)) {
478e66f31c5Sopenharmony_ci    uv_fatal_error(GetLastError(), "QueryPerformanceCounter");
479e66f31c5Sopenharmony_ci  }
480e66f31c5Sopenharmony_ci  assert(counter.QuadPart != 0);
481e66f31c5Sopenharmony_ci
482e66f31c5Sopenharmony_ci  /* Because we have no guarantee about the order of magnitude of the
483e66f31c5Sopenharmony_ci   * performance counter interval, integer math could cause this computation
484e66f31c5Sopenharmony_ci   * to overflow. Therefore we resort to floating point math.
485e66f31c5Sopenharmony_ci   */
486e66f31c5Sopenharmony_ci  scaled_freq = (double) hrtime_frequency_ / scale;
487e66f31c5Sopenharmony_ci  result = (double) counter.QuadPart / scaled_freq;
488e66f31c5Sopenharmony_ci  return (uint64_t) result;
489e66f31c5Sopenharmony_ci}
490e66f31c5Sopenharmony_ci
491e66f31c5Sopenharmony_ci
492e66f31c5Sopenharmony_ciint uv_resident_set_memory(size_t* rss) {
493e66f31c5Sopenharmony_ci  HANDLE current_process;
494e66f31c5Sopenharmony_ci  PROCESS_MEMORY_COUNTERS pmc;
495e66f31c5Sopenharmony_ci
496e66f31c5Sopenharmony_ci  current_process = GetCurrentProcess();
497e66f31c5Sopenharmony_ci
498e66f31c5Sopenharmony_ci  if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) {
499e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
500e66f31c5Sopenharmony_ci  }
501e66f31c5Sopenharmony_ci
502e66f31c5Sopenharmony_ci  *rss = pmc.WorkingSetSize;
503e66f31c5Sopenharmony_ci
504e66f31c5Sopenharmony_ci  return 0;
505e66f31c5Sopenharmony_ci}
506e66f31c5Sopenharmony_ci
507e66f31c5Sopenharmony_ci
508e66f31c5Sopenharmony_ciint uv_uptime(double* uptime) {
509e66f31c5Sopenharmony_ci  *uptime = GetTickCount64() / 1000.0;
510e66f31c5Sopenharmony_ci  return 0;
511e66f31c5Sopenharmony_ci}
512e66f31c5Sopenharmony_ci
513e66f31c5Sopenharmony_ci
514e66f31c5Sopenharmony_ciunsigned int uv_available_parallelism(void) {
515e66f31c5Sopenharmony_ci  SYSTEM_INFO info;
516e66f31c5Sopenharmony_ci  unsigned rc;
517e66f31c5Sopenharmony_ci
518e66f31c5Sopenharmony_ci  /* TODO(bnoordhuis) Use GetLogicalProcessorInformationEx() to support systems
519e66f31c5Sopenharmony_ci   * with > 64 CPUs? See https://github.com/libuv/libuv/pull/3458
520e66f31c5Sopenharmony_ci   */
521e66f31c5Sopenharmony_ci  GetSystemInfo(&info);
522e66f31c5Sopenharmony_ci
523e66f31c5Sopenharmony_ci  rc = info.dwNumberOfProcessors;
524e66f31c5Sopenharmony_ci  if (rc < 1)
525e66f31c5Sopenharmony_ci    rc = 1;
526e66f31c5Sopenharmony_ci
527e66f31c5Sopenharmony_ci  return rc;
528e66f31c5Sopenharmony_ci}
529e66f31c5Sopenharmony_ci
530e66f31c5Sopenharmony_ci
531e66f31c5Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
532e66f31c5Sopenharmony_ci  uv_cpu_info_t* cpu_infos;
533e66f31c5Sopenharmony_ci  SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
534e66f31c5Sopenharmony_ci  DWORD sppi_size;
535e66f31c5Sopenharmony_ci  SYSTEM_INFO system_info;
536e66f31c5Sopenharmony_ci  DWORD cpu_count, i;
537e66f31c5Sopenharmony_ci  NTSTATUS status;
538e66f31c5Sopenharmony_ci  ULONG result_size;
539e66f31c5Sopenharmony_ci  int err;
540e66f31c5Sopenharmony_ci  uv_cpu_info_t* cpu_info;
541e66f31c5Sopenharmony_ci
542e66f31c5Sopenharmony_ci  cpu_infos = NULL;
543e66f31c5Sopenharmony_ci  cpu_count = 0;
544e66f31c5Sopenharmony_ci  sppi = NULL;
545e66f31c5Sopenharmony_ci
546e66f31c5Sopenharmony_ci  uv__once_init();
547e66f31c5Sopenharmony_ci
548e66f31c5Sopenharmony_ci  GetSystemInfo(&system_info);
549e66f31c5Sopenharmony_ci  cpu_count = system_info.dwNumberOfProcessors;
550e66f31c5Sopenharmony_ci
551e66f31c5Sopenharmony_ci  cpu_infos = uv__calloc(cpu_count, sizeof *cpu_infos);
552e66f31c5Sopenharmony_ci  if (cpu_infos == NULL) {
553e66f31c5Sopenharmony_ci    err = ERROR_OUTOFMEMORY;
554e66f31c5Sopenharmony_ci    goto error;
555e66f31c5Sopenharmony_ci  }
556e66f31c5Sopenharmony_ci
557e66f31c5Sopenharmony_ci  sppi_size = cpu_count * sizeof(*sppi);
558e66f31c5Sopenharmony_ci  sppi = uv__malloc(sppi_size);
559e66f31c5Sopenharmony_ci  if (sppi == NULL) {
560e66f31c5Sopenharmony_ci    err = ERROR_OUTOFMEMORY;
561e66f31c5Sopenharmony_ci    goto error;
562e66f31c5Sopenharmony_ci  }
563e66f31c5Sopenharmony_ci
564e66f31c5Sopenharmony_ci  status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
565e66f31c5Sopenharmony_ci                                     sppi,
566e66f31c5Sopenharmony_ci                                     sppi_size,
567e66f31c5Sopenharmony_ci                                     &result_size);
568e66f31c5Sopenharmony_ci  if (!NT_SUCCESS(status)) {
569e66f31c5Sopenharmony_ci    err = pRtlNtStatusToDosError(status);
570e66f31c5Sopenharmony_ci    goto error;
571e66f31c5Sopenharmony_ci  }
572e66f31c5Sopenharmony_ci
573e66f31c5Sopenharmony_ci  assert(result_size == sppi_size);
574e66f31c5Sopenharmony_ci
575e66f31c5Sopenharmony_ci  for (i = 0; i < cpu_count; i++) {
576e66f31c5Sopenharmony_ci    WCHAR key_name[128];
577e66f31c5Sopenharmony_ci    HKEY processor_key;
578e66f31c5Sopenharmony_ci    DWORD cpu_speed;
579e66f31c5Sopenharmony_ci    DWORD cpu_speed_size = sizeof(cpu_speed);
580e66f31c5Sopenharmony_ci    WCHAR cpu_brand[256];
581e66f31c5Sopenharmony_ci    DWORD cpu_brand_size = sizeof(cpu_brand);
582e66f31c5Sopenharmony_ci    size_t len;
583e66f31c5Sopenharmony_ci
584e66f31c5Sopenharmony_ci    len = _snwprintf(key_name,
585e66f31c5Sopenharmony_ci                     ARRAY_SIZE(key_name),
586e66f31c5Sopenharmony_ci                     L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
587e66f31c5Sopenharmony_ci                     i);
588e66f31c5Sopenharmony_ci
589e66f31c5Sopenharmony_ci    assert(len > 0 && len < ARRAY_SIZE(key_name));
590e66f31c5Sopenharmony_ci
591e66f31c5Sopenharmony_ci    err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
592e66f31c5Sopenharmony_ci                        key_name,
593e66f31c5Sopenharmony_ci                        0,
594e66f31c5Sopenharmony_ci                        KEY_QUERY_VALUE,
595e66f31c5Sopenharmony_ci                        &processor_key);
596e66f31c5Sopenharmony_ci    if (err != ERROR_SUCCESS) {
597e66f31c5Sopenharmony_ci      goto error;
598e66f31c5Sopenharmony_ci    }
599e66f31c5Sopenharmony_ci
600e66f31c5Sopenharmony_ci    err = RegQueryValueExW(processor_key,
601e66f31c5Sopenharmony_ci                           L"~MHz",
602e66f31c5Sopenharmony_ci                           NULL,
603e66f31c5Sopenharmony_ci                           NULL,
604e66f31c5Sopenharmony_ci                           (BYTE*)&cpu_speed,
605e66f31c5Sopenharmony_ci                           &cpu_speed_size);
606e66f31c5Sopenharmony_ci    if (err != ERROR_SUCCESS) {
607e66f31c5Sopenharmony_ci      RegCloseKey(processor_key);
608e66f31c5Sopenharmony_ci      goto error;
609e66f31c5Sopenharmony_ci    }
610e66f31c5Sopenharmony_ci
611e66f31c5Sopenharmony_ci    err = RegQueryValueExW(processor_key,
612e66f31c5Sopenharmony_ci                           L"ProcessorNameString",
613e66f31c5Sopenharmony_ci                           NULL,
614e66f31c5Sopenharmony_ci                           NULL,
615e66f31c5Sopenharmony_ci                           (BYTE*)&cpu_brand,
616e66f31c5Sopenharmony_ci                           &cpu_brand_size);
617e66f31c5Sopenharmony_ci    RegCloseKey(processor_key);
618e66f31c5Sopenharmony_ci    if (err != ERROR_SUCCESS)
619e66f31c5Sopenharmony_ci      goto error;
620e66f31c5Sopenharmony_ci
621e66f31c5Sopenharmony_ci    cpu_info = &cpu_infos[i];
622e66f31c5Sopenharmony_ci    cpu_info->speed = cpu_speed;
623e66f31c5Sopenharmony_ci    cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
624e66f31c5Sopenharmony_ci    cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
625e66f31c5Sopenharmony_ci        sppi[i].IdleTime.QuadPart) / 10000;
626e66f31c5Sopenharmony_ci    cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
627e66f31c5Sopenharmony_ci    cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
628e66f31c5Sopenharmony_ci    cpu_info->cpu_times.nice = 0;
629e66f31c5Sopenharmony_ci
630e66f31c5Sopenharmony_ci    uv__convert_utf16_to_utf8(cpu_brand,
631e66f31c5Sopenharmony_ci                              cpu_brand_size / sizeof(WCHAR),
632e66f31c5Sopenharmony_ci                              &(cpu_info->model));
633e66f31c5Sopenharmony_ci  }
634e66f31c5Sopenharmony_ci
635e66f31c5Sopenharmony_ci  uv__free(sppi);
636e66f31c5Sopenharmony_ci
637e66f31c5Sopenharmony_ci  *cpu_count_ptr = cpu_count;
638e66f31c5Sopenharmony_ci  *cpu_infos_ptr = cpu_infos;
639e66f31c5Sopenharmony_ci
640e66f31c5Sopenharmony_ci  return 0;
641e66f31c5Sopenharmony_ci
642e66f31c5Sopenharmony_ci error:
643e66f31c5Sopenharmony_ci  if (cpu_infos != NULL) {
644e66f31c5Sopenharmony_ci    /* This is safe because the cpu_infos array is zeroed on allocation. */
645e66f31c5Sopenharmony_ci    for (i = 0; i < cpu_count; i++)
646e66f31c5Sopenharmony_ci      uv__free(cpu_infos[i].model);
647e66f31c5Sopenharmony_ci  }
648e66f31c5Sopenharmony_ci
649e66f31c5Sopenharmony_ci  uv__free(cpu_infos);
650e66f31c5Sopenharmony_ci  uv__free(sppi);
651e66f31c5Sopenharmony_ci
652e66f31c5Sopenharmony_ci  return uv_translate_sys_error(err);
653e66f31c5Sopenharmony_ci}
654e66f31c5Sopenharmony_ci
655e66f31c5Sopenharmony_ci
656e66f31c5Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses_ptr,
657e66f31c5Sopenharmony_ci    int* count_ptr) {
658e66f31c5Sopenharmony_ci  IP_ADAPTER_ADDRESSES* win_address_buf;
659e66f31c5Sopenharmony_ci  ULONG win_address_buf_size;
660e66f31c5Sopenharmony_ci  IP_ADAPTER_ADDRESSES* adapter;
661e66f31c5Sopenharmony_ci
662e66f31c5Sopenharmony_ci  uv_interface_address_t* uv_address_buf;
663e66f31c5Sopenharmony_ci  char* name_buf;
664e66f31c5Sopenharmony_ci  size_t uv_address_buf_size;
665e66f31c5Sopenharmony_ci  uv_interface_address_t* uv_address;
666e66f31c5Sopenharmony_ci
667e66f31c5Sopenharmony_ci  int count;
668e66f31c5Sopenharmony_ci  ULONG flags;
669e66f31c5Sopenharmony_ci
670e66f31c5Sopenharmony_ci  *addresses_ptr = NULL;
671e66f31c5Sopenharmony_ci  *count_ptr = 0;
672e66f31c5Sopenharmony_ci
673e66f31c5Sopenharmony_ci  flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
674e66f31c5Sopenharmony_ci    GAA_FLAG_SKIP_DNS_SERVER;
675e66f31c5Sopenharmony_ci
676e66f31c5Sopenharmony_ci  /* Fetch the size of the adapters reported by windows, and then get the list
677e66f31c5Sopenharmony_ci   * itself. */
678e66f31c5Sopenharmony_ci  win_address_buf_size = 0;
679e66f31c5Sopenharmony_ci  win_address_buf = NULL;
680e66f31c5Sopenharmony_ci
681e66f31c5Sopenharmony_ci  for (;;) {
682e66f31c5Sopenharmony_ci    ULONG r;
683e66f31c5Sopenharmony_ci
684e66f31c5Sopenharmony_ci    /* If win_address_buf is 0, then GetAdaptersAddresses will fail with.
685e66f31c5Sopenharmony_ci     * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in
686e66f31c5Sopenharmony_ci     * win_address_buf_size. */
687e66f31c5Sopenharmony_ci    r = GetAdaptersAddresses(AF_UNSPEC,
688e66f31c5Sopenharmony_ci                             flags,
689e66f31c5Sopenharmony_ci                             NULL,
690e66f31c5Sopenharmony_ci                             win_address_buf,
691e66f31c5Sopenharmony_ci                             &win_address_buf_size);
692e66f31c5Sopenharmony_ci
693e66f31c5Sopenharmony_ci    if (r == ERROR_SUCCESS)
694e66f31c5Sopenharmony_ci      break;
695e66f31c5Sopenharmony_ci
696e66f31c5Sopenharmony_ci    uv__free(win_address_buf);
697e66f31c5Sopenharmony_ci
698e66f31c5Sopenharmony_ci    switch (r) {
699e66f31c5Sopenharmony_ci      case ERROR_BUFFER_OVERFLOW:
700e66f31c5Sopenharmony_ci        /* This happens when win_address_buf is NULL or too small to hold all
701e66f31c5Sopenharmony_ci         * adapters. */
702e66f31c5Sopenharmony_ci        win_address_buf = uv__malloc(win_address_buf_size);
703e66f31c5Sopenharmony_ci        if (win_address_buf == NULL)
704e66f31c5Sopenharmony_ci          return UV_ENOMEM;
705e66f31c5Sopenharmony_ci
706e66f31c5Sopenharmony_ci        continue;
707e66f31c5Sopenharmony_ci
708e66f31c5Sopenharmony_ci      case ERROR_NO_DATA: {
709e66f31c5Sopenharmony_ci        /* No adapters were found. */
710e66f31c5Sopenharmony_ci        uv_address_buf = uv__malloc(1);
711e66f31c5Sopenharmony_ci        if (uv_address_buf == NULL)
712e66f31c5Sopenharmony_ci          return UV_ENOMEM;
713e66f31c5Sopenharmony_ci
714e66f31c5Sopenharmony_ci        *count_ptr = 0;
715e66f31c5Sopenharmony_ci        *addresses_ptr = uv_address_buf;
716e66f31c5Sopenharmony_ci
717e66f31c5Sopenharmony_ci        return 0;
718e66f31c5Sopenharmony_ci      }
719e66f31c5Sopenharmony_ci
720e66f31c5Sopenharmony_ci      case ERROR_ADDRESS_NOT_ASSOCIATED:
721e66f31c5Sopenharmony_ci        return UV_EAGAIN;
722e66f31c5Sopenharmony_ci
723e66f31c5Sopenharmony_ci      case ERROR_INVALID_PARAMETER:
724e66f31c5Sopenharmony_ci        /* MSDN says:
725e66f31c5Sopenharmony_ci         *   "This error is returned for any of the following conditions: the
726e66f31c5Sopenharmony_ci         *   SizePointer parameter is NULL, the Address parameter is not
727e66f31c5Sopenharmony_ci         *   AF_INET, AF_INET6, or AF_UNSPEC, or the address information for
728e66f31c5Sopenharmony_ci         *   the parameters requested is greater than ULONG_MAX."
729e66f31c5Sopenharmony_ci         * Since the first two conditions are not met, it must be that the
730e66f31c5Sopenharmony_ci         * adapter data is too big.
731e66f31c5Sopenharmony_ci         */
732e66f31c5Sopenharmony_ci        return UV_ENOBUFS;
733e66f31c5Sopenharmony_ci
734e66f31c5Sopenharmony_ci      default:
735e66f31c5Sopenharmony_ci        /* Other (unspecified) errors can happen, but we don't have any special
736e66f31c5Sopenharmony_ci         * meaning for them. */
737e66f31c5Sopenharmony_ci        assert(r != ERROR_SUCCESS);
738e66f31c5Sopenharmony_ci        return uv_translate_sys_error(r);
739e66f31c5Sopenharmony_ci    }
740e66f31c5Sopenharmony_ci  }
741e66f31c5Sopenharmony_ci
742e66f31c5Sopenharmony_ci  /* Count the number of enabled interfaces and compute how much space is
743e66f31c5Sopenharmony_ci   * needed to store their info. */
744e66f31c5Sopenharmony_ci  count = 0;
745e66f31c5Sopenharmony_ci  uv_address_buf_size = 0;
746e66f31c5Sopenharmony_ci
747e66f31c5Sopenharmony_ci  for (adapter = win_address_buf;
748e66f31c5Sopenharmony_ci       adapter != NULL;
749e66f31c5Sopenharmony_ci       adapter = adapter->Next) {
750e66f31c5Sopenharmony_ci    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
751e66f31c5Sopenharmony_ci    int name_size;
752e66f31c5Sopenharmony_ci
753e66f31c5Sopenharmony_ci    /* Interfaces that are not 'up' should not be reported. Also skip
754e66f31c5Sopenharmony_ci     * interfaces that have no associated unicast address, as to avoid
755e66f31c5Sopenharmony_ci     * allocating space for the name for this interface. */
756e66f31c5Sopenharmony_ci    if (adapter->OperStatus != IfOperStatusUp ||
757e66f31c5Sopenharmony_ci        adapter->FirstUnicastAddress == NULL)
758e66f31c5Sopenharmony_ci      continue;
759e66f31c5Sopenharmony_ci
760e66f31c5Sopenharmony_ci    /* Compute the size of the interface name. */
761e66f31c5Sopenharmony_ci    name_size = uv_utf16_length_as_wtf8(adapter->FriendlyName, -1);
762e66f31c5Sopenharmony_ci    uv_address_buf_size += name_size + 1;
763e66f31c5Sopenharmony_ci
764e66f31c5Sopenharmony_ci    /* Count the number of addresses associated with this interface, and
765e66f31c5Sopenharmony_ci     * compute the size. */
766e66f31c5Sopenharmony_ci    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
767e66f31c5Sopenharmony_ci                           adapter->FirstUnicastAddress;
768e66f31c5Sopenharmony_ci         unicast_address != NULL;
769e66f31c5Sopenharmony_ci         unicast_address = unicast_address->Next) {
770e66f31c5Sopenharmony_ci      count++;
771e66f31c5Sopenharmony_ci      uv_address_buf_size += sizeof(uv_interface_address_t);
772e66f31c5Sopenharmony_ci    }
773e66f31c5Sopenharmony_ci  }
774e66f31c5Sopenharmony_ci
775e66f31c5Sopenharmony_ci  /* Allocate space to store interface data plus adapter names. */
776e66f31c5Sopenharmony_ci  uv_address_buf = uv__malloc(uv_address_buf_size);
777e66f31c5Sopenharmony_ci  if (uv_address_buf == NULL) {
778e66f31c5Sopenharmony_ci    uv__free(win_address_buf);
779e66f31c5Sopenharmony_ci    return UV_ENOMEM;
780e66f31c5Sopenharmony_ci  }
781e66f31c5Sopenharmony_ci
782e66f31c5Sopenharmony_ci  /* Compute the start of the uv_interface_address_t array, and the place in
783e66f31c5Sopenharmony_ci   * the buffer where the interface names will be stored. */
784e66f31c5Sopenharmony_ci  uv_address = uv_address_buf;
785e66f31c5Sopenharmony_ci  name_buf = (char*) (uv_address_buf + count);
786e66f31c5Sopenharmony_ci
787e66f31c5Sopenharmony_ci  /* Fill out the output buffer. */
788e66f31c5Sopenharmony_ci  for (adapter = win_address_buf;
789e66f31c5Sopenharmony_ci       adapter != NULL;
790e66f31c5Sopenharmony_ci       adapter = adapter->Next) {
791e66f31c5Sopenharmony_ci    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
792e66f31c5Sopenharmony_ci    size_t name_size;
793e66f31c5Sopenharmony_ci    int r;
794e66f31c5Sopenharmony_ci
795e66f31c5Sopenharmony_ci    if (adapter->OperStatus != IfOperStatusUp ||
796e66f31c5Sopenharmony_ci        adapter->FirstUnicastAddress == NULL)
797e66f31c5Sopenharmony_ci      continue;
798e66f31c5Sopenharmony_ci
799e66f31c5Sopenharmony_ci    /* Convert the interface name to UTF8. */
800e66f31c5Sopenharmony_ci    name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
801e66f31c5Sopenharmony_ci    r = uv__copy_utf16_to_utf8(adapter->FriendlyName,
802e66f31c5Sopenharmony_ci                               -1,
803e66f31c5Sopenharmony_ci                               name_buf,
804e66f31c5Sopenharmony_ci                               &name_size);
805e66f31c5Sopenharmony_ci    if (r) {
806e66f31c5Sopenharmony_ci      uv__free(win_address_buf);
807e66f31c5Sopenharmony_ci      uv__free(uv_address_buf);
808e66f31c5Sopenharmony_ci      return r;
809e66f31c5Sopenharmony_ci    }
810e66f31c5Sopenharmony_ci    name_size += 1; /* Add NUL byte. */
811e66f31c5Sopenharmony_ci
812e66f31c5Sopenharmony_ci    /* Add an uv_interface_address_t element for every unicast address. */
813e66f31c5Sopenharmony_ci    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
814e66f31c5Sopenharmony_ci                           adapter->FirstUnicastAddress;
815e66f31c5Sopenharmony_ci         unicast_address != NULL;
816e66f31c5Sopenharmony_ci         unicast_address = unicast_address->Next) {
817e66f31c5Sopenharmony_ci      struct sockaddr* sa;
818e66f31c5Sopenharmony_ci      ULONG prefix_len;
819e66f31c5Sopenharmony_ci
820e66f31c5Sopenharmony_ci      sa = unicast_address->Address.lpSockaddr;
821e66f31c5Sopenharmony_ci
822e66f31c5Sopenharmony_ci      prefix_len =
823e66f31c5Sopenharmony_ci        ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength;
824e66f31c5Sopenharmony_ci
825e66f31c5Sopenharmony_ci      memset(uv_address, 0, sizeof *uv_address);
826e66f31c5Sopenharmony_ci
827e66f31c5Sopenharmony_ci      uv_address->name = name_buf;
828e66f31c5Sopenharmony_ci
829e66f31c5Sopenharmony_ci      if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) {
830e66f31c5Sopenharmony_ci        memcpy(uv_address->phys_addr,
831e66f31c5Sopenharmony_ci               adapter->PhysicalAddress,
832e66f31c5Sopenharmony_ci               sizeof(uv_address->phys_addr));
833e66f31c5Sopenharmony_ci      }
834e66f31c5Sopenharmony_ci
835e66f31c5Sopenharmony_ci      uv_address->is_internal =
836e66f31c5Sopenharmony_ci          (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
837e66f31c5Sopenharmony_ci
838e66f31c5Sopenharmony_ci      if (sa->sa_family == AF_INET6) {
839e66f31c5Sopenharmony_ci        uv_address->address.address6 = *((struct sockaddr_in6 *) sa);
840e66f31c5Sopenharmony_ci
841e66f31c5Sopenharmony_ci        uv_address->netmask.netmask6.sin6_family = AF_INET6;
842e66f31c5Sopenharmony_ci        memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3);
843e66f31c5Sopenharmony_ci        /* This check ensures that we don't write past the size of the data. */
844e66f31c5Sopenharmony_ci        if (prefix_len % 8) {
845e66f31c5Sopenharmony_ci          uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] =
846e66f31c5Sopenharmony_ci              0xff << (8 - prefix_len % 8);
847e66f31c5Sopenharmony_ci        }
848e66f31c5Sopenharmony_ci
849e66f31c5Sopenharmony_ci      } else {
850e66f31c5Sopenharmony_ci        uv_address->address.address4 = *((struct sockaddr_in *) sa);
851e66f31c5Sopenharmony_ci
852e66f31c5Sopenharmony_ci        uv_address->netmask.netmask4.sin_family = AF_INET;
853e66f31c5Sopenharmony_ci        uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ?
854e66f31c5Sopenharmony_ci            htonl(0xffffffff << (32 - prefix_len)) : 0;
855e66f31c5Sopenharmony_ci      }
856e66f31c5Sopenharmony_ci
857e66f31c5Sopenharmony_ci      uv_address++;
858e66f31c5Sopenharmony_ci    }
859e66f31c5Sopenharmony_ci
860e66f31c5Sopenharmony_ci    name_buf += name_size;
861e66f31c5Sopenharmony_ci  }
862e66f31c5Sopenharmony_ci
863e66f31c5Sopenharmony_ci  uv__free(win_address_buf);
864e66f31c5Sopenharmony_ci
865e66f31c5Sopenharmony_ci  *addresses_ptr = uv_address_buf;
866e66f31c5Sopenharmony_ci  *count_ptr = count;
867e66f31c5Sopenharmony_ci
868e66f31c5Sopenharmony_ci  return 0;
869e66f31c5Sopenharmony_ci}
870e66f31c5Sopenharmony_ci
871e66f31c5Sopenharmony_ci
872e66f31c5Sopenharmony_civoid uv_free_interface_addresses(uv_interface_address_t* addresses,
873e66f31c5Sopenharmony_ci    int count) {
874e66f31c5Sopenharmony_ci  uv__free(addresses);
875e66f31c5Sopenharmony_ci}
876e66f31c5Sopenharmony_ci
877e66f31c5Sopenharmony_ci
878e66f31c5Sopenharmony_ciint uv_getrusage(uv_rusage_t *uv_rusage) {
879e66f31c5Sopenharmony_ci  FILETIME createTime, exitTime, kernelTime, userTime;
880e66f31c5Sopenharmony_ci  SYSTEMTIME kernelSystemTime, userSystemTime;
881e66f31c5Sopenharmony_ci  PROCESS_MEMORY_COUNTERS memCounters;
882e66f31c5Sopenharmony_ci  IO_COUNTERS ioCounters;
883e66f31c5Sopenharmony_ci  int ret;
884e66f31c5Sopenharmony_ci
885e66f31c5Sopenharmony_ci  ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
886e66f31c5Sopenharmony_ci  if (ret == 0) {
887e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
888e66f31c5Sopenharmony_ci  }
889e66f31c5Sopenharmony_ci
890e66f31c5Sopenharmony_ci  ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);
891e66f31c5Sopenharmony_ci  if (ret == 0) {
892e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
893e66f31c5Sopenharmony_ci  }
894e66f31c5Sopenharmony_ci
895e66f31c5Sopenharmony_ci  ret = FileTimeToSystemTime(&userTime, &userSystemTime);
896e66f31c5Sopenharmony_ci  if (ret == 0) {
897e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
898e66f31c5Sopenharmony_ci  }
899e66f31c5Sopenharmony_ci
900e66f31c5Sopenharmony_ci  ret = GetProcessMemoryInfo(GetCurrentProcess(),
901e66f31c5Sopenharmony_ci                             &memCounters,
902e66f31c5Sopenharmony_ci                             sizeof(memCounters));
903e66f31c5Sopenharmony_ci  if (ret == 0) {
904e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
905e66f31c5Sopenharmony_ci  }
906e66f31c5Sopenharmony_ci
907e66f31c5Sopenharmony_ci  ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
908e66f31c5Sopenharmony_ci  if (ret == 0) {
909e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
910e66f31c5Sopenharmony_ci  }
911e66f31c5Sopenharmony_ci
912e66f31c5Sopenharmony_ci  memset(uv_rusage, 0, sizeof(*uv_rusage));
913e66f31c5Sopenharmony_ci
914e66f31c5Sopenharmony_ci  uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
915e66f31c5Sopenharmony_ci                               userSystemTime.wMinute * 60 +
916e66f31c5Sopenharmony_ci                               userSystemTime.wSecond;
917e66f31c5Sopenharmony_ci  uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;
918e66f31c5Sopenharmony_ci
919e66f31c5Sopenharmony_ci  uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 +
920e66f31c5Sopenharmony_ci                               kernelSystemTime.wMinute * 60 +
921e66f31c5Sopenharmony_ci                               kernelSystemTime.wSecond;
922e66f31c5Sopenharmony_ci  uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
923e66f31c5Sopenharmony_ci
924e66f31c5Sopenharmony_ci  uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
925e66f31c5Sopenharmony_ci  uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
926e66f31c5Sopenharmony_ci
927e66f31c5Sopenharmony_ci  uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;
928e66f31c5Sopenharmony_ci  uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;
929e66f31c5Sopenharmony_ci
930e66f31c5Sopenharmony_ci  return 0;
931e66f31c5Sopenharmony_ci}
932e66f31c5Sopenharmony_ci
933e66f31c5Sopenharmony_ci
934e66f31c5Sopenharmony_ciint uv_os_homedir(char* buffer, size_t* size) {
935e66f31c5Sopenharmony_ci  uv_passwd_t pwd;
936e66f31c5Sopenharmony_ci  size_t len;
937e66f31c5Sopenharmony_ci  int r;
938e66f31c5Sopenharmony_ci
939e66f31c5Sopenharmony_ci  /* Check if the USERPROFILE environment variable is set first. The task of
940e66f31c5Sopenharmony_ci     performing input validation on buffer and size is taken care of by
941e66f31c5Sopenharmony_ci     uv_os_getenv(). */
942e66f31c5Sopenharmony_ci  r = uv_os_getenv("USERPROFILE", buffer, size);
943e66f31c5Sopenharmony_ci
944e66f31c5Sopenharmony_ci  /* Don't return an error if USERPROFILE was not found. */
945e66f31c5Sopenharmony_ci  if (r != UV_ENOENT)
946e66f31c5Sopenharmony_ci    return r;
947e66f31c5Sopenharmony_ci
948e66f31c5Sopenharmony_ci  /* USERPROFILE is not set, so call uv_os_get_passwd() */
949e66f31c5Sopenharmony_ci  r = uv_os_get_passwd(&pwd);
950e66f31c5Sopenharmony_ci
951e66f31c5Sopenharmony_ci  if (r != 0) {
952e66f31c5Sopenharmony_ci    return r;
953e66f31c5Sopenharmony_ci  }
954e66f31c5Sopenharmony_ci
955e66f31c5Sopenharmony_ci  len = strlen(pwd.homedir);
956e66f31c5Sopenharmony_ci
957e66f31c5Sopenharmony_ci  if (len >= *size) {
958e66f31c5Sopenharmony_ci    *size = len + 1;
959e66f31c5Sopenharmony_ci    uv_os_free_passwd(&pwd);
960e66f31c5Sopenharmony_ci    return UV_ENOBUFS;
961e66f31c5Sopenharmony_ci  }
962e66f31c5Sopenharmony_ci
963e66f31c5Sopenharmony_ci  memcpy(buffer, pwd.homedir, len + 1);
964e66f31c5Sopenharmony_ci  *size = len;
965e66f31c5Sopenharmony_ci  uv_os_free_passwd(&pwd);
966e66f31c5Sopenharmony_ci
967e66f31c5Sopenharmony_ci  return 0;
968e66f31c5Sopenharmony_ci}
969e66f31c5Sopenharmony_ci
970e66f31c5Sopenharmony_ci
971e66f31c5Sopenharmony_ciint uv_os_tmpdir(char* buffer, size_t* size) {
972e66f31c5Sopenharmony_ci  wchar_t *path;
973e66f31c5Sopenharmony_ci  size_t len;
974e66f31c5Sopenharmony_ci
975e66f31c5Sopenharmony_ci  if (buffer == NULL || size == NULL || *size == 0)
976e66f31c5Sopenharmony_ci    return UV_EINVAL;
977e66f31c5Sopenharmony_ci
978e66f31c5Sopenharmony_ci  len = 0;
979e66f31c5Sopenharmony_ci  len = GetTempPathW(0, NULL);
980e66f31c5Sopenharmony_ci  if (len == 0) {
981e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
982e66f31c5Sopenharmony_ci  }
983e66f31c5Sopenharmony_ci  /* Include space for terminating null char. */
984e66f31c5Sopenharmony_ci  len += 1;
985e66f31c5Sopenharmony_ci  path = uv__malloc(len * sizeof(wchar_t));
986e66f31c5Sopenharmony_ci  if (path == NULL) {
987e66f31c5Sopenharmony_ci    return UV_ENOMEM;
988e66f31c5Sopenharmony_ci  }
989e66f31c5Sopenharmony_ci  len = GetTempPathW(len, path);
990e66f31c5Sopenharmony_ci
991e66f31c5Sopenharmony_ci  if (len == 0) {
992e66f31c5Sopenharmony_ci    uv__free(path);
993e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
994e66f31c5Sopenharmony_ci  }
995e66f31c5Sopenharmony_ci
996e66f31c5Sopenharmony_ci  /* The returned directory should not have a trailing slash, unless it points
997e66f31c5Sopenharmony_ci   * at a drive root, like c:\. Remove it if needed. */
998e66f31c5Sopenharmony_ci  if (path[len - 1] == L'\\' &&
999e66f31c5Sopenharmony_ci      !(len == 3 && path[1] == L':')) {
1000e66f31c5Sopenharmony_ci    len--;
1001e66f31c5Sopenharmony_ci    path[len] = L'\0';
1002e66f31c5Sopenharmony_ci  }
1003e66f31c5Sopenharmony_ci
1004e66f31c5Sopenharmony_ci  return uv__copy_utf16_to_utf8(path, len, buffer, size);
1005e66f31c5Sopenharmony_ci}
1006e66f31c5Sopenharmony_ci
1007e66f31c5Sopenharmony_ci
1008e66f31c5Sopenharmony_ci/*
1009e66f31c5Sopenharmony_ci * Converts a UTF-16 string into a UTF-8 one. The resulting string is
1010e66f31c5Sopenharmony_ci * null-terminated.
1011e66f31c5Sopenharmony_ci *
1012e66f31c5Sopenharmony_ci * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
1013e66f31c5Sopenharmony_ci * be specified.
1014e66f31c5Sopenharmony_ci */
1015e66f31c5Sopenharmony_ciint uv__convert_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char** utf8) {
1016e66f31c5Sopenharmony_ci  size_t utf8_len = 0;
1017e66f31c5Sopenharmony_ci
1018e66f31c5Sopenharmony_ci  if (utf16 == NULL)
1019e66f31c5Sopenharmony_ci    return UV_EINVAL;
1020e66f31c5Sopenharmony_ci
1021e66f31c5Sopenharmony_ci   *utf8 = NULL;
1022e66f31c5Sopenharmony_ci   return uv_utf16_to_wtf8(utf16, utf16len, utf8, &utf8_len);
1023e66f31c5Sopenharmony_ci}
1024e66f31c5Sopenharmony_ci
1025e66f31c5Sopenharmony_ci
1026e66f31c5Sopenharmony_ci/*
1027e66f31c5Sopenharmony_ci * Converts a UTF-8 string into a UTF-16 one. The resulting string is
1028e66f31c5Sopenharmony_ci * null-terminated.
1029e66f31c5Sopenharmony_ci */
1030e66f31c5Sopenharmony_ciint uv__convert_utf8_to_utf16(const char* utf8, WCHAR** utf16) {
1031e66f31c5Sopenharmony_ci  int bufsize;
1032e66f31c5Sopenharmony_ci
1033e66f31c5Sopenharmony_ci  if (utf8 == NULL)
1034e66f31c5Sopenharmony_ci    return UV_EINVAL;
1035e66f31c5Sopenharmony_ci
1036e66f31c5Sopenharmony_ci  /* Check how much space we need (including NUL). */
1037e66f31c5Sopenharmony_ci  bufsize = uv_wtf8_length_as_utf16(utf8);
1038e66f31c5Sopenharmony_ci  if (bufsize < 0)
1039e66f31c5Sopenharmony_ci    return UV__EINVAL;
1040e66f31c5Sopenharmony_ci
1041e66f31c5Sopenharmony_ci  /* Allocate the destination buffer. */
1042e66f31c5Sopenharmony_ci  *utf16 = uv__malloc(sizeof(WCHAR) * bufsize);
1043e66f31c5Sopenharmony_ci
1044e66f31c5Sopenharmony_ci  if (*utf16 == NULL)
1045e66f31c5Sopenharmony_ci    return UV_ENOMEM;
1046e66f31c5Sopenharmony_ci
1047e66f31c5Sopenharmony_ci  /* Convert to UTF-16 */
1048e66f31c5Sopenharmony_ci  uv_wtf8_to_utf16(utf8, *utf16, bufsize);
1049e66f31c5Sopenharmony_ci
1050e66f31c5Sopenharmony_ci  return 0;
1051e66f31c5Sopenharmony_ci}
1052e66f31c5Sopenharmony_ci
1053e66f31c5Sopenharmony_ci
1054e66f31c5Sopenharmony_ci/*
1055e66f31c5Sopenharmony_ci * Converts a UTF-16 string into a UTF-8 one in an existing buffer. The
1056e66f31c5Sopenharmony_ci * resulting string is null-terminated.
1057e66f31c5Sopenharmony_ci *
1058e66f31c5Sopenharmony_ci * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
1059e66f31c5Sopenharmony_ci * be specified.
1060e66f31c5Sopenharmony_ci */
1061e66f31c5Sopenharmony_ciint uv__copy_utf16_to_utf8(const WCHAR* utf16buffer, size_t utf16len, char* utf8, size_t *size) {
1062e66f31c5Sopenharmony_ci  int r;
1063e66f31c5Sopenharmony_ci
1064e66f31c5Sopenharmony_ci  if (utf8 == NULL || size == NULL)
1065e66f31c5Sopenharmony_ci    return UV_EINVAL;
1066e66f31c5Sopenharmony_ci
1067e66f31c5Sopenharmony_ci  if (*size == 0) {
1068e66f31c5Sopenharmony_ci    *size = uv_utf16_length_as_wtf8(utf16buffer, utf16len);
1069e66f31c5Sopenharmony_ci    r = UV_ENOBUFS;
1070e66f31c5Sopenharmony_ci  } else {
1071e66f31c5Sopenharmony_ci    *size -= 1; /* Reserve space for NUL. */
1072e66f31c5Sopenharmony_ci    r = uv_utf16_to_wtf8(utf16buffer, utf16len, &utf8, size);
1073e66f31c5Sopenharmony_ci  }
1074e66f31c5Sopenharmony_ci  if (r == UV_ENOBUFS)
1075e66f31c5Sopenharmony_ci    *size += 1; /* Add space for NUL. */
1076e66f31c5Sopenharmony_ci  return r;
1077e66f31c5Sopenharmony_ci}
1078e66f31c5Sopenharmony_ci
1079e66f31c5Sopenharmony_ci
1080e66f31c5Sopenharmony_cistatic int uv__getpwuid_r(uv_passwd_t* pwd) {
1081e66f31c5Sopenharmony_ci  HANDLE token;
1082e66f31c5Sopenharmony_ci  wchar_t username[UNLEN + 1];
1083e66f31c5Sopenharmony_ci  wchar_t *path;
1084e66f31c5Sopenharmony_ci  DWORD bufsize;
1085e66f31c5Sopenharmony_ci  int r;
1086e66f31c5Sopenharmony_ci
1087e66f31c5Sopenharmony_ci  if (pwd == NULL)
1088e66f31c5Sopenharmony_ci    return UV_EINVAL;
1089e66f31c5Sopenharmony_ci
1090e66f31c5Sopenharmony_ci  /* Get the home directory using GetUserProfileDirectoryW() */
1091e66f31c5Sopenharmony_ci  if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
1092e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
1093e66f31c5Sopenharmony_ci
1094e66f31c5Sopenharmony_ci  bufsize = 0;
1095e66f31c5Sopenharmony_ci  GetUserProfileDirectoryW(token, NULL, &bufsize);
1096e66f31c5Sopenharmony_ci  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1097e66f31c5Sopenharmony_ci    r = GetLastError();
1098e66f31c5Sopenharmony_ci    CloseHandle(token);
1099e66f31c5Sopenharmony_ci    return uv_translate_sys_error(r);
1100e66f31c5Sopenharmony_ci  }
1101e66f31c5Sopenharmony_ci
1102e66f31c5Sopenharmony_ci  path = uv__malloc(bufsize * sizeof(wchar_t));
1103e66f31c5Sopenharmony_ci  if (path == NULL) {
1104e66f31c5Sopenharmony_ci    CloseHandle(token);
1105e66f31c5Sopenharmony_ci    return UV_ENOMEM;
1106e66f31c5Sopenharmony_ci  }
1107e66f31c5Sopenharmony_ci
1108e66f31c5Sopenharmony_ci  if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
1109e66f31c5Sopenharmony_ci    r = GetLastError();
1110e66f31c5Sopenharmony_ci    CloseHandle(token);
1111e66f31c5Sopenharmony_ci    uv__free(path);
1112e66f31c5Sopenharmony_ci    return uv_translate_sys_error(r);
1113e66f31c5Sopenharmony_ci  }
1114e66f31c5Sopenharmony_ci
1115e66f31c5Sopenharmony_ci  CloseHandle(token);
1116e66f31c5Sopenharmony_ci
1117e66f31c5Sopenharmony_ci  /* Get the username using GetUserNameW() */
1118e66f31c5Sopenharmony_ci  bufsize = ARRAY_SIZE(username);
1119e66f31c5Sopenharmony_ci  if (!GetUserNameW(username, &bufsize)) {
1120e66f31c5Sopenharmony_ci    r = GetLastError();
1121e66f31c5Sopenharmony_ci    uv__free(path);
1122e66f31c5Sopenharmony_ci
1123e66f31c5Sopenharmony_ci    /* This should not be possible */
1124e66f31c5Sopenharmony_ci    if (r == ERROR_INSUFFICIENT_BUFFER)
1125e66f31c5Sopenharmony_ci      return UV_ENOMEM;
1126e66f31c5Sopenharmony_ci
1127e66f31c5Sopenharmony_ci    return uv_translate_sys_error(r);
1128e66f31c5Sopenharmony_ci  }
1129e66f31c5Sopenharmony_ci
1130e66f31c5Sopenharmony_ci  pwd->homedir = NULL;
1131e66f31c5Sopenharmony_ci  r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir);
1132e66f31c5Sopenharmony_ci  uv__free(path);
1133e66f31c5Sopenharmony_ci
1134e66f31c5Sopenharmony_ci  if (r != 0)
1135e66f31c5Sopenharmony_ci    return r;
1136e66f31c5Sopenharmony_ci
1137e66f31c5Sopenharmony_ci  pwd->username = NULL;
1138e66f31c5Sopenharmony_ci  r = uv__convert_utf16_to_utf8(username, -1, &pwd->username);
1139e66f31c5Sopenharmony_ci
1140e66f31c5Sopenharmony_ci  if (r != 0) {
1141e66f31c5Sopenharmony_ci    uv__free(pwd->homedir);
1142e66f31c5Sopenharmony_ci    return r;
1143e66f31c5Sopenharmony_ci  }
1144e66f31c5Sopenharmony_ci
1145e66f31c5Sopenharmony_ci  pwd->shell = NULL;
1146e66f31c5Sopenharmony_ci  pwd->uid = -1;
1147e66f31c5Sopenharmony_ci  pwd->gid = -1;
1148e66f31c5Sopenharmony_ci
1149e66f31c5Sopenharmony_ci  return 0;
1150e66f31c5Sopenharmony_ci}
1151e66f31c5Sopenharmony_ci
1152e66f31c5Sopenharmony_ci
1153e66f31c5Sopenharmony_ciint uv_os_get_passwd(uv_passwd_t* pwd) {
1154e66f31c5Sopenharmony_ci  return uv__getpwuid_r(pwd);
1155e66f31c5Sopenharmony_ci}
1156e66f31c5Sopenharmony_ci
1157e66f31c5Sopenharmony_ci
1158e66f31c5Sopenharmony_ciint uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid) {
1159e66f31c5Sopenharmony_ci  return UV_ENOTSUP;
1160e66f31c5Sopenharmony_ci}
1161e66f31c5Sopenharmony_ci
1162e66f31c5Sopenharmony_ci
1163e66f31c5Sopenharmony_ciint uv_os_get_group(uv_group_t* grp, uv_uid_t gid) {
1164e66f31c5Sopenharmony_ci  return UV_ENOTSUP;
1165e66f31c5Sopenharmony_ci}
1166e66f31c5Sopenharmony_ci
1167e66f31c5Sopenharmony_ci
1168e66f31c5Sopenharmony_ciint uv_os_environ(uv_env_item_t** envitems, int* count) {
1169e66f31c5Sopenharmony_ci  wchar_t* env;
1170e66f31c5Sopenharmony_ci  wchar_t* penv;
1171e66f31c5Sopenharmony_ci  int i, cnt;
1172e66f31c5Sopenharmony_ci  uv_env_item_t* envitem;
1173e66f31c5Sopenharmony_ci
1174e66f31c5Sopenharmony_ci  *envitems = NULL;
1175e66f31c5Sopenharmony_ci  *count = 0;
1176e66f31c5Sopenharmony_ci
1177e66f31c5Sopenharmony_ci  env = GetEnvironmentStringsW();
1178e66f31c5Sopenharmony_ci  if (env == NULL)
1179e66f31c5Sopenharmony_ci    return 0;
1180e66f31c5Sopenharmony_ci
1181e66f31c5Sopenharmony_ci  for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++);
1182e66f31c5Sopenharmony_ci
1183e66f31c5Sopenharmony_ci  *envitems = uv__calloc(i, sizeof(**envitems));
1184e66f31c5Sopenharmony_ci  if (*envitems == NULL) {
1185e66f31c5Sopenharmony_ci    FreeEnvironmentStringsW(env);
1186e66f31c5Sopenharmony_ci    return UV_ENOMEM;
1187e66f31c5Sopenharmony_ci  }
1188e66f31c5Sopenharmony_ci
1189e66f31c5Sopenharmony_ci  penv = env;
1190e66f31c5Sopenharmony_ci  cnt = 0;
1191e66f31c5Sopenharmony_ci
1192e66f31c5Sopenharmony_ci  while (*penv != L'\0' && cnt < i) {
1193e66f31c5Sopenharmony_ci    char* buf;
1194e66f31c5Sopenharmony_ci    char* ptr;
1195e66f31c5Sopenharmony_ci
1196e66f31c5Sopenharmony_ci    if (uv__convert_utf16_to_utf8(penv, -1, &buf) != 0)
1197e66f31c5Sopenharmony_ci      goto fail;
1198e66f31c5Sopenharmony_ci
1199e66f31c5Sopenharmony_ci    /* Using buf + 1 here because we know that `buf` has length at least 1,
1200e66f31c5Sopenharmony_ci     * and some special environment variables on Windows start with a = sign. */
1201e66f31c5Sopenharmony_ci    ptr = strchr(buf + 1, '=');
1202e66f31c5Sopenharmony_ci    if (ptr == NULL) {
1203e66f31c5Sopenharmony_ci      uv__free(buf);
1204e66f31c5Sopenharmony_ci      goto do_continue;
1205e66f31c5Sopenharmony_ci    }
1206e66f31c5Sopenharmony_ci
1207e66f31c5Sopenharmony_ci    *ptr = '\0';
1208e66f31c5Sopenharmony_ci
1209e66f31c5Sopenharmony_ci    envitem = &(*envitems)[cnt];
1210e66f31c5Sopenharmony_ci    envitem->name = buf;
1211e66f31c5Sopenharmony_ci    envitem->value = ptr + 1;
1212e66f31c5Sopenharmony_ci
1213e66f31c5Sopenharmony_ci    cnt++;
1214e66f31c5Sopenharmony_ci
1215e66f31c5Sopenharmony_ci  do_continue:
1216e66f31c5Sopenharmony_ci    penv += wcslen(penv) + 1;
1217e66f31c5Sopenharmony_ci  }
1218e66f31c5Sopenharmony_ci
1219e66f31c5Sopenharmony_ci  FreeEnvironmentStringsW(env);
1220e66f31c5Sopenharmony_ci
1221e66f31c5Sopenharmony_ci  *count = cnt;
1222e66f31c5Sopenharmony_ci  return 0;
1223e66f31c5Sopenharmony_ci
1224e66f31c5Sopenharmony_cifail:
1225e66f31c5Sopenharmony_ci  FreeEnvironmentStringsW(env);
1226e66f31c5Sopenharmony_ci
1227e66f31c5Sopenharmony_ci  for (i = 0; i < cnt; i++) {
1228e66f31c5Sopenharmony_ci    envitem = &(*envitems)[cnt];
1229e66f31c5Sopenharmony_ci    uv__free(envitem->name);
1230e66f31c5Sopenharmony_ci  }
1231e66f31c5Sopenharmony_ci  uv__free(*envitems);
1232e66f31c5Sopenharmony_ci
1233e66f31c5Sopenharmony_ci  *envitems = NULL;
1234e66f31c5Sopenharmony_ci  *count = 0;
1235e66f31c5Sopenharmony_ci  return UV_ENOMEM;
1236e66f31c5Sopenharmony_ci}
1237e66f31c5Sopenharmony_ci
1238e66f31c5Sopenharmony_ci
1239e66f31c5Sopenharmony_ciint uv_os_getenv(const char* name, char* buffer, size_t* size) {
1240e66f31c5Sopenharmony_ci  wchar_t fastvar[512];
1241e66f31c5Sopenharmony_ci  wchar_t* var;
1242e66f31c5Sopenharmony_ci  DWORD varlen;
1243e66f31c5Sopenharmony_ci  wchar_t* name_w;
1244e66f31c5Sopenharmony_ci  size_t len;
1245e66f31c5Sopenharmony_ci  int r;
1246e66f31c5Sopenharmony_ci
1247e66f31c5Sopenharmony_ci  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
1248e66f31c5Sopenharmony_ci    return UV_EINVAL;
1249e66f31c5Sopenharmony_ci
1250e66f31c5Sopenharmony_ci  r = uv__convert_utf8_to_utf16(name, &name_w);
1251e66f31c5Sopenharmony_ci
1252e66f31c5Sopenharmony_ci  if (r != 0)
1253e66f31c5Sopenharmony_ci    return r;
1254e66f31c5Sopenharmony_ci
1255e66f31c5Sopenharmony_ci  var = fastvar;
1256e66f31c5Sopenharmony_ci  varlen = ARRAY_SIZE(fastvar);
1257e66f31c5Sopenharmony_ci
1258e66f31c5Sopenharmony_ci  for (;;) {
1259e66f31c5Sopenharmony_ci    SetLastError(ERROR_SUCCESS);
1260e66f31c5Sopenharmony_ci    len = GetEnvironmentVariableW(name_w, var, varlen);
1261e66f31c5Sopenharmony_ci
1262e66f31c5Sopenharmony_ci    if (len < varlen)
1263e66f31c5Sopenharmony_ci      break;
1264e66f31c5Sopenharmony_ci
1265e66f31c5Sopenharmony_ci    /* Try repeatedly because we might have been preempted by another thread
1266e66f31c5Sopenharmony_ci     * modifying the environment variable just as we're trying to read it.
1267e66f31c5Sopenharmony_ci     */
1268e66f31c5Sopenharmony_ci    if (var != fastvar)
1269e66f31c5Sopenharmony_ci      uv__free(var);
1270e66f31c5Sopenharmony_ci
1271e66f31c5Sopenharmony_ci    varlen = 1 + len;
1272e66f31c5Sopenharmony_ci    var = uv__malloc(varlen * sizeof(*var));
1273e66f31c5Sopenharmony_ci
1274e66f31c5Sopenharmony_ci    if (var == NULL) {
1275e66f31c5Sopenharmony_ci      r = UV_ENOMEM;
1276e66f31c5Sopenharmony_ci      goto fail;
1277e66f31c5Sopenharmony_ci    }
1278e66f31c5Sopenharmony_ci  }
1279e66f31c5Sopenharmony_ci
1280e66f31c5Sopenharmony_ci  uv__free(name_w);
1281e66f31c5Sopenharmony_ci  name_w = NULL;
1282e66f31c5Sopenharmony_ci
1283e66f31c5Sopenharmony_ci  if (len == 0) {
1284e66f31c5Sopenharmony_ci    r = GetLastError();
1285e66f31c5Sopenharmony_ci    if (r != ERROR_SUCCESS) {
1286e66f31c5Sopenharmony_ci      r = uv_translate_sys_error(r);
1287e66f31c5Sopenharmony_ci      goto fail;
1288e66f31c5Sopenharmony_ci    }
1289e66f31c5Sopenharmony_ci  }
1290e66f31c5Sopenharmony_ci
1291e66f31c5Sopenharmony_ci  r = uv__copy_utf16_to_utf8(var, len, buffer, size);
1292e66f31c5Sopenharmony_ci
1293e66f31c5Sopenharmony_cifail:
1294e66f31c5Sopenharmony_ci
1295e66f31c5Sopenharmony_ci  if (name_w != NULL)
1296e66f31c5Sopenharmony_ci    uv__free(name_w);
1297e66f31c5Sopenharmony_ci
1298e66f31c5Sopenharmony_ci  if (var != fastvar)
1299e66f31c5Sopenharmony_ci    uv__free(var);
1300e66f31c5Sopenharmony_ci
1301e66f31c5Sopenharmony_ci  return r;
1302e66f31c5Sopenharmony_ci}
1303e66f31c5Sopenharmony_ci
1304e66f31c5Sopenharmony_ci
1305e66f31c5Sopenharmony_ciint uv_os_setenv(const char* name, const char* value) {
1306e66f31c5Sopenharmony_ci  wchar_t* name_w;
1307e66f31c5Sopenharmony_ci  wchar_t* value_w;
1308e66f31c5Sopenharmony_ci  int r;
1309e66f31c5Sopenharmony_ci
1310e66f31c5Sopenharmony_ci  if (name == NULL || value == NULL)
1311e66f31c5Sopenharmony_ci    return UV_EINVAL;
1312e66f31c5Sopenharmony_ci
1313e66f31c5Sopenharmony_ci  r = uv__convert_utf8_to_utf16(name, &name_w);
1314e66f31c5Sopenharmony_ci
1315e66f31c5Sopenharmony_ci  if (r != 0)
1316e66f31c5Sopenharmony_ci    return r;
1317e66f31c5Sopenharmony_ci
1318e66f31c5Sopenharmony_ci  r = uv__convert_utf8_to_utf16(value, &value_w);
1319e66f31c5Sopenharmony_ci
1320e66f31c5Sopenharmony_ci  if (r != 0) {
1321e66f31c5Sopenharmony_ci    uv__free(name_w);
1322e66f31c5Sopenharmony_ci    return r;
1323e66f31c5Sopenharmony_ci  }
1324e66f31c5Sopenharmony_ci
1325e66f31c5Sopenharmony_ci  r = SetEnvironmentVariableW(name_w, value_w);
1326e66f31c5Sopenharmony_ci  uv__free(name_w);
1327e66f31c5Sopenharmony_ci  uv__free(value_w);
1328e66f31c5Sopenharmony_ci
1329e66f31c5Sopenharmony_ci  if (r == 0)
1330e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
1331e66f31c5Sopenharmony_ci
1332e66f31c5Sopenharmony_ci  return 0;
1333e66f31c5Sopenharmony_ci}
1334e66f31c5Sopenharmony_ci
1335e66f31c5Sopenharmony_ci
1336e66f31c5Sopenharmony_ciint uv_os_unsetenv(const char* name) {
1337e66f31c5Sopenharmony_ci  wchar_t* name_w;
1338e66f31c5Sopenharmony_ci  int r;
1339e66f31c5Sopenharmony_ci
1340e66f31c5Sopenharmony_ci  if (name == NULL)
1341e66f31c5Sopenharmony_ci    return UV_EINVAL;
1342e66f31c5Sopenharmony_ci
1343e66f31c5Sopenharmony_ci  r = uv__convert_utf8_to_utf16(name, &name_w);
1344e66f31c5Sopenharmony_ci
1345e66f31c5Sopenharmony_ci  if (r != 0)
1346e66f31c5Sopenharmony_ci    return r;
1347e66f31c5Sopenharmony_ci
1348e66f31c5Sopenharmony_ci  r = SetEnvironmentVariableW(name_w, NULL);
1349e66f31c5Sopenharmony_ci  uv__free(name_w);
1350e66f31c5Sopenharmony_ci
1351e66f31c5Sopenharmony_ci  if (r == 0)
1352e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
1353e66f31c5Sopenharmony_ci
1354e66f31c5Sopenharmony_ci  return 0;
1355e66f31c5Sopenharmony_ci}
1356e66f31c5Sopenharmony_ci
1357e66f31c5Sopenharmony_ci
1358e66f31c5Sopenharmony_ciint uv_os_gethostname(char* buffer, size_t* size) {
1359e66f31c5Sopenharmony_ci  WCHAR buf[UV_MAXHOSTNAMESIZE];
1360e66f31c5Sopenharmony_ci
1361e66f31c5Sopenharmony_ci  if (buffer == NULL || size == NULL || *size == 0)
1362e66f31c5Sopenharmony_ci    return UV_EINVAL;
1363e66f31c5Sopenharmony_ci
1364e66f31c5Sopenharmony_ci  uv__once_init(); /* Initialize winsock */
1365e66f31c5Sopenharmony_ci
1366e66f31c5Sopenharmony_ci  if (pGetHostNameW == NULL)
1367e66f31c5Sopenharmony_ci    return UV_ENOSYS;
1368e66f31c5Sopenharmony_ci
1369e66f31c5Sopenharmony_ci  if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
1370e66f31c5Sopenharmony_ci    return uv_translate_sys_error(WSAGetLastError());
1371e66f31c5Sopenharmony_ci
1372e66f31c5Sopenharmony_ci  return uv__copy_utf16_to_utf8(buf, -1, buffer, size);
1373e66f31c5Sopenharmony_ci}
1374e66f31c5Sopenharmony_ci
1375e66f31c5Sopenharmony_ci
1376e66f31c5Sopenharmony_cistatic int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
1377e66f31c5Sopenharmony_ci  int r;
1378e66f31c5Sopenharmony_ci
1379e66f31c5Sopenharmony_ci  if (pid == 0)
1380e66f31c5Sopenharmony_ci    *handle = GetCurrentProcess();
1381e66f31c5Sopenharmony_ci  else
1382e66f31c5Sopenharmony_ci    *handle = OpenProcess(access, FALSE, pid);
1383e66f31c5Sopenharmony_ci
1384e66f31c5Sopenharmony_ci  if (*handle == NULL) {
1385e66f31c5Sopenharmony_ci    r = GetLastError();
1386e66f31c5Sopenharmony_ci
1387e66f31c5Sopenharmony_ci    if (r == ERROR_INVALID_PARAMETER)
1388e66f31c5Sopenharmony_ci      return UV_ESRCH;
1389e66f31c5Sopenharmony_ci    else
1390e66f31c5Sopenharmony_ci      return uv_translate_sys_error(r);
1391e66f31c5Sopenharmony_ci  }
1392e66f31c5Sopenharmony_ci
1393e66f31c5Sopenharmony_ci  return 0;
1394e66f31c5Sopenharmony_ci}
1395e66f31c5Sopenharmony_ci
1396e66f31c5Sopenharmony_ci
1397e66f31c5Sopenharmony_ciint uv_os_getpriority(uv_pid_t pid, int* priority) {
1398e66f31c5Sopenharmony_ci  HANDLE handle;
1399e66f31c5Sopenharmony_ci  int r;
1400e66f31c5Sopenharmony_ci
1401e66f31c5Sopenharmony_ci  if (priority == NULL)
1402e66f31c5Sopenharmony_ci    return UV_EINVAL;
1403e66f31c5Sopenharmony_ci
1404e66f31c5Sopenharmony_ci  r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
1405e66f31c5Sopenharmony_ci
1406e66f31c5Sopenharmony_ci  if (r != 0)
1407e66f31c5Sopenharmony_ci    return r;
1408e66f31c5Sopenharmony_ci
1409e66f31c5Sopenharmony_ci  r = GetPriorityClass(handle);
1410e66f31c5Sopenharmony_ci
1411e66f31c5Sopenharmony_ci  if (r == 0) {
1412e66f31c5Sopenharmony_ci    r = uv_translate_sys_error(GetLastError());
1413e66f31c5Sopenharmony_ci  } else {
1414e66f31c5Sopenharmony_ci    /* Map Windows priority classes to Unix nice values. */
1415e66f31c5Sopenharmony_ci    if (r == REALTIME_PRIORITY_CLASS)
1416e66f31c5Sopenharmony_ci      *priority = UV_PRIORITY_HIGHEST;
1417e66f31c5Sopenharmony_ci    else if (r == HIGH_PRIORITY_CLASS)
1418e66f31c5Sopenharmony_ci      *priority = UV_PRIORITY_HIGH;
1419e66f31c5Sopenharmony_ci    else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
1420e66f31c5Sopenharmony_ci      *priority = UV_PRIORITY_ABOVE_NORMAL;
1421e66f31c5Sopenharmony_ci    else if (r == NORMAL_PRIORITY_CLASS)
1422e66f31c5Sopenharmony_ci      *priority = UV_PRIORITY_NORMAL;
1423e66f31c5Sopenharmony_ci    else if (r == BELOW_NORMAL_PRIORITY_CLASS)
1424e66f31c5Sopenharmony_ci      *priority = UV_PRIORITY_BELOW_NORMAL;
1425e66f31c5Sopenharmony_ci    else  /* IDLE_PRIORITY_CLASS */
1426e66f31c5Sopenharmony_ci      *priority = UV_PRIORITY_LOW;
1427e66f31c5Sopenharmony_ci
1428e66f31c5Sopenharmony_ci    r = 0;
1429e66f31c5Sopenharmony_ci  }
1430e66f31c5Sopenharmony_ci
1431e66f31c5Sopenharmony_ci  CloseHandle(handle);
1432e66f31c5Sopenharmony_ci  return r;
1433e66f31c5Sopenharmony_ci}
1434e66f31c5Sopenharmony_ci
1435e66f31c5Sopenharmony_ci
1436e66f31c5Sopenharmony_ciint uv_os_setpriority(uv_pid_t pid, int priority) {
1437e66f31c5Sopenharmony_ci  HANDLE handle;
1438e66f31c5Sopenharmony_ci  int priority_class;
1439e66f31c5Sopenharmony_ci  int r;
1440e66f31c5Sopenharmony_ci
1441e66f31c5Sopenharmony_ci  /* Map Unix nice values to Windows priority classes. */
1442e66f31c5Sopenharmony_ci  if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
1443e66f31c5Sopenharmony_ci    return UV_EINVAL;
1444e66f31c5Sopenharmony_ci  else if (priority < UV_PRIORITY_HIGH)
1445e66f31c5Sopenharmony_ci    priority_class = REALTIME_PRIORITY_CLASS;
1446e66f31c5Sopenharmony_ci  else if (priority < UV_PRIORITY_ABOVE_NORMAL)
1447e66f31c5Sopenharmony_ci    priority_class = HIGH_PRIORITY_CLASS;
1448e66f31c5Sopenharmony_ci  else if (priority < UV_PRIORITY_NORMAL)
1449e66f31c5Sopenharmony_ci    priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
1450e66f31c5Sopenharmony_ci  else if (priority < UV_PRIORITY_BELOW_NORMAL)
1451e66f31c5Sopenharmony_ci    priority_class = NORMAL_PRIORITY_CLASS;
1452e66f31c5Sopenharmony_ci  else if (priority < UV_PRIORITY_LOW)
1453e66f31c5Sopenharmony_ci    priority_class = BELOW_NORMAL_PRIORITY_CLASS;
1454e66f31c5Sopenharmony_ci  else
1455e66f31c5Sopenharmony_ci    priority_class = IDLE_PRIORITY_CLASS;
1456e66f31c5Sopenharmony_ci
1457e66f31c5Sopenharmony_ci  r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
1458e66f31c5Sopenharmony_ci
1459e66f31c5Sopenharmony_ci  if (r != 0)
1460e66f31c5Sopenharmony_ci    return r;
1461e66f31c5Sopenharmony_ci
1462e66f31c5Sopenharmony_ci  if (SetPriorityClass(handle, priority_class) == 0)
1463e66f31c5Sopenharmony_ci    r = uv_translate_sys_error(GetLastError());
1464e66f31c5Sopenharmony_ci
1465e66f31c5Sopenharmony_ci  CloseHandle(handle);
1466e66f31c5Sopenharmony_ci  return r;
1467e66f31c5Sopenharmony_ci}
1468e66f31c5Sopenharmony_ci
1469e66f31c5Sopenharmony_ciint uv_thread_getpriority(uv_thread_t tid, int* priority) {
1470e66f31c5Sopenharmony_ci  int r;
1471e66f31c5Sopenharmony_ci
1472e66f31c5Sopenharmony_ci  if (priority == NULL)
1473e66f31c5Sopenharmony_ci    return UV_EINVAL;
1474e66f31c5Sopenharmony_ci
1475e66f31c5Sopenharmony_ci  r = GetThreadPriority(tid);
1476e66f31c5Sopenharmony_ci  if (r == THREAD_PRIORITY_ERROR_RETURN)
1477e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
1478e66f31c5Sopenharmony_ci
1479e66f31c5Sopenharmony_ci  *priority = r;
1480e66f31c5Sopenharmony_ci  return 0;
1481e66f31c5Sopenharmony_ci}
1482e66f31c5Sopenharmony_ci
1483e66f31c5Sopenharmony_ciint uv_thread_setpriority(uv_thread_t tid, int priority) {
1484e66f31c5Sopenharmony_ci  int r;
1485e66f31c5Sopenharmony_ci
1486e66f31c5Sopenharmony_ci  switch (priority) {
1487e66f31c5Sopenharmony_ci    case UV_THREAD_PRIORITY_HIGHEST:
1488e66f31c5Sopenharmony_ci      r = SetThreadPriority(tid, THREAD_PRIORITY_HIGHEST);
1489e66f31c5Sopenharmony_ci      break;
1490e66f31c5Sopenharmony_ci    case UV_THREAD_PRIORITY_ABOVE_NORMAL:
1491e66f31c5Sopenharmony_ci      r = SetThreadPriority(tid, THREAD_PRIORITY_ABOVE_NORMAL);
1492e66f31c5Sopenharmony_ci      break;
1493e66f31c5Sopenharmony_ci    case UV_THREAD_PRIORITY_NORMAL:
1494e66f31c5Sopenharmony_ci      r = SetThreadPriority(tid, THREAD_PRIORITY_NORMAL);
1495e66f31c5Sopenharmony_ci      break;
1496e66f31c5Sopenharmony_ci    case UV_THREAD_PRIORITY_BELOW_NORMAL:
1497e66f31c5Sopenharmony_ci      r = SetThreadPriority(tid, THREAD_PRIORITY_BELOW_NORMAL);
1498e66f31c5Sopenharmony_ci      break;
1499e66f31c5Sopenharmony_ci    case UV_THREAD_PRIORITY_LOWEST:
1500e66f31c5Sopenharmony_ci      r = SetThreadPriority(tid, THREAD_PRIORITY_LOWEST);
1501e66f31c5Sopenharmony_ci      break;
1502e66f31c5Sopenharmony_ci    default:
1503e66f31c5Sopenharmony_ci      return 0;
1504e66f31c5Sopenharmony_ci  }
1505e66f31c5Sopenharmony_ci
1506e66f31c5Sopenharmony_ci  if (r == 0)
1507e66f31c5Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
1508e66f31c5Sopenharmony_ci
1509e66f31c5Sopenharmony_ci  return 0;
1510e66f31c5Sopenharmony_ci}
1511e66f31c5Sopenharmony_ci
1512e66f31c5Sopenharmony_ciint uv_os_uname(uv_utsname_t* buffer) {
1513e66f31c5Sopenharmony_ci  /* Implementation loosely based on
1514e66f31c5Sopenharmony_ci     https://github.com/gagern/gnulib/blob/master/lib/uname.c */
1515e66f31c5Sopenharmony_ci  OSVERSIONINFOW os_info;
1516e66f31c5Sopenharmony_ci  SYSTEM_INFO system_info;
1517e66f31c5Sopenharmony_ci  HKEY registry_key;
1518e66f31c5Sopenharmony_ci  WCHAR product_name_w[256];
1519e66f31c5Sopenharmony_ci  DWORD product_name_w_size;
1520e66f31c5Sopenharmony_ci  size_t version_size;
1521e66f31c5Sopenharmony_ci  int processor_level;
1522e66f31c5Sopenharmony_ci  int r;
1523e66f31c5Sopenharmony_ci
1524e66f31c5Sopenharmony_ci  if (buffer == NULL)
1525e66f31c5Sopenharmony_ci    return UV_EINVAL;
1526e66f31c5Sopenharmony_ci
1527e66f31c5Sopenharmony_ci  uv__once_init();
1528e66f31c5Sopenharmony_ci  os_info.dwOSVersionInfoSize = sizeof(os_info);
1529e66f31c5Sopenharmony_ci  os_info.szCSDVersion[0] = L'\0';
1530e66f31c5Sopenharmony_ci
1531e66f31c5Sopenharmony_ci  /* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()
1532e66f31c5Sopenharmony_ci     if RtlGetVersion() is not available. */
1533e66f31c5Sopenharmony_ci  if (pRtlGetVersion) {
1534e66f31c5Sopenharmony_ci    pRtlGetVersion(&os_info);
1535e66f31c5Sopenharmony_ci  } else {
1536e66f31c5Sopenharmony_ci    /* Silence GetVersionEx() deprecation warning. */
1537e66f31c5Sopenharmony_ci    #ifdef _MSC_VER
1538e66f31c5Sopenharmony_ci    #pragma warning(suppress : 4996)
1539e66f31c5Sopenharmony_ci    #endif
1540e66f31c5Sopenharmony_ci    if (GetVersionExW(&os_info) == 0) {
1541e66f31c5Sopenharmony_ci      r = uv_translate_sys_error(GetLastError());
1542e66f31c5Sopenharmony_ci      goto error;
1543e66f31c5Sopenharmony_ci    }
1544e66f31c5Sopenharmony_ci  }
1545e66f31c5Sopenharmony_ci
1546e66f31c5Sopenharmony_ci  /* Populate the version field. */
1547e66f31c5Sopenharmony_ci  version_size = 0;
1548e66f31c5Sopenharmony_ci  r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1549e66f31c5Sopenharmony_ci                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
1550e66f31c5Sopenharmony_ci                    0,
1551e66f31c5Sopenharmony_ci                    KEY_QUERY_VALUE | KEY_WOW64_64KEY,
1552e66f31c5Sopenharmony_ci                    &registry_key);
1553e66f31c5Sopenharmony_ci
1554e66f31c5Sopenharmony_ci  if (r == ERROR_SUCCESS) {
1555e66f31c5Sopenharmony_ci    product_name_w_size = sizeof(product_name_w);
1556e66f31c5Sopenharmony_ci    r = RegGetValueW(registry_key,
1557e66f31c5Sopenharmony_ci                     NULL,
1558e66f31c5Sopenharmony_ci                     L"ProductName",
1559e66f31c5Sopenharmony_ci                     RRF_RT_REG_SZ,
1560e66f31c5Sopenharmony_ci                     NULL,
1561e66f31c5Sopenharmony_ci                     (PVOID) product_name_w,
1562e66f31c5Sopenharmony_ci                     &product_name_w_size);
1563e66f31c5Sopenharmony_ci    RegCloseKey(registry_key);
1564e66f31c5Sopenharmony_ci
1565e66f31c5Sopenharmony_ci    if (r == ERROR_SUCCESS) {
1566e66f31c5Sopenharmony_ci      /* Windows 11 shares dwMajorVersion with Windows 10
1567e66f31c5Sopenharmony_ci       * this workaround tries to disambiguate that by checking
1568e66f31c5Sopenharmony_ci       * if the dwBuildNumber is from Windows 11 releases (>= 22000).
1569e66f31c5Sopenharmony_ci       *
1570e66f31c5Sopenharmony_ci       * This workaround replaces the ProductName key value
1571e66f31c5Sopenharmony_ci       * from "Windows 10 *" to "Windows 11 *" */
1572e66f31c5Sopenharmony_ci      if (os_info.dwMajorVersion == 10 &&
1573e66f31c5Sopenharmony_ci          os_info.dwBuildNumber >= 22000 &&
1574e66f31c5Sopenharmony_ci          product_name_w_size >= ARRAY_SIZE(L"Windows 10")) {
1575e66f31c5Sopenharmony_ci        /* If ProductName starts with "Windows 10" */
1576e66f31c5Sopenharmony_ci        if (wcsncmp(product_name_w, L"Windows 10", ARRAY_SIZE(L"Windows 10") - 1) == 0) {
1577e66f31c5Sopenharmony_ci          /* Bump 10 to 11 */
1578e66f31c5Sopenharmony_ci          product_name_w[9] = '1';
1579e66f31c5Sopenharmony_ci        }
1580e66f31c5Sopenharmony_ci      }
1581e66f31c5Sopenharmony_ci
1582e66f31c5Sopenharmony_ci      version_size = sizeof(buffer->version);
1583e66f31c5Sopenharmony_ci      r = uv__copy_utf16_to_utf8(product_name_w,
1584e66f31c5Sopenharmony_ci                                 -1,
1585e66f31c5Sopenharmony_ci                                 buffer->version,
1586e66f31c5Sopenharmony_ci                                 &version_size);
1587e66f31c5Sopenharmony_ci      if (r)
1588e66f31c5Sopenharmony_ci        goto error;
1589e66f31c5Sopenharmony_ci    }
1590e66f31c5Sopenharmony_ci  }
1591e66f31c5Sopenharmony_ci
1592e66f31c5Sopenharmony_ci  /* Append service pack information to the version if present. */
1593e66f31c5Sopenharmony_ci  if (os_info.szCSDVersion[0] != L'\0') {
1594e66f31c5Sopenharmony_ci    if (version_size > 0)
1595e66f31c5Sopenharmony_ci      buffer->version[version_size++] = ' ';
1596e66f31c5Sopenharmony_ci
1597e66f31c5Sopenharmony_ci    version_size = sizeof(buffer->version) - version_size;
1598e66f31c5Sopenharmony_ci    r = uv__copy_utf16_to_utf8(os_info.szCSDVersion,
1599e66f31c5Sopenharmony_ci                               -1,
1600e66f31c5Sopenharmony_ci                               buffer->version +
1601e66f31c5Sopenharmony_ci                                 sizeof(buffer->version) - version_size,
1602e66f31c5Sopenharmony_ci                               &version_size);
1603e66f31c5Sopenharmony_ci    if (r)
1604e66f31c5Sopenharmony_ci      goto error;
1605e66f31c5Sopenharmony_ci  }
1606e66f31c5Sopenharmony_ci
1607e66f31c5Sopenharmony_ci  /* Populate the sysname field. */
1608e66f31c5Sopenharmony_ci#ifdef __MINGW32__
1609e66f31c5Sopenharmony_ci  r = snprintf(buffer->sysname,
1610e66f31c5Sopenharmony_ci               sizeof(buffer->sysname),
1611e66f31c5Sopenharmony_ci               "MINGW32_NT-%u.%u",
1612e66f31c5Sopenharmony_ci               (unsigned int) os_info.dwMajorVersion,
1613e66f31c5Sopenharmony_ci               (unsigned int) os_info.dwMinorVersion);
1614e66f31c5Sopenharmony_ci  assert((size_t)r < sizeof(buffer->sysname));
1615e66f31c5Sopenharmony_ci#else
1616e66f31c5Sopenharmony_ci  uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
1617e66f31c5Sopenharmony_ci#endif
1618e66f31c5Sopenharmony_ci
1619e66f31c5Sopenharmony_ci  /* Populate the release field. */
1620e66f31c5Sopenharmony_ci  r = snprintf(buffer->release,
1621e66f31c5Sopenharmony_ci               sizeof(buffer->release),
1622e66f31c5Sopenharmony_ci               "%d.%d.%d",
1623e66f31c5Sopenharmony_ci               (unsigned int) os_info.dwMajorVersion,
1624e66f31c5Sopenharmony_ci               (unsigned int) os_info.dwMinorVersion,
1625e66f31c5Sopenharmony_ci               (unsigned int) os_info.dwBuildNumber);
1626e66f31c5Sopenharmony_ci  assert((size_t)r < sizeof(buffer->release));
1627e66f31c5Sopenharmony_ci
1628e66f31c5Sopenharmony_ci  /* Populate the machine field. */
1629e66f31c5Sopenharmony_ci  GetSystemInfo(&system_info);
1630e66f31c5Sopenharmony_ci
1631e66f31c5Sopenharmony_ci  switch (system_info.wProcessorArchitecture) {
1632e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_AMD64:
1633e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));
1634e66f31c5Sopenharmony_ci      break;
1635e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_IA64:
1636e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));
1637e66f31c5Sopenharmony_ci      break;
1638e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_INTEL:
1639e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));
1640e66f31c5Sopenharmony_ci
1641e66f31c5Sopenharmony_ci      if (system_info.wProcessorLevel > 3) {
1642e66f31c5Sopenharmony_ci        processor_level = system_info.wProcessorLevel < 6 ?
1643e66f31c5Sopenharmony_ci                          system_info.wProcessorLevel : 6;
1644e66f31c5Sopenharmony_ci        buffer->machine[1] = '0' + processor_level;
1645e66f31c5Sopenharmony_ci      }
1646e66f31c5Sopenharmony_ci
1647e66f31c5Sopenharmony_ci      break;
1648e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
1649e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));
1650e66f31c5Sopenharmony_ci      break;
1651e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_MIPS:
1652e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));
1653e66f31c5Sopenharmony_ci      break;
1654e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_ALPHA:
1655e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_ALPHA64:
1656e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));
1657e66f31c5Sopenharmony_ci      break;
1658e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_PPC:
1659e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));
1660e66f31c5Sopenharmony_ci      break;
1661e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_SHX:
1662e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));
1663e66f31c5Sopenharmony_ci      break;
1664e66f31c5Sopenharmony_ci    case PROCESSOR_ARCHITECTURE_ARM:
1665e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));
1666e66f31c5Sopenharmony_ci      break;
1667e66f31c5Sopenharmony_ci    default:
1668e66f31c5Sopenharmony_ci      uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));
1669e66f31c5Sopenharmony_ci      break;
1670e66f31c5Sopenharmony_ci  }
1671e66f31c5Sopenharmony_ci
1672e66f31c5Sopenharmony_ci  return 0;
1673e66f31c5Sopenharmony_ci
1674e66f31c5Sopenharmony_cierror:
1675e66f31c5Sopenharmony_ci  buffer->sysname[0] = '\0';
1676e66f31c5Sopenharmony_ci  buffer->release[0] = '\0';
1677e66f31c5Sopenharmony_ci  buffer->version[0] = '\0';
1678e66f31c5Sopenharmony_ci  buffer->machine[0] = '\0';
1679e66f31c5Sopenharmony_ci  return r;
1680e66f31c5Sopenharmony_ci}
1681e66f31c5Sopenharmony_ci
1682e66f31c5Sopenharmony_ciint uv_gettimeofday(uv_timeval64_t* tv) {
1683e66f31c5Sopenharmony_ci  /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */
1684e66f31c5Sopenharmony_ci  const uint64_t epoch = (uint64_t) 116444736000000000ULL;
1685e66f31c5Sopenharmony_ci  FILETIME file_time;
1686e66f31c5Sopenharmony_ci  ULARGE_INTEGER ularge;
1687e66f31c5Sopenharmony_ci
1688e66f31c5Sopenharmony_ci  if (tv == NULL)
1689e66f31c5Sopenharmony_ci    return UV_EINVAL;
1690e66f31c5Sopenharmony_ci
1691e66f31c5Sopenharmony_ci  GetSystemTimeAsFileTime(&file_time);
1692e66f31c5Sopenharmony_ci  ularge.LowPart = file_time.dwLowDateTime;
1693e66f31c5Sopenharmony_ci  ularge.HighPart = file_time.dwHighDateTime;
1694e66f31c5Sopenharmony_ci  tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L);
1695e66f31c5Sopenharmony_ci  tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
1696e66f31c5Sopenharmony_ci  return 0;
1697e66f31c5Sopenharmony_ci}
1698e66f31c5Sopenharmony_ci
1699e66f31c5Sopenharmony_ciint uv__random_rtlgenrandom(void* buf, size_t buflen) {
1700e66f31c5Sopenharmony_ci  if (buflen == 0)
1701e66f31c5Sopenharmony_ci    return 0;
1702e66f31c5Sopenharmony_ci
1703e66f31c5Sopenharmony_ci  if (SystemFunction036(buf, buflen) == FALSE)
1704e66f31c5Sopenharmony_ci    return UV_EIO;
1705e66f31c5Sopenharmony_ci
1706e66f31c5Sopenharmony_ci  return 0;
1707e66f31c5Sopenharmony_ci}
1708e66f31c5Sopenharmony_ci
1709e66f31c5Sopenharmony_civoid uv_sleep(unsigned int msec) {
1710e66f31c5Sopenharmony_ci  Sleep(msec);
1711e66f31c5Sopenharmony_ci}
1712