Ignore:
Timestamp:
Aug 26, 1999, 2:56:02 PM (26 years ago)
Author:
sandervl
Message:

Cleanup

File:
1 edited

Legend:

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

    r690 r705  
    1 /* $Id: virtual.cpp,v 1.7 1999-08-25 14:27:07 sandervl Exp $ */
     1/* $Id: virtual.cpp,v 1.8 1999-08-26 12:55:37 sandervl Exp $ */
    22
    33/*
    44 * Win32 virtual memory functions
    55 *
    6  * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
     6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
     7 * Copyright 1998 Knut St. Osmundsen
     8 * Copyright 1998 Peter FitzSimmons
    79 *
    810 * Parts (VIRTUAL_MapFileA/W) based on Wine code (memory\virtual.c):
     
    2123#include <handlemanager.h>
    2224#include "mmap.h"
     25#include "oslibdos.h"
    2326
    2427/***********************************************************************
     
    239242    return hMapping;
    240243}
     244
     245//******************************************************************************
     246//******************************************************************************
     247LPVOID WIN32API VirtualAlloc(LPVOID lpvAddress, DWORD cbSize, DWORD fdwAllocationType,
     248                             DWORD fdwProtect)
     249{
     250 PVOID Address = lpvAddress;
     251 ULONG flag = 0, base;
     252 APIRET rc;
     253
     254  dprintf(("VirtualAlloc at %X; %d bytes, fAlloc %d, fProtect %d\n", (int)lpvAddress, cbSize, fdwAllocationType, fdwProtect));
     255
     256  if (cbSize > 0x7fc00000)  /* 2Gb - 4Mb */
     257  {
     258        dprintf(("VirtualAlloc: size too large"));
     259        SetLastError( ERROR_OUTOFMEMORY );
     260        return NULL;
     261  }
     262
     263  if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
     264       (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
     265  {
     266        dprintf(("VirtualAlloc: Invalid parameter"));
     267        SetLastError( ERROR_INVALID_PARAMETER );
     268        return NULL;
     269  }
     270
     271  if(fdwAllocationType & MEM_COMMIT) {
     272        dprintf(("VirtualAlloc: commit\n"));
     273        flag = PAG_COMMIT;
     274  }
     275  if(fdwProtect & PAGE_READONLY)          flag |= PAG_READ;
     276  if(fdwProtect & PAGE_READWRITE)         flag |= (PAG_READ | PAG_WRITE);
     277  if(fdwProtect & PAGE_WRITECOPY)         flag |= (PAG_READ | PAG_WRITE);
     278
     279  if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
     280  if(fdwProtect & PAGE_EXECUTE_READ)      flag |= (PAG_EXECUTE | PAG_READ);
     281  if(fdwProtect & PAGE_EXECUTE)           flag |= PAG_EXECUTE;
     282
     283  if(fdwProtect & PAGE_GUARD)             flag |= PAG_GUARD;
     284
     285  //just do this if other options are used
     286  if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
     287  {
     288        dprintf(("VirtualAlloc: Unknown protection flags, default to read/write"));
     289        flag |= PAG_READ | PAG_WRITE;
     290  }
     291
     292  if(fdwAllocationType & MEM_COMMIT && lpvAddress != NULL)
     293  {
     294    Address = lpvAddress;
     295
     296    rc = OSLibDosSetMem(lpvAddress, cbSize, flag);
     297
     298    //might try to commit larger part with same base address
     299    if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > 4096 )
     300    { //knut: AND more than one page
     301      char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
     302      ULONG size, os2flags;
     303
     304      while(newbase >= (char *)lpvAddress)
     305      {  //knut: should check first page to!!
     306        size     = 4096;
     307        os2flags = 0;
     308        rc = OSLibDosQueryMem(newbase, &size, &os2flags);
     309        if(rc)
     310          break;
     311
     312        if(os2flags & PAG_COMMIT)
     313        {
     314          newbase += 4096;
     315          break;
     316        }
     317        newbase -= 4096;
     318      }
     319
     320      if(rc == 0)
     321      {
     322        //In case it wants to commit bytes that fall into the last
     323        //page of the previous commit command
     324        if(cbSize > ((int)newbase - (int)lpvAddress))
     325                rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
     326      }
     327      else      return(NULL);
     328
     329    }
     330    else
     331    {
     332        if(rc == OSLIB_ERROR_INVALID_ADDRESS) {
     333                rc = OSLibDosAllocMem(&Address, cbSize, flag );
     334        }
     335        else
     336        if(rc)  dprintf(("Unexpected DosSetMem error %x", rc));
     337    }
     338  }
     339  else
     340  {
     341    rc = OSLibDosAllocMem(&Address, cbSize, flag);
     342  }
     343
     344  if(rc)
     345  {
     346    dprintf(("DosSetMem returned %d\n", rc));
     347    SetLastError( ERROR_OUTOFMEMORY );
     348    return(NULL);
     349  }
     350
     351  dprintf(("VirtualAlloc returned %X\n", Address));
     352  return(Address);
     353}
     354//******************************************************************************
     355//******************************************************************************
     356BOOL WIN32API VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD FreeType)
     357{
     358 APIRET rc;
     359
     360  dprintf(("VirtualFree at %d; %d bytes, freetype %d\n", (int)lpvAddress, cbSize, FreeType));
     361
     362  if(lpvAddress == NULL || cbSize == 0) {
     363        SetLastError(ERROR_INVALID_PARAMETER);
     364        return(FALSE);
     365  }
     366  if(FreeType & MEM_DECOMMIT) {
     367        rc = OSLibDosSetMem(lpvAddress, cbSize, PAG_DECOMMIT);
     368  }
     369  else  rc = OSLibDosFreeMem(lpvAddress);    //MEM_RELEASE, cbSize == 0 (or should be)
     370
     371  if(rc) {
     372        SetLastError(ERROR_GEN_FAILURE);
     373        return(FALSE);
     374  }
     375  return(TRUE);
     376}
     377//******************************************************************************
     378//LPVOID lpvAddress;            /* address of region of committed pages */
     379//DWORD  cbSize;                /* size of the region   */
     380//DWORD  fdwNewProtect;         /* desired access protection    */
     381//PDWORD pfdwOldProtect;        /* address of variable to get old protection    */
     382//TODO: Not 100% complete
     383//TODO: SetLastError on failure
     384//******************************************************************************
     385BOOL WIN32API VirtualProtect(LPVOID lpvAddress, DWORD cbSize, DWORD fdwNewProtect,
     386                             DWORD *pfdwOldProtect)
     387{
     388 APIRET rc;
     389 ULONG  pageFlags = 0;
     390 int npages;
     391
     392  dprintf(("VirtualProtect %X; %d bytes, new flags %X (%X)\n", (int)lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect));
     393  if(pfdwOldProtect == NULL)
     394        return(FALSE);
     395
     396  rc = OSLibDosQueryMem(lpvAddress, &cbSize, &pageFlags);
     397  if(rc) {
     398        dprintf(("DosQueryMem returned %d\n", rc));
     399        return(FALSE);
     400  }
     401  dprintf(("Old memory flags %X\n", pageFlags));
     402  *pfdwOldProtect = 0;
     403  if(pageFlags & PAG_READ && !(pageFlags & PAG_WRITE))
     404        *pfdwOldProtect |= PAGE_READONLY;
     405  if(pageFlags & (PAG_WRITE))
     406        *pfdwOldProtect |= PAGE_READWRITE;
     407
     408  if(pageFlags & (PAG_WRITE | PAG_EXECUTE))
     409        *pfdwOldProtect |= PAGE_EXECUTE_READWRITE;
     410  else
     411  if(pageFlags & PAG_EXECUTE)
     412        *pfdwOldProtect |= PAGE_EXECUTE_READ;
     413
     414  if(pageFlags & PAG_GUARD)
     415        *pfdwOldProtect |= PAGE_GUARD;
     416  pageFlags = 0;
     417
     418  if(fdwNewProtect & PAGE_READONLY)     pageFlags |= PAG_READ;
     419  if(fdwNewProtect & PAGE_READWRITE)    pageFlags |= (PAG_READ | PAG_WRITE);
     420  if(fdwNewProtect & PAGE_WRITECOPY)    pageFlags |= (PAG_READ | PAG_WRITE);
     421  if(fdwNewProtect & PAGE_EXECUTE_READ) pageFlags |= (PAG_EXECUTE | PAG_READ);
     422  if(fdwNewProtect & PAGE_EXECUTE_READWRITE)
     423        pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
     424  if(fdwNewProtect & PAGE_EXECUTE_WRITECOPY)
     425        pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
     426  if(fdwNewProtect & PAGE_GUARD)        pageFlags |= PAG_GUARD;
     427//Not supported in OS/2??
     428//  if(fdwNewProtect & PAGE_NOACCESS)
     429
     430  dprintf(("New memory flags %X\n", pageFlags));
     431  if(pageFlags == 0) {
     432        dprintf(("pageFlags == 0\n"));
     433        return(TRUE);   //nothing to do
     434  }
     435  npages = ((int)lpvAddress + cbSize >> 12) - ((int)lpvAddress >> 12) + 1;
     436
     437  lpvAddress = (LPVOID)((int)lpvAddress & ~0xFFF);
     438  cbSize     = npages*4096;
     439  dprintf(("lpvAddress = %X, cbSize = %d\n", lpvAddress, cbSize));
     440
     441  rc = OSLibDosSetMem(lpvAddress, cbSize, pageFlags);
     442  if(rc) {
     443        dprintf(("DosSetMem returned %d\n", rc));
     444        return(FALSE);
     445  }
     446  return(TRUE);
     447}
     448//******************************************************************************
     449//******************************************************************************
     450DWORD WIN32API VirtualQuery(LPCVOID lpvAddress, LPMEMORY_BASIC_INFORMATION pmbiBuffer,
     451                            DWORD cbLength)
     452{
     453 ULONG  cbRangeSize, dAttr;
     454 APIRET rc;
     455
     456  if(lpvAddress == NULL || pmbiBuffer == NULL || cbLength == 0) {
     457        return 0;
     458  }
     459  cbRangeSize = cbLength;
     460  rc = OSLibDosQueryMem((LPVOID)lpvAddress, &cbRangeSize, &dAttr);
     461  if(rc) {
     462        dprintf(("VirtualQuery - DosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
     463        return 0;
     464  }
     465  memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
     466  pmbiBuffer->BaseAddress = (LPVOID)lpvAddress;
     467  pmbiBuffer->RegionSize  = cbRangeSize;
     468  if(dAttr & PAG_READ && !(dAttr & PAG_WRITE))
     469        pmbiBuffer->Protect |= PAGE_READONLY;
     470  if(dAttr & PAG_WRITE)
     471        pmbiBuffer->Protect |= PAGE_READWRITE;
     472
     473  if(dAttr & (PAG_WRITE | PAG_EXECUTE))
     474        pmbiBuffer->Protect |= PAGE_EXECUTE_READWRITE;
     475  else
     476  if(dAttr & PAG_EXECUTE)
     477        pmbiBuffer->Protect |= PAGE_EXECUTE_READ;
     478
     479  if(dAttr & PAG_GUARD)
     480        pmbiBuffer->Protect |= PAGE_GUARD;
     481
     482  if(dAttr & PAG_FREE)
     483        pmbiBuffer->State = MEM_FREE;
     484  else
     485  if(dAttr & PAG_COMMIT)
     486        pmbiBuffer->State = MEM_COMMIT;
     487  else  pmbiBuffer->State = MEM_RESERVE;
     488
     489  if(!(dAttr & PAG_SHARED))
     490        pmbiBuffer->Type = MEM_PRIVATE;
     491
     492  //TODO: This is not correct: AllocationProtect should contain the protection
     493  //      flags used in the initial call to VirtualAlloc
     494  pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
     495  if(dAttr & PAG_BASE) {
     496        pmbiBuffer->AllocationBase = (LPVOID)lpvAddress;
     497  }
     498  else {
     499   while(lpvAddress > 0) {
     500      rc = OSLibDosQueryMem((LPVOID)lpvAddress, &cbRangeSize, &dAttr);
     501      if(rc) {
     502         dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
     503         break;
     504      }
     505      if(dAttr & PAG_BASE) {
     506         pmbiBuffer->AllocationBase = (LPVOID)lpvAddress;
     507         break;
     508      }
     509      lpvAddress = (LPVOID)((ULONG)lpvAddress - PAGE_SIZE);
     510   }
     511  }
     512  return sizeof(MEMORY_BASIC_INFORMATION);
     513}
     514//******************************************************************************
     515//******************************************************************************
     516BOOL WIN32API VirtualLock( LPVOID lpAddress, DWORD dwSize )
     517{
     518  dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
     519  return TRUE;
     520}
     521
     522//******************************************************************************
     523BOOL WIN32API VirtualUnlock( LPVOID lpAddress, DWORD dwSize )
     524{
     525  dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
     526  return TRUE;
     527}
     528
     529/*****************************************************************************
     530 * Name      : BOOL VirtualProtectEx
     531 * Purpose   : The VirtualProtectEx function changes the access protection on
     532 *             a region of committed pages in the virtual address space of a specified
     533 *             process. Note that this function differs from VirtualProtect,
     534 *             which changes the access protection on the calling process only.
     535 * Parameters: HANDLE hProcess       handle of process
     536 *             LPVOID lpvAddress     address of region of committed pages
     537 *             DWORD  cbSize         size of region
     538 *             DWORD  fdwNewProtect  desired access protection
     539 *             PDWORD pfdwOldProtect address of variable to get old protection
     540 * Variables :
     541 * Result    : size of target buffer
     542 * Remark    :
     543 * Status    : UNTESTED STUB
     544 *
     545 * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
     546 *****************************************************************************/
     547
     548BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
     549                                  LPVOID lpvAddress,
     550                                  DWORD  cbSize,
     551                                  DWORD  fdwNewProtect,
     552                                  LPDWORD pfdwOldProtect)
     553{
     554  dprintf(("KERNEL32: VirtualProtectEx(%08x,%08xh,%08xh,%08xh,%08xh) not implemented for different processes.\n",
     555           hProcess,
     556           lpvAddress,
     557           cbSize,
     558           fdwNewProtect,
     559           pfdwOldProtect));
     560
     561  return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
     562}
     563
     564
     565/*****************************************************************************
     566 * Name      : DWORD VirtualQueryEx
     567 * Purpose   : The VirtualQueryEx function provides information about a range
     568 *             of pages within the virtual address space of a specified process.
     569 * Parameters: HANDLE  hProcess                     handle of process
     570 *             LPCVOID  lpvAddress                  address of region
     571 *             LPMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
     572 *             DWORD  cbLength                      size of buffer
     573 * Variables :
     574 * Result    : number of bytes returned in buffer
     575 * Remark    :
     576 * Status    : UNTESTED STUB
     577 *
     578 * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
     579 *****************************************************************************/
     580
     581DWORD WIN32API VirtualQueryEx(HANDLE  hProcess,
     582                                 LPCVOID  lpvAddress,
     583                                 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
     584                                 DWORD   cbLength)
     585{
     586  dprintf(("KERNEL32: VirtualQueryEx(%08x,%08xh,%08xh,%08xh) not implemented for different processes.\n",
     587           hProcess,
     588           lpvAddress,
     589           pmbiBuffer,
     590           cbLength));
     591
     592  return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
     593}
     594//******************************************************************************
     595//******************************************************************************
Note: See TracChangeset for help on using the changeset viewer.