home *** CD-ROM | disk | FTP | other *** search
- /*+--------------------------------------------------------------------------+*/
- /*| |*/
- /*| PROGRAM NAME: SEH |*/
- /*| ------------- |*/
- /*| A Structured Exception Handling Sample program |*/
- /*| |*/
- /*| COPYRIGHT: |*/
- /*| ---------- |*/
- /*| Copyright (C) International Business Machines Corp., |*/
- /*| 1991,1992,1993,1994,1995,1996. |*/
- /*| |*/
- /*| DISCLAIMER OF WARRANTIES: |*/
- /*| ------------------------- |*/
- /*| The following [enclosed] code is sample code created by IBM |*/
- /*| Corporation. This sample code is not part of any standard IBM product |*/
- /*| and is provided to you solely for the purpose of assisting you in the |*/
- /*| development of your applications. The code is provided "AS IS", |*/
- /*| without warranty of any kind. IBM shall not be liable for any damages |*/
- /*| arising out of your use of the sample code, even if they have been |*/
- /*| advised of the possibility of such damages. |*/
- /*| |*/
- /*| REVISION LEVEL: 1.0 |*/
- /*| --------------- |*/
- /*| |*/
- /*| WHAT THIS PROGRAM DOES: |*/
- /*| ----------------------- |*/
- /*| This program is a demonstration of the use of Structured Exception |*/
- /*| Handling. It will show both Termination Handling and Exception Hanlding.|*/
- /*| Some concepts adapted from Advanced Windows NT by Jeffrey Richter. |*/
- /*| |*/
- /*| WHAT THIS PROGRAM DEMONSTRATES: |*/
- /*| ------------------------------- |*/
- /*| This program demonstrates the following in Structured Exceptions: |*/
- /*| TRY-FINALLY Block |*/
- /*| TRY-EXCEPT Block |*/
- /*| Global Unwind |*/
- /*| AbnormalTermination |*/
- /*| GetExceptionCode |*/
- /*| GetExceptionInformation |*/
- /*| REQUIRED FILES: |*/
- /*| --------------- |*/
- /*| |*/
- /*| SEH.C - Source code |*/
- /*| |*/
- /*| REQUIRED PROGRAMS: |*/
- /*| ------------------ |*/
- /*| |*/
- /*| IBM C Set++ Compiler |*/
- /*| IBM Linker |*/
- /*| |*/
- /*| |*/
- /*+--------------------------------------------------------------------------+*/
-
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <excpt.h>
-
- #define FILENAME "seh.txt" /* File for reading */
- #define FILEMODE "r" /* open file for read */
- #define NUMOBJECTS (50) /* Make it 50 objects */
- #define NUMATTEMPTS (100) /* Make 100 attempts at accessing these objects */
-
- void openFile(void);
- int MakeArrayFilter (LPEXCEPTION_POINTERS, LPBYTE, LONG);
-
- /* Useful macro for creating our own software exception codes.
- This is a 32 bit value laid out as follows:
- Bit 31-30 Sev 00 Success
- 01 Informational
- 10 Warning
- 11 Error
- Bit 29 Cus/MS 0 MS reserved
- 1 Customer code
- Bit 28 Reserved bit (always 0)
- Bit 27-16 Facility Code
- Bit 15-0 Facility's status code
- */
- #define MAKEUSEREXCEPTION(Severity, Facility, Exception) \
- ((DWORD) ( \
- /* Severity code */ (Severity << 30) | \
- /* MS(0) or Cust(1) */ (1 << 29) | \
- /* Reserved(0) */ (0 << 28) | \
- /* Facility code */ (Facility << 16) | \
- /* Exception code */ (Exception << 0)))
-
- /* Our very own software exception. This exception is raised
- when an object of the array needs to be initialized
- to all zeroes.
- */
- #define SE_ZERO_OBJECT MAKEUSEREXCEPTION(3, 0, 1)
-
- /* Declare each array object to be 1K bytes. */
- typedef struct {
- BYTE OneK[1024];
- } OBJECT, *LPOBJECT;
-
- int openFileFilter(DWORD dwExceptionCode) {
- #if !NDEBUG
- printf(" ExceptionCode is:%x\n",dwExceptionCode);
- #endif
- switch (dwExceptionCode){
- case EXCEPTION_ACCESS_VIOLATION:
- return EXCEPTION_EXECUTE_HANDLER;
- default:
- return EXCEPTION_CONTINUE_SEARCH;
- }
- }
-
- void openFile() {
- FILE *hFile;
-
- __try {
- /* Clear the "Execution log" list box. */
- printf("Starting execution for Termination Handler sample\n");
-
- /* Open the file. */
-
- /* This line could cause an exception */
- hFile = fopen(FILENAME,FILEMODE);
-
- if (hFile != NULL)
- printf(" File open: OK\n");
- else {
- printf(" File open: FAIL\n");
- __leave;
- }
-
- /* Now do some processing that will cause an exception
- We will just raise a dummy exception to cause a Global Unwind */
- RaiseException(EXCEPTION_ACCESS_VIOLATION,
- 0, /*ontinuable exception, */
- 0, NULL); /* No arguments */
-
- } /* try */
- __finally {
- /*Display a notification that we are cleaning up. */
- printf(" Cleaning up\n");
-
- /* Guarantee that the file is closed. */
- if (!AbnormalTermination()) {
- /* Normal Exit of Try block involves:
- 1. Execution to the closing brace
- 2. exit through __leave
- No errors occurred in the try block, so just close the file */
- if (hFile) {
- printf(" Normal Exit: Closing file\n");
- fclose(hFile);
- } else
- printf(" Exit through __leave: nothing to close\n");
-
- } else {
- /* Abnormal exit of TRY block. Possibly due to:
- 1. an exception causing a Global Unwind
- 2. Local Unwind
- Option 2 is impossible as there are no goto/return/break/continue/longjmp
- in TRY block. So it must be a Global Unwind. */
- if (hFile) {
- printf(" Abnormal Exit: Closing file\n");
- fclose(hFile);
- }
- }
- } /*finally*/
- }
-
- void SetVirtualMem(LPEXCEPTION_POINTERS lpEP, LPBYTE lpAccessMemAddr) {
-
- BOOL fWriteToMem;
-
- /* Find out whether a memory read or write was tried. */
- fWriteToMem = (BOOL)lpEP->ExceptionRecord->ExceptionInformation[0];
-
- /* Add an entry to the "Execution log" list box. */
- printf("---> Committing memory (%s attempted)\n",fWriteToMem ? "write" : "read");
-
- /* The attempted memory access did occur while the
- program was accessing an object in our array.
- Let's try to commit memory to an individual object of
- the reserved array's address space. */
-
- VirtualAlloc (lpAccessMemAddr, sizeof(OBJECT), MEM_COMMIT, PAGE_READWRITE);
-
- if (!fWriteToMem) {
- /* The program is trying to read an array OBJECT
- that has never been created. We'll raise our very
- own software exception so that this array object
- will be zeroed before it is accessed. */
- RaiseException(SE_ZERO_OBJECT, 0, 1,(LPDWORD) &lpAccessMemAddr);
- }
- }
-
- int MakeArrayFilter (LPEXCEPTION_POINTERS lpEP, LPBYTE lpArrayOfObject, LONG lNumBytesinArrayofObject) {
-
- /* Get the exception code explaining
- why the filter is executing. */
- DWORD dwExceptionCode =lpEP->ExceptionRecord->ExceptionCode;
- /* Assume that this filter will NOT handle the exception
- and will let the system continue scanning
- for other filters. */
- int nFilterAction = EXCEPTION_CONTINUE_SEARCH;
-
- LPBYTE lpAccessMemAddr;
- #if !NDEBUG
- printf("Filter:dwExceptionCode=%x\n",dwExceptionCode);
- #endif
- __try {
- /* Declare an EXCEPTION_RECORD structure that is local
- to this __try frame. This variable is used in the
- __except block below. */
- EXCEPTION_RECORD ArrayExceptRec;
-
- /* We must first determine if the exception is
- occurring because of a memory access to zero the
- array of elements. This filter and handler does not
- process any other types of exceptions. */
-
- if (dwExceptionCode != EXCEPTION_ACCESS_VIOLATION) {
- /* If the exception is not a memory access violation,
- the exception is not due to an array object
- access. The system should continue its search for
- another exception filter. */
- nFilterAction = EXCEPTION_CONTINUE_SEARCH;
- __leave;
- }
-
- if (lpArrayOfObject == NULL) {
- /* The exception occurred either before attempting to
- reserve the address space or, the array's address
- space was unsuccessfully reserved. */
- nFilterAction = EXCEPTION_CONTINUE_SEARCH;
- __leave;
- }
-
- /* Get the address of the attempted memory access. */
- lpAccessMemAddr = (LPBYTE)lpEP->ExceptionRecord->ExceptionInformation[1];
-
- if ((lpAccessMemAddr < lpArrayOfObject) ||((lpArrayOfObject + lNumBytesinArrayofObject) < lpAccessMemAddr)) {
- /* Address attempted is BELOW the beginning of the
- array's reserved space or is ABOVE the end of the
- array's reserved space. We'll let some other
- filter handle this exception. */
- nFilterAction = EXCEPTION_CONTINUE_SEARCH;
- __leave;
- }
-
-
- __try {
- /* Call the function that commits memory to the
- accessed array object. This function will raise
- a software exception if read-access was attempted.
- In this case, we want to zero the contents of the
- array object before the read continues. */
-
- SetVirtualMem(lpEP, lpAccessMemAddr);
- }
-
- /* We only want to handle the exception if it is our
- very own software exception telling us to zero the
- contents of the array object. If this happens, we
- need to save the additional information given to us
- with the SE_ZERO_OBJECT exception code so that the
- handler knows which array object to zero. */
- __except ((GetExceptionCode() == SE_ZERO_OBJECT) ?
- (ArrayExceptRec =
- *((GetExceptionInformation())->ExceptionRecord),
- EXCEPTION_EXECUTE_HANDLER) : EXCEPTION_CONTINUE_SEARCH) {
- /* Get the address of the array object to zero. */
- LPOBJECT lpArrayObjectToZero = (LPOBJECT)
- ArrayExceptRec.ExceptionInformation[0];
-
- /* Zero the array object before reading from it. */
- memset((LPVOID) lpArrayObjectToZero, 0, sizeof(OBJECT));
-
- printf("---> Zeroed array object\n");
- }
-
- /* Memory is committed now, let's restart the
- instruction that caused the exception in the first
- place. This time, it will succeed and not cause
- another exception. */
- nFilterAction = EXCEPTION_CONTINUE_EXECUTION;
- }
-
- __finally {
- /* There is nothing to do here, except to show that
- one can have a Termination Handler inside an
- Exception Handler.
- You could use this to show status. */
- }
-
- /* Now that memory is committed, we can continue execution
- on the instruction that generated the exception in
- the first place. */
- return(nFilterAction);
- }
-
- void makeArray(int nNumAttempts) {
- LPOBJECT lpArrayOfObject;
- OBJECT Object;
- int nObjectNum;
- const LONG lNumBytesinArrayofObject = sizeof(OBJECT) * NUMOBJECTS;
-
- __try {
- /* Clear the "Execution log" list box. */
- printf("Starting Execution on Exception Handler sample\n");
-
- /* Reserve an address space large enough to
- hold NUMOBJECTS number of ELEMENTs. */
- lpArrayOfObject=VirtualAlloc(NULL,lNumBytesinArrayofObject,MEM_RESERVE, PAGE_NOACCESS);
-
- while (nNumAttempts--) {
- #if !NDEBUG
- printf("NumAccesses=%d\n",nNumAttempts);
- #endif
- /* Get the index of a random object to access. */
- nObjectNum = rand() % NUMOBJECTS;
-
- /* Give us a 50% chance of reading and a
- 50% chance of writing. */
- if ((rand() % 2) == 0) {
- /* Attempt a read access. */
- printf("Reading index: %d\n",nObjectNum);
-
- /* The exception will occur on this line. */
- Object = lpArrayOfObject[nObjectNum];
-
- } else {
- /* Attempt a write access. */
- printf("Writing index: %d\n",nObjectNum);
-
- /* The exception will occur on this line. */
- lpArrayOfObject[nObjectNum] = Object;
- }
-
- } /* while */
-
- /* We are done with the execution. */
- printf("Execution ended\n");
-
- /* Decommit and free the array of ELEMENTs. */
- VirtualFree(lpArrayOfObject,0, MEM_RELEASE);
- } /* __try */
-
- __except (
- MakeArrayFilter(GetExceptionInformation(), (LPBYTE) lpArrayOfObject,
- lNumBytesinArrayofObject)) {
-
- /* Since the filter never returns
- EXCEPTION_EXECUTE_HANDLER, there is nothing
- to do here. */
-
- } /* __except */
- }
-
- void main() {
- /* Part 1: demonstrate Termination Handling */
- /* This will attempt to open a non-existant file, and will
- clean itself up through the finally body */
- __try {
- openFile();
- }
- __except (openFileFilter(GetExceptionCode())) {
- printf(" Open File: Caught Exception Access Violation\n");
- } /* except */
- /* Part 2: demonstrate Exception Handling */
- makeArray(NUMATTEMPTS);
- }
- /* ouput should be something like:
-
- Starting execution for Termination Handler sample
- File open: FAIL
- Cleaning up
- Exit through __leave: nothing to close
- Starting Execution on Exception Handler sample
- Reading index: 38
- ---> Committing memory (read attempted)
- ---> Zeroed array object
- Writing index: 13
- ---> Committing memory (write attempted)
- Writing index: 1
- ---> Committing memory (write attempted)
- Writing index: 10
- ---> Committing memory (write attempted)
- Reading index: 12
- Writing index: 49
- ---> Committing memory (write attempted)
- Reading index: 34
- ---> Committing memory (read attempted)
- ---> Zeroed array object
- Writing index: 25
- ---> Committing memory (write attempted)
- Writing index: 39
- Reading index: 37
- Reading index: 16
- ---> Committing memory (read attempted)
- ---> Zeroed array object
- Writing index: 45
- ---> Committing memory (write attempted)
- Reading index: 17
- Writing index: 31
- ---> Committing memory (write attempted)
- Reading index: 32
- Writing index: 24
- Reading index: 44
- Writing index: 1
- Writing index: 4
- ---> Committing memory (write attempted)
- Reading index: 11
- Reading index: 28
- Writing index: 35
- Reading index: 17
- Writing index: 15
- Reading index: 12
- Reading index: 3
- Writing index: 44
- Reading index: 12
- Writing index: 22
- ---> Committing memory (write attempted)
- Writing index: 7
- Writing index: 29
- Reading index: 1
- Writing index: 20
- Writing index: 48
- Reading index: 29
- Reading index: 6
- Reading index: 38
- Reading index: 14
- Writing index: 16
- Reading index: 31
- Reading index: 43
- ---> Committing memory (read attempted)
- ---> Zeroed array object
- Reading index: 33
- Writing index: 10
- Writing index: 21
- Writing index: 36
- Writing index: 10
- Reading index: 29
- Writing index: 25
- Writing index: 14
- Writing index: 38
- Writing index: 2
- Writing index: 34
- Writing index: 32
- Writing index: 36
- Reading index: 6
- Reading index: 1
- Reading index: 23
- Reading index: 43
- Reading index: 48
- Writing index: 20
- Reading index: 6
- Writing index: 16
- Reading index: 43
- Writing index: 41
- Writing index: 26
- Reading index: 35
- Reading index: 10
- Writing index: 2
- Reading index: 20
- Reading index: 39
- Writing index: 35
- Writing index: 25
- Writing index: 14
- Writing index: 26
- Writing index: 43
- Writing index: 19
- Writing index: 23
- Reading index: 15
- Writing index: 23
- Writing index: 13
- Writing index: 49
- Reading index: 13
- Writing index: 26
- Reading index: 46
- Reading index: 36
- Reading index: 28
- Writing index: 23
- Writing index: 21
- Reading index: 2
- Writing index: 41
- Reading index: 22
- Writing index: 28
- Writing index: 13
- Reading index: 41
- Reading index: 25
- Writing index: 13
- Writing index: 44
- Writing index: 13
- Reading index: 11
- Reading index: 45
- Execution ended
- */
-