Figure 2    app.cpp
/*************************************************************
Module name: app.cpp
Notices:     Written 1998 by Jeffrey Richter
Description: Demonstration of delay-load DLL error handling.
*************************************************************/

#include <Windows.h>
#include <Delayimp.h>   // For error handling & advanced features
#include "lib\lib.h"    // My DLL's function prototypes

// Statically link __delayLoadHelper/__FUnloadDelayLoadedDLL
#pragma comment(lib, "Delayimp.lib")

// Tell the linker that my DLL should be delay loaded
#pragma comment(linker, "/DelayLoad:lib.dll")

// Tell the linker that I want to be able to unload by DLL
#pragma comment(linker, "/Delay:unload")

// Tell the linker to make the delay-load DLL unbindable
// You usually want this, so I commented out this line
//#pragma comment(linker, "/Delay:nobind")

// Forward function prototype
LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep);

int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE, 
   LPSTR pszCmdLine, int nCmdShow) {

   // Wrap all calls to delay-load DLL functions inside SEH
   __try {
      int x = 0;

      // If you're in the debugger, try the new Debug.Modules menu item to see 
      // that the DLL is not loaded prior to executing the line below

      x = fnLib();  // Attempt to call delay-load function

      // Use Debug.Modules to see that the DLL is now loaded

      x = fnLib2(); // Attempt to call delay-load function

      // Unload the delay-loaded DLL
      // NOTE: Name must exactly match /DelayLoad:(DllName)
      __FUnloadDelayLoadedDLL("lib.dll");

      // Use Debug.Modules to see that the DLL is now unloaded

      x = fnLib();  // Attempt to call delay-load function

      // Use Debug.Modules to see that the DLL is loaded again
   }
   __except (DelayLoadDllExceptionFilter(GetExceptionInformation())) {
      // Nothing to do in here, thread continues to run normally
   }

   // More code goes here...

    return(0);
}

LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep) {

   // Assume we recognize this exception
   LONG lDisposition = EXCEPTION_EXECUTE_HANDLER;  

   // If this is a Delay-load problem, ExceptionInformation[0] points 
   // to a DelayLoadInfo structure that has detailed error info
   PDelayLoadInfo pdli = PDelayLoadInfo(pep->ExceptionRecord
      ->ExceptionInformation[0]);

   // Create a buffer where we construct error messages
   char sz[500] = { 0 };

   switch (pep->ExceptionRecord->ExceptionCode) {
   case VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND):
      // The DLL module was not found at runtime
      wsprintf(sz, "Dll not found: %s", pdli->szDll); 
      break;

   case VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND):
      // The DLL module was found but it doesn't contain the function
      if (pdli->dlp.fImportByName) {
         wsprintf(sz, "Function %s was not found in %s",
            pdli->dlp.szProcName, pdli->szDll);
      } else {
         wsprintf(sz, "Function ordinal %d was not found in %s",
            pdli->dlp.dwOrdinal, pdli->szDll);
      }
      break; 

   default:
      lDisposition = EXCEPTION_CONTINUE_SEARCH;  // We don't recognize this 	                                                 // exception
      break;
   }

   if (lDisposition == EXCEPTION_EXECUTE_HANDLER) {
      // We recognized this error and constructed a message, show it
      MessageBox(NULL, sz, NULL, MB_OK);
   }

   return(lDisposition);
}

// Skeleton DliHook function that does nothing interesting
FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli) {
   FARPROC fp = NULL;   // Default return value

   // NOTE: The members of the DelayLoadInfo structure pointed
   // to by pdli shows the results of progress made so far. 

   switch (dliNotify) {
   case dliStartProcessing:
      // Called when __delayLoadHelper attempts to find a DLL/function
      // Return 0 to have normal behavior, or non-0 to override
      // everything (you will still get dliNoteEndProcessing)
      break;

   case dliNotePreLoadLibrary:
      // Called just before LoadLibrary
      // Return NULL to have __delayLoadHelper call LoadLibary
      // or you can call LoadLibrary yourself and return the HMODULE
      fp = (FARPROC)(HMODULE) NULL;
      break;

   case dliFailLoadLib:
      // Called if LoadLibrary fails
      // Again, you can call LoadLibary yourself here and return an HMODULE
      // If you return NULL, __delayLoadHelper raises the 
      // ERROR_MOD_NOT_FOUND exception
      fp = (FARPROC)(HMODULE) NULL;
      break;

   case dliNotePreGetProcAddress:
      // Called just before GetProcAddress
      // Return NULL to have __delayLoadHelper call GetProcAddress
      // or you can call GetProcAddress yourself and return the address
      fp = (FARPROC) NULL;
      break;

   case dliFailGetProc:
      // Called if GetProcAddress fails
      // Again, you can call GetProcAddress yourself here and return an address
      // If you return NULL, __delayLoadHelper raises the 
      // ERROR_PROC_NOT_FOUND exception
      fp = (FARPROC) NULL;
      break;

   case dliNoteEndProcessing:
      // A simple notification that __delayLoadHelper is done
      // You can examine the members of the DelayLoadInfo structure
      // pointed to by pdli and raise an exception if you desire
      break;
   }

   return(fp);
}

// Tell __delayLoadHelper to call my hook function
PfnDliHook __pfnDliNotifyHook  = DliHook;
PfnDliHook __pfnDliFailureHook = DliHook;