Ignore:
Timestamp:
Nov 11, 2010, 1:19:13 PM (15 years ago)
Author:
dmik
Message:

kernel32: Allow FILE_MAP_READ access for PAGE_WRITECOPY mappings. Fixes #14.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/mmap.cpp

    r10572 r21472  
    3535#include "oslibmem.h"
    3636#include <winimagepeldr.h>
    37 #include <custombuild.h> 
     37#include <custombuild.h>
    3838#include "asmutil.h"
    3939
     
    5454//******************************************************************************
    5555//******************************************************************************
    56 void WIN32API SetCustomMMapSemName(LPSTR pszSemName) 
     56void WIN32API SetCustomMMapSemName(LPSTR pszSemName)
    5757{
    5858    pszMMapSemName = pszSemName;
     
    7979//******************************************************************************
    8080Win32MemMap::Win32MemMap(HANDLE hfile, ULONG size, ULONG fdwProtect, LPSTR lpszName)
    81                : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), 
     81               : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0),
    8282                 image(0), pWriteBitmap(NULL), lpszFileName(NULL)
    8383{
     
    105105//******************************************************************************
    106106Win32MemMap::Win32MemMap(Win32PeLdrImage *pImage, ULONG baseAddress, ULONG size)
    107                : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0), 
     107               : nrMappings(0), pMapping(NULL), mMapAccess(0), referenced(0),
    108108                 image(0), pWriteBitmap(NULL), lpszFileName(NULL)
    109109{
     
    273273    dprintf(("Win32MemMap::commitRange %x (faultaddr %x)", pageAddr, lpPageFaultAddr));
    274274
    275     if(fWriteAccess) 
     275    if(fWriteAccess)
    276276    {//writes are handled on a per-page basis
    277         for(int i=0;i<nrpages;i++) 
     277        for(int i=0;i<nrpages;i++)
    278278        {
    279279            if(commitPage(ulFaultAddr, offset, TRUE, 1) == FALSE) {
     
    305305//   FALSE                      - failure
    306306//
    307 // NOTE: 
     307// NOTE:
    308308//   We handle only one pages for write access!
    309309//
     
    327327  }
    328328
    329   if(fWriteAccess && (mProtFlags & PAGE_WRITECOPY)) 
     329  if(fWriteAccess && (mProtFlags & PAGE_WRITECOPY))
    330330  {//this is a COW map, call commitGuardPage to handle write faults
    331331      return commitGuardPage(ulFaultAddr, offset, fWriteAccess);
     
    340340  if(fWriteAccess) {
    341341      Win32MemMapView *view = Win32MemMapView::findView(ulFaultAddr);
    342       if(view) { 
     342      if(view) {
    343343          if(!(view->getAccessFlags() & MEMMAP_ACCESS_WRITE)) {
    344344              dprintf(("Write access for a readonly view!!"));
     
    354354  int faultsize = nrpages*PAGE_SIZE;
    355355
    356   if(fWriteAccess) 
     356  if(fWriteAccess)
    357357  {//write access needs special care, so do that on a per page basis
    358358      dprintf(("Write access -> handle only one page"));
     
    365365  }
    366366
    367   while(faultsize) 
     367  while(faultsize)
    368368  {
    369369        if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) {
     
    386386            updateViewPages(offset, memInfo.RegionSize, (fWriteAccess) ? PAGEVIEW_VIEW : PAGEVIEW_READONLY);
    387387
    388             if(hMemFile != -1) 
     388            if(hMemFile != -1)
    389389            {//now read the page(s) from disk
    390390                DWORD size;
     
    408408                    goto fail;
    409409                }
    410             }           
    411             //We set the protection flags to PAGE_READONLY, unless this pagefault 
     410            }
     411            //We set the protection flags to PAGE_READONLY, unless this pagefault
    412412            //was due to a write access
    413413            //This way we can track dirty pages which need to be flushed to
    414414            //disk when FlushViewOfFile is called or the map is closed.
    415             if(!fWriteAccess) 
     415            if(!fWriteAccess)
    416416            {
    417417                if(VirtualProtect((LPVOID)pageAddr, memInfo.RegionSize, PAGE_READONLY, &oldProt) == FALSE) {
     
    420420                }
    421421            }
    422             else 
     422            else
    423423            {//make these pages as dirty
    424424                ULONG startPage  = (pageAddr - (ULONG)pMapping) >> PAGE_SHIFT;
     
    431431                markDirtyPages(startPage, nrPages);
    432432
    433                 //Write access means that the next time the corresponding COW page 
     433                //Write access means that the next time the corresponding COW page
    434434                //is touched, we need to reload it. So set the GUARD flags.
    435435                updateViewPages(offset, memInfo.RegionSize, PAGEVIEW_GUARD);
    436436            }
    437437        }
    438         else 
    439         if(fWriteAccess) 
     438        else
     439        if(fWriteAccess)
    440440        {
    441441            //mark these pages as dirty
     
    457457            updateViewPages(offset, memInfo.RegionSize, PAGEVIEW_VIEW);
    458458
    459             //Write access means that the next time the corresponding COW page 
     459            //Write access means that the next time the corresponding COW page
    460460            //is touched, we need to reload it. So set the GUARD flags.
    461461            updateViewPages(offset, memInfo.RegionSize, PAGEVIEW_GUARD);
     
    519519   memcpy((LPVOID)pageAddr, (char *)pMapping+ulOffset, PAGE_SIZE);
    520520
    521    if(fWriteAccess) 
     521   if(fWriteAccess)
    522522   {//copy on write; mark pages as private
    523523        DWORD startpage = (ulOffset) >> PAGE_SHIFT;
     
    526526
    527527        Win32MemMapView *view = Win32MemMapView::findView(ulFaultAddr);
    528         if(view) 
     528        if(view)
    529529        {
    530530            view->markCOWPages(startpage, 1);
     
    532532        else DebugInt3(); //oh, oh
    533533   }
    534    else 
     534   else
    535535   {//read access; must set the map + all views to READONLY to track write access
    536536
     
    574574    int localmaps;
    575575
    576     if(views) 
     576    if(views)
    577577    {
    578578        localmaps = Win32MemMapView::findViews(this, nrMappings, views);
    579         if(localmaps <= nrMappings) 
     579        if(localmaps <= nrMappings)
    580580        {
    581             for(int i=0;i<localmaps;i++) 
     581            for(int i=0;i<localmaps;i++)
    582582            {
    583583                views[i]->changePageFlags(offset, size, flags);
    584             }           
     584            }
    585585        }
    586586        else {
     
    619619        dprintf(("ERROR: Win32MemMap::invalidatePages: VirtualFree failed!!"));
    620620    }
    621     //invalidate all shared COW pages too by setting the GUARD flag 
     621    //invalidate all shared COW pages too by setting the GUARD flag
    622622    //(which forces a resync the next time the app touches them)
    623623    return updateViewPages(offset, size, PAGEVIEW_GUARD);
     
    640640
    641641    //Memory has already been allocated for executable image maps (only used internally)
    642     if(!pMapping && nrMappings == 0) 
     642    if(!pMapping && nrMappings == 0)
    643643    {//if not mapped, reserve/commit entire view
    644644        //SvL: Always read/write access or else ReadFile will crash once we
     
    648648        //     flag it will also crash)
    649649        //NOTE: If this is ever changed, then we must update setProtFlags!!!!
    650        
     650
    651651        //All named file mappings are shared (files & memory only)
    652652        if(lpszMapName) {
     
    687687    return TRUE;
    688688
    689 fail: 
     689fail:
    690690    return FALSE;
    691691}
     
    702702//                                FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_COPY
    703703//                                FILE_MAP_ALL_ACCESS
    704 //                               
     704//
    705705//
    706706// Returns:
     
    723723    if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE))
    724724        goto parmfail;
    725     if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY)))
     725    // CreateFileMapping docs say that PAGE_WRITECOPY is equivalent to PAGE_READONLY and thus
     726    // is okay for FILE_MAP_READ too
     727    if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY|PAGE_WRITECOPY)))
    726728        goto parmfail;
    727    
     729
    728730    if (fdwAccess != FILE_MAP_ALL_ACCESS)
    729731        if((fdwAccess & FILE_MAP_COPY) && !(mProtFlags & PAGE_WRITECOPY))
     
    786788
    787789    view = Win32MemMapView::findView((ULONG)addr);
    788     if(view == NULL) 
     790    if(view == NULL)
    789791        goto fail;
    790792
     
    825827      goto parmfail;
    826828
    827   if(viewaddr != MMAP_FLUSHVIEW_ALL) 
     829  if(viewaddr != MMAP_FLUSHVIEW_ALL)
    828830  {
    829831      view = Win32MemMapView::findView(viewaddr);
     
    854856
    855857  //Check the write page bitmap for dirty pages and write them to disk
    856   while(cbFlush) 
     858  while(cbFlush)
    857859  {
    858860      int startPage = offset >> PAGE_SHIFT;
     
    944946  Win32MemMap *map = memmaps;
    945947
    946   if(map != NULL) 
     948  if(map != NULL)
    947949  {
    948950    while(map) {
    949951        //TODO: we currently don't support sharing file maps between processes
    950         if(map->mProcessId == processId && map->lpszFileName) 
     952        if(map->mProcessId == processId && map->lpszFileName)
    951953        {
    952954            if(!strcmp(map->lpszFileName, szFileName))
     
    10201022  while(map) {
    10211023      nextmap = map->next;
    1022       if(map->getProcessId() == processId) 
     1024      if(map->getProcessId() == processId)
    10231025      {
    10241026          //delete map can delete multiple objects (duplicate memory map), so make
Note: See TracChangeset for help on using the changeset viewer.