5 out of 10 rated this helpful Rate this topic

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;
}


 

 

Send comments about this topic to Microsoft

Build date: 12/3/2011

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
bug: possible handle leak
If LookupPrivilegeValue() or AdjustTokenPrivileges() fails or the privilege is not adjusted as requested, the token handle opened in the beginning of LoggedSetLockPagesPrivilege() is never closed.





minor code smell

if( Result != TRUE ) ...

Comparing explicitliy with TRUE or FALSE is a code smell. One should really not do this. Instead, just write

if( ! Result) ...

The special problem here is, that a great number of people will think that this is good style, because "... even the experts at Microsoft do it this way, so it must be correct".






AWE Example (Windows)
/******************************************************************************
Copyright (c) ChuChe
******************************************************************************/
#include "stdafx.h"
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <fstream>

using namespace std; // позволяет обращаться к обьектам например std::cout напрямую.

/// размер требуемой памяти
#define MEMORY_REQUESTED 1024*1024*dob // request 128 megabytes

/// получение привилегий на блокировку страниц памяти
BOOL LoggedSetLockPagesPrivilege ( HANDLE hProcess,
BOOL bEnable);

/// главная функция программы
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bResult; // общее логическое значение
ULONG_PTR NumberOfPages; // число страниц для запроса
ULONG_PTR NumberOfPagesInitial; // начальное число страниц, запрошенных
ULONG_PTR *aPFNs; // информация о странице; проводит непрозрачных данных
PVOID lpMemReserved; // AWE window
SYSTEM_INFO sSysInfo; // полезной информации системы
int PFNArraySize; // памяти для запроса PFN массива
int dob; // кол-во мегабайт запрошенной памяти
int ps;
char c;
unsigned int i;
DWORD start, finish, timebuf;

GetSystemInfo(&sSysInfo); // заполнить структуру информационной системы

printf("*****************************************************************\n");
printf("\t\t Address Windowing Extensions \n");
printf("\t\t\t NAU 2011 \n");
printf("\t\t\t Cherednichenko Anton \n");
printf("*****************************************************************\n");

// определяемся с размером памяти
printf ( "\t Enter the size of the engaged memory in megabytes \n\t and push <Enter> for start process \n" );
scanf ( "%i" , &dob);
printf("\t Request %i megabytes of memory\n",dob);

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

ps = sSysInfo.dwPageSize;

// Вычислить количество страниц памяти для запроса.
NumberOfPages = MEMORY_REQUESTED / sSysInfo.dwPageSize;
printf ("\t Requesting %d pages of memory.\n", NumberOfPages);

// Вычислить размер пользователь PFN массива.
PFNArraySize = NumberOfPages * sizeof (ULONG_PTR);

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

// Массив страниц памяти
aPFNs = (ULONG_PTR *) HeapAlloc(GetProcessHeap() , 0 , PFNArraySize);

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

// Включить привилегий.
if( ! LoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) )
{
return true;
}

// Выделяем физической памяти.
NumberOfPagesInitial = NumberOfPages;
// Выделяет физические страницы памяти, которые необходимо сопоставить и нанесенных на карту в любом AWE области указанного процесса.
bResult = AllocateUserPhysicalPages( GetCurrentProcess(), // Дескриптор процесса. Функция выделяет память, что впоследствии может быть отображена в виртуальном адресном пространстве этого процесса.
&NumberOfPages, // Размер физической памяти для размещения, на страницах.
aPFNs ); // Указатель на массив для хранения номера страниц рамках выделенной памяти.

if( bResult != TRUE )
{
printf ( "\t Cannot allocate physical pages (%u)\n" , GetLastError() );
return true;
}
else
{
printf("\t Allocate physical pages: \t...successfully\n");
}

if( NumberOfPagesInitial != NumberOfPages )
{
printf ( "\t Allocated only %i pages.\n\t NOT Enough physical memory, the process is interrupted!\n", NumberOfPages );
return true;
}
else
{
printf("\t Allocated all physical pages.\n\t Enough physical memory available\n");
}

