Chrome disable-directwrite-for-ui补丁

Chrome从版本41开始强制启用directwrite ui,ui界面包括主菜单、地址栏、书签栏等不再使用点阵宋体渲染,如果系统是windows classical主题,这些地方的字体会严重发虚。

通过在chrome的快捷方式中指定–disable-directwrite-for-ui启动参数可以解决这个问题。但如果是其他程序打开浏览器的第一个实例,就没法应用这个参数。同理,基于chrome的atom、visual studio code等electron应用,通常都是通过关联文件而不是快捷方式启动,所以依然会悲剧,观感非常难受,如下图。

今天决定彻底干掉这个问题。方法很容易想到,通过劫持一个dll进行注入,然后改掉GetCommandLine返回的结果。研究chrome的依赖dll后决定选择DWrite.dll进行劫持,就像游戏外挂都喜欢用d3d9.dll注入一样,优点是它们都是只需要转发一个函数即可。d3d9是Direct3DCreate9,DWrite是DWriteCreateFactory。

代码:

#include <Windows.h>

static void* pDWriteCreateFactory;

extern "C" __declspec(dllexport) __declspec(naked) void DWriteCreateFactory()
{
	__asm jmp dword ptr [pDWriteCreateFactory];
}

BOOL WINAPI DllMain(HMODULE, UINT uReason, LPVOID)
{
	if (uReason == DLL_PROCESS_ATTACH)
	{
		WCHAR path[MAX_PATH];
		GetSystemDirectoryW(path, sizeof(path));
		lstrcatW(path, L"\\DWrite.dll");
		HMODULE hModule = LoadLibraryW(path);
		pDWriteCreateFactory = GetProcAddress(hModule, "DWriteCreateFactory");

		static WCHAR commandLine[4096];
		lstrcpyW(commandLine, GetCommandLineW());
		lstrcatW(commandLine, L" --disable-directwrite-for-ui");

		BYTE* code = (BYTE*)&GetCommandLineW;
		DWORD protect = PAGE_EXECUTE_READWRITE;
		VirtualProtect(code, 6, protect, &protect);
		code[0] = 0xB8;
		*(WCHAR**)&code[1] = commandLine;
		code[5] = 0xC3;
		VirtualProtect(code, 6, protect, &protect);
	}
	return TRUE;
}

下载:

DWrite.zip

用法:

放置到chrome内核所在的目录即可。Chrome浏览器放到chrome.dll的目录(目录名是版本号的,非chrome.exe目录),vscode等electron应用放置到exe所在目录。

 

效果:

One Reply to “Chrome disable-directwrite-for-ui补丁”

Leave a Reply

Your email address will not be published. Required fields are marked *