VirtualAlloc()で20KB分(0x5000)確保した後、4KB毎にVirtualProtect()で保護モードを変更してみるサンプル。
va01.cpp:
#include <windows.h> #include <stdio.h> void PrintErrorMsg(DWORD err) { LPTSTR lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); printf("%s\n", lpMsgBuf); LocalFree(lpMsgBuf); } void DumpMemoryInfo(void *addr) { MEMORY_BASIC_INFORMATION mbi; size_t res_sz = 0; res_sz = VirtualQuery(addr, &mbi, sizeof(mbi)); if (0 == res_sz) { PrintErrorMsg(GetLastError()); fprintf(stderr, "VirtualQuery() failed.\n"); exit(-1); } printf("[MBI at 0x%08X]:\n", addr); printf("\tmbi.BaseAddress = 0x%08X\n", mbi.BaseAddress); printf("\tmbi.AllocationBase = 0x%08X\n", mbi.AllocationBase); printf("\tmbi.AllocationProtect = 0x%08X\n", mbi.AllocationProtect); printf("\tmbi.RegionSize = 0x%08X\n", mbi.RegionSize); printf("\tmbi.State = 0x%08X\n", mbi.State); printf("\tmbi.Protect = 0x%08X\n", mbi.Protect); printf("\tmbi.Type = 0x%08X\n", mbi.Type); } char msg[] = "ABCD"; int main(int argc, char *argv[]) { void *p1 = NULL; DWORD dw1 = 0; size_t init_sz = 0x5000; p1 = VirtualAlloc(NULL, init_sz, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); if (NULL == p1) { PrintErrorMsg(GetLastError()); fprintf(stderr, "VirtualAlloc() failed.\n"); return -1; } printf("p1 = 0x%08X\n", p1); dw1 = (DWORD)p1; DumpMemoryInfo((void*)(dw1 + 123)); DWORD oldp = 0; DWORD start = dw1; if (!VirtualProtect((void*)(start), 0x1000, PAGE_READONLY, &oldp)) { PrintErrorMsg(GetLastError()); fprintf(stderr, "VirtualProtect() failed.\n"); return -1; } printf("------[1]\n"); DumpMemoryInfo((void*)(start)); start += 0x1000; if (!VirtualProtect((void*)(start), 0x1000, PAGE_EXECUTE_READ, &oldp)) { PrintErrorMsg(GetLastError()); fprintf(stderr, "VirtualProtect() failed.\n"); return -1; } printf("------[2]\n"); DumpMemoryInfo((void*)(start)); start += 0x1000; if (!VirtualProtect((void*)(start), 0x1000, PAGE_READWRITE, &oldp)) { PrintErrorMsg(GetLastError()); fprintf(stderr, "VirtualProtect() failed.\n"); return -1; } printf("------[3]\n"); DumpMemoryInfo((void*)(start)); start += 0x1000; if (!VirtualProtect((void*)(start), 0x1000, PAGE_READONLY, &oldp)) { PrintErrorMsg(GetLastError()); fprintf(stderr, "VirtualProtect() failed.\n"); return -1; } printf("------[4]\n"); DumpMemoryInfo((void*)(start)); return 0; }
実行結果:
p1 = 0x003A0000
[MBI at 0x003A007B]:
mbi.BaseAddress = 0x003A0000
mbi.AllocationBase = 0x003A0000
mbi.AllocationProtect = 0x00000004
mbi.RegionSize = 0x00005000
mbi.State = 0x00001000
mbi.Protect = 0x00000004
mbi.Type = 0x00020000
------[1]
[MBI at 0x003A0000]:
mbi.BaseAddress = 0x003A0000
mbi.AllocationBase = 0x003A0000
mbi.AllocationProtect = 0x00000004
mbi.RegionSize = 0x00001000
mbi.State = 0x00001000
mbi.Protect = 0x00000002
mbi.Type = 0x00020000
------[2]
[MBI at 0x003A1000]:
mbi.BaseAddress = 0x003A1000
mbi.AllocationBase = 0x003A0000
mbi.AllocationProtect = 0x00000004
mbi.RegionSize = 0x00001000
mbi.State = 0x00001000
mbi.Protect = 0x00000020
mbi.Type = 0x00020000
------[3]
[MBI at 0x003A2000]:
mbi.BaseAddress = 0x003A2000
mbi.AllocationBase = 0x003A0000
mbi.AllocationProtect = 0x00000004
mbi.RegionSize = 0x00003000
mbi.State = 0x00001000
mbi.Protect = 0x00000004
mbi.Type = 0x00020000
------[4]
[MBI at 0x003A3000]:
mbi.BaseAddress = 0x003A3000
mbi.AllocationBase = 0x003A0000
mbi.AllocationProtect = 0x00000004
mbi.RegionSize = 0x00001000
mbi.State = 0x00001000
mbi.Protect = 0x00000002
mbi.Type = 0x00020000
VirtualAlloc()で確保したメモリ中を、0x1000サイズの領域毎にプロテクトモードを変更出来ている。