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