source: branches/gcc-kmk/src/kernel32/mmapdup.cpp@ 21716

Last change on this file since 21716 was 21716, checked in by dmik, 13 years ago

Place local includes in quotes.

GCC doesn't search for <> includes in the current directory (intentionally).

File size: 9.3 KB
Line 
1/* $Id: mmapdup.cpp,v 1.3 2003-05-06 12:06: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, HANDLE 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 //can't use hMemFile or else we'll close this file handle in the memmap dtor!!
71 hDupMemFile = parent->getFileHandle();
72
73 //If the parent is a readonly map and we allow write access, then we must
74 //override our parent's protection flags
75 if((getProtFlags() & PAGE_READWRITE) && (parent->getProtFlags() == PAGE_READONLY))
76 {
77 parent->setProtFlags(PAGE_READWRITE);
78 }
79 return TRUE;
80}
81//******************************************************************************
82//******************************************************************************
83BOOL Win32MemMapDup::flushView(ULONG viewaddr, ULONG offset, ULONG cbFlush)
84{
85 return parent->flushView(viewaddr, offset, cbFlush);
86}
87//******************************************************************************
88// Win32MemMapDup::mapViewOfFile
89//
90// Map the view identified by addr. Create a view with our parent as the parent
91// map and ourselves as the ower.
92//
93// View parent = memory map that contains the original memory map
94// View owner = duplicate memory map that created this view (can be NULL)
95//
96// Parameters:
97//
98// ULONG size - size of view
99// ULONG offset - offset in memory map
100// ULONG fdwAccess - access flags
101// FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_COPY
102// FILE_MAP_ALL_ACCESS
103//
104// Returns:
105// <>NULL - success, view address
106// NULL - failure
107//
108//******************************************************************************
109LPVOID Win32MemMapDup::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
110{
111 DWORD processId = GetCurrentProcessId();
112
113 mapMutex.enter();
114 ULONG memFlags = (mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY));
115 Win32MemMapView *mapview;
116
117 //@@@PH: if(fdwAccess & ~(FILE_MAP_WRITE|FILE_MAP_READ|FILE_MAP_COPY))
118 // Docs say FILE_MAP_ALL_ACCESS is same as FILE_MAP_WRITE. Doesn't match reality though.
119 if(fdwAccess & ~FILE_MAP_ALL_ACCESS)
120 goto parmfail;
121 if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE))
122 goto parmfail;
123 if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
124 goto parmfail;
125
126 if (fdwAccess != FILE_MAP_ALL_ACCESS)
127 if((fdwAccess & FILE_MAP_COPY) && !(mProtFlags & PAGE_WRITECOPY))
128 goto parmfail;
129
130 if(offset+size > mSize && (!(fdwAccess & FILE_MAP_WRITE) || hDupMemFile == -1))
131 goto parmfail;
132
133 //SvL: TODO: Doesn't work for multiple views
134 if(offset+size > mSize) {
135 mSize = offset+size;
136 }
137
138
139 if(parent->allocateMap() == FALSE) {
140 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
141 goto fail;
142 }
143
144 mapview = new Win32MemMapView(parent, offset, (size == 0) ? (mSize - offset) : size, fdwAccess, this);
145 if(mapview == NULL) {
146 goto fail;
147 }
148 if(mapview->everythingOk() == FALSE) {
149 dprintf(("Win32MemMapDup::mapViewOfFile: !mapview->everythingOk"));
150 delete mapview;
151 goto fail;
152 }
153
154 mapMutex.leave();
155 SetLastError(ERROR_SUCCESS);
156 return mapview->getViewAddr();
157
158parmfail:
159 dprintf(("Win32MemMapDup::mapViewOfFile: invalid parameter (ERROR_ACCESS_DENIED)"));
160 //NT4 SP6 returns ERROR_ACCESS_DENIED for most invalid parameters
161 SetLastError(ERROR_ACCESS_DENIED);
162fail:
163 mapMutex.leave();
164 return 0;
165}
166//******************************************************************************
167// Win32MemMapDup::unmapViewOfFile
168//
169// Unmap the view identified by addr by calling the parent and cleaning up
170// the duplicate object
171//
172// Parameters:
173//
174// LPVOID addr - view address; doesn't need to be the address
175// returned by MapViewOfFile(Ex) (as MSDN clearly says);
176// can be any address within the view range
177//
178// Returns:
179// TRUE - success
180// FALSE - failure
181//
182//******************************************************************************
183BOOL Win32MemMapDup::unmapViewOfFile(LPVOID addr)
184{
185 BOOL ret;
186
187 dprintf(("Win32MemMapDup::unmapViewOfFile %x (nrmaps=%d)", addr, nrMappings));
188
189 mapMutex.enter();
190
191 if(nrMappings == 0)
192 goto fail;
193
194 ret = parent->unmapViewOfFile(addr);
195
196 mapMutex.leave();
197
198 SetLastError(ERROR_SUCCESS);
199 return TRUE;
200fail:
201 mapMutex.leave();
202 SetLastError(ERROR_INVALID_ADDRESS);
203 return FALSE;
204}
205//******************************************************************************
206// Win32MemMapDup::commitPage
207//
208// Handle a pagefault for a duplicate view
209//
210// Parameters:
211//
212// ULONG ulFaultAddr - exception address
213// ULONG ulOffset - offset in memory map
214// BOOL fWriteAccess - TRUE -> write exception
215// FALSE -> read exception
216//
217// Returns:
218// TRUE - success
219// FALSE - failure
220//
221//******************************************************************************
222BOOL Win32MemMapDup::commitPage(ULONG ulFaultAddr, ULONG offset, BOOL fWriteAccess, int nrpages)
223{
224 if(mProtFlags & PAGE_WRITECOPY)
225 {//this is a COW map, call commitGuardPage
226 return commitGuardPage(ulFaultAddr, offset, fWriteAccess);
227 }
228 return parent->commitPage(ulFaultAddr, offset, fWriteAccess, nrpages);
229}
230//******************************************************************************
231// Win32MemMapDup::commitGuardPage
232//
233// Handle a guard page exception for a copy-on-write view
234//
235// Parameters:
236//
237// ULONG ulFaultAddr - exception address
238// ULONG ulOffset - offset in memory map
239// BOOL fWriteAccess - TRUE -> write exception
240// FALSE -> read exception
241//
242// Returns:
243// TRUE - success
244// FALSE - failure
245//
246//******************************************************************************
247BOOL Win32MemMapDup::commitGuardPage(ULONG ulFaultAddr, ULONG ulOffset,
248 BOOL fWriteAccess)
249{
250 return parent->commitGuardPage(ulFaultAddr, ulOffset, fWriteAccess);
251}
252//******************************************************************************
253// Win32MemMapDup::invalidatePages
254//
255// Invalidate map pages. (called by WriteFile)
256//
257// Parameters:
258//
259// ULONG offset - offset in memory map
260// ULONG size - invalid range size
261//
262// Returns:
263// TRUE - success
264// FALSE - failure
265//
266//******************************************************************************
267BOOL Win32MemMapDup::invalidatePages(ULONG offset, ULONG size)
268{
269 return parent->invalidatePages(offset, size);
270}
271//******************************************************************************
272//******************************************************************************
Note: See TracBrowser for help on using the repository browser.