ReactOS.exe 安装程序分析

ReactOS.exe 安装程序分析

概述

reactos.exe 是 ReactOS 的 GUI 第一阶段安装程序 ,位于 d:\reactos\base\setup\reactos\。它是一个 Win32 属性表(Property Sheet)向导,提供 7 步安装流程(欢迎 → 安装类型 → 设备 → 分区 → 摘要 → 安装进度 → 完成),并调用 setuplib 库完成底层安装操作(分区、格式化、文件复制、注册表更新、引导加载器安装)。


1. 源文件清单

文件 路径 用途
reactos.c base\setup\reactos\reactos.c 主入口、所有页面过程、安装线程、辅助函数
drivepage.c base\setup\reactos\drivepage.c 分区/驱动器选择页面
treelist.c base\setup\reactos\treelist.c TreeList 控件(第三方,分区树形列表)
fileqsup.c base\setup\reactos\spapisup\fileqsup.c SetupAPI 文件队列支持
infsupp.c base\setup\reactos\spapisup\infsupp.c SetupAPI INF 文件支持
reactos.h base\setup\reactos\reactos.h 主头文件
treelist.h base\setup\reactos\treelist.h TreeList 头文件

2. 全局数据结构

文件reactos.c#L23(file:///d:/reactos/base/setup/reactos/reactos.c#L23)

c 复制代码
HANDLE ProcessHeap;            // 进程堆句柄
SETUPDATA SetupData;           // 安装配置数据(源路径、目标路径等)
PPARTENTRY InstallPartition;   // 目标安装分区
PPARTENTRY SystemPartition;    // 系统分区(活动引导分区)
UI_CONTEXT UiContext;          // UI 上下文(字体、语言等)

3. wWinMain --- 程序入口

文件reactos.c#L3210(file:///d:/reactos/base/setup/reactos/reactos.c#L3210)

复制代码
_tWinMain(INSTANCE, PREVINSTANCE, CMDLINE, CMD_SHOW)
  │
  ├─ 1. ProcessHeap = GetProcessHeap()
  ├─ 2. ZeroMemory(&SetupData)
  │
  ├─ ★ 3. InitializeSetup()                  调用 setuplib:加载 txtsetup.sif
  ├─ 4. CheckUnattendedSetup()                检查无人值守配置
  │
  ├─ ★ 5. LoadSetupData()                    加载分区、NTOS安装、硬件列表
  │     ├─ CreatePartitionList()              枚举磁盘分区
  │     ├─ CreateNTOSInstallationsList()      检测已有 NT 系统
  │     ├─ CreateComputerTypeList()           计算机类型列表
  │     ├─ CreateDisplayDriverList()          显示驱动列表
  │     └─ CreateKeyboardDriverList()         键盘驱动列表
  │
  ├─ 6. CreateThread(HotkeyThread)            Shift+F10 打开 cmd
  ├─ 7. InitCommonControls + 注册 TreeList
  ├─ 8. CreateTitleFont() + CreateBoldFont()
  │
  ├─ 9. 创建 9 个属性页:
  │     ├─ IDD_STARTPAGE      → StartDlgProc   (仅非无人值守)
  │     ├─ IDD_TYPEPAGE       → TypeDlgProc    (仅非无人值守)
  │     ├─ IDD_UPDATEREPAIR   → UpgradeRepair  (仅非无人值守)
  │     ├─ IDD_DEVICEPAGE     → DeviceDlgProc  (仅非无人值守)
  │     ├─ IDD_DRIVEPAGE      → DriveDlgProc   (仅非无人值守)
  │     ├─ IDD_SUMMARYPAGE    → SummaryDlgProc (仅非无人值守)
  │     ├─ IDD_PROCESSPAGE    → ProcessDlgProc (始终)
  │     ├─ IDD_FINISHPAGE     → FinishDlgProc  (始终)
  │     └─ IDD_ABORTPAGE      → FinishDlgProc  (始终)
  │
  ├─ 10. PropertySheet(所有页面)              ← 以向导模式显示
  │
  ├─ 11. 等待安装线程结束
  ├─ 12. 清理字体 + TreeList
  ├─ 13. TerminateThread(HotkeyThread)
  ├─ 14. FinishSetup()                        清理 setuplib
  │
  └─ 15. ExitWindowsEx(EWX_REBOOT)            需要重启时

4. 7 步安装向导详解

