rbuv 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (233) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +0 -1
  6. data/README.md +6 -1
  7. data/Rakefile +42 -0
  8. data/deps/libuv/.gitignore +34 -0
  9. data/deps/libuv/.mailmap +16 -0
  10. data/deps/libuv/AUTHORS +81 -0
  11. data/deps/libuv/ChangeLog +45 -0
  12. data/deps/libuv/LICENSE +41 -0
  13. data/deps/libuv/Makefile +53 -0
  14. data/deps/libuv/README.md +118 -0
  15. data/deps/libuv/build.mk +164 -0
  16. data/deps/libuv/checksparse.sh +230 -0
  17. data/deps/libuv/common.gypi +197 -0
  18. data/deps/libuv/config-mingw.mk +48 -0
  19. data/deps/libuv/config-unix.mk +167 -0
  20. data/deps/libuv/gyp_uv +98 -0
  21. data/deps/libuv/include/uv-private/ngx-queue.h +129 -0
  22. data/deps/libuv/include/uv-private/stdint-msvc2008.h +247 -0
  23. data/deps/libuv/include/uv-private/tree.h +768 -0
  24. data/deps/libuv/include/uv-private/uv-bsd.h +34 -0
  25. data/deps/libuv/include/uv-private/uv-darwin.h +61 -0
  26. data/deps/libuv/include/uv-private/uv-linux.h +34 -0
  27. data/deps/libuv/include/uv-private/uv-sunos.h +44 -0
  28. data/deps/libuv/include/uv-private/uv-unix.h +332 -0
  29. data/deps/libuv/include/uv-private/uv-win.h +585 -0
  30. data/deps/libuv/include/uv.h +1987 -0
  31. data/deps/libuv/src/fs-poll.c +248 -0
  32. data/deps/libuv/src/inet.c +298 -0
  33. data/deps/libuv/src/unix/aix.c +393 -0
  34. data/deps/libuv/src/unix/async.c +281 -0
  35. data/deps/libuv/src/unix/core.c +714 -0
  36. data/deps/libuv/src/unix/cygwin.c +93 -0
  37. data/deps/libuv/src/unix/darwin-proctitle.m +78 -0
  38. data/deps/libuv/src/unix/darwin.c +431 -0
  39. data/deps/libuv/src/unix/dl.c +83 -0
  40. data/deps/libuv/src/unix/error.c +109 -0
  41. data/deps/libuv/src/unix/freebsd.c +343 -0
  42. data/deps/libuv/src/unix/fs.c +869 -0
  43. data/deps/libuv/src/unix/fsevents.c +299 -0
  44. data/deps/libuv/src/unix/getaddrinfo.c +159 -0
  45. data/deps/libuv/src/unix/internal.h +259 -0
  46. data/deps/libuv/src/unix/kqueue.c +347 -0
  47. data/deps/libuv/src/unix/linux-core.c +724 -0
  48. data/deps/libuv/src/unix/linux-inotify.c +236 -0
  49. data/deps/libuv/src/unix/linux-syscalls.c +388 -0
  50. data/deps/libuv/src/unix/linux-syscalls.h +150 -0
  51. data/deps/libuv/src/unix/loop-watcher.c +64 -0
  52. data/deps/libuv/src/unix/loop.c +114 -0
  53. data/deps/libuv/src/unix/netbsd.c +353 -0
  54. data/deps/libuv/src/unix/openbsd.c +304 -0
  55. data/deps/libuv/src/unix/pipe.c +261 -0
  56. data/deps/libuv/src/unix/poll.c +108 -0
  57. data/deps/libuv/src/unix/process.c +501 -0
  58. data/deps/libuv/src/unix/proctitle.c +103 -0
  59. data/deps/libuv/src/unix/signal.c +455 -0
  60. data/deps/libuv/src/unix/stream.c +1380 -0
  61. data/deps/libuv/src/unix/sunos.c +647 -0
  62. data/deps/libuv/src/unix/tcp.c +357 -0
  63. data/deps/libuv/src/unix/thread.c +431 -0
  64. data/deps/libuv/src/unix/threadpool.c +286 -0
  65. data/deps/libuv/src/unix/timer.c +153 -0
  66. data/deps/libuv/src/unix/tty.c +179 -0
  67. data/deps/libuv/src/unix/udp.c +715 -0
  68. data/deps/libuv/src/uv-common.c +431 -0
  69. data/deps/libuv/src/uv-common.h +204 -0
  70. data/deps/libuv/src/version.c +60 -0
  71. data/deps/libuv/src/win/async.c +99 -0
  72. data/deps/libuv/src/win/atomicops-inl.h +56 -0
  73. data/deps/libuv/src/win/core.c +310 -0
  74. data/deps/libuv/src/win/dl.c +86 -0
  75. data/deps/libuv/src/win/error.c +164 -0
  76. data/deps/libuv/src/win/fs-event.c +506 -0
  77. data/deps/libuv/src/win/fs.c +1951 -0
  78. data/deps/libuv/src/win/getaddrinfo.c +365 -0
  79. data/deps/libuv/src/win/handle-inl.h +164 -0
  80. data/deps/libuv/src/win/handle.c +153 -0
  81. data/deps/libuv/src/win/internal.h +346 -0
  82. data/deps/libuv/src/win/loop-watcher.c +124 -0
  83. data/deps/libuv/src/win/pipe.c +1656 -0
  84. data/deps/libuv/src/win/poll.c +615 -0
  85. data/deps/libuv/src/win/process-stdio.c +503 -0
  86. data/deps/libuv/src/win/process.c +1048 -0
  87. data/deps/libuv/src/win/req-inl.h +224 -0
  88. data/deps/libuv/src/win/req.c +25 -0
  89. data/deps/libuv/src/win/signal.c +354 -0
  90. data/deps/libuv/src/win/stream-inl.h +67 -0
  91. data/deps/libuv/src/win/stream.c +198 -0
  92. data/deps/libuv/src/win/tcp.c +1422 -0
  93. data/deps/libuv/src/win/thread.c +666 -0
  94. data/deps/libuv/src/win/threadpool.c +82 -0
  95. data/deps/libuv/src/win/timer.c +230 -0
  96. data/deps/libuv/src/win/tty.c +1857 -0
  97. data/deps/libuv/src/win/udp.c +744 -0
  98. data/deps/libuv/src/win/util.c +946 -0
  99. data/deps/libuv/src/win/winapi.c +152 -0
  100. data/deps/libuv/src/win/winapi.h +4476 -0
  101. data/deps/libuv/src/win/winsock.c +560 -0
  102. data/deps/libuv/src/win/winsock.h +171 -0
  103. data/deps/libuv/test/benchmark-async-pummel.c +119 -0
  104. data/deps/libuv/test/benchmark-async.c +139 -0
  105. data/deps/libuv/test/benchmark-fs-stat.c +136 -0
  106. data/deps/libuv/test/benchmark-getaddrinfo.c +91 -0
  107. data/deps/libuv/test/benchmark-list.h +163 -0
  108. data/deps/libuv/test/benchmark-loop-count.c +90 -0
  109. data/deps/libuv/test/benchmark-million-async.c +112 -0
  110. data/deps/libuv/test/benchmark-million-timers.c +77 -0
  111. data/deps/libuv/test/benchmark-multi-accept.c +432 -0
  112. data/deps/libuv/test/benchmark-ping-pongs.c +212 -0
  113. data/deps/libuv/test/benchmark-pound.c +325 -0
  114. data/deps/libuv/test/benchmark-pump.c +459 -0
  115. data/deps/libuv/test/benchmark-sizes.c +45 -0
  116. data/deps/libuv/test/benchmark-spawn.c +163 -0
  117. data/deps/libuv/test/benchmark-tcp-write-batch.c +141 -0
  118. data/deps/libuv/test/benchmark-thread.c +64 -0
  119. data/deps/libuv/test/benchmark-udp-pummel.c +238 -0
  120. data/deps/libuv/test/blackhole-server.c +118 -0
  121. data/deps/libuv/test/dns-server.c +329 -0
  122. data/deps/libuv/test/echo-server.c +384 -0
  123. data/deps/libuv/test/fixtures/empty_file +0 -0
  124. data/deps/libuv/test/fixtures/load_error.node +1 -0
  125. data/deps/libuv/test/run-benchmarks.c +64 -0
  126. data/deps/libuv/test/run-tests.c +159 -0
  127. data/deps/libuv/test/runner-unix.c +328 -0
  128. data/deps/libuv/test/runner-unix.h +36 -0
  129. data/deps/libuv/test/runner-win.c +318 -0
  130. data/deps/libuv/test/runner-win.h +43 -0
  131. data/deps/libuv/test/runner.c +394 -0
  132. data/deps/libuv/test/runner.h +165 -0
  133. data/deps/libuv/test/task.h +122 -0
  134. data/deps/libuv/test/test-active.c +83 -0
  135. data/deps/libuv/test/test-async.c +136 -0
  136. data/deps/libuv/test/test-barrier.c +98 -0
  137. data/deps/libuv/test/test-callback-order.c +77 -0
  138. data/deps/libuv/test/test-callback-stack.c +204 -0
  139. data/deps/libuv/test/test-condvar.c +173 -0
  140. data/deps/libuv/test/test-connection-fail.c +150 -0
  141. data/deps/libuv/test/test-cwd-and-chdir.c +64 -0
  142. data/deps/libuv/test/test-delayed-accept.c +189 -0
  143. data/deps/libuv/test/test-dlerror.c +58 -0
  144. data/deps/libuv/test/test-embed.c +136 -0
  145. data/deps/libuv/test/test-error.c +59 -0
  146. data/deps/libuv/test/test-fail-always.c +29 -0
  147. data/deps/libuv/test/test-fs-event.c +504 -0
  148. data/deps/libuv/test/test-fs-poll.c +148 -0
  149. data/deps/libuv/test/test-fs.c +1899 -0
  150. data/deps/libuv/test/test-get-currentexe.c +63 -0
  151. data/deps/libuv/test/test-get-loadavg.c +36 -0
  152. data/deps/libuv/test/test-get-memory.c +38 -0
  153. data/deps/libuv/test/test-getaddrinfo.c +120 -0
  154. data/deps/libuv/test/test-getsockname.c +344 -0
  155. data/deps/libuv/test/test-hrtime.c +54 -0
  156. data/deps/libuv/test/test-idle.c +82 -0
  157. data/deps/libuv/test/test-ipc-send-recv.c +218 -0
  158. data/deps/libuv/test/test-ipc.c +625 -0
  159. data/deps/libuv/test/test-list.h +492 -0
  160. data/deps/libuv/test/test-loop-handles.c +337 -0
  161. data/deps/libuv/test/test-loop-stop.c +73 -0
  162. data/deps/libuv/test/test-multiple-listen.c +103 -0
  163. data/deps/libuv/test/test-mutexes.c +63 -0
  164. data/deps/libuv/test/test-pass-always.c +28 -0
  165. data/deps/libuv/test/test-ping-pong.c +250 -0
  166. data/deps/libuv/test/test-pipe-bind-error.c +144 -0
  167. data/deps/libuv/test/test-pipe-connect-error.c +98 -0
  168. data/deps/libuv/test/test-platform-output.c +87 -0
  169. data/deps/libuv/test/test-poll-close.c +73 -0
  170. data/deps/libuv/test/test-poll.c +575 -0
  171. data/deps/libuv/test/test-process-title.c +49 -0
  172. data/deps/libuv/test/test-ref.c +415 -0
  173. data/deps/libuv/test/test-run-nowait.c +46 -0
  174. data/deps/libuv/test/test-run-once.c +49 -0
  175. data/deps/libuv/test/test-semaphore.c +111 -0
  176. data/deps/libuv/test/test-shutdown-close.c +105 -0
  177. data/deps/libuv/test/test-shutdown-eof.c +184 -0
  178. data/deps/libuv/test/test-signal-multiple-loops.c +270 -0
  179. data/deps/libuv/test/test-signal.c +152 -0
  180. data/deps/libuv/test/test-spawn.c +938 -0
  181. data/deps/libuv/test/test-stdio-over-pipes.c +250 -0
  182. data/deps/libuv/test/test-tcp-bind-error.c +198 -0
  183. data/deps/libuv/test/test-tcp-bind6-error.c +159 -0
  184. data/deps/libuv/test/test-tcp-close-while-connecting.c +81 -0
  185. data/deps/libuv/test/test-tcp-close.c +130 -0
  186. data/deps/libuv/test/test-tcp-connect-error-after-write.c +96 -0
  187. data/deps/libuv/test/test-tcp-connect-error.c +71 -0
  188. data/deps/libuv/test/test-tcp-connect-timeout.c +86 -0
  189. data/deps/libuv/test/test-tcp-connect6-error.c +69 -0
  190. data/deps/libuv/test/test-tcp-flags.c +52 -0
  191. data/deps/libuv/test/test-tcp-open.c +175 -0
  192. data/deps/libuv/test/test-tcp-read-stop.c +73 -0
  193. data/deps/libuv/test/test-tcp-shutdown-after-write.c +132 -0
  194. data/deps/libuv/test/test-tcp-unexpected-read.c +114 -0
  195. data/deps/libuv/test/test-tcp-write-to-half-open-connection.c +136 -0
  196. data/deps/libuv/test/test-tcp-writealot.c +171 -0
  197. data/deps/libuv/test/test-thread.c +183 -0
  198. data/deps/libuv/test/test-threadpool-cancel.c +311 -0
  199. data/deps/libuv/test/test-threadpool.c +77 -0
  200. data/deps/libuv/test/test-timer-again.c +142 -0
  201. data/deps/libuv/test/test-timer.c +266 -0
  202. data/deps/libuv/test/test-tty.c +111 -0
  203. data/deps/libuv/test/test-udp-dgram-too-big.c +87 -0
  204. data/deps/libuv/test/test-udp-ipv6.c +158 -0
  205. data/deps/libuv/test/test-udp-multicast-join.c +140 -0
  206. data/deps/libuv/test/test-udp-multicast-ttl.c +87 -0
  207. data/deps/libuv/test/test-udp-open.c +154 -0
  208. data/deps/libuv/test/test-udp-options.c +87 -0
  209. data/deps/libuv/test/test-udp-send-and-recv.c +210 -0
  210. data/deps/libuv/test/test-util.c +97 -0
  211. data/deps/libuv/test/test-walk-handles.c +78 -0
  212. data/deps/libuv/uv.gyp +431 -0
  213. data/deps/libuv/vcbuild.bat +128 -0
  214. data/ext/rbuv/debug.h +27 -0
  215. data/ext/rbuv/error.c +7 -0
  216. data/ext/rbuv/error.h +10 -0
  217. data/ext/rbuv/extconf.rb +35 -0
  218. data/ext/rbuv/handle.c +40 -0
  219. data/ext/rbuv/handle.h +14 -0
  220. data/ext/rbuv/libuv.mk +12 -0
  221. data/ext/rbuv/loop.c +50 -0
  222. data/ext/rbuv/loop.h +13 -0
  223. data/ext/rbuv/rbuv.c +15 -0
  224. data/ext/rbuv/rbuv.h +27 -0
  225. data/ext/rbuv/timer.c +133 -0
  226. data/ext/rbuv/timer.h +13 -0
  227. data/lib/rbuv/timer.rb +7 -0
  228. data/lib/rbuv/version.rb +1 -1
  229. data/lib/rbuv.rb +24 -2
  230. data/rbuv.gemspec +5 -1
  231. data/spec/spec_helper.rb +22 -0
  232. data/spec/timer_spec.rb +144 -0
  233. metadata +278 -9
