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