WINLOGON 初始化与作用分析
2026/7/22 17:06:08 网站建设 项目流程

WINLOGON 初始化与作用分析

概述

WINLOGON.EXE 是 ReactOS 的用户登录进程,由 SMSS 在启动 CSRSS 之后创建。它负责创建窗口站 WinSta0 和三个桌面(Default/Winlogon/Screen-Saver)、加载 GINA DLL 处理用户身份验证、启动 Shell(explorer.exe)和服务管理器(services.exe),并作为系统安全关注序列(SAS,即 Ctrl+Alt+Del)的处理者。

源码目录d:\reactos\base\system\winlogon\

文件用途
winlogon.c主入口点WinMain
wlx.cGINA 加载/窗口站和桌面创建/WINLOGON 分发表
sas.cSAS 处理/登录注销/Shell 启动
security.c安全描述符/桌面和窗口站访问控制
notify.c通知包管理
shutdown.c系统关闭对话框
screensaver.c屏幕保护管理
environment.c用户环境创建
setup.c安装模式支持
rpcserver.c远程注册表 RPC 服务

1. WINLOGON 启动的完整路径

1.1 SMSS 启动 WINLOGON

SMSS _main() │ ├─ SmpInit() ← SMSS 自身初始化 │ └─ SmpLoadSubSystemsForMuSession() │ ├─ 创建会话 0 │ ├─ 加载 win32k.sys │ └─ 启动 CSRSS (csrss.exe) │ └─ SmpExecuteInitialCommand(0, "winlogon.exe", Handles[1], NULL) ├─ SmConnectToSm(\SmApiPort) ← 连接 SMSS 的 LPC 端口 ├─ SmpExecuteImage(winlogon.exe, DEFERRED) ← 创建 WINLOGON (挂起) └─ SmExecPgm() → SmpExecPgm() → SmpSbCreateSession() ├─ SmpLocateKnownSubSysByType() → 找 CSRSS ├─ NtDuplicateObject() → 传递句柄到 CSRSS ├─ SmpAllocateSessionId() → 分配会话 1 ├─ NtRequestWaitReplyPort(SbpCreateSession) → CSRSS 创建会话 1 └─ NtResumeThread(WINLOGON) ← ★ WINLOGON 开始运行

1.2 与 SMSS 的关系

SMSS ←→ CSRSS = 通过 \SmApiPort (LPC) 和 SbApiPort 双向通信 SMSS → WINLOGON = 创建进程 + SmExecPgm LPC 消息(含会话创建) WINLOGON → SMSS = 不直接通信 (通过 CSRSS 间接) | v SMSS 在 _main 末尾: NtWaitForMultipleObjects(CSRSS_Handle, WINLOGON_Handle) └─ 任一终止 → SmpTerminate() → 系统关闭

2. WinMain — 初始化序列

