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

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

use critical sections in vmutex; change global vmutex in mmap to use a shared critical section

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