Home | History | Annotate | Download | only in app
      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