summaryrefslogtreecommitdiffstats
path: root/src/win
diff options
context:
space:
mode:
authorlibuv upstream <libuv@googlegroups.com>2019-06-10 13:17:21 (GMT)
committerBrad King <brad.king@kitware.com>2019-06-18 11:45:34 (GMT)
commitb4069b04ff63b327ff4881282200c3c73fded34d (patch)
treef1c97b98e2253ec8e4a9b75ee2f8f99426e9b2f6 /src/win
parent4fcb0d0213112bb2fdb04bb27e82543b93cfe41d (diff)
downloadCMake-b4069b04ff63b327ff4881282200c3c73fded34d.zip
CMake-b4069b04ff63b327ff4881282200c3c73fded34d.tar.gz
CMake-b4069b04ff63b327ff4881282200c3c73fded34d.tar.bz2
libuv 2019-06-10 (ee24ce90)
Code extracted from: https://github.com/libuv/libuv.git at commit ee24ce900e5714c950b248da2bdd311b01c983be (v1.x).
Diffstat (limited to 'src/win')
-rw-r--r--src/win/core.c27
-rw-r--r--src/win/fs.c175
-rw-r--r--src/win/handle.c1
-rw-r--r--src/win/internal.h8
-rw-r--r--src/win/tcp.c40
-rw-r--r--src/win/thread.c27
-rw-r--r--src/win/tty.c4
-rw-r--r--src/win/udp.c103
-rw-r--r--src/win/util.c110
-rw-r--r--src/win/winsock.c15
10 files changed, 429 insertions, 81 deletions
diff --git a/src/win/core.c b/src/win/core.c
index bf80d77..e9d0a58 100644
--- a/src/win/core.c
+++ b/src/win/core.c
@@ -623,3 +623,30 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
return 0;
}
+
+int uv_cpumask_size(void) {
+ return (int)(sizeof(DWORD_PTR) * 8);
+}
+
+int uv__getsockpeername(const uv_handle_t* handle,
+ uv__peersockfunc func,
+ struct sockaddr* name,
+ int* namelen,
+ int delayed_error) {
+
+ int result;
+ uv_os_fd_t fd;
+
+ result = uv_fileno(handle, &fd);
+ if (result != 0)
+ return result;
+
+ if (delayed_error)
+ return uv_translate_sys_error(delayed_error);
+
+ result = func((SOCKET) fd, name, namelen);
+ if (result != 0)
+ return uv_translate_sys_error(WSAGetLastError());
+
+ return 0;
+}
diff --git a/src/win/fs.c b/src/win/fs.c
index 65d936b..9e2f084 100644
--- a/src/win/fs.c
+++ b/src/win/fs.c
@@ -1125,6 +1125,137 @@ cleanup:
uv__free(dirents);
}
+void fs__opendir(uv_fs_t* req) {
+ WCHAR* pathw;
+ size_t len;
+ const WCHAR* fmt;
+ WCHAR* find_path;
+ uv_dir_t* dir;
+
+ pathw = req->file.pathw;
+ dir = NULL;
+ find_path = NULL;
+
+ /* Figure out whether path is a file or a directory. */
+ if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
+ SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
+ goto error;
+ }
+
+ dir = uv__malloc(sizeof(*dir));
+ if (dir == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+ goto error;
+ }
+
+ len = wcslen(pathw);
+
+ if (len == 0)
+ fmt = L"./*";
+ else if (IS_SLASH(pathw[len - 1]))
+ fmt = L"%s*";
+ else
+ fmt = L"%s\\*";
+
+ find_path = uv__malloc(sizeof(WCHAR) * (len + 4));
+ if (find_path == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+ goto error;
+ }
+
+ _snwprintf(find_path, len + 3, fmt, pathw);
+ dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
+ uv__free(find_path);
+ find_path = NULL;
+ if (dir->dir_handle == INVALID_HANDLE_VALUE &&
+ GetLastError() != ERROR_FILE_NOT_FOUND) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ goto error;
+ }
+
+ dir->need_find_call = FALSE;
+ req->ptr = dir;
+ SET_REQ_RESULT(req, 0);
+ return;
+
+error:
+ uv__free(dir);
+ uv__free(find_path);
+ req->ptr = NULL;
+}
+
+void fs__readdir(uv_fs_t* req) {
+ uv_dir_t* dir;
+ uv_dirent_t* dirents;
+ uv__dirent_t dent;
+ unsigned int dirent_idx;
+ PWIN32_FIND_DATAW find_data;
+ unsigned int i;
+ int r;
+
+ req->flags |= UV_FS_FREE_PTR;
+ dir = req->ptr;
+ dirents = dir->dirents;
+ memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
+ find_data = &dir->find_data;
+ dirent_idx = 0;
+
+ while (dirent_idx < dir->nentries) {
+ if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ break;
+ goto error;
+ }
+
+ /* Skip "." and ".." entries. */
+ if (find_data->cFileName[0] == L'.' &&
+ (find_data->cFileName[1] == L'\0' ||
+ (find_data->cFileName[1] == L'.' &&
+ find_data->cFileName[2] == L'\0'))) {
+ dir->need_find_call = TRUE;
+ continue;
+ }
+
+ r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
+ -1,
+ (char**) &dirents[dirent_idx].name);
+ if (r != 0)
+ goto error;
+
+ /* Copy file type. */
+ if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ dent.d_type = UV__DT_DIR;
+ else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
+ dent.d_type = UV__DT_LINK;
+ else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
+ dent.d_type = UV__DT_CHAR;
+ else
+ dent.d_type = UV__DT_FILE;
+
+ dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
+ dir->need_find_call = TRUE;
+ ++dirent_idx;
+ }
+
+ SET_REQ_RESULT(req, dirent_idx);
+ return;
+
+error:
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ for (i = 0; i < dirent_idx; ++i) {
+ uv__free((char*) dirents[i].name);
+ dirents[i].name = NULL;
+ }
+}
+
+void fs__closedir(uv_fs_t* req) {
+ uv_dir_t* dir;
+
+ dir = req->ptr;
+ FindClose(dir->dir_handle);
+ uv__free(req->ptr);
+ SET_REQ_RESULT(req, 0);
+}
INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
int do_lstat) {
@@ -2039,6 +2170,9 @@ static void uv__fs_work(struct uv__work* w) {
XX(MKDTEMP, mkdtemp)
XX(RENAME, rename)
XX(SCANDIR, scandir)
+ XX(READDIR, readdir)
+ XX(OPENDIR, opendir)
+ XX(CLOSEDIR, closedir)
XX(LINK, link)
XX(SYMLINK, symlink)
XX(READLINK, readlink)
@@ -2080,6 +2214,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
if (req->flags & UV_FS_FREE_PTR) {
if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
uv__fs_scandir_cleanup(req);
+ else if (req->fs_type == UV_FS_READDIR)
+ uv__fs_readdir_cleanup(req);
else
uv__free(req->ptr);
}
@@ -2247,6 +2383,45 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
POST;
}
+int uv_fs_opendir(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_fs_cb cb) {
+ int err;
+
+ INIT(UV_FS_OPENDIR);
+ err = fs__capture_path(req, path, NULL, cb != NULL);
+ if (err)
+ return uv_translate_sys_error(err);
+ POST;
+}
+
+int uv_fs_readdir(uv_loop_t* loop,
+ uv_fs_t* req,
+ uv_dir_t* dir,
+ uv_fs_cb cb) {
+ INIT(UV_FS_READDIR);
+
+ if (dir == NULL ||
+ dir->dirents == NULL ||
+ dir->dir_handle == INVALID_HANDLE_VALUE) {
+ return UV_EINVAL;
+ }
+
+ req->ptr = dir;
+ POST;
+}
+
+int uv_fs_closedir(uv_loop_t* loop,
+ uv_fs_t* req,
+ uv_dir_t* dir,
+ uv_fs_cb cb) {
+ INIT(UV_FS_CLOSEDIR);
+ if (dir == NULL)
+ return UV_EINVAL;
+ req->ptr = dir;
+ POST;
+}
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
diff --git a/src/win/handle.c b/src/win/handle.c
index 9d76c3f..61e4df6 100644
--- a/src/win/handle.c
+++ b/src/win/handle.c
@@ -139,7 +139,6 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
case UV_FS_POLL:
uv__fs_poll_close((uv_fs_poll_t*) handle);
uv__handle_closing(handle);
- uv_want_endgame(loop, handle);
return;
default:
diff --git a/src/win/internal.h b/src/win/internal.h
index 634b9f7..70ddaa5 100644
--- a/src/win/internal.h
+++ b/src/win/internal.h
@@ -272,6 +272,14 @@ int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
+typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+ uv__peersockfunc func,
+ struct sockaddr* name,
+ int* namelen,
+ int delayed_error);
+
/*
* Process stdio handles.
diff --git a/src/win/tcp.c b/src/win/tcp.c
index 3ce5548..f2cb527 100644
--- a/src/win/tcp.c
+++ b/src/win/tcp.c
@@ -809,44 +809,24 @@ static int uv_tcp_try_connect(uv_connect_t* req,
int uv_tcp_getsockname(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
-
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
-
- if (handle->delayed_error) {
- return uv_translate_sys_error(handle->delayed_error);
- }
-
- result = getsockname(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen,
+ handle->delayed_error);
}
int uv_tcp_getpeername(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
-
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
-
- if (handle->delayed_error) {
- return uv_translate_sys_error(handle->delayed_error);
- }
-
- result = getpeername(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen,
+ handle->delayed_error);
}
diff --git a/src/win/thread.c b/src/win/thread.c
index fd4b7c9..89c53ad 100644
--- a/src/win/thread.c
+++ b/src/win/thread.c
@@ -112,9 +112,34 @@ static UINT __stdcall uv__thread_start(void* arg) {
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
+ uv_thread_options_t params;
+ params.flags = UV_THREAD_NO_FLAGS;
+ return uv_thread_create_ex(tid, &params, entry, arg);
+}
+
+int uv_thread_create_ex(uv_thread_t* tid,
+ const uv_thread_options_t* params,
+ void (*entry)(void *arg),
+ void *arg) {
struct thread_ctx* ctx;
int err;
HANDLE thread;
+ SYSTEM_INFO sysinfo;
+ size_t stack_size;
+ size_t pagesize;
+
+ stack_size =
+ params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
+
+ if (stack_size != 0) {
+ GetNativeSystemInfo(&sysinfo);
+ pagesize = (size_t)sysinfo.dwPageSize;
+ /* Round up to the nearest page boundary. */
+ stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
+
+ if ((unsigned)stack_size != stack_size)
+ return UV_EINVAL;
+ }
ctx = uv__malloc(sizeof(*ctx));
if (ctx == NULL)
@@ -126,7 +151,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
/* Create the thread in suspended state so we have a chance to pass
* its own creation handle to it */
thread = (HANDLE) _beginthreadex(NULL,
- 0,
+ (unsigned)stack_size,
uv__thread_start,
ctx,
CREATE_SUSPENDED,
diff --git a/src/win/tty.c b/src/win/tty.c
index f38e9a8..a98fe26 100644
--- a/src/win/tty.c
+++ b/src/win/tty.c
@@ -736,8 +736,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
/* Ignore keyup events, unless the left alt key was held and a valid
* unicode character was emitted. */
if (!KEV.bKeyDown &&
- KEV.wVirtualKeyCode != VK_MENU &&
- KEV.uChar.UnicodeChar != 0) {
+ (KEV.wVirtualKeyCode != VK_MENU ||
+ KEV.uChar.UnicodeChar == 0)) {
continue;
}
diff --git a/src/win/udp.c b/src/win/udp.c
index 37df849..8aeeab3 100644
--- a/src/win/udp.c
+++ b/src/win/udp.c
@@ -36,22 +36,27 @@ const unsigned int uv_active_udp_streams_threshold = 0;
/* A zero-size buffer for use by uv_udp_read */
static char uv_zero_[] = "";
-
-int uv_udp_getsockname(const uv_udp_t* handle,
+int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen,
+ 0);
+}
- result = getsockname(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+int uv_udp_getsockname(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen) {
+
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen,
+ 0);
}
@@ -784,6 +789,18 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
}
+int uv__udp_is_bound(uv_udp_t* handle) {
+ struct sockaddr_storage addr;
+ int addrlen;
+
+ addrlen = sizeof(addr);
+ if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+ return 0;
+
+ return addrlen > 0;
+}
+
+
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
@@ -803,7 +820,16 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
handle,
sock,
protocol_info.iAddressFamily);
- return uv_translate_sys_error(err);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ if (uv__udp_is_bound(handle))
+ handle->flags |= UV_HANDLE_BOUND;
+
+ if (uv__udp_is_connected(handle))
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
}
@@ -880,6 +906,50 @@ int uv__udp_bind(uv_udp_t* handle,
}
+int uv__udp_connect(uv_udp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen) {
+ const struct sockaddr* bind_addr;
+ int err;
+
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ if (addrlen == sizeof(uv_addr_ip4_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
+ else if (addrlen == sizeof(uv_addr_ip6_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
+ else
+ return UV_EINVAL;
+
+ err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ if (err)
+ return uv_translate_sys_error(err);
+ }
+
+ err = connect(handle->socket, addr, addrlen);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+ int err;
+ struct sockaddr addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ err = connect(handle->socket, &addr, sizeof(addr));
+ if (err)
+ return uv_translate_sys_error(err);
+
+ handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+ return 0;
+}
+
+
/* This function is an egress point, i.e. it returns libuv errors rather than
* system errors.
*/
@@ -900,6 +970,7 @@ int uv__udp_send(uv_udp_send_t* req,
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
else
return UV_EINVAL;
+
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
@@ -925,9 +996,11 @@ int uv__udp_try_send(uv_udp_t* handle,
assert(nbufs > 0);
- err = uv__convert_to_localhost_if_unspecified(addr, &converted);
- if (err)
- return err;
+ if (addr != NULL) {
+ err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+ if (err)
+ return err;
+ }
/* Already sending a message.*/
if (handle->send_queue_count != 0)
diff --git a/src/win/util.c b/src/win/util.c
index 9237891..7ca8321 100644
--- a/src/win/util.c
+++ b/src/win/util.c
@@ -59,13 +59,6 @@
# define UNLEN 256
#endif
-/*
- Max hostname length. The Windows gethostname() documentation states that 256
- bytes will always be large enough to hold the null-terminated hostname.
-*/
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 256
-#endif
/* Maximum environment variable size, including the terminating null */
#define MAX_ENV_VAR_LENGTH 32767
@@ -327,6 +320,11 @@ uint64_t uv_get_total_memory(void) {
}
+uint64_t uv_get_constrained_memory(void) {
+ return 0; /* Memory constraints are unknown. */
+}
+
+
uv_pid_t uv_os_getpid(void) {
return GetCurrentProcessId();
}
@@ -684,12 +682,9 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
NULL,
(BYTE*)&cpu_brand,
&cpu_brand_size);
- if (err != ERROR_SUCCESS) {
- RegCloseKey(processor_key);
- goto error;
- }
-
RegCloseKey(processor_key);
+ if (err != ERROR_SUCCESS)
+ goto error;
cpu_info = &cpu_infos[i];
cpu_info->speed = cpu_speed;
@@ -713,9 +708,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
return 0;
error:
- /* This is safe because the cpu_infos array is zeroed on allocation. */
- for (i = 0; i < cpu_count; i++)
- uv__free(cpu_infos[i].model);
+ if (cpu_infos != NULL) {
+ /* This is safe because the cpu_infos array is zeroed on allocation. */
+ for (i = 0; i < cpu_count; i++)
+ uv__free(cpu_infos[i].model);
+ }
uv__free(cpu_infos);
uv__free(sppi);
@@ -1510,7 +1507,7 @@ int uv_os_unsetenv(const char* name) {
int uv_os_gethostname(char* buffer, size_t* size) {
- char buf[MAXHOSTNAMELEN + 1];
+ char buf[UV_MAXHOSTNAMESIZE];
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
@@ -1634,6 +1631,10 @@ int uv_os_uname(uv_utsname_t* buffer) {
https://github.com/gagern/gnulib/blob/master/lib/uname.c */
OSVERSIONINFOW os_info;
SYSTEM_INFO system_info;
+ HKEY registry_key;
+ WCHAR product_name_w[256];
+ DWORD product_name_w_size;
+ int version_size;
int processor_level;
int r;
@@ -1658,16 +1659,56 @@ int uv_os_uname(uv_utsname_t* buffer) {
}
/* Populate the version field. */
- if (WideCharToMultiByte(CP_UTF8,
- 0,
- os_info.szCSDVersion,
- -1,
- buffer->version,
- sizeof(buffer->version),
- NULL,
- NULL) == 0) {
- r = uv_translate_sys_error(GetLastError());
- goto error;
+ version_size = 0;
+ r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+ 0,
+ KEY_QUERY_VALUE,
+ &registry_key);
+
+ if (r == ERROR_SUCCESS) {
+ product_name_w_size = sizeof(product_name_w);
+ r = RegGetValueW(registry_key,
+ NULL,
+ L"ProductName",
+ RRF_RT_REG_SZ,
+ NULL,
+ (PVOID) product_name_w,
+ &product_name_w_size);
+ RegCloseKey(registry_key);
+
+ if (r == ERROR_SUCCESS) {
+ version_size = WideCharToMultiByte(CP_UTF8,
+ 0,
+ product_name_w,
+ -1,
+ buffer->version,
+ sizeof(buffer->version),
+ NULL,
+ NULL);
+ if (version_size == 0) {
+ r = uv_translate_sys_error(GetLastError());
+ goto error;
+ }
+ }
+ }
+
+ /* Append service pack information to the version if present. */
+ if (os_info.szCSDVersion[0] != L'\0') {
+ if (version_size > 0)
+ buffer->version[version_size - 1] = ' ';
+
+ if (WideCharToMultiByte(CP_UTF8,
+ 0,
+ os_info.szCSDVersion,
+ -1,
+ buffer->version + version_size,
+ sizeof(buffer->version) - version_size,
+ NULL,
+ NULL) == 0) {
+ r = uv_translate_sys_error(GetLastError());
+ goto error;
+ }
}
/* Populate the sysname field. */
@@ -1744,3 +1785,20 @@ error:
buffer->machine[0] = '\0';
return r;
}
+
+int uv_gettimeofday(uv_timeval64_t* tv) {
+ /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */
+ const uint64_t epoch = (uint64_t) 116444736000000000ULL;
+ FILETIME file_time;
+ ULARGE_INTEGER ularge;
+
+ if (tv == NULL)
+ return UV_EINVAL;
+
+ GetSystemTimeAsFileTime(&file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+ tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L);
+ tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
+ return 0;
+}
diff --git a/src/win/winsock.c b/src/win/winsock.c
index 5e7da2a..5820ba9 100644
--- a/src/win/winsock.c
+++ b/src/win/winsock.c
@@ -87,12 +87,6 @@ void uv_winsock_init(void) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
- /* Initialize winsock */
- errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
- if (errorno != 0) {
- uv_fatal_error(errorno, "WSAStartup");
- }
-
/* Set implicit binding address used by connectEx */
if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
abort();
@@ -102,6 +96,15 @@ void uv_winsock_init(void) {
abort();
}
+ /* Skip initialization in safe mode without network support */
+ if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
+
+ /* Initialize winsock */
+ errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
+ if (errorno != 0) {
+ uv_fatal_error(errorno, "WSAStartup");
+ }
+
/* Detect non-IFS LSPs */
dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);