// Резервный виртуальной памяти. Резервирует области страниц в виртуальном адресном пространстве вызывающего процесса.
lpMemReserved = VirtualAlloc( NULL, // Начальный адрес области выделения.
MEMORY_REQUESTED, // Размер области, в байтах.
MEM_RESERVE | MEM_PHYSICAL,// Тип распределения памяти.
PAGE_READWRITE ); // Защиту памяти для области страниц, отводимых.

if( lpMemReserved == NULL )
{
_tprintf(_T("\t Cannot reserve memory.\n"));
return 0;
}

// Карта физической памяти в окне. Карты ранее выделенные физические страницы памяти по определенному адресу в AWE области.
// Функция MapUserPhysicalPages проецирует выделенную ранее область физической памяти
// в указанное адрусное пространство AWE-региона виртуальной памяти.
bResult = MapUserPhysicalPages( lpMemReserved, // начальный адрес области памяти
NumberOfPages, // размер физической памяти в страницах
aPFNs ); // Указатель на массив физических номера кадров странице.
// первый элемент массива фреймов страниц

if( bResult != TRUE ) // В случае удачного завершения ф-ция возвращает True.
{
printf ( "\t MapUserPhysicalPages failed (%u)\n" , GetLastError() );
return true;
}

// запуск эксперемента
printf("\t Please wait... \n");
unsigned char* buf;
buf = (unsigned char*) lpMemReserved; // начальный адрес области памяти

/****************************************************
эксперимент 1 - запись в память
*****************************************************/
start = GetTickCount();

for (int i = 0; i < MEMORY_REQUESTED; i++)
{
buf[i] = '-';
}

finish = GetTickCount();

printf("\t ------------------------------------------ \n");
printf("\t - Write memory block - \n");
printf("\t\t %i ms \n", finish - start);
printf("\t\t %i ms \n", MEMORY_REQUESTED/finish - start);
printf("\t ------------------------------------------ \n");

/****************************************************
эксперимент 2 - чтение из памяти
*****************************************************/
start = GetTickCount();

for (int i = 0; i < MEMORY_REQUESTED; i++)
{
if (buf[i]!= '-')
{
printf("MEMORY READ FAILED");
return -1;
}
}

finish = GetTickCount();

printf("\t ------------------------------------------ \n");
printf("\t - Read memory block - \n");
printf("\t\t %i ms \n",finish-start);
printf("\t ------------------------------------------ \n");

/****************************************************
эксперимент 3 - запись и чтение
*****************************************************/
start = GetTickCount();
for (int i = 0; i < MEMORY_REQUESTED; i++)
{
buf[i]= 'x';
}
for (int i = 0; i < MEMORY_REQUESTED; i++)
{
if (buf[i]!= 'x')
{
printf("MEMORY READ FAILED"); return -1;
}
}
finish = GetTickCount();

printf("\t ------------------------------------------ \n");
printf("\t - Both memory operation with block - \n");
printf("\t\t %i ms \n", finish - start);
printf("\t ------------------------------------------ \n");

/****************************************************
запись результирующего файла на диск
*****************************************************/
printf("\t Memory print saving to disk now. Please wait... \n");

start = GetTickCount();
fstream File("c:\Test.dat", ios::out);
File.write((char*) buf, MEMORY_REQUESTED);
File.close();

finish = GetTickCount();

printf("\t ------------------------------------------ \n");
printf("\t - Memory print saved to c:\Test.dat - \n");
printf("\t\t %i ms \n",finish-start);
printf("\t ------------------------------------------ \n");

/****************************************************
ЗАВЕРШЕНИЕ ИСПОЛЬЗОВАНИЯ "AWE"
*****************************************************/

// освобождение памяти
bResult = MapUserPhysicalPages( lpMemReserved,
NumberOfPages,
NULL ); // Указание значение NULL этому параметру , позволяет провести распроецирование
// указанного диапазона адресов. При этом указанные страницы не освобождаются в физической памяти,
// для этого нужно выполнять специальный вызов FreeUserPhysicalPages.

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

