Changeset 9946 for trunk/src


Ignore:
Timestamp:
Mar 27, 2003, 3:13:11 PM (22 years ago)
Author:
sandervl
Message:

memory map updates

Location:
trunk/src/kernel32
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/asmutil.asm

    r8415 r9946  
    1 ; $Id: asmutil.asm,v 1.2 2002-05-15 10:57:44 sandervl Exp $
     1; $Id: asmutil.asm,v 1.3 2003-03-27 14:13:10 sandervl Exp $
    22
    33;/*
     
    2020        assume  cs:FLAT, ds:FLAT, ss:FLAT, es:FLAT
    2121
     22extrn   Dos32TIB:abs
     23
    2224CODE32          SEGMENT DWORD PUBLIC USE32 'CODE'
    2325
     
    99101        PUBLIC RestoreOS2FS
    100102RestoreOS2FS proc near
    101         push    150bh
     103        push    Dos32TIB
    102104        mov     ax, fs
    103105        pop     fs
     
    189191
    190192
     193        align 4h
     194
     195        public _set_bit
     196;void CDECL set_bit(int bitnr, void *addr);
     197_set_bit proc near
     198    push esi
     199
     200    mov  esi, [esp+12]
     201    mov  eax, [esp+8]
     202
     203    bts  dword ptr [esi], eax
     204
     205    pop  esi
     206    ret
     207_set_bit endp
     208
     209        align 4h
     210
     211        public _test_bit
     212;int CDECL test_bit(int bitnr, void *addr);
     213_test_bit proc near
     214    push esi
     215
     216    mov  esi, [esp+12]
     217    mov  eax, [esp+8]
     218
     219    bt   dword ptr [esi], eax
     220    setc al
     221    movzx eax, al
     222
     223    pop  esi
     224    ret
     225_test_bit endp
     226
     227        public _clear_bit
     228;void CDECL clear_bit(int bitnr, void *addr);
     229_clear_bit proc near
     230    push esi
     231
     232    mov  esi, [esp+12]
     233    mov  eax, [esp+8]
     234
     235    btr  dword ptr [esi], eax
     236
     237    pop  esi
     238    ret
     239_clear_bit endp
     240
    191241CODE32          ENDS
    192242
  • trunk/src/kernel32/asmutil.h

    r8401 r9946  
    1 /* $Id: asmutil.h,v 1.1 2002-05-10 14:55:10 sandervl Exp $ */
     1/* $Id: asmutil.h,v 1.2 2003-03-27 14:13:10 sandervl Exp $ */
    22
    33/*
     
    2929void CDECL Add64(LARGE_INTEGER *a, LARGE_INTEGER *b, LARGE_INTEGER *result);
    3030
     31
     32void CDECL set_bit(int bitnr, void *addr);
     33void CDECL clear_bit(int bitnr, void *addr);
     34int  CDECL test_bit(int bitnr, void *addr);
     35
    3136#ifdef __cplusplus
    3237}
  • trunk/src/kernel32/mmap.cpp

    r9911 r9946  
    1 /* $Id: mmap.cpp,v 1.63 2003-03-06 10:44:34 sandervl Exp $ */
     1/* $Id: mmap.cpp,v 1.64 2003-03-27 14:13:10 sandervl Exp $ */
    22
    33/*
    44 * Win32 Memory mapped file & view classes
    55 *
    6  * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
     6 * Copyright 1999-2003 Sander van Leeuwen (sandervl@xs4all.nl)
    77 *
    88 * NOTE: Memory mapping DOES NOT work when kernel-mode code causes
     
    3636#include <winimagepeldr.h>
    3737#include <custombuild.h>
     38#include "asmutil.h"
    3839
    3940#define DBG_LOCALLOG    DBG_mmap
    4041#include "dbglocal.h"
     42
     43
    4144
    4245//Global DLL Data
     
    4548CRITICAL_SECTION_OS2       globalmapcritsect = {0};
    4649#pragma data_seg()
    47 Win32MemMapView *Win32MemMapView::mapviews = NULL;
    4850
    4951
     
    7274//******************************************************************************
    7375Win32MemMap::Win32MemMap(HFILE hfile, ULONG size, ULONG fdwProtect, LPSTR lpszName)
    74                : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), image(0)
     76               : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0),
     77                 image(0), pWriteBitmap(NULL)
    7578{
    7679    DosEnterCriticalSection(&globalmapcritsect);
     
    8386    mSize      = size;
    8487    mProtFlags = fdwProtect;
     88
    8589    mProcessId  = GetCurrentProcessId();
    8690
     
    96100//******************************************************************************
    97101Win32MemMap::Win32MemMap(Win32PeLdrImage *pImage, ULONG baseAddress, ULONG size)
    98                : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), image(0)
     102               : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0),
     103                 image(0), pWriteBitmap(NULL)
    99104{
    100105    DosEnterCriticalSection(&globalmapcritsect);
     
    171176    Win32MemMapView::deleteViews(this); //delete all views of our memory mapped file
    172177
    173     dprintf(("Win32MemMap dtor: deleting view %x %x", pMapping, mSize));
     178    dprintf(("Win32MemMap dtor: deleting map %x %x", pMapping, mSize));
    174179
    175180    mapMutex.enter();
     
    190195        hMemFile = -1;
    191196    }
     197    if(pWriteBitmap) free(pWriteBitmap);
     198
    192199    mapMutex.leave();
    193200
     
    212219}
    213220//******************************************************************************
    214 // Win32MemMap::setProtFlags
    215 //
    216 // Change the protection flags of this memory map if required
    217 // This is currently only used when creating a mapping for a file which already
    218 // has an existing mapping.
    219 //
    220 //
    221 // Parameters:
    222 //
    223 //   DWORD dwNewProtect         - new protection flags
    224 //
    225 // Returns:
    226 //   TRUE                       - success
    227 //   FALSE                      - failure
    228 //
    229 // NOTE:
    230 //   We're ignoring the SEC_* flags for now
    231 //
    232 //******************************************************************************
    233 BOOL Win32MemMap::setProtFlags(DWORD dwNewProtect)
    234 {
    235     if(!(dwNewProtect & (PAGE_READWRITE|PAGE_WRITECOPY))) return TRUE; //no need for changes
    236 
    237     if(!(mProtFlags & PAGE_READWRITE))
    238     {//ok, current mapping is readonly; need to change it to readwrite
    239         mProtFlags &= ~PAGE_READONLY;
    240         mProtFlags |= PAGE_READWRITE;
    241 
    242         //that's all we need to do for now; memory mappings are readwrite by
    243         //default (see mapViewOfFile)
    244     }
    245     return TRUE;
    246 }
    247 //******************************************************************************
    248 //If memory map has no more views left, then we can safely delete it when
    249 //it's handle is closed
    250 //******************************************************************************
    251 void Win32MemMap::Release()
     221//******************************************************************************
     222int Win32MemMap::Release()
    252223{
    253224    dprintf(("Win32MemMap::Release %s (%d)", lpszMapName, referenced-1));
    254225    --referenced;
    255     if(nrMappings == 0 && referenced == 0) {
     226    if(referenced == 0) {
    256227        delete this;
    257     }
     228        return 0;
     229    }
     230    return referenced;
    258231}
    259232//******************************************************************************
     
    327300 LPVOID lpPageFaultAddr = (LPVOID)((ULONG)pMapping + offset);
    328301 DWORD pageAddr         = (DWORD)lpPageFaultAddr & ~0xFFF;
    329  DWORD oldProt, newProt, nrBytesRead, size;
     302 DWORD oldProt, newProt, nrBytesRead;
    330303 int i;
    331304
     
    333306
    334307  if(image) {
    335     return image->commitPage(pageAddr, fWriteAccess);
    336   }
    337   newProt  = mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY);
     308      return image->commitPage(pageAddr, fWriteAccess);
     309  }
    338310
    339311  dprintf(("Win32MemMap::commitPage %x (faultaddr %x)", pageAddr, lpPageFaultAddr));
    340   if(hMemFile != -1)
     312
     313  //align at page boundary
     314  offset &= ~0xFFF;
     315
     316  //If it's a write access violation and the view is readonly, then fail
     317  if(fWriteAccess) {
     318      Win32MemMapView *view = Win32MemMapView::findView(ulFaultAddr);
     319      if(view) {
     320          if(!(view->getAccessFlags() & MEMMAP_ACCESS_WRITE)) {
     321              dprintf(("Write access for a readonly view!!"));
     322              return FALSE;
     323          }
     324      }
     325      else {
     326          DebugInt3(); //can't happen
     327          return FALSE;
     328      }
     329  }
     330
     331  int faultsize = nrpages*PAGE_SIZE;
     332
     333  if(fWriteAccess)
     334  {//write access needs special care, so do that on a per page basis
     335      dprintf(("Write access -> handle only one page"));
     336      faultsize = PAGE_SIZE;
     337  }
     338
     339  offset = pageAddr - (ULONG)pMapping;
     340  if(offset + faultsize > mSize) {
     341      faultsize = mSize - offset;
     342  }
     343
     344  while(faultsize)
    341345  {
    342     int faultsize = nrpages*PAGE_SIZE;
    343 
    344     offset = pageAddr - (ULONG)pMapping;
    345     if(offset + faultsize > mSize) {
    346         faultsize = mSize - offset;
    347     }
    348 
    349     while(faultsize) {
    350346        if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
    351347            dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed for %x", pageAddr, nrpages*PAGE_SIZE));
     
    362358                goto fail;
    363359            }
    364             offset = pageAddr - (ULONG)pMapping;
    365             size   = memInfo.RegionSize;
    366             if(offset + size > mSize) {
    367                 dprintf(("Adjusting size from %d to %d", size, mSize - offset));
    368                 size = mSize - offset;
    369             }
    370             if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
    371                 dprintf(("Win32MemMap::commitPage: SetFilePointer failed to set pos to %x", offset));
    372                 goto fail;
    373             }
    374             if(ReadFile(hMemFile, (LPSTR)pageAddr, size, &nrBytesRead, NULL) == FALSE) {
    375                 dprintf(("Win32MemMap::commitPage: ReadFile failed for %x", pageAddr));
    376                 goto fail;
    377             }
    378             if(nrBytesRead != size) {
    379                 dprintf(("Win32MemMap::commitPage: ReadFile didn't read all bytes for %x", pageAddr));
    380                 goto fail;
    381             }
    382             if(newProt != PAGE_READWRITE) {
    383                 if(VirtualProtect((LPVOID)pageAddr, memInfo.RegionSize, newProt, &oldProt) == FALSE) {
     360
     361            //Part of the memory map has been committed, so now we can change
     362            //the protection flags of the aliases (DosSetMem fails for reserved pages)
     363            updateViewPages(offset, memInfo.RegionSize, (fWriteAccess) ? PAGEVIEW_VIEW : PAGEVIEW_READONLY);
     364
     365            if(hMemFile != -1)
     366            {//now read the page(s) from disk
     367                DWORD size;
     368
     369                offset = pageAddr - (ULONG)pMapping;
     370                size   = memInfo.RegionSize;
     371                if(offset + size > mSize) {
     372                    dprintf(("Adjusting size from %d to %d", size, mSize - offset));
     373                    size = mSize - offset;
     374                }
     375                if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
     376                    dprintf(("Win32MemMap::commitPage: SetFilePointer failed to set pos to %x", offset));
     377                    goto fail;
     378                }
     379                if(ReadFile(hMemFile, (LPSTR)pageAddr, size, &nrBytesRead, NULL) == FALSE) {
     380                    dprintf(("Win32MemMap::commitPage: ReadFile failed for %x", pageAddr));
     381                    goto fail;
     382                }
     383                if(nrBytesRead != size) {
     384                    dprintf(("Win32MemMap::commitPage: ReadFile didn't read all bytes for %x", pageAddr));
     385                    goto fail;
     386                }
     387            }           
     388            //We set the protection flags to PAGE_READONLY, unless this pagefault
     389            //was due to a write access
     390            //This way we can track dirty pages which need to be flushed to
     391            //disk when FlushViewOfFile is called or the map is closed.
     392            if(!fWriteAccess)
     393            {
     394                if(VirtualProtect((LPVOID)pageAddr, memInfo.RegionSize, PAGE_READONLY, &oldProt) == FALSE) {
     395                    dprintf(("VirtualProtect %x %x PAGE_READWRITE failed with %d!!", pageAddr, memInfo.RegionSize, GetLastError()));
    384396                    goto fail;
    385397                }
    386398            }
     399            else
     400            {//make these pages as dirty
     401                ULONG startPage  = (pageAddr - (ULONG)pMapping) >> PAGE_SHIFT;
     402                ULONG nrPages    = memInfo.RegionSize >> PAGE_SHIFT;
     403
     404                if(memInfo.RegionSize & 0xFFF)
     405                    nrPages++;
     406
     407                dprintf(("Mark %d page(s) starting at %x as dirty", nrPages, pageAddr));
     408                markDirtyPages(startPage, nrPages);
     409            }
     410        }
     411        else
     412        if(fWriteAccess)
     413        {
     414            //mark these pages as dirty
     415            ULONG startPage  = (pageAddr - (ULONG)pMapping) >> PAGE_SHIFT;
     416            ULONG nrPages    = memInfo.RegionSize >> PAGE_SHIFT;
     417
     418            if(memInfo.RegionSize & 0xFFF)
     419                nrPages++;
     420
     421            dprintf(("Mark %d page(s) starting at %x as dirty", nrPages, pageAddr));
     422            markDirtyPages(startPage, nrPages);
     423
     424            //and turn on a write access
     425            if(VirtualProtect((LPVOID)pageAddr, memInfo.RegionSize, PAGE_READWRITE, &oldProt) == FALSE) {
     426                dprintf(("VirtualProtect %x %x PAGE_READWRITE failed with %d!!", pageAddr, memInfo.RegionSize, GetLastError()));
     427                goto fail;
     428            }
     429            //Now change all the aliased pages according to their view protection flags
     430            updateViewPages(offset, memInfo.RegionSize, PAGEVIEW_VIEW);
    387431        }
    388432        faultsize -= memInfo.RegionSize;
    389433        pageAddr  += memInfo.RegionSize;
    390     }
    391   }
    392   else {
    393     ULONG sizeleft = nrpages*PAGE_SIZE;
    394     while(sizeleft)
    395     {
    396         if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
    397             dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed", pageAddr, sizeleft));
    398             goto fail;
    399         }
    400         memInfo.RegionSize = min(memInfo.RegionSize, sizeleft);
    401 
    402         if(!(memInfo.State & MEM_COMMIT))
    403             {//if it's already committed, then the app tried to write to it
    404             if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, newProt) == FALSE)
    405                 goto fail;
    406         }
    407         memInfo.RegionSize = (memInfo.RegionSize+PAGE_SIZE-1) & ~0xfff;
    408         pageAddr += memInfo.RegionSize;
    409         sizeleft -= memInfo.RegionSize;
    410     }
    411434  }
    412435
     
    420443// Win32MemMap::commitGuardPage
    421444//
    422 // Handle a guard page exception for a copy-on-write view (one page only)
     445// Handle a guard page exception
    423446//
    424447// Parameters:
     
    436459BOOL Win32MemMap::commitGuardPage(ULONG ulFaultAddr, ULONG ulOffset, BOOL fWriteAccess)
    437460{
    438     return FALSE;
    439 }
    440 //******************************************************************************
    441 // Win32MemMap::invalidatePages
    442 //
    443 // Invalidate map pages. (called by WriteFile)
     461   MEMORY_BASIC_INFORMATION memInfo;
     462   BOOL   ret;
     463   DWORD  pageAddr = ulFaultAddr & ~0xFFF;
     464   DWORD  dwNewProt, dwOldProt;
     465
     466   dprintf(("Win32MemMap::commitGuardPage %x (faultaddr %x)", pageAddr, ulFaultAddr));
     467
     468   //align at page boundary
     469   ulOffset &= ~0xFFF;
     470
     471   return TRUE;
     472fail:
     473   return FALSE;
     474}
     475//******************************************************************************
     476// Win32MemMap::updateViewPages
     477//
     478// Update the page flags of all views
    444479//
    445480// Parameters:
    446481//
    447482//   ULONG offset               - offset in memory map
    448 //   ULONG size                 - invalid range size
     483//   ULONG size                 - range size
     484//   PAGEVIEW flags             - page flags
     485//       PAGEVIEW_READONLY      -> set page flags to readonly
     486//       PAGEVIEW_VIEW          -> set page flags to view default
    449487//
    450488// Returns:
     
    453491//
    454492//******************************************************************************
    455 BOOL Win32MemMap::invalidatePages(ULONG offset, ULONG size)
    456 {
    457     return FALSE;
    458 }
    459 //******************************************************************************
    460 // Win32MemMap::unmapViewOfFile
    461 //
    462 // Unmap the view identified by addr
     493BOOL Win32MemMap::updateViewPages(ULONG offset, ULONG size, PAGEVIEW flags)
     494{
     495    Win32MemMapView **views = (Win32MemMapView **)alloca(sizeof(Win32MemMapView*)*nrMappings);
     496    if(views)
     497    {
     498        if(Win32MemMapView::findViews(this, nrMappings, views) == nrMappings)
     499        {
     500            for(int i=0;i<nrMappings;i++)
     501            {
     502                views[i]->changePageFlags(offset, size, flags);
     503            }           
     504        }
     505        else DebugInt3(); //oh, oh
     506    }
     507    return TRUE;
     508}
     509//******************************************************************************
     510// Win32MemMap::invalidatePages
     511//
     512// Invalidate map pages. (called by WriteFile)
    463513//
    464514// Parameters:
    465515//
    466 //   LPVOID addr                - view address; doesn't need to be the address
    467 //                                returned by MapViewOfFile(Ex) (as MSDN clearly says);
    468 //                                can be any address within the view range
     516//   ULONG offset               - offset in memory map
     517//   ULONG size                 - invalid range size
    469518//
    470519// Returns:
     
    473522//
    474523//******************************************************************************
    475 BOOL Win32MemMap::unmapViewOfFile(LPVOID addr)
    476 {
    477     Win32MemMapView *view;
    478 
    479     dprintf(("Win32MemMap::unmapViewOfFile %x (nrmaps=%d)", addr, nrMappings));
    480     mapMutex.enter();
    481 
    482     if(nrMappings == 0)
    483         goto fail;
    484 
    485     view = Win32MemMapView::findView((ULONG)addr);
    486     if(view == NULL)
    487         goto fail;
    488 
    489     delete view;
    490 
    491     if(--nrMappings == 0) {
    492         VirtualFree(pMapping, 0, MEM_RELEASE);
    493         pMapping = NULL;
    494     }
    495     mapMutex.leave();
    496 
    497     //if there are no more mappings left and the memory map's handle has been
    498     //closed, then delete the object
    499     if(nrMappings == 0 && referenced == 0) {
    500         delete this;
     524BOOL Win32MemMap::invalidatePages(ULONG offset, ULONG size)
     525{
     526    ULONG diff = offset & 0xFFF;
     527    BOOL ret;
     528
     529    offset &= ~0xFFF;
     530    size   += diff;
     531
     532    dprintf(("Win32MemMap::invalidatePages %x %x", offset, size));
     533    ret = VirtualFree((LPSTR)pMapping + offset, size, MEM_DECOMMIT);
     534    if(ret == FALSE) {
     535        dprintf(("ERROR: Win32MemMap::invalidatePages: VirtualFree failed!!"));
    501536    }
    502537    return TRUE;
    503 fail:
    504     mapMutex.leave();
    505     return FALSE;
    506 }
    507 //******************************************************************************
    508 //******************************************************************************
    509 LPVOID Win32MemMap::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
    510 {
    511  DWORD processId = GetCurrentProcessId();
    512 
    513     mapMutex.enter();
    514     ULONG memFlags = (mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY));
     538}
     539//******************************************************************************
     540// Win32MemMap::allocateMap
     541//
     542// Allocate memory for the map if not yet already done.
     543//
     544// Returns:
     545//   FALSE                      - success
     546//   TRUE                       - failure
     547//
     548//******************************************************************************
     549BOOL Win32MemMap::allocateMap()
     550{
    515551    ULONG fAlloc   = 0;
    516     Win32MemMapView *mapview;
    517 
    518     //@@@PH: if(fdwAccess & ~(FILE_MAP_WRITE|FILE_MAP_READ|FILE_MAP_COPY))
    519     // Docs say FILE_MAP_ALL_ACCESS is same as FILE_MAP_WRITE. Doesn't match reality though.
    520     if(fdwAccess & ~FILE_MAP_ALL_ACCESS)
    521         goto parmfail;
    522     if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE))
    523         goto parmfail;
    524     if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
    525         goto parmfail;
    526 
    527     //@@@PH
    528     if (fdwAccess != FILE_MAP_ALL_ACCESS)
    529         if((fdwAccess & FILE_MAP_COPY) && !(mProtFlags & PAGE_WRITECOPY))
    530         goto parmfail;
    531 
    532     if(offset+size > mSize && (!(fdwAccess & FILE_MAP_WRITE) || hMemFile == -1))
    533         goto parmfail;
    534 
    535     //SvL: TODO: Doesn't work for multiple views
    536     if(offset+size > mSize) {
    537         mSize = offset+size;
    538     }
    539 
    540 //TODO: If committed, read file into memory
    541 #if 0
    542     if(mProtFlags & SEC_COMMIT)
    543         fAlloc |= MEM_COMMIT;
    544     else
    545     if(mProtFlags & SEC_RESERVE)
    546         fAlloc |= MEM_RESERVE;
    547 #else
     552
    548553    fAlloc = MEM_RESERVE;
    549 #endif
    550554
    551555    //Memory has already been allocated for executable image maps (only used internally)
     
    567571        }
    568572        if(pMapping == NULL) {
    569             dprintf(("Win32MemMap::mapFileView: VirtualAlloc %x %x %x failed!", mSize, fAlloc, memFlags));
     573            dprintf(("Win32MemMap::mapViewOfFile: VirtualAlloc %x %x failed!", mSize, fAlloc));
    570574            goto fail;
    571575        }
     
    574578            VirtualAlloc(pMapping, mSize, MEM_COMMIT, PAGE_READWRITE);
    575579        }
     580
     581        DWORD nrPages = mSize >> PAGE_SHIFT;
     582        if(mSize & 0xFFF)
     583           nrPages++;
     584
    576585        if(hMemFile != -1 && (mProtFlags & SEC_COMMIT)) {
    577             DWORD nrPages = mSize >> PAGE_SHIFT;
    578             if(mSize & 0xFFF)
    579                 nrPages++;
    580 
    581             commitPage(0, FALSE, nrPages);
    582         }
    583     }
     586            commitPage((ULONG)pMapping, 0, FALSE, nrPages);
     587        }
     588        //Allocate bitmap for all pages to keep track of write access (file maps only)
     589        //Necessary for FlushViewOfFile.
     590        if(hMemFile != -1) {
     591            int sizebitmap = nrPages/8 + 1;
     592
     593            pWriteBitmap = (char *)_smalloc(sizebitmap);
     594            if(pWriteBitmap == NULL) {
     595                DebugInt3();
     596                goto fail;
     597            }
     598            memset(pWriteBitmap, 0, sizebitmap);
     599        }
     600    }
     601    return TRUE;
     602
     603fail:
     604    return FALSE;
     605}
     606//******************************************************************************
     607// Win32MemMap::mapViewOfFile
     608//
     609// Map the view identified by addr
     610//
     611// Parameters:
     612//
     613//   ULONG size                 - size of view
     614//   ULONG offset               - offset in memory map
     615//   ULONG fdwAccess            - access flags
     616//                                FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_COPY
     617//                                FILE_MAP_ALL_ACCESS
     618//                               
     619//
     620// Returns:
     621//   <>NULL                     - success, view address
     622//   NULL                       - failure
     623//
     624//******************************************************************************
     625LPVOID Win32MemMap::mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess)
     626{
     627    DWORD processId = GetCurrentProcessId();
     628
     629    mapMutex.enter();
     630    ULONG memFlags = (mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY));
     631    Win32MemMapView *mapview;
     632
     633    //@@@PH: if(fdwAccess & ~(FILE_MAP_WRITE|FILE_MAP_READ|FILE_MAP_COPY))
     634    // Docs say FILE_MAP_ALL_ACCESS is same as FILE_MAP_WRITE. Doesn't match reality though.
     635    if(fdwAccess & ~FILE_MAP_ALL_ACCESS)
     636        goto parmfail;
     637    if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE))
     638        goto parmfail;
     639    if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
     640        goto parmfail;
     641   
     642    if (fdwAccess != FILE_MAP_ALL_ACCESS)
     643        if((fdwAccess & FILE_MAP_COPY) && !(mProtFlags & PAGE_WRITECOPY))
     644             goto parmfail;
     645
     646    if(offset+size > mSize && (!(fdwAccess & FILE_MAP_WRITE) || hMemFile == -1))
     647        goto parmfail;
     648
     649    //SvL: TODO: Doesn't work for multiple views
     650    if(offset+size > mSize) {
     651        mSize = offset+size;
     652    }
     653
     654    if(allocateMap() == FALSE) {
     655        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
     656        goto fail;
     657    }
     658
    584659    mapview = new Win32MemMapView(this, offset, (size == 0) ? (mSize - offset) : size, fdwAccess);
    585660    if(mapview == NULL) {
     
    587662    }
    588663    if(mapview->everythingOk() == FALSE) {
    589         dprintf(("Win32MemMap::mapFileView: !mapview->everythingOk"));
     664        dprintf(("Win32MemMap::mapViewOfFile: !mapview->everythingOk"));
    590665        delete mapview;
    591666        goto fail;
    592667    }
    593     nrMappings++;
    594668    mapMutex.leave();
     669    SetLastError(ERROR_SUCCESS);
    595670    return mapview->getViewAddr();
    596671
    597672parmfail:
    598     dprintf(("Win32MemMap::mapFileView: ERROR_INVALID_PARAMETER"));
    599     SetLastError(ERROR_INVALID_PARAMETER);
     673    dprintf(("Win32MemMap::mapViewOfFile: invalid parameter (ERROR_ACCESS_DENIED)"));
     674    //NT4 SP6 returns ERROR_ACCESS_DENIED for most invalid parameters
     675    SetLastError(ERROR_ACCESS_DENIED);
    600676fail:
    601677    mapMutex.leave();
     
    603679}
    604680//******************************************************************************
     681// Win32MemMap::unmapViewOfFile
     682//
     683// Unmap the view identified by addr
     684//
     685// Parameters:
     686//
     687//   LPVOID addr                - view address; doesn't need to be the address
     688//                                returned by MapViewOfFile(Ex) (as MSDN clearly says);
     689//                                can be any address within the view range
     690//
     691// Returns:
     692//   TRUE                       - success
     693//   FALSE                      - failure
     694//
     695//******************************************************************************
     696BOOL Win32MemMap::unmapViewOfFile(LPVOID addr)
     697{
     698    Win32MemMapView *view;
     699
     700    dprintf(("Win32MemMap::unmapViewOfFile %x (nrmaps=%d)", addr, nrMappings));
     701    mapMutex.enter();
     702
     703    if(nrMappings == 0)
     704        goto fail;
     705
     706    view = Win32MemMapView::findView((ULONG)addr);
     707    if(view == NULL)
     708        goto fail;
     709
     710    delete view;
     711
     712    if(nrMappings == 0) {
     713        VirtualFree(pMapping, 0, MEM_RELEASE);
     714        pMapping = NULL;
     715    }
     716    mapMutex.leave();
     717
     718    SetLastError(ERROR_SUCCESS);
     719    return TRUE;
     720fail:
     721    mapMutex.leave();
     722    SetLastError(ERROR_INVALID_ADDRESS);
     723    return FALSE;
     724}
     725//******************************************************************************
    605726//We determine whether a page has been modified by checking it's protection flags
    606727//If the write flag is set, this means commitPage had to enable this due to a pagefault
     
    612733BOOL Win32MemMap::flushView(ULONG viewaddr, ULONG offset, ULONG cbFlush)
    613734{
    614  LPVOID lpvBase = (LPVOID)((ULONG)pMapping+offset);
    615  MEMORY_BASIC_INFORMATION memInfo;
    616  ULONG nrBytesWritten, size;
    617  int   i;
     735  ULONG nrBytesWritten, size, accessflags, oldProt;
     736  Win32MemMapView *view;
     737  int i;
     738
     739  dprintf(("Win32MemMap::flushView: %x %x", (ULONG)pMapping+offset, cbFlush));
    618740
    619741  if(image) //no flushing for image maps
    620     return TRUE;
    621 
    622   dprintf(("Win32MemMap::flushView: %x %x", lpvBase, cbFlush));
    623   if(nrMappings == 0)
    624     goto parmfail;
     742      return TRUE;
     743
     744  if(hMemFile == -1)
     745      goto success; //TODO: Return an error here?
     746
     747  if(offset > mSize)
     748      goto parmfail;
     749
     750  if(viewaddr != MMAP_FLUSHVIEW_ALL)
     751  {
     752      view = Win32MemMapView::findView(viewaddr);
     753      if(nrMappings == 0 || view == NULL) {
     754          DebugInt3(); //should never happen
     755          goto parmfail;
     756      }
     757      accessflags = view->getAccessFlags();
     758  }
     759  else {
     760      //force a flush to disk; only those pages marked dirty are flushed anyway
     761      accessflags = FILE_MAP_WRITE;
     762  }
     763  //If the view is readonly or copy on write, then the flush is ignored
     764  if(!(accessflags & MEMMAP_ACCESS_WRITE) || (accessflags & MEMMAP_ACCESS_COPYONWRITE))
     765  {
     766      dprintf(("Readonly or Copy-On-Write memory map -> ignore flush"));
     767      //this is not a failure; NT4 SP6 returns success
     768      goto success;
     769  }
    625770
    626771  if(cbFlush == 0)
    627     cbFlush = mSize;
    628 
    629   if(lpvBase < pMapping || (ULONG)lpvBase+cbFlush > (ULONG)pMapping+mSize)
    630     goto parmfail;
    631 
    632   if(mProtFlags & PAGE_READONLY)
    633     goto parmfail;
    634 
    635   if(hMemFile == -1)
    636     goto success; //TODO: Return an error here?
    637 
    638   while(cbFlush) {
    639     if(VirtualQuery((LPSTR)lpvBase, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
    640         dprintf(("Win32MemMap::flushView: VirtualQuery (%x,%x) failed for %x", lpvBase, cbFlush, (ULONG)lpvBase+i*PAGE_SIZE));
    641         goto fail;
    642     }
    643     //If a page (or range of pages) is reserved or write protected, we
    644         //won't bother flushing it to disk
    645     if(memInfo.State & MEM_COMMIT &&
    646            memInfo.AllocationProtect & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY))
    647         {//committed and allowed for writing?
    648         offset = (ULONG)lpvBase - (ULONG)pMapping;
    649         size   = memInfo.RegionSize;
    650         if(size > cbFlush) {
    651             size = cbFlush;
    652         }
    653         dprintf(("Win32MemMap::flushView for offset %x, size %d", offset, size));
    654 
    655         if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
    656             dprintf(("Win32MemMap::flushView: SetFilePointer failed to set pos to %x", offset));
    657             goto fail;
    658         }
    659         if(WriteFile(hMemFile, (LPSTR)lpvBase, size, &nrBytesWritten, NULL) == FALSE) {
    660             dprintf(("Win32MemMap::flushView: WriteFile failed for %x", (ULONG)lpvBase));
    661             goto fail;
    662         }
    663         if(nrBytesWritten != size) {
    664             dprintf(("Win32MemMap::flushView: WriteFile didn't write all bytes for %x", (ULONG)lpvBase));
    665             goto fail;
    666         }
    667     }
    668     lpvBase = (LPVOID)((ULONG)lpvBase + memInfo.RegionSize);
    669 
    670     if(cbFlush < memInfo.RegionSize)
    671         break;
    672 
    673     cbFlush -= memInfo.RegionSize;
     772      cbFlush = mSize;
     773
     774  if(offset + cbFlush > mSize) {
     775      cbFlush -= (offset + cbFlush - mSize);
     776  }
     777
     778  //Check the write page bitmap for dirty pages and write them to disk
     779  while(cbFlush)
     780  {
     781      int startPage = offset >> PAGE_SHIFT;
     782      size = PAGE_SIZE;
     783
     784      if(isDirtyPage(startPage))
     785      {
     786          if(size > cbFlush) {
     787              size = cbFlush;
     788          }
     789          dprintf(("Win32MemMap::flushView for offset %x, size %d", offset, size));
     790
     791          if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) {
     792              dprintf(("Win32MemMap::flushView: SetFilePointer failed to set pos to %x", offset));
     793              goto fail;
     794          }
     795          if(WriteFile(hMemFile, (LPSTR)((ULONG)pMapping + offset), size, &nrBytesWritten, NULL) == FALSE) {
     796              dprintf(("Win32MemMap::flushView: WriteFile failed for %x", (ULONG)pMapping + offset));
     797              goto fail;
     798          }
     799          if(nrBytesWritten != size) {
     800              dprintf(("Win32MemMap::flushView: WriteFile didn't write all bytes for %x", (ULONG)pMapping + offset));
     801              goto fail;
     802          }
     803          clearDirtyPages(startPage, 1);
     804
     805          //We've just flushed the page to disk, so we need to track future writes
     806          //again; Set page to readonly (first memory map, then alias(es))
     807          if(VirtualProtect((LPVOID)((ULONG)pMapping + offset), size, PAGE_READONLY, &oldProt) == FALSE) {
     808              dprintf(("VirtualProtect %x %x PAGE_READWRITE failed with %d!!", (ULONG)pMapping + offset, size, GetLastError()));
     809              goto fail;
     810          }
     811          updateViewPages(offset, size, PAGEVIEW_READONLY);
     812      }
     813
     814      if(cbFlush < size)
     815          break;
     816
     817      cbFlush -= size;
     818      offset  += size;
    674819  }
    675820success:
     821  SetLastError(ERROR_SUCCESS);
    676822  return TRUE;
     823
    677824parmfail:
    678825  SetLastError(ERROR_INVALID_PARAMETER);
     
    724871  if(map) map->AddRef();
    725872  DosLeaveCriticalSection(&globalmapcritsect);
    726   if(!map) dprintf(("Win32MemMap::findMapByFile: couldn't find map with file handle %x", hFile));
     873  if(!map) dprintf2(("Win32MemMap::findMapByFile: couldn't find map with file handle %x", hFile));
    727874  return map;
    728875}
     
    752899void Win32MemMap::deleteAll()
    753900{
    754  Win32MemMap *map = memmaps, *nextmap;
     901 Win32MemMap *map, *nextmap;
    755902 DWORD processId = GetCurrentProcessId();
    756903
    757904  //delete all maps created by this process
    758905  DosEnterCriticalSection(&globalmapcritsect);
     906
     907startdeleteviews:
     908  map = memmaps;
    759909  while(map) {
    760     nextmap = map->next;
    761     if(map->getProcessId() == processId) {
    762         //Delete map directly for executable images (only used internally)
    763         if(map->getImage()) {
    764             delete map;
    765         }
    766         else {
    767             delete map;
    768         }
    769     }
    770     else {
    771         //delete all views created by this process for this map
    772         Win32MemMapView::deleteViews(map);
    773     }
    774     map = nextmap;
     910      map->AddRef(); //make sure it doesn't get deleted
     911
     912      //delete all views created by this process for this map
     913      Win32MemMapView::deleteViews(map);
     914
     915      nextmap = map->next;
     916
     917      //map->Release can delete multiple objects (duplicate memory map), so make
     918      //sure our nextmap pointer remains valid by increasing the refcount
     919      if(nextmap) nextmap->AddRef();
     920      map->Release();
     921
     922      if(nextmap && nextmap->Release() == 0) {
     923          //oops, nextmap was just deleted and is no longer valid
     924          //can't continue from here, so let's start again
     925          dprintf(("oops, nextmap is invalid -> start again (1)"));
     926          goto startdeleteviews;
     927      }
     928
     929      map = nextmap;
     930  }
     931startdelete:
     932  map = memmaps;
     933  while(map) {
     934      nextmap = map->next;
     935      if(map->getProcessId() == processId)
     936      {
     937          //delete map can delete multiple objects (duplicate memory map), so make
     938          //sure our nextmap pointer remains valid by increasing the refcount
     939          if(nextmap) nextmap->AddRef();
     940          delete map;
     941
     942          if(nextmap && nextmap->Release() == 0) {
     943              //oops, nextmap was just deleted and is no longer valid
     944              //can't continue from here, so let's start again
     945              dprintf(("oops, nextmap is invalid -> start again (2)"));
     946              goto startdelete;
     947          }
     948      }
     949      map = nextmap;
    775950  }
    776951  DosLeaveCriticalSection(&globalmapcritsect);
    777952}
    778953//******************************************************************************
    779 //******************************************************************************
    780 Win32MemMapView::Win32MemMapView(Win32MemMap *map, ULONG offset, ULONG size,
    781                                  ULONG fdwAccess)
    782 {
    783  LPVOID           viewaddr = (LPVOID)((ULONG)map->getMappingAddr()+offset);
    784  ULONG            accessAttr = 0;
    785  Win32MemMapView *tmpview  = mapviews;
    786 
    787     errorState      = 0;
    788     mParentMap      = map;
    789     mSize           = size;
    790     mOffset         = offset;
    791     mProcessId      = GetCurrentProcessId();
    792     pShareViewAddr  = NULL;
    793 
    794     switch(fdwAccess) {
    795     case FILE_MAP_READ:
    796         accessAttr  = PAG_READ;
    797         mfAccess    = MEMMAP_ACCESS_READ;
    798         break;
    799     case FILE_MAP_ALL_ACCESS:
    800     case FILE_MAP_WRITE:
    801     case FILE_MAP_WRITE|FILE_MAP_READ:
    802     case FILE_MAP_COPY:
    803         accessAttr  = (PAG_READ|PAG_WRITE);
    804         mfAccess    = MEMMAP_ACCESS_READ | MEMMAP_ACCESS_WRITE;
    805         break;
    806     }
    807     //Named file mappings from other processes are always shared;
    808     //map into our address space
    809     if(map->getMemName() != NULL && map->getProcessId() != mProcessId)
    810     {
    811         //shared memory map, so map it into our address space
    812         if(OSLibDosGetNamedSharedMem((LPVOID *)&viewaddr, map->getMemName()) != OSLIB_NOERROR) {
    813             dprintf(("new OSLibDosGetNamedSharedMem FAILED"));
    814             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    815             errorState = 1;
    816             return;
    817         }
    818         pShareViewAddr = viewaddr;
    819     }
    820 
    821     //view == memory mapping for executable images (only used internally)
    822     if(map->getImage()) {
    823         pMapView = map->getMappingAddr();
    824     }
    825     else {
    826         if(OSLibDosAliasMem(viewaddr, size, &pMapView, accessAttr) != OSLIB_NOERROR) {
    827             dprintf(("new OSLibDosAliasMem FAILED"));
    828             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    829             errorState = 1;
    830             return;
    831         }
    832     }
    833     dprintf(("Win32MemMapView::Win32MemMapView: created %x (alias for %x), size %d", pMapView, viewaddr, size));
    834 
    835     DosEnterCriticalSection(&globalmapcritsect);
    836     if(tmpview == NULL || tmpview->getViewAddr() > pMapView) {
    837         next     = mapviews;
    838         mapviews = this;
    839     }
    840     else {
    841         while(tmpview->next) {
    842             if(tmpview->next->getViewAddr() > pMapView) {
    843                 break;
    844             }
    845             tmpview = tmpview->next;
    846         }
    847         next          = tmpview->next;
    848         tmpview->next = this;
    849     }
    850     DosLeaveCriticalSection(&globalmapcritsect);
    851 }
    852 //******************************************************************************
    853 //******************************************************************************
    854 Win32MemMapView::~Win32MemMapView()
    855 {
    856     if(errorState != 0)
    857         return;
    858 
    859     dprintf(("Win32MemMapView dtor: deleting view %x %x", mOffset, mSize));
    860 
    861     if(mfAccess & MEMMAP_ACCESS_WRITE)
    862         mParentMap->flushView(MMAP_FLUSHVIEW_ALL, mOffset, mSize);
    863 
    864     //Don't free memory for executable image map views (only used internally)
    865     if(!mParentMap->getImage())
    866         OSLibDosFreeMem(pMapView);
    867 
    868     if(pShareViewAddr) {
    869         OSLibDosFreeMem(pShareViewAddr);
    870     }
    871 
    872     DosEnterCriticalSection(&globalmapcritsect);
    873     Win32MemMapView *view = mapviews;
    874 
    875     if(view == this) {
    876         mapviews = next;
    877     }
    878     else {
    879         while(view->next) {
    880             if(view->next == this)
    881                 break;
    882             view = view->next;
    883         }
    884         if(view->next) {
    885                 view->next = next;
    886         }
    887         else    dprintf(("Win32MemMapView::~Win32MemMapView: map not found!! (%x)", this));
    888     }
    889     DosLeaveCriticalSection(&globalmapcritsect);
    890 }
    891 //******************************************************************************
    892 //******************************************************************************
    893 void Win32MemMapView::deleteViews(Win32MemMap *map)
    894 {
    895   DosEnterCriticalSection(&globalmapcritsect);
    896   Win32MemMapView *view = mapviews, *nextview;
    897 
    898   if(view != NULL) {
    899     while(view) {
    900         nextview = view->next;
    901         if(view->getParentMap() == map)
    902         {
    903             DosLeaveCriticalSection(&globalmapcritsect);
    904             delete view;
    905             DosEnterCriticalSection(&globalmapcritsect);
    906         }
    907         view = nextview;
    908     }
    909   }
    910   DosLeaveCriticalSection(&globalmapcritsect);
    911 }
    912 //******************************************************************************
    913 //******************************************************************************
    914 // Win32MemMap::findMapByView
    915 //
    916 // Find the map of the view that contains the specified starting address
    917 // and has the specified access type
     954// Win32MemMapView::markDirtyPages
     955//
     956// Mark pages as dirty (changed) in the write page bitmap
    918957//
    919958// Parameters:
    920959//
    921 //   ULONG address              - view address
    922 //   ULONG *offset              - address of ULONG that receives the offset
    923 //                                in the returned memory map
    924 //   ULONG accessType           - access type:
    925 //                                MEMMAP_ACCESS_READ
    926 //                                MEMMAP_ACCESS_WRITE
    927 //                                MEMMAP_ACCESS_EXECUTE
    928 //
    929 // Returns:
    930 //   <> NULL                    - success, address of parent map object
    931 //   NULL                       - failure
    932 //
    933 //******************************************************************************
    934 //******************************************************************************
    935 Win32MemMap *Win32MemMapView::findMapByView(ULONG address,
    936                                             ULONG *offset,
    937                                             ULONG accessType)
    938 {
    939   Win32MemMap *map = NULL;
    940   ULONG ulOffset;
    941 
    942   if(mapviews == NULL) return NULL;
    943 
    944   DosEnterCriticalSection(&globalmapcritsect);
    945   Win32MemMapView *view = mapviews;
    946   ULONG ulViewAddr;
    947 
    948   if(!offset)  offset = &ulOffset;
    949 
    950   *offset = 0;
    951 
    952   if(view != NULL)
    953   {
    954     do
    955     {
    956       ulViewAddr = (ULONG)view->getViewAddr();
    957 
    958       // if ulViewAddr is > address, we've exhausted
    959       // the sorted list already and can abort search.
    960       if(ulViewAddr <= address)
    961       {
    962         if(ulViewAddr + view->getSize() > address &&
    963            view->getAccessFlags() >= accessType)
    964         {
    965           *offset = view->getOffset() + (address - ulViewAddr);
    966           goto success;
    967         }
    968 
    969         // Not found yet, continue search with next map
    970         view = view->next;
    971       }
    972       else
    973       {
    974           // list is exhausted, abort loop
    975           view = NULL;
    976       }
    977     }
    978     while(view);
    979 
    980     //failure if we get here
    981     view = NULL;
    982   }
    983 success:
    984 #ifdef DEBUG
    985   if(view && !view->getParentMap()->isImageMap())
    986       dprintf(("findMapByView %x %x -> %x off %x",
    987                address,
    988                accessType,
    989                view->getViewAddr(),
    990                *offset));
    991 #endif
    992 
    993   if(view) {
    994       map = view->getParentMap();
    995       if(map) map->AddRef();
    996   }
    997 
    998   DosLeaveCriticalSection(&globalmapcritsect);
    999 
    1000   return map;
    1001 }
    1002 //******************************************************************************
    1003 // Win32MemMap::findView
    1004 //
    1005 // Find the view that contains the specified starting address
     960//   int startpage              - start page
     961//   int nrpages                - number of pages
     962//
     963//
     964//******************************************************************************
     965void Win32MemMap::markDirtyPages(int startpage, int nrpages)
     966{
     967    if(pWriteBitmap == NULL) return; //can be NULL for non-file mappings
     968
     969    for(int i=startpage;i<startpage+nrpages;i++) {
     970        set_bit(i, pWriteBitmap);
     971    }
     972}
     973//******************************************************************************
     974// Win32MemMapView::clearDirtyPages
     975//
     976// Mark pages as clean in the write page bitmap
    1006977//
    1007978// Parameters:
    1008979//
    1009 //   LPVOID address             - view address
    1010 //
    1011 // Returns:
    1012 //   <> NULL                    - success, address view object
    1013 //   NULL                       - failure
    1014 //
    1015 //******************************************************************************
    1016 Win32MemMapView *Win32MemMapView::findView(ULONG address)
    1017 {
    1018   ULONG ulViewAddr;
    1019 
    1020   DosEnterCriticalSection(&globalmapcritsect);
    1021   Win32MemMapView *view = mapviews;
    1022 
    1023   if(view != NULL) {
    1024     while(view) {
    1025         ulViewAddr = (ULONG)view->getViewAddr();
    1026         if(ulViewAddr <= address && ulViewAddr + view->getSize() > address)
    1027         {
    1028             break;
    1029         }
    1030         view = view->next;
    1031     }
    1032   }
    1033   DosLeaveCriticalSection(&globalmapcritsect);
    1034   return view;
    1035 }
    1036 //******************************************************************************
    1037 //******************************************************************************
     980//   int startpage              - start page
     981//   int nrpages                - number of pages
     982//
     983//
     984//******************************************************************************
     985void Win32MemMap::clearDirtyPages(int startpage, int nrpages)
     986{
     987    if(pWriteBitmap == NULL) return; //can be NULL for non-file mappings
     988
     989    for(int i=startpage;i<startpage+nrpages;i++) {
     990        clear_bit(i, pWriteBitmap);
     991    }
     992}
     993//******************************************************************************
     994//******************************************************************************
  • trunk/src/kernel32/mmap.h

    r9911 r9946  
    1 /* $Id: mmap.h,v 1.26 2003-03-06 10:44:34 sandervl Exp $ */
     1/* $Id: mmap.h,v 1.27 2003-03-27 14:13:11 sandervl Exp $ */
    22
    33/*
    44 * Memory mapped class
    55 *
    6  * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
     6 * Copyright 1999-2003 Sander van Leeuwen (sandervl@xs4all.nl)
    77 *
    88 *
     
    1515#include <vmutex.h>
    1616#include "heapshared.h"
     17#include "asmutil.h"
     18
    1719
    1820#ifndef PAGE_SIZE
     
    2527#define MEMMAP_CRITSECTION_NAME "\\SEM32\\ODIN_MMAP.SEM"
    2628
    27 //commit 4 pages at once when the app accesses it
     29//commit 16 pages at once when the app accesses it
    2830#define NRPAGES_TOCOMMIT        16
    2931
     
    3638#define MMAP_FLUSHVIEW_ALL              0xFFFFFFFF
    3739
     40typedef enum
     41{
     42    PAGEVIEW_READONLY,
     43    PAGEVIEW_VIEW,
     44    PAGEVIEW_GUARD
     45} PAGEVIEW;
     46
    3847class Win32MemMapView;
    3948class Win32PeLdrImage;
    4049
    4150//******************************************************************************
     51//Memory mapping class
    4252//******************************************************************************
    4353class Win32MemMap
     
    4757   //Use by PE loader image class only:
    4858   Win32MemMap(Win32PeLdrImage *pImage, ULONG lpImageMem, ULONG size);
    49   ~Win32MemMap();
     59virtual ~Win32MemMap();
    5060
    5161virtual BOOL   Init(DWORD aMSize=0);
     
    5464virtual BOOL   unmapViewOfFile(LPVOID addr);
    5565
     66        BOOL   updateViewPages(ULONG offset, ULONG size, PAGEVIEW flags);
     67        BOOL   allocateMap();
     68
    5669   HFILE  getFileHandle()                { return hMemFile; };
    5770   LPSTR  getMemName()                   { return lpszMapName; };
     71   DWORD  getMapSize()                   { return mSize; };
    5872   DWORD  getProtFlags()                 { return mProtFlags; };
    59    BOOL   setProtFlags(DWORD dwNewProtect);
     73   void   setProtFlags(DWORD dwNewFlags) { mProtFlags = dwNewFlags; };
    6074   LPVOID getMappingAddr()               { return pMapping; };
    6175   DWORD  getProcessId()                 { return mProcessId;};
     
    6579
    6680   void   AddRef()                       { ++referenced; };
    67    void   Release();
     81   int    Release();
     82
     83   void   AddView()                      { ++nrMappings; };
     84   void   RemoveView()                   { --nrMappings; };
     85
     86
     87   void   markDirtyPages(int startpage, int nrpages);
     88   void   clearDirtyPages(int startpage, int nrpages);
     89   BOOL   isDirtyPage(int pagenr)        { return test_bit(pagenr, pWriteBitmap) != 0; };
    6890
    6991virtual BOOL   invalidatePages(ULONG offset, ULONG size);
     
    109131   void  *pMapping;
    110132
     133   char  *pWriteBitmap;
     134
    111135   ULONG  nrMappings;
    112136
     
    116140
    117141   Win32PeLdrImage *image;
     142
     143   Win32MemMapView *views;
    118144
    119145private:
     
    122148};
    123149//******************************************************************************
     150//Duplicate memory mapping class (duplicate map with different protection flags
     151//associated with an existing memory map)
     152//******************************************************************************
     153class Win32MemMapDup : public Win32MemMap
     154{
     155public:
     156            Win32MemMapDup(Win32MemMap *parent, HFILE hFile, ULONG size, ULONG fdwProtect, LPSTR lpszName);
     157   virtual ~Win32MemMapDup();
     158
     159virtual BOOL   Init(DWORD aMSize=0);
     160virtual BOOL   flushView(ULONG viewaddr, ULONG offset, ULONG cbFlush);
     161virtual LPVOID mapViewOfFile(ULONG size, ULONG offset, ULONG fdwAccess);
     162virtual BOOL   unmapViewOfFile(LPVOID addr);
     163
     164virtual BOOL   invalidatePages(ULONG offset, ULONG size);
     165virtual BOOL   commitGuardPage(ULONG ulFaultAddr, ULONG offset, BOOL fWriteAccess);
     166virtual BOOL   commitPage(ULONG ulFaultAddr, ULONG offset, BOOL fWriteAccess, int nrpages = NRPAGES_TOCOMMIT);
     167
     168protected:
     169            Win32MemMap *parent;
     170
     171private:
     172};
     173//******************************************************************************
    124174//Memory mapped file View Class
    125175//******************************************************************************
     
    127177{
    128178public:
    129    Win32MemMapView(Win32MemMap *map, ULONG offset, ULONG size, ULONG fdwAccess);
     179   Win32MemMapView(Win32MemMap *parent, ULONG offset, ULONG size, ULONG fdwAccess, Win32MemMap *owner = NULL);
    130180  ~Win32MemMapView();
     181
     182   BOOL   changePageFlags(ULONG offset, ULONG size, PAGEVIEW flags);
    131183
    132184   DWORD  getAccessFlags()               { return mfAccess; };
     
    138190
    139191Win32MemMap *getParentMap()              { return mParentMap;};
     192Win32MemMap *getOwnerMap()               { return mOwnerMap; };
     193
    140194   DWORD  getProcessId()                 { return mProcessId;};
     195
     196   void   markCOWPages(int startpage, int nrpages);
     197   BOOL   isCOWPage(int pagenr)          { return (pCOWBitmap) ? (test_bit(pagenr, pCOWBitmap) != 0) : FALSE; };
    141198
    142199static void             deleteViews(Win32MemMap *map);
    143200static Win32MemMap     *findMapByView(ULONG address, ULONG *offset = NULL,
    144201                                      ULONG accessType = MEMMAP_ACCESS_READ);
     202static int              findViews(Win32MemMap *map, int nrViews, Win32MemMapView *viewarray[]);
    145203static Win32MemMapView *findView(ULONG address);
    146204
     
    171229   void  *pMapView, *pShareViewAddr;
    172230
     231   char  *pCOWBitmap;
     232
     233   //parent map object; memory map that contains the original memory map
    173234   Win32MemMap *mParentMap;
     235   //owner map object (can be NULL); duplicate memory map that created this view
     236   Win32MemMap *mOwnerMap;
    174237
    175238private:
     
    182245//******************************************************************************
    183246
     247#pragma data_seg(_GLOBALDATA)
     248extern CRITICAL_SECTION_OS2 globalmapcritsect;
     249#pragma data_seg()
     250
    184251void InitializeMemMaps();
    185252
Note: See TracChangeset for help on using the changeset viewer.