1 /**
2  * plat_mmap_windows.c
3  *
4  * Copyright (c) 2005, 2006, 2010, 2012-2014
5  *      libchewing Core Team. See ChangeLog for details.
6  *
7  * See the file "COPYING" for information on usage and redistribution
8  * of this file.
9  */
10 
11 #ifdef HAVE_CONFIG_H
12 #    include <config.h>
13 #endif
14 
15 #if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
16 
17 #    include "plat_mmap.h"
18 
19 /* set the mmap handle an invalid value */
plat_mmap_set_invalid(plat_mmap * handle)20 void plat_mmap_set_invalid(plat_mmap *handle)
21 {
22     /* check error(s) */
23     if (!handle)
24         return;
25 
26     handle->fd_file = NULL;
27     handle->address = NULL;
28     handle->fd_map = NULL;
29     handle->fAccessAttr = 0;
30 }
31 
32 /* verify if the mmap handle is valid */
plat_mmap_is_valid(plat_mmap * handle)33 int plat_mmap_is_valid(plat_mmap *handle)
34 {
35     /* check error(s) */
36     if (!handle)
37         return 0;
38 
39     return (int) (handle->fd_map != NULL);
40 }
41 
42 /* map a file into system meory, return the file size */
plat_mmap_create(plat_mmap * handle,const char * file,int fileAccessAttr)43 size_t plat_mmap_create(plat_mmap *handle, const char *file, int fileAccessAttr)
44 {
45     LARGE_INTEGER sizet;
46 
47     /* check error(s) */
48     if (!handle)
49         return 0;
50 
51     handle->fd_map = NULL;
52     handle->address = NULL;
53 
54     if (FLAG_ATTRIBUTE_READ & fileAccessAttr) {
55 #    ifdef _WIN32_WCE
56         handle->fd_file = CreateFileForMappingA(file,
57                                                 GENERIC_READ,
58                                                 FILE_SHARE_READ, NULL,
59                                                 OPEN_EXISTING,
60                                                 FILE_ATTRIBUTE_NORMAL, NULL);
61 #    else                       /* !_WIN32_WCE */
62         handle->fd_file = CreateFileA(file,
63                                       GENERIC_READ,
64                                       FILE_SHARE_READ,
65                                       NULL, OPEN_EXISTING,
66                                       FILE_ATTRIBUTE_READONLY |
67                                       FILE_FLAG_RANDOM_ACCESS, 0);
68 #    endif                      /* _WIN32_WCE */
69 
70         if (INVALID_HANDLE_VALUE == handle->fd_file)
71             return 0;
72 
73         sizet.LowPart = GetFileSize(handle->fd_file,
74                                     (LPDWORD) & sizet.HighPart);
75         handle->fd_map = CreateFileMappingA(handle->fd_file, NULL,
76                                             PAGE_READONLY,
77                                             sizet.HighPart, sizet.LowPart, 0);
78     } else {
79 #    ifdef _WIN32_WCE
80         handle->fd_file = CreateFileForMappingA(file,
81                                                 GENERIC_WRITE | GENERIC_READ,
82                                                 FILE_SHARE_WRITE, NULL,
83                                                 CREATE_ALWAYS,
84                                                 FILE_ATTRIBUTE_NORMAL, NULL);
85 #    else                       /* !_WIN32_WCE */
86         handle->fd_file = CreateFileA(file,
87                                       GENERIC_WRITE | GENERIC_READ,
88                                       FILE_SHARE_WRITE, NULL,
89                                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
90 #    endif                      /* _WIN32_WCE */
91 
92         if (INVALID_HANDLE_VALUE == handle->fd_file)
93             return 0;
94 
95         sizet.LowPart = 0;
96         sizet.HighPart = 1;
97         handle->fd_map = CreateFileMapping(handle->fd_file, NULL,
98                                            PAGE_READWRITE, 0,
99                                            sizet.LowPart, 0);
100         sizet.LowPart = 1024 * 1024 * 1024;
101         sizet.HighPart = 0;
102 
103         while (!handle->fd_map) {
104             DWORD error;
105 
106             handle->fd_map = CreateFileMapping(handle->fd_file, NULL,
107                                                PAGE_READWRITE, 0,
108                                                sizet.LowPart, 0);
109             error = GetLastError();
110 
111             if (ERROR_NOT_ENOUGH_MEMORY == error || ERROR_DISK_FULL == error)
112                 sizet.LowPart /= 2;
113             else
114                 break;
115         }
116     }
117 
118     handle->fAccessAttr = fileAccessAttr;
119 
120     if (FLAG_ATTRIBUTE_READ & fileAccessAttr ||
121         16 * 1024 * 1024 <= sizet.LowPart) {
122         if (handle->fd_map)
123             return (size_t) sizet.QuadPart;
124     }
125 
126     plat_mmap_close(handle);
127 
128     return 0;
129 }
130 
131 /* obtain the a view of the mapped file */
plat_mmap_set_view(plat_mmap * handle,size_t * offset,size_t * sizet)132 void *plat_mmap_set_view(plat_mmap *handle, size_t * offset, size_t * sizet)
133 {
134     LARGE_INTEGER t_offset;
135     LARGE_INTEGER t_sizet;
136     SYSTEM_INFO info;
137     size_t pagesize;
138     size_t edge;
139 
140     /* check error(s) */
141     if (!handle)
142         return NULL;
143 
144     if (handle->address)
145         UnmapViewOfFile(handle->address);
146 
147     GetSystemInfo(&info);
148     pagesize = info.dwAllocationGranularity;
149 
150     edge = (*sizet) + (*offset);
151     t_offset.QuadPart = (*offset) = (size_t) ((*offset) / pagesize) * pagesize;
152 
153     t_sizet.QuadPart = (*sizet) = edge - (*offset);
154 
155     if (FLAG_ATTRIBUTE_READ & handle->fAccessAttr) {
156         handle->address = MapViewOfFile(handle->fd_map,
157                                         FILE_MAP_READ,
158                                         t_offset.HighPart,
159                                         t_offset.LowPart, t_sizet.LowPart);
160     } else {
161         handle->address = MapViewOfFile(handle->fd_map,
162                                         FILE_MAP_WRITE,
163                                         t_offset.HighPart,
164                                         t_offset.LowPart, t_sizet.LowPart);
165     }
166 
167     return handle->address;
168 }
169 
170 /* close the mmap */
plat_mmap_close(plat_mmap * handle)171 void plat_mmap_close(plat_mmap *handle)
172 {
173     /* check error(s) */
174     if (!handle)
175         return;
176 
177     if (handle->address) {
178         UnmapViewOfFile(handle->address);
179         handle->address = NULL;
180     }
181 
182     if (handle->fd_map) {
183         CloseHandle(handle->fd_map);
184         handle->fd_map = NULL;
185     }
186 
187     if (INVALID_HANDLE_VALUE != handle->fd_file) {
188         CloseHandle(handle->fd_file);
189         handle->fd_file = INVALID_HANDLE_VALUE;
190     }
191 }
192 
193 /*  return page size*/
plat_mmap_get_page_size()194 unsigned int plat_mmap_get_page_size()
195 {
196     SYSTEM_INFO info;
197 
198     GetSystemInfo(&info);
199     return info.dwPageSize;
200 }
201 
plat_mmap_get_alloc_granularity()202 unsigned int plat_mmap_get_alloc_granularity()
203 {
204     SYSTEM_INFO info;
205 
206     GetSystemInfo(&info);
207     return info.dwAllocationGranularity;
208 }
209 
plat_mmap_unmap(plat_mmap * handle)210 void plat_mmap_unmap(plat_mmap *handle)
211 {
212     /* check error(s) */
213     if (!handle)
214         return;
215 
216     if (handle->address) {
217         UnmapViewOfFile(handle->address);
218         handle->address = NULL;
219     }
220 }
221 
222 #endif /* defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE) */
223