@@ -0,0 +1,946 @@
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 <malloc.h>
26
+ #include <stdio.h>
27
+ #include <string.h>
28
+ #include <time.h>
29
+ #include <wchar.h>
30
+
31
+ #include "uv.h"
32
+ #include "internal.h"
33
+
34
+ #include <iphlpapi.h>
35
+ #include <psapi.h>
36
+ #include <tlhelp32.h>
37
+
38
+
39
+ /*
40
+ * Max title length; the only thing MSDN tells us about the maximum length
41
+ * of the console title is that it is smaller than 64K. However in practice
42
+ * it is much smaller, and there is no way to figure out what the exact length
43
+ * of the title is or can be, at least not on XP. To make it even more
44
+ * annoying, GetConsoleTitle failes when the buffer to be read into is bigger
45
+ * than the actual maximum length. So we make a conservative guess here;
46
+ * just don't put the novel you're writing in the title, unless the plot
47
+ * survives truncation.
48
+ */
49
+ #define MAX_TITLE_LENGTH 8192
50
+
51
+ /* The number of nanoseconds in one second. */
52
+ #undef NANOSEC
53
+ #define NANOSEC 1000000000
54
+
55
+
56
+ /* Cached copy of the process title, plus a mutex guarding it. */
57
+ static char *process_title;
58
+ static CRITICAL_SECTION process_title_lock;
59
+
60
+ /* The tick frequency of the high-resolution clock. */
61
+ static uint64_t hrtime_frequency_ = 0;
62
+
63
+
64
+ /*
65
+ * One-time intialization code for functionality defined in util.c.
66
+ */
67
+ void uv__util_init() {
68
+ /* Initialize process title access mutex. */
69
+ InitializeCriticalSection(&process_title_lock);
70
+
71
+ /* Retrieve high-resolution timer frequency. */
72
+ if (!QueryPerformanceFrequency((LARGE_INTEGER*) &hrtime_frequency_))
73
+ hrtime_frequency_ = 0;
74
+ }
75
+
76
+
77
+ int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size,
78
+ char* utf8Buffer, size_t utf8Size) {
79
+ return WideCharToMultiByte(CP_UTF8,
80
+ 0,
81
+ utf16Buffer,
82
+ utf16Size,
83
+ utf8Buffer,
84
+ utf8Size,
85
+ NULL,
86
+ NULL);
87
+ }
88
+
89
+
90
+ int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer,
91
+ size_t utf16Size) {
92
+ return MultiByteToWideChar(CP_UTF8,
93
+ 0,
94
+ utf8Buffer,
95
+ -1,
96
+ utf16Buffer,
97
+ utf16Size);
98
+ }
99
+
100
+
101
+ int uv_exepath(char* buffer, size_t* size_ptr) {
102
+ int utf8_len, utf16_buffer_len, utf16_len;
103
+ WCHAR* utf16_buffer;
104
+
105
+ if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
106
+ return -1;
107
+ }
108
+
109
+ if (*size_ptr > 32768) {
110
+ /* Windows paths can never be longer than this. */
111
+ utf16_buffer_len = 32768;
112
+ } else {
113
+ utf16_buffer_len = (int) *size_ptr;
114
+ }
115
+
116
+ utf16_buffer = (WCHAR*) malloc(sizeof(WCHAR) * utf16_buffer_len);
117
+ if (!utf16_buffer) {
118
+ return -1;
119
+ }
120
+
121
+ /* Get the path as UTF-16. */
122
+ utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
123
+ if (utf16_len <= 0) {
124
+ goto error;
125
+ }
126
+
127
+ /* utf16_len contains the length, *not* including the terminating null. */
128
+ utf16_buffer[utf16_len] = L'\0';
129
+
130
+ /* Convert to UTF-8 */
131
+ utf8_len = WideCharToMultiByte(CP_UTF8,
132
+ 0,
133
+ utf16_buffer,
134
+ -1,
135
+ buffer,
136
+ *size_ptr > INT_MAX ? INT_MAX : (int) *size_ptr,
137
+ NULL,
138
+ NULL);
139
+ if (utf8_len == 0) {
140
+ goto error;
141
+ }
142
+
143
+ free(utf16_buffer);
144
+
145
+ /* utf8_len *does* include the terminating null at this point, but the */
146
+ /* returned size shouldn't. */
147
+ *size_ptr = utf8_len - 1;
148
+ return 0;
149
+
150
+ error:
151
+ free(utf16_buffer);
152
+ return -1;
153
+ }
154
+
155
+
156
+ uv_err_t uv_cwd(char* buffer, size_t size) {
157
+ DWORD utf16_len;
158
+ WCHAR utf16_buffer[MAX_PATH];
159
+ int r;
160
+
161
+ if (buffer == NULL || size == 0) {
162
+ return uv__new_artificial_error(UV_EINVAL);
163
+ }
164
+
165
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
166
+ if (utf16_len == 0) {
167
+ return uv__new_sys_error(GetLastError());
168
+ } else if (utf16_len > MAX_PATH) {
169
+ /* This should be impossible; however the CRT has a code path to deal */
170
+ /* with this scenario, so I added a check anyway. */
171
+ return uv__new_artificial_error(UV_EIO);
172
+ }
173
+
174
+ /* utf16_len contains the length, *not* including the terminating null. */
175
+ utf16_buffer[utf16_len] = L'\0';
176
+
177
+ /* The returned directory should not have a trailing slash, unless it */
178
+ /* points at a drive root, like c:\. Remove it if needed.*/
179
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
180
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
181
+ utf16_len--;
182
+ utf16_buffer[utf16_len] = L'\0';
183
+ }
184
+
185
+ /* Convert to UTF-8 */
186
+ r = WideCharToMultiByte(CP_UTF8,
187
+ 0,
188
+ utf16_buffer,
189
+ -1,
190
+ buffer,
191
+ size > INT_MAX ? INT_MAX : (int) size,
192
+ NULL,
193
+ NULL);
194
+ if (r == 0) {
195
+ return uv__new_sys_error(GetLastError());
196
+ }
197
+
198
+ return uv_ok_;
199
+ }
200
+
201
+
202
+ uv_err_t uv_chdir(const char* dir) {
203
+ WCHAR utf16_buffer[MAX_PATH];
204
+ size_t utf16_len;
205
+ WCHAR drive_letter, env_var[4];
206
+
207
+ if (dir == NULL) {
208
+ return uv__new_artificial_error(UV_EINVAL);
209
+ }
210
+
211
+ if (MultiByteToWideChar(CP_UTF8,
212
+ 0,
213
+ dir,
214
+ -1,
215
+ utf16_buffer,
216
+ MAX_PATH) == 0) {
217
+ DWORD error = GetLastError();
218
+ /* The maximum length of the current working directory is 260 chars, */
219
+ /* including terminating null. If it doesn't fit, the path name must be */
220
+ /* too long. */
221
+ if (error == ERROR_INSUFFICIENT_BUFFER) {
222
+ return uv__new_artificial_error(UV_ENAMETOOLONG);
223
+ } else {
224
+ return uv__new_sys_error(error);
225
+ }
226
+ }
227
+
228
+ if (!SetCurrentDirectoryW(utf16_buffer)) {
229
+ return uv__new_sys_error(GetLastError());
230
+ }
231
+
232
+ /* Windows stores the drive-local path in an "hidden" environment variable, */
233
+ /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
234
+ /* update this, so we'll have to do it. */
235
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
236
+ if (utf16_len == 0) {
237
+ return uv__new_sys_error(GetLastError());
238
+ } else if (utf16_len > MAX_PATH) {
239
+ return uv__new_artificial_error(UV_EIO);
240
+ }
241
+
242
+ /* The returned directory should not have a trailing slash, unless it */
243
+ /* points at a drive root, like c:\. Remove it if needed. */
244
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
245
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
246
+ utf16_len--;
247
+ utf16_buffer[utf16_len] = L'\0';
248
+ }
249
+
250
+ if (utf16_len < 2 || utf16_buffer[1] != L':') {
251
+ /* Doesn't look like a drive letter could be there - probably an UNC */
252
+ /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
253
+ drive_letter = 0;
254
+ } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
255
+ drive_letter = utf16_buffer[0];
256
+ } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
257
+ /* Convert to uppercase. */
258
+ drive_letter = utf16_buffer[0] - L'a' + L'A';
259
+ } else {
260
+ /* Not valid. */
261
+ drive_letter = 0;
262
+ }
263
+
264
+ if (drive_letter != 0) {
265
+ /* Construct the environment variable name and set it. */
266
+ env_var[0] = L'=';
267
+ env_var[1] = drive_letter;
268
+ env_var[2] = L':';
269
+ env_var[3] = L'\0';
270
+
271
+ if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
272
+ return uv__new_sys_error(GetLastError());
273
+ }
274
+ }
275
+
276
+ return uv_ok_;
277
+ }
278
+
279
+
280
+ void uv_loadavg(double avg[3]) {
281
+ /* Can't be implemented */
282
+ avg[0] = avg[1] = avg[2] = 0;
283
+ }
284
+
285
+
286
+ uint64_t uv_get_free_memory(void) {
287
+ MEMORYSTATUSEX memory_status;
288
+ memory_status.dwLength = sizeof(memory_status);
289
+
290
+ if(!GlobalMemoryStatusEx(&memory_status))
291
+ {
292
+ return -1;
293
+ }
294
+
295
+ return (uint64_t)memory_status.ullAvailPhys;
296
+ }
297
+
298
+
299
+ uint64_t uv_get_total_memory(void) {
300
+ MEMORYSTATUSEX memory_status;
301
+ memory_status.dwLength = sizeof(memory_status);
302
+
303
+ if(!GlobalMemoryStatusEx(&memory_status))
304
+ {
305
+ return -1;
306
+ }
307
+
308
+ return (uint64_t)memory_status.ullTotalPhys;
309
+ }
310
+
311
+
312
+ int uv_parent_pid() {
313
+ int parent_pid = -1;
314
+ HANDLE handle;
315
+ PROCESSENTRY32 pe;
316
+ int current_pid = GetCurrentProcessId();
317
+
318
+ pe.dwSize = sizeof(PROCESSENTRY32);
319
+ handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
320
+
321
+ if (Process32First(handle, &pe)) {
322
+ do {
323
+ if (pe.th32ProcessID == current_pid) {
324
+ parent_pid = pe.th32ParentProcessID;
325
+ break;
326
+ }
327
+ } while( Process32Next(handle, &pe));
328
+ }
329
+
330
+ CloseHandle(handle);
331
+ return parent_pid;
332
+ }
333
+
334
+
335
+ char** uv_setup_args(int argc, char** argv) {
336
+ return argv;
337
+ }
338
+
339
+
340
+ uv_err_t uv_set_process_title(const char* title) {
341
+ uv_err_t err;
342
+ int length;
343
+ WCHAR* title_w = NULL;
344
+
345
+ uv__once_init();
346
+
347
+ /* Find out how big the buffer for the wide-char title must be */
348
+ length = uv_utf8_to_utf16(title, NULL, 0);
349
+ if (!length) {
350
+ err = uv__new_sys_error(GetLastError());
351
+ goto done;
352
+ }
353
+
354
+ /* Convert to wide-char string */
355
+ title_w = (WCHAR*)malloc(sizeof(WCHAR) * length);
356
+ if (!title_w) {
357
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
358
+ }
359
+
360
+ length = uv_utf8_to_utf16(title, title_w, length);
361
+ if (!length) {
362
+ err = uv__new_sys_error(GetLastError());
363
+ goto done;
364
+ };
365
+
366
+ /* If the title must be truncated insert a \0 terminator there */
367
+ if (length > MAX_TITLE_LENGTH) {
368
+ title_w[MAX_TITLE_LENGTH - 1] = L'\0';
369
+ }
370
+
371
+ if (!SetConsoleTitleW(title_w)) {
372
+ err = uv__new_sys_error(GetLastError());
373
+ goto done;
374
+ }
375
+
376
+ EnterCriticalSection(&process_title_lock);
377
+ free(process_title);
378
+ process_title = strdup(title);
379
+ LeaveCriticalSection(&process_title_lock);
380
+
381
+ err = uv_ok_;
382
+
383
+ done:
384
+ free(title_w);
385
+ return err;
386
+ }
387
+
388
+
389
+ static int uv__get_process_title() {
390
+ WCHAR title_w[MAX_TITLE_LENGTH];
391
+ int length;
392
+
393
+ if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
394
+ return -1;
395
+ }
396
+
397
+ /* Find out what the size of the buffer is that we need */
398
+ length = uv_utf16_to_utf8(title_w, -1, NULL, 0);
399
+ if (!length) {
400
+ return -1;
401
+ }
402
+
403
+ assert(!process_title);
404
+ process_title = (char*)malloc(length);
405
+ if (!process_title) {
406
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
407
+ }
408
+
409
+ /* Do utf16 -> utf8 conversion here */
410
+ if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) {
411
+ free(process_title);
412
+ return -1;
413
+ }
414
+
415
+ return 0;
416
+ }
417
+
418
+
419
+ uv_err_t uv_get_process_title(char* buffer, size_t size) {
420
+ uv__once_init();
421
+
422
+ EnterCriticalSection(&process_title_lock);
423
+ /*
424
+ * If the process_title was never read before nor explicitly set,
425
+ * we must query it with getConsoleTitleW
426
+ */
427
+ if (!process_title && uv__get_process_title() == -1) {
428
+ return uv__new_sys_error(GetLastError());
429
+ }
430
+
431
+ assert(process_title);
432
+ strncpy(buffer, process_title, size);
433
+ LeaveCriticalSection(&process_title_lock);
434
+
435
+ return uv_ok_;
436
+ }
437
+
438
+
439
+ uint64_t uv_hrtime(void) {
440
+ LARGE_INTEGER counter;
441
+
442
+ uv__once_init();
443
+
444
+ /* If the performance frequency is zero, there's no support. */
445
+ if (!hrtime_frequency_) {
446
+ /* uv__set_sys_error(loop, ERROR_NOT_SUPPORTED); */
447
+ return 0;
448
+ }
449
+
450
+ if (!QueryPerformanceCounter(&counter)) {
451
+ /* uv__set_sys_error(loop, GetLastError()); */
452
+ return 0;
453
+ }
454
+
455
+ /* Because we have no guarantee about the order of magnitude of the */
456
+ /* performance counter frequency, and there may not be much headroom to */
457
+ /* multiply by NANOSEC without overflowing, we use 128-bit math instead. */
458
+ return ((uint64_t) counter.LowPart * NANOSEC / hrtime_frequency_) +
459
+ (((uint64_t) counter.HighPart * NANOSEC / hrtime_frequency_)
460
+ << 32);
461
+ }
462
+
463
+
464
+ uv_err_t uv_resident_set_memory(size_t* rss) {
465
+ HANDLE current_process;
466
+ PROCESS_MEMORY_COUNTERS pmc;
467
+
468
+ current_process = GetCurrentProcess();
469
+
470
+ if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) {
471
+ return uv__new_sys_error(GetLastError());
472
+ }
473
+
474
+ *rss = pmc.WorkingSetSize;
475
+
476
+ return uv_ok_;
477
+ }
478
+
479
+
480
+ uv_err_t uv_uptime(double* uptime) {
481
+ BYTE stack_buffer[4096];
482
+ BYTE* malloced_buffer = NULL;
483
+ BYTE* buffer = (BYTE*) stack_buffer;
484
+ size_t buffer_size = sizeof(stack_buffer);
485
+ DWORD data_size;
486
+
487
+ PERF_DATA_BLOCK* data_block;
488
+ PERF_OBJECT_TYPE* object_type;
489
+ PERF_COUNTER_DEFINITION* counter_definition;
490
+
491
+ DWORD i;
492
+
493
+ for (;;) {
494
+ LONG result;
495
+
496
+ data_size = (DWORD) buffer_size;
497
+ result = RegQueryValueExW(HKEY_PERFORMANCE_DATA,
498
+ L"2",
499
+ NULL,
500
+ NULL,
501
+ buffer,
502
+ &data_size);
503
+ if (result == ERROR_SUCCESS) {
504
+ break;
505
+ } else if (result != ERROR_MORE_DATA) {
506
+ *uptime = 0;
507
+ return uv__new_sys_error(result);
508
+ }
509
+
510
+ free(malloced_buffer);
511
+
512
+ buffer_size *= 2;
513
+ /* Don't let the buffer grow infinitely. */
514
+ if (buffer_size > 1 << 20) {
515
+ goto internalError;
516
+ }
517
+
518
+ buffer = malloced_buffer = (BYTE*) malloc(buffer_size);
519
+ if (malloced_buffer == NULL) {
520
+ *uptime = 0;
521
+ return uv__new_artificial_error(UV_ENOMEM);
522
+ }
523
+ }
524
+
525
+ if (data_size < sizeof(*data_block))
526
+ goto internalError;
527
+
528
+ data_block = (PERF_DATA_BLOCK*) buffer;
529
+
530
+ if (wmemcmp(data_block->Signature, L"PERF", 4) != 0)
531
+ goto internalError;
532
+
533
+ if (data_size < data_block->HeaderLength + sizeof(*object_type))
534
+ goto internalError;
535
+
536
+ object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength);
537
+
538
+ if (object_type->NumInstances != PERF_NO_INSTANCES)
539
+ goto internalError;
540
+
541
+ counter_definition = (PERF_COUNTER_DEFINITION*) (buffer +
542
+ data_block->HeaderLength + object_type->HeaderLength);
543
+ for (i = 0; i < object_type->NumCounters; i++) {
544
+ if ((BYTE*) counter_definition + sizeof(*counter_definition) >
545
+ buffer + data_size) {
546
+ break;
547
+ }
548
+
549
+ if (counter_definition->CounterNameTitleIndex == 674 &&
550
+ counter_definition->CounterSize == sizeof(uint64_t)) {
551
+ if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size ||
552
+ !(counter_definition->CounterType & PERF_OBJECT_TIMER)) {
553
+ goto internalError;
554
+ } else {
555
+ BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
556
+ counter_definition->CounterOffset;
557
+ uint64_t value = *((uint64_t*) address);
558
+ *uptime = (double) (object_type->PerfTime.QuadPart - value) /
559
+ (double) object_type->PerfFreq.QuadPart;
560
+ free(malloced_buffer);
561
+ return uv_ok_;
562
+ }
563
+ }
564
+
565
+ counter_definition = (PERF_COUNTER_DEFINITION*)
566
+ ((BYTE*) counter_definition + counter_definition->ByteLength);
567
+ }
568
+
569
+ /* If we get here, the uptime value was not found. */
570
+ free(malloced_buffer);
571
+ *uptime = 0;
572
+ return uv__new_artificial_error(UV_ENOSYS);
573
+
574
+ internalError:
575
+ free(malloced_buffer);
576
+ *uptime = 0;
577
+ return uv__new_artificial_error(UV_EIO);
578
+ }
579
+
580
+
581
+ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
582
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
583
+ DWORD sppi_size;
584
+ SYSTEM_INFO system_info;
585
+ DWORD cpu_count, i, r;
586
+ ULONG result_size;
587
+ size_t size;
588
+ uv_err_t err;
589
+ uv_cpu_info_t* cpu_info;
590
+
591
+ *cpu_infos = NULL;
592
+ *count = 0;
593
+
594
+ uv__once_init();
595
+
596
+ GetSystemInfo(&system_info);
597
+ cpu_count = system_info.dwNumberOfProcessors;
598
+
599
+ size = cpu_count * sizeof(uv_cpu_info_t);
600
+ *cpu_infos = (uv_cpu_info_t*) malloc(size);
601
+ if (*cpu_infos == NULL) {
602
+ err = uv__new_artificial_error(UV_ENOMEM);
603
+ goto out;
604
+ }
605
+ memset(*cpu_infos, 0, size);
606
+
607
+ sppi_size = sizeof(*sppi) * cpu_count;
608
+ sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(sppi_size);
609
+ if (!sppi) {
610
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
611
+ }
612
+
613
+ r = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
614
+ sppi,
615
+ sppi_size,
616
+ &result_size);
617
+ if (r != ERROR_SUCCESS || result_size != sppi_size) {
618
+ err = uv__new_sys_error(GetLastError());
619
+ goto out;
620
+ }
621
+
622
+ for (i = 0; i < cpu_count; i++) {
623
+ WCHAR key_name[128];
624
+ HKEY processor_key;
625
+ DWORD cpu_speed;
626
+ DWORD cpu_speed_size = sizeof(cpu_speed);
627
+ WCHAR cpu_brand[256];
628
+ DWORD cpu_brand_size = sizeof(cpu_brand);
629
+
630
+ _snwprintf(key_name,
631
+ ARRAY_SIZE(key_name),
632
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
633
+ i);
634
+
635
+ r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
636
+ key_name,
637
+ 0,
638
+ KEY_QUERY_VALUE,
639
+ &processor_key);
640
+ if (r != ERROR_SUCCESS) {
641
+ err = uv__new_sys_error(GetLastError());
642
+ goto out;
643
+ }
644
+
645
+ if (RegQueryValueExW(processor_key,
646
+ L"~MHz",
647
+ NULL, NULL,
648
+ (BYTE*) &cpu_speed,
649
+ &cpu_speed_size) != ERROR_SUCCESS) {
650
+ err = uv__new_sys_error(GetLastError());
651
+ RegCloseKey(processor_key);
652
+ goto out;
653
+ }
654
+
655
+ if (RegQueryValueExW(processor_key,
656
+ L"ProcessorNameString",
657
+ NULL, NULL,
658
+ (BYTE*) &cpu_brand,
659
+ &cpu_brand_size) != ERROR_SUCCESS) {
660
+ err = uv__new_sys_error(GetLastError());
661
+ RegCloseKey(processor_key);
662
+ goto out;
663
+ }
664
+
665
+ RegCloseKey(processor_key);
666
+
667
+ cpu_info = &(*cpu_infos)[i];
668
+ cpu_info->speed = cpu_speed;
669
+ cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
670
+ cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
671
+ sppi[i].IdleTime.QuadPart) / 10000;
672
+ cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
673
+ cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
674
+ cpu_info->cpu_times.nice = 0;
675
+
676
+ size = uv_utf16_to_utf8(cpu_brand,
677
+ cpu_brand_size / sizeof(WCHAR),
678
+ NULL,
679
+ 0);
680
+ if (size == 0) {
681
+ err = uv__new_sys_error(GetLastError());
682
+ goto out;
683
+ }
684
+
685
+ /* Allocate 1 extra byte for the null terminator. */
686
+ cpu_info->model = (char*) malloc(size + 1);
687
+ if (cpu_info->model == NULL) {
688
+ err = uv__new_artificial_error(UV_ENOMEM);
689
+ goto out;
690
+ }
691
+
692
+ if (uv_utf16_to_utf8(cpu_brand,
693
+ cpu_brand_size / sizeof(WCHAR),
694
+ cpu_info->model,
695
+ size) == 0) {
696
+ err = uv__new_sys_error(GetLastError());
697
+ goto out;
698
+ }
699
+
700
+ /* Ensure that cpu_info->model is null terminated. */
701
+ cpu_info->model[size] = '\0';
702
+
703
+ (*count)++;
704
+ }
705
+
706
+ err = uv_ok_;
707
+
708
+ out:
709
+ if (sppi) {
710
+ free(sppi);
711
+ }
712
+
713
+ if (err.code != UV_OK &&
714
+ *cpu_infos != NULL) {
715
+ int i;
716
+
717
+ for (i = 0; i < *count; i++) {
718
+ /* This is safe because the cpu_infos memory area is zeroed out */
719
+ /* immediately after allocating it. */
720
+ free((*cpu_infos)[i].model);
721
+ }
722
+ free(*cpu_infos);
723
+
724
+ *cpu_infos = NULL;
725
+ *count = 0;
726
+ }
727
+
728
+ return err;
729
+ }
730
+
731
+
732
+ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
733
+ int i;
734
+
735
+ for (i = 0; i < count; i++) {
736
+ free(cpu_infos[i].model);
737
+ }
738
+
739
+ free(cpu_infos);
740
+ }
741
+
742
+
743
+ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses_ptr,
744
+ int* count_ptr) {
745
+ IP_ADAPTER_ADDRESSES* win_address_buf;
746
+ ULONG win_address_buf_size;
747
+ IP_ADAPTER_ADDRESSES* win_address;
748
+
749
+ uv_interface_address_t* uv_address_buf;
750
+ char* name_buf;
751
+ size_t uv_address_buf_size;
752
+ uv_interface_address_t* uv_address;
753
+
754
+ int count;
755
+
756
+ /* Fetch the size of the adapters reported by windows, and then get the */
757
+ /* list itself. */
758
+ win_address_buf_size = 0;
759
+ win_address_buf = NULL;
760
+
761
+ for (;;) {
762
+ ULONG r;
763
+
764
+ /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */
765
+ /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */
766
+ /* win_address_buf_size. */
767
+ r = GetAdaptersAddresses(AF_UNSPEC,
768
+ 0,
769
+ NULL,
770
+ win_address_buf,
771
+ &win_address_buf_size);
772
+
773
+ if (r == ERROR_SUCCESS)
774
+ break;
775
+
776
+ free(win_address_buf);
777
+
778
+ switch (r) {
779
+ case ERROR_BUFFER_OVERFLOW:
780
+ /* This happens when win_address_buf is NULL or too small to hold */
781
+ /* all adapters. */
782
+ win_address_buf = malloc(win_address_buf_size);
783
+ if (win_address_buf == NULL)
784
+ return uv__new_artificial_error(UV_ENOMEM);
785
+
786
+ continue;
787
+
788
+ case ERROR_NO_DATA: {
789
+ /* No adapters were found. */
790
+ uv_address_buf = malloc(1);
791
+ if (uv_address_buf == NULL)
792
+ return uv__new_artificial_error(UV_ENOMEM);
793
+
794
+ *count_ptr = 0;
795
+ *addresses_ptr = uv_address_buf;
796
+
797
+ return uv_ok_;
798
+ }
799
+
800
+ case ERROR_ADDRESS_NOT_ASSOCIATED:
801
+ return uv__new_artificial_error(UV_EAGAIN);
802
+
803
+ case ERROR_INVALID_PARAMETER:
804
+ /* MSDN says:
805
+ * "This error is returned for any of the following conditions: the
806
+ * SizePointer parameter is NULL, the Address parameter is not
807
+ * AF_INET, AF_INET6, or AF_UNSPEC, or the address information for
808
+ * the parameters requested is greater than ULONG_MAX."
809
+ * Since the first two conditions are not met, it must be that the
810
+ * adapter data is too big.
811
+ */
812
+ return uv__new_artificial_error(UV_ENOBUFS);
813
+
814
+ default:
815
+ /* Other (unspecified) errors can happen, but we don't have any */
816
+ /* special meaning for them. */
817
+ assert(r != ERROR_SUCCESS);
818
+ return uv__new_sys_error(r);
819
+ }
820
+ }
821
+
822
+ /* Count the number of enabled interfaces and compute how much space is */
823
+ /* needed to store their info. */
824
+ count = 0;
825
+ uv_address_buf_size = 0;
826
+
827
+ for (win_address = win_address_buf;
828
+ win_address != NULL;
829
+ win_address = win_address->Next) {
830
+ /* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */
831
+ /* with Windows XP */
832
+ IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address;
833
+ int name_size;
834
+
835
+ /* Interfaces that are not 'up' should not be reported. Also skip */
836
+ /* interfaces that have no associated unicast address, as to avoid */
837
+ /* allocating space for the name for this interface. */
838
+ if (win_address->OperStatus != IfOperStatusUp ||
839
+ win_address->FirstUnicastAddress == NULL)
840
+ continue;
841
+
842
+ /* Compute the size of the interface name. */
843
+ name_size = WideCharToMultiByte(CP_UTF8,
844
+ 0,
845
+ win_address->FriendlyName,
846
+ -1,
847
+ NULL,
848
+ 0,
849
+ NULL,
850
+ FALSE);
851
+ if (name_size <= 0) {
852
+ free(win_address_buf);
853
+ return uv__new_sys_error(GetLastError());
854
+ }
855
+ uv_address_buf_size += name_size;
856
+
857
+ /* Count the number of addresses associated with this interface, and */
858
+ /* compute the size. */
859
+ for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
860
+ win_address->FirstUnicastAddress;
861
+ unicast_address != NULL;
862
+ unicast_address = unicast_address->Next) {
863
+ count++;
864
+ uv_address_buf_size += sizeof(uv_interface_address_t);
865
+ }
866
+ }
867
+
868
+ /* Allocate space to store interface data plus adapter names. */
869
+ uv_address_buf = malloc(uv_address_buf_size);
870
+ if (uv_address_buf == NULL) {
871
+ free(win_address_buf);
872
+ return uv__new_artificial_error(UV_ENOMEM);
873
+ }
874
+
875
+ /* Compute the start of the uv_interface_address_t array, and the place in */
876
+ /* the buffer where the interface names will be stored. */
877
+ uv_address = uv_address_buf;
878
+ name_buf = (char*) (uv_address_buf + count);
879
+
880
+ /* Fill out the output buffer. */
881
+ for (win_address = win_address_buf;
882
+ win_address != NULL;
883
+ win_address = win_address->Next) {
884
+ IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address;
885
+ int name_size;
886
+ size_t max_name_size;
887
+
888
+ if (win_address->OperStatus != IfOperStatusUp ||
889
+ win_address->FirstUnicastAddress == NULL)
890
+ continue;
891
+
892
+ /* Convert the interface name to UTF8. */
893
+ max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
894
+ if (max_name_size > (size_t) INT_MAX)
895
+ max_name_size = INT_MAX;
896
+ name_size = WideCharToMultiByte(CP_UTF8,
897
+ 0,
898
+ win_address->FriendlyName,
899
+ -1,
900
+ name_buf,
901
+ (int) max_name_size,
902
+ NULL,
903
+ FALSE);
904
+ if (name_size <= 0) {
905
+ free(win_address_buf);
906
+ free(uv_address_buf);
907
+ return uv__new_sys_error(GetLastError());
908
+ }
909
+
910
+ /* Add an uv_interface_address_t element for every unicast address. */
911
+ for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
912
+ win_address->FirstUnicastAddress;
913
+ unicast_address != NULL;
914
+ unicast_address = unicast_address->Next) {
915
+ struct sockaddr* sa;
916
+
917
+ uv_address->name = name_buf;
918
+
919
+ sa = unicast_address->Address.lpSockaddr;
920
+ if (sa->sa_family == AF_INET6)
921
+ uv_address->address.address6 = *((struct sockaddr_in6 *) sa);
922
+ else
923
+ uv_address->address.address4 = *((struct sockaddr_in *) sa);
924
+
925
+ uv_address->is_internal =
926
+ (win_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
927
+
928
+ uv_address++;
929
+ }
930
+
931
+ name_buf += name_size;
932
+ }
933
+
934
+ free(win_address_buf);
935
+
936
+ *addresses_ptr = uv_address_buf;
937
+ *count_ptr = count;
938
+
939
+ return uv_ok_;
940
+ }
941
+
942
+
943
+ void uv_free_interface_addresses(uv_interface_address_t* addresses,
944
+ int count) {
945
+ free(addresses);
946
+ }