master
c 934 lines 20.6 KB
Raw
1 /*
2 * os-win32.c
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2010-2016 Red Hat, Inc.
6 *
7 * QEMU library functions for win32 which are shared between QEMU and
8 * the QEMU tools.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 */
28
29 #include "qemu/osdep.h"
30 #include <windows.h>
31 #include "qapi/error.h"
32 #include "qemu/main-loop.h"
33 #include "trace.h"
34 #include "qemu/sockets.h"
35 #include "qemu/cutils.h"
36 #include "qemu/error-report.h"
37 #include <malloc.h>
38
39 static int get_allocation_granularity(void)
40 {
41 SYSTEM_INFO system_info;
42
43 GetSystemInfo(&system_info);
44 return system_info.dwAllocationGranularity;
45 }
46
47 void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
48 bool noreserve)
49 {
50 void *ptr;
51
52 if (noreserve) {
53 /*
54 * We need a MEM_COMMIT before accessing any memory in a MEM_RESERVE
55 * area; we cannot easily mimic POSIX MAP_NORESERVE semantics.
56 */
57 error_report("Skipping reservation of swap space is not supported.");
58 return NULL;
59 }
60
61 ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
62 trace_qemu_anon_ram_alloc(size, ptr);
63
64 if (ptr && align) {
65 *align = MAX(get_allocation_granularity(), getpagesize());
66 }
67 return ptr;
68 }
69
70 void qemu_anon_ram_free(void *ptr, size_t size)
71 {
72 trace_qemu_anon_ram_free(ptr, size);
73 if (ptr) {
74 VirtualFree(ptr, 0, MEM_RELEASE);
75 }
76 }
77
78 #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
79 /* FIXME: add proper locking */
80 struct tm *gmtime_r(const time_t *timep, struct tm *result)
81 {
82 struct tm *p = gmtime(timep);
83 memset(result, 0, sizeof(*result));
84 if (p) {
85 *result = *p;
86 p = result;
87 }
88 return p;
89 }
90
91 /* FIXME: add proper locking */
92 struct tm *localtime_r(const time_t *timep, struct tm *result)
93 {
94 struct tm *p = localtime(timep);
95 memset(result, 0, sizeof(*result));
96 if (p) {
97 *result = *p;
98 p = result;
99 }
100 return p;
101 }
102 #endif /* _POSIX_THREAD_SAFE_FUNCTIONS */
103
104 static int socket_error(void)
105 {
106 switch (WSAGetLastError()) {
107 case 0:
108 return 0;
109 case WSAEINTR:
110 return EINTR;
111 case WSAEINVAL:
112 return EINVAL;
113 case WSA_INVALID_HANDLE:
114 return EBADF;
115 case WSA_NOT_ENOUGH_MEMORY:
116 return ENOMEM;
117 case WSA_INVALID_PARAMETER:
118 return EINVAL;
119 case WSAENAMETOOLONG:
120 return ENAMETOOLONG;
121 case WSAENOTEMPTY:
122 return ENOTEMPTY;
123 case WSAEWOULDBLOCK:
124 /* not using EWOULDBLOCK as we don't want code to have
125 * to check both EWOULDBLOCK and EAGAIN */
126 return EAGAIN;
127 case WSAEINPROGRESS:
128 return EINPROGRESS;
129 case WSAEALREADY:
130 return EALREADY;
131 case WSAENOTSOCK:
132 return ENOTSOCK;
133 case WSAEDESTADDRREQ:
134 return EDESTADDRREQ;
135 case WSAEMSGSIZE:
136 return EMSGSIZE;
137 case WSAEPROTOTYPE:
138 return EPROTOTYPE;
139 case WSAENOPROTOOPT:
140 return ENOPROTOOPT;
141 case WSAEPROTONOSUPPORT:
142 return EPROTONOSUPPORT;
143 case WSAEOPNOTSUPP:
144 return EOPNOTSUPP;
145 case WSAEAFNOSUPPORT:
146 return EAFNOSUPPORT;
147 case WSAEADDRINUSE:
148 return EADDRINUSE;
149 case WSAEADDRNOTAVAIL:
150 return EADDRNOTAVAIL;
151 case WSAENETDOWN:
152 return ENETDOWN;
153 case WSAENETUNREACH:
154 return ENETUNREACH;
155 case WSAENETRESET:
156 return ENETRESET;
157 case WSAECONNABORTED:
158 return ECONNABORTED;
159 case WSAECONNRESET:
160 return ECONNRESET;
161 case WSAENOBUFS:
162 return ENOBUFS;
163 case WSAEISCONN:
164 return EISCONN;
165 case WSAENOTCONN:
166 return ENOTCONN;
167 case WSAETIMEDOUT:
168 return ETIMEDOUT;
169 case WSAECONNREFUSED:
170 return ECONNREFUSED;
171 case WSAELOOP:
172 return ELOOP;
173 case WSAEHOSTUNREACH:
174 return EHOSTUNREACH;
175 default:
176 return EIO;
177 }
178 }
179
180 bool qemu_set_blocking(int fd, bool block, Error **errp)
181 {
182 unsigned long opt = block ? 0 : 1;
183
184 if (block) {
185 qemu_socket_unselect_nofail(fd);
186 }
187
188 if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
189 error_setg_errno(errp, socket_error(),
190 "Can't set file descriptor %d %s", fd,
191 block ? "blocking" : "non-blocking");
192 return false;
193 }
194
195 return true;
196 }
197
198 int socket_set_fast_reuse(int fd)
199 {
200 /* Enabling the reuse of an endpoint that was used by a socket still in
201 * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
202 * fast reuse is the default and SO_REUSEADDR does strange things. So we
203 * don't have to do anything here. More info can be found at:
204 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
205 return 0;
206 }
207
208 int inet_aton(const char *cp, struct in_addr *ia)
209 {
210 uint32_t addr = inet_addr(cp);
211 if (addr == 0xffffffff) {
212 return 0;
213 }
214 ia->s_addr = addr;
215 return 1;
216 }
217
218 void qemu_set_cloexec(int fd)
219 {
220 }
221
222 void qemu_clear_cloexec(int fd)
223 {
224 }
225
226 int qemu_get_thread_id(void)
227 {
228 return GetCurrentThreadId();
229 }
230
231 char *
232 qemu_get_local_state_dir(void)
233 {
234 const char * const *data_dirs = g_get_system_data_dirs();
235
236 g_assert(data_dirs && data_dirs[0]);
237
238 return g_strdup(data_dirs[0]);
239 }
240
241 void qemu_set_tty_echo(int fd, bool echo)
242 {
243 HANDLE handle = (HANDLE)_get_osfhandle(fd);
244 DWORD dwMode = 0;
245
246 if (handle == INVALID_HANDLE_VALUE) {
247 return;
248 }
249
250 GetConsoleMode(handle, &dwMode);
251
252 if (echo) {
253 SetConsoleMode(handle, dwMode | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
254 } else {
255 SetConsoleMode(handle,
256 dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
257 }
258 }
259
260 int getpagesize(void)
261 {
262 SYSTEM_INFO system_info;
263
264 GetSystemInfo(&system_info);
265 return system_info.dwPageSize;
266 }
267
268 bool qemu_prealloc_mem(int fd, char *area, size_t sz, int max_threads,
269 ThreadContext *tc, bool async, Error **errp)
270 {
271 int i;
272 size_t pagesize = qemu_real_host_page_size();
273
274 sz = (sz + pagesize - 1) & -pagesize;
275 for (i = 0; i < sz / pagesize; i++) {
276 memset(area + pagesize * i, 0, 1);
277 }
278
279 return true;
280 }
281
282 bool qemu_finish_async_prealloc_mem(Error **errp)
283 {
284 /* async prealloc not supported, there is nothing to finish */
285 return true;
286 }
287
288 char *qemu_get_pid_name(pid_t pid)
289 {
290 /* XXX Implement me */
291 abort();
292 }
293
294
295 bool qemu_socket_select(int sockfd, WSAEVENT hEventObject,
296 long lNetworkEvents, Error **errp)
297 {
298 SOCKET s = _get_osfhandle(sockfd);
299
300 if (s == INVALID_SOCKET) {
301 error_setg(errp, "invalid socket fd=%d", sockfd);
302 return false;
303 }
304
305 if (WSAEventSelect(s, hEventObject, lNetworkEvents) != 0) {
306 error_setg_win32(errp, WSAGetLastError(), "failed to WSAEventSelect()");
307 return false;
308 }
309
310 return true;
311 }
312
313 bool qemu_socket_unselect(int sockfd, Error **errp)
314 {
315 return qemu_socket_select(sockfd, NULL, 0, errp);
316 }
317
318 void qemu_socket_select_nofail(int sockfd, WSAEVENT hEventObject,
319 long lNetworkEvents)
320 {
321 Error *err = NULL;
322
323 if (!qemu_socket_select(sockfd, hEventObject, lNetworkEvents, &err)) {
324 warn_report_err(err);
325 }
326 }
327
328 void qemu_socket_unselect_nofail(int sockfd)
329 {
330 Error *err = NULL;
331
332 if (!qemu_socket_unselect(sockfd, &err)) {
333 warn_report_err(err);
334 }
335 }
336
337 int qemu_socketpair(int domain, int type, int protocol, int sv[2])
338 {
339 struct sockaddr_un addr = {
340 0,
341 };
342 socklen_t socklen;
343 int listener = -1;
344 int client = -1;
345 int server = -1;
346 g_autofree char *path = NULL;
347 int tmpfd;
348 u_long arg;
349 int ret = -1;
350
351 g_return_val_if_fail(sv != NULL, -1);
352
353 addr.sun_family = AF_UNIX;
354 socklen = sizeof(addr);
355
356 tmpfd = g_file_open_tmp(NULL, &path, NULL);
357 if (tmpfd == -1 || !path) {
358 errno = EACCES;
359 goto out;
360 }
361
362 close(tmpfd);
363
364 if (strlen(path) >= sizeof(addr.sun_path)) {
365 errno = EINVAL;
366 goto out;
367 }
368
369 strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
370
371 listener = socket(domain, type, protocol);
372 if (listener == -1) {
373 goto out;
374 }
375
376 if (DeleteFile(path) == 0 && GetLastError() != ERROR_FILE_NOT_FOUND) {
377 errno = EACCES;
378 goto out;
379 }
380 g_clear_pointer(&path, g_free);
381
382 if (bind(listener, (struct sockaddr *)&addr, socklen) == -1) {
383 goto out;
384 }
385
386 if (listen(listener, 1) == -1) {
387 goto out;
388 }
389
390 client = socket(domain, type, protocol);
391 if (client == -1) {
392 goto out;
393 }
394
395 arg = 1;
396 if (ioctlsocket(client, FIONBIO, &arg) != NO_ERROR) {
397 goto out;
398 }
399
400 if (connect(client, (struct sockaddr *)&addr, socklen) == -1 &&
401 WSAGetLastError() != WSAEWOULDBLOCK) {
402 goto out;
403 }
404
405 server = accept(listener, NULL, NULL);
406 if (server == -1) {
407 goto out;
408 }
409
410 arg = 0;
411 if (ioctlsocket(client, FIONBIO, &arg) != NO_ERROR) {
412 goto out;
413 }
414
415 arg = 0;
416 if (ioctlsocket(client, SIO_AF_UNIX_GETPEERPID, &arg) != NO_ERROR) {
417 goto out;
418 }
419
420 if (arg != GetCurrentProcessId()) {
421 errno = EPERM;
422 goto out;
423 }
424
425 sv[0] = server;
426 server = -1;
427 sv[1] = client;
428 client = -1;
429 ret = 0;
430
431 out:
432 if (listener != -1) {
433 close(listener);
434 }
435 if (client != -1) {
436 close(client);
437 }
438 if (server != -1) {
439 close(server);
440 }
441 if (path) {
442 DeleteFile(path);
443 }
444 return ret;
445 }
446
447 #undef connect
448 int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
449 socklen_t addrlen)
450 {
451 int ret;
452 SOCKET s = _get_osfhandle(sockfd);
453
454 if (s == INVALID_SOCKET) {
455 return -1;
456 }
457
458 ret = connect(s, addr, addrlen);
459 if (ret < 0) {
460 if (WSAGetLastError() == WSAEWOULDBLOCK) {
461 errno = EINPROGRESS;
462 } else {
463 errno = socket_error();
464 }
465 }
466 return ret;
467 }
468
469
470 #undef listen
471 int qemu_listen_wrap(int sockfd, int backlog)
472 {
473 int ret;
474 SOCKET s = _get_osfhandle(sockfd);
475
476 if (s == INVALID_SOCKET) {
477 return -1;
478 }
479
480 ret = listen(s, backlog);
481 if (ret < 0) {
482 errno = socket_error();
483 }
484 return ret;
485 }
486
487
488 #undef bind
489 int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
490 socklen_t addrlen)
491 {
492 int ret;
493 SOCKET s = _get_osfhandle(sockfd);
494
495 if (s == INVALID_SOCKET) {
496 return -1;
497 }
498
499 ret = bind(s, addr, addrlen);
500 if (ret < 0) {
501 errno = socket_error();
502 }
503 return ret;
504 }
505
506 QEMU_USED EXCEPTION_DISPOSITION
507 win32_close_exception_handler(struct _EXCEPTION_RECORD *exception_record,
508 void *registration, struct _CONTEXT *context,
509 void *dispatcher)
510 {
511 return EXCEPTION_EXECUTE_HANDLER;
512 }
513
514 #undef close
515 int qemu_close_socket_osfhandle(int fd)
516 {
517 SOCKET s = _get_osfhandle(fd);
518 DWORD flags = 0;
519
520 /*
521 * If we were to just call _close on the descriptor, it would close the
522 * HANDLE, but it wouldn't free any of the resources associated to the
523 * SOCKET, and we can't call _close after calling closesocket, because
524 * closesocket has already closed the HANDLE, and _close would attempt to
525 * close the HANDLE again, resulting in a double free. We can however
526 * protect the HANDLE from actually being closed long enough to close the
527 * file descriptor, then close the socket itself.
528 */
529 if (!GetHandleInformation((HANDLE)s, &flags)) {
530 errno = EACCES;
531 return -1;
532 }
533
534 if (!SetHandleInformation((HANDLE)s, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE)) {
535 errno = EACCES;
536 return -1;
537 }
538
539 __try1(win32_close_exception_handler) {
540 /*
541 * close() returns EBADF since we PROTECT_FROM_CLOSE the underlying
542 * handle, but the FD is actually freed
543 */
544 if (close(fd) < 0 && errno != EBADF) {
545 return -1;
546 }
547 }
548 __except1 {
549 }
550
551 if (!SetHandleInformation((HANDLE)s, flags, flags)) {
552 errno = EACCES;
553 return -1;
554 }
555
556 return 0;
557 }
558
559 int qemu_close_wrap(int fd)
560 {
561 SOCKET s = INVALID_SOCKET;
562 int ret = -1;
563
564 if (!fd_is_socket(fd)) {
565 return close(fd);
566 }
567
568 s = _get_osfhandle(fd);
569 qemu_close_socket_osfhandle(fd);
570
571 ret = closesocket(s);
572 if (ret < 0) {
573 errno = socket_error();
574 }
575
576 return ret;
577 }
578
579
580 #undef socket
581 int qemu_socket_wrap(int domain, int type, int protocol)
582 {
583 SOCKET s;
584 int fd;
585
586 s = socket(domain, type, protocol);
587 if (s == -1) {
588 errno = socket_error();
589 return -1;
590 }
591
592 fd = _open_osfhandle(s, _O_BINARY);
593 if (fd < 0) {
594 closesocket(s);
595 /* _open_osfhandle may not set errno, and closesocket() may override it */
596 errno = ENOMEM;
597 }
598
599 return fd;
600 }
601
602
603 #undef accept
604 int qemu_accept_wrap(int sockfd, struct sockaddr *addr,
605 socklen_t *addrlen)
606 {
607 int fd;
608 SOCKET s = _get_osfhandle(sockfd);
609
610 if (s == INVALID_SOCKET) {
611 return -1;
612 }
613
614 s = accept(s, addr, addrlen);
615 if (s == -1) {
616 errno = socket_error();
617 return -1;
618 }
619
620 fd = _open_osfhandle(s, _O_BINARY);
621 if (fd < 0) {
622 closesocket(s);
623 /* _open_osfhandle may not set errno, and closesocket() may override it */
624 errno = ENOMEM;
625 }
626
627 return fd;
628 }
629
630
631 #undef shutdown
632 int qemu_shutdown_wrap(int sockfd, int how)
633 {
634 int ret;
635 SOCKET s = _get_osfhandle(sockfd);
636
637 if (s == INVALID_SOCKET) {
638 return -1;
639 }
640
641 ret = shutdown(s, how);
642 if (ret < 0) {
643 errno = socket_error();
644 }
645 return ret;
646 }
647
648
649 #undef ioctlsocket
650 int qemu_ioctlsocket_wrap(int fd, int req, void *val)
651 {
652 int ret;
653 SOCKET s = _get_osfhandle(fd);
654
655 if (s == INVALID_SOCKET) {
656 return -1;
657 }
658
659 ret = ioctlsocket(s, req, val);
660 if (ret < 0) {
661 errno = socket_error();
662 }
663 return ret;
664 }
665
666
667 #undef getsockopt
668 int qemu_getsockopt_wrap(int sockfd, int level, int optname,
669 void *optval, socklen_t *optlen)
670 {
671 int ret;
672 SOCKET s = _get_osfhandle(sockfd);
673
674 if (s == INVALID_SOCKET) {
675 return -1;
676 }
677
678 ret = getsockopt(s, level, optname, optval, optlen);
679 if (ret < 0) {
680 errno = socket_error();
681 }
682 return ret;
683 }
684
685
686 #undef setsockopt
687 int qemu_setsockopt_wrap(int sockfd, int level, int optname,
688 const void *optval, socklen_t optlen)
689 {
690 int ret;
691 SOCKET s = _get_osfhandle(sockfd);
692
693 if (s == INVALID_SOCKET) {
694 return -1;
695 }
696
697 ret = setsockopt(s, level, optname, optval, optlen);
698 if (ret < 0) {
699 errno = socket_error();
700 }
701 return ret;
702 }
703
704
705 #undef getpeername
706 int qemu_getpeername_wrap(int sockfd, struct sockaddr *addr,
707 socklen_t *addrlen)
708 {
709 int ret;
710 SOCKET s = _get_osfhandle(sockfd);
711
712 if (s == INVALID_SOCKET) {
713 return -1;
714 }
715
716 ret = getpeername(s, addr, addrlen);
717 if (ret < 0) {
718 errno = socket_error();
719 }
720 return ret;
721 }
722
723
724 #undef getsockname
725 int qemu_getsockname_wrap(int sockfd, struct sockaddr *addr,
726 socklen_t *addrlen)
727 {
728 int ret;
729 SOCKET s = _get_osfhandle(sockfd);
730
731 if (s == INVALID_SOCKET) {
732 return -1;
733 }
734
735 ret = getsockname(s, addr, addrlen);
736 if (ret < 0) {
737 errno = socket_error();
738 }
739 return ret;
740 }
741
742
743 #undef send
744 ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags)
745 {
746 int ret;
747 SOCKET s = _get_osfhandle(sockfd);
748
749 if (s == INVALID_SOCKET) {
750 return -1;
751 }
752
753 ret = send(s, buf, len, flags);
754 if (ret < 0) {
755 errno = socket_error();
756 }
757 return ret;
758 }
759
760
761 #undef sendto
762 ssize_t qemu_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,
763 const struct sockaddr *addr, socklen_t addrlen)
764 {
765 int ret;
766 SOCKET s = _get_osfhandle(sockfd);
767
768 if (s == INVALID_SOCKET) {
769 return -1;
770 }
771
772 ret = sendto(s, buf, len, flags, addr, addrlen);
773 if (ret < 0) {
774 errno = socket_error();
775 }
776 return ret;
777 }
778
779
780 #undef recv
781 ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags)
782 {
783 int ret;
784 SOCKET s = _get_osfhandle(sockfd);
785
786 if (s == INVALID_SOCKET) {
787 return -1;
788 }
789
790 ret = recv(s, buf, len, flags);
791 if (ret < 0) {
792 errno = socket_error();
793 }
794 return ret;
795 }
796
797
798 #undef recvfrom
799 ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
800 struct sockaddr *addr, socklen_t *addrlen)
801 {
802 int ret;
803 SOCKET s = _get_osfhandle(sockfd);
804
805 if (s == INVALID_SOCKET) {
806 return -1;
807 }
808
809 ret = recvfrom(s, buf, len, flags, addr, addrlen);
810 if (ret < 0) {
811 errno = socket_error();
812 }
813 return ret;
814 }
815
816 bool qemu_write_pidfile(const char *filename, Error **errp)
817 {
818 char buffer[128];
819 int len;
820 HANDLE file;
821 OVERLAPPED overlap;
822 BOOL ret;
823 memset(&overlap, 0, sizeof(overlap));
824
825 file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
826 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
827
828 if (file == INVALID_HANDLE_VALUE) {
829 error_setg(errp, "Failed to create PID file");
830 return false;
831 }
832 len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", (pid_t)getpid());
833 ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len,
834 NULL, &overlap);
835 CloseHandle(file);
836 if (ret == 0) {
837 error_setg(errp, "Failed to write PID file");
838 return false;
839 }
840 return true;
841 }
842
843 size_t qemu_get_host_physmem(void)
844 {
845 MEMORYSTATUSEX statex;
846 statex.dwLength = sizeof(statex);
847
848 if (GlobalMemoryStatusEx(&statex)) {
849 return statex.ullTotalPhys;
850 }
851 return 0;
852 }
853
854 int qemu_msync(void *addr, size_t length, int fd)
855 {
856 /**
857 * Perform the sync based on the file descriptor
858 * The sync range will most probably be wider than the one
859 * requested - but it will still get the job done
860 */
861 return qemu_fdatasync(fd);
862 }
863
864 void *qemu_win32_map_alloc(size_t size, HANDLE *h, Error **errp)
865 {
866 void *bits;
867
868 trace_win32_map_alloc(size);
869
870 *h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
871 size, NULL);
872 if (*h == NULL) {
873 error_setg_win32(errp, GetLastError(), "Failed to CreateFileMapping");
874 return NULL;
875 }
876
877 bits = MapViewOfFile(*h, FILE_MAP_ALL_ACCESS, 0, 0, size);
878 if (bits == NULL) {
879 error_setg_win32(errp, GetLastError(), "Failed to MapViewOfFile");
880 CloseHandle(*h);
881 return NULL;
882 }
883
884 return bits;
885 }
886
887 void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp)
888 {
889 trace_win32_map_free(ptr, h);
890
891 if (UnmapViewOfFile(ptr) == 0) {
892 error_setg_win32(errp, GetLastError(), "Failed to UnmapViewOfFile");
893 }
894 CloseHandle(h);
895 }
896
897 int qemu_shm_alloc(size_t size, Error **errp)
898 {
899 error_setg(errp, "Shared memory is not supported.");
900 return -1;
901 }
902
903 int qemu_ftruncate64(int fd, int64_t length)
904 {
905 LARGE_INTEGER li;
906 DWORD dw;
907 LONG high;
908 HANDLE h;
909 BOOL res;
910
911 if ((GetVersion()&0x80000000UL) && (length >> 32) != 0) {
912 return -1;
913 }
914
915 h = (HANDLE)_get_osfhandle(fd);
916
917 /* get current position, ftruncate do not change position */
918 li.HighPart = 0;
919 li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
920 if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
921 return -1;
922 }
923
924 high = length >> 32;
925 dw = SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN);
926 if (dw == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
927 return -1;
928 }
929 res = SetEndOfFile(h);
930
931 /* back to old position */
932 SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
933 return res ? 0 : -1;
934 }