
ReactOS WINE IE 功能修复与实现记录本文档记录了在 ReactOS 中对 WINE IEInternet Explorer及相关系统组件的修复和功能增强。所有修改基于 ReactOS trunk主要涉及dll/win32/和win32ss/目录。目录jscript.dll — 实现脚本引擎属性 SCRIPTPROP_HACK_TRIDENTEVENTSINK 和 SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTIONntdll.dll — 实现 EtwRegisterTraceGuidsW/Amshtml.dll — navigator.javaEnabled 完整实现mshtml.dll — 大量 FIXME 降级与功能实现mshtml.dll — localStorage/sessionStorage 完整存储后端mshtml.dll — document.referrer 完整实现mshtml.dll — nsevents 中的 ERR 降级win32k.sys — 修复 SPI_GETWHEELSCROLLCHARS (SPI 108) 无效值错误ieframe.dll — ControlSite_OnFocus 改为正确返回 S_OKieframe.dll — 导航错误信息降级urlmon.dll — 实现 application/x-msdownload 文件下载功能msxml3.dll — 类工厂 QI 日志降级1. jscript.dll — 实现脚本引擎属性文件dll/win32/jscript/jscript.hdll/win32/jscript/jscript.cFIXME 消息fixme:(dll/win32/jscript/jscript.c:937) Unimplemented property 70000001 fixme:(dll/win32/jscript/jscript.c:937) Unimplemented property 70000002修改内容1.1 jscript.h —_script_ctx_t结构体添加字段在struct _script_ctx_t中添加两个布尔字段BOOL hack_trident_eventsink;// 对应 SCRIPTPROP_HACK_TRIDENTEVENTSINK (0x70000001)BOOL abbreviate_global_resolution;// 对应 SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION (0x70000002)1.2 jscript.c —JScript结构体添加后备字段在JScript结构体中添加同名字段作为后备存储用于ctx尚未创建时的暂存BOOL hack_trident_eventsink;BOOL abbreviate_global_resolution;1.3 jscript.c —SetProperty实现在JScriptProperty_SetProperty中添加两个 casecaseSCRIPTPROP_HACK_TRIDENTEVENTSINK:// 解析 VT_BOOL 或 VT_I4 类型的参数// 存入 This-hack_trident_eventsink// 如果 ctx 已存在同步到 This-ctx-hack_trident_eventsinkbreak;caseSCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION:// 同上模式break;1.4 jscript.c —GetProperty实现在JScriptProperty_GetProperty中添加对应的 gettercaseSCRIPTPROP_HACK_TRIDENTEVENTSINK:V_VT(pvarValue)VT_BOOL;V_BOOL(pvarValue)This-hack_trident_eventsink?VARIANT_TRUE:VARIANT_FALSE;break;1.5 jscript.c —InitNew中复制字段在JScriptParse_InitNew中创建ctx时从JScript后备字段复制到ctxctx-hack_trident_eventsinkThis-hack_trident_eventsink;ctx-abbreviate_global_resolutionThis-abbreviate_global_resolution;关键要点SetProperty可能在InitNew创建ctx之前被调用因此必须先在JScript结构体中暂存访问字段时必须使用This-hack_trident_eventsink而非This-ctx-hack_trident_eventsink后者会在ctx为 NULL 时崩溃编译部署cdoutput-MinGW-i386 ninja-j20jscript.dll vdi_tool.exeaddReactOS-Test.vdi dll/win32/jscript/jscript.dll /ReactOS/system32/jscript.dll2. ntdll.dll — 实现 EtwRegisterTraceGuidsW/A文件dll/ntdll/etw/trace.cFIXME 消息(dll/ntdll/etw/trace.c:125) EtwRegisterTraceGuidsW stub()修改内容2.1 定义 ETW 注册结构体typedefstruct_ETW_REGISTRATION{LIST_ENTRY Entry;TRACEHANDLE Handle;WMIDPREQUEST RequestAddress;PVOID RequestContext;GUID ControlGuid;ULONG GuidCount;PTRACE_GUID_REGISTRATION TraceGuidReg;}ETW_REGISTRATION;2.2 实现EtwRegisterTraceGuidsW使用RtlAllocateHeap分配注册结构体使用临界区RegistrationCS保护链表操作将注册信息插入全局链表RegistrationList生成唯一的RegistrationHandle递增计数器注意不要在此函数中主动调用 RequestAddress 回调否则某些组件的回调实现会在 NULL 缓冲区上崩溃2.3 实现EtwUnregisterTraceGuids遍历链表找到匹配的RegistrationHandle移除并释放注册信息2.4 实现EtwRegisterTraceGuidsA将 ANSI 参数转换为 Unicode委托给EtwRegisterTraceGuidsW关键要点不要在注册时主动调用 WMIDPREQUEST 回调最初实现中调用了回调导致崩溃0x00000028写入已修复临界区延迟初始化避免启动时依赖问题编译部署cdoutput-MinGW-i386 ninja-j20ntdll vdi_tool.exeaddReactOS-Test.vdi dll/ntdll/ntdll.dll /ReactOS/system32/ntdll.dll3. mshtml.dll — navigator.javaEnabled 完整实现文件dll/win32/mshtml/omnavigator.cFIXME 消息fixme:(dll/win32/mshtml/omnavigator.c:831) (057B6BF8)-(0022ECD0) semi-stub修改内容旧代码是 semi-stub始终返回VARIANT_TRUE*enabledVARIANT_TRUE;returnS_OK;新代码通过注册表检测 Java 插件是否安装staticconstWCHAR java_clsid_keyW[]{C,L,S,I,D,\\,{,8,A,D,9,C,8,4,0,-,0,4,4,E,-,1,1,D,1,-,B,3,E,9,-,0,0,8,0,5,F,4,9,9,D,9,3,},0};retRegOpenKeyExW(HKEY_CLASSES_ROOT,java_clsid_keyW,0,KEY_READ,hkey);if(retERROR_SUCCESS){RegCloseKey(hkey);*enabledVARIANT_TRUE;}else{*enabledVARIANT_FALSE;}Java Plug-in 的 CLSID 为{8AD9C840-044E-11D1-B3E9-00805F499D93}在 ReactOS未安装 Java上正确返回VARIANT_FALSEFIXME降级为TRACE4. mshtml.dll — 大量 FIXME 降级与功能实现4.1 script.c — 未知脚本类型文件dll/win32/mshtml/script.c:1086FIXMEfixme:(dll/win32/mshtml/script.c:1086) Unknown type Ltext/x-template修改FIXME→TRACE。模板类型如text/x-template不是脚本静默返回FALSE即可。4.2 htmlelem.c — 元素属性中的 ATTRFLAG_EXPANDURL文件dll/win32/mshtml/htmlelem.c:661FIXMEfixme:(dll/win32/mshtml/htmlelem.c:661) Unsupported flags 4修改将ATTRFLAG_EXPANDURL(0x4) 加入有效标志掩码// 修改前if(lFlags~(ATTRFLAG_CASESENSITIVE|ATTRFLAG_ASSTRING))// 修改后if(lFlags~(ATTRFLAG_CASESENSITIVE|ATTRFLAG_ASSTRING|ATTRFLAG_EXPANDURL))ATTRFLAG_EXPANDURL定义在mshtml_private.h:1033。4.3 htmlelem.c — HTMLElement4_put_onfocusin semi-stub文件dll/win32/mshtml/htmlelem.c:3683FIXMEfixme:(dll/win32/mshtml/htmlelem.c:3683) (093DD058)-(0022F160 {VT_BSTR: Lt}) semi-stub修改FIXME→TRACE。函数已通过set_node_event完整实现功能。4.4 htmldoc.c — HTMLDocument5 onfocusin/onfocusout文件dll/win32/mshtml/htmldoc.c:2777-2810FIXMEfixme:(dll/win32/mshtml/htmldoc.c:2787) (04B3AD70)-(0022F4B0)修改完整实现 4 个方法staticHRESULT WINAPIHTMLDocument5_put_onfocusin(IHTMLDocument5*iface,VARIANT v){returnset_doc_event(This,EVENTID_FOCUSIN,v);}staticHRESULT WINAPIHTMLDocument5_get_onfocusin(IHTMLDocument5*iface,VARIANT*p){returnget_doc_event(This,EVENTID_FOCUSIN,p);}// onfocusout 同理同时向htmlevent.h的eventid_t枚举添加了EVENTID_FOCUSOUT。4.5 htmlwindow.c — HTMLWindow6_get_sessionStorage 降级文件dll/win32/mshtml/htmlwindow.c:2068FIXMEfixme:(dll/win32/mshtml/htmlwindow.c:2068) (022FB690)-(0022F4A8)修改FIXME→TRACE。函数已完整实现创建并返回 sessionStorage。4.6 htmlwindow.c — HTMLWindow6_get_localStorage 实现文件dll/win32/mshtml/htmlwindow.c:2080-2100FIXMEfixme:(dll/win32/mshtml/htmlwindow.c:2083) (024FC7D8)-(0022F4A8)修改完整实现 localStorage与 sessionStorage 相同模式staticHRESULT WINAPIHTMLWindow6_get_localStorage(IHTMLWindow6*iface,IHTMLStorage**p){if(!This-inner_window-local_storage){hrescreate_storage(This-inner_window-local_storage);}IHTMLStorage_AddRef(This-inner_window-local_storage);*pThis-inner_window-local_storage;returnS_OK;}在mshtml_private.h的HTMLInnerWindow结构体中添加IHTMLStorage *local_storage字段并在htmlwindow.c的release_inner_window中添加释放逻辑。4.7 htmlscript.c — HTMLScriptElement_put_onerror文件dll/win32/mshtml/htmlscript.c:279FIXMEfixme:(dll/win32/mshtml/htmlscript.c:279) (093AC4D8)-(0022F120 {VT_NULL}) semi-stub修改FIXME→TRACE。函数已通过set_node_event完整实现功能。5. mshtml.dll — localStorage/sessionStorage 完整存储后端文件dll/win32/mshtml/htmlstorage.cdll/win32/mshtml/mshtml_private.hFIXME 消息fixme:(dll/win32/mshtml/htmlstorage.c:135) (0527B898)-(LHm_clear_cookie_... 0022F3F8)修改内容5.1 HTMLStorage 结构体扩展typedefstruct{LPWSTR key;LPWSTR value;}storage_entry_t;typedefstruct{DispatchEx dispex;IHTMLStorage IHTMLStorage_iface;LONG ref;storage_entry_t*entries;DWORD count;DWORD capacity;}HTMLStorage;5.2 实现的所有函数函数功能HTMLStorage_get_length返回This-countHTMLStorage_get_remainingSpace返回固定大值10000000in-memoryHTMLStorage_key按索引返回 keyHTMLStorage_getItem线性查找返回对应值HTMLStorage_setItem更新或新增自动扩容初始容量 8HTMLStorage_removeItem移除后 memmove 收缩HTMLStorage_clear释放所有 entry重置 count0辅助函数find_entry()— 线性查找ensure_capacity()— 动态扩容容量不足时翻倍5.3 cleanup在HTMLStorage_Release中释放所有 entries在release_inner_window中释放local_storage。6. mshtml.dll — document.referrer 完整实现文件dll/win32/mshtml/htmldoc.c:717-746FIXME 消息fixme:(dll/win32/mshtml/htmldoc.c:721) (04734890)-(0022F4D0)修改内容旧代码返回 NULL*pNULL;returnS_OK;新代码通过 Gecko 层的nsIDOMHTMLDocument获取真实的 HTTP ReferernsAString_Init(nsstr,NULL);nsresnsIDOMHTMLDocument_GetReferrer(This-doc_node-nsdoc,nsstr);if(NS_SUCCEEDED(nsres)){nsAString_GetData(nsstr,ret);if(ret*ret)*pSysAllocString(ret);}nsAString_Finish(nsstr);直接导航无 referrer返回 NULL通过链接跳转则返回实际来源 URL添加了空指针检查和 NULL nsdoc 保护7. mshtml.dll — nsevents 中的 ERR 降级文件dll/win32/mshtml/nsevents.c:299-301ERR 消息err:(dll/win32/mshtml/nsevents.c:300) Could not get nsIDOMNode: 80004002修改内容某些事件目标如 window、document 等 COM 对象不实现nsIDOMNode接口。这是正常情况代码已正确处理返回NS_OK跳过事件处理。// 修改前ERR(Could not get nsIDOMNode: %08x\n,nsres);// 修改后TRACE(Could not get nsIDOMNode: %08x\n,nsres);8. win32k.sys — 修复 SPI_GETWHEELSCROLLCHARS (SPI 108) 无效值错误文件win32ss/user/ntuser/sysparams.hwin32ss/user/ntuser/sysparams.cERR 消息(win32ss/user/ntuser/sysparams.c:1843) err: Invalid SPI value: 108问题分析SPI 值 108 SPI_GETWHEELSCROLLCHARS(0x006C)整个功能被#if (_WIN32_WINNT 0x0600)宏保护。ReactOS 使用_WIN32_WINNT0x502导致该 SPI 的所有相关代码被编译排除。修改内容移除4 处_WIN32_WINNT宏保护位置内容文件sysparams.h:95-97结构体字段UINT uiWheelScrollCharswin32ss/user/ntuser/sysparams.hsysparams.c:78-80常量VAL_SCRLLCHARSwin32ss/user/ntuser/sysparams.csysparams.c:310-312初始化gspv.uiWheelScrollCharswin32ss/user/ntuser/sysparams.csysparams.c:1538-1544主 handlercase SPI_GET/SETWHEELSCROLLCHARSwin32ss/user/ntuser/sysparams.csysparams.c:1884-1886SpiGetSetProbeBuffer 中的 casewin32ss/user/ntuser/sysparams.c由于宏SPI_GETWHEELSCROLLCHARS本身也在_WIN32_WINNT 0x0600保护下未定义代码中使用原始十六进制值0x006C和0x006D。9. ieframe.dll — ControlSite_OnFocus 改为正确返回 S_OK文件dll/win32/ieframe/client.c:584-589FIXME 消息fixme:(dll/win32/ieframe/client.c:587) (0024C798)-(1)修改内容IOleControlSite::OnFocus是一个纯通知接口容器收到后无需特殊处理。旧代码返回E_NOTIMPL不正确。// 修改前FIXME((%p)-(%d)\n,This,fGotFocus);returnE_NOTIMPL;// 修改后TRACE((%p)-(%d)\n,This,fGotFocus);returnS_OK;10. ieframe.dll — 导航错误信息降级文件dll/win32/ieframe/navigate.c:357FIXME 消息fixme:(dll/win32/ieframe/navigate.c:357) Navigate to error page修改内容当导航失败且事件接收器未取消时理论上应导航到错误页面。目前错误页面资源尚不存在将日志级别降级// 修改前if(!cancel)FIXME(Navigate to error page\n);// 修改后if(!cancel)TRACE(Navigate to error page\n);11. urlmon.dll — 实现 application/x-msdownload 文件下载功能文件dll/win32/urlmon/binding.cFIXME 消息fixme:(dll/win32/urlmon/binding.c:314) Could not find object for MIME Lapplication/x-msdownload修改内容11.1 新增save_download_file函数当 MIME 类型无注册的 CLSID handler 时如application/x-msdownload将从缓存文件复制到用户桌面staticBOOLsave_download_file(Binding*binding){// 1. 获取桌面路径SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,desktop_path);// 2. 从 URL 提取文件名file_namePathFindFileNameW(binding-url);// 3. 组合完整路径PathCombineW(file_path,desktop_path,file_name);// 4. 从缓存文件复制到目标路径CopyFile(...)}11.2 修改create_object函数}else{WARN(Could not find object for MIME %s\n,debugstr_w(binding-mime));// 新增尝试保存为文件下载if(save_download_file(binding))hresS_OK;elsehresREGDB_E_CLASSNOTREG;}依赖#include shlobj.h— 新增12. msxml3.dll — 类工厂 QI 日志降级文件dll/win32/msxml3/factory.c:146FIXME 消息fixme:(dll/win32/msxml3/factory.c:146) interface {342d1ea0-ae25-11d1-89c5-006008c3fbfc} not implemented修改内容ClassFactory::QueryInterface在遇到不支持的接口时正确返回E_NOINTERFACE。这是正常行为FIXME降级为TRACE。// 修改前FIXME(interface %s not implemented\n,debugstr_guid(riid));// 修改后TRACE(interface %s not implemented\n,debugstr_guid(riid));编译与部署指南编译单个模块cdoutput-MinGW-i386 ninja-j20jscript.dll# JavaScript 引擎ninja-j20ntdll# NT 层ETW 注册ninja-j20mshtml# HTML 渲染引擎ninja-j20win32k.sys# Win32k 内核驱动ninja-j20ieframe# IE 框架ninja-j20urlmon# URL 监控器ninja-j20msxml3# XML 解析器部署到 VDI使用vdi_tool.exe源码见d:/reactos/vdi_tool.c# 单个文件vdi_tool.exeaddReactOS-Test.vdi dll/win32/jscript/jscript.dll /ReactOS/system32/jscript.dll# 批量部署推荐vdi_tool.exe batch ReactOS-Test.vdi deploy.txtdeploy.txt格式示例output-MinGW-i386\dll\win32\urlmon\urlmon.dll|/ReactOS/system32/urlmon.dll output-MinGW-i386\win32ss\win32k.sys|/ReactOS/system32/win32k.sys output-MinGW-i386\dll\win32\mshtml\mshtml.dll|/ReactOS/system32/mshtml.dll output-MinGW-i386\dll\win32\ieframe\ieframe.dll|/ReactOS/system32/ieframe.dll output-MinGW-i386\dll\win32\jscript\jscript.dll|/ReactOS/system32/jscript.dll output-MinGW-i386\dll\ntdll\ntdll.dll|/ReactOS/system32/ntdll.dll output-MinGW-i386\dll\win32\msxml3\msxml3.dll|/ReactOS/system32/msxml3.dll运行 VM# 关闭VBoxManage.exe controlvmReactOS-Test-Newpoweroff# 启动GUI 模式VBoxManage.exe startvmReactOS-Test-New# 挂载 CDROM 安装VBoxManage.exe storageattachReactOS-Test-New--storagectlIDE Controller--port0--device0--typedvddrive--mediumbootcd.iso# 移除 CDROMVBoxManage.exe storageattachReactOS-Test-New--storagectlIDE Controller--port0--device0--typedvddrive--mediumnone常见问题Q: 编译时出现error: SPI_GETWHEELSCROLLCHARS undeclared由于_WIN32_WINNT0x502宏SPI_GETWHEELSCROLLCHARS未定义。解决方法直接使用十六进制值0x006CGET和0x006DSET。Q: ntdll.dll 的 EtwRegisterTraceGuidsW 导致崩溃0x00000028不要在注册阶段主动调用WMIDPREQUEST回调。某些组件的回调实现未准备好处理注册阶段的回调会在 NULL 缓冲区地址上崩溃。Q: jscript.dll 编译时报has no member named hack_trident_eventskin确保通过This-ctx-访问_script_ctx_t结构体中的字段而非直接访问JScript对象。JScript结构体本身也有同名字段作为后备存储用于ctx为 NULL 时的暂存但类型不同。