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

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

DF: Removed 64 MB memory mapped file limit & Fix for opening memory mapped file with size larger than the file size

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