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

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

Fixed wrong access of global memory map critical section

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