页面 1: StartDlgProc --- 欢迎页面

文件reactos.c#L352(file:///d:/reactos/base/setup/reactos/reactos.c#L352)

c 复制代码
StartDlgProc(hwndDlg, uMsg, wParam, lParam)
{
    WM_INITDIALOG: 保存 SETUPDATA 指针,设置标题字体,居中窗口
    PSN_SETACTIVE: 只显示"下一步"按钮,隐藏"上一步"
    PSN_KILLACTIVE: 重新显示"上一步"
}

页面 2: TypeDlgProc --- 安装类型

文件reactos.c#L422(file:///d:/reactos/base/setup/reactos/reactos.c#L422)

复制代码
用户选择:
  ├─ "安装 ReactOS" (全新安装)
  │     → PSN_WIZNEXT → 跳到设备页面 (IDD_DEVICEPAGE)
  │
  └─ "升级或修复现有安装"
        → 检测到有多个 NT 系统?
        │    Yes → UpdataRepair 页面 (选要升级的系统)
        │    No  → 直接跳到设备页面
        └─ SetupData.RepairUpdateFlag = TRUE

页面 3: UpdataRepairDlgProc --- 升级选择

文件reactos.c#L789(file:///d:/reactos/base/setup/reactos/reactos.c#L789)

复制代码
WM_INITDIALOG: 初始化列表视图,显示检测到的 NTOS 安装列表
PSN_WIZNEXT: 设置选中的 NTOS 安装,RepairUpdateFlag=TRUE
IDC_SKIPUPGRADE: 跳过升级,全新安装

页面 4: DeviceDlgProc --- 设备配置

文件reactos.c#L975(file:///d:/reactos/base/setup/reactos/reactos.c#L975)

c 复制代码
DeviceDlgProc(hwndDlg, uMsg, wParam, lParam)
{
    WM_INITDIALOG:
        InitGenericComboList(IDC_COMPUTER, ComputerTypeList)    ← 计算机类型
        InitGenericComboList(IDC_DISPLAY, DisplayDriverList)    ← 显示驱动
        InitGenericComboList(IDC_KEYBOARD, KeyboardDriverList)  ← 键盘驱动

    PSN_WIZNEXT:
        保存三个下拉框的选中值到 SetupData
}

设备列表数据来自 txtsetup.sif 文件,由 LoadSetupData() 在程序启动时加载。

页面 5: DriveDlgProc --- 分区选择

文件drivepage.c#L1593(file:///d:/reactos/base/setup/reactos/drivepage.c#L1593)

这是最复杂的页面。TreeList 控件显示所有磁盘和分区的树形结构。

复制代码
DriveDlgProc(hwndDlg, uMsg, wParam, lParam)
  │
  ├─ WM_INITDIALOG:
  │     InitPartitionList() → 填充 TreeList (磁盘/分区树)
  │     隐藏创建/删除/格式化按钮
  │
  ├─ TVN_SELCHANGED (选中项变化):
  │     根据选中项类型显示/隐藏按钮:
  │     ├─ 未分区空间 → 显示"创建分区"
  │     ├─ 已分区     → 显示"格式化"/"删除"
  │     ├─ 已格式化   → 显示"格式化"
  │     └─ 磁盘头     → 无操作按钮
  │
  ├─ IDC_PARTCREATE → PartitionDlgProc()      创建分区对话框
  ├─ IDC_PARTDELETE → DoDeletePartition()     删除分区
  ├─ IDC_PARTFORMAT → FormatDlgProc()         格式化对话框
  ├─ IDC_PARTMOREOPTS → MoreOptsDlgProc()     高级选项 (安装目录)
  │
  └─ PSN_WIZNEXT:
        ├─ 检查选中分区 → 未格式化? → 弹出格式化对话框
        ├─ 设置 InstallPartition = 选中分区
        └─ 检查 BIOS 识别性 → 不可引导? → 警告

