diff options
Diffstat (limited to 'src/platform/windows.c')
| -rw-r--r-- | src/platform/windows.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/platform/windows.c b/src/platform/windows.c new file mode 100644 index 0000000..fb37837 --- /dev/null +++ b/src/platform/windows.c @@ -0,0 +1,108 @@ +/* mmap() replacement for Windows + * + * Author: Mike Frysinger <vapier@gentoo.org> + * Modified to not leak the CreateFileMapping-Handle, as well as fixed MAP_PRIVATE to actually work by Markus Mittendrein + * Placed into the public domain + */ + +/* References: + * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx + * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx + * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx + * https://source.winehq.org/source/dlls/kernel32/virtual.c#0356 + * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx + */ + +#include <io.h> +#include <windows.h> +#include <sys/types.h> + +#include <stdio.h> + +#include "platform.h" + +#ifdef __USE_FILE_OFFSET64 +# define DWORD_HI(x) (x >> 32) +# define DWORD_LO(x) ((x) & 0xffffffff) +#else +# define DWORD_HI(x) (0) +# define DWORD_LO(x) (x) +#endif + +void *cc4group_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset, void** extra) +{ + (void)start; + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return MAP_FAILED; + if (fd == -1) { + if (!(flags & MAP_ANON) || offset) + return MAP_FAILED; + } else if (flags & MAP_ANON) + return MAP_FAILED; + + DWORD flProtect; + if (prot & PROT_WRITE) { + if (prot & PROT_EXEC) { + if(prot & MAP_PRIVATE) + flProtect = PAGE_EXECUTE_WRITECOPY; + else + flProtect = PAGE_EXECUTE_READWRITE; + } + else { + if(prot & MAP_PRIVATE) + flProtect = PAGE_WRITECOPY; + else + flProtect = PAGE_READWRITE; + } + } else if (prot & PROT_EXEC) { + if (prot & PROT_READ) + flProtect = PAGE_EXECUTE_READ; + else if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE; + } else + flProtect = PAGE_READONLY; + + off_t end = length + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + if (h == NULL) + return MAP_FAILED; + + DWORD dwDesiredAccess; + if (flags & MAP_PRIVATE) + dwDesiredAccess = FILE_MAP_COPY; + else if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + if (flags & MAP_PRIVATE) + dwDesiredAccess |= FILE_MAP_COPY; + + void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + if (ret == NULL) { + CloseHandle(h); + ret = MAP_FAILED; + } + + *extra = h; + + return ret; +} + +int cc4group_munmap(void *addr, size_t length, void* extra) +{ + (void)length; + UnmapViewOfFile(addr); + CloseHandle(extra); + /* ruh-ro, we leaked handle from CreateFileMapping() ... */ + return 0; +} + +#undef DWORD_HI +#undef DWORD_LO |
