OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/renderer/render_font_warmup_win.h" | 5 #include "content/common/font_warmup_win.h" |
6 | 6 |
7 #include <dwrite.h> | 7 #include <dwrite.h> |
8 | 8 |
9 #include "base/debug/alias.h" | 9 #include "base/debug/alias.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/win/iat_patch_function.h" | 11 #include "base/win/iat_patch_function.h" |
12 #include "base/win/windows_version.h" | 12 #include "base/win/windows_version.h" |
13 #include "content/public/common/dwrite_font_platform_win.h" | 13 #include "content/public/common/dwrite_font_platform_win.h" |
14 #include "third_party/WebKit/public/web/win/WebFontRendering.h" | 14 #include "third_party/WebKit/public/web/win/WebFontRendering.h" |
15 #include "third_party/skia/include/core/SkPaint.h" | 15 #include "third_party/skia/include/core/SkPaint.h" |
16 #include "third_party/skia/include/ports/SkFontMgr.h" | 16 #include "third_party/skia/include/ports/SkFontMgr.h" |
17 #include "third_party/skia/include/ports/SkTypeface_win.h" | 17 #include "third_party/skia/include/ports/SkTypeface_win.h" |
18 | 18 |
19 namespace content { | 19 namespace content { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 SkFontMgr* g_warmup_fontmgr = NULL; | 23 SkFontMgr* g_warmup_fontmgr = nullptr; |
24 | 24 |
25 base::win::IATPatchFunction g_iat_patch_open_sc_manager; | 25 base::win::IATPatchFunction g_iat_patch_open_sc_manager; |
26 base::win::IATPatchFunction g_iat_patch_close_service_handle; | 26 base::win::IATPatchFunction g_iat_patch_close_service_handle; |
27 base::win::IATPatchFunction g_iat_patch_open_service; | 27 base::win::IATPatchFunction g_iat_patch_open_service; |
28 base::win::IATPatchFunction g_iat_patch_start_service; | 28 base::win::IATPatchFunction g_iat_patch_start_service; |
29 base::win::IATPatchFunction g_iat_patch_nt_connect_port; | 29 base::win::IATPatchFunction g_iat_patch_nt_connect_port; |
30 | 30 |
31 // These are from ntddk.h | 31 // These are from ntddk.h |
32 #if !defined(STATUS_ACCESS_DENIED) | 32 #if !defined(STATUS_ACCESS_DENIED) |
33 #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) | 33 #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) |
34 #endif | 34 #endif |
35 | 35 |
36 typedef LONG NTSTATUS; | 36 typedef LONG NTSTATUS; |
37 | 37 |
| 38 const uintptr_t kFakeSCMHandle = 0xdead0001; |
| 39 const uintptr_t kFakeServiceHandle = 0xdead0002; |
| 40 |
38 SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name, | 41 SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name, |
39 const wchar_t* database_name, | 42 const wchar_t* database_name, |
40 DWORD access_mask) { | 43 DWORD access_mask) { |
41 ::SetLastError(0); | 44 ::SetLastError(0); |
42 return reinterpret_cast<SC_HANDLE>(0xdeadbeef); | 45 return reinterpret_cast<SC_HANDLE>(kFakeSCMHandle); |
43 } | 46 } |
44 | 47 |
45 SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager, | 48 SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager, |
46 const wchar_t* service_name, | 49 const wchar_t* service_name, |
47 DWORD access_mask) { | 50 DWORD access_mask) { |
48 ::SetLastError(0); | 51 ::SetLastError(0); |
49 return reinterpret_cast<SC_HANDLE>(0xdeadbabe); | 52 return reinterpret_cast<SC_HANDLE>(kFakeServiceHandle); |
50 } | 53 } |
51 | 54 |
52 BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) { | 55 BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) { |
53 if (service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbabe) && | 56 if (service_handle != reinterpret_cast<SC_HANDLE>(kFakeServiceHandle) && |
54 service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbeef)) | 57 service_handle != reinterpret_cast<SC_HANDLE>(kFakeSCMHandle)) |
55 CHECK(false); | 58 CHECK(false); |
56 ::SetLastError(0); | 59 ::SetLastError(0); |
57 return TRUE; | 60 return TRUE; |
58 } | 61 } |
59 | 62 |
60 BOOL WINAPI StartServiceWPatch(SC_HANDLE service, | 63 BOOL WINAPI StartServiceWPatch(SC_HANDLE service, |
61 DWORD args, | 64 DWORD args, |
62 const wchar_t** arg_vectors) { | 65 const wchar_t** arg_vectors) { |
63 if (service != reinterpret_cast<SC_HANDLE>(0xdeadbabe)) | 66 if (service != reinterpret_cast<SC_HANDLE>(kFakeServiceHandle)) |
64 CHECK(false); | 67 CHECK(false); |
65 ::SetLastError(ERROR_ACCESS_DENIED); | 68 ::SetLastError(ERROR_ACCESS_DENIED); |
66 return FALSE; | 69 return FALSE; |
67 } | 70 } |
68 | 71 |
69 NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle, | 72 NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle, |
70 void* port_name, | 73 void* port_name, |
71 void* object_attribs, | 74 void* object_attribs, |
72 void* port_attribs, | 75 void* port_attribs, |
73 DWORD flags, | 76 DWORD flags, |
(...skipping 20 matching lines...) Expand all Loading... |
94 // OpenSCManagerW | 97 // OpenSCManagerW |
95 // OpenServiceW | 98 // OpenServiceW |
96 // StartServiceW | 99 // StartServiceW |
97 // CloseServiceHandle. | 100 // CloseServiceHandle. |
98 // These are all IAT patched. | 101 // These are all IAT patched. |
99 void PatchServiceManagerCalls() { | 102 void PatchServiceManagerCalls() { |
100 static bool is_patched = false; | 103 static bool is_patched = false; |
101 if (is_patched) | 104 if (is_patched) |
102 return; | 105 return; |
103 const char* service_provider_dll = | 106 const char* service_provider_dll = |
104 (base::win::GetVersion() >= base::win::VERSION_WIN8 ? | 107 (base::win::GetVersion() >= base::win::VERSION_WIN8 |
105 "api-ms-win-service-management-l1-1-0.dll" : "advapi32.dll"); | 108 ? "api-ms-win-service-management-l1-1-0.dll" |
| 109 : "advapi32.dll"); |
106 | 110 |
107 is_patched = true; | 111 is_patched = true; |
108 | 112 |
109 DWORD patched = g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", | 113 DWORD patched = |
110 service_provider_dll, "OpenSCManagerW", OpenSCManagerWPatch); | 114 g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", service_provider_dll, |
| 115 "OpenSCManagerW", OpenSCManagerWPatch); |
111 DCHECK(patched == 0); | 116 DCHECK(patched == 0); |
112 | 117 |
113 patched = g_iat_patch_close_service_handle.Patch(L"dwrite.dll", | 118 patched = g_iat_patch_close_service_handle.Patch( |
114 service_provider_dll, "CloseServiceHandle", CloseServiceHandlePatch); | 119 L"dwrite.dll", service_provider_dll, "CloseServiceHandle", |
| 120 CloseServiceHandlePatch); |
115 DCHECK(patched == 0); | 121 DCHECK(patched == 0); |
116 | 122 |
117 patched = g_iat_patch_open_service.Patch(L"dwrite.dll", | 123 patched = g_iat_patch_open_service.Patch(L"dwrite.dll", service_provider_dll, |
118 service_provider_dll, "OpenServiceW", OpenServiceWPatch); | 124 "OpenServiceW", OpenServiceWPatch); |
119 DCHECK(patched == 0); | 125 DCHECK(patched == 0); |
120 | 126 |
121 patched = g_iat_patch_start_service.Patch(L"dwrite.dll", | 127 patched = g_iat_patch_start_service.Patch( |
122 service_provider_dll, "StartServiceW", StartServiceWPatch); | 128 L"dwrite.dll", service_provider_dll, "StartServiceW", StartServiceWPatch); |
123 DCHECK(patched == 0); | 129 DCHECK(patched == 0); |
124 | 130 |
125 patched = g_iat_patch_nt_connect_port.Patch(L"dwrite.dll", | 131 patched = g_iat_patch_nt_connect_port.Patch( |
126 "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch); | 132 L"dwrite.dll", "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch); |
127 DCHECK(patched == 0); | 133 DCHECK(patched == 0); |
128 } | 134 } |
129 | 135 |
130 // Windows-only DirectWrite support. These warm up the DirectWrite paths | 136 // Windows-only DirectWrite support. These warm up the DirectWrite paths |
131 // before sandbox lock down to allow Skia access to the Font Manager service. | 137 // before sandbox lock down to allow Skia access to the Font Manager service. |
132 void CreateDirectWriteFactory(IDWriteFactory** factory) { | 138 void CreateDirectWriteFactory(IDWriteFactory** factory) { |
133 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; | 139 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; |
134 HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll"); | 140 HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll"); |
135 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. | 141 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. |
136 if (!dwrite_dll) { | 142 if (!dwrite_dll) { |
137 DWORD load_library_get_last_error = GetLastError(); | 143 DWORD load_library_get_last_error = GetLastError(); |
138 base::debug::Alias(&dwrite_dll); | 144 base::debug::Alias(&dwrite_dll); |
139 base::debug::Alias(&load_library_get_last_error); | 145 base::debug::Alias(&load_library_get_last_error); |
140 CHECK(false); | 146 CHECK(false); |
141 } | 147 } |
142 | 148 |
143 PatchServiceManagerCalls(); | 149 PatchServiceManagerCalls(); |
144 | 150 |
145 DWriteCreateFactoryProc dwrite_create_factory_proc = | 151 DWriteCreateFactoryProc dwrite_create_factory_proc = |
146 reinterpret_cast<DWriteCreateFactoryProc>( | 152 reinterpret_cast<DWriteCreateFactoryProc>( |
147 GetProcAddress(dwrite_dll, "DWriteCreateFactory")); | 153 GetProcAddress(dwrite_dll, "DWriteCreateFactory")); |
148 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. | 154 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. |
149 if (!dwrite_create_factory_proc) { | 155 if (!dwrite_create_factory_proc) { |
150 DWORD get_proc_address_get_last_error = GetLastError(); | 156 DWORD get_proc_address_get_last_error = GetLastError(); |
151 base::debug::Alias(&dwrite_create_factory_proc); | 157 base::debug::Alias(&dwrite_create_factory_proc); |
152 base::debug::Alias(&get_proc_address_get_last_error); | 158 base::debug::Alias(&get_proc_address_get_last_error); |
153 CHECK(false); | 159 CHECK(false); |
154 } | 160 } |
155 CHECK(SUCCEEDED( | 161 CHECK(SUCCEEDED(dwrite_create_factory_proc( |
156 dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_ISOLATED, | 162 DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory), |
157 __uuidof(IDWriteFactory), | 163 reinterpret_cast<IUnknown**>(factory)))); |
158 reinterpret_cast<IUnknown**>(factory)))); | |
159 } | 164 } |
160 | 165 |
161 HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory, | 166 HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory, |
162 IDWriteFontCollection** col, | 167 IDWriteFontCollection** col, |
163 BOOL checkUpdates) { | 168 BOOL checkUpdates) { |
164 // We always return pre-created font collection from here. | 169 // We always return pre-created font collection from here. |
165 IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory); | 170 IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory); |
166 DCHECK(custom_collection != NULL); | 171 DCHECK(custom_collection != nullptr); |
167 *col = custom_collection; | 172 *col = custom_collection; |
168 return S_OK; | 173 return S_OK; |
169 } | 174 } |
170 | 175 |
171 void PatchDWriteFactory(IDWriteFactory* factory) { | 176 void PatchDWriteFactory(IDWriteFactory* factory) { |
172 const unsigned int kGetSystemFontCollectionVTableIndex = 3; | 177 const unsigned int kGetSystemFontCollectionVTableIndex = 3; |
173 | 178 |
174 PROC* vtable = *reinterpret_cast<PROC**>(factory); | 179 PROC* vtable = *reinterpret_cast<PROC**>(factory); |
175 PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex]; | 180 PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex]; |
176 void* stub_function = &StubFontCollection; | 181 void* stub_function = &StubFontCollection; |
(...skipping 18 matching lines...) Expand all Loading... |
195 | 200 |
196 PatchDWriteFactory(factory); | 201 PatchDWriteFactory(factory); |
197 | 202 |
198 blink::WebFontRendering::setDirectWriteFactory(factory); | 203 blink::WebFontRendering::setDirectWriteFactory(factory); |
199 g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory); | 204 g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory); |
200 } | 205 } |
201 return g_warmup_fontmgr; | 206 return g_warmup_fontmgr; |
202 } | 207 } |
203 | 208 |
204 } // namespace content | 209 } // namespace content |
OLD | NEW |