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