//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation. // // File: D L O A D . C // // Contents: Delay Load Failure Hook // // Notes: This lib implements all of the stub functions for modules // that are delayloaded by the OS. It merges together all of the // dloadXXX.lib files from each depot. // // To Use: In your sources file, right after you specify the modules you // are delayloading do: // // DLOAD_ERROR_HANDLER=kernel32 // // If you want to use kernel32 as your dload error handler. If you // do this, your dll will be checked that everything it delayloads // has a proper error handler function by the delayload.cmd postbuild // script. // // To check that all functions you delayload have error handlers you // can do the following: // // 1. do a "link -dump -imports foo.dll", and find all functions // that you delay-import. // // 2. do a "link -dump -symbols \nt\public\internal\base\lib\*\dload.lib" // and make sure every function that shows up as delayloaded in step #1 // has a error handler fn. in dload.lib. // // 3. if a function is missing in step #2 (dlcheck will also fails as // part of postbuild), you need to add an error handler. Go to the depot // where that dll is build, and go to the dload subdir (usually under // the root or under the published\dload subdir) and add an error handler. // // // Author: shaunco 19 May 1998 // Modified: reinerf 12 Jan 2001 Changed above comment // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop // External global variables // extern HANDLE BaseDllHandle; #if DBG extern int DloadBreakOnFail; extern int DloadDbgPrint; #endif #if DBG #define DBG_ERROR 0 #define DBG_INFO 1 //+--------------------------------------------------------------------------- // Trace a message to the debug console. Prefix with who we are so // people know who to contact. // INT __cdecl DbgTrace ( INT nLevel, PCSTR Format, ... ) { INT cch = 0; if (DloadDbgPrint) { if (nLevel <= DBG_INFO) { CHAR szBuf [1024]; va_list argptr; va_start (argptr, Format); cch = vsprintf (szBuf, Format, argptr); va_end (argptr); OutputDebugStringA ("dload: "); OutputDebugStringA (szBuf); } } return cch; } //+--------------------------------------------------------------------------- // Cannot use RtlAssert since doing so will cause setupapi.dll to fail // for upgrade over win95(gold) // VOID WINAPI DelayLoadAssertFailed( IN PCSTR FailedAssertion, IN PVOID FileName, IN ULONG LineNumber, IN PCSTR Message OPTIONAL ) { DbgTrace ( DBG_ERROR, "Assertion failure at line %u in file %s: %s%s%s\r\n", LineNumber, FileName, FailedAssertion, (Message && Message[0] && FailedAssertion[0]) ? " " : "", Message ? Message : "" ); if (DloadBreakOnFail) { DebugBreak(); } } #endif // DBG //+--------------------------------------------------------------------------- // // FARPROC WINAPI DelayLoadFailureHook ( LPCSTR pszDllName, LPCSTR pszProcName ) { FARPROC ReturnValue = NULL; MYASSERT (pszDllName); MYASSERT (pszProcName); // Trace some potentially useful information about why we were called. // #if DBG if (!IS_INTRESOURCE(pszProcName)) { DbgTrace (DBG_INFO, "DelayloadFailureHook: Dll=%s, ProcName=%s\n", pszDllName, pszProcName); } else { DbgTrace (DBG_INFO, "DelayloadFailureHook: Dll=%s, Ordinal=%u\n", pszDllName, (DWORD)((DWORD_PTR)pszProcName)); } #endif ReturnValue = LookupHandler(pszDllName, pszProcName); if (ReturnValue) { #if DBG DbgTrace (DBG_INFO, "Returning handler function at address 0x%08x\n", (LONG_PTR)ReturnValue); #endif } #if DBG else { CHAR pszMsg [MAX_PATH]; if (!IS_INTRESOURCE(pszProcName)) { sprintf (pszMsg, "No delayload handler found for Dll=%s, ProcName=%s\n" "Please add one in private\\dload.", pszDllName, pszProcName); } else { sprintf (pszMsg, "No delayload handler found for Dll=%s, Ordinal=%u\n" "Please add one in private\\dload.", pszDllName, (DWORD)((DWORD_PTR)pszProcName)); } DelayLoadAssertFailed ( "" , __FILE__, __LINE__, pszMsg); } #endif return ReturnValue; }