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

Last change on this file since 3830 was 3782, checked in by sandervl, 25 years ago

memory map fixes

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