1 #ifdef _WIN32
2
3 #include <windows.h>
4 #include <errno.h>
5 #include <io.h>
6
7 #include "mman.h"
8
9 #ifndef FILE_MAP_EXECUTE
10 #define FILE_MAP_EXECUTE 0x0020
11 #endif /* FILE_MAP_EXECUTE */
12
__map_mman_error(const DWORD err,const int deferr)13 static int __map_mman_error(const DWORD err, const int deferr)
14 {
15 if (err == 0)
16 return 0;
17 //TODO: implement
18 return err;
19 }
20
__map_mmap_prot_page(const int prot)21 static DWORD __map_mmap_prot_page(const int prot)
22 {
23 DWORD protect = 0;
24
25 if (prot == PROT_NONE)
26 return protect;
27
28 if ((prot & PROT_EXEC) != 0)
29 {
30 protect = ((prot & PROT_WRITE) != 0) ?
31 PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
32 }
33 else
34 {
35 protect = ((prot & PROT_WRITE) != 0) ?
36 PAGE_READWRITE : PAGE_READONLY;
37 }
38
39 return protect;
40 }
41
__map_mmap_prot_file(const int prot)42 static DWORD __map_mmap_prot_file(const int prot)
43 {
44 DWORD desiredAccess = 0;
45
46 if (prot == PROT_NONE)
47 return desiredAccess;
48
49 if ((prot & PROT_READ) != 0)
50 desiredAccess |= FILE_MAP_READ;
51 if ((prot & PROT_WRITE) != 0)
52 desiredAccess |= FILE_MAP_WRITE;
53 if ((prot & PROT_EXEC) != 0)
54 desiredAccess |= FILE_MAP_EXECUTE;
55
56 return desiredAccess;
57 }
58
mmap(void * addr,size_t len,int prot,int flags,int fildes,off_t off)59 void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
60 {
61 HANDLE fm, h;
62
63 void * map = MAP_FAILED;
64
65 #ifdef _MSC_VER
66 #pragma warning(push)
67 #pragma warning(disable: 4293)
68 #endif
69
70 const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ?
71 (DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
72 const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
73 (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
74 const DWORD protect = __map_mmap_prot_page(prot);
75 const DWORD desiredAccess = __map_mmap_prot_file(prot);
76
77 const off_t maxSize = off + (off_t)len;
78
79 const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ?
80 (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
81 const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
82 (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
83
84 #ifdef _MSC_VER
85 #pragma warning(pop)
86 #endif
87
88 errno = 0;
89
90 if (len == 0
91 /* Unsupported flag combinations */
92 || (flags & MAP_FIXED) != 0
93 /* Usupported protection combinations */
94 || prot == PROT_EXEC)
95 {
96 errno = EINVAL;
97 return MAP_FAILED;
98 }
99
100 h = ((flags & MAP_ANONYMOUS) == 0) ?
101 (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;
102
103 if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
104 {
105 errno = EBADF;
106 return MAP_FAILED;
107 }
108
109 fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
110
111 if (fm == NULL)
112 {
113 errno = __map_mman_error(GetLastError(), EPERM);
114 return MAP_FAILED;
115 }
116
117 map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
118
119 CloseHandle(fm);
120
121 if (map == NULL)
122 {
123 errno = __map_mman_error(GetLastError(), EPERM);
124 return MAP_FAILED;
125 }
126
127 return map;
128 }
129
munmap(void * addr,size_t len)130 int munmap(void *addr, size_t len)
131 {
132 if (UnmapViewOfFile(addr))
133 return 0;
134
135 errno = __map_mman_error(GetLastError(), EPERM);
136
137 return -1;
138 }
139
mprotect(void * addr,size_t len,int prot)140 int mprotect(void *addr, size_t len, int prot)
141 {
142 DWORD newProtect = __map_mmap_prot_page(prot);
143 DWORD oldProtect = 0;
144
145 if (VirtualProtect(addr, len, newProtect, &oldProtect))
146 return 0;
147
148 errno = __map_mman_error(GetLastError(), EPERM);
149
150 return -1;
151 }
152
msync(void * addr,size_t len,int flags)153 int msync(void *addr, size_t len, int flags)
154 {
155 if (FlushViewOfFile(addr, len))
156 return 0;
157
158 errno = __map_mman_error(GetLastError(), EPERM);
159
160 return -1;
161 }
162
mlock(const void * addr,size_t len)163 int mlock(const void *addr, size_t len)
164 {
165 if (VirtualLock((LPVOID)addr, len))
166 return 0;
167
168 errno = __map_mman_error(GetLastError(), EPERM);
169
170 return -1;
171 }
172
munlock(const void * addr,size_t len)173 int munlock(const void *addr, size_t len)
174 {
175 if (VirtualUnlock((LPVOID)addr, len))
176 return 0;
177
178 errno = __map_mman_error(GetLastError(), EPERM);
179
180 return -1;
181 }
182
183 #endif // _WIN32