locked
Handling exceptions (Win32) RRS feed

  • Question

  • I want to monitor a particular area in a program's virtual memory. For example, a notification message's spawn if there's a read/write operation upon the area.

    Actually, making use of guard pages is the most appropriate approach. In the article named "Creating Guard Pages", MSDN stated that: "If a program attempts to access an address within a guard page, the system raises a STATUS_GUARD_PAGE_VIOLATION (0x80000001) exception. The system also clears the PAGE_GUARD modifier, removing the memory page's guard page status. The system will not stop the next attempt to access the memory page with a STATUS_GUARD_PAGE_VIOLATION exception.". Technically, it's wise to use a mini debugger (with Win32 debugging APIs) in this situation. In the debugger's main loop, I just need to handle the exception.

    But how could I continue execution after a STATUS_GUARD_PAGE_VIOLATION exception occurs? How to re-execute the previous instruction which accessed the guarded area?

    I'm sad not to see why I'm glad
    Tuesday, March 29, 2011 10:17 AM

Answers

  • __try 
      { 
         // guarded code
      } 
     __except( GetExceptionCode() == EXCEPTION_GUARD_PAGE ?
    EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH){}
    

    I'm preparing for the exam 70-660 TS: Windows Internals
    • Marked as answer by Le Duc Anh Thursday, March 31, 2011 5:21 AM
    Tuesday, March 29, 2011 11:36 AM

All replies

  • __try 
      { 
         // guarded code
      } 
     __except( GetExceptionCode() == EXCEPTION_GUARD_PAGE ?
    EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH){}
    

    I'm preparing for the exam 70-660 TS: Windows Internals
    • Marked as answer by Le Duc Anh Thursday, March 31, 2011 5:21 AM
    Tuesday, March 29, 2011 11:36 AM
  • __try 
     { 
     // guarded code
     } 
     __except( GetExceptionCode() == EXCEPTION_GUARD_PAGE ?
    EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH){}
    

    I'm preparing for the exam 70-660 TS: Windows Internals

    Dear Sergmat,

    Following your idea, I implemented a program shown below. In the code, I have a 3-bytes memory area allocated by VirtualAlloc with PAGE_GUARD flag set. Subsequently, I write data to the area.What  I expect is  the routine guardPageExceptionHandler() called 3 times, but it doesn't. Please explain to me what happened?

    #include <windows.h>
    #include <stdio.h>  // for printf
    #include <stdlib.h>  // for exit
    
    DWORD dwPageSize;  // the page size on this computer
    LPVOID globalBase;  // base address of the test memory
    int index=0;
    INT guardPageExceptionHandler(DWORD dwCode)
    {
     if(dwCode !=EXCEPTION_GUARD_PAGE)
     // we just care about exception regarding accessing guarded pages
     return EXCEPTION_EXECUTE_HANDLER;
    
     printf("\tGuard page violation found %d\r\n", index++);
    
     return EXCEPTION_CONTINUE_EXECUTION;
    }
    
    VOID ErrorExit(LPTSTR lpMsg)
    {
     printf ("Error! %s with error code of %ld\n",
     lpMsg, GetLastError ());
     exit (0);
    }
    
    
    VOID main(VOID)
    {
     LPTSTR lpPtr;   // generic character pointer
     BOOL bSuccess;  // flag
     DWORD i;   // generic counter
    
     dwPageSize = 3;
    
     // creates a guard pages
     globalBase = VirtualAlloc(
     NULL,   // system selects address
     dwPageSize, // size of allocation
     MEM_COMMIT,  // allocate reserved pages
     PAGE_READWRITE| PAGE_GUARD); // protection = no access
     if (globalBase == NULL )
     ErrorExit(L"VirtualAlloc reserve failed");
    
     lpPtr = (LPTSTR) globalBase;
    
     // Use structured exception handling when accessing the pages.
     // If a page fault occurs, the exception filter is executed to
     // commit another page from the reserved block of pages.
     for (i=0; i < dwPageSize; i++)
     {
     printf("Trying %d...\r\n", i);
     __try
     {
      // Write to memory.
      lpPtr[i] = 'a';
      printf("\tContinue execution...\r\n");
     }
     // If there's a page fault, commit another page and try again.
     __except ( guardPageExceptionHandler( GetExceptionCode() ) )
     {
    
      // This code is executed only if the filter function is
      // unsuccessful in committing the next page.
      ExitProcess( GetLastError() );
     }
     }
    
     // Release the block of pages when you are finished using them.
     bSuccess = VirtualFree(
     globalBase, // base address of block
     0,  // bytes of committed pages
     MEM_RELEASE); // decommit the pages
    
     printf ("Release %s.\n", bSuccess ? "succeeded" : "failed" );
    }
    
    

     

    The output is :

    Trying 0...
     Guard page violation found 0
     Continue execution...
    Trying 1...
     Continue execution...
    Trying 2...
     Continue execution...
    Release succeeded.

     


    I'm sad not to see why I'm glad

    Wednesday, March 30, 2011 9:01 AM
  • I have a 3-bytes memory area allocated by VirtualAlloc with PAGE_GUARD flag set.
    You have 4096 bytes.
    What I expect is the routine guardPageExceptionHandler() called 3 times, but it doesn't. Please explain to me what happened?
    VirtualAlloc function reserves or commits a region of PAGES in the virtual address space of the calling process. Physical storage and the virtual address space of each process are organized into pages, units of memory, whose size depends on the host computer. For example, on x86 computers the host page size is 4 kilobytes. Read this book

    I'm preparing for the exam 70-660 TS: Windows Internals
    Wednesday, March 30, 2011 11:14 AM
  • I have a 3-bytes memory area allocated by VirtualAlloc with PAGE_GUARD flag set.
      You have 4096 bytes.

    Yeah, I've already known that. A friend of mine recommended that I should call VirtualProtect() in  the exception handler to modify the protection on that area. I did follow but it resulted in an endless loop :(

     

    INT guardPageExceptionHandler(DWORD dwCode)
    {
    	if(dwCode !=EXCEPTION_GUARD_PAGE)
    		// we just care about exception regarding accessing guarded pages
    		return EXCEPTION_EXECUTE_HANDLER;
    
    	printf("\tGuard page violation found %d\r\n", index++);
    	
    	// new code
    	DWORD dwOldProtect;
    	VirtualProtect(globalBase, dwPageSize,PAGE_READWRITE| PAGE_GUARD, &dwOldProtect);
    
    	return EXCEPTION_CONTINUE_EXECUTION;
    }
    

     

     


    I'm sad not to see why I'm glad



    Thursday, March 31, 2011 2:38 AM
  • Hei, my problem's solved! Thanks anyway. :D
    I'm sad not to see why I'm glad
    Thursday, March 31, 2011 5:21 AM