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
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.
- 7/9/2011
- JensG
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".
- 7/9/2011
- JensG
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;
}
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;
}
