AWE Example

The following sample program illustrates the Address Windowing Extensions.

#include <windows.h>
#include <stdio.h>
#include <tchar.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 to request
  ULONG_PTR 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);  // fill the system information structure

  _tprintf(_T("This computer has page size %d.\n"), sSysInfo.dwPageSize);

  // Calculate the number of pages of memory to request.

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

  // Calculate the size of the user PFN array.

  PFNArraySize = NumberOfPages * sizeof (ULONG_PTR);

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

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

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

  // Enable the privilege.

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

  // Allocate the physical memory.

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

  if( NumberOfPagesInitial != NumberOfPages ) 
  {
    _tprintf(_T("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 ) 
  {
    _tprintf(_T("Cannot reserve memory.\n"));
    return;
  }

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

  if( bResult != TRUE ) 
  {
    _tprintf(_T("MapUserPhysicalPages failed (%u)\n"), GetLastError() );
    return;
  }

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

  if( bResult != TRUE ) 
  {
    _tprintf(_T("MapUserPhysicalPages failed (%u)\n"), GetLastError() );
    return;
  }

  // Free the physical pages.

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

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

  // Free virtual memory.

  bResult = VirtualFree( lpMemReserved,
                         0,
                         MEM_RELEASE );

  // Release the aPFNs array.

  bResult = HeapFree(GetProcessHeap(), 0, aPFNs);

  if( bResult != TRUE )
  {
      _tprintf(_T("Call to HeapFree has failed (%u)\n"), GetLastError() );
  }

}

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

   Inputs:

       HANDLE hProcess: Handle for the process for which the
       privilege is needed

       BOOL bEnable: 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 ) 
  {
    _tprintf( _T("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 ) 
  {
    _tprintf( _T("Cannot get privilege for %s.\n"), SE_LOCK_MEMORY_NAME );
    return FALSE;
  }

  // Adjust the privilege.

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

  // Check the result.

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

  CloseHandle( Token );

  return TRUE;
}