Home | History | Annotate | Download | only in mman-win32
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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