/* * Copyright (C) 2007, 2009-2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SoftLinking_h #define SoftLinking_h #include #include #pragma mark - Soft-link helper macros #define SOFT_LINK_LIBRARY_HELPER(lib, suffix) \ static HMODULE lib##Library() \ { \ static HMODULE library = LoadLibraryW(L###lib suffix); \ return library; \ } #define SOFT_LINK_GETPROCADDRESS GetProcAddress #define SOFT_LINK_LIBRARY(lib) SOFT_LINK_LIBRARY_HELPER(lib, L".dll") #define SOFT_LINK_DEBUG_LIBRARY(lib) SOFT_LINK_LIBRARY_HELPER(lib, L"_debug.dll") #pragma mark - Soft-link macros for use within a single source file #define SOFT_LINK(library, functionName, resultType, callingConvention, parameterDeclarations, parameterNames) \ static resultType callingConvention init##functionName parameterDeclarations; \ static resultType (callingConvention*softLink##functionName) parameterDeclarations = init##functionName; \ \ static resultType callingConvention init##functionName parameterDeclarations \ { \ softLink##functionName = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #functionName)); \ ASSERT(softLink##functionName); \ return softLink##functionName parameterNames; \ } \ \ inline resultType functionName parameterDeclarations \ { \ return softLink##functionName parameterNames; \ } #define SOFT_LINK_OPTIONAL(library, functionName, resultType, callingConvention, parameterDeclarations) \ typedef resultType (callingConvention *functionName##PtrType) parameterDeclarations; \ static functionName##PtrType functionName##Ptr() \ { \ static functionName##PtrType ptr; \ static bool initialized; \ \ if (initialized) \ return ptr; \ initialized = true; \ \ ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #functionName)); \ return ptr; \ } \ #define SOFT_LINK_LOADED_LIBRARY(library, functionName, resultType, callingConvention, parameterDeclarations) \ typedef resultType (callingConvention *functionName##PtrType) parameterDeclarations; \ static functionName##PtrType functionName##Ptr() \ { \ static functionName##PtrType ptr; \ static bool initialized; \ \ if (initialized) \ return ptr; \ initialized = true; \ \ static HINSTANCE libraryInstance = ::GetModuleHandle(L#library); \ \ ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(libraryInstance, #functionName)); \ return ptr; \ } \ /* In order to soft link against functions decorated with __declspec(dllimport), we prepend "softLink_" to the function names. If you use SOFT_LINK_DLL_IMPORT(), you will also need to #define the function name to account for this, e.g.: SOFT_LINK_DLL_IMPORT(myLibrary, myFunction, ...) #define myFunction softLink_myFunction */ #define SOFT_LINK_DLL_IMPORT(library, functionName, resultType, callingConvention, parameterDeclarations, parameterNames) \ static resultType callingConvention init##functionName parameterDeclarations; \ static resultType(callingConvention*softLink##functionName) parameterDeclarations = init##functionName; \ \ static resultType callingConvention init##functionName parameterDeclarations \ { \ softLink##functionName = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #functionName)); \ ASSERT(softLink##functionName); \ return softLink##functionName parameterNames; \ } \ \ inline resultType softLink_##functionName parameterDeclarations \ { \ return softLink##functionName parameterNames; \ } #define SOFT_LINK_DLL_IMPORT_OPTIONAL(library, functionName, resultType, callingConvention, parameterDeclarations) \ typedef resultType (callingConvention *functionName##PtrType) parameterDeclarations; \ static functionName##PtrType functionName##Ptr() \ { \ static functionName##PtrType ptr; \ static bool initialized; \ \ if (initialized) \ return ptr; \ initialized = true; \ \ ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #functionName)); \ return ptr; \ } \ #define SOFT_LINK_DLL_IMPORT_OPTIONAL(library, functionName, resultType, callingConvention, parameterDeclarations) \ typedef resultType (callingConvention *functionName##PtrType) parameterDeclarations; \ static functionName##PtrType functionName##Ptr() \ { \ static functionName##PtrType ptr; \ static bool initialized; \ \ if (initialized) \ return ptr; \ initialized = true; \ \ ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #functionName)); \ return ptr; \ } \ /* Variables exported by a DLL need to be accessed through a function. If you use SOFT_LINK_VARIABLE_DLL_IMPORT(), you will also need to #define the variable name to account for this, e.g.: SOFT_LINK_VARIABLE_DLL_IMPORT(myLibrary, myVar, int) #define myVar get_myVar() */ #define SOFT_LINK_VARIABLE_DLL_IMPORT(library, variableName, variableType) \ static variableType get##variableName() \ { \ static variableType* ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #variableName)); \ ASSERT(ptr); \ return *ptr; \ } \ /* Note that this will only work for variable types for which a return value of 0 can signal an error. */ #define SOFT_LINK_VARIABLE_DLL_IMPORT_OPTIONAL(library, variableName, variableType) \ static variableType get##variableName() \ { \ static variableType* ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(library##Library(), #variableName)); \ if (!ptr) \ return 0; \ return *ptr; \ } \ #pragma mark - Soft-link macros for sharing across multiple source files // See Source/WebCore/platform/cf/CoreMediaSoftLink.{cpp,h} for an example implementation. #define SOFT_LINK_FRAMEWORK_FOR_HEADER(functionNamespace, framework) \ namespace functionNamespace { \ extern HMODULE framework##Library(bool isOptional = false); \ bool is##framework##FrameworkAvailable(); \ inline bool is##framework##FrameworkAvailable() { \ return framework##Library(true) != nullptr; \ } \ } #define SOFT_LINK_FRAMEWORK_HELPER(functionNamespace, framework, suffix) \ namespace functionNamespace { \ HMODULE framework##Library(bool isOptional = false); \ HMODULE framework##Library(bool isOptional) \ { \ static HMODULE library = LoadLibraryW(L###framework suffix); \ ASSERT_WITH_MESSAGE_UNUSED(isOptional, isOptional || library, "Could not load %s", L###framework suffix); \ return library; \ } \ } #define SOFT_LINK_FRAMEWORK(functionNamespace, framework) SOFT_LINK_FRAMEWORK_HELPER(functionNamespace, framework, L".dll") #define SOFT_LINK_DEBUG_FRAMEWORK(functionNamespace, framework) SOFT_LINK_FRAMEWORK_HELPER(functionNamespace, framework, L"_debug.dll") #ifdef DEBUG_ALL #define SOFT_LINK_FRAMEWORK_FOR_SOURCE(functionNamespace, framework) SOFT_LINK_DEBUG_FRAMEWORK(functionNamespace, framework) #else #define SOFT_LINK_FRAMEWORK_FOR_SOURCE(functionNamespace, framework) SOFT_LINK_FRAMEWORK(functionNamespace, framework) #endif #define SOFT_LINK_CONSTANT_FOR_HEADER(functionNamespace, framework, variableName, variableType) \ namespace functionNamespace { \ variableType get_##framework##_##variableName(); \ } #define SOFT_LINK_CONSTANT_FOR_SOURCE(functionNamespace, framework, variableName, variableType) \ namespace functionNamespace { \ static void init##framework##variableName(void* context) { \ variableType* ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(framework##Library(), #variableName)); \ RELEASE_ASSERT(ptr); \ *static_cast(context) = *ptr; \ } \ variableType get_##framework##_##variableName(); \ variableType get_##framework##_##variableName() \ { \ static variableType constant##framework##variableName; \ static dispatch_once_t once; \ dispatch_once_f(&once, static_cast(&constant##framework##variableName), init##framework##variableName); \ return constant##framework##variableName; \ } \ } #define SOFT_LINK_CONSTANT_MAY_FAIL_FOR_HEADER(functionNamespace, framework, variableName, variableType) \ namespace functionNamespace { \ bool canLoad_##framework##_##variableName(); \ bool init_##framework##_##variableName(); \ variableType get_##framework##_##variableName(); \ } #define SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE(functionNamespace, framework, variableName, variableType) \ namespace functionNamespace { \ static variableType constant##framework##variableName; \ bool init_##framework##_##variableName(); \ bool init_##framework##_##variableName() \ { \ variableType* ptr = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(framework##Library(), #variableName)); \ if (!ptr) \ return false; \ constant##framework##variableName = *ptr; \ return true; \ } \ bool canLoad_##framework##_##variableName(); \ bool canLoad_##framework##_##variableName() \ { \ static bool loaded = init_##framework##_##variableName(); \ return loaded; \ } \ variableType get_##framework##_##variableName(); \ variableType get_##framework##_##variableName() \ { \ return constant##framework##variableName; \ } \ } #define SOFT_LINK_FUNCTION_FOR_HEADER(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \ namespace functionNamespace { \ extern resultType(__cdecl*softLink##framework##functionName) parameterDeclarations; \ inline resultType softLink_##framework##_##functionName parameterDeclarations \ { \ return softLink##framework##functionName parameterNames; \ } \ } #define SOFT_LINK_FUNCTION_FOR_SOURCE(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \ namespace functionNamespace { \ static resultType __cdecl init##framework##functionName parameterDeclarations; \ resultType(__cdecl*softLink##framework##functionName) parameterDeclarations = init##framework##functionName; \ static resultType __cdecl init##framework##functionName parameterDeclarations \ { \ softLink##framework##functionName = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(framework##Library(), #functionName)); \ RELEASE_ASSERT(softLink##framework##functionName); \ return softLink##framework##functionName parameterNames; \ } \ } #define SOFT_LINK_FUNCTION_MAY_FAIL_FOR_HEADER(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \ WTF_EXTERN_C_BEGIN \ resultType functionName parameterDeclarations; \ WTF_EXTERN_C_END \ namespace functionNamespace { \ extern resultType (*softLink##framework##functionName) parameterDeclarations; \ bool canLoad_##framework##_##functionName(); \ bool init_##framework##_##functionName(); \ resultType softLink_##framework##_##functionName parameterDeclarations; \ } #define SOFT_LINK_FUNCTION_MAY_FAIL_FOR_SOURCE(functionNamespace, framework, functionName, resultType, parameterDeclarations, parameterNames) \ WTF_EXTERN_C_BEGIN \ resultType functionName parameterDeclarations; \ WTF_EXTERN_C_END \ namespace functionNamespace { \ resultType (*softLink##framework##functionName) parameterDeclarations = 0; \ bool init_##framework##_##functionName(); \ bool init_##framework##_##functionName() \ { \ ASSERT(!softLink##framework##functionName); \ softLink##framework##functionName = reinterpret_cast(SOFT_LINK_GETPROCADDRESS(framework##Library(), #functionName)); \ return !!softLink##framework##functionName; \ } \ \ bool canLoad_##framework##_##functionName(); \ bool canLoad_##framework##_##functionName() \ { \ static bool loaded = init_##framework##_##functionName(); \ return loaded; \ } \ \ resultType softLink_##framework##_##functionName parameterDeclarations; \ resultType softLink_##framework##_##functionName parameterDeclarations \ { \ ASSERT(softLink##framework##functionName); \ return softLink##framework##functionName parameterNames; \ } \ } #endif // SoftLinking_h