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

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

GetVolumeInformation bugfix + invalid VirtualFree calls corrected + free named shared memory

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