source: trunk/src/kernel32/mmap.cpp@ 664

Last change on this file since 664 was 664, checked in by sandervl, 26 years ago

Memory mapped file changes

File size: 7.7 KB
Line 
1/* $Id: mmap.cpp,v 1.8 1999-08-24 18:46:40 sandervl Exp $ */
2
3/*
4 * Win32 Memory mapped file class
5 *
6 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * NOTE: Memory mapping DOES NOT work when kernel-mode code causes
9 * a pagefault in the memory mapped object. (exceptions aren't
10 * dispatched to our exception handler until after the kernel mode
11 * call returns (too late))
12 *
13 * NOTE: There's no easy way to determine which pages were modified. Temporary
14 * solution is to write all paged-in memory to disk.
15 *
16 * NOTE: Are apps allowed to change the protection flags of memory mapped pages?
17 * I'm assuming they aren't for now.
18 *
19 * TODO: Handles returned should be usable by all apis that accept file handles
20 *
21 * Project Odin Software License can be found in LICENSE.TXT
22 *
23 */
24#include <os2win.h>
25#include <stdlib.h>
26#include <string.h>
27#include <win\virtual.h>
28#include <vmutex.h>
29#include <handlemanager.h>
30#include "mmap.h"
31
32VMutex globalmapMutex;
33
34//******************************************************************************
35//TODO: sharing between processes
36//******************************************************************************
37Win32MemMap::Win32MemMap(HFILE hfile, ULONG size, ULONG fdwProtect, LPSTR lpszName)
38 : fMapped(FALSE), pMapping(NULL), mMapAccess(0), referenced(0)
39{
40 globalmapMutex.enter();
41 memmaps = this;
42 next = memmaps;
43 globalmapMutex.leave();
44
45 hMemFile = hfile;
46
47 mSize = size;
48 mProtFlags = fdwProtect;
49
50 if(lpszName) {
51 lpszMapName = (char *)malloc(strlen(lpszName)+1);
52 strcpy(lpszMapName, lpszName);
53 }
54 else lpszMapName = NULL;
55}
56//******************************************************************************
57//******************************************************************************
58BOOL Win32MemMap::Init(HANDLE hMemMap)
59{
60 mapMutex.enter();
61 if(hMemFile != -1)
62 {
63 if(DuplicateHandle(GetCurrentProcess(), hMemFile, GetCurrentProcess(),
64 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE)
65 {
66 dprintf(("Win32MemMap::Init: DuplicateHandle failed!"));
67 goto fail;
68 }
69 }
70 this->hMemMap = hMemMap;
71 mapMutex.leave();
72 return TRUE;
73fail:
74 mapMutex.leave();
75 return FALSE;
76}
77//******************************************************************************
78//******************************************************************************
79Win32MemMap::~Win32MemMap()
80{
81 unmapViewOfFile();
82 if(lpszMapName) {
83 free(lpszMapName);
84 }
85 mapMutex.enter();
86 if(pMapping) {
87 VirtualFree(pMapping, mSize, MEM_RELEASE);
88 pMapping = NULL;
89 }
90 if(hMemFile != -1) {
91 CloseHandle(hMemFile);
92 hMemFile = -1;
93 }
94 mapMutex.leave();
95
96 globalmapMutex.enter();
97 Win32MemMap *map = memmaps;
98
99 if(map == this) {
100 memmaps = next;
101 }
102 else {
103 while(map->next) {
104 if(map->next == this)
105 break;
106 map = map->next;
107 }
108 if(map->next) {
109 map->next = next;
110 }
111 else dprintf(("Win32MemMap::~Win32MemMap: map not found!! (%x)", this));
112 }
113 globalmapMutex.leave();
114}
115//******************************************************************************
116//******************************************************************************
117BOOL Win32MemMap::unmapViewOfFile()
118{
119 if(fMapped == FALSE)
120 return FALSE;
121
122 flushView(pMapping, mSize);
123 mapMutex.enter();
124 if(pMapping) {
125 VirtualFree(pMapping, mSize, MEM_RELEASE);
126 }
127 pMapping = NULL;
128 fMapped = FALSE;
129 mapMutex.leave();
130 return TRUE;
131}
132//******************************************************************************
133//******************************************************************************
134LPVOID Win32MemMap::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
135{
136 mapMutex.enter();
137 ULONG memFlags = (mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY));
138 ULONG fAlloc = 0;
139 LPVOID mapview;
140
141 if(fdwAccess & (FILE_MAP_WRITE|FILE_MAP_ALL_ACCESS) && !(mProtFlags & PAGE_READWRITE))
142 goto parmfail;
143 if(fdwAccess & FILE_MAP_READ && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
144 goto parmfail;
145 if(fdwAccess & FILE_MAP_COPY && !(mProtFlags & PAGE_WRITECOPY))
146 goto parmfail;
147
148 if(mProtFlags & SEC_COMMIT)
149 fAlloc |= MEM_COMMIT;
150 if(mProtFlags & SEC_RESERVE)
151 fAlloc |= MEM_RESERVE;
152
153 if(fMapped == FALSE) {//if not mapped, reserve/commit entire view
154 pMapping = VirtualAlloc(0, mSize, fAlloc, mProtFlags);
155 if(pMapping == NULL) {
156 dprintf(("Win32MemMap::mapFileView: VirtualAlloc %x %x %x failed!", mSize, fAlloc, memFlags));
157 goto fail;
158 }
159 fMapped = TRUE;
160 }
161 mapview = (LPVOID)((ULONG)pMapping + offset);
162 mapMutex.leave();
163 return mapview;
164
165parmfail:
166 dprintf(("Win32MemMap::mapFileView: ERROR_INVALID_PARAMETER"));
167 SetLastError(ERROR_INVALID_PARAMETER);
168fail:
169 mapMutex.leave();
170 return 0;
171}
172//******************************************************************************
173// NOTE: There's no easy way to determine which pages were modified. Temporary
174// solution is to write all paged-in memory to disk.
175//TODO: Are apps allowed to change the protection flags of memory mapped pages?
176// I'm assuming they aren't for now.
177//******************************************************************************
178BOOL Win32MemMap::flushView(LPVOID lpvBase, ULONG cbFlush)
179{
180 MEMORY_BASIC_INFORMATION memInfo;
181 ULONG nrpages, nrBytesWritten;
182 int i;
183
184 mapMutex.enter();
185 if(fMapped == FALSE)
186 goto parmfail;
187
188 if(lpvBase < pMapping || (ULONG)lpvBase+cbFlush > (ULONG)pMapping+mSize)
189 goto parmfail;
190
191 if(mProtFlags & PAGE_READONLY)
192 goto parmfail;
193
194 nrpages = cbFlush/PAGE_SIZE;
195 if(cbFlush & 0xFFF) nrpages++;
196
197 for(i=0;i<nrpages;i++) {
198 if(VirtualQuery((LPSTR)lpvBase+i*PAGE_SIZE, &memInfo, PAGE_SIZE) == 0) {
199 dprintf(("Win32MemMap::flushView: VirtualQuery (%x,%x) failed for %x", lpvBase, cbFlush, (ULONG)lpvBase+i*PAGE_SIZE));
200 goto fail;
201 }
202 //If a page is reserved or write protected, we won't bother flushing it to disk
203 if(memInfo.State & MEM_COMMIT &&
204 memInfo.AllocationProtect & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY))
205 {//committed and allowed for writing?
206 if(WriteFile(hMemFile, (LPSTR)lpvBase+i*PAGE_SIZE, PAGE_SIZE, &nrBytesWritten, NULL) == FALSE) {
207 dprintf(("Win32MemMap::flushView: WriteFile failed for %x", (ULONG)lpvBase+i*PAGE_SIZE));
208 goto fail;
209 }
210 if(nrBytesWritten != PAGE_SIZE) {
211 dprintf(("Win32MemMap::flushView: WriteFile didn't write all bytes for %x", (ULONG)lpvBase+i*PAGE_SIZE));
212 goto fail;
213 }
214 }
215 }
216 mapMutex.leave();
217 return TRUE;
218parmfail:
219 SetLastError(ERROR_INVALID_PARAMETER);
220 mapMutex.leave();
221 return FALSE;
222fail:
223 mapMutex.leave();
224 return FALSE;
225}
226//******************************************************************************
227//******************************************************************************
228Win32MemMap *Win32MemMap::findMap(LPSTR lpszName)
229{
230 globalmapMutex.enter();
231 Win32MemMap *map = memmaps;
232
233 if(map != NULL) {
234 while(map) {
235 if(map->lpszMapName && !strcmp(map->lpszMapName, lpszName))
236 break;
237 map = map->next;
238 }
239 }
240 globalmapMutex.leave();
241 dprintf(("Win32MemMap::findMap: couldn't find map %s", lpszName));
242 return map;
243}
244//******************************************************************************
245//******************************************************************************
246Win32MemMap *Win32MemMap::findMap(ULONG address)
247{
248 globalmapMutex.enter();
249 Win32MemMap *map = memmaps;
250
251 if(map != NULL) {
252 while(map) {
253 if(map->pMapping && (ULONG)map->pMapping <= address &&
254 (ULONG)map->pMapping + map->mSize > address)
255 {
256 break;
257 }
258 map = map->next;
259 }
260 }
261 globalmapMutex.leave();
262 return map;
263}
264//******************************************************************************
265//******************************************************************************
266Win32MemMap *Win32MemMap::memmaps = NULL;
Note: See TracBrowser for help on using the repository browser.