mshtml/nsio.c 实现报告

mshtml/nsio.c 实现报告

概述

dll/win32/mshtml/nsio.c 进行了全面的 XPCOM 接口实现,将原本大量 NS_ERROR_NOT_IMPLEMENTED 的 stub 函数实现为可正常工作的代码。同时修复了一个关键的 vtable 错位 bug,并扩展了 nsChannel 结构体以支持新实现的字段。

涉及修改的文件:

  • dll/win32/mshtml/nsio.c --- 主要实现
  • dll/win32/mshtml/binding.h --- nsChannel 结构体字段扩展
  • dll/win32/mshtml/nsiface.idl --- 接口定义修复

一、关键 Bug 修复:vtable 偏移

问题

Gecko 2.40(wine_gecko)的 nsIHttpChannelInternal IDL 相比 ReactOS 版本多了两个方法:

idl 复制代码
// Gecko 40 有,但 ReactOS 缺失
attribute unsigned long thirdPartyFlags;  // 产生 Get + Set 两个 vtable 槽位

这导致 ReactOS 的虚函数表从第 10 项起整体偏移了 2 个位置 。当 Gecko 调用 GetNetworkInterfaceId(vtable 索引 38)时,实际调用的是 ReactOS 的 SetCorsMode,传入的参数被错误地解析为 nsACString*,导致写入无效内存地址 0x00000002,引发 xul.dll 崩溃。

修复

nsiface.idl 中添加缺失的两个方法:

idl 复制代码
nsresult GetThirdPartyFlags(uint32_t *aThirdPartyFlags);
nsresult SetThirdPartyFlags(uint32_t aThirdPartyFlags);

同时在 nsio.c 中实现这两个函数,并在 vtable 中插入对应的条目。修复后 vtable 与 Gecko 40 完全对齐,GetNetworkInterfaceId/SetNetworkInterfaceId 正常工作。


二、已实现的函数清单

nsChannel(nsIHttpChannel 接口)

函数 实现方式
GetContentLength 返回 This->content_length
SetContentLength 存储到 This->content_length
IsPending 返回 This->pending 字段
Cancel 设置 This->canceled = TRUE
Suspend no-op,返回 NS_OK
Resume no-op,返回 NS_OK
GetSecurityInfo 返回 NULL
GetContentDisposition 返回 This->content_disposition
SetContentDisposition 存储到 This->content_disposition
GetContentDispositionFilename 返回 This->content_disposition_filename(WCHAR* → nsAString)
SetContentDispositionFilename 存储 WCHAR*(释放旧值,heap_strdupW 新值)
VisitRequestHeaders 调用 visit_http_headers(&This->request_headers, ...)
GetAllowPipelining 返回 This->allow_pipelining
SetAllowPipelining 存储到 This->allow_pipelining
GetAllowTLS 返回 This->allow_tls
SetAllowTLS 存储到 This->allow_tls
GetRedirectionLimit 返回 This->redirection_limit
SetRedirectionLimit 存储到 This->redirection_limit
SetResponseHeader 调用 set_channel_http_header(&This->response_headers, ...)
IsNoStoreResponse 检查 Cache-Control: no-store(已有实现)
IsNoCacheResponse 检查 Cache-Control: no-cache
IsPrivateResponse 检查 Cache-Control: private
RedirectTo 引用计数存储 nsIURI*This->redirect_to_uri
GetReferrerPolicy 返回 This->referrer_policy
SetReferrerWithPolicy 存储 referrer URI + policy

nsIHttpChannelInternal 接口

函数 实现方式
GetDocumentURI 引用计数返回 This->document_uri
SetDocumentURI 引用计数存储 This->document_uri
GetRequestVersion 返回 1/1(HTTP/1.1)
GetResponseVersion 返回 1/1(HTTP/1.1)
TakeAllSecurityMessages no-op(无安全消息)
SetCookie no-op(cookie 由 wininet 处理)
SetupFallbackChannel no-op
GetThirdPartyFlags 返回 This->third_party_flags
SetThirdPartyFlags 存储到 This->third_party_flags
GetForceAllowThirdPartyCookie 返回 This->force_third_party_cookie
SetForceAllowThirdPartyCookie 存储到 This->force_third_party_cookie
GetCanceled 返回 This->canceled
GetChannelIsForDownload 返回 This->channel_is_for_download
SetChannelIsForDownload 存储到 This->channel_is_for_download
GetLocalAddress 返回 "0.0.0.0"
GetLocalPort 返回 0
GetRemoteAddress 返回 "0.0.0.0"
GetRemotePort 返回 0
SetCacheKeysRedirectChain no-op
GetAllowSpdy 返回 This->allow_spdy
SetAllowSpdy 存储到 This->allow_spdy
GetResponseTimeoutEnabled 返回 This->response_timeout_enabled
SetResponseTimeoutEnabled 存储到 This->response_timeout_enabled
GetApiRedirectToURI 引用计数返回 This->redirect_to_uri
GetAllowAltSvc 返回 This->allow_alt_svc
SetAllowAltSvc 存储到 This->allow_alt_svc
AddRedirect no-op
GetLastModifiedTime 返回 This->last_modified_time
ForceNoIntercept no-op
GetCorsIncludeCredentials 返回 This->cors_include_credentials
SetCorsIncludeCredentials 存储到 This->cors_include_credentials
GetCorsMode 返回 This->cors_mode
SetCorsMode 存储到 This->cors_mode
GetTopWindowURI 返回 NULL
GetNetworkInterfaceId 返回 This->network_interface_id
SetNetworkInterfaceId 存储到 This->network_interface_id
ContinueBeginConnect no-op
GetProxyURI 返回 NULL

