11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include <assert.h>
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci#include "uv.h"
251cb0ef41Sopenharmony_ci#include "internal.h"
261cb0ef41Sopenharmony_ci#include "req-inl.h"
271cb0ef41Sopenharmony_ci#include "idna.h"
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci/* EAI_* constants. */
301cb0ef41Sopenharmony_ci#include <winsock2.h>
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */
331cb0ef41Sopenharmony_ci#include <iphlpapi.h>
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciint uv__getaddrinfo_translate_error(int sys_err) {
361cb0ef41Sopenharmony_ci  switch (sys_err) {
371cb0ef41Sopenharmony_ci    case 0:                       return 0;
381cb0ef41Sopenharmony_ci    case WSATRY_AGAIN:            return UV_EAI_AGAIN;
391cb0ef41Sopenharmony_ci    case WSAEINVAL:               return UV_EAI_BADFLAGS;
401cb0ef41Sopenharmony_ci    case WSANO_RECOVERY:          return UV_EAI_FAIL;
411cb0ef41Sopenharmony_ci    case WSAEAFNOSUPPORT:         return UV_EAI_FAMILY;
421cb0ef41Sopenharmony_ci    case WSA_NOT_ENOUGH_MEMORY:   return UV_EAI_MEMORY;
431cb0ef41Sopenharmony_ci    case WSAHOST_NOT_FOUND:       return UV_EAI_NONAME;
441cb0ef41Sopenharmony_ci    case WSATYPE_NOT_FOUND:       return UV_EAI_SERVICE;
451cb0ef41Sopenharmony_ci    case WSAESOCKTNOSUPPORT:      return UV_EAI_SOCKTYPE;
461cb0ef41Sopenharmony_ci    default:                      return uv_translate_sys_error(sys_err);
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci/*
521cb0ef41Sopenharmony_ci * MinGW is missing this
531cb0ef41Sopenharmony_ci */
541cb0ef41Sopenharmony_ci#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)
551cb0ef41Sopenharmony_ci  typedef struct addrinfoW {
561cb0ef41Sopenharmony_ci    int ai_flags;
571cb0ef41Sopenharmony_ci    int ai_family;
581cb0ef41Sopenharmony_ci    int ai_socktype;
591cb0ef41Sopenharmony_ci    int ai_protocol;
601cb0ef41Sopenharmony_ci    size_t ai_addrlen;
611cb0ef41Sopenharmony_ci    WCHAR* ai_canonname;
621cb0ef41Sopenharmony_ci    struct sockaddr* ai_addr;
631cb0ef41Sopenharmony_ci    struct addrinfoW* ai_next;
641cb0ef41Sopenharmony_ci  } ADDRINFOW, *PADDRINFOW;
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node,
671cb0ef41Sopenharmony_ci                                          const WCHAR* service,
681cb0ef41Sopenharmony_ci                                          const ADDRINFOW* hints,
691cb0ef41Sopenharmony_ci                                          PADDRINFOW* result);
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo);
721cb0ef41Sopenharmony_ci#endif
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
761cb0ef41Sopenharmony_ci * Do we need different versions of this for different architectures? */
771cb0ef41Sopenharmony_ci#define ALIGNED_SIZE(X)     ((((X) + 3) >> 2) << 2)
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci#ifndef NDIS_IF_MAX_STRING_SIZE
801cb0ef41Sopenharmony_ci#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE
811cb0ef41Sopenharmony_ci#endif
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_cistatic void uv__getaddrinfo_work(struct uv__work* w) {
841cb0ef41Sopenharmony_ci  uv_getaddrinfo_t* req;
851cb0ef41Sopenharmony_ci  struct addrinfoW* hints;
861cb0ef41Sopenharmony_ci  int err;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  req = container_of(w, uv_getaddrinfo_t, work_req);
891cb0ef41Sopenharmony_ci  hints = req->addrinfow;
901cb0ef41Sopenharmony_ci  req->addrinfow = NULL;
911cb0ef41Sopenharmony_ci  err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
921cb0ef41Sopenharmony_ci  req->retcode = uv__getaddrinfo_translate_error(err);
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci/*
971cb0ef41Sopenharmony_ci * Called from uv_run when complete. Call user specified callback
981cb0ef41Sopenharmony_ci * then free returned addrinfo
991cb0ef41Sopenharmony_ci * Returned addrinfo strings are converted from UTF-16 to UTF-8.
1001cb0ef41Sopenharmony_ci *
1011cb0ef41Sopenharmony_ci * To minimize allocation we calculate total size required,
1021cb0ef41Sopenharmony_ci * and copy all structs and referenced strings into the one block.
1031cb0ef41Sopenharmony_ci * Each size calculation is adjusted to avoid unaligned pointers.
1041cb0ef41Sopenharmony_ci */
1051cb0ef41Sopenharmony_cistatic void uv__getaddrinfo_done(struct uv__work* w, int status) {
1061cb0ef41Sopenharmony_ci  uv_getaddrinfo_t* req;
1071cb0ef41Sopenharmony_ci  int addrinfo_len = 0;
1081cb0ef41Sopenharmony_ci  int name_len = 0;
1091cb0ef41Sopenharmony_ci  size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
1101cb0ef41Sopenharmony_ci  struct addrinfoW* addrinfow_ptr;
1111cb0ef41Sopenharmony_ci  struct addrinfo* addrinfo_ptr;
1121cb0ef41Sopenharmony_ci  char* alloc_ptr = NULL;
1131cb0ef41Sopenharmony_ci  char* cur_ptr = NULL;
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  req = container_of(w, uv_getaddrinfo_t, work_req);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  /* release input parameter memory */
1181cb0ef41Sopenharmony_ci  uv__free(req->alloc);
1191cb0ef41Sopenharmony_ci  req->alloc = NULL;
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  if (status == UV_ECANCELED) {
1221cb0ef41Sopenharmony_ci    assert(req->retcode == 0);
1231cb0ef41Sopenharmony_ci    req->retcode = UV_EAI_CANCELED;
1241cb0ef41Sopenharmony_ci    goto complete;
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  if (req->retcode == 0) {
1281cb0ef41Sopenharmony_ci    /* Convert addrinfoW to addrinfo. First calculate required length. */
1291cb0ef41Sopenharmony_ci    addrinfow_ptr = req->addrinfow;
1301cb0ef41Sopenharmony_ci    while (addrinfow_ptr != NULL) {
1311cb0ef41Sopenharmony_ci      addrinfo_len += addrinfo_struct_len +
1321cb0ef41Sopenharmony_ci          ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
1331cb0ef41Sopenharmony_ci      if (addrinfow_ptr->ai_canonname != NULL) {
1341cb0ef41Sopenharmony_ci        name_len = WideCharToMultiByte(CP_UTF8,
1351cb0ef41Sopenharmony_ci                                       0,
1361cb0ef41Sopenharmony_ci                                       addrinfow_ptr->ai_canonname,
1371cb0ef41Sopenharmony_ci                                       -1,
1381cb0ef41Sopenharmony_ci                                       NULL,
1391cb0ef41Sopenharmony_ci                                       0,
1401cb0ef41Sopenharmony_ci                                       NULL,
1411cb0ef41Sopenharmony_ci                                       NULL);
1421cb0ef41Sopenharmony_ci        if (name_len == 0) {
1431cb0ef41Sopenharmony_ci          req->retcode = uv_translate_sys_error(GetLastError());
1441cb0ef41Sopenharmony_ci          goto complete;
1451cb0ef41Sopenharmony_ci        }
1461cb0ef41Sopenharmony_ci        addrinfo_len += ALIGNED_SIZE(name_len);
1471cb0ef41Sopenharmony_ci      }
1481cb0ef41Sopenharmony_ci      addrinfow_ptr = addrinfow_ptr->ai_next;
1491cb0ef41Sopenharmony_ci    }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci    /* allocate memory for addrinfo results */
1521cb0ef41Sopenharmony_ci    alloc_ptr = (char*)uv__malloc(addrinfo_len);
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci    /* do conversions */
1551cb0ef41Sopenharmony_ci    if (alloc_ptr != NULL) {
1561cb0ef41Sopenharmony_ci      cur_ptr = alloc_ptr;
1571cb0ef41Sopenharmony_ci      addrinfow_ptr = req->addrinfow;
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci      while (addrinfow_ptr != NULL) {
1601cb0ef41Sopenharmony_ci        /* copy addrinfo struct data */
1611cb0ef41Sopenharmony_ci        assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);
1621cb0ef41Sopenharmony_ci        addrinfo_ptr = (struct addrinfo*)cur_ptr;
1631cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;
1641cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;
1651cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;
1661cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;
1671cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;
1681cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_canonname = NULL;
1691cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_addr = NULL;
1701cb0ef41Sopenharmony_ci        addrinfo_ptr->ai_next = NULL;
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci        cur_ptr += addrinfo_struct_len;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci        /* copy sockaddr */
1751cb0ef41Sopenharmony_ci        if (addrinfo_ptr->ai_addrlen > 0) {
1761cb0ef41Sopenharmony_ci          assert(cur_ptr + addrinfo_ptr->ai_addrlen <=
1771cb0ef41Sopenharmony_ci                 alloc_ptr + addrinfo_len);
1781cb0ef41Sopenharmony_ci          memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);
1791cb0ef41Sopenharmony_ci          addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;
1801cb0ef41Sopenharmony_ci          cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);
1811cb0ef41Sopenharmony_ci        }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci        /* convert canonical name to UTF-8 */
1841cb0ef41Sopenharmony_ci        if (addrinfow_ptr->ai_canonname != NULL) {
1851cb0ef41Sopenharmony_ci          name_len = WideCharToMultiByte(CP_UTF8,
1861cb0ef41Sopenharmony_ci                                         0,
1871cb0ef41Sopenharmony_ci                                         addrinfow_ptr->ai_canonname,
1881cb0ef41Sopenharmony_ci                                         -1,
1891cb0ef41Sopenharmony_ci                                         NULL,
1901cb0ef41Sopenharmony_ci                                         0,
1911cb0ef41Sopenharmony_ci                                         NULL,
1921cb0ef41Sopenharmony_ci                                         NULL);
1931cb0ef41Sopenharmony_ci          assert(name_len > 0);
1941cb0ef41Sopenharmony_ci          assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
1951cb0ef41Sopenharmony_ci          name_len = WideCharToMultiByte(CP_UTF8,
1961cb0ef41Sopenharmony_ci                                         0,
1971cb0ef41Sopenharmony_ci                                         addrinfow_ptr->ai_canonname,
1981cb0ef41Sopenharmony_ci                                         -1,
1991cb0ef41Sopenharmony_ci                                         cur_ptr,
2001cb0ef41Sopenharmony_ci                                         name_len,
2011cb0ef41Sopenharmony_ci                                         NULL,
2021cb0ef41Sopenharmony_ci                                         NULL);
2031cb0ef41Sopenharmony_ci          assert(name_len > 0);
2041cb0ef41Sopenharmony_ci          addrinfo_ptr->ai_canonname = cur_ptr;
2051cb0ef41Sopenharmony_ci          cur_ptr += ALIGNED_SIZE(name_len);
2061cb0ef41Sopenharmony_ci        }
2071cb0ef41Sopenharmony_ci        assert(cur_ptr <= alloc_ptr + addrinfo_len);
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci        /* set next ptr */
2101cb0ef41Sopenharmony_ci        addrinfow_ptr = addrinfow_ptr->ai_next;
2111cb0ef41Sopenharmony_ci        if (addrinfow_ptr != NULL) {
2121cb0ef41Sopenharmony_ci          addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
2131cb0ef41Sopenharmony_ci        }
2141cb0ef41Sopenharmony_ci      }
2151cb0ef41Sopenharmony_ci      req->addrinfo = (struct addrinfo*)alloc_ptr;
2161cb0ef41Sopenharmony_ci    } else {
2171cb0ef41Sopenharmony_ci      req->retcode = UV_EAI_MEMORY;
2181cb0ef41Sopenharmony_ci    }
2191cb0ef41Sopenharmony_ci  }
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  /* return memory to system */
2221cb0ef41Sopenharmony_ci  if (req->addrinfow != NULL) {
2231cb0ef41Sopenharmony_ci    FreeAddrInfoW(req->addrinfow);
2241cb0ef41Sopenharmony_ci    req->addrinfow = NULL;
2251cb0ef41Sopenharmony_ci  }
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_cicomplete:
2281cb0ef41Sopenharmony_ci  uv__req_unregister(req->loop, req);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  /* finally do callback with converted result */
2311cb0ef41Sopenharmony_ci  if (req->getaddrinfo_cb)
2321cb0ef41Sopenharmony_ci    req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
2331cb0ef41Sopenharmony_ci}
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_civoid uv_freeaddrinfo(struct addrinfo* ai) {
2371cb0ef41Sopenharmony_ci  char* alloc_ptr = (char*)ai;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  /* release copied result memory */
2401cb0ef41Sopenharmony_ci  uv__free(alloc_ptr);
2411cb0ef41Sopenharmony_ci}
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci/*
2451cb0ef41Sopenharmony_ci * Entry point for getaddrinfo
2461cb0ef41Sopenharmony_ci * we convert the UTF-8 strings to UNICODE
2471cb0ef41Sopenharmony_ci * and save the UNICODE string pointers in the req
2481cb0ef41Sopenharmony_ci * We also copy hints so that caller does not need to keep memory until the
2491cb0ef41Sopenharmony_ci * callback.
2501cb0ef41Sopenharmony_ci * return 0 if a callback will be made
2511cb0ef41Sopenharmony_ci * return error code if validation fails
2521cb0ef41Sopenharmony_ci *
2531cb0ef41Sopenharmony_ci * To minimize allocation we calculate total size required,
2541cb0ef41Sopenharmony_ci * and copy all structs and referenced strings into the one block.
2551cb0ef41Sopenharmony_ci * Each size calculation is adjusted to avoid unaligned pointers.
2561cb0ef41Sopenharmony_ci */
2571cb0ef41Sopenharmony_ciint uv_getaddrinfo(uv_loop_t* loop,
2581cb0ef41Sopenharmony_ci                   uv_getaddrinfo_t* req,
2591cb0ef41Sopenharmony_ci                   uv_getaddrinfo_cb getaddrinfo_cb,
2601cb0ef41Sopenharmony_ci                   const char* node,
2611cb0ef41Sopenharmony_ci                   const char* service,
2621cb0ef41Sopenharmony_ci                   const struct addrinfo* hints) {
2631cb0ef41Sopenharmony_ci  char hostname_ascii[256];
2641cb0ef41Sopenharmony_ci  int nodesize = 0;
2651cb0ef41Sopenharmony_ci  int servicesize = 0;
2661cb0ef41Sopenharmony_ci  int hintssize = 0;
2671cb0ef41Sopenharmony_ci  char* alloc_ptr = NULL;
2681cb0ef41Sopenharmony_ci  int err;
2691cb0ef41Sopenharmony_ci  long rc;
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  if (req == NULL || (node == NULL && service == NULL)) {
2721cb0ef41Sopenharmony_ci    return UV_EINVAL;
2731cb0ef41Sopenharmony_ci  }
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  UV_REQ_INIT(req, UV_GETADDRINFO);
2761cb0ef41Sopenharmony_ci  req->getaddrinfo_cb = getaddrinfo_cb;
2771cb0ef41Sopenharmony_ci  req->addrinfo = NULL;
2781cb0ef41Sopenharmony_ci  req->loop = loop;
2791cb0ef41Sopenharmony_ci  req->retcode = 0;
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  /* calculate required memory size for all input values */
2821cb0ef41Sopenharmony_ci  if (node != NULL) {
2831cb0ef41Sopenharmony_ci    rc = uv__idna_toascii(node,
2841cb0ef41Sopenharmony_ci                          node + strlen(node),
2851cb0ef41Sopenharmony_ci                          hostname_ascii,
2861cb0ef41Sopenharmony_ci                          hostname_ascii + sizeof(hostname_ascii));
2871cb0ef41Sopenharmony_ci    if (rc < 0)
2881cb0ef41Sopenharmony_ci      return rc;
2891cb0ef41Sopenharmony_ci    nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
2901cb0ef41Sopenharmony_ci                                                -1, NULL, 0) * sizeof(WCHAR));
2911cb0ef41Sopenharmony_ci    if (nodesize == 0) {
2921cb0ef41Sopenharmony_ci      err = GetLastError();
2931cb0ef41Sopenharmony_ci      goto error;
2941cb0ef41Sopenharmony_ci    }
2951cb0ef41Sopenharmony_ci    node = hostname_ascii;
2961cb0ef41Sopenharmony_ci  }
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  if (service != NULL) {
2991cb0ef41Sopenharmony_ci    servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
3001cb0ef41Sopenharmony_ci                                                   0,
3011cb0ef41Sopenharmony_ci                                                   service,
3021cb0ef41Sopenharmony_ci                                                   -1,
3031cb0ef41Sopenharmony_ci                                                   NULL,
3041cb0ef41Sopenharmony_ci                                                   0) *
3051cb0ef41Sopenharmony_ci                               sizeof(WCHAR));
3061cb0ef41Sopenharmony_ci    if (servicesize == 0) {
3071cb0ef41Sopenharmony_ci      err = GetLastError();
3081cb0ef41Sopenharmony_ci      goto error;
3091cb0ef41Sopenharmony_ci    }
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci  if (hints != NULL) {
3121cb0ef41Sopenharmony_ci    hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
3131cb0ef41Sopenharmony_ci  }
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  /* allocate memory for inputs, and partition it as needed */
3161cb0ef41Sopenharmony_ci  alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
3171cb0ef41Sopenharmony_ci  if (!alloc_ptr) {
3181cb0ef41Sopenharmony_ci    err = WSAENOBUFS;
3191cb0ef41Sopenharmony_ci    goto error;
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  /* save alloc_ptr now so we can free if error */
3231cb0ef41Sopenharmony_ci  req->alloc = (void*)alloc_ptr;
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci  /* Convert node string to UTF16 into allocated memory and save pointer in the
3261cb0ef41Sopenharmony_ci   * request. */
3271cb0ef41Sopenharmony_ci  if (node != NULL) {
3281cb0ef41Sopenharmony_ci    req->node = (WCHAR*)alloc_ptr;
3291cb0ef41Sopenharmony_ci    if (MultiByteToWideChar(CP_UTF8,
3301cb0ef41Sopenharmony_ci                            0,
3311cb0ef41Sopenharmony_ci                            node,
3321cb0ef41Sopenharmony_ci                            -1,
3331cb0ef41Sopenharmony_ci                            (WCHAR*) alloc_ptr,
3341cb0ef41Sopenharmony_ci                            nodesize / sizeof(WCHAR)) == 0) {
3351cb0ef41Sopenharmony_ci      err = GetLastError();
3361cb0ef41Sopenharmony_ci      goto error;
3371cb0ef41Sopenharmony_ci    }
3381cb0ef41Sopenharmony_ci    alloc_ptr += nodesize;
3391cb0ef41Sopenharmony_ci  } else {
3401cb0ef41Sopenharmony_ci    req->node = NULL;
3411cb0ef41Sopenharmony_ci  }
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  /* Convert service string to UTF16 into allocated memory and save pointer in
3441cb0ef41Sopenharmony_ci   * the req. */
3451cb0ef41Sopenharmony_ci  if (service != NULL) {
3461cb0ef41Sopenharmony_ci    req->service = (WCHAR*)alloc_ptr;
3471cb0ef41Sopenharmony_ci    if (MultiByteToWideChar(CP_UTF8,
3481cb0ef41Sopenharmony_ci                            0,
3491cb0ef41Sopenharmony_ci                            service,
3501cb0ef41Sopenharmony_ci                            -1,
3511cb0ef41Sopenharmony_ci                            (WCHAR*) alloc_ptr,
3521cb0ef41Sopenharmony_ci                            servicesize / sizeof(WCHAR)) == 0) {
3531cb0ef41Sopenharmony_ci      err = GetLastError();
3541cb0ef41Sopenharmony_ci      goto error;
3551cb0ef41Sopenharmony_ci    }
3561cb0ef41Sopenharmony_ci    alloc_ptr += servicesize;
3571cb0ef41Sopenharmony_ci  } else {
3581cb0ef41Sopenharmony_ci    req->service = NULL;
3591cb0ef41Sopenharmony_ci  }
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  /* copy hints to allocated memory and save pointer in req */
3621cb0ef41Sopenharmony_ci  if (hints != NULL) {
3631cb0ef41Sopenharmony_ci    req->addrinfow = (struct addrinfoW*)alloc_ptr;
3641cb0ef41Sopenharmony_ci    req->addrinfow->ai_family = hints->ai_family;
3651cb0ef41Sopenharmony_ci    req->addrinfow->ai_socktype = hints->ai_socktype;
3661cb0ef41Sopenharmony_ci    req->addrinfow->ai_protocol = hints->ai_protocol;
3671cb0ef41Sopenharmony_ci    req->addrinfow->ai_flags = hints->ai_flags;
3681cb0ef41Sopenharmony_ci    req->addrinfow->ai_addrlen = 0;
3691cb0ef41Sopenharmony_ci    req->addrinfow->ai_canonname = NULL;
3701cb0ef41Sopenharmony_ci    req->addrinfow->ai_addr = NULL;
3711cb0ef41Sopenharmony_ci    req->addrinfow->ai_next = NULL;
3721cb0ef41Sopenharmony_ci  } else {
3731cb0ef41Sopenharmony_ci    req->addrinfow = NULL;
3741cb0ef41Sopenharmony_ci  }
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci  uv__req_register(loop, req);
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  if (getaddrinfo_cb) {
3791cb0ef41Sopenharmony_ci    uv__work_submit(loop,
3801cb0ef41Sopenharmony_ci                    &req->work_req,
3811cb0ef41Sopenharmony_ci                    UV__WORK_SLOW_IO,
3821cb0ef41Sopenharmony_ci                    uv__getaddrinfo_work,
3831cb0ef41Sopenharmony_ci                    uv__getaddrinfo_done);
3841cb0ef41Sopenharmony_ci    return 0;
3851cb0ef41Sopenharmony_ci  } else {
3861cb0ef41Sopenharmony_ci    uv__getaddrinfo_work(&req->work_req);
3871cb0ef41Sopenharmony_ci    uv__getaddrinfo_done(&req->work_req, 0);
3881cb0ef41Sopenharmony_ci    return req->retcode;
3891cb0ef41Sopenharmony_ci  }
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_cierror:
3921cb0ef41Sopenharmony_ci  if (req != NULL) {
3931cb0ef41Sopenharmony_ci    uv__free(req->alloc);
3941cb0ef41Sopenharmony_ci    req->alloc = NULL;
3951cb0ef41Sopenharmony_ci  }
3961cb0ef41Sopenharmony_ci  return uv_translate_sys_error(err);
3971cb0ef41Sopenharmony_ci}
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ciint uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
4001cb0ef41Sopenharmony_ci  NET_LUID luid;
4011cb0ef41Sopenharmony_ci  wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
4021cb0ef41Sopenharmony_ci  DWORD bufsize;
4031cb0ef41Sopenharmony_ci  int r;
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  if (buffer == NULL || size == NULL || *size == 0)
4061cb0ef41Sopenharmony_ci    return UV_EINVAL;
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  r = ConvertInterfaceIndexToLuid(ifindex, &luid);
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ci  if (r != 0)
4111cb0ef41Sopenharmony_ci    return uv_translate_sys_error(r);
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci  if (r != 0)
4161cb0ef41Sopenharmony_ci    return uv_translate_sys_error(r);
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  /* Check how much space we need */
4191cb0ef41Sopenharmony_ci  bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci  if (bufsize == 0) {
4221cb0ef41Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
4231cb0ef41Sopenharmony_ci  } else if (bufsize > *size) {
4241cb0ef41Sopenharmony_ci    *size = bufsize;
4251cb0ef41Sopenharmony_ci    return UV_ENOBUFS;
4261cb0ef41Sopenharmony_ci  }
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci  /* Convert to UTF-8 */
4291cb0ef41Sopenharmony_ci  bufsize = WideCharToMultiByte(CP_UTF8,
4301cb0ef41Sopenharmony_ci                                0,
4311cb0ef41Sopenharmony_ci                                wname,
4321cb0ef41Sopenharmony_ci                                -1,
4331cb0ef41Sopenharmony_ci                                buffer,
4341cb0ef41Sopenharmony_ci                                *size,
4351cb0ef41Sopenharmony_ci                                NULL,
4361cb0ef41Sopenharmony_ci                                NULL);
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci  if (bufsize == 0)
4391cb0ef41Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci  *size = bufsize - 1;
4421cb0ef41Sopenharmony_ci  return 0;
4431cb0ef41Sopenharmony_ci}
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ciint uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
4461cb0ef41Sopenharmony_ci  int r;
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  if (buffer == NULL || size == NULL || *size == 0)
4491cb0ef41Sopenharmony_ci    return UV_EINVAL;
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  r = snprintf(buffer, *size, "%d", ifindex);
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci  if (r < 0)
4541cb0ef41Sopenharmony_ci    return uv_translate_sys_error(r);
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  if (r >= (int) *size) {
4571cb0ef41Sopenharmony_ci    *size = r + 1;
4581cb0ef41Sopenharmony_ci    return UV_ENOBUFS;
4591cb0ef41Sopenharmony_ci  }
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  *size = r;
4621cb0ef41Sopenharmony_ci  return 0;
4631cb0ef41Sopenharmony_ci}
464