source: trunk/src/kernel32/mmapdup.cpp@ 9946

Last change on this file since 9946 was 9946, checked in by sandervl, 22 years ago

memory map updates

File size: 9.0 KB
Line 
1/* $Id: mmapdup.cpp,v 1.1 2003-03-27 14:13:11 sandervl Exp $ */
2
3/*
4 * Win32 Memory mapped file & view classes
5 *
6 * Copyright 1999-2003 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: Are apps allowed to change the protection flags of memory mapped pages?
14 * I'm assuming they aren't for now.
15 *
16 * TODO: Handles returned should be usable by all apis that accept file handles
17 * TODO: Sharing memory mapped files between multiple processes
18 * TODO: Memory mapped files with views that extend the file (not 100% correct now)
19 * TODO: Suspend all threads when a page is committed (possible that another thread
20 * accesses the same memory before the page is read from disk
21 * TODO: File maps for new files (must select an initial size)!
22 *
23 * Project Odin Software License can be found in LICENSE.TXT
24 *
25 */
26#include <os2win.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <win\virtual.h>
31#include <odincrt.h>
32#include <handlemanager.h>
33#include "mmap.h"
34#include "oslibdos.h"
35#include "oslibmem.h"
36#include <winimagepeldr.h>
37#include <custombuild.h>
38
39#define DBG_LOCALLOG DBG_mmapdup
40#include "dbglocal.h"
41
42
43//******************************************************************************
44// Class Win32MemMapDup
45//
46// Duplicate memory mapping class (duplicate map with different protection flags
47// associated with an existing memory map)
48//
49//******************************************************************************
50Win32MemMapDup::Win32MemMapDup(Win32MemMap *parent, HFILE hFile, ULONG size,
51 ULONG fdwProtect, LPSTR lpszName) :
52 Win32MemMap(hFile, size, fdwProtect, lpszName)
53{
54 this->parent = parent;
55 hOrgMemFile = -1; //we're a duplicate
56 parent->AddRef();
57}
58//******************************************************************************
59//******************************************************************************
60Win32MemMapDup::~Win32MemMapDup()
61{
62 parent->Release();
63}
64//******************************************************************************
65//******************************************************************************
66BOOL Win32MemMapDup::Init(DWORD aMSize)
67{
68 //copy values from original map
69 mSize = parent->getMapSize();
70 hMemFile = parent->getFileHandle();
71
72 //If the parent is a readonly map and we allow write access, then we must
73 //override our parent's protection flags
74 if((getProtFlags() & PAGE_READWRITE) && (parent->getProtFlags() == PAGE_READONLY))
75 {
76 parent->setProtFlags(PAGE_READWRITE);
77 }
78 return TRUE;
79}
80//******************************************************************************
81//******************************************************************************
82BOOL Win32MemMapDup::flushView(ULONG viewaddr, ULONG offset, ULONG cbFlush)
83{
84 return parent->flushView(viewaddr, offset, cbFlush);
85}
86//******************************************************************************
87// Win32MemMapDup::mapViewOfFile
88//
89// Map the view identified by addr. Create a view with our parent as the parent
90// map and ourselves as the ower.
91//
92// View parent = memory map that contains the original memory map
93// View owner = duplicate memory map that created this view (can be NULL)
94//
95// Parameters:
96//
97// ULONG size - size of view
98// ULONG offset - offset in memory map
99// ULONG fdwAccess - access flags
100// FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_COPY
101// FILE_MAP_ALL_ACCESS
102//
103// Returns:
104// <>NULL - success, view address
105// NULL - failure
106//
107//******************************************************************************
108LPVOID Win32MemMapDup::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
109{
110 DWORD processId = GetCurrentProcessId();
111
112 mapMutex.enter();
113 ULONG memFlags = (mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY));
114 Win32MemMapView *mapview;
115
116 //@@@PH: if(fdwAccess & ~(FILE_MAP_WRITE|FILE_MAP_READ|FILE_MAP_COPY))
117 // Docs say FILE_MAP_ALL_ACCESS is same as FILE_MAP_WRITE. Doesn't match reality though.
118 if(fdwAccess & ~FILE_MAP_ALL_ACCESS)
119 goto parmfail;
120 if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE))
121 goto parmfail;
122 if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
123 goto parmfail;
124
125 if (fdwAccess != FILE_MAP_ALL_ACCESS)
126 if((fdwAccess & FILE_MAP_COPY) && !(mProtFlags & PAGE_WRITECOPY))
127 goto parmfail;
128
129 if(offset+size > mSize && (!(fdwAccess & FILE_MAP_WRITE) || hMemFile == -1))
130 goto parmfail;
131
132 //SvL: TODO: Doesn't work for multiple views
133 if(offset+size > mSize) {
134 mSize = offset+size;
135 }
136
137
138 if(parent->allocateMap() == FALSE) {
139 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
140 goto fail;
141 }
142
143 mapview = new Win32MemMapView(parent, offset, (size == 0) ? (mSize - offset) : size, fdwAccess, this);
144 if(mapview == NULL) {
145 goto fail;
146 }
147 if(mapview->everythingOk() == FALSE) {
148 dprintf(("Win32MemMapDup::mapViewOfFile: !mapview->everythingOk"));
149 delete mapview;
150 goto fail;
151 }
152
153 mapMutex.leave();
154 SetLastError(ERROR_SUCCESS);
155 return mapview->getViewAddr();
156
157parmfail:
158 dprintf(("Win32MemMapDup::mapViewOfFile: invalid parameter (ERROR_ACCESS_DENIED)"));
159 //NT4 SP6 returns ERROR_ACCESS_DENIED for most invalid parameters
160 SetLastError(ERROR_ACCESS_DENIED);
161fail:
162 mapMutex.leave();
163 return 0;
164}
165//******************************************************************************
166// Win32MemMapDup::unmapViewOfFile
167//
168// Unmap the view identified by addr by calling the parent and cleaning up
169// the duplicate object
170//
171// Parameters:
172//
173// LPVOID addr - view address; doesn't need to be the address
174// returned by MapViewOfFile(Ex) (as MSDN clearly says);
175// can be any address within the view range
176//
177// Returns:
178// TRUE - success
179// FALSE - failure
180//
181//******************************************************************************
182BOOL Win32MemMapDup::unmapViewOfFile(LPVOID addr)
183{
184 BOOL ret;
185
186 dprintf(("Win32MemMapDup::unmapViewOfFile %x (nrmaps=%d)", addr, nrMappings));
187
188 mapMutex.enter();
189
190 if(nrMappings == 0)
191 goto fail;
192
193 ret = parent->unmapViewOfFile(addr);
194
195 mapMutex.leave();
196
197 SetLastError(ERROR_SUCCESS);
198 return TRUE;
199fail:
200 mapMutex.leave();
201 SetLastError(ERROR_INVALID_ADDRESS);
202 return FALSE;
203}
204//******************************************************************************
205// Win32MemMapDup::commitPage
206//
207// Handle a pagefault for a duplicate view
208//
209// Parameters:
210//
211// ULONG ulFaultAddr - exception address
212// ULONG ulOffset - offset in memory map
213// BOOL fWriteAccess - TRUE -> write exception
214// FALSE -> read exception
215//
216// Returns:
217// TRUE - success
218// FALSE - failure
219//
220//******************************************************************************
221BOOL Win32MemMapDup::commitPage(ULONG ulFaultAddr, ULONG offset, BOOL fWriteAccess, int nrpages)
222{
223 return parent->commitPage(ulFaultAddr, offset, fWriteAccess, nrpages);
224}
225//******************************************************************************
226// Win32MemMapDup::commitGuardPage
227//
228// Handle a guard page exception
229//
230// Parameters:
231//
232// ULONG ulFaultAddr - exception address
233// ULONG ulOffset - offset in memory map
234// BOOL fWriteAccess - TRUE -> write exception
235// FALSE -> read exception
236//
237// Returns:
238// TRUE - success
239// FALSE - failure
240//
241//******************************************************************************
242BOOL Win32MemMapDup::commitGuardPage(ULONG ulFaultAddr, ULONG ulOffset,
243 BOOL fWriteAccess)
244{
245 return parent->commitGuardPage(ulFaultAddr, ulOffset, fWriteAccess);
246}
247//******************************************************************************
248// Win32MemMapDup::invalidatePages
249//
250// Invalidate map pages. (called by WriteFile)
251//
252// Parameters:
253//
254// ULONG offset - offset in memory map
255// ULONG size - invalid range size
256//
257// Returns:
258// TRUE - success
259// FALSE - failure
260//
261//******************************************************************************
262BOOL Win32MemMapDup::invalidatePages(ULONG offset, ULONG size)
263{
264 return parent->invalidatePages(offset, size);
265}
266//******************************************************************************
267//******************************************************************************
Note: See TracBrowser for help on using the repository browser.