OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/native_library.h" | 5 #include "base/native_library.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
10 #include "base/metrics/histogram_macros.h" | |
10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
11 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
13 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
14 | 15 |
15 namespace base { | 16 namespace base { |
16 | 17 |
17 typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name); | 18 typedef HMODULE(WINAPI* AddDllDirectory)(PCWSTR NewDirectory); |
19 typedef HMODULE(WINAPI* LoadLibraryFunction)(const wchar_t* file_name); | |
20 typedef HMODULE(WINAPI* LoadLibraryFunctionEx)(const wchar_t* file_name, | |
21 HANDLE hFile, | |
22 DWORD dwFlags); | |
18 | 23 |
19 namespace { | 24 namespace { |
20 | 25 // This helper method uses LoadLibrary() WinAPI. |
21 NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path, | 26 NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path, |
22 LoadLibraryFunction load_library_api, | 27 LoadLibraryFunction load_library_api, |
23 NativeLibraryLoadError* error) { | 28 NativeLibraryLoadError* error) { |
24 // LoadLibrary() opens the file off disk. | 29 // LoadLibrary() opens the file off disk. |
25 ThreadRestrictions::AssertIOAllowed(); | 30 ThreadRestrictions::AssertIOAllowed(); |
26 | 31 |
27 // Switch the current directory to the library directory as the library | 32 // Switch the current directory to the library directory as the library |
28 // may have dependencies on DLLs in this directory. | 33 // may have dependencies on DLLs in this directory. |
29 bool restore_directory = false; | 34 bool restore_directory = false; |
30 FilePath current_directory; | 35 FilePath current_directory; |
(...skipping 10 matching lines...) Expand all Loading... | |
41 // GetLastError() needs to be called immediately after |load_library_api|. | 46 // GetLastError() needs to be called immediately after |load_library_api|. |
42 error->code = GetLastError(); | 47 error->code = GetLastError(); |
43 } | 48 } |
44 | 49 |
45 if (restore_directory) | 50 if (restore_directory) |
46 SetCurrentDirectory(current_directory); | 51 SetCurrentDirectory(current_directory); |
47 | 52 |
48 return module; | 53 return module; |
49 } | 54 } |
50 | 55 |
56 // This helper method uses LoadLibraryEx() WinAPI. | |
57 NativeLibrary LoadNativeLibraryHelperEx(const FilePath& library_path, | |
58 LoadLibraryFunctionEx load_library_api, | |
59 NativeLibraryLoadError* error) { | |
60 // LoadLibraryEx() opens the file off disk. | |
61 ThreadRestrictions::AssertIOAllowed(); | |
62 | |
63 // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR flag is needed to search the library | |
64 // directory as the library may have dependencies on DLLs in this directory. | |
65 HMODULE module = (*load_library_api)( | |
66 library_path.value().c_str(), nullptr, | |
67 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); | |
68 if (!module && error) { | |
69 // GetLastError() needs to be called immediately after |load_library_api|. | |
70 error->code = GetLastError(); | |
71 } | |
72 | |
73 return module; | |
74 } | |
75 | |
51 } // namespace | 76 } // namespace |
52 | 77 |
53 std::string NativeLibraryLoadError::ToString() const { | 78 std::string NativeLibraryLoadError::ToString() const { |
54 return StringPrintf("%u", code); | 79 return StringPrintf("%u", code); |
55 } | 80 } |
56 | 81 |
57 // static | 82 // static |
58 NativeLibrary LoadNativeLibraryWithOptions(const FilePath& library_path, | 83 NativeLibrary LoadNativeLibraryWithOptions(const FilePath& library_path, |
59 const NativeLibraryOptions& options, | 84 const NativeLibraryOptions& options, |
60 NativeLibraryLoadError* error) { | 85 NativeLibraryLoadError* error) { |
61 return LoadNativeLibraryHelper(library_path, LoadLibraryW, error); | 86 return LoadNativeLibraryHelper(library_path, LoadLibraryW, error); |
62 } | 87 } |
63 | 88 |
64 NativeLibrary LoadNativeLibraryDynamically(const FilePath& library_path) { | 89 NativeLibrary LoadNativeLibraryDynamically(const FilePath& library_path) { |
65 typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name); | 90 HMODULE load_library_module = nullptr; |
66 | 91 |
67 LoadLibraryFunction load_library = reinterpret_cast<LoadLibraryFunction>( | 92 enum LoadLibraryResult { |
68 GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW")); | 93 // LoadLibraryExW API/flags are available and the call succeeds. |
94 LoadLibExW_Succeed = 0, | |
95 // LoadLibraryExW API/flags are availabe to use but the call fails, then | |
96 // LoadLibraryW is used and succeeds. | |
97 LoadLibExW_Fail_LoadLibW_Succeed, | |
98 // LoadLibraryExW API/flags are availabe to use but the call fails, then | |
99 // LoadLibraryW is used but fails as well. | |
100 LoadLibExW_Fail_LoadLibW_Fail, | |
101 // LoadLibraryExW API/flags are unavailabe to use, then LoadLibraryW is used | |
102 // and succeeds. | |
103 LoadLibExW_Unavailable_LoadLibW_Succeed, | |
104 // LoadLibraryExW API/flags are unavailabe to use, then LoadLibraryW is used | |
105 // but fails. | |
106 LoadLibExW_Unavailable_LoadLibW_Fail, | |
107 // Add new items before this one, always keep this one at the end. | |
108 END | |
xhwang
2017/03/14 00:14:32
nit: We use UPPER_CASE style for enums
https://chr
chengx
2017/03/14 02:44:40
Done.
| |
109 }; | |
69 | 110 |
70 return LoadNativeLibraryHelper(library_path, load_library, NULL); | 111 // This variable records the library loading result. |
112 LoadLibraryResult load_library_status = LoadLibraryResult::LoadLibExW_Succeed; | |
113 | |
114 // The LOAD_LIBRARY_SEARCH_* flags are available on systems that have | |
115 // KB2533623 installed. To determine whether the flags are available, use | |
116 // GetProcAddress to get the address of the AddDllDirectory, | |
117 // RemoveDllDirectory, or SetDefaultDllDirectories function. If GetProcAddress | |
118 // succeeds, the LOAD_LIBRARY_SEARCH_* flags can be used with LoadLibraryEx. | |
119 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85). aspx | |
120 // The LOAD_LIBRARY_SEARCH_* flags are used in LoadNativeLibraryHelperEx | |
121 // method above. | |
122 auto add_dll_dir_func = reinterpret_cast<AddDllDirectory>( | |
123 GetProcAddress(GetModuleHandle(L"kernel32.dll"), "AddDllDirectory")); | |
124 | |
125 if (add_dll_dir_func) { | |
126 LoadLibraryFunctionEx load_library = | |
127 reinterpret_cast<LoadLibraryFunctionEx>( | |
128 GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryExW")); | |
129 load_library_module = | |
130 LoadNativeLibraryHelperEx(library_path, load_library, nullptr); | |
xhwang
2017/03/14 00:14:32
I guess we are mixing DLL load failure with LOAD_L
chengx
2017/03/14 02:44:40
I think you are right. We have LoadLibraryW and Lo
| |
131 } | |
xhwang
2017/03/14 00:14:32
nit: We (media) like to return early...
So here y
chengx
2017/03/14 02:44:40
Return early SGTM.
| |
132 | |
133 // If LoadLibraryExW API call fails, try LoadLibraryW API. | |
134 if (!load_library_module) { | |
135 LoadLibraryFunction load_library = reinterpret_cast<LoadLibraryFunction>( | |
136 GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW")); | |
137 load_library_module = | |
138 LoadNativeLibraryHelper(library_path, load_library, nullptr); | |
139 // Record the library loading result. | |
140 if (add_dll_dir_func) { | |
141 if (load_library_module) | |
142 load_library_status = | |
143 LoadLibraryResult::LoadLibExW_Fail_LoadLibW_Succeed; | |
144 else | |
145 load_library_status = LoadLibraryResult::LoadLibExW_Fail_LoadLibW_Fail; | |
146 } else if (load_library_module) | |
147 load_library_status = | |
148 LoadLibraryResult::LoadLibExW_Unavailable_LoadLibW_Succeed; | |
149 else | |
150 load_library_status = | |
151 LoadLibraryResult::LoadLibExW_Unavailable_LoadLibW_Fail; | |
152 } | |
153 | |
154 UMA_HISTOGRAM_ENUMERATION("LibraryLoader.NativeLibraryDynamicallyLoad", | |
155 load_library_status, LoadLibraryResult::END); | |
156 return load_library_module; | |
71 } | 157 } |
72 | 158 |
73 // static | 159 // static |
74 void UnloadNativeLibrary(NativeLibrary library) { | 160 void UnloadNativeLibrary(NativeLibrary library) { |
75 FreeLibrary(library); | 161 FreeLibrary(library); |
76 } | 162 } |
77 | 163 |
78 // static | 164 // static |
79 void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, | 165 void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, |
80 StringPiece name) { | 166 StringPiece name) { |
81 return GetProcAddress(library, name.data()); | 167 return GetProcAddress(library, name.data()); |
82 } | 168 } |
83 | 169 |
84 // static | 170 // static |
85 std::string GetNativeLibraryName(StringPiece name) { | 171 std::string GetNativeLibraryName(StringPiece name) { |
86 DCHECK(IsStringASCII(name)); | 172 DCHECK(IsStringASCII(name)); |
87 return name.as_string() + ".dll"; | 173 return name.as_string() + ".dll"; |
88 } | 174 } |
89 | 175 |
90 } // namespace base | 176 } // namespace base |
OLD | NEW |