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

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

odininst update, CreateProcess fix & workaround for PM hang in WaitForSingleObject (process handle)

File size: 25.5 KB
Line 
1/* $Id: mmap.cpp,v 1.48 2001-01-14 17:16: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 * 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 <vmutex.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//NOTE: This must be in the local data segment -> if a shared semaphore was
41// created by a different process, the handle returned by DosOpenMutexSem
42// will be returned in hGlobalMapMutex
43HMTX hGlobalMapMutex = 0;
44
45//Global DLL Data
46#pragma data_seg(_GLOBALDATA)
47Win32MemMap *Win32MemMap::memmaps = NULL;
48VMutex globalmapMutex(VMUTEX_SHARED, &hGlobalMapMutex);
49#pragma data_seg()
50VMutex globalviewMutex;
51Win32MemMapView *Win32MemMapView::mapviews = NULL;
52
53//******************************************************************************
54//TODO: sharing between processes
55//******************************************************************************
56Win32MemMap::Win32MemMap(HFILE hfile, ULONG size, ULONG fdwProtect, LPSTR lpszName)
57 : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), image(0),
58 fClosed(FALSE)
59{
60 globalmapMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalMapMutex);
61 next = memmaps;
62 memmaps = this;
63 globalmapMutex.leave(&hGlobalMapMutex);
64
65 hMemFile = hfile;
66
67 mSize = size;
68 mProtFlags = fdwProtect;
69 mProcessId = GetCurrentProcess();
70
71 if(lpszName) {
72 lpszMapName = (char *)_smalloc(strlen(lpszName)+1);
73 strcpy(lpszMapName, lpszName);
74 }
75 else lpszMapName = NULL;
76}
77//******************************************************************************
78//Map constructor used for executable image maps (only used internally)
79//******************************************************************************
80Win32MemMap::Win32MemMap(Win32PeLdrImage *pImage, ULONG baseAddress, ULONG size)
81 : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), image(0),
82 fClosed(FALSE)
83{
84 globalmapMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalMapMutex);
85 next = memmaps;
86 memmaps = this;
87 globalmapMutex.leave(&hGlobalMapMutex);
88
89 hMemFile = -1;
90
91 mSize = size;
92 mProtFlags = PAGE_READWRITE;
93 mProcessId = GetCurrentProcess();
94
95 pMapping = (LPVOID)baseAddress;
96
97 image = pImage;
98 lpszMapName= NULL;
99}
100//******************************************************************************
101//******************************************************************************
102BOOL Win32MemMap::Init(HANDLE hMemMap)
103{
104 mapMutex.enter();
105 if(hMemFile != -1)
106 {
107#if 0
108 if(DuplicateHandle(mProcessId, hMemFile, GetCurrentProcess(),
109 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE)
110#else
111 DWORD dwOdinOptions;
112
113 if(!(mProtFlags & PAGE_READWRITE)) {
114 dwOdinOptions = DUPLICATE_ACCESS_READ | DUPLICATE_SHARE_DENYNONE;
115 }
116 else dwOdinOptions = DUPLICATE_ACCESS_READWRITE | DUPLICATE_SHARE_DENYNONE;
117
118 if(HMDuplicateHandleOdin(mProcessId, hMemFile, GetCurrentProcess(),
119 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS, dwOdinOptions) == FALSE)
120#endif
121 {
122 dprintf(("Win32MemMap::Init: DuplicateHandle failed!"));
123 goto fail;
124 }
125 mSize = SetFilePointer(hMemFile, 0, NULL, FILE_BEGIN);
126 mSize = SetFilePointer(hMemFile, 0, NULL, FILE_END);
127 if(mSize == -1) {
128 dprintf(("Win32MemMap::init: SetFilePointer failed to set pos end"));
129 goto fail;
130 }
131 //SvL: Temporary limitation of size (Warp Server Advanced doesn't allow
132 // one to reserve more than 450 MB (unless you override the virtual
133 // memory max limit) of continuous memory; (Warp 4 much less))
134 if(mSize > 64*1024*1024) {
135 mSize = 64*1024*1024;
136 }
137 }
138
139 dprintf(("CreateFileMappingA for file %x, prot %x size %d, name %s", hMemFile, mProtFlags, mSize, lpszMapName));
140 this->hMemMap = hMemMap;
141 mapMutex.leave();
142 return TRUE;
143fail:
144 mapMutex.leave();
145 return FALSE;
146}
147//******************************************************************************
148//******************************************************************************
149Win32MemMap::~Win32MemMap()
150{
151 Win32MemMapView::deleteViews(this); //delete all views of our memory mapped file
152
153 dprintf(("Win32MemMap dtor: deleting view %x %x", pMapping, mSize));
154
155 mapMutex.enter();
156 if(lpszMapName) {
157 free(lpszMapName);
158 }
159 if(pMapping && !image) {
160 if(lpszMapName) {
161 OSLibDosFreeMem(pMapping);
162 }
163 else VirtualFree(pMapping, 0, MEM_RELEASE);
164
165 pMapping = NULL;
166 }
167 if(hMemFile != -1) {
168 dprintf(("Win32MemMap dtor: closing memory file %x", hMemFile));
169 CloseHandle(hMemFile);
170 hMemFile = -1;
171 }
172 mapMutex.leave();
173
174 globalmapMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalMapMutex);
175 Win32MemMap *map = memmaps;
176
177 if(map == this) {
178 memmaps = next;
179 }
180 else {
181 while(map->next) {
182 if(map->next == this)
183 break;
184 map = map->next;
185 }
186 if(map->next) {
187 map->next = next;
188 }
189 else dprintf(("Win32MemMap::~Win32MemMap: map not found!! (%x)", this));
190 }
191 globalmapMutex.leave(&hGlobalMapMutex);
192}
193//******************************************************************************
194//If memory map has no more views left, then we can safely delete it when
195//it's handle is closed
196//******************************************************************************
197void Win32MemMap::close()
198{
199#ifdef DEBUG
200 dprintf(("Win32MemMap::close %s", lpszMapName));
201#endif
202 fClosed = TRUE;
203 if(nrMappings == 0) {
204 delete this;
205 }
206}
207//******************************************************************************
208//We determine whether a page has been modified by checking it's protection flags
209//If the write flag is set, this means commitPage had to enable this due to a pagefault
210//(all pages are readonly until the app tries to write to it)
211//******************************************************************************
212BOOL Win32MemMap::commitPage(ULONG offset, BOOL fWriteAccess, int nrpages)
213{
214 MEMORY_BASIC_INFORMATION memInfo;
215 LPVOID lpPageFaultAddr = (LPVOID)((ULONG)pMapping + offset);
216 DWORD pageAddr = (DWORD)lpPageFaultAddr & ~0xFFF;
217 DWORD oldProt, newProt, nrBytesRead, size;
218 int i;
219
220// mapMutex.enter();
221
222 if(image) {
223 return image->commitPage(pageAddr, fWriteAccess);
224 }
225 newProt = mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY);
226
227 dprintf(("Win32MemMap::commitPage %x (faultaddr %x)", pageAddr, lpPageFaultAddr));
228 if(hMemFile != -1)
229 {
230 int faultsize = nrpages*PAGE_SIZE;
231
232 offset = pageAddr - (ULONG)pMapping;
233 if(offset + faultsize > mSize) {
234 faultsize = mSize - offset;
235 }
236
237 while(faultsize) {
238 if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
239 dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed for %x", pageAddr, nrpages*PAGE_SIZE));
240 goto fail;
241 }
242 memInfo.RegionSize = min(memInfo.RegionSize, faultsize);
243 //Only changes the state of the pages with the same attribute flags
244 //(returned in memInfo.RegionSize)
245 //If it's smaller than the mNrPages, it simply means one or more of the
246 //other pages have already been committed
247 if(!(memInfo.State & MEM_COMMIT))
248 {
249 if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, PAGE_READWRITE) == FALSE) {
250 goto fail;
251 }
252 if(!fWriteAccess) {
253 offset = pageAddr - (ULONG)pMapping;
254 size = memInfo.RegionSize;
255 if(offset + size > mSize) {
256 dprintf(("Adjusting size from %d to %d", size, mSize - offset));
257 size = mSize - offset;
258 }
259 if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
260 dprintf(("Win32MemMap::commitPage: SetFilePointer failed to set pos to %x", offset));
261 goto fail;
262 }
263 if(ReadFile(hMemFile, (LPSTR)pageAddr, size, &nrBytesRead, NULL) == FALSE) {
264 dprintf(("Win32MemMap::commitPage: ReadFile failed for %x", pageAddr));
265 goto fail;
266 }
267 if(nrBytesRead != size) {
268 dprintf(("Win32MemMap::commitPage: ReadFile didn't read all bytes for %x", pageAddr));
269 goto fail;
270 }
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 && fClosed) {
330 delete this;
331 }
332 return TRUE;
333fail:
334 mapMutex.leave();
335 if(nrMappings == 0 && fClosed) {
336 delete this;
337 }
338 return FALSE;
339}
340//******************************************************************************
341//******************************************************************************
342LPVOID Win32MemMap::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
343{
344 DWORD processId = GetCurrentProcess();
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 if(hMemFile == -1 && lpszMapName) {
392 pMapping = VirtualAllocShared(mSize, fAlloc, PAGE_READWRITE, lpszMapName);
393 }
394 else {
395 pMapping = VirtualAlloc(0, mSize, fAlloc, PAGE_READWRITE);
396 }
397 if(pMapping == NULL) {
398 dprintf(("Win32MemMap::mapFileView: VirtualAlloc %x %x %x failed!", mSize, fAlloc, memFlags));
399 goto fail;
400 }
401 //Windows NT seems to commit memory for memory maps, regardsless of the SEC_COMMIT flag
402 if((hMemFile == -1 && !image)) {//commit memory
403 VirtualAlloc(pMapping, mSize, MEM_COMMIT, PAGE_READWRITE);
404 }
405 if(hMemFile != -1 && (mProtFlags & SEC_COMMIT)) {
406 DWORD nrPages = mSize >> PAGE_SHIFT;
407 if(mSize & 0xFFF)
408 nrPages++;
409
410 commitPage(0, FALSE, nrPages);
411 }
412 }
413 mapview = new Win32MemMapView(this, offset, (size == 0) ? mSize : size, fdwAccess);
414 if(mapview == NULL) {
415 goto fail;
416 }
417 if(mapview->everythingOk() == FALSE) {
418 dprintf(("Win32MemMap::mapFileView: !mapview->everythingOk"));
419 delete mapview;
420 goto fail;
421 }
422 nrMappings++;
423 mapMutex.leave();
424 return mapview->getViewAddr();
425
426parmfail:
427 dprintf(("Win32MemMap::mapFileView: ERROR_INVALID_PARAMETER"));
428 SetLastError(ERROR_INVALID_PARAMETER);
429fail:
430 mapMutex.leave();
431 return 0;
432}
433//******************************************************************************
434//We determine whether a page has been modified by checking it's protection flags
435//If the write flag is set, this means commitPage had to enable this due to a pagefault
436//(all pages are readonly until the app tries to modify the contents of the page)
437//
438//TODO: Are apps allowed to change the protection flags of memory mapped pages?
439// I'm assuming they aren't for now.
440//******************************************************************************
441BOOL Win32MemMap::flushView(ULONG offset, ULONG cbFlush)
442{
443 LPVOID lpvBase = (LPVOID)((ULONG)pMapping+offset);
444 MEMORY_BASIC_INFORMATION memInfo;
445 ULONG nrBytesWritten, size;
446 int i;
447
448 if(image) //no flushing for image maps
449 return TRUE;
450
451 dprintf(("Win32MemMap::flushView: %x %x", lpvBase, cbFlush));
452 if(nrMappings == 0)
453 goto parmfail;
454
455 if(cbFlush == 0)
456 cbFlush = mSize;
457
458 if(lpvBase < pMapping || (ULONG)lpvBase+cbFlush > (ULONG)pMapping+mSize)
459 goto parmfail;
460
461 if(mProtFlags & PAGE_READONLY)
462 goto parmfail;
463
464 if(hMemFile == -1)
465 goto success; //TODO: Return an error here?
466
467 while(cbFlush) {
468 if(VirtualQuery((LPSTR)lpvBase, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
469 dprintf(("Win32MemMap::flushView: VirtualQuery (%x,%x) failed for %x", lpvBase, cbFlush, (ULONG)lpvBase+i*PAGE_SIZE));
470 goto fail;
471 }
472 //If a page (or range of pages) is reserved or write protected, we
473 //won't bother flushing it to disk
474 if(memInfo.State & MEM_COMMIT &&
475 memInfo.AllocationProtect & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY))
476 {//committed and allowed for writing?
477 offset = (ULONG)lpvBase - (ULONG)pMapping;
478 size = memInfo.RegionSize;
479 if(size > cbFlush) {
480 size = cbFlush;
481 }
482 dprintf(("Win32MemMap::flushView for offset %x, size %d", offset, size));
483
484 if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
485 dprintf(("Win32MemMap::flushView: SetFilePointer failed to set pos to %x", offset));
486 goto fail;
487 }
488 if(WriteFile(hMemFile, (LPSTR)lpvBase, size, &nrBytesWritten, NULL) == FALSE) {
489 dprintf(("Win32MemMap::flushView: WriteFile failed for %x", (ULONG)lpvBase));
490 goto fail;
491 }
492 if(nrBytesWritten != size) {
493 dprintf(("Win32MemMap::flushView: WriteFile didn't write all bytes for %x", (ULONG)lpvBase));
494 goto fail;
495 }
496 }
497 lpvBase = (LPVOID)((ULONG)lpvBase + memInfo.RegionSize);
498
499 if(cbFlush < memInfo.RegionSize)
500 break;
501
502 cbFlush -= memInfo.RegionSize;
503 }
504success:
505 return TRUE;
506parmfail:
507 SetLastError(ERROR_INVALID_PARAMETER);
508 return FALSE;
509fail:
510 return FALSE;
511}
512//******************************************************************************
513//******************************************************************************
514Win32MemMap *Win32MemMap::findMap(LPSTR lpszName)
515{
516 if(lpszName == NULL)
517 return NULL;
518
519 globalmapMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalMapMutex);
520 Win32MemMap *map = memmaps;
521
522 if(map != NULL) {
523 while(map) {
524 if(map->lpszMapName && !strcmp(map->lpszMapName, lpszName))
525 break;
526 map = map->next;
527 }
528 }
529 globalmapMutex.leave(&hGlobalMapMutex);
530 if(!map) dprintf(("Win32MemMap::findMap: couldn't find map %s", lpszName));
531 return map;
532}
533//******************************************************************************
534//******************************************************************************
535Win32MemMap *Win32MemMap::findMap(ULONG address)
536{
537 globalmapMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalMapMutex);
538 Win32MemMap *map = memmaps;
539
540 if(map != NULL) {
541 while(map) {
542 if(map->pMapping && (ULONG)map->pMapping <= address &&
543 (ULONG)map->pMapping + map->mSize > address)
544 {
545 break;
546 }
547 map = map->next;
548 }
549 }
550 globalmapMutex.leave(&hGlobalMapMutex);
551 return map;
552}
553//******************************************************************************
554//******************************************************************************
555void Win32MemMap::deleteAll()
556{
557 Win32MemMap *map = memmaps, *nextmap;
558 DWORD processId = GetCurrentProcess();
559
560 //delete all maps created by this process
561 globalviewMutex.enter();
562 while(map) {
563 nextmap = map->next;
564 if(map->getProcessId() == processId) {
565 //Delete map directly for executable images (only used internally)
566 if(map->getImage()) {
567 delete map;
568 }
569 else {
570 if(!map->isClosed())
571 CloseHandle(memmaps->hMemMap);
572 else delete map;
573 }
574 }
575 else {
576 //delete all views created by this process for this map
577 Win32MemMapView::deleteViews(map);
578 }
579 map = nextmap;
580 }
581 globalviewMutex.leave();
582}
583//******************************************************************************
584//******************************************************************************
585Win32MemMapView::Win32MemMapView(Win32MemMap *map, ULONG offset, ULONG size,
586 ULONG fdwAccess)
587{
588 LPVOID viewaddr = (LPVOID)((ULONG)map->getMappingAddr()+offset);
589 ULONG accessAttr = 0;
590 Win32MemMapView *tmpview = mapviews;
591
592 errorState = 0;
593 mParentMap = map;
594 mSize = size;
595 mOffset = offset;
596 mProcessId = GetCurrentProcess();
597 pShareViewAddr = NULL;
598
599 switch(fdwAccess) {
600 case FILE_MAP_READ:
601 accessAttr = PAG_READ;
602 mfAccess = MEMMAP_ACCESS_READ;
603 break;
604 case FILE_MAP_ALL_ACCESS:
605 case FILE_MAP_WRITE:
606 case FILE_MAP_WRITE|FILE_MAP_READ:
607 case FILE_MAP_COPY:
608 accessAttr = (PAG_READ|PAG_WRITE);
609 mfAccess = MEMMAP_ACCESS_READ | MEMMAP_ACCESS_WRITE;
610 break;
611 }
612 if(map->getMemName() != NULL && map->getFileHandle() == -1 &&
613 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 globalviewMutex.enter();
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 globalviewMutex.leave();
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 globalviewMutex.enter();
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 globalviewMutex.leave();
694}
695//******************************************************************************
696//******************************************************************************
697void Win32MemMapView::deleteViews(Win32MemMap *map)
698{
699 globalviewMutex.enter();
700 Win32MemMapView *view = mapviews, *nextview;
701
702 if(view != NULL) {
703 while(view) {
704 nextview = view->next;
705 if(view->getParentMap() == map)
706 {
707 globalviewMutex.leave();
708 delete view;
709 globalviewMutex.enter();
710 }
711 view = nextview;
712 }
713 }
714 globalviewMutex.leave();
715}
716//******************************************************************************
717//******************************************************************************
718Win32MemMap *Win32MemMapView::findMapByView(ULONG address, ULONG *offset,
719 ULONG accessType,
720 Win32MemMapView **pView)
721{
722 globalviewMutex.enter();
723 Win32MemMapView *view = mapviews;
724
725 *offset = 0;
726
727 if(view != NULL) {
728 while(view && (ULONG)view->getViewAddr() <= address) {
729 if((ULONG)view->getViewAddr() <= address &&
730 (ULONG)view->getViewAddr() + view->getSize() > address &&
731 view->getAccessFlags() >= accessType)
732 {
733 *offset = view->getOffset() + (address - (ULONG)view->getViewAddr());
734 goto success;
735 }
736 view = view->next;
737 }
738 //failure if we get here
739 view = NULL;
740 }
741success:
742 if(view && !view->getParentMap()->isImageMap())
743 dprintf(("findMapByView %x %x -> %x off %x", address, accessType, view->getViewAddr(), *offset));
744
745 globalviewMutex.leave();
746 if(pView) *pView = view;
747 return (view) ? view->getParentMap() : NULL;
748}
749//******************************************************************************
750//******************************************************************************
751Win32MemMapView *Win32MemMapView::findView(LPVOID address)
752{
753 Win32MemMapView *view = mapviews;
754
755 globalviewMutex.enter();
756 if(view != NULL) {
757 while(view) {
758 if(view->getViewAddr() == address)
759 {
760 break;
761 }
762 view = view->next;
763 }
764 }
765 globalviewMutex.leave();
766 return view;
767}
768//******************************************************************************
769//******************************************************************************
770
Note: See TracBrowser for help on using the repository browser.