// Функция FreeUserPhysicalPages освобождает физические страницы памяти,
// которые были ранее выделены при помощи вызова {AllocateUserPhysicalPages}.
// Если текущие страницы были спроецированы в AWE-регион, то при вызове автоматически произойдет очишение проецирования.
// Заметим, что указанный вызов никак не затронет виртуальное адресное пространство, занимающее AWE-регион.
bResult = FreeUserPhysicalPages( GetCurrentProcess(), // Дескриптор процесса. Функция освобождает память в виртуальном адресном пространстве этого процесса.
&NumberOfPages, // Размер физической памяти, чтобы освободить, в страницах.
aPFNs ); // Указатель на массив номеров страниц рамках выделенной памяти для освобождения.

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

// Функция VirtualFree либо только освобождает физическую память, находящуюся под страницей,
// либо выполняет еще и снятие резервирования переводя страницу в состояние свободное.
// Страница должна быть расположена в виртуальном адресном пространстве вызывающего процесса.
bResult = VirtualFree( lpMemReserved, // начальный адрес освобожаемого региона памяти
0, // размер освобождаемого региона памяти
MEM_RELEASE ); // способ освобождения

// Фунция HeapFree освобождает фрагмент памяти, который был ранее выделен из кучи при помощи одного из вызовов HeapAlloc или HeapReAlloc.
bResult = HeapFree( GetProcessHeap(), // дескриптор кучи
0, // опции освобождения памяти
aPFNs); // указатель на освобождамый блок

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

printf("\t Free reserved memory: \t...successfully \n");
printf("\n\t Process successfully completed... \n");
printf("\n*****************************************************************\n");
scanf("%i",&c);
}

/*****************************************************************
LoggedSetLockPagesPrivilege: функция для получения прав на
блокировку страниц
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;

// Функция OpenProcessToken открывает access token, связанных с процессом.
Result = OpenProcessToken ( hProcess, // Дескриптор процесса, маркер доступа открыта. Процесс должен иметь разрешение PROCESS_QUERY_INFORMATION доступа.
TOKEN_ADJUST_PRIVILEGES, // Задает маску доступа , что указывает требуемых типов доступа к маркер доступа.
&Token); // Указатель на дескриптор, который идентифицирует недавно открытый маркер доступа, когда функция возвращает.

if( Result != TRUE )
{
printf("\t Cannot open process token.\n");
return 0;
}
else
{
printf("\t Open process token: \t...successfully \n");
}

// Enable or disable?

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

// Get the LUID.
// Функция LookupPrivilegeValue извлекает локально уникальный идентификатор (LUID),
// используемых на указанной системы в локально представляют указанным именем привилегий.
Result = LookupPrivilegeValue ( NULL, // Указатель на завершающуюся нулем строку, которая определяет имя системы, на которой привилегия имя доступно. Если пустая строка не указан, функция пытается найти имя привилегий в локальной системе.
SE_LOCK_MEMORY_NAME, // Указатель на завершающуюся нулем строку, которая определяет имя привилегии, как это определено в заголовке файла winnt.h.
&(Info.Privilege[0].Luid)); // Указатель на переменную, которая получает LUID которой привилегия известно о системе указанного lpSystemName параметра.

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

// Функция AdjustTokenPrivileges разрешает или запрещает привилегии в указанный маркер доступа .
Result = AdjustTokenPrivileges ( Token, FALSE, // Дескриптор маркер доступа, который содержит привилегии быть изменены.
(PTOKEN_PRIVILEGES) &Info, // Указывает, будет ли функция отключает все маркера привилегий.
0, NULL, NULL); // Указатель на TOKEN_PRIVILEGES структура, которая определяет множество привилегий и их атрибуты.

// результат
if( Result != TRUE )
{
printf ( "\t Cannot adjust token privileges (%u)\n", GetLastError() );
return false;
}
else
{
printf ( "\t Adjust token privileges: \t...successfully \n" );
if( GetLastError() != ERROR_SUCCESS )
{
printf ("\t Cannot enable the SE_LOCK_MEMORY_NAME privilege; ");
printf ("\t please check the local policy.\n");
return false;
}
}
// Закрывает дескриптор объекта.
CloseHandle( Token );

printf("\t Rights to lock pages received: \t...successfully \n");

return TRUE;
}