这可能是一个圣诞节故事,结局很幸福,但事实并非如此。
在2018年圣诞节前夕,我在ReactOS的经过测试的应用程序列表中注意到一个.NET 4.0安装程序,并对安装成功并启动应用程序感到惊讶。 但是由于4.0的使用时间已经很短了,所以我被一个疯狂的主意所吸引-如果我尝试安装4.5版会怎样?
安装程序立即声明操作系统版本不合适。 他还决定以兼容模式启动并拒绝安装。 事情在开始之前就结束了...

是的,现在我将更改版本,它将可以使用!
ReactOS正在开发为Windows 2003的类似产品,它报告的版本为5.2。 安装至少需要6.0,但后来我决定最好立即瞄准Windows 7,并开始寻找如何将版本更改为6.1。 在代码中,根据版本/ MajorVersion / MinorVersion,整个系统中有多个位置,即使您没有想到。 将所有5.2对替换为6.1,结果为零-即使OS安装程序也没有启动。 引导时对freeldr和ntldr进行了进一步的搜索-在4个地方,有必要将_WIN32_WINNT_WS03替换为_WIN32_WINNT_WIN7。 操作系统已安装,并告诉我们这是6.1。 好吗? 不行 由于某种原因,实际上没有安装任何替代产品-VirtualBox Guest Additions,Firefox,.NET 4.0甚至Explorer都无法使用。 好的,因此您需要使用所需的所有内容创建一个ISO并将其连接到虚拟机。 荣耀到字节,驱动器仍在工作,安装程序再次从其启动。 万岁! 它甚至开始,但抱怨缺少某些OS组件:

第一个是自动更新服务,第二个是受信任的安装程序。 我们没有这样的东西-真的,为什么在ReactOS中有Windows更新,而Trusted Installer却无法定义,因为它与Windows 7一同出现。在日志中也有一行缺少wusa.exe。 好的,为
PR 355更新服务创建wusa.exe和wuauserv.dll的存根。 Trusted Installer刚刚从Windows 7和注册表项中复制了32位。 现在,安装程序确定了所有必要的可用性,并且仅保留一滴血即可固定合同。
文件验证过程成功,安装开始。 立即我们收到一条消息,指出kernel32模块中的LCMapStringEx函数丢失。

