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

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

SetCustomMMapSemName added to override shared semaphore name used to synchronize global memory map list access (to avoid name clash with Odin)

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