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

Last change on this file since 8913 was 8913, checked in by sandervl, 23 years ago

Enhanced PE loader class to support files with PE image starting at an offset ..= 0 (custom build) & Fixes for memory map view with offset

File size: 27.2 KB
Line 
1/* $Id: mmap.cpp,v 1.59 2002-07-23 13:51:47 sandervl Exp $ */
2
3/*
4 * Win32 Memory mapped file & view classes
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: 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_mmap
40#include "dbglocal.h"
41
42//Global DLL Data
43#pragma data_seg(_GLOBALDATA)
44Win32MemMap *Win32MemMap::memmaps = NULL;
45CRITICAL_SECTION_OS2 globalmapcritsect = {0};
46#pragma data_seg()
47Win32MemMapView *Win32MemMapView::mapviews = NULL;
48
49
50static char *pszMMapSemName = NULL;
51
52//******************************************************************************
53//******************************************************************************
54void WIN32API SetCustomMMapSemName(LPSTR pszSemName)
55{
56 pszMMapSemName = pszSemName;
57}
58//******************************************************************************
59//******************************************************************************
60void InitializeMemMaps()
61{
62 if(globalmapcritsect.hmtxLock == 0) {
63 dprintf(("InitializeMemMaps -> create shared critical section"));
64 DosInitializeCriticalSection(&globalmapcritsect, (pszMMapSemName) ? pszMMapSemName : MEMMAP_CRITSECTION_NAME);
65 }
66 else {
67 dprintf(("InitializeMemMaps -> access shared critical section"));
68 DosAccessCriticalSection(&globalmapcritsect, MEMMAP_CRITSECTION_NAME);
69 }
70}
71//******************************************************************************
72//TODO: sharing between processes
73//******************************************************************************
74Win32MemMap::Win32MemMap(HFILE hfile, ULONG size, ULONG fdwProtect, LPSTR lpszName)
75 : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), image(0)
76{
77 DosEnterCriticalSection(&globalmapcritsect);
78 next = memmaps;
79 memmaps = this;
80 DosLeaveCriticalSection(&globalmapcritsect);
81
82 hMemFile = hfile;
83
84 mSize = size;
85 mProtFlags = fdwProtect;
86 mProcessId = GetCurrentProcessId();
87
88 if(lpszName) {
89 lpszMapName = (char *)_smalloc(strlen(lpszName)+1);
90 strcpy(lpszMapName, lpszName);
91 }
92 else lpszMapName = NULL;
93}
94//******************************************************************************
95//Map constructor used for executable image maps (only used internally)
96//******************************************************************************
97Win32MemMap::Win32MemMap(Win32PeLdrImage *pImage, ULONG baseAddress, ULONG size)
98 : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), image(0)
99{
100 DosEnterCriticalSection(&globalmapcritsect);
101 next = memmaps;
102 memmaps = this;
103 DosLeaveCriticalSection(&globalmapcritsect);
104
105 hMemFile = -1;
106
107 mSize = size;
108 mProtFlags = PAGE_READWRITE;
109 mProcessId = GetCurrentProcessId();
110
111 pMapping = (LPVOID)baseAddress;
112
113 image = pImage;
114 lpszMapName= NULL;
115}
116//******************************************************************************
117//******************************************************************************
118BOOL Win32MemMap::Init(DWORD aMSize)
119{
120 mapMutex.enter();
121 if(hMemFile != -1)
122 {
123#if 0
124 if(DuplicateHandle(GetCurrentProcess(), hMemFile, GetCurrentProcess(),
125 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE)
126#else
127 DWORD dwOdinOptions;
128
129 if(!(mProtFlags & PAGE_READWRITE)) {
130 dwOdinOptions = DUPLICATE_ACCESS_READ | DUPLICATE_SHARE_DENYNONE;
131 }
132 else dwOdinOptions = DUPLICATE_ACCESS_READWRITE | DUPLICATE_SHARE_DENYNONE;
133
134 if(HMDuplicateHandleOdin(GetCurrentProcess(), hMemFile, GetCurrentProcess(),
135 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS, dwOdinOptions) == FALSE)
136#endif
137 {
138 dprintf(("Win32MemMap::Init: DuplicateHandle failed!"));
139 goto fail;
140 }
141 mSize = SetFilePointer(hMemFile, 0, NULL, FILE_BEGIN);
142 mSize = SetFilePointer(hMemFile, 0, NULL, FILE_END);
143 if(mSize == -1) {
144 dprintf(("Win32MemMap::init: SetFilePointer failed to set pos end"));
145 goto fail;
146 }
147 if (mSize < aMSize)
148 {
149 dprintf(("Win32MemMap::init: file size %d, memory map size %d", mSize, aMSize));
150 //Froloff: Need to check if exist the possibility of file to memory
151 // mapping not from the beginning of file
152 mSize = SetFilePointer(hMemFile, aMSize, NULL, FILE_BEGIN);
153 // Commit filesize changes onto disk
154 SetEndOfFile(hMemFile);
155 }
156#if 0
157 //SvL: Temporary limitation of size (Warp Server Advanced doesn't allow
158 // one to reserve more than 450 MB (unless you override the virtual
159 // memory max limit) of continuous memory; (Warp 4 much less))
160 if(mSize > 64*1024*1024) {
161 mSize = 64*1024*1024;
162 }
163#endif
164 }
165
166 dprintf(("CreateFileMappingA for file %x, prot %x size %d, name %s", hMemFile, mProtFlags, mSize, lpszMapName));
167 mapMutex.leave();
168 return TRUE;
169fail:
170 mapMutex.leave();
171 return FALSE;
172}
173//******************************************************************************
174//******************************************************************************
175Win32MemMap::~Win32MemMap()
176{
177 Win32MemMapView::deleteViews(this); //delete all views of our memory mapped file
178
179 dprintf(("Win32MemMap dtor: deleting view %x %x", pMapping, mSize));
180
181 mapMutex.enter();
182 if(lpszMapName) {
183 free(lpszMapName);
184 }
185 if(pMapping && !image) {
186 if(lpszMapName) {
187 OSLibDosFreeMem(pMapping);
188 }
189 else VirtualFree(pMapping, 0, MEM_RELEASE);
190
191 pMapping = NULL;
192 }
193 if(hMemFile != -1) {
194 dprintf(("Win32MemMap dtor: closing memory file %x", hMemFile));
195 CloseHandle(hMemFile);
196 hMemFile = -1;
197 }
198 mapMutex.leave();
199
200 DosEnterCriticalSection(&globalmapcritsect);
201 Win32MemMap *map = memmaps;
202
203 if(map == this) {
204 memmaps = next;
205 }
206 else {
207 while(map->next) {
208 if(map->next == this)
209 break;
210 map = map->next;
211 }
212 if(map->next) {
213 map->next = next;
214 }
215 else dprintf(("Win32MemMap::~Win32MemMap: map not found!! (%x)", this));
216 }
217 DosLeaveCriticalSection(&globalmapcritsect);
218}
219//******************************************************************************
220//If memory map has no more views left, then we can safely delete it when
221//it's handle is closed
222//******************************************************************************
223void Win32MemMap::Release()
224{
225 dprintf(("Win32MemMap::Release %s (%d)", lpszMapName, referenced-1));
226 --referenced;
227 if(nrMappings == 0 && referenced == 0) {
228 delete this;
229 }
230}
231//******************************************************************************
232//We determine whether a page has been modified by checking it's protection flags
233//If the write flag is set, this means commitPage had to enable this due to a pagefault
234//(all pages are readonly until the app tries to write to it)
235//******************************************************************************
236BOOL Win32MemMap::commitPage(ULONG offset, BOOL fWriteAccess, int nrpages)
237{
238 MEMORY_BASIC_INFORMATION memInfo;
239 LPVOID lpPageFaultAddr = (LPVOID)((ULONG)pMapping + offset);
240 DWORD pageAddr = (DWORD)lpPageFaultAddr & ~0xFFF;
241 DWORD oldProt, newProt, nrBytesRead, size;
242 int i;
243
244// mapMutex.enter();
245
246 if(image) {
247 return image->commitPage(pageAddr, fWriteAccess);
248 }
249 newProt = mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY);
250
251 dprintf(("Win32MemMap::commitPage %x (faultaddr %x)", pageAddr, lpPageFaultAddr));
252 if(hMemFile != -1)
253 {
254 int faultsize = nrpages*PAGE_SIZE;
255
256 offset = pageAddr - (ULONG)pMapping;
257 if(offset + faultsize > mSize) {
258 faultsize = mSize - offset;
259 }
260
261 while(faultsize) {
262 if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
263 dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed for %x", pageAddr, nrpages*PAGE_SIZE));
264 goto fail;
265 }
266 memInfo.RegionSize = min(memInfo.RegionSize, faultsize);
267 //Only changes the state of the pages with the same attribute flags
268 //(returned in memInfo.RegionSize)
269 //If it's smaller than the mNrPages, it simply means one or more of the
270 //other pages have already been committed
271 if(!(memInfo.State & MEM_COMMIT))
272 {
273 if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, PAGE_READWRITE) == FALSE) {
274 goto fail;
275 }
276 offset = pageAddr - (ULONG)pMapping;
277 size = memInfo.RegionSize;
278 if(offset + size > mSize) {
279 dprintf(("Adjusting size from %d to %d", size, mSize - offset));
280 size = mSize - offset;
281 }
282 if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
283 dprintf(("Win32MemMap::commitPage: SetFilePointer failed to set pos to %x", offset));
284 goto fail;
285 }
286 if(ReadFile(hMemFile, (LPSTR)pageAddr, size, &nrBytesRead, NULL) == FALSE) {
287 dprintf(("Win32MemMap::commitPage: ReadFile failed for %x", pageAddr));
288 goto fail;
289 }
290 if(nrBytesRead != size) {
291 dprintf(("Win32MemMap::commitPage: ReadFile didn't read all bytes for %x", pageAddr));
292 goto fail;
293 }
294 if(newProt != PAGE_READWRITE) {
295 if(VirtualProtect((LPVOID)pageAddr, memInfo.RegionSize, newProt, &oldProt) == FALSE) {
296 goto fail;
297 }
298 }
299 }
300 faultsize -= memInfo.RegionSize;
301 pageAddr += memInfo.RegionSize;
302 }
303 }
304 else {
305 ULONG sizeleft = nrpages*PAGE_SIZE;
306 while(sizeleft)
307 {
308 if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
309 dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed", pageAddr, sizeleft));
310 goto fail;
311 }
312 memInfo.RegionSize = min(memInfo.RegionSize, sizeleft);
313
314 if(!(memInfo.State & MEM_COMMIT))
315 {//if it's already committed, then the app tried to write to it
316 if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, newProt) == FALSE)
317 goto fail;
318 }
319 memInfo.RegionSize = (memInfo.RegionSize+PAGE_SIZE-1) & ~0xfff;
320 pageAddr += memInfo.RegionSize;
321 sizeleft -= memInfo.RegionSize;
322 }
323 }
324
325// mapMutex.leave();
326 return TRUE;
327fail:
328// mapMutex.leave();
329 return FALSE;
330}
331//******************************************************************************
332//******************************************************************************
333BOOL Win32MemMap::unmapViewOfFile(Win32MemMapView *view)
334{
335 dprintf(("Win32MemMap::unmapViewOfFile %x (nrmaps=%d)", view, nrMappings));
336 mapMutex.enter();
337
338 if(nrMappings == 0)
339 goto fail;
340
341 delete view;
342
343 if(--nrMappings == 0) {
344 VirtualFree(pMapping, 0, MEM_RELEASE);
345 pMapping = NULL;
346 }
347 mapMutex.leave();
348
349 //if there are no more mappings left and the memory map's handle has been
350 //closed, then delete the object
351 if(nrMappings == 0 && referenced == 0) {
352 delete this;
353 }
354 return TRUE;
355fail:
356 mapMutex.leave();
357 if(nrMappings == 0 && referenced == 0) {
358 delete this;
359 }
360 return FALSE;
361}
362//******************************************************************************
363//******************************************************************************
364LPVOID Win32MemMap::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
365{
366 DWORD processId = GetCurrentProcessId();
367
368 mapMutex.enter();
369 ULONG memFlags = (mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY));
370 ULONG fAlloc = 0;
371 Win32MemMapView *mapview;
372
373 //@@@PH: if(fdwAccess & ~(FILE_MAP_WRITE|FILE_MAP_READ|FILE_MAP_COPY))
374 // Docs say FILE_MAP_ALL_ACCESS is same as FILE_MAP_WRITE. Doesn't match reality though.
375 if(fdwAccess & ~FILE_MAP_ALL_ACCESS)
376 goto parmfail;
377 if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE))
378 goto parmfail;
379 if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
380 goto parmfail;
381
382 //@@@PH
383 if (fdwAccess != FILE_MAP_ALL_ACCESS)
384 if((fdwAccess & FILE_MAP_COPY) && !(mProtFlags & PAGE_WRITECOPY))
385 goto parmfail;
386
387 if(offset+size > mSize && (!(fdwAccess & FILE_MAP_WRITE) || hMemFile == -1))
388 goto parmfail;
389
390 //SvL: TODO: Doesn't work for multiple views
391 if(offset+size > mSize) {
392 mSize = offset+size;
393 }
394
395//TODO: If committed, read file into memory
396#if 0
397 if(mProtFlags & SEC_COMMIT)
398 fAlloc |= MEM_COMMIT;
399 else
400 if(mProtFlags & SEC_RESERVE)
401 fAlloc |= MEM_RESERVE;
402#else
403 fAlloc = MEM_RESERVE;
404#endif
405
406 //Memory has already been allocated for executable image maps (only used internally)
407 if(!pMapping && nrMappings == 0) {//if not mapped, reserve/commit entire view
408 //SvL: Always read/write access or else ReadFile will crash once we
409 // start committing pages.
410 // This is most likely an OS/2 bug and doesn't happen in Aurora
411 // when allocating memory with the PAG_ANY bit set. (without this
412 // flag it will also crash)
413 //All named file mappings are shared (files & memory only)
414 if(lpszMapName) {
415 pMapping = VirtualAllocShared(mSize, fAlloc, PAGE_READWRITE, lpszMapName);
416 }
417 else {
418 pMapping = VirtualAlloc(0, mSize, fAlloc, PAGE_READWRITE);
419 }
420 if(pMapping == NULL) {
421 dprintf(("Win32MemMap::mapFileView: VirtualAlloc %x %x %x failed!", mSize, fAlloc, memFlags));
422 goto fail;
423 }
424 //Windows NT seems to commit memory for memory maps, regardsless of the SEC_COMMIT flag
425 if((hMemFile == -1 && !image)) {//commit memory
426 VirtualAlloc(pMapping, mSize, MEM_COMMIT, PAGE_READWRITE);
427 }
428 if(hMemFile != -1 && (mProtFlags & SEC_COMMIT)) {
429 DWORD nrPages = mSize >> PAGE_SHIFT;
430 if(mSize & 0xFFF)
431 nrPages++;
432
433 commitPage(0, FALSE, nrPages);
434 }
435 }
436 mapview = new Win32MemMapView(this, offset, (size == 0) ? (mSize - offset) : size, fdwAccess);
437 if(mapview == NULL) {
438 goto fail;
439 }
440 if(mapview->everythingOk() == FALSE) {
441 dprintf(("Win32MemMap::mapFileView: !mapview->everythingOk"));
442 delete mapview;
443 goto fail;
444 }
445 nrMappings++;
446 mapMutex.leave();
447 return mapview->getViewAddr();
448
449parmfail:
450 dprintf(("Win32MemMap::mapFileView: ERROR_INVALID_PARAMETER"));
451 SetLastError(ERROR_INVALID_PARAMETER);
452fail:
453 mapMutex.leave();
454 return 0;
455}
456//******************************************************************************
457//We determine whether a page has been modified by checking it's protection flags
458//If the write flag is set, this means commitPage had to enable this due to a pagefault
459//(all pages are readonly until the app tries to modify the contents of the page)
460//
461//TODO: Are apps allowed to change the protection flags of memory mapped pages?
462// I'm assuming they aren't for now.
463//******************************************************************************
464BOOL Win32MemMap::flushView(ULONG offset, ULONG cbFlush)
465{
466 LPVOID lpvBase = (LPVOID)((ULONG)pMapping+offset);
467 MEMORY_BASIC_INFORMATION memInfo;
468 ULONG nrBytesWritten, size;
469 int i;
470
471 if(image) //no flushing for image maps
472 return TRUE;
473
474 dprintf(("Win32MemMap::flushView: %x %x", lpvBase, cbFlush));
475 if(nrMappings == 0)
476 goto parmfail;
477
478 if(cbFlush == 0)
479 cbFlush = mSize;
480
481 if(lpvBase < pMapping || (ULONG)lpvBase+cbFlush > (ULONG)pMapping+mSize)
482 goto parmfail;
483
484 if(mProtFlags & PAGE_READONLY)
485 goto parmfail;
486
487 if(hMemFile == -1)
488 goto success; //TODO: Return an error here?
489
490 while(cbFlush) {
491 if(VirtualQuery((LPSTR)lpvBase, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
492 dprintf(("Win32MemMap::flushView: VirtualQuery (%x,%x) failed for %x", lpvBase, cbFlush, (ULONG)lpvBase+i*PAGE_SIZE));
493 goto fail;
494 }
495 //If a page (or range of pages) is reserved or write protected, we
496 //won't bother flushing it to disk
497 if(memInfo.State & MEM_COMMIT &&
498 memInfo.AllocationProtect & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY))
499 {//committed and allowed for writing?
500 offset = (ULONG)lpvBase - (ULONG)pMapping;
501 size = memInfo.RegionSize;
502 if(size > cbFlush) {
503 size = cbFlush;
504 }
505 dprintf(("Win32MemMap::flushView for offset %x, size %d", offset, size));
506
507 if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
508 dprintf(("Win32MemMap::flushView: SetFilePointer failed to set pos to %x", offset));
509 goto fail;
510 }
511 if(WriteFile(hMemFile, (LPSTR)lpvBase, size, &nrBytesWritten, NULL) == FALSE) {
512 dprintf(("Win32MemMap::flushView: WriteFile failed for %x", (ULONG)lpvBase));
513 goto fail;
514 }
515 if(nrBytesWritten != size) {
516 dprintf(("Win32MemMap::flushView: WriteFile didn't write all bytes for %x", (ULONG)lpvBase));
517 goto fail;
518 }
519 }
520 lpvBase = (LPVOID)((ULONG)lpvBase + memInfo.RegionSize);
521
522 if(cbFlush < memInfo.RegionSize)
523 break;
524
525 cbFlush -= memInfo.RegionSize;
526 }
527success:
528 return TRUE;
529parmfail:
530 SetLastError(ERROR_INVALID_PARAMETER);
531 return FALSE;
532fail:
533 return FALSE;
534}
535//******************************************************************************
536//******************************************************************************
537Win32MemMap *Win32MemMap::findMap(LPSTR lpszName)
538{
539 if(lpszName == NULL)
540 return NULL;
541
542 DosEnterCriticalSection(&globalmapcritsect);
543 Win32MemMap *map = memmaps;
544
545 if(map != NULL) {
546 while(map) {
547 if(map->lpszMapName && !strcmp(map->lpszMapName, lpszName))
548 break;
549 map = map->next;
550 }
551 }
552 DosLeaveCriticalSection(&globalmapcritsect);
553 if(!map) dprintf(("Win32MemMap::findMap: couldn't find map %s", lpszName));
554 return map;
555}
556//******************************************************************************
557//******************************************************************************
558Win32MemMap *Win32MemMap::findMap(ULONG address)
559{
560 DosEnterCriticalSection(&globalmapcritsect);
561 Win32MemMap *map = memmaps;
562
563 if(map != NULL) {
564 while(map) {
565 if(map->pMapping && (ULONG)map->pMapping <= address &&
566 (ULONG)map->pMapping + map->mSize > address)
567 {
568 break;
569 }
570 map = map->next;
571 }
572 }
573 DosLeaveCriticalSection(&globalmapcritsect);
574 return map;
575}
576//******************************************************************************
577//******************************************************************************
578void Win32MemMap::deleteAll()
579{
580 Win32MemMap *map = memmaps, *nextmap;
581 DWORD processId = GetCurrentProcessId();
582
583 //delete all maps created by this process
584 DosEnterCriticalSection(&globalmapcritsect);
585 while(map) {
586 nextmap = map->next;
587 if(map->getProcessId() == processId) {
588 //Delete map directly for executable images (only used internally)
589 if(map->getImage()) {
590 delete map;
591 }
592 else {
593 delete map;
594 }
595 }
596 else {
597 //delete all views created by this process for this map
598 Win32MemMapView::deleteViews(map);
599 }
600 map = nextmap;
601 }
602 DosLeaveCriticalSection(&globalmapcritsect);
603}
604//******************************************************************************
605//******************************************************************************
606Win32MemMapView::Win32MemMapView(Win32MemMap *map, ULONG offset, ULONG size,
607 ULONG fdwAccess)
608{
609 LPVOID viewaddr = (LPVOID)((ULONG)map->getMappingAddr()+offset);
610 ULONG accessAttr = 0;
611 Win32MemMapView *tmpview = mapviews;
612
613 errorState = 0;
614 mParentMap = map;
615 mSize = size;
616 mOffset = offset;
617 mProcessId = GetCurrentProcessId();
618 pShareViewAddr = NULL;
619
620 switch(fdwAccess) {
621 case FILE_MAP_READ:
622 accessAttr = PAG_READ;
623 mfAccess = MEMMAP_ACCESS_READ;
624 break;
625 case FILE_MAP_ALL_ACCESS:
626 case FILE_MAP_WRITE:
627 case FILE_MAP_WRITE|FILE_MAP_READ:
628 case FILE_MAP_COPY:
629 accessAttr = (PAG_READ|PAG_WRITE);
630 mfAccess = MEMMAP_ACCESS_READ | MEMMAP_ACCESS_WRITE;
631 break;
632 }
633 //Named file mappings from other processes are always shared;
634 //map into our address space
635 if(map->getMemName() != NULL && map->getProcessId() != mProcessId)
636 {
637 //shared memory map, so map it into our address space
638 if(OSLibDosGetNamedSharedMem((LPVOID *)&viewaddr, map->getMemName()) != OSLIB_NOERROR) {
639 dprintf(("new OSLibDosGetNamedSharedMem FAILED"));
640 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
641 errorState = 1;
642 return;
643 }
644 pShareViewAddr = viewaddr;
645 }
646
647 //view == memory mapping for executable images (only used internally)
648 if(map->getImage()) {
649 pMapView = map->getMappingAddr();
650 }
651 else {
652 if(OSLibDosAliasMem(viewaddr, size, &pMapView, accessAttr) != OSLIB_NOERROR) {
653 dprintf(("new OSLibDosAliasMem FAILED"));
654 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
655 errorState = 1;
656 return;
657 }
658 }
659 dprintf(("Win32MemMapView::Win32MemMapView: created %x (alias for %x), size %d", pMapView, viewaddr, size));
660
661 DosEnterCriticalSection(&globalmapcritsect);
662 if(tmpview == NULL || tmpview->getViewAddr() > pMapView) {
663 next = mapviews;
664 mapviews = this;
665 }
666 else {
667 while(tmpview->next) {
668 if(tmpview->next->getViewAddr() > pMapView) {
669 break;
670 }
671 tmpview = tmpview->next;
672 }
673 next = tmpview->next;
674 tmpview->next = this;
675 }
676 DosLeaveCriticalSection(&globalmapcritsect);
677}
678//******************************************************************************
679//******************************************************************************
680Win32MemMapView::~Win32MemMapView()
681{
682 if(errorState != 0)
683 return;
684
685 dprintf(("Win32MemMapView dtor: deleting view %x %x", mOffset, mSize));
686
687 if(mfAccess & MEMMAP_ACCESS_WRITE)
688 mParentMap->flushView(mOffset, mSize);
689
690 //Don't free memory for executable image map views (only used internally)
691 if(!mParentMap->getImage())
692 OSLibDosFreeMem(pMapView);
693
694 if(pShareViewAddr) {
695 OSLibDosFreeMem(pShareViewAddr);
696 }
697
698 DosEnterCriticalSection(&globalmapcritsect);
699 Win32MemMapView *view = mapviews;
700
701 if(view == this) {
702 mapviews = next;
703 }
704 else {
705 while(view->next) {
706 if(view->next == this)
707 break;
708 view = view->next;
709 }
710 if(view->next) {
711 view->next = next;
712 }
713 else dprintf(("Win32MemMapView::~Win32MemMapView: map not found!! (%x)", this));
714 }
715 DosLeaveCriticalSection(&globalmapcritsect);
716}
717//******************************************************************************
718//******************************************************************************
719void Win32MemMapView::deleteViews(Win32MemMap *map)
720{
721 DosEnterCriticalSection(&globalmapcritsect);
722 Win32MemMapView *view = mapviews, *nextview;
723
724 if(view != NULL) {
725 while(view) {
726 nextview = view->next;
727 if(view->getParentMap() == map)
728 {
729 DosLeaveCriticalSection(&globalmapcritsect);
730 delete view;
731 DosEnterCriticalSection(&globalmapcritsect);
732 }
733 view = nextview;
734 }
735 }
736 DosLeaveCriticalSection(&globalmapcritsect);
737}
738//******************************************************************************
739//******************************************************************************
740Win32MemMap *Win32MemMapView::findMapByView(ULONG address,
741 ULONG *offset,
742 ULONG accessType,
743 Win32MemMapView **pView)
744{
745 if(mapviews == NULL) return NULL;
746
747 DosEnterCriticalSection(&globalmapcritsect);
748 Win32MemMapView *view = mapviews;
749 ULONG ulViewAddr;
750
751 *offset = 0;
752
753 if(view != NULL)
754 {
755 do
756 {
757 ulViewAddr = (ULONG)view->getViewAddr();
758
759 // if ulViewAddr is > address, we've exhausted
760 // the sorted list already and can abort search.
761 if(ulViewAddr <= address)
762 {
763 if(ulViewAddr + view->getSize() > address &&
764 view->getAccessFlags() >= accessType)
765 {
766 *offset = view->getOffset() + (address - ulViewAddr);
767 goto success;
768 }
769
770 // Not found yet, continue search with next map
771 view = view->next;
772 }
773 else
774 {
775 // list is exhausted, abort loop
776 view = NULL;
777 }
778 }
779 while(view);
780
781 //failure if we get here
782 view = NULL;
783 }
784
785success:
786#ifdef DEBUG
787 if(view && !view->getParentMap()->isImageMap())
788 dprintf(("findMapByView %x %x -> %x off %x",
789 address,
790 accessType,
791 view->getViewAddr(),
792 *offset));
793#endif
794
795 DosLeaveCriticalSection(&globalmapcritsect);
796
797 if(pView)
798 *pView = view;
799
800 return (view) ? view->getParentMap() : NULL;
801}
802//******************************************************************************
803//******************************************************************************
804Win32MemMapView *Win32MemMapView::findView(LPVOID address)
805{
806 Win32MemMapView *view = mapviews;
807
808 DosEnterCriticalSection(&globalmapcritsect);
809 if(view != NULL) {
810 while(view) {
811 if(view->getViewAddr() == address)
812 {
813 break;
814 }
815 view = view->next;
816 }
817 }
818 DosLeaveCriticalSection(&globalmapcritsect);
819 return view;
820}
821//******************************************************************************
822//******************************************************************************
823
Note: See TracBrowser for help on using the repository browser.