WINE IE 与 wine_gecko 架构分析
一、整体架构
ReactOS 中的 Internet Explorer 采用 四层架构,每一层都是独立的 DLL/EXE 模块:
iexplore.exe (可执行入口)
|
v
ieframe.dll (浏览器框架 - 窗口、菜单、导航栏、IWebBrowser2)
|
v
mshtml.dll (Trident COM ↔ XPCOM 桥接层 - HTMLDocument, IHTMLDocument2)
|
v
wine_gecko (Mozilla Gecko 引擎 - xul.dll + 配套 DLL)
核心设计理念 :mshtml.dll 不包含自有的 HTML/CSS 引擎实现 ,而是作为 Trident(MSHTML)COM 接口与 Mozilla Gecko(XPCOM)引擎之间的桥接层。这使得 ReactOS/Wine 无需重新实现整个浏览器引擎即可提供 HTML 渲染能力。
二、各层详解
2.1 iexplore.exe --- 可执行入口
位置 :base/applications/iexplore/main.c
- 极简的包装器 EXE
- 主要逻辑通过
IEWinMain()委托给ieframe.dll - 支持
/regserver和/unregserver命令行参数
2.2 ieframe.dll --- 浏览器框架
位置 :dll/win32/ieframe/
职责:完整的浏览器壳(shell),提供用户可见的 UI 元素和浏览器服务。
核心结构体
| 结构体 | 文件 | 职责 |
|---|---|---|
DocHost |
ieframe.h:119 |
文档宿主机,管理 WebBrowser 控件、URL、状态、travel log |
ShellBrowser |
ieframe.h:84 |
IShellBrowser/IBrowserService 实现,与 shell 集成 |
WebBrowser |
ieframe.h:178 |
IWebBrowser2 COM 接口实现,供外部调用 |
TravelLog |
shellbrowser.c:41 |
ITravelLog COM 接口,管理浏览历史 |
关键 COM 接口
| 接口 | 用途 |
|---|---|
IWebBrowser2 |
外部控制浏览器的主要 COM 接口(Navigate, GoBack, GoForward 等) |
IShellBrowser |
与 Windows Shell 的集成接口 |
IBrowserService |
浏览器内部服务接口 |
IDocHostUIHandler2 |
自定义 MSHTML 宿主行为(菜单、键盘、拖放等) |
IOleClientSite |
OLE 嵌入容器接口 |
IDocObjectService |
文档对象服务(BeforeNavigate2, NavigateComplete2 事件) |
启动流程
IEWinMain() → InternetExplorer_Construct()
→ DocHost_Init() # 初始化 DocHost
→ HlinkFrame_Init() # 初始化超链接框架
→ IWebBrowser2_Navigate2() # 导航到 URL
→ OleCreate(CLSID_HTMLDocument) # 创建 mshtml 的 HTMLDocument
2.3 mshtml.dll --- Trident/Gecko 桥接层
位置 :dll/win32/mshtml/
职责:实现 Trident(MSHTML)COM 接口,但将实际渲染工作委托给 wine_gecko。
核心组件
| 组件 | 文件 | 职责 |
|---|---|---|
HTMLDocumentObj |
htmldoc.c |
IHTMLDocument2/3 的 COM 实现 |
NSContainer |
nsembed.c |
Gecko 容器,持有 XPCOM 接口指针 |
load_gecko() |
nsembed.c:754 |
Gecko 加载入口 |
load_xul() |
nsembed.c:472 |
加载 xul.dll |
init_xpcom() |
nsembed.c:690 |
初始化 XPCOM 运行时 |
Gecko 加载流程
mshtml.dll DLL_PROCESS_ATTACH
→ load_gecko() [DLL 加载时调用]
→ load_wine_gecko(gre_path) [从注册表读取 Gecko 路径]
→ RegOpenKey(HKLM\Software\Wine\MSHTML\2.40)
→ RegQueryValueExW("GeckoPath")
→ "%SystemRoot%\wine_gecko" (REG_EXPAND_SZ)
→ ExpandEnvironmentStringsW → "C:\ReactOS\wine_gecko"
→ check_version() [验证 VERSION 文件 = "Wine Gecko 2.40"]
→ load_xul() [LoadLibraryExW(xul.dll)]
→ set_environment() [设置 PATH, NSPR_LOG_MODULES 等]
→ GetProcAddress 解析 15 个 XPCOM 核心函数
→ init_xpcom(gre_path) [初始化 XPCOM]
→ NS_InitXPCOM2()
→ 获取 nsIComponentManager
→ 注册 nsIComponentRegistrar (nsio, mutation observer)
→ 设置偏好 (set_preferences)
→ 注册自定义 nsIO 服务
← 成功: pCompMgr != NULL
← 失败: "Could not load wine-gecko. HTML rendering will be disabled."
动态解析的 XPCOM 函数
从 xul.dll 通过 GetProcAddress 解析的 15 个核心函数:
| 函数 | 用途 |
|---|---|
NS_InitXPCOM2 |
初始化 XPCOM 运行时 |
NS_ShutdownXPCOM |
关闭 XPCOM |
NS_GetComponentRegistrar |
获取组件注册器 |
NS_StringContainerInit2 |
初始化 Unicode 字符串容器 |
NS_CStringContainerInit2 |
初始化 C 字符串容器 |
NS_StringContainerFinish |
销毁 Unicode 字符串容器 |
NS_CStringContainerFinish |
销毁 C 字符串容器 |
NS_StringSetData |
设置 Unicode 字符串数据 |
NS_CStringSetData |
设置 C 字符串数据 |
NS_NewLocalFile |
创建 nsIFile 本地文件对象 |
NS_StringGetData |
获取 Unicode 字符串数据 |
NS_CStringGetData |
获取 C 字符串数据 |
NS_Alloc / NS_Free |
XPCOM 内存分配/释放 |
| 循环收集函数 | ccref_incr, ccref_decr, ccref_init, ccp_init, describe_cc_node, note_cc_edge |
NSContainer --- Gecko 与 MSHTML 的桥接
位置 :mshtml_private.h:650
NSContainer 是 mshtml 中最核心的桥接结构体,它持有 Gecko 引擎的 XPCOM 接口指针:
c
struct NSContainer {
nsIWebBrowserChrome nsIWebBrowserChrome_iface; // Gecko 浏览器 chrome
nsIContextMenuListener nsIContextMenuListener_iface; // 右键菜单监听
nsIURIContentListener nsIURIContentListener_iface; // URI 内容监听
nsIEmbeddingSiteWindow nsIEmbeddingSiteWindow_iface; // 嵌入站点窗口
nsITooltipListener nsITooltipListener_iface; // 工具提示
nsIInterfaceRequestor nsIInterfaceRequestor_iface; // 接口请求器
nsISupportsWeakReference nsISupportsWeakReference_iface;
nsIWebBrowser *webbrowser; // Gecko 的 WebBrowser 对象
nsIBaseWindow *window; // Gecko 的基础窗口
nsIWebNavigation *navigation; // 导航接口 (GoBack, GoForward, LoadURI)
nsIWebBrowserFocus *focus; // 焦点管理
nsIWebBrowserSetup *setup; // 浏览器设置
HTMLDocumentObj *doc; // 关联的 MSHTML 文档对象
NSContainer *parent; // 父容器
HWND hwnd; // Gecko 子窗口句柄
...
};
导航时序
IWebBrowser2::Navigate(url)
→ navigate_url() [navigate.c:941]
→ 触发 BeforeNavigate2 事件 [IDocObjectService::FireBeforeNavigate2]
→ OleCreate(CLSID_HTMLDocument) [创建 HTMLDocument]
→ HTMLDocument_Create() [htmldoc.c:4821]
→ create_nscontainer() [nsembed.c:2093]
→ load_gecko() [首次使用时触发]
→ init_nscontainer() [创建 nsIWebBrowser + nsIBaseWindow]
→ 创建 IHTMLDocument2 接口
→ nsIWebNavigation::LoadURI() [委托给 Gecko]
→ NavigateComplete2 事件 [IDocObjectService::FireNavigateComplete2]
→ 更新 travel log [update_travellog in dochost.c]
→ DocumentComplete 事件 [IDocObjectService::FireDocumentComplete]
XPCOM 接口定义
位置 :dll/win32/mshtml/nsiface.idl
这是一个特殊的 IDL 文件:
"This file is not a typical idl file. Interfaces in this file are XPCOM interfaces (NOT MSCOM!), but we generate the header file with WIDL compatible with XPCOM, usable in C code."
定义了约 100 个 XPCOM 接口的 C 语言绑定,涵盖:
- 核心接口:nsIWebBrowser, nsIBaseWindow, nsIWebNavigation
- 内容接口:nsIURIContentListener, nsIWebPageDescriptor
- 历史接口:nsIGlobalHistory, nsIHistoryEntry
- 安全接口:nsISecureBrowserUI, nsISSLStatus
- 打印接口:nsIWebBrowserPrint, nsIWebProgressListener
- 辅助接口:nsIIOService, nsIFileProtocolHandler, nsICategoryManager
2.4 wine_gecko --- Mozilla Gecko 引擎
位置 :modules/optional/wine_gecko/
文件清单:
wine_gecko/
├── xul.dll # Gecko 核心引擎 DLL (~30MB)
├── VERSION # 版本文件:"Wine Gecko 2.40"
├── omni.ja # 打包的 JS/XPCOM 组件(ZIP 格式)
├── platform.ini # 平台配置
├── dependentlibs.list # 依赖列表
├── LICENSE
├── freebl3.dll # NSS 加密库
├── mozglue.dll # Mozilla 胶水库
├── nss3.dll # NSS 安全层
├── nssckbi.dll # NSS CKBI 内置根证书
├── nssdbm3.dll # NSS DBM 数据库
├── softokn3.dll # NSS 软件令牌
├── libEGL.dll # EGL 图形接口
├── libGLESv2.dll # GLESv2 图形接口
├── plugin-container.exe # 插件进程容器
├── plugin-hang-ui.exe # 插件挂起 UI
├── dictionaries/
│ ├── en-US.aff # 拼写检查词形
│ └── en-US.dic # 拼写检查词典
└── gmp-clearkey/0.1/ # ClearKey DRM
├── clearkey.dll
└── clearkey.info
注册表配置 (boot/bootdata/hivedef.inf:1997-1999):
ini
; Gecko 下载 URL
HKCU,"SOFTWARE\Wine\MSHTML","GeckoUrl",,"http://source.winehq.org/winegecko.php"
; 安装 CAB 目录
HKCU,"SOFTWARE\Wine\MSHTML","GeckoCabDir",0x00020000,"%SystemRoot%\"
; Gecko 安装路径 (REG_EXPAND_SZ)
HKLM,"SOFTWARE\Wine\MSHTML\2.40","GeckoPath",0x00020000,"%SystemRoot%\wine_gecko"
三、关键接口映射
| Trident (MSCOM) | Gecko (XPCOM) | 功能 |
|---|---|---|
IHTMLDocument2 |
nsIWebBrowser + nsIDOMDocument |
HTML 文档对象 |
IWebBrowser2::Navigate |
nsIWebNavigation::LoadURI |
URL 导航 |
IHTMLElement |
nsIDOMHTMLElement |
DOM 元素操作 |
IHTMLWindow2 |
nsIDOMWindow |
窗口对象 |
IDocHostUIHandler |
nsIWebBrowserChrome |
宿主 UI 自定义 |
IOleInPlaceSite |
nsIEmbeddingSiteWindow |
内嵌站点窗口 |
四、宿主 UI 自定义链
应用程序 → ieframe.dll DocHostUIHandler
↓ (通过 hostui 链式转发)
外部宿主 (如应用程序自定义的 IDocHostUIHandler)
↓
mshtml.dll 内部处理
↓
NSContainer → nsIWebBrowserChrome
↓
xul.dll (Gecko 引擎)
关键方法(dochost.c:790-951):
| 方法 | 功能 |
|---|---|
ShowContextMenu |
右键菜单(可以禁止或自定义) |
GetHostInfo |
返回 DOCHOSTUIFLAG(如禁用脚本、禁用 ActiveX 等) |
GetOptionKeyPath |
IE 选项的注册表路径 |
GetExternal |
提供 window.external 的 IDispatch 接口 |
TranslateAccelerator |
键盘加速键处理 |
GetDropTarget |
OLE 拖放目标 |
FilterDataObject |
剪贴板数据过滤 |
五、wine_gecko 安装机制
5.1 首次安装时
系统安装向导(syssetup/wizard.c:2710)调用 appwiz.cpl,,install_gecko,弹出安装对话框。
5.2 安装流程
dll/cpl/appwiz/addons.c:
install_addon(ADDON_GECKO)
→ install_from_registered_dir() # 尝试从 GeckoCabDir 安装 MSI
→ 搜索 GeckoCabDir\wine_gecko-2.40-x86.msi
→ MsiInstallProductW()
→ [失败时] download_proc() # 弹出下载对话框
→ URLDownloadToFileW(url, temp_msi)
→ SHA1 校验
→ MsiInstallProductW(temp_msi)
5.3 MSI 安装结果
MSI 将 xul.dll 等文件解压到 %SystemRoot%\wine_gecko\,并在注册表中写入 GeckoPath。
5.4 系统自带的 wine_gecko
ReactOS 的 bootcd.iso 中已包含 wine_gecko(modules/optional/wine_gecko/),通过 txtsetup.sif 在系统安装时直接复制到 %SystemRoot%\wine_gecko\,无需下载。
六、构建系统集成
6.1 mshtml.dll 构建
cmake
# dll/win32/mshtml/CMakeLists.txt
add_idl_headers(mshtml_nsiface_header nsiface.idl) # 从 XPCOM IDL 生成头文件
...
add_library(mshtml MODULE nsembed.c ...) # nsembed.c 是 Gecko 集成核心
add_dependencies(mshtml mshtml_nsiface_header) # 依赖 XPCOM 头文件
6.2 wine_gecko 文件集成
cmake
# modules/CMakeLists.txt
# 使用 NO_CAB 确保文件直接放在 ISO 上,不打包进 CAB
add_cd_file(FILE .../wine_gecko/xul.dll
DESTINATION reactos/wine_gecko
NO_CAB
FOR bootcd livecd regtest)
6.3 安装时文件复制
txtsetup.sif 中定义了 5 个目录 ID(82, 88-91)和 27 个文件条目,确保安装程序将所有 wine_gecko 文件复制到 %SystemRoot%\wine_gecko\。
七、ReactOS 特有修复
详见 wine_gecko集成与修复总结.md,主要包括:
| # | 文件 | 修复 |
|---|---|---|
| 1 | nsembed.c |
支持 REG_EXPAND_SZ 展开 %SystemRoot% |
| 2 | hivedef.inf |
GeckoPath 使用 REG_EXPAND_SZ |
| 3 | msvcrt.spec |
去掉 -version=0x600+ 限制 |
| 4 | kernel32/time.c |
实现 GetSystemTimePreciseAsFileTime |
| 5 | modules/CMakeLists.txt |
wine_gecko 用 NO_CAB |
| 6 | txtsetup.sif |
添加目录 ID 和文件复制规则 |
八、调试指南
调试频道
| 频道名 | 启用方式 | 范围 |
|---|---|---|
ieframe |
WINE_DEFAULT_DEBUG_CHANNEL(ieframe) |
浏览器框架 |
gecko |
WINE_DECLARE_DEBUG_CHANNEL(gecko) |
Gecko 集成 (nsembed.c) |
常见错误日志
| 日志 | 含义 |
|---|---|
err: Could not open VERSION file |
VERSION 文件未找到 |
err: Could not load XUL: %d |
xul.dll 加载失败(依赖缺失) |
err: xul.dll failing with c0000139 |
缺少 CRT 导出函数 (DLL_NOT_FOUND) |
err: Could not load wine-gecko |
Gecko 加载链路中任一阶段失败 |
fixme: BrowserService_GetTravelLog |
ITravelLog 未实现(已修复) |
err: class {591209c7-...} not registered |
ApplicationAssociationRegistration 未注册(已修复) |
九、架构图示
┌─────────────────────────────────────────────────────────────────┐
│ iexplore.exe │
│ (base/applications/iexplore/main.c) │
└───────────────────────────┬─────────────────────────────────────┘
│ IEWinMain()
▼
┌─────────────────────────────────────────────────────────────────┐
│ ieframe.dll │
│ (dll/win32/ieframe/) │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌────────────────────┐ │
│ │ WebBrowser │ │ ShellBrowser │ │ DocHost │ │
│ │ (IWebBrowser2)│ │(IShellBrowser)│ │(IDocHostUIHandler2) │ │
│ └───────┬───────┘ └───────┬───────┘ └─────────┬──────────┘ │
│ │ │ │ │
│ └─────────────────┴─────────────────────┘ │
│ │ │
│ IWebBrowser2::Navigate() │
└───────────────────────────┬─────────────────────────────────────┘
│ OleCreate(CLSID_HTMLDocument)
▼
┌─────────────────────────────────────────────────────────────────┐
│ mshtml.dll │
│ (dll/win32/mshtml/) │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────────────┐ │
│ │ HTMLDocumentObj │ │ NSContainer │ │
│ │ (IHTMLDocument2/3) │ │ │ │
│ │ (IDispatch) │ │ nsIWebBrowser │ │
│ └──────────┬───────────┘ │ nsIWebNavigation │ │
│ │ │ nsIBaseWindow │ │
│ │ │ nsIWebBrowserChrome │ │
│ │ │ nsIWebBrowserFocus │ │
│ │ │ ... │ │
│ │ └──────────┬───────────────────────┘ │
│ │ │ │
│ └──────────────────────────┼─────────────────────────┘
│ │ │
│ load_gecko() ◄────────────┘ │
│ (加载 xul.dll + 初始化 XPCOM) │
└────────────────────────────────────────┬─────────────────────────┘
│ XPCOM 调用
▼
┌─────────────────────────────────────────────────────────────────┐
│ wine_gecko (xul.dll) │
│ (modules/optional/wine_gecko/) │
│ │
│ Mozilla Gecko 引擎 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Gecko │ │ Necko │ │ NSS │ │
│ │ (HTML/CSS)│ │ (网络层) │ │ (安全层) │ │
│ ├──────────┤ ├──────────┤ ├──────────┤ │
│ │ Spider- │ │ DOM │ │ Layout │ │
│ │ monkey │ │ │ │ Engine │ │
│ │ (JS引擎) │ │ │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
十、关键文件索引
| 文件路径 | 说明 |
|---|---|
base/applications/iexplore/main.c |
IE 可执行入口 |
dll/win32/ieframe/iexplore.c |
IEWinMain, InternetExplorer_Construct |
dll/win32/ieframe/webbrowser.c |
IWebBrowser2 实现 |
dll/win32/ieframe/dochost.c |
DocHost, IDocHostUIHandler2, travel log |
dll/win32/ieframe/shellbrowser.c |
ShellBrowser, IBrowserService, ITravelLog |
dll/win32/ieframe/navigate.c |
navigate_url 函数 |
dll/win32/ieframe/client.c |
IOleClientSite, IOleInPlaceSite |
dll/win32/ieframe/ieframe.h |
核心数据结构定义 |
dll/win32/mshtml/nsembed.c |
Gecko 加载、XPCOM 初始化、NSContainer |
dll/win32/mshtml/nsiface.idl |
~100 个 XPCOM 接口的 C 绑定 |
dll/win32/mshtml/htmldoc.c |
HTMLDocument COM 实现 |
dll/win32/mshtml/navigate.c |
MSHTML 导航逻辑 |
dll/win32/mshtml/mshtml_private.h |
NSContainer 等内部结构 |
dll/win32/mshtml/main.c |
DllMain, DLL_PROCESS_ATTACH 时调用 load_gecko |
modules/optional/wine_gecko/ |
wine_gecko 文件目录 |
modules/optional/wine_gecko-2.40-x86.msi |
wine_gecko MSI 安装包 |
modules/CMakeLists.txt |
wine_gecko 构建集成 |
boot/bootdata/hivedef.inf |
Gecko 注册表默认值 |
boot/bootdata/txtsetup.sif |
安装时文件复制规则 |
dll/cpl/appwiz/addons.c |
Gecko 安装/下载 UI |
dll/win32/syssetup/wizard.c |
系统安装时触发 Gecko 安装 |