Platform SDK: Memory

AWE Example

The following sample program illustrates the Address Windowing Extensions for Windows 2000.

#include <windows.h>
#include <stdio.h>

#define MEMORY_REQUESTED 1024*1024 // request a megabyte

BOOL
LoggedSetLockPagesPrivilege ( HANDLE hProcess,
                              BOOL bEnable);

void _cdecl main()
{
  BOOL bResult;                 // generic boolean value
  ULONG_PTR NumberOfPages,      // number of pages we will request
    NumberOfPagesInitial;       // initial number of pages requested
  ULONG_PTR *aPFNs;             // page info; holds opaque data
  PVOID lpMemReserved;          // AWE window
  SYSTEM_INFO sSysInfo;         // useful system information
  int PFNArraySize;             // memory to request for PFN array

  GetSystemInfo(&sSysInfo);     // populate the system information structure

  printf ("This computer has a page size of %d.\n", sSysInfo.dwPageSize);

  // Calculate the number of pages of memory we'll request.

  NumberOfPages = MEMORY_REQUESTED/sSysInfo.dwPageSize;
  printf ("Requesting %d pages of memory.\n", NumberOfPages);

  // Calculate the size of the user PFN array.

  PFNArraySize = NumberOfPages * sizeof (ULONG_PTR);

  printf ("Requesting a PFN array of %d bytes.\n", PFNArraySize);

  aPFNs = (ULONG_PTR *) HeapAlloc (GetProcessHeap (), 0, PFNArraySize);

  if (aPFNs == NULL) {
    printf ("Failed to allocate on heap.\n");
    return;
  }

  // Enable the privilege.

  if( ! LoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) ) {
    return;
  }

  // Allocate the physical memory we want.

  NumberOfPagesInitial = NumberOfPages;
  bResult = AllocateUserPhysicalPages( GetCurrentProcess(),
                                       &NumberOfPages,
                                       aPFNs );
    
  if( bResult != TRUE ) 
  {
    printf("Cannot allocate physical pages, error %u.\n", GetLastError() );
    return;
  }

  if( NumberOfPagesInitial != NumberOfPages ) 
  {
    printf("Allocated only %p pages.\n", NumberOfPages );
    return;
  }

  // Reserve the virtual memory.
    
  lpMemReserved = VirtualAlloc( NULL,
                                MEMORY_REQUESTED,
                                MEM_RESERVE | MEM_PHYSICAL,
                                PAGE_READWRITE );

  if( lpMemReserved == NULL ) 
  {
    printf("Cannot reserve memory.\n");
    return;
  }

  // Map the physical memory into our window.
    
  bResult = MapUserPhysicalPages( lpMemReserved,
                                  NumberOfPages,
                                  aPFNs );

  if( bResult != TRUE ) 
  {
    printf("MapUserPhysicalPages failed to map, error %u.\n", GetLastError() );
    return;
  }

  // unmap
    
  bResult = MapUserPhysicalPages( lpMemReserved,
                                  NumberOfPages,
                                  NULL );

  if( bResult != TRUE ) 
  {
    printf("MapUserPhysicalPages failed to unmap, error %u.\n", GetLastError() );
    return;
  }

  // Free the physical pages.

  bResult = FreeUserPhysicalPages( GetCurrentProcess(),
                                   &NumberOfPages,
                                   aPFNs );

  if( bResult != TRUE ) 
  {
    printf("Cannot free physical pages, error %u.\n", GetLastError() );
    return;
  }

  // Free virtual memory.

  bResult = VirtualFree( lpMemReserved,
                         0,
                         MEM_RELEASE );
}

/*****************************************************************
   LoggedSetLockPagesPrivilege: a function to obtain, if possible, or
   release the privilege of locking physical pages.

   Inputs:

       HANDLE hProcess: Handle for the process for which we seek the
       privilege

       BOOL bEnable: Shall we enable (TRUE) or disable?

   Return value: TRUE indicates success, FALSE failure.

*****************************************************************/
BOOL
LoggedSetLockPagesPrivilege ( HANDLE hProcess,
                              BOOL bEnable)
{
  struct {
    DWORD Count;
    LUID_AND_ATTRIBUTES Privilege [1];
  } Info;

  HANDLE Token;
  BOOL Result;

  // Open the token.

  Result = OpenProcessToken ( hProcess,
                              TOKEN_ADJUST_PRIVILEGES,
                              & Token);

  if( Result != TRUE ) {
    printf( "Cannot open process token.\n" );
    return FALSE;
  }

  // Enable or disable?

  Info.Count = 1;
  if( bEnable ) 
  {
    Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
  } 
  else 
  {
    Info.Privilege[0].Attributes = 0;
  }

  // Get the LUID.

  Result = LookupPrivilegeValue ( NULL,
                                  SE_LOCK_MEMORY_NAME,
                                  &(Info.Privilege[0].Luid));

  if( Result != TRUE ) 
  {
    printf( "Cannot get privilege value for %s.\n", SE_LOCK_MEMORY_NAME );
    return FALSE;
  }

  // Adjust the privilege.

  Result = AdjustTokenPrivileges ( Token, FALSE,
                                   (PTOKEN_PRIVILEGES) &Info,
                                   NULL, NULL, NULL);

  // Check the result.

  if( Result != TRUE ) 
  {
    printf ("Cannot adjust token privileges, error %u.\n", GetLastError() );
    return FALSE;
  } 
  else 
  {
    if( GetLastError() != ERROR_SUCCESS ) 
    {
      printf ("Cannot enable SE_LOCK_MEMORY privilege, please check the local policy.\n");
      return FALSE;
    }
  }

  CloseHandle( Token );

  return TRUE;
}