1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <windows.h>
33#include <glib.h>
34#include <stdlib.h>
35#include "config-host.h"
36#include "sysemu/sysemu.h"
37#include "qemu/main-loop.h"
38#include "trace.h"
39#include "qemu/sockets.h"
40
41
42#include <shlobj.h>
43
44void *qemu_oom_check(void *ptr)
45{
46 if (ptr == NULL) {
47 fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
48 abort();
49 }
50 return ptr;
51}
52
53void *qemu_try_memalign(size_t alignment, size_t size)
54{
55 void *ptr;
56
57 if (!size) {
58 abort();
59 }
60 ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
61 trace_qemu_memalign(alignment, size, ptr);
62 return ptr;
63}
64
65void *qemu_memalign(size_t alignment, size_t size)
66{
67 return qemu_oom_check(qemu_try_memalign(alignment, size));
68}
69
70void *qemu_anon_ram_alloc(size_t size, uint64_t *align)
71{
72 void *ptr;
73
74
75
76
77 ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
78 trace_qemu_anon_ram_alloc(size, ptr);
79 return ptr;
80}
81
82void qemu_vfree(void *ptr)
83{
84 trace_qemu_vfree(ptr);
85 if (ptr) {
86 VirtualFree(ptr, 0, MEM_RELEASE);
87 }
88}
89
90void qemu_anon_ram_free(void *ptr, size_t size)
91{
92 trace_qemu_anon_ram_free(ptr, size);
93 if (ptr) {
94 VirtualFree(ptr, 0, MEM_RELEASE);
95 }
96}
97
98
99struct tm *gmtime_r(const time_t *timep, struct tm *result)
100{
101 struct tm *p = gmtime(timep);
102 memset(result, 0, sizeof(*result));
103 if (p) {
104 *result = *p;
105 p = result;
106 }
107 return p;
108}
109
110
111struct tm *localtime_r(const time_t *timep, struct tm *result)
112{
113 struct tm *p = localtime(timep);
114 memset(result, 0, sizeof(*result));
115 if (p) {
116 *result = *p;
117 p = result;
118 }
119 return p;
120}
121
122void qemu_set_block(int fd)
123{
124 unsigned long opt = 0;
125 WSAEventSelect(fd, NULL, 0);
126 ioctlsocket(fd, FIONBIO, &opt);
127}
128
129void qemu_set_nonblock(int fd)
130{
131 unsigned long opt = 1;
132 ioctlsocket(fd, FIONBIO, &opt);
133 qemu_fd_register(fd);
134}
135
136int socket_set_fast_reuse(int fd)
137{
138
139
140
141
142
143 return 0;
144}
145
146int inet_aton(const char *cp, struct in_addr *ia)
147{
148 uint32_t addr = inet_addr(cp);
149 if (addr == 0xffffffff) {
150 return 0;
151 }
152 ia->s_addr = addr;
153 return 1;
154}
155
156void qemu_set_cloexec(int fd)
157{
158}
159
160
161#define _W32_FT_OFFSET (116444736000000000ULL)
162
163int qemu_gettimeofday(qemu_timeval *tp)
164{
165 union {
166 unsigned long long ns100;
167 FILETIME ft;
168 } _now;
169
170 if(tp) {
171 GetSystemTimeAsFileTime (&_now.ft);
172 tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
173 tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
174 }
175
176
177 return 0;
178}
179
180int qemu_get_thread_id(void)
181{
182 return GetCurrentThreadId();
183}
184
185char *
186qemu_get_local_state_pathname(const char *relative_pathname)
187{
188 HRESULT result;
189 char base_path[MAX_PATH+1] = "";
190
191 result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
192 0, base_path);
193 if (result != S_OK) {
194
195 g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result);
196 abort();
197 }
198 return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
199 relative_pathname);
200}
201
202void qemu_set_tty_echo(int fd, bool echo)
203{
204 HANDLE handle = (HANDLE)_get_osfhandle(fd);
205 DWORD dwMode = 0;
206
207 if (handle == INVALID_HANDLE_VALUE) {
208 return;
209 }
210
211 GetConsoleMode(handle, &dwMode);
212
213 if (echo) {
214 SetConsoleMode(handle, dwMode | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
215 } else {
216 SetConsoleMode(handle,
217 dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
218 }
219}
220
221static char exec_dir[PATH_MAX];
222
223void qemu_init_exec_dir(const char *argv0)
224{
225
226 char *p;
227 char buf[MAX_PATH];
228 DWORD len;
229
230 len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
231 if (len == 0) {
232 return;
233 }
234
235 buf[len] = 0;
236 p = buf + len - 1;
237 while (p != buf && *p != '\\') {
238 p--;
239 }
240 *p = 0;
241 if (access(buf, R_OK) == 0) {
242 pstrcpy(exec_dir, sizeof(exec_dir), buf);
243 }
244}
245
246char *qemu_get_exec_dir(void)
247{
248 return g_strdup(exec_dir);
249}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283static int poll_rest(gboolean poll_msgs, HANDLE *handles, gint nhandles,
284 GPollFD *fds, guint nfds, gint timeout)
285{
286 DWORD ready;
287 GPollFD *f;
288 int recursed_result;
289
290 if (poll_msgs) {
291
292
293
294 ready = MsgWaitForMultipleObjectsEx(nhandles, handles, timeout,
295 QS_ALLINPUT, MWMO_ALERTABLE);
296
297 if (ready == WAIT_FAILED) {
298 gchar *emsg = g_win32_error_message(GetLastError());
299 g_warning("MsgWaitForMultipleObjectsEx failed: %s", emsg);
300 g_free(emsg);
301 }
302 } else if (nhandles == 0) {
303
304 if (timeout == INFINITE) {
305 ready = WAIT_FAILED;
306 } else {
307 SleepEx(timeout, TRUE);
308 ready = WAIT_TIMEOUT;
309 }
310 } else {
311
312
313
314 ready =
315 WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE);
316 if (ready == WAIT_FAILED) {
317 gchar *emsg = g_win32_error_message(GetLastError());
318 g_warning("WaitForMultipleObjectsEx failed: %s", emsg);
319 g_free(emsg);
320 }
321 }
322
323 if (ready == WAIT_FAILED) {
324 return -1;
325 } else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) {
326 return 0;
327 } else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles) {
328 for (f = fds; f < &fds[nfds]; ++f) {
329 if (f->fd == G_WIN32_MSG_HANDLE && f->events & G_IO_IN) {
330 f->revents |= G_IO_IN;
331 }
332 }
333
334
335
336
337 if (timeout != 0 || nhandles == 0) {
338 return 1;
339 }
340
341
342
343
344 recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0);
345 return (recursed_result == -1) ? -1 : 1 + recursed_result;
346 } else if (
347
348 ready < WAIT_OBJECT_0 + nhandles) {
349 for (f = fds; f < &fds[nfds]; ++f) {
350 if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
351 f->revents = f->events;
352 }
353 }
354
355
356
357
358 if (timeout == 0 && nhandles > 1) {
359
360 int i;
361 if (ready < nhandles - 1) {
362 for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
363 handles[i-1] = handles[i];
364 }
365 }
366 nhandles--;
367 recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0);
368 return (recursed_result == -1) ? -1 : 1 + recursed_result;
369 }
370 return 1;
371 }
372
373 return 0;
374}
375
376gint g_poll(GPollFD *fds, guint nfds, gint timeout)
377{
378 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
379 gboolean poll_msgs = FALSE;
380 GPollFD *f;
381 gint nhandles = 0;
382 int retval;
383
384 for (f = fds; f < &fds[nfds]; ++f) {
385 if (f->fd == G_WIN32_MSG_HANDLE && (f->events & G_IO_IN)) {
386 poll_msgs = TRUE;
387 } else if (f->fd > 0) {
388
389
390
391
392 gint i;
393
394 for (i = 0; i < nhandles; i++) {
395 if (handles[i] == (HANDLE) f->fd) {
396 break;
397 }
398 }
399
400 if (i == nhandles) {
401 if (nhandles == MAXIMUM_WAIT_OBJECTS) {
402 g_warning("Too many handles to wait for!\n");
403 break;
404 } else {
405 handles[nhandles++] = (HANDLE) f->fd;
406 }
407 }
408 }
409 }
410
411 for (f = fds; f < &fds[nfds]; ++f) {
412 f->revents = 0;
413 }
414
415 if (timeout == -1) {
416 timeout = INFINITE;
417 }
418
419
420 if (nhandles > 1 || (nhandles > 0 && poll_msgs)) {
421
422
423
424 retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, 0);
425
426
427
428
429
430
431
432
433
434
435 if (retval == 0 && (timeout == INFINITE || timeout > 0)) {
436 retval = poll_rest(poll_msgs, handles, nhandles,
437 fds, nfds, timeout);
438 }
439 } else {
440
441
442
443 retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, timeout);
444 }
445
446 if (retval == -1) {
447 for (f = fds; f < &fds[nfds]; ++f) {
448 f->revents = 0;
449 }
450 }
451
452 return retval;
453}
454
455size_t getpagesize(void)
456{
457 SYSTEM_INFO system_info;
458
459 GetSystemInfo(&system_info);
460 return system_info.dwPageSize;
461}
462
463void os_mem_prealloc(int fd, char *area, size_t memory)
464{
465 int i;
466 size_t pagesize = getpagesize();
467
468 memory = (memory + pagesize - 1) & -pagesize;
469 for (i = 0; i < memory / pagesize; i++) {
470 memset(area + pagesize * i, 0, 1);
471 }
472}
473
474
475
476int qemu_read_password(char *buf, int buf_size)
477{
478 int c, i;
479
480 printf("Password: ");
481 fflush(stdout);
482 i = 0;
483 for (;;) {
484 c = getchar();
485 if (c < 0) {
486 buf[i] = '\0';
487 return -1;
488 } else if (c == '\n') {
489 break;
490 } else if (i < (buf_size - 1)) {
491 buf[i++] = c;
492 }
493 }
494 buf[i] = '\0';
495 return 0;
496}
497