294f05894fa2c31155a6a880b3ce7ae31a2c9ea9
[pcsx_rearmed.git] / libpcsxcore / memmap_win32.c
1 #include <windows.h>
2 #include <errno.h>
3 #include <io.h>
4
5 #include "memmap.h"
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