PartitionDlgProc (drivepage.c#L608(file:///d:/reactos/base/setup/reactos/drivepage.c#L608)) --- 创建分区:

复制代码
用户输入分区大小 (MB)
可勾选"使用所有可用空间"
调用 CreatePartition(空间, 大小)
→ DoCreatePartition() → 刷新 TreeList 显示

FormatDlgProc (drivepage.c#L555(file:///d:/reactos/base/setup/reactos/drivepage.c#L555)) --- 格式化:

复制代码
选择文件系统 (FAT/FAT32/BtrFS)
勾选"快速格式化"
确认 → FsVolCommitOpsQueue → 执行实际格式化

MoreOptsDlgProc (drivepage.c#L212(file:///d:/reactos/base/setup/reactos/drivepage.c#L212)) --- 高级选项:

复制代码
设置安装目录路径 (默认: \ReactOS)
设置引导加载程序位置 (MBR/软盘/不安装)
调用 IsValidInstallDirectory() 验证目录名合法性

页面 6: SummaryDlgProc --- 安装摘要

文件reactos.c#L1078(file:///d:/reactos/base/setup/reactos/reactos.c#L1078)

复制代码
PSN_SETACTIVE:
  显示用户选择的全部安装选项:
  ├─ 安装类型 (新安装/升级)
  ├─ 计算机类型
  ├─ 显示驱动
  ├─ 键盘驱动
  ├─ 目标分区
  └─ 目标路径
  按钮文本改为"安装"
  复选框 IDC_CONFIRM_INSTALL 勾选后启用"安装"按钮

页面 7: ProcessDlgProc --- 安装进度

文件reactos.c#L2230(file:///d:/reactos/base/setup/reactos/reactos.c#L2230)

复制代码
PSN_SETACTIVE:
  创建安装线程 PrepareAndDoCopyThread() (挂起)
  恢复线程 → 正式开始安装
  (属性表页面显示进度信息)

PSN_QUERYCANCEL:
  停止安装线程
  跳到中止页面 (IDD_ABORTPAGE)

5. 核心安装线程: PrepareAndDoCopyThread

文件reactos.c#L1847(file:///d:/reactos/base/setup/reactos/reactos.c#L1847)

这是执行实际安装操作的函数,运行在独立线程中,分为 8 个子步骤:

c 复制代码
DWORD WINAPI PrepareAndDoCopyThread(LPVOID lpParameter)
{
    │
    ├─ Step 1: InitSystemPartition()
    │  查找或设置活动系统分区,如无则自动创建
    │
    ├─ Step 2: FsVolCommitOpsQueue() + FsVolCallback()
    │  执行格式化/检查操作队列:
    │  ├─ FSVOLNOTIFY_STARTFORMAT → 显示"正在格式化..."
    │  ├─ FSVOLNOTIFY_FORMATPROGRESS → 格式化进度百分比
    │  ├─ FSVOLNOTIFY_FORMATSTATUS → 文件系统类型
    │  ├─ FSVOLNOTIFY_STARTCHKDSK → 显示"正在检查磁盘..."
    │  └─ FSVOLNOTIFY_CHKDSKPROGRESS → 检查进度
    │
    ├─ Step 3: InitDestinationPaths()
    │  重新计算目标路径(ARC路径、NT路径、Win32路径)
    │
    ├─ Step 4: PrepareFileCopy()
    │  准备文件复制队列:
    │  ├─ 从 txtsetup.sif [SourceDisksFiles] 读取所有文件
    │  ├─ 按目标目录分组
    │  └─ 创建 SetupAPI 文件队列
    │
    ├─ Step 5: DoFileCopy() + FileCopyCallback()
    │  执行文件复制:
    │  ├─ 从 CAB 或源目录复制文件
    │  ├─ FILECOPYNOTIFY_PROGRESS → 进度百分比
    │  ├─ FILECOPYNOTIFY_ERROR → 文件错误处理(重试/跳过)
    │  ├─ FILECOPYNOTIFY_DELETE → 删除旧文件
    │  └─ FILECOPYNOTIFY_RENAME → 重命名文件
    │
    ├─ Step 6: InstallSetupInfFile()
    │  创建 $winnt$.inf 安装配置文件(包含分区、目录等配置)
    │
    ├─ Step 7: UpdateRegistry() + RegistryStatus()
    │  创建并更新注册表配置单元:
    │  ├─ RegInitializeRegistry() → 初始化 HIVE
    │  ├─ 从 HiveInfs.Fresh/HiveInfs.Install 导入
    │  ├─ 更新显示设置
    │  ├─ 设置区域/键盘布局
    │  ├─ 添加代码页
    │  ├─ 设置默认页面文件
    │  └─ 更新已挂载设备值
    │
    └─ Step 8: 安装引导加载器
        ├─ BootLoader=0: 不安装
        ├─ BootLoader=1: InstallBootcodeToRemovable()    ← 软盘
        ├─ BootLoader=2: InstallBootManagerAndBootEntries() ← MBR
        └─ BootLoader=3: 仅安装 VBR
}

6. 辅助函数清单

文件reactos.c(file:///d:/reactos/base/setup/reactos/reactos.c)

UI 辅助函数

函数 行号 用途
CenterWindow 43 居中窗口
CreateBoldFont 70 创建粗体字体
CreateTitleFont 104 创建 12pt 粗体标题字体
LoadAllocStringW 112 从资源加载字符串(自动分配)
FormatAllocStringWV 147 格式化字符串(va_list)
DisplayMessageV 172 显示消息框
DisplayMessage 241 消息框包装
DisplayError 260 错误消息框
SetWindowResTextW 281 从资源设置窗口文本
SetWindowResPrintfVW 300 格式化窗口文本
CreateListViewColumns 558 创建列表视图列
InitGenericComboList 597 初始化下拉框列表
GetSelectedComboListItem 635 获取选中下拉框项
InitGenericListView 656 初始化列表视图
GetSelectedListViewItem 693 获取选中列表视图项
GetSettingDescription 712 获取设置描述文本
AddNTOSInstallationItem 723 添加 NT 安装项到列表

安装数据加载

函数 行号 用途
LoadSetupData 2627 加载分区、NT安装、硬件列表
InitNtToWin32PathMappingList 2718 初始化 NT→Win32 路径映射
FreeNtToWin32PathMappingList 2726 释放路径映射链表
ConvertNtPathToWin32Path 2747 NT 路径 → Win32 路径转换
EnablePrivilege 3006 启用/禁用特权
HotkeyThread 3036 Shift+F10 → cmd.exe
GetLocalSetupDllPath 3085 获取 setuplib.dll 路径
setupDelayHook 3144 延迟加载钩子(加载 setuplib.dll)

安装回调函数

函数 行号 用途
FormatCallback 1266 格式化进度回调
ChkdskCallback 1313 磁盘检查回调
FsVolCallback 1331 文件系统/卷操作回调
FileCopyCallback 1676 文件复制回调
RegistryStatus 1797 注册表操作状态回调
PropSheet_SetCloseCancel 1836 启用/禁用关闭/取消按钮

完成相关

函数 行号 用途
IsShellActive 2353 检测 Windows shell 是否活动
FindUserClosableWindowProc 2375 查找可关闭的用户窗口
AreThereInteractiveWindows 2411 检测交互式窗口存在

7. 完成页面 & 重启

文件reactos.c#L2429(file:///d:/reactos/base/setup/reactos/reactos.c#L2429)

复制代码
FinishDlgProc(hwndDlg, uMsg, wParam, lParam)
  ├─ WM_INITDIALOG:
  │     设置"必须重启"标志
  │     显示重启倒计时进度条 (300步 = 15秒)
  │     (或显示"稍后重启"文字)
  │
  ├─ WM_TIMER:
  │     每50ms递增进度条
  │     300步到 → PostMessage(PSBTN_FINISH)
  │
  └─ PSN_SETACTIVE:
       只显示"完成"按钮(文字改为"重启")
       隐藏"上一步"和"下一步"

wWinMainPropertySheet() 返回后:

c 复制代码
// reactos.c#L3393-3428
WaitForSingleObject(InstallThread, INFINITE);   ← 等安装线程结束
FinishSetup();                                   ← 清理 setuplib
if (NeedsReboot)
    ExitWindowsEx(EWX_REBOOT, 0);               ← 重启系统

8. setuplib 库调用关系

reactos.exe 通过延迟加载调用 setuplib.dll。以下是所有被调用的 setuplib 函数及其作用:

函数 所在文件 用途 调用点
InitializeSetup setuplib.c 初始化安装(源路径、加载 txtsetup.sif) wWinMain 第3235行
CheckUnattendedSetup setuplib.c 检查无人值守配置 wWinMain 第3253行
CreatePartitionList partlist.c 枚举所有磁盘分区 LoadSetupData 第2630行
CreateNTOSInstallationsList osdetect.c 检测已有 NT 系统 LoadSetupData 第2637行
CreateComputerTypeList settings.c 计算机类型列表 LoadSetupData 第2643行
CreateDisplayDriverList settings.c 显示驱动列表 LoadSetupData 第2644行
CreateKeyboardDriverList settings.c 键盘驱动列表 LoadSetupData 第2645行
CreateLanguageList settings.c 语言列表 LoadSetupData 第2647行
CreateKeyboardLayoutList settings.c 键盘布局列表 LoadSetupData 第2669行
IsValidInstallDirectory setuplib.c 验证安装目录 MoreOptDlgProc 第312行
InitSystemPartition setuplib.c 设置活动系统分区 安装线程 Step1
FsVolCommitOpsQueue fsutil.c 执行格式化/检查 安装线程 Step2
InitDestinationPaths setuplib.c 初始化目标路径 安装线程 Step3
PrepareFileCopy install.c 准备文件复制队列 安装线程 Step4
DoFileCopy install.c 执行文件复制 安装线程 Step5
InstallSetupInfFile setuplib.c 创建 winntwinntwinnt.inf 安装线程 Step6
UpdateRegistry setuplib.c 创建/更新注册表 安装线程 Step7
InstallBootManagerAndBootEntries bootsup.c 安装引导管理器到 MBR 安装线程 Step8
InstallBootcodeToRemovable bootsup.c 安装引导到可移动介质 安装线程 Step8
FinishSetup setuplib.c 清理安装数据 wWinMain 第3410行
GetRegisteredFileSystems fsutil.c 获取注册的文件系统 DriveDlgProc

9. 安装流程图

复制代码
wWinMain
  │
  ├─ InitializeSetup()         ← 加载 txtsetup.sif,获取源路径
  │
  ├─ LoadSetupData()           ← 枚举磁盘/分区/硬件
  │
  ├─ PropertySheet(9 pages)
  │   │
  │   ├─ [欢迎] → [安装类型] → [设备] → [分区] → [摘要]
  │   │                                                │
  │   │                                          用户点击"安装"
  │   │                                                │
  │   └────────────────────────────────────────────────┘
  │                                                    │
  ├─ ProcessDlgProc → CreateThread(PrepareAndDoCopyThread)
  │                                                    │
  │   PrepareAndDoCopyThread:                          │
  │   ├─ Step 1: InitSystemPartition()                 │
  │   ├─ Step 2: FsVolCommitOpsQueue()   格式化       │
  │   ├─ Step 3: InitDestinationPaths()                │
  │   ├─ Step 4: PrepareFileCopy()       准备复制      │
  │   ├─ Step 5: DoFileCopy()            复制文件      │
  │   ├─ Step 6: InstallSetupInfFile()   $winnt$.inf  │
  │   ├─ Step 7: UpdateRegistry()        注册表        │
  │   └─ Step 8: Install Bootloader      引导加载器    │
  │                                                    │
  ├─ WaitForSingleObject(InstallThread)                 │
  ├─ FinishSetup()                                      │
  └─ ExitWindowsEx(EWX_REBOOT)                          │

设计要点

概念 说明
属性表向导 使用 Win32 PropertySheet 控件实现多步向导
独立安装线程 实际安装操作在 PrepareAndDoCopyThread 中异步执行
setuplib 延迟加载 通过 setupDelayHook 动态加载 setuplib.dll
txtsetup.sif 驱动 所有硬件列表从 txtsetup.sif 读取
SetupAPI 文件队列 使用 SetupAPI 管理文件复制、删除、重命名操作
回调机制 格式化/检查/复制/注册表操作通过回调更新 UI 进度
Shift+F10 调试 热键线程允许在安装过程中打开命令提示符
无人值守 支持通过 unattend.inf 自动跳过所有配置页面
相关推荐
caimouse12 小时前
KPRCB 结构分析与调度流程
reactos
caimouse2 天前
Phase1Initialization 函数分析
单片机·嵌入式硬件·reactos
caimouse3 天前
ReactOS bootcd.iso 引导到桌面显示过程分析
reactos
caimouse4 天前
ReactOS BootCD 光盘布局完整深度分析
单片机·reactos
caimouse4 天前
KiSwitchToBootStack 函数分析
reactos
caimouse4 天前
KiSystemStartupBootStack 函数分析
开发语言·reactos
caimouse6 天前
ReactOS Development Notes
reactos
爱学习的大牛1232 年前
通过VirtualBox虚拟机安装和调试编译好的 ReactOS
reactos·windows内核学习
zhyjhacker2 年前
ReactOS 4.2 OBJECT_TYPE_INITIALIZERj结构体的实现
c++·windows·reactos