好的,我正在代码中寻找一个函数,您会感到惊讶,它存在,但是由于某种原因未添加到导出列表中(每个DLL根目录中CMakeLists.txt旁边的规范文件)。 生成/安装/运行,再次出现类似错误。 好吧,脚本是已知的。 在安装程序单击重复5-10次此过程后,会向安装程序询问该操作系统具有无人参与的安装模式。 为此,请在文件boot \ bootdata \ bootcd \ unattend.inf中启用UnattendSetupEnabled = yes。 超级雪橇骑! 它们的运行速度如此之快,以至于您没有时间去喝茶-整个安装过程只有两分钟。
unattend.inf中的设置在那里,您可以将安装文件夹从ReactOS更改为Windows或Bolgenos(或者可能是GreenteaOS?:)),图形模式的分辨率,启用主题的安装以及其他几点
由于ReactOS是2003年编写的,因此没有人特别支持6.0+的代码。 #if _WIN32_WINNT> = 0x600甚至#if 0会覆盖这些位置,因此必须将其投入运行。 添加缺少的函数(尽管其代码为@ $&^%!)进行导出(SleepConditionVariableCS需要RtlSleepConditionVariableCS)或在SDK标头中的某个位置解锁结构/字段。 一个带有ntdll,kernel32和advapi32的陌生拐杖-出于某种原因,它们以ntdll_vista,kernel32_vista和advapi32_vista的形式创建了附件,每个附件最多具有10-15个过程,而kernel32具有两个完整的vista.c文件。 天鹅,癌症和梭子鱼做出了这样的决定。 现在还没有确定性-在github上放置PR时,一个要求将代码传输到* _vista lib,第二个要求在spec文件中以-version = 0x600 +条件关闭导出就足够了。 这里最令人惊讶的是,所有这些功能都是新的API,并且可以与主要代码和平共处,尚不清楚为什么要围成这样的花园。
这些尝试持续了几个月,但最终一切都取决于安装程序会在安装过程中挂起,既不会诅咒也不会摔倒。
成为,似乎
在夏天,我决定返回炮弹。 尽管如此,仍然花费了很多时间,结果为零。 这次,我决定采取不同的方法-因为将报告的版本从5.2更改为6.1时,所有操作都是随机的,所以您需要从完全不同的方向更改版本-尝试完全在NT6模式下构建ReactOS。
为此,在根CMakeLists.txt中,将以下条件0x502替换为0x600。 是的,没有时间要发胖,至少要有6.0才能获得输出。
尽管这个想法总体上是正确的,但最初对这项事业取得成功的期望是这样。
问题的实质在于,在NT6内核中,许多函数更改了签名,数据结构在字段的组成和顺序方面有所不同。
#if (_WIN32_WINNT >= 0x600) NTSTATUS RxConstructSrvCall( _In_ PRX_CONTEXT RxContext, _In_ PIRP Irp, _In_ PSRV_CALL SrvCall, _Out_ PLOCK_HOLDING_STATE LockHoldingState); #else NTSTATUS RxConstructSrvCall( _In_ PRX_CONTEXT RxContext, _In_ PSRV_CALL SrvCall, _Out_ PLOCK_HOLDING_STATE LockHoldingState); #endif
编译错误像聚宝盆一样下雨,其中最简单的错误是在某些dll的CMake文件中,将WINVER和_WIN32_WINNT明确分配给其他值,例如0x602。 同时,ReactOS充满了dll,其中WINVER现在从0x502重新定义为0x600。 有一些真正的bug
#356 #359 #747 #814 #815 。
它持续了同一个月或两个月,结果,所有拐杖都聚集了图像,但安装程序根本没有显示任何生命迹象。 折磨了一点保险丝
逻辑不是铁
新的圣诞节快到了,.NET 4.5困扰不已。 再次,我返回第一个选项,重复所有编辑,但有一些更改。 如果以前,我只是做桩,而不是缺少功能(操作系统中没有代码),现在我决定在Wine代码中查找它们,瞧,它们在那里。 转移,以适应ReactOS,到下一个
#1045 。 在某个地方,您可以编写实际代码,而不是存根:)
#1046 。 安装程序在进行此类编辑时会更加有力地工作,甚至“成功”结束,但是与安装程序不同,.NET 4.0在安装后不提供重新启动的功能-我注销说,新一代操作系统使用所有相同的软件,因此无需每次都重新启动(哈哈,天真)。 当我尝试启动helloWorld应用程序时,屏幕上什么都没有发生;在任务管理器中,我也没有时间注意到任何活动。
安装程序的一个小问题为了避免每次都等待安装程序启动,我将其解压缩到一个文件夹中,然后手动单击setup.exe。 您需要运行/ x86参数,为其创建了快捷方式
不久之后,我决定深入研究安装程序的资源,在其中找到错误消息和此处的文字-所有限制均在ParameterInfo.xml文件中指示! 对StopBlockers条件IsInOSCompatibilityMode进行评论就足够了,一切开始都没有问题。 我删除了将OS版本从5.2更改为6.0的编辑,在设置的快捷方式中打开Vista兼容模式(因此它不希望使用Trusted Installer),并添加了一些其他功能,使安装程序“成功”结束。 但是,如果先安装4.0,然后运行安装程序4.5,则该过程已经完成,并要求重新启动! 胜利! 不行 我说这是一个没有圆满结局的故事。 尝试启动HelloWorld时,结果略有不同,但差别不大-该过程占用11-12MB的内存,并且在挂起20秒后结束。 在兼容模式下启动无济于事(毕竟,CLR运行时是在每个进程中单独启动的,而不是在以OS 5.2版作为操作系统的系统范围内启动的环境)。
在日志中,我们看到确定版本的调用:

