1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/app/delay_load_hook_win.h" 6 7 #if defined(_WIN32_WINNT_WIN8) && _MSC_VER < 1700 8 // The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h, and in 9 // delayimp.h previous to VS2012. 10 #undef FACILITY_VISUALCPP 11 #endif 12 #include <DelayIMP.h> 13 14 #include "base/logging.h" 15 #include "base/strings/string_util.h" 16 #include "base/strings/stringprintf.h" 17 18 // So long as these symbols are supplied to the final binary through an 19 // object file (as opposed to indirectly through a library), these pointers 20 // will override the CRT's symbols and direct the notifications to our hook. 21 // Alternatively referencing the ChromeDelayLoadHook function somehow will 22 // cause this declaration of these variables to take preference to the delay 23 // load runtime's defaults (in delayimp.lib). 24 PfnDliHook __pfnDliNotifyHook2 = ChromeDelayLoadHook; 25 PfnDliHook __pfnDliFailureHook2 = ChromeDelayLoadHook; 26 27 28 namespace { 29 30 FARPROC OnPreLoadLibrary(DelayLoadInfo* info) { 31 // If the DLL name ends with "-delay.dll", this call is about one of our 32 // custom import libraries. In this case we need to snip the suffix off, 33 // and bind to the real DLL. 34 std::string dll_name(info->szDll); 35 const char kDelaySuffix[] = "-delay.dll"; 36 if (EndsWith(dll_name, kDelaySuffix, false)) { 37 // Trim the "-delay.dll" suffix from the string. 38 dll_name.resize(dll_name.length() - (sizeof(kDelaySuffix) - 1)); 39 dll_name.append(".dll"); 40 41 return reinterpret_cast<FARPROC>(::LoadLibraryA(dll_name.c_str())); 42 } 43 44 return NULL; 45 } 46 47 } // namespace 48 49 // This function is a delay load notification hook. It is invoked by the 50 // delay load support in the visual studio runtime. 51 // See http://msdn.microsoft.com/en-us/library/z9h1h6ty(v=vs.100).aspx for 52 // details. 53 extern "C" FARPROC WINAPI ChromeDelayLoadHook(unsigned reason, 54 DelayLoadInfo* info) { 55 switch (reason) { 56 case dliNoteStartProcessing: 57 case dliNoteEndProcessing: 58 // Nothing to do here. 59 break; 60 61 case dliNotePreLoadLibrary: 62 return OnPreLoadLibrary(info); 63 break; 64 65 case dliNotePreGetProcAddress: 66 // Nothing to do here. 67 break; 68 69 case dliFailLoadLib: 70 case dliFailGetProc: 71 // Returning NULL from error notifications will cause the delay load 72 // runtime to raise a VcppException structured exception, that some code 73 // might want to handle. 74 return NULL; 75 break; 76 77 default: 78 NOTREACHED() << "Impossible delay load notification."; 79 break; 80 } 81 82 // Returning NULL causes the delay load machinery to perform default 83 // processing for this notification. 84 return NULL; 85 } 86