|
|
1.1.1.3 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 Microsoft Corporation. ! 5: * All rights reserved. ! 6: * This source code is only intended as a supplement to ! 7: * Microsoft Development Tools and/or WinHelp documentation. ! 8: * See these sources for detailed information regarding the ! 9: * Microsoft samples programs. ! 10: \******************************************************************************/ ! 11: 1.1 root 12: /*************************************************************************\ 13: * PROGRAM: Virtmem.c 14: * 15: * PURPOSE: 16: * 17: * To demonstrate the use of various virtual memory API. 18: * 19: * FUNCTIONS: 20: * 21: * WinMain() - Initializes the window, and process the message loop. 22: * MainWndProc() - Process messages, launches server & client threads. 23: * ResetMenu() - Looks at the memory page and checks the menu items 24: * accordingly. 25: * ShowDlgProc() - Shows information regarding the virtual page. 26: * 27: * GLOBAL VARIABLES: 28: * 29: * - Buf, Buf2: 30: * Character arrays used for error messages. 31: * 32: * - base: Pointer to CHAR, used as a pointer to the base of the page. 33: * - hInst: Handle to the application's Instance. 34: * - hWnd: Handle to the parent window. 35: * - MemInfo: 36: * Structure used to hold the page's memory information. 37: * 38: * COMMENTS: 39: * 40: * To Use: 41: * Start the application. You are automatically given a Reserved page 42: * of memory with no access (4096 bytes in size). You can then use 43: * the various menu selection to change the state and protection on 44: * the page. "State" allows you to change the page between Free, 45: * Reserved, and Committed. "Access" allows you to change the 46: * protection on the page between Read/Write, Read Only, or No Access. 47: * Lock allows you to Lock or Unlock the page in memory (note that 48: * this was not yet implemented in PDK-2). Test trys to write to 49: * memory. If the page is not committed, and is marked with read/ 50: * write access, this will cause an exception. There is an example 51: * of exception handling in the code. 52: * 53: * The menu will keep track of the state and protection access 54: * to the page, and the menu items will be checked accordingly. 55: * For more information on the page, you can select "Show Page" 56: * from the menu. A dialog box will appear showing you the page 57: * information. You can dismiss the dialog box through its system 58: * menu. 59: * 60: \*************************************************************************/ 61: 62: 63: #include <windows.h> 64: #include <excpt.h> 65: #include <stdio.h> 66: #include <stdlib.h> 67: #include "virtmem.h" 68: 69: #define WERR(who,where) {sprintf(Buf,"ERROR: %s returned %u, line: %u", who, GetLastError(), __LINE__);\ 70: sprintf(Buf2,"From within %s", where);\ 71: MessageBox(hwnd, Buf, Buf2, MB_OK);} 72: 73: 74: #define IMPLEMENTED // Used if VirtualLock and VirtualUnlock are implemented. 75: 76: CHAR Buf[80]; 77: CHAR Buf2[80]; 78: 79: CHAR *base; 80: CHAR *page; 81: 82: HANDLE hInst; 83: HANDLE hWnd; 84: MEMORY_BASIC_INFORMATION MemInfo; 85: 86: /*************************************************************************\ 87: * 88: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) 89: * 90: * PURPOSE: calls initialization function, processes message loop 91: * 92: * COMMENTS: 93: * 94: \*************************************************************************/ 95: int APIENTRY WinMain (HANDLE hInstance, 96: HANDLE hPrevInstance, 97: LPSTR lpCmdLine, 98: int nCmdShow) 99: { 100: MSG msg; 101: WNDCLASS wc; 102: 103: UNREFERENCED_PARAMETER( lpCmdLine ); 104: UNREFERENCED_PARAMETER( hPrevInstance ); 105: 106: hInst = hInstance; 107: 1.1.1.3 ! root 108: wc.style = 0; 1.1 root 109: wc.lpfnWndProc = (WNDPROC)MainWndProc; 110: wc.cbClsExtra = 0; 111: wc.cbWndExtra = 0; 112: wc.hInstance = hInstance; 113: wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); 114: wc.hCursor = LoadCursor (NULL, IDC_ARROW); 115: wc.hbrBackground = GetStockObject (WHITE_BRUSH); 116: wc.lpszMenuName = "Virtmem_Menu"; 117: wc.lpszClassName = "VirtmemWClass"; 118: 119: RegisterClass(&wc); 120: 121: 122: hWnd = CreateWindow ("VirtmemWClass", 123: "Virtual Memory Sample", 124: WS_OVERLAPPEDWINDOW, 125: CW_USEDEFAULT, 126: CW_USEDEFAULT, 127: CW_USEDEFAULT, 128: CW_USEDEFAULT, 129: NULL, 130: NULL, 131: hInstance, 132: NULL); 133: 134: 135: ShowWindow(hWnd, nCmdShow); 1.1.1.3 ! root 136: while (GetMessage (&msg, NULL, 0, 0)) 1.1 root 137: DispatchMessage (&msg); // Dispatch message to window. 138: 139: return (msg.wParam); // Returns value from PostQuitMessage. 140: 141: } 142: 143: /*************************************************************************\ 144: * 145: * FUNCTION: MainWndProc (HWND, UINT, UINT, LONG) 146: * 147: * PURPOSE: To process the windows messages. 148: * 149: * VARIABLES USED: 150: * 151: * - Buf[]: Array of CHAR, error message buffer. 152: * - retCode: 153: * DWORD used to trap return codes. 154: * - oldProtection: 155: * DWORD used to hold the old protection value returned from 156: * VirtualProtect() call. 157: * - page: Array of CHAR, used as a base pointer to the page. 158: * - ExceptError[]: 159: * Array of CHAR, used to be printed as an error message string. 160: * - ExceptSuccess[]: 161: * Array of CHAR, used to be printed an a success message string. 162: * 163: * MESSAGES: 164: * 165: * WM_DESTROY: - Terminates the threads and post the quit message. 166: * WM_CREATE: - Allocates memory to hold some color values, and 167: * creates the two threads. 168: * WM_USER: - Used to delay the message to reset the menu until 169: * the window is created. 170: * 171: * WM_COMMAND 172: * 173: * IDM_LOCK: 174: * Uses VirtualLock() to lock the page into memory (preventing 175: * it from being paged out. 176: * 177: * IDM_UNLOCK: 178: * Unlocks the page from memory allowing it to be paged out 179: * by the system. 180: * 181: * IDM_WRITE: 182: * Attempts to write to the page. This message uses structured 183: * exception handling and tries to write to offset 100 in the 184: * page. If there is an exception (usually due to the memory 185: * not being committed, or not having the proper read/write 186: * access), then the exception is handled by putting up a message 187: * box. If no exception is trapped, a success message is 188: * put up. 189: * 190: * IDM_SHOW: 191: * Puts up a dialog box which gives information about the current 192: * state of the page (See comments on ShowDlgProc); 193: * 194: * IDM_NOACCESS: 195: * Uses VirtualProtect() to change the protection on the page 196: * to PAGE_NOACCESS. Note a page must be committed before 197: * changing its protection. 198: * 199: * IDM_READONLY: 200: * Uses VirtualProtect() to change the protection on the page to 201: * PAGE_READONLY. Note a page must be committed before changing 202: * its protection. 203: * 204: * IDM_READWRITE: 205: * Uses VirtualProtect() to change the protection on the page to 206: * PAGE_READWRITE. Note a page must be committed before 207: * changing its protection. 208: * 209: * IDM_COMMIT: 210: * Uses VirtualAlloc() to commit the page. Note that if the 211: * page has been previously RESERVED with VirtualAlloc, then 212: * you can use a pointer to the base of the memory as the first 213: * parameter of the call. If the page is FREE rather than 214: * RESERVED, then you use NULL as the first parameter. 215: * 216: * IDM_FREE: 217: * Uses VirtualFree() to commit the page. Note that a committed 218: * page must first be decommitted before it can be freed. 219: * 220: * IDM_RESERVE: 221: * If the page is FREE, this uses VirtualAlloc() reserve it. 222: * If the page is committed, this uses VirtualFree() to 223: * decommit the page. 224: * 225: * CALLED BY: 226: * 227: * WinMain(); 228: * 229: * CALLS TO: 230: * 231: * ResetMenu(); 232: * ShowDlgProc(); 233: * 234: * COMMENTS: 235: * 236: * 237: \*************************************************************************/ 238: 239: 240: LONG APIENTRY MainWndProc (HWND hwnd, 241: UINT message, 242: UINT wParam, 243: LONG lParam) 244: { 245: CHAR Buf[80]; 246: DWORD retCode; 247: DWORD oldProtection; 248: CHAR *page; 249: CHAR ExceptError[200] = "An exception was trapped and handled with this message box.\ 250: Make sure the page is commited and that you have Read/Write access."; 251: CHAR ExceptSuccess[] = "Writing to memory was successful: base[100] = 'a'"; 252: 253: switch (message) 254: { 255: 256: case WM_CREATE: 257: 258: base = VirtualAlloc (NULL, 259: PAGESIZE, 260: MEM_RESERVE, 261: PAGE_NOACCESS); 262: 263: if (!base) 264: WERR ("VirtualAlloc", "WM_CREATE"); 265: 1.1.1.3 ! root 266: PostMessage (hwnd, WM_USER, 0, 0); 1.1 root 267: 268: return (0); 269: 270: 271: case WM_USER: 272: ResetMenu(); 273: return (0); 274: 275: case WM_COMMAND: 276: switch (LOWORD(wParam)) 277: { 278: 279: #ifdef IMPLEMENTED 280: 281: case IDM_LOCK: 282: 283: VirtualQuery (base, &MemInfo, sizeof(MemInfo)); 284: if (MemInfo.State != MEM_COMMIT) 285: { 286: MessageBox (hWnd, 287: "Stop! You must first COMMIT a page before locking it.", 288: "From IDM_LOCK", MB_OK); 289: return (0); 290: } 291: 292: retCode = VirtualLock(base, PAGESIZE); 293: if (!retCode) 294: 295: MessageBox(hWnd, "Error in locking memory", 296: "From within IDM_LOCK", MB_OK); 297: else 298: MessageBox(hWnd, "The Memory was Locked.", 299: "From within IDM_LOCK", MB_OK); 300: 301: return (0); 302: 303: case IDM_UNLOCK: 304: 305: retCode = VirtualUnlock(base, PAGESIZE); 306: if (!retCode) 307: 308: MessageBox(hWnd, "Error in unlocking memory", 309: "From within IDM_UNLOCK", MB_OK); 310: else 311: MessageBox(hWnd, "The Memory was Unlocked.", 312: "From within IDM_UNLOCK", MB_OK); 313: 314: return (0); 315: 316: #endif 317: 318: case IDM_WRITE: 1.1.1.3 ! root 319: __try 1.1 root 320: { 321: base[100] = 'a'; 322: MessageBox (hWnd, ExceptSuccess, "try/except", MB_OK); 323: } 1.1.1.3 ! root 324: __except (EXCEPTION_EXECUTE_HANDLER) 1.1 root 325: { 326: MessageBox (hWnd, ExceptError, "try/except", MB_OK); 327: } 328: return (0); 329: 330: 331: case IDM_SHOW: 1.1.1.2 root 332: DialogBox (hInst, "Page_Info", hwnd, (DLGPROC)ShowDlgProc); 1.1 root 333: return (0); 334: 335: 336: case IDM_NOACCESS: 337: 338: retCode = VirtualQuery (base, &MemInfo, 339: sizeof(MEMORY_BASIC_INFORMATION)); 340: if (!retCode) 341: { 342: WERR("VirtualQuery", "IDM_NOACCESS"); 343: return (0); 344: } 345: 346: if (MemInfo.State != MEM_COMMIT) 347: { 348: MessageBox ( hWnd, "The page must be commited first.", 349: "From IDM_NOACCESS", MB_OK); 350: return (0); 351: } 352: 353: retCode = VirtualProtect (base, PAGESIZE, 354: PAGE_NOACCESS, &oldProtection); 355: if (!retCode) 356: WERR("VirtualProtect","IDM_NOACCESS"); 357: 358: ResetMenu(); 359: return (0); 360: 361: 362: case IDM_READONLY: 363: retCode = VirtualQuery (base, &MemInfo, 364: sizeof(MEMORY_BASIC_INFORMATION)); 365: if (!retCode) 366: { 367: WERR("VirtualQuery", "IDM_READONLY"); 368: return (0); 369: } 370: 371: if (MemInfo.State != MEM_COMMIT) 372: { 373: MessageBox ( hWnd, "The page must be commited first.", 374: "From IDM_READONLY", MB_OK); 375: return (0); 376: } 377: 378: retCode = VirtualProtect (base, PAGESIZE, 379: PAGE_READONLY, &oldProtection); 380: if (!retCode) 381: WERR("VirtualProtect", "IDM_READONLY"); 382: 383: ResetMenu(); 384: return (0); 385: 386: 387: case IDM_READWRITE: 388: retCode = VirtualQuery (base, &MemInfo, 389: sizeof(MEMORY_BASIC_INFORMATION)); 390: if (!retCode) 391: { 392: WERR("VirtualQuery", "IDM_READWRITE"); 393: return (0); 394: } 395: 396: if (MemInfo.State != MEM_COMMIT) 397: { 398: MessageBox ( hWnd, "The page must be commited first.", 399: "From IDM_READWRITE", MB_OK); 400: return (0); 401: } 402: 403: retCode = VirtualProtect (base, PAGESIZE, 404: PAGE_READWRITE, &oldProtection); 405: if (!retCode) 406: WERR("VirtualProtect", "IDM_READWRITE"); 407: 408: ResetMenu(); 409: return (0); 410: 411: 412: case IDM_COMMIT: 413: 414: VirtualQuery ((LPVOID)base, 415: &MemInfo, 416: sizeof(MEMORY_BASIC_INFORMATION)); 417: 418: switch (MemInfo.State) 419: { 420: case MEM_COMMIT: 421: return (0); 422: 423: case MEM_RESERVE: 424: page = VirtualAlloc (base,PAGESIZE,MEM_COMMIT,PAGE_READWRITE); 425: 426: if (page) 427: ResetMenu(); 428: else 429: WERR("VirtualAlloc", "IDM_COMMIT"); 430: break; 431: 432: case MEM_FREE: 433: base = VirtualAlloc(NULL,PAGESIZE,MEM_COMMIT,PAGE_READWRITE); 434: if (base) 435: ResetMenu(); 436: else 437: WERR("VirtualAlloc", "IDM_COMMIT"); 438: break; 439: } 440: 441: ResetMenu(); 442: return (0); 443: 444: 445: case IDM_FREE: 446: 447: VirtualQuery (base, 448: &MemInfo, 449: sizeof(MEMORY_BASIC_INFORMATION)); 450: 451: if (MemInfo.State == MEM_COMMIT) 452: { 453: retCode = VirtualFree(base, PAGESIZE, MEM_DECOMMIT); 454: if (!retCode) 455: WERR("VirtualFree","IDM_FREE"); 456: 457: } 458: 459: VirtualQuery (base, 460: &MemInfo, 461: sizeof(MEMORY_BASIC_INFORMATION)); 462: 463: if (MemInfo.State == MEM_RESERVE) 464: { 465: retCode = VirtualFree(base, 0, MEM_RELEASE); 466: if (!retCode) 467: WERR("VirtualFree", "IDM_FREE"); 468: } 469: 470: ResetMenu(); 471: return (0); 472: 473: 474: 475: case IDM_RESERVE: 476: 477: VirtualQuery ((LPVOID)base, 478: &MemInfo, 479: sizeof(MEMORY_BASIC_INFORMATION)); 480: 481: switch (MemInfo.State) 482: { 483: case MEM_RESERVE: 484: return (0); 485: 486: case MEM_FREE: 487: base = VirtualAlloc(NULL, PAGESIZE, MEM_RESERVE, PAGE_NOACCESS); 488: if (!base) 489: WERR("VirtualAlloc","IDM_RESERVE"); 490: 491: ResetMenu(); 492: return (0); 493: 494: case MEM_COMMIT: 495: retCode = VirtualFree(base, PAGESIZE, MEM_DECOMMIT); 496: 497: if (!retCode) 498: WERR("VirtualFree","IDM_RESERVE"); 499: 500: ResetMenu(); 501: return (0); 502: 503: default: 504: MessageBox(hWnd, "Unknown MemInfo.State", "From IDM_RESERVE", MB_OK); 505: 506: } 507: return (0); 508: 509: default: 510: return (0); 511: } 512: 513: case WM_DESTROY: 514: PostQuitMessage(0); 515: return (0); 516: 517: 518: } 519: return DefWindowProc (hwnd, message, wParam, lParam); 520: } 521: 522: 523: /*************************************************************************\ 524: * 525: * FUNCTION: VOID ResetMenu (VOID) 526: * 527: * PURPOSE: Updates the menu with check marks to indicate the pages state 528: * and protection. 529: * 530: * VARIABLES USED: 531: * 532: * - i: Local integer used for counting in a for loop. 533: * - hMenu: Local menu handle to the menu. 534: * 535: * CALLED BY: 536: * 537: * MainWndProc(); 538: * 539: * COMMENTS: 540: * This function uses a for loop to uncheck all the menu items. It then 541: * calls VirtualQuery() to determine information about the page, and 542: * updates the menu items with check marks as appropriate. 543: * 544: \*************************************************************************/ 545: VOID ResetMenu (VOID) 546: { 547: 548: HMENU hMenu; 549: INT i; 550: 551: hMenu = GetMenu(hWnd); 552: 553: for (i = IDM_FREE; i <= IDM_READWRITE; i++) 554: CheckMenuItem(hMenu, i, MF_BYCOMMAND | MF_UNCHECKED); 555: 556: 557: VirtualQuery (base, 558: &MemInfo, 559: sizeof(MEMORY_BASIC_INFORMATION)); 560: 561: switch (MemInfo.State) 562: { 563: case MEM_COMMIT: 564: CheckMenuItem(hMenu, 565: IDM_COMMIT, 566: MF_BYCOMMAND | MF_CHECKED); 567: break; 568: 569: case MEM_FREE: 570: CheckMenuItem(hMenu, 571: IDM_FREE, 572: MF_BYCOMMAND | MF_CHECKED); 573: break; 574: 575: case MEM_RESERVE: 576: CheckMenuItem(hMenu, 577: IDM_RESERVE, 578: MF_BYCOMMAND | MF_CHECKED); 579: break; 580: } 581: 582: 583: switch (MemInfo.Protect) 584: { 585: case 0: 586: break; 587: 588: case PAGE_READWRITE: 589: CheckMenuItem(hMenu, 590: IDM_READWRITE, 591: MF_BYCOMMAND | MF_CHECKED); 592: 593: break; 594: 595: case PAGE_READONLY: 596: CheckMenuItem(hMenu, 597: IDM_READONLY, 598: MF_BYCOMMAND | MF_CHECKED); 599: break; 600: 601: case PAGE_NOACCESS: 602: CheckMenuItem(hMenu, 603: IDM_NOACCESS, 604: MF_BYCOMMAND | MF_CHECKED); 605: break; 606: } 607: 608: CloseHandle (hMenu); 609: 610: 611: } 612: 613: 614: /*************************************************************************\ 615: * 616: * FUNCTION: LONG APIENTRY ShowDlgProc (HWND, UINT, UINT, LONG) 617: * 618: * PURPOSE: This is a dialog box function which queries page information 619: * using VirtualQuery, and then displays the information in 620: * the appropriate edit fields. 621: * 622: * MESSAGES: 623: * 624: * WM_SYSCOMMAND: 625: * If this message is trapped, the dialog box is terminated. 626: * 627: * WM_INITDIALOG: 628: * Does a VirtualQuery, checks the values returned in the 629: * fields of the MEMORY_BASIC_INFORMATION structure, and 630: * fills the edit fields of the dialog box with the appropriate 631: * information. 632: * 633: * CALLED BY: 634: * 635: * MainWndProc(); 636: * 637: \*************************************************************************/ 638: 639: LONG APIENTRY ShowDlgProc (HWND hdlg, 640: UINT message, 641: UINT wParam, 642: LONG lParam) 643: { 644: UNREFERENCED_PARAMETER( lParam ); 645: 646: switch (message) 647: { 648: case WM_SYSCOMMAND: 649: if (wParam == SC_CLOSE) 650: { 651: EndDialog(hdlg, TRUE); 652: return (TRUE); 653: } 654: return (0); 655: 656: case WM_INITDIALOG: 657: 658: VirtualQuery ((LPVOID)base, 659: &MemInfo, 660: sizeof(MEMORY_BASIC_INFORMATION)); 661: 662: SetDlgItemInt (hdlg, IDE_BASEADDR, (int)MemInfo.BaseAddress, FALSE); 663: SetDlgItemInt (hdlg, IDE_ALLOCBASE, (int)MemInfo.AllocationBase, FALSE); 664: 665: switch (MemInfo.AllocationProtect) 666: { 667: case PAGE_NOACCESS: 668: SetDlgItemText (hdlg, IDE_INITPROT, "No Access"); 669: break; 670: 671: case PAGE_READONLY: 672: SetDlgItemText (hdlg, IDE_INITPROT, "Read Only"); 673: break; 674: 675: case PAGE_READWRITE: 676: SetDlgItemText (hdlg, IDE_INITPROT, "Read/Write"); 677: break; 678: 679: default: 680: SetDlgItemText (hdlg, IDE_INITPROT, "Unknown"); 681: 682: } 683: 684: SetDlgItemInt (hdlg, IDE_SIZE, MemInfo.RegionSize, FALSE); 685: 686: 687: switch (MemInfo.State) 688: { 689: case MEM_FREE: 690: SetDlgItemText (hdlg, IDE_STATE, "Free"); 691: break; 692: 693: case MEM_RESERVE: 694: SetDlgItemText (hdlg, IDE_STATE, "Reserved"); 695: break; 696: 697: case MEM_COMMIT: 698: SetDlgItemText (hdlg, IDE_STATE, "Commited"); 699: break; 700: 701: default: 702: SetDlgItemText (hdlg, IDE_STATE, "Unknown"); 703: 704: } 705: 706: 707: switch (MemInfo.Protect) 708: { 709: case 0: 710: SetDlgItemText (hdlg, IDE_PROTECT, "Undefined"); 711: break; 712: 713: case PAGE_NOACCESS: 714: SetDlgItemText (hdlg, IDE_PROTECT, "No Access"); 715: break; 716: 717: case PAGE_READONLY: 718: SetDlgItemText (hdlg, IDE_PROTECT, "Read Only"); 719: break; 720: 721: case PAGE_READWRITE: 722: SetDlgItemText (hdlg, IDE_PROTECT, "Read/Write"); 723: break; 724: 725: default: 726: SetDlgItemText (hdlg, IDE_PROTECT, "Unknown"); 727: 728: } 729: 730: 731: return (TRUE); 732: 733: default: 734: return (0); 735: 736: } 737: 738: return (0); 739: 740: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.