文件:[winlogon.c#L431](file:///d:/reactos/base/system/winlogon/winlogon.c#L431)

WinMain() │ ├─ 1. RtlSetProcessIsCritical(TRUE) ← 标记为关键进程 ├─ 2. RtlSetThreadIsCritical(TRUE) ← 线程也为关键 │ ├─ 3. UpdateTcpIpInformation() ← 更新 TCP/IP 主机名 │ ├─ ★ 4. RegisterLogonProcess() ← 注册到 win32k.sys + CSRSS │ ├─ 5. 分配并初始化 WLSession 结构体 │ ├─ ★ 6. CreateWindowStationAndDesktops() ← ★ 创建 WinSta0 + 三个桌面 │ ├─ 7. InitKeyboardLayouts() ← 加载键盘布局 │ ├─ 8. StartRpcServer() ← 启动远程注册表 RPC │ ├─ ★ 9. StartServicesManager() ← ★ 启动 services.exe (SCM) │ ├─ ★ 10. StartLsass() ← ★ 启动 lsass.exe (LSA) │ ├─ 11. WaitForLsass() ← 等待 LSA 事件 │ ├─ 12. InitNotifications() ← 加载通知包 │ ├─ ★ 13. GinaInit(msgina.dll) ← ★ 加载 GINA DLL │ ├─ 14. CallNotificationDlls(Startup) ← 发送启动通知 │ ├─ ★ 15. InitializeSAS() ← ★ 创建 SAS 窗口 + 注册热键 │ ├─ 16. 检查安装模式 (GetSetupType()) │ └─ 17. NtInitializeRegistry() ← 标记 ControlSet 有效 │ └─ 18. 进入消息循环 (GetMessage/DispatchMessage)

3. 注册到 Win32 子系统 — 三步注册

3.1 注册到内核模式 win32k.sys

WinMain() └─ RegisterLogonProcess(GetCurrentProcessId(), TRUE) [winlogon.c:463] └─ user32!RegisterLogonProcess() [logon.c:43] ├─ NtUserRegisterLogonProcess() → 系统调用进入 win32k.sys │ └─ co_IntRegisterLogonProcess() [simplecall.c:18] │ └─ gpidLogon = PID [simplecall.c:40] │ ← win32k 全局变量记录登录进程 PID │ └─ CsrClientCallServer(UserpRegisterLogonProcess) → 发到 CSRSS └─ CSRSS!SrvRegisterLogonProcess() [register.c:30] └─ LogonProcessId = WINLOGON PID

3.2 注册 SAS 通知窗口

InitializeSAS() [sas.c:1740] └─ CreateWindow("SAS Window class", "SAS window", WS_POPUP, ...) └─ SetLogonNotifyWindow(Session->SASWindow) [sas.c:1786] └─ user32!SetLogonNotifyWindow(hWnd) └─ NtUserSetLogonNotifyWindow() → win32k.sys [winsta.c:1963] └─ gspm.hwndSAS = hWnd [winsta.c:1978] ← win32k 全局变量记录 SAS 窗口句柄

3.3 注册热键

InitializeSAS() [sas.c:1740] └─ RegisterHotKeys(SASWindow, ...) [sas.c:1437] ├─ Ctrl+Alt+Del → IDHK_CTRL_ALT_DEL (0) ← SAS 触发 ├─ Ctrl+Shift+Esc → IDHK_CTRL_SHIFT_ESC (1) ← 任务管理器 ├─ Win+L → IDHK_WIN_L (2) ← 锁定工作站 └─ Win+U → IDHK_WIN_U (3) ← 辅助工具管理器

4. 创建窗口站和桌面

文件:[wlx.c#L953](file:///d:/reactos/base/system/winlogon/wlx.c#L953)

这是 WINLOGON 最关键的初始化操作之一。它创建了所有 Win32 应用程序运行的窗口环境。

CreateWindowStationAndDesktops() │ ├─ 1. CreateWinstaSecurity() [security.c:112] │ 权限: SYSTEM(全部), Administrators(受限) │ ├─ 2. CreateWindowStationW(L"WinSta0", ...) [wlx.c:1010] │ → 创建 WinSta0 窗口站 │ ├─ 3. SetProcessWindowStation(WinSta0) [wlx.c:1021] │ → 将 WINLOGON 进程关联到 WinSta0 │ ├─ 4. 创建三个桌面的安全描述符 [security.c:359-854] │ ├─ 5. CreateDesktopW("Default", ...) [wlx.c:1030] │ → 创建 Default 桌面 (应用程序桌面) │ ├─ 6. CreateDesktopW("Winlogon", ...) [wlx.c:1046] │ → 创建 Winlogon 桌面 (安全桌面) │ ├─ 7. CreateDesktopW("Screen-Saver", ...) [wlx.c:1062] │ → 创建 Screen-Saver 桌面 │ ├─ 8. SetThreadDesktop(Winlogon) [wlx.c:1078] ├─ 9. SwitchDesktop(Winlogon) [wlx.c:1079] │ → ★ 切换到 Winlogon 安全桌面 │ └─ 10. SetWindowStationUser(...) [wlx.c:1085]

三个桌面

桌面用途安全权限
Winlogon安全桌面 — 登录界面SYSTEM(全部), Administrators(受限)
Default应用程序桌面 — 用户日常工作SYSTEM(全部), 用户(全部)
Screen-Saver屏幕保护桌面SYSTEM(全部), Interactive(受限)

登录后,AllowAccessOnSession([security.c#L1391](file:///d:/reactos/base/system/winlogon/security.c#L1391))为当前登录用户授予 WinSta0 和 Default 桌面的访问权限。


5. 启动关键系统进程

5.1 启动服务管理器 (services.exe)

文件:[winlogon.c#L46](file:///d:/reactos/base/system/winlogon/winlogon.c#L46)

staticBOOLStartServicesManager(VOID){returnCreateProcessW(L"services.exe",NULL,...,DETACHED_PROCESS,...);}

WinMain第 508 行调用。SCM 以独立进程方式启动,负责管理系统服务。

5.2 启动 LSA (lsass.exe)

文件:[winlogon.c#L82](file:///d:/reactos/base/system/winlogon/winlogon.c#L82)

staticBOOLStartLsass(VOID){returnCreateProcessW(L"lsass.exe",NULL,...,CREATE_SUSPENDED|DETACHED_PROCESS,...);}

创建后通过WaitForLsass()等待LSA_RPC_SERVER_ACTIVE事件,确保 LSA 已完成初始化后再继续。


6. GINA 接口

6.1 GINA DLL 定位

文件:[wlx.c#L779](file:///d:/reactos/base/system/winlogon/wlx.c#L779)

从注册表读取:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GinaDLL

默认值:msgina.dll(ReactOS 内置)

6.2 GINA 函数表

文件:[wlx.c#L830](file:///d:/reactos/base/system/winlogon/wlx.c#L830)

GINA DLL 需导出的函数(按版本):

函数版本用途
WlxNegotiatev1.0协商接口版本(可选)
WlxInitializev1.0初始化 GINA,接收 WINLOGON 分发表
WlxDisplaySASNoticev1.0显示 SAS 提示(如"按 Ctrl+Alt+Del 登录")
WlxLoggedOutSASv1.0处理登录 SAS(显示登录对话框)
WlxActivateUserShellv1.0激活用户 Shell(启动 explorer.exe)
WlxLoggedOnSASv1.0处理已登录时的 SAS
WlxDisplayLockedNoticev1.0显示锁定提示
WlxWkstaLockedSASv1.0处理锁定状态的 SAS(解锁对话框)
WlxIsLockOkv1.0检查是否允许锁定
WlxIsLogoffOkv1.0检查是否允许注销
WlxLogoffv1.0注销处理
WlxShutdownv1.0关机处理
WlxScreenSaverNotifyv1.1屏保通知(可选)
WlxStartApplicationv1.1启动应用程序(可选)
WlxDisplayStatusMessagev1.3显示状态消息
WlxGetStatusMessagev1.3获取状态消息
WlxNetworkProviderLoadv1.3网络提供者加载
WlxRemoveStatusMessagev1.3移除状态消息

6.3 WINLOGON 分发表(提供给 GINA)

文件:[wlx.c#L747](file:///d:/reactos/base/system/winlogon/wlx.c#L747)

WINLOGON 暴露 27 个函数给 GINA:

函数用途
WlxUseCtrlAltDel启用/禁用 Ctrl+Alt+Del
WlxSetContextPointer设置上下文指针
WlxSasNotify发送 SAS 通知
WlxSetTimeout设置对话框超时
WlxMessageBox消息框
WlxDialogBox/WlxDialogBoxParam/WlxDialogBoxIndirect对话框
WlxSwitchDesktopToUser切换到 Default 桌面
WlxSwitchDesktopToWinlogon切换到 Winlogon 桌面
WlxSetOption/WlxGetOption选项管理
密码通知、桌面管理等

7. SAS 处理机制

7.1 SAS 触发路径

用户按下 Ctrl+Alt+Del │ ├─ 键盘驱动 → win32k.sys (MOD_WINLOGON_SAS 标志) │ └─ PostMessage(hwndSAS, WM_HOTKEY, IDHK_CTRL_ALT_DEL, ...) │ └─ SASWindowProc() [sas.c:1526] └─ PostMessage(SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0) └─ DispatchSAS() [sas.c:1322] └─ 根据 LogonState 分发: STATE_INIT → GINA.WlxDisplaySASNotice() STATE_LOGGED_OFF → GINA.WlxLoggedOutSAS() STATE_LOGGED_ON → GINA.WlxLoggedOnSAS() STATE_LOCKED → GINA.WlxWkstaLockedSAS()

7.2 SAS 窗口

文件:[sas.c#L1526](file:///d:/reactos/base/system/winlogon/sas.c#L1526)

  • 窗口类:"SAS Window class"(隐藏弹出窗口)
  • 窗口标题:"SAS window"
  • 注册:SetLogonNotifyWindow(SASWindow)gspm.hwndSAS
  • 消息处理:
    • WM_HOTKEY→ 转换为 SAS 事件或直接动作
    • WM_LOGONNOTIFY→ 系统级通知(Shell退出、锁屏、注销等)
    • WLX_WM_SAS→ 分发给 GINA

7.3 SAS 动作分发

文件:[sas.c#L1206](file:///d:/reactos/base/system/winlogon/sas.c#L1206)

GINA 返回wlxAction后,由DoGenericAction调度:

动作处理
WLX_SAS_ACTION_LOGONHandleLogon()→ 加载用户配置、启动 Shell
WLX_SAS_ACTION_LOGOFFHandleLogoff()→ 卸载配置、杀死进程
WLX_SAS_ACTION_SHUTDOWNHandleLogoff()+HandleShutdown()
WLX_SAS_ACTION_LOCK_WKSTA锁定工作站
WLX_SAS_ACTION_TASKLISTStartTaskManager()
WLX_SAS_ACTION_FORCE_LOGOFF强制注销
WLX_SAS_ACTION_SHUTDOWN_REBOOT重启
WLX_SAS_ACTION_SHUTDOWN_POWER_OFF关机断电

8. 登录流程详解

用户输入凭据 → GINA.WlxLoggedOutSAS() 返回 WLX_SAS_ACTION_LOGON │ └─ DoGenericAction(WLX_SAS_ACTION_LOGON) └─ HandleLogon(Session) [sas.c:571] │ ├─ 1. GINA.WlxLogoff() ← 清理旧会话 │ ├─ ★ 2. GINA.WlxLoggedOutSAS() 返回 WLX_SAS_ACTION_LOGON │ ↓ 用户凭据已验证 │ ├─ 3. LoadUserProfileW(hToken) ← 加载用户配置文件 ├─ 4. CreateEnvironmentBlock() ← 创建环境块 │ ├─ 5. CallNotificationDlls(LogonHandler) ← 登录通知 │ ├─ 6. CallNotificationDlls(StartShellHandler) │ ├─ ★ 7. GINA.WlxActivateUserShell() ← ★ 启动 Shell │ └─ msgina.dll 读取注册表: │ HKLM\...\Winlogon\Shell = "explorer.exe" │ → CreateProcessAsUser(hToken, "explorer.exe", ...) │ ├─ 8. CallNotificationDlls(PostShellHandler) │ ├─ 9. InitializeScreenSaver() ← 初始化屏保 │ ├─ 10. SwitchDesktopToUser() ← 切换到 Default 桌面 │ └─ 11. LogonState = STATE_LOGGED_ON

9. 通知包机制

文件:[notify.c](file:///d:/reactos/base/system/winlogon/notify.c)

WINLOGON 提供可扩展的通知包机制,允许第三方软件获知登录/注销事件。

InitNotifications() [notify.c:417] │ ├─ InitializeListHead(通知链表) ├─ AddSfcNotification() │ → sfc.dll: SfcWLEventLogon / SfcWLEventLogoff │ └─ 枚举注册表: HKLM\...\Winlogon\Notify\* ├─ DllName = 通知 DLL 路径 ├─ Logon / Logoff / Lock / Unlock 等处理函数 ├─ Asynchronous / Impersonate / MaxWait 配置 └─ → AddNotificationDll() [notify.c:467]

12 种通知类型

LogonHandler → 登录 LogoffHandler → 注销 LockHandler → 锁定 UnlockHandler → 解锁 StartupHandler → 系统启动 ShutdownHandler → 系统关闭 StartScreenSaverHandler → 启动屏保 StopScreenSaverHandler → 停止屏保 DisconnectHandler → 断开连接 ReconnectHandler → 重新连接 StartShellHandler → 启动 Shell PostShellHandler → Shell 启动后

10. 完整交互架构图

┌─────────────────────────────────────────────────────────────────┐ │ 用户模式 │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ SMSS │ │ CSRSS │ │ WINLOGON │ │ │ │ │ │ │ │ │ │ │ │ 启动进程 │ │ Win32 API │ │ WinSta0 │ │ │ │ 管理会话 │ │ 控制台 │ │ 三个桌面 │ │ │ │ \SmApiPort │ │ 硬错误 │ │ SAS 处理 │ │ │ └─────┬──────┘ └─────┬──────┘ └──────┬─────┘ │ │ │ │ │ │ │ │ LPC │ LPC │ │ │ │ (SbApiPort) │ (ApiPort) │ │ │ └────────────────┼─────────────────┘ │ │ │ │ │ ┌────┴──────┐ │ │ │ 用户进程 │ │ │ │ explorer │ │ │ │ notepad │ │ │ └───────────┘ │ │ │ │ │ │ system call (0x1XXX) │ ├─────────────────────────┼─────────────────────────────────────────┤ │ 内核模式 │ │ │ │ │ ┌────┴──────────────────────────────────────┐ │ │ │ win32k.sys │ │ │ │ ┌──────────────┐ ┌─────────────────────┐ │ │ │ │ │ USER 子系统 │ │ GDI 子系统 │ │ │ │ │ │ │ │ │ │ │ │ │ │ 窗口管理 │ │ 绘图/字体/调色板 │ │ │ │ │ │ 消息路由 │ │ 设备上下文(DC) │ │ │ │ │ │ 输入处理 │ │ 位图/画刷/区域 │ │ │ │ │ │ │ │ │ │ │ │ │ │ gpidLogon │ │ │ │ │ │ │ │ = WINLOGON │ │ │ │ │ │ │ │ hwndSAS = │ │ │ │ │ │ │ │ SAS 窗口 │ │ │ │ │ │ │ └──────────────┘ └─────────────────────┘ │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘

11. 四者关系总结

启动顺序

SMSS ──(SystemSessionCreate)──→ 创建会话 0 SMSS ──(ExtendServiceTable)───→ 加载 win32k.sys SMSS ──(CreateProcess)────────→ CSRSS │ │ │ ──(LPC 连接互认)──────────────→ CSRSS 开始运行 │ SMSS ──(CreateProcess DEFERRED)→ WINLOGON │ ──(LPC: SbpCreateSession)─→ CSRSS: 创建会话 1 │ ──(ResumeThread)──────────→ WINLOGON 开始运行 │ SMSS ←→ CSRSS = LPC 双向通信 (\SmApiPort / SbApiPort) SMSS ←→ WINLOGON = 间接通信 (通过 CSRSS)

角色职责

进程作用与 WINLOGON 的关系
SMSS会话管理器,系统引导第二阶段启动 WINLOGON(挂起 → LPC 会话创建 → 恢复)
CSRSSWin32 子系统服务器端注册登录进程、会话创建、LPC API 服务
win32k.sys内核模式窗口/图形子系统记录登录 PID(gpidLogon)、接收 SAS 热键、桌面管理
WINLOGON用户登录管理创建 WinSta0/桌面、加载 GINA、启动 Shell/SCM/LSA

关键注册点

WINLOGON → win32k.sys: RegisterLogonProcess → gpidLogon = PID WINLOGON → win32k.sys: SetLogonNotifyWindow → hwndSAS = SAS Window WINLOGON → CSRSS: SrvRegisterLogonProcess WINLOGON → CSRSS: SrvLogon (GINA 登录成功后)

设计要点

概念说明
关键进程RtlSetProcessIsCritical(TRUE),终止即蓝屏
安全桌面Winlogon 桌面隔离登录界面,防止应用程序窃取密码
SAS 独占Ctrl+Alt+Del 由 win32k 捕获后发给 WINLOGON,用户程序无法拦截
GINA 可替换通过注册表GinaDLL可替换为自定义登录界面
通知包HKLM\...\Winlogon\Notify允许第三方注册登录/注销回调
Shell 独立WINLOGON 不直接管理 Shell(通过 GINA 代理),崩溃后自动重启
状态机STATE_INIT → LOGGED_OFF → LOGGED_ON → LOCKED等 10+ 个状态

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询