author Daniel Holbert <>
Tue, 03 Dec 2013 09:33:57 -0800
changeset 158611 3930e0fc40aca2ec07979db52f5c8a57edf244b4
parent 156989 34be216f6d0e8ef3a51140156a62a807ab315f48
child 158924 4a61d432db433c9ccc98333b8ec22f6a72be00aa
permissions -rw-r--r--
Bug 945148: Prevent FACILITY_VISUALCPP redefinition in nsDllMain.cpp, with pre-2012 MSVC with Windows 8 SDK. r=bsmedberg

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */
#include <windows.h>
#if defined(_WIN32_WINNT_WIN8) && defined(_MSC_VER) && _MSC_VER < 1700
// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h, and MSVC
// defines it in delayimp.h previous to VS2012.
#include <delayimp.h>
#include "nsToolkit.h"
#include "mozilla/Assertions.h"
#include "mozilla/WindowsVersion.h"

using mozilla::IsWin8OrLater;

#if defined(__GNUC__)
// If DllMain gets name mangled, it won't be seen.
extern "C" {

                      HINSTANCE hModule, 
                      DWORD reason, 
                      LPVOID lpReserved )
    switch( reason ) {
        case DLL_PROCESS_ATTACH:

        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:


    return TRUE;

#if defined(MOZ_METRO)
 * DelayDllLoadHook - the crt calls here anytime a delay load dll is about to
 * load. There are a number of events, we listen for dliNotePreLoadLibrary.
 * On Win8, we enable Windows Runtime Component Extension support. When enabled
 * the compiler bakes auto-generated code into our binary, including a c init-
 * ializer which inits the winrt library through a call into the winrt standard
 * lib 'vccorlib'. Vccorlib in turn has system dll dependencies which are only
 * available on Win8 (currently API-MS-WIN-CORE-WINRT and
 * API-MS-WIN-CORE-WINRT-STRING), which prevent xul.dll from loading on os <=
 * Win7. To get around this we generate a dummy vccore lib with the three entry
 * points the initializer needs and load it in place of the real vccorlib. We
 * also have to add vccorlib and the system dlls to the delay load list.
 * In addition to setting up dummyvccorlib, we also have additional checks for
 * for unexpected behavior, specifically:
 * - trap attempts to load entry points in dummyvccorlib. This is not expected
 *   to happen in release code. It can happen during development if winrt apis
 *   are accessed when running on the desktop, or when winrt objects are
 *   accidentially placed in the global scope.
 * - trap and handle calls to vccorlib's __abi_FailFast in a breakpad compatible
 *   way. __abi_FailFast is called by exception handling code generated by the
 *   compiler for delegate events.

const char* kvccorlib = "vccorlib";
const char* kwinrtprelim = "api-ms-win-core-winrt";
const char* kfailfast = "?__abi_FailFast";

static bool IsWinRTDLLNotPresent(PDelayLoadInfo pdli, const char* aLibToken)
  return (!IsWin8OrLater() && pdli->szDll &&
          !strnicmp(pdli->szDll, aLibToken, strlen(aLibToken)));

static bool IsWinRTDLLPresent(PDelayLoadInfo pdli, const char* aLibToken)
  return (IsWin8OrLater() && pdli->szDll &&
          !strnicmp(pdli->szDll, aLibToken, strlen(aLibToken)));

void __stdcall __abi_MozFailFast()

FARPROC WINAPI DelayDllLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
  if (dliNotify == dliNotePreLoadLibrary) {
    if (IsWinRTDLLNotPresent(pdli, kvccorlib)) {
      return (FARPROC)LoadLibraryA("dummyvccorlib.dll");
    NS_ASSERTION(!IsWinRTDLLNotPresent(pdli, kwinrtprelim),
      "Attempting to load winrt libs in non-metro environment. "
      "(Winrt variable type placed in global scope?)");
  if (dliNotify == dliFailGetProc && IsWinRTDLLNotPresent(pdli, kvccorlib)) {
    NS_WARNING("Attempting to access winrt vccorlib entry point in non-metro environment.");
  if (dliNotify == dliNotePreGetProcAddress &&
      IsWinRTDLLPresent(pdli, kvccorlib) &&
      pdli->dlp.szProcName &&
      !strnicmp(pdli->dlp.szProcName, kfailfast, strlen(kfailfast))) {
    return (FARPROC)__abi_MozFailFast;
  return nullptr;

ExternC PfnDliHook __pfnDliNotifyHook2 = DelayDllLoadHook;
ExternC PfnDliHook __pfnDliFailureHook2 = DelayDllLoadHook;

#endif // MOZ_METRO

#if defined(__GNUC__)
} // extern "C"