向RtlVerifyVersionInfo添加了一个hack,如果请求版本6。*,则将操作系统版本替换为6.0。 箭头标记的线消失了,但是结果是一样的。
没有一个幸福的结局。
结论
也许成功的余地很小,而您受此故事启发,准备下载并编译ReactOS代码来完成并完成您的入门工作了吗? 没那么快。 在几乎所有PR中,都首先讨论了布局时所做的更改,但是这些更改在没有引起主要OS开发人员注意的情况下挂起。
为了重复上述操作,有必要使用文本中的链接在master分支上滚动PR,解锁spec文件中的功能包(将版本替换为-version条件,使用0x500 +),并在标头中使用多个0x600条件
NET 4.5的变更日志除了PRov,您还需要修复一点winbase.h wincon.h并从下面的列表中打开功能
advapi32- EventWrite(存根)
- EventRegister(存根)
- EventUnregister(存根)
- RegLoadMUIStringA
- RegLoadMUIStringW
msvcrt内核32- 获取SRWLockExclusive
- 获取SRWLockShared
- 关闭线程池
- CloseThreadpoolCleanupGroup
- CloseThreadpoolCleanupGroupMembers
- 关闭线程池
- 关闭线程池计时器
- 关闭线程池等待
- 关闭线程池工作
- SetThreadpoolTimer
- SetThreadpoolWait
- CompareStringEx
- CreateSemaphoreExA(存根)
- CreateSemaphoreExW(存根)
- 创建线程池
- CreateThreadpoolCleanupGroup
- CreateThreadpoolIo
- CreateThreadpoolTimer
- CreateThreadpoolWait
- CreateThreadpoolWork
- EnumCalendarInfoExEx
- EnumDateFormatsExEx
- EnumSystemLocalesEx
- EnumTimeFormatsExEx
- FlushProcessWriteBuffers(存根)
- GetCalendarInfoEx
- GetDateFormatEx
- GetLocaleInfoEx
- IsValidLocaleName(存根)
- GetNLSVersionEx(存根)
- GetNumberFormatEx
- GetTickCount64
- GetTimeFormatEx
- GetUserDefaultLocaleName
- LCMapStringEx
- InitOnceExecuteOnce
- InitializeCriticalSectionEx
- 初始化SRWLock
- 释放SRWLockExclusive
- 释放SRWLockShared
- WerSetFlags(存根)
没有时间去组装,快来这里进行建造!
如果您跟随ReactOS的开发并尝试安装新的应用程序,那么您可能会遇到以下事实:某些功能丢失或有趣/有用的PR不断挂起。 我对此也很熟悉,因此决定定期用缺失的零件和PR编译OS程序集(我想每周或每两周保持一次计划)。 试试这个程序集,也许会有用! 如果遇到另一个缺少的功能,请写-它很可能已经存在于ReactOS代码中或位于Wine中。 尚无USB驱动程序。
在这里下载
新年快乐,稳定的ReactOS!
PS
重要更新! 在4.0或4.5下构建的简单控制台应用程序可以列出磁盘上的文件夹/文件,但效果很好。 因此,不能在WinForms和WPF(像WinForms示例一样挂起)的地方,而不是所有CLR。
在安装4.5期间,我注意到带有参数remove System.Windows.Forms或System.Dynamic等的ngen.exe进程。 似乎删除已删除,但没有正常注册新程序集
PPS
SUPER重要更新! 在此过程中,安装程序4.5从GAC中删除了一些程序集,但是该程序崩溃了,并且没有时间复制新程序集(\ Microsoft.NET \ Assembly \ GAC_MSIL)。 结果,在115个程序集中,剩下的73个程序如果在其中复制System,System.Drawing,System.Windows.Forms和Accessibility程序集,则将启动一个简单的WinForms应用程序!
PPPS事实证明很重要-如果您从system32中的4.0复制mscoree.dll,则安装程序4.5不能完全正常运行,但是在重新启动控制台并启动win-form应用程序之后。