1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include <windows.h>
7 
8 // Delayed load libraries are loaded when the first symbol is used.
9 // The following ensures that we load the delayed loaded libraries from the
10 // system directory.
11 struct AutoLoadSystemDependencies {
AutoLoadSystemDependenciesAutoLoadSystemDependencies12   AutoLoadSystemDependencies() {
13     // Remove the current directory from the search path for dynamically loaded
14     // DLLs as a precaution.  This call has no effect for delay load DLLs.
15     SetDllDirectory(L"");
16 
17     HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
18     if (module) {
19       // SetDefaultDllDirectories is always available on Windows 8 and above. It
20       // is also available on Windows Vista, Windows Server 2008, and
21       // Windows 7 when MS KB2533623 has been applied.
22       decltype(SetDefaultDllDirectories)* setDefaultDllDirectories =
23           (decltype(SetDefaultDllDirectories)*)GetProcAddress(
24               module, "SetDefaultDllDirectories");
25       if (setDefaultDllDirectories) {
26         setDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
27         return;
28       }
29     }
30 
31     // When SetDefaultDllDirectories is not available, fallback to preloading
32     // dlls. The order that these are loaded does not matter since they are
33     // loaded using the LOAD_WITH_ALTERED_SEARCH_PATH flag.
34 #ifdef HAVE_64BIT_BUILD
35     // DLLs for Firefox x64 on Windows 7 (x64).
36     // Note: dwmapi.dll is preloaded since a crash will try to load it from the
37     // application's directory.
38     static LPCWSTR delayDLLs[] = {
39         L"apphelp.dll", L"cryptbase.dll", L"cryptsp.dll", L"dwmapi.dll",
40         L"mpr.dll",     L"ntmarta.dll",   L"profapi.dll", L"propsys.dll",
41         L"sspicli.dll", L"wsock32.dll"};
42 
43 #else
44     // DLLs for Firefox x86 on Windows XP through Windows 7 (x86 and x64).
45     // Note: dwmapi.dll is preloaded since a crash will try to load it from the
46     // application's directory.
47     static LPCWSTR delayDLLs[] = {
48         L"apphelp.dll", L"crypt32.dll", L"cryptbase.dll", L"cryptsp.dll",
49         L"dwmapi.dll",  L"mpr.dll",     L"msasn1.dll",    L"ntmarta.dll",
50         L"profapi.dll", L"propsys.dll", L"psapi.dll",     L"secur32.dll",
51         L"sspicli.dll", L"userenv.dll", L"uxtheme.dll",   L"ws2_32.dll",
52         L"ws2help.dll", L"wsock32.dll"};
53 #endif
54 
55     WCHAR systemDirectory[MAX_PATH + 1] = {L'\0'};
56     // If GetSystemDirectory fails we accept that we'll load the DLLs from the
57     // normal search path.
58     GetSystemDirectoryW(systemDirectory, MAX_PATH + 1);
59     size_t systemDirLen = wcslen(systemDirectory);
60 
61     // Make the system directory path terminate with a slash
62     if (systemDirectory[systemDirLen - 1] != L'\\' && systemDirLen) {
63       systemDirectory[systemDirLen] = L'\\';
64       ++systemDirLen;
65       // No need to re-null terminate
66     }
67 
68     // For each known DLL ensure it is loaded from the system32 directory
69     for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i) {
70       size_t fileLen = wcslen(delayDLLs[i]);
71       wcsncpy(systemDirectory + systemDirLen, delayDLLs[i],
72               MAX_PATH - systemDirLen);
73       if (systemDirLen + fileLen <= MAX_PATH) {
74         systemDirectory[systemDirLen + fileLen] = L'\0';
75       } else {
76         systemDirectory[MAX_PATH] = L'\0';
77       }
78       LPCWSTR fullModulePath = systemDirectory;  // just for code readability
79       // LOAD_WITH_ALTERED_SEARCH_PATH makes a dll look in its own directory for
80       // dependencies and is only available on Win 7 and below.
81       LoadLibraryExW(fullModulePath, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
82     }
83   }
84 } loadDLLs;
85