Ignore:
Timestamp:
Oct 26, 2000, 7:21:39 PM (25 years ago)
Author:
sandervl
Message:

registry fixes (heap corruption) + VirtualAlloc change

File:
1 edited

Legend:

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

    r4279 r4534  
    1 /* $Id: virtual.cpp,v 1.34 2000-09-18 19:26:16 sandervl Exp $ */
     1/* $Id: virtual.cpp,v 1.35 2000-10-26 17:21:39 sandervl Exp $ */
    22
    33/*
     
    2828#include "oslibdos.h"
    2929
    30 #define DBG_LOCALLOG    DBG_virtual
     30#define DBG_LOCALLOG    DBG_virtual
    3131#include "dbglocal.h"
    3232
     
    4040 *
    4141 * RETURNS
    42  *      Handle: Success
    43  *      0: Mapping object does not exist
    44  *      NULL: Failure
     42 *  Handle: Success
     43 *  0: Mapping object does not exist
     44 *  NULL: Failure
    4545 */
    4646HANDLE WINAPI CreateFileMappingA(
     
    8282 *
    8383 * RETURNS
    84  *      Handle: Success
    85  *      NULL: Failure
     84 *  Handle: Success
     85 *  NULL: Failure
    8686 */
    8787HANDLE WINAPI OpenFileMappingA(
     
    113113 *
    114114 * RETURNS
    115  *      Starting address of mapped view
    116  *      NULL: Failure
     115 *  Starting address of mapped view
     116 *  NULL: Failure
    117117 */
    118118LPVOID WINAPI MapViewOfFile(
     
    134134 *
    135135 * RETURNS
    136  *      Starting address of mapped view
    137  *      NULL: Failure
     136 *  Starting address of mapped view
     137 *  NULL: Failure
    138138 */
    139139LPVOID WINAPI MapViewOfFileEx(
     
    155155 *
    156156 * RETURNS
    157  *      TRUE: Success
    158  *      FALSE: Failure
     157 *  TRUE: Success
     158 *  FALSE: Failure
    159159 */
    160160BOOL WINAPI FlushViewOfFile(
     
    185185 *
    186186 * NOTES
    187  *      Should addr be an LPCVOID?
     187 *  Should addr be an LPCVOID?
    188188 *
    189189 * RETURNS
    190  *      TRUE: Success
    191  *      FALSE: Failure
     190 *  TRUE: Success
     191 *  FALSE: Failure
    192192 */
    193193BOOL WINAPI UnmapViewOfFile(LPVOID addr /* [in] Address where mapped view begins */
     
    216216 *
    217217 * Helper function to map a file to memory:
    218  *  name                        -       file name
    219  *  [RETURN] ptr                -       pointer to mapped file
     218 *  name            -   file name
     219 *  [RETURN] ptr        -   pointer to mapped file
    220220 */
    221221HANDLE WINAPI VIRTUAL_MapFileW( LPCWSTR name , LPVOID *lpMapping, BOOL fReadIntoMemory)
     
    241241 *
    242242 * Helper function to map a file to memory:
    243  *  name                        -       file name
    244  *  [RETURN] ptr                -       pointer to mapped file
     243 *  name            -   file name
     244 *  [RETURN] ptr        -   pointer to mapped file
    245245 */
    246246HANDLE WINAPI VIRTUAL_MapFileA( LPCSTR name , LPVOID *lpMapping, BOOL fReadIntoMemory)
     
    277277  if (cbSize > 0x7fc00000)  /* 2Gb - 4Mb */
    278278  {
    279         dprintf(("VirtualAlloc: size too large"));
     279    dprintf(("VirtualAlloc: size too large"));
    280280        SetLastError( ERROR_OUTOFMEMORY );
    281281        return NULL;
     
    285285       (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
    286286  {
    287         dprintf(("VirtualAlloc: Invalid parameter"));
     287        dprintf(("VirtualAlloc: Invalid parameter"));
    288288        SetLastError( ERROR_INVALID_PARAMETER );
    289289        return NULL;
     
    295295        flag = PAG_COMMIT;
    296296  }
    297  
     297
    298298  if(fdwAllocationType & MEM_RESERVE) {
    299         //SvL: DosRead crashes if memory is initially reserved with write
     299    //SvL: DosRead crashes if memory is initially reserved with write
    300300        //     access disabled (OS/2 bug) even if the commit sets the page
    301301        //     flags to read/write:
    302         // DosSetMem does not alter the 16 bit selectors so if you change memory
    303         // attributes and then access the memory with a 16 bit API (such as DosRead),
    304         // it will have the old (alloc time) attributes
    305         flag |= PAG_READ|PAG_WRITE;
     302    // DosSetMem does not alter the 16 bit selectors so if you change memory
     303    // attributes and then access the memory with a 16 bit API (such as DosRead),
     304    // it will have the old (alloc time) attributes
     305    flag |= PAG_READ|PAG_WRITE;
    306306  }
    307307  if(fdwProtect & PAGE_READONLY)     flag |= PAG_READ;
     
    315315
    316316  if(fdwProtect & PAGE_GUARD) {
    317         dprintf(("ERROR: PAGE_GUARD bit set for VirtualAlloc -> we don't support this right now!"));
     317        dprintf(("ERROR: PAGE_GUARD bit set for VirtualAlloc -> we don't support this right now!"));
    318318        flag |= PAG_GUARD;
    319319  }
     
    326326  }
    327327
    328   if(lpvAddress) 
     328  if(lpvAddress)
    329329  {
    330330   Win32MemMap *map;
    331331   ULONG offset, nrpages, accessflags = 0;
    332332
    333         nrpages = cbSize >> PAGE_SHIFT;
    334         if(cbSize & 0xFFF)
    335                 nrpages++;
    336 
    337         if(flag & PAG_READ) {
    338                 accessflags |= MEMMAP_ACCESS_READ;
    339         }
    340         if(flag & PAG_WRITE) {
    341                 accessflags |= MEMMAP_ACCESS_WRITE;
    342         }
    343         if(flag & PAG_EXECUTE) {
    344                 accessflags |= MEMMAP_ACCESS_EXECUTE;
    345         }
    346         map = Win32MemMapView::findMapByView((ULONG)lpvAddress, &offset, accessflags);
    347         if(map) {
    348                 //TODO: We don't allow protection flag changes for mmaped files now
    349                 map->commitPage(offset, FALSE, nrpages);
    350                 return lpvAddress;
    351         }
     333    nrpages = cbSize >> PAGE_SHIFT;
     334    if(cbSize & 0xFFF)
     335        nrpages++;
     336
     337    if(flag & PAG_READ) {
     338        accessflags |= MEMMAP_ACCESS_READ;
     339    }
     340    if(flag & PAG_WRITE) {
     341        accessflags |= MEMMAP_ACCESS_WRITE;
     342    }
     343    if(flag & PAG_EXECUTE) {
     344        accessflags |= MEMMAP_ACCESS_EXECUTE;
     345    }
     346    map = Win32MemMapView::findMapByView((ULONG)lpvAddress, &offset, accessflags);
     347    if(map) {
     348        //TODO: We don't allow protection flag changes for mmaped files now
     349        map->commitPage(offset, FALSE, nrpages);
     350        return lpvAddress;
     351    }
    352352  }
    353353
     
    362362    if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > 4096 )
    363363    { //knut: AND more than one page
    364       char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
    365       ULONG size, os2flags;
    366 
    367       while(newbase >= (char *)lpvAddress)
    368       {  //knut: should check first page to!!
    369         size     = 4096;
    370         os2flags = 0;
    371         rc = OSLibDosQueryMem(newbase, &size, &os2flags);
    372         if(rc)
    373           break;
    374 
    375         if(os2flags & PAG_COMMIT)
     364        char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
     365        ULONG size, os2flags;
     366
     367        while(newbase >= (char *)lpvAddress)
     368        {     //knut: should check first page to!!
     369            size     = 4096;
     370            os2flags = 0;
     371            rc = OSLibDosQueryMem(newbase, &size, &os2flags);
     372            if(rc)
     373                break;
     374
     375            if(os2flags & PAG_COMMIT)
     376            {
     377                newbase += 4096;
     378                break;
     379            }
     380            newbase -= 4096;
     381        }
     382
     383        if(rc == 0)
    376384        {
    377           newbase += 4096;
    378           break;
     385            //In case it wants to commit bytes that fall into the last
     386            //page of the previous commit command
     387            if(cbSize > ((int)newbase - (int)lpvAddress))
     388                rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
    379389        }
    380         newbase -= 4096;
    381       }
    382 
    383       if(rc == 0)
    384       {
    385         //In case it wants to commit bytes that fall into the last
    386         //page of the previous commit command
    387         if(cbSize > ((int)newbase - (int)lpvAddress))
    388                 rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
    389       }
    390       else      return(NULL);
     390        else  return(NULL);
    391391
    392392    }
    393393    else
    394394    {
    395         if(rc == OSLIB_ERROR_INVALID_ADDRESS) {
    396                 rc = OSLibDosAllocMem(&Address, cbSize, flag );
    397         }
    398         else
    399         if(rc)  dprintf(("Unexpected DosSetMem error %x", rc));
     395        if(rc == OSLIB_ERROR_INVALID_ADDRESS) {
     396            rc = OSLibDosAllocMem(&Address, cbSize, flag );
     397        }
     398        else {
     399            if(rc) {
     400                //check if the app tries to commit an already commited part of memory or change the protection flags
     401                ULONG size = cbSize, os2flags, newrc;
     402                newrc = OSLibDosQueryMem(lpvAddress, &size, &os2flags);
     403                if(newrc == 0) {
     404                    if(size >= cbSize && (os2flags & PAG_COMMIT)) {
     405                            dprintf(("VirtualAlloc: commit on committed memory"));
     406                            if((flag & (PAG_READ|PAG_WRITE|PAG_EXECUTE)) != (os2flags & (PAG_READ|PAG_WRITE|PAG_EXECUTE)))
     407                            {   //change protection flags
     408                                DWORD tmp;
     409                                if(VirtualProtect(lpvAddress, cbSize, fdwAllocationType, &tmp) == TRUE) {
     410                                    return lpvAddress;
     411                                }
     412                                dprintf(("ERROR: VirtualAlloc: commit on committed memory -> VirtualProtect failed!!"));
     413                                return NULL;
     414                            }
     415                            //else everything ok
     416                            return lpvAddress;
     417                    }
     418                    else    dprintf(("Unexpected DosSetMem error %x", rc));
     419                }
     420                else {
     421                    dprintf(("Unexpected DosQueryMem error %x", newrc));
     422                }
     423            }
     424        }
    400425    }
    401426  }
     
    446471    if(rc)
    447472    {
    448         if(rc == 32803) { //SvL: ERROR_ALIAS
    449                 dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d; app tries to decommit aliased memory; ignore", rc));
    450                 return(TRUE);
    451         }
    452         dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d\n", rc));
    453         SetLastError(ERROR_INVALID_ADDRESS);
    454         return(FALSE);
     473    if(rc == 32803) { //SvL: ERROR_ALIAS
     474            dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d; app tries to decommit aliased memory; ignore", rc));
     475        return(TRUE);
     476    }
     477        dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d\n", rc));
     478        SetLastError(ERROR_INVALID_ADDRESS);
     479    return(FALSE);
    455480    }
    456481  }
     
    492517  if(pfdwOldProtect == NULL) {
    493518        dprintf(("WARNING: pfdwOldProtect == NULL"));
    494         SetLastError(ERROR_INVALID_PARAMETER);
     519    SetLastError(ERROR_INVALID_PARAMETER);
    495520        return(FALSE);
    496521  }
     
    542567  cb = (cbSize & 0xFFF) + offset; // !!! added, some optimization :)
    543568  if( cb > 0 ) { // changed
    544         npages++;
     569    npages++;
    545570  }
    546571  if( cb > 4096 ) { // changed, note '>' sign ( not '>=' ) 4096 is exactly one page
    547         npages++;
     572    npages++;
    548573  }
    549574
     
    574599  if(pmbiBuffer == NULL || cbLength != sizeof(MEMORY_BASIC_INFORMATION)) // check parameters
    575600  {
    576         dprintf(("WARNING: invalid parameter"));
    577         SetLastError(ERROR_INVALID_PARAMETER);
    578         return 0;                             // nothing to return
     601    dprintf(("WARNING: invalid parameter"));
     602    SetLastError(ERROR_INVALID_PARAMETER);
     603        return 0;                             // nothing to return
    579604  }
    580605
     
    588613  if(rc)
    589614  {
    590         dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
    591                   lpBase, cbLength, rc));
    592         SetLastError(ERROR_INVALID_PARAMETER);
    593         return 0;
     615        dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
     616                  lpBase, cbLength, rc));
     617    SetLastError(ERROR_INVALID_PARAMETER);
     618        return 0;
    594619  }
    595620
     
    625650
    626651  if(!(dAttr & PAG_SHARED))
    627         pmbiBuffer->Type = MEM_PRIVATE;
     652        pmbiBuffer->Type = MEM_PRIVATE;
    628653
    629654  //TODO: This is not correct: AllocationProtect should contain the protection
     
    631656  pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
    632657  if(dAttr & PAG_BASE) {
    633         pmbiBuffer->AllocationBase = lpBase;
     658        pmbiBuffer->AllocationBase = lpBase;
    634659  }
    635660  else
    636661  {
    637         while(lpBase > 0)
    638         {
    639                 rc = OSLibDosQueryMem(lpBase, &cbRangeSize, &dAttr);
    640                 if(rc) {
    641                         dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
    642                                   lpBase, cbLength, rc));
    643                         break;
    644                 }
    645                 if(dAttr & PAG_BASE) {
    646                         pmbiBuffer->AllocationBase = lpBase;
    647                         break;
    648                 }
    649                 lpBase = (LPVOID)((ULONG)lpBase - PAGE_SIZE);
    650         }
     662        while(lpBase > 0)
     663        {
     664            rc = OSLibDosQueryMem(lpBase, &cbRangeSize, &dAttr);
     665            if(rc) {
     666                dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
     667                          lpBase, cbLength, rc));
     668                break;
     669            }
     670            if(dAttr & PAG_BASE) {
     671                pmbiBuffer->AllocationBase = lpBase;
     672                break;
     673            }
     674            lpBase = (LPVOID)((ULONG)lpBase - PAGE_SIZE);
     675    }
    651676  }
    652677  return sizeof(MEMORY_BASIC_INFORMATION);
     
    752777  if (cbSize > 0x7fc00000)  /* 2Gb - 4Mb */
    753778  {
    754         dprintf(("VirtualAllocShared: size too large"));
     779    dprintf(("VirtualAllocShared: size too large"));
    755780        SetLastError( ERROR_OUTOFMEMORY );
    756781        return NULL;
     
    760785       (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
    761786  {
    762         dprintf(("VirtualAllocShared: Invalid parameter"));
     787    dprintf(("VirtualAllocShared: Invalid parameter"));
    763788        SetLastError( ERROR_INVALID_PARAMETER );
    764789        return NULL;
     
    781806
    782807  if(fdwProtect & PAGE_GUARD) {
    783         dprintf(("ERROR: PAGE_GUARD bit set for VirtualAllocShared -> we don't support this right now!"));
     808    dprintf(("ERROR: PAGE_GUARD bit set for VirtualAllocShared -> we don't support this right now!"));
    784809        flag |= PAG_GUARD;
    785810  }
Note: See TracChangeset for help on using the changeset viewer.