// First, reserve a 1MB region for the address window
ULONG_PTR ulRAMBytes = 1024 * 1024;
PVOID pvWindow = VirtualAlloc(NULL, ulRAMBytes,
MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE);
// Get the number of bytes in a page for this CPU platform
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
// Calculate the required number of RAM pages for the desired number of bytes
ULONG_PTR ulRAMPages = ulRAMBytes / sinf.dwPageSize
// Allocate array for RAM page's page frame numbers
ULONG_PTR aRAMPages[ulRAMPages];
// Allocate the pages of RAM
// (requires Lock Pages in Memory user right)
AllocateUserPhysicalPages(
GetCurrentProcess(), // Allocate the storage for our process
&ulRAMPages, // Input: # of RAM pages, Output: # pages allocated
aRAMPages); // Output: Opaque array indicating pages allocated
// Assign the RAM pages to our window
MapUserPhysicalPages(pvWindow, // The address of the address window
ulRAMPages, // Number of entries in array
aRAMPages); // Array of RAM pages
// Access the RAM pages via the pvWindow virtual address
•
•
•
// Free the block of RAM pages
FreeUserPhysicalPages(
GetCurrentProcess(), // Free the RAM allocated for our process
&ulRAMPages, // Input, # of RAM pages, Output: # pages freed
aRAMPages); // Input: Array indicating the RAM pages to free
// Destroy the address window
VirtualFree(pvWindow, 0, MEM_RELEASE);
Figure 2 AWETest
AddrWindow.h
/*******************************************************
Module: AddrWindow.h
Notices: Written by Jeffrey Richter
*******************************************************/
#pragma once
#include <tchar.h>
//////////////////////
class CSystemInfo : public SYSTEM_INFO {
public:
CSystemInfo() { GetSystemInfo(this); }
};
//////////////////////
class CAddrWindow {
public:
CAddrWindow() { m_pvWindow = NULL; }
~CAddrWindow() { Destroy(); }
BOOL Create(SIZE_T dwBytes,
PVOID pvPreferredWindowBase = NULL) {
// Reserve address window region to view physical
// storage
m_pvWindow = VirtualAlloc(pvPreferredWindowBase,
dwBytes,MEM_RESERVE | MEM_PHYSICAL,
PAGE_READWRITE);
return(m_pvWindow != NULL);
}
BOOL Destroy() {
BOOL fOk = TRUE;
if (m_pvWindow != NULL) {
// Destroy address window region
fOk = VirtualFree(m_pvWindow, 0, MEM_RELEASE);
m_pvWindow = NULL;
}
return(fOk);
}
BOOL UnmapStorage() {
// Unmap all storage from address window region
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(m_pvWindow, &mbi, sizeof(mbi));
return(MapUserPhysicalPages(m_pvWindow,
mbi.RegionSize / sm_sinf.dwPageSize, NULL));
}
// Returns virtual address of address window
operator PVOID() { return(m_pvWindow); }
private:
PVOID m_pvWindow; // Virtual address of address
// window region
static CSystemInfo sm_sinf;
};
//////////////////////
CSystemInfo CAddrWindow::sm_sinf;
//////////////////////
class CAddrWindowStorage {
public:
CAddrWindowStorage() { m_ulPages = 0;
m_pulUserPfnArray = NULL; }
~CAddrWindowStorage() { Free(); }
BOOL Allocate(ULONG_PTR ulBytes) {
// Allocate storage intended for an address window
Free(); // Clean up this object's existing address
// window
// Calculate number of pages from number of bytes
m_ulPages = (ulBytes + sm_sinf.dwPageSize) /
sm_sinf.dwPageSize;
// Allocate array of page frame numbers
m_pulUserPfnArray = (PULONG_PTR)
HeapAlloc(GetProcessHeap(), 0, m_ulPages *
sizeof(ULONG_PTR));
BOOL fOk = (m_pulUserPfnArray != NULL);
if (fOk) {
// The "Lock Pages in Memory" privilege must be
// enabled
EnablePrivilege(SE_LOCK_MEMORY_NAME, TRUE);
fOk = AllocateUserPhysicalPages(
GetCurrentProcess(), &m_ulPages,
m_pulUserPfnArray);
EnablePrivilege(SE_LOCK_MEMORY_NAME, FALSE);
}
return(fOk);
}
BOOL Free() {
BOOL fOk = TRUE;
if (m_pulUserPfnArray != NULL) {
fOk = FreeUserPhysicalPages(GetCurrentProcess(),
&m_ulPages, m_pulUserPfnArray);
if (fOk) {
// Free the array of page frame numbers
HeapFree(GetProcessHeap(), 0,
m_pulUserPfnArray);
m_ulPages = 0;
m_pulUserPfnArray = NULL;
}
}
return(fOk);
}
ULONG_PTR HowManyPagesAllocated() { return(m_ulPages); }
BOOL MapStorage(CAddrWindow& aw) {
return(MapUserPhysicalPages(aw,
HowManyPagesAllocated(), m_pulUserPfnArray));
}
BOOL UnmapStorage(CAddrWindow& aw) {
return(MapUserPhysicalPages(aw,
HowManyPagesAllocated(), NULL));
}
private:
static BOOL EnablePrivilege(PCTSTR pszPrivName,
BOOL fEnable = TRUE) {
BOOL fOk = FALSE; // Assume function fails
HANDLE hToken;
// Try to open this process's access token
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES, &hToken)) {
// Attempt to modify the "Lock pages in Memory"
// privilege
TOKEN_PRIVILEGES tp = { 1 };
LookupPrivilegeValue(NULL, pszPrivName,
&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ?
SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp,
sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return(fOk);
}
private:
ULONG_PTR m_ulPages; // Number of storage pages
PULONG_PTR m_pulUserPfnArray; // Page frame number
// array
private:
static CSystemInfo sm_sinf;
};
//////////////////////
CSystemInfo CAddrWindowStorage::sm_sinf;
//// End of File ////
AWETest.cpp
/*******************************************************
Module: AWETest.cpp
Notices: Written by Jeffrey Richter
*******************************************************/
#define _WIN32_WINNT 0x0500
#include <Windows.h>
#include <Windowsx.h>
#include <tchar.h>
#include "AddrWindow.h"
#include "Resource.h"
//////////////////////
CAddrWindow g_aw[2]; // 2 memory address windows
CAddrWindowStorage g_aws[2]; // 2 storage blocks
const ULONG_PTR g_nChars = 1024; // 1024 character
// buffers
//////////////////////
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus,
LPARAM lParam) {
// Create the 2 memory address windows
g_aw[0].Create(g_nChars * sizeof(TCHAR));
g_aw[1].Create(g_nChars * sizeof(TCHAR));
// Create the 2 storage blocks
if (!g_aws[0].Allocate(g_nChars * sizeof(TCHAR))) {
MessageBoxA(NULL,
"Failed to allocate RAM.\nMost likely reason: "
"you are not granted the Lock Pages in Memory
user right.",
NULL, MB_OK);
ExitProcess(0);
}
g_aws[1].Allocate(g_nChars * sizeof(TCHAR));
// Put some default text in the 1st storage block
g_aws[0].MapStorage(g_aw[0]);
lstrcpy((PSTR) (PVOID) g_aw[0],
TEXT("Text in Storage 0"));
// Put some default text in the 2nd storage block
g_aws[1].MapStorage(g_aw[0]);
lstrcpy((PSTR) (PVOID) g_aw[0],
TEXT("Text in Storage 1"));
// Populate the dialog box controls
for (int n = 0; n <= 1; n++) {
// Set the combobox for each address window
int id = ((n == 0) ? IDC_WINDOW0STORAGE :
IDC_WINDOW1STORAGE);
HWND hwndCB = GetDlgItem(hwnd, id);
ComboBox_AddString(hwndCB, TEXT("No storage"));
ComboBox_AddString(hwndCB, TEXT("Storage 0"));
ComboBox_AddString(hwndCB, TEXT("Storage 1"));
// Window 0 shows Storage 0,
// Window 1 shows Storage 1
ComboBox_SetCurSel(hwndCB, n + 1);
FORWARD_WM_COMMAND(hwnd, id, hwndCB, CBN_SELCHANGE,
SendMessage);
Edit_LimitText(GetDlgItem(hwnd,
(n == 0) ? IDC_WINDOW0TEXT : IDC_WINDOW1TEXT),
g_nChars);
}
return(TRUE);
}
//////////////////////
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl,
UINT codeNotify) {
switch (id) {
case IDCANCEL:
EndDialog(hwnd, id);
break;
case IDC_WINDOW0STORAGE:
case IDC_WINDOW1STORAGE:
if (codeNotify == CBN_SELCHANGE) {
// Show different storage in address window
int nWindow = ((id == IDC_WINDOW0STORAGE) ?
0 : 1);
int nStorage = ComboBox_GetCurSel(hwndCtl) - 1;
// Show no storage in this window
if (nStorage == -1) {
g_aw[nWindow].UnmapStorage();
} else {
if
(!g_aws[nStorage].MapStorage(
g_aw[nWindow])) {
// Couldn't map storage in window
g_aw[nWindow].UnmapStorage();
// Force "No storage"
ComboBox_SetCurSel(hwndCtl, 0);
MessageBoxA(NULL,
"This storage can be mapped only
once.",
NULL, MB_OK);
}
}
// Update the address window's text display
HWND hwndText = GetDlgItem(hwnd,
((nWindow == 0) ? IDC_WINDOW0TEXT :
IDC_WINDOW1TEXT));
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(g_aw[nWindow], &mbi, sizeof(mbi));
// Note: mbi.State == MEM_RESERVE if no storage
// is in address window
EnableWindow(hwndText,
(mbi.State == MEM_COMMIT));
Edit_SetText(hwndText, IsWindowEnabled(hwndText)
? (PCSTR) (PVOID) g_aw[nWindow] :
TEXT("(No storage)"));
}
break;
case IDC_WINDOW0TEXT:
case IDC_WINDOW1TEXT:
if (codeNotify == EN_CHANGE) {
// Update the storage in the address window
int nWindow = ((id == IDC_WINDOW0TEXT) ? 0 : 1);
Edit_GetText(hwndCtl,
(PSTR) (PVOID) g_aw[nWindow], g_nChars);
}
break;
}
}
//// chHANDLE_DLGMSG Macro ////
// The normal HANDLE_MSG macro in WindowsX.h does not
// work properly for dialog boxes because DlgProc return
// a BOOL instead of an LRESULT (like WndProcs).
// This chHANDLE_DLGMSG macro corrects the problem:
#define chHANDLE_DLGMSG(hwnd, message, fn) \
case (message): return (SetDlgMsgResult(hwnd, uMsg, \
HANDLE_##message((hwnd), (wParam), (lParam),
(fn))))
//////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG,
Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND,
Dlg_OnCommand);
}
return(FALSE);
}
//////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE,
PTSTR pszCmdLine, int) {
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_AWETEST),
NULL, Dlg_Proc);
return(0);
}
//// End of File ////