保持 NOT_IMPLEMENTED 的函数

函数 原因
nsChannel_Open 同步打开涉及 urlmon 绑定,实现复杂
nsChannel_GetContentDispositionHeader 需要从 filename/type 构造 Content-Disposition 头
HTTPUpgrade 需要完整的 HTTP Upgrade 协议支持

三、结构体字段变更

binding.h --- nsChannel 结构体

新增字段(全部在 /* FIXME function implementation fields */ 区域):

c 复制代码
INT64 content_length;                   // Get/SetContentLength
cpp_bool pending;                       // IsPending
UINT32 content_disposition;             // Get/SetContentDisposition
WCHAR *content_disposition_filename;    // Get/SetContentDispositionFilename
UINT32 referrer_policy;                 // GetReferrerPolicy
cpp_bool allow_pipelining;              // Get/SetAllowPipelining
cpp_bool allow_tls;                     // Get/SetAllowTLS
UINT32 redirection_limit;               // Get/SetRedirectionLimit
cpp_bool canceled;                      // GetCanceled
cpp_bool channel_is_for_download;       // Get/SetChannelIsForDownload
cpp_bool allow_spdy;                    // Get/SetAllowSpdy
cpp_bool response_timeout_enabled;      // Get/SetResponseTimeoutEnabled
cpp_bool allow_alt_svc;                 // Get/SetAllowAltSvc
cpp_bool cors_include_credentials;      // Get/SetCorsIncludeCredentials
UINT32 cors_mode;                       // Get/SetCorsMode
UINT32 third_party_flags;               // Get/SetThirdPartyFlags
cpp_bool force_third_party_cookie;      // Get/SetForceAllowThirdPartyCookie
nsIURI *document_uri;                   // Get/SetDocumentURI
nsIURI *redirect_to_uri;                // RedirectTo / GetApiRedirectToURI
PRTime last_modified_time;              // GetLastModifiedTime
char *network_interface_id;             // Get/SetNetworkInterfaceId

nsiface.idl --- nsIHttpChannelInternal 接口

新增方法(修复 vtable 对齐):

idl 复制代码
nsresult GetThirdPartyFlags(uint32_t *aThirdPartyFlags);
nsresult SetThirdPartyFlags(uint32_t aThirdPartyFlags);

四、内存管理

nsChannel_Release(引用计数归零时清理)中添加了 heap_free 调用:

c 复制代码
heap_free(This->content_disposition_filename);
heap_free(This->network_interface_id);

确保堆分配的字符串在通道销毁时被正确释放,避免内存泄漏。


五、经验教训

  1. vtable 对齐至关重要 --- ReactOS 与 Gecko 之间的 XPCOM 接口必须完全匹配,即使少一个方法也会导致整个 vtable 偏移,引发难以调试的崩溃。

  2. 无效指针 0x00000002 --- 这个看似可疑的值实际上是 vtable 偏移的证据。当 vtable 错位时,Gecko 调用方法 A 的参数被错误地传递给方法 B,导致参数类型不匹配。

  3. NOT_IMPLEMENTED 有时更安全 --- 对于某些函数(尤其是 nsIHttpChannelInternal 中的内部 API),返回 NS_ERROR_NOT_IMPLEMENTED 可能比返回带有默认值的 NS_OK 更安全,因为前者会阻止 Gecko 进入不完整的代码路径。


六、编译验证

所有修改已通过 ninja mshtml 编译,零错误零警告。

ReactOS 运行测试通过,未出现 xul.dll 崩溃(之前因 vtable 偏移导致的崩溃已消除)。

相关推荐
weixin_467182281 小时前
Arduino进阶二|自定义类库保姆级教程(从零手写属于自己的传感器类库+完整源码)
c语言·c++·单片机·嵌入式硬件·arduino·c++面向对象·diy库文件
龙侠九重天1 小时前
C# 构建 AI Agent 系统 — 我的实践笔记
开发语言·人工智能·语言模型·自然语言处理·大模型·agent·智能体
SilentSamsara1 小时前
Pandas 工程化:多层索引、分组聚合与窗口函数的进阶用法
开发语言·python·青少年编程·pandas
何以解忧,唯有..1 小时前
Python 字符串完全指南:从基础到高级操作
开发语言·python
kiss strong1 小时前
自制请求工具
开发语言·python·lua
scan7241 小时前
短期记忆记忆存储在内存里,一个会话里的多轮对话
开发语言·c#
玖玥拾1 小时前
C/C++ 基础笔记(八)
c语言·c++
程序员皮皮林2 小时前
Dubbo 的 SPI 和 JDK 的 SPI 有什么区别?
java·开发语言·dubbo
是多巴胺不是尼古丁2 小时前
java‘期末复习--多态
java·开发语言