diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 2354d6dac45..5ff2a85faaf 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -524,6 +524,8 @@ MOZ_ENABLE_D2D_SURFACE = @MOZ_ENABLE_D2D_SURFACE@ MOZ_ENABLE_D3D9_LAYER = @MOZ_ENABLE_D3D9_LAYER@ MOZ_ENABLE_D3D10_LAYER = @MOZ_ENABLE_D3D10_LAYER@ MOZ_METRO = @MOZ_METRO@ +CRTDLLVERSION = @CRTDLLVERSION@ +CRTEXPDLLVERSION = @CRTEXPDLLVERSION@ MOZ_GTK2_CFLAGS = @MOZ_GTK2_CFLAGS@ MOZ_GTK2_LIBS = @MOZ_GTK2_LIBS@ diff --git a/configure.in b/configure.in index bc517769027..c4dea38b07e 100644 --- a/configure.in +++ b/configure.in @@ -618,12 +618,18 @@ if test -n "$MOZ_METRO"; then WINSDK_TARGETVER=602 # Allow a higher api set WINVER=602 + # toolkit/library/makefile.in needs these, see nsDllMain. + CRTDLLVERSION=110 + CRTEXPDLLVERSION=1-1-0 else # Target the Windows 7 SDK by default WINSDK_TARGETVER=601 WINVER=502 fi +AC_SUBST(CRTDLLVERSION) +AC_SUBST(CRTEXPDLLVERSION) + if test -n "$MOZ_METRO"; then case "$target" in *-mingw*) diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index c4a40664163..ae76246c215 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -17,6 +17,10 @@ LIBRARY_NAME = xul FORCE_SHARED_LIB = 1 MOZILLA_INTERNAL_API = 1 +ifdef MOZ_METRO +DIRS += winvccorlib +endif + ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) # This is going to be a framework named "XUL", not an ordinary library named # "libxul.dylib" @@ -544,6 +548,18 @@ EXTRA_DSO_LDOPTS += \ -DELAYLOAD:winspool.drv \ -DELAYLOAD:secur32.dll \ $(NULL) + +# See nsDllMain for an explanation +ifdef MOZ_METRO +ifdef MOZ_DEBUG +EXTRA_DSO_LDOPTS += -DELAYLOAD:VCCORLIB$(CRTDLLVERSION)D.DLL +else +EXTRA_DSO_LDOPTS += -DELAYLOAD:VCCORLIB$(CRTDLLVERSION).DLL +endif +EXTRA_DSO_LDOPTS += -DELAYLOAD:API-MS-WIN-CORE-WINRT-L$(CRTEXPDLLVERSION).DLL +EXTRA_DSO_LDOPTS += -DELAYLOAD:API-MS-WIN-CORE-WINRT-STRING-L$(CRTEXPDLLVERSION).DLL +endif + ifdef ACCESSIBILITY EXTRA_DSO_LDOPTS += -DELAYLOAD:oleacc.dll endif diff --git a/toolkit/library/nsDllMain.cpp b/toolkit/library/nsDllMain.cpp index 8198db3a17a..cf99e2e0a19 100644 --- a/toolkit/library/nsDllMain.cpp +++ b/toolkit/library/nsDllMain.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include "nsToolkit.h" #if defined(__GNUC__) @@ -36,6 +37,63 @@ BOOL APIENTRY DllMain( 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. + */ +static bool IsWin8OrHigher() +{ + static PRInt32 version = 0; + + if (version) { + return (version >= 0x602); + } + + // Match Win8 or Win8 Server or higher + OSVERSIONINFOEX osInfo; + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ::GetVersionEx((OSVERSIONINFO*)&osInfo); + version = + (osInfo.dwMajorVersion & 0xff) << 8 | (osInfo.dwMinorVersion & 0xff); + return (version >= 0x602); +} + +const char* kvccorlib = "vccorlib"; +const char* kwinrtprelim = "api-ms-win-core-winrt"; + +static bool IsWinRTDLLPresent(PDelayLoadInfo pdli, const char* aLibToken) +{ + return (!IsWin8OrHigher() && pdli->szDll && + !strnicmp(pdli->szDll, aLibToken, strlen(aLibToken))); +} + +FARPROC WINAPI DelayDllLoadHook(unsigned dliNotify, PDelayLoadInfo pdli) +{ + if (dliNotify == dliNotePreLoadLibrary) { + if (IsWinRTDLLPresent(pdli, kvccorlib)) { + return (FARPROC)LoadLibraryA("dummyvccorlib.dll"); + } + NS_ASSERTION(!IsWinRTDLLPresent(pdli, kwinrtprelim), + "Attempting to load winrt libs in non-metro environment. " + "(Winrt variable type placed in global scope?)"); + } + return NULL; +} + +ExternC PfnDliHook __pfnDliNotifyHook2 = DelayDllLoadHook; +#endif // MOZ_METRO + #if defined(__GNUC__) } // extern "C" #endif diff --git a/toolkit/library/winvccorlib/Makefile.in b/toolkit/library/winvccorlib/Makefile.in new file mode 100644 index 00000000000..02b4fb2a3c1 --- /dev/null +++ b/toolkit/library/winvccorlib/Makefile.in @@ -0,0 +1,23 @@ +# 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 http://mozilla.org/MPL/2.0/. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +LIBRARY_NAME = dummyvccorlib +MODULE = dummyvccorlib +GRE_MODULE = 1 + +include $(DEPTH)/config/autoconf.mk + +FORCE_SHARED_LIB=1 + +CPPSRCS = \ + dummyvccorlib.cpp \ + $(NULL) + +include $(topsrcdir)/config/rules.mk + diff --git a/toolkit/library/winvccorlib/dummyvccorlib.cpp b/toolkit/library/winvccorlib/dummyvccorlib.cpp new file mode 100644 index 00000000000..145f12af285 --- /dev/null +++ b/toolkit/library/winvccorlib/dummyvccorlib.cpp @@ -0,0 +1,20 @@ +/* -*- 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 http://mozilla.org/MPL/2.0/. */ + +#include + +// A dummy vccorlib.dll for shunting winrt initialization calls when we are not +// using the winrt library. For a longer explanantion see nsDllMain.cpp. + +extern "C" { +__declspec(dllexport) long __stdcall __InitializeWinRTRuntime(unsigned long data) { return S_OK; } +} + +namespace Platform { +namespace Details { +__declspec(dllexport) HRESULT InitializeData(int __threading_model) { return S_OK; } +__declspec(dllexport) void UninitializeData(int __threading_model) { } +} +}