Ядро Windows сканирует параметры загрузки в поисках спецификаторов безопасного режима и устанавливает значение внутренней переменной InitSafeBootMode в соответствии с результатом поиска. Значение этой переменной также записывается в раздел HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Option\OptionValue, что позволяет компонентам пользовательского режима (например, SCM) определять режим загрузки системы. Кроме того, при выборе Safe Mode With Command Prompt, ядро присваивает значение 1 параметру UseAlternateShell в разделе реестра HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Option. Кроме того, ядро записывает параметры, переданные Ntldr, в раздел HKLM\SYSTEM\CurrentControlSet\Control\SystemStartOptions.
Когда диспетчер ввода-вывода загружает драйверы устройств, указанные в разделе HKLM\SYSTEM\CurrentControlSet\Services, он выполняет функцию IopLoadDriver. A когда диспетчер Plug and Play обнаруживает новое устройство и хочет динамически загрузить драйвер для этого устройства, он вызывает функцию IopCallDriverAddDevice. Обе эти функции перед загрузкой драйвера обращаются к функции IopSafeBootDriverLoad. Последняя проверяет значение переменной InitSafeBootMode и определяет, можно ли загрузить данный драйвер. Так, если система загружается в стандартном безопасном режиме, IopSafeBootDriverLoad ищет группу этого драйвера (если таковая есть) в подразделе Minimal. Найдя ее, IopSafeBootDriverLoad уведомляет вызвавшую функцию о том, что этот драйвер можно загрузить. B ином случае IopSafeBootDriverLoad ищет в том же подразделе имя драйвера. Если оно есть в списке, драйвер может быть загружен. Если IopSafeBootDriverLoad не находит в списке группу или имя данного драйвера, его загрузка запрещается. При загрузке системы в безопасном режиме с сетевой поддержкой IopSafeBootDriverLoad ведет поиск в подразделе Network, а в случае загрузки системы в нормальном режиме IopSafeBootDriverLoad разрешает загрузку всех драйверов.
Однако Ntldr загружает все драйверы, у которых в соответствующих разделах реестра значение Start равно 0, что указывает на необходимость их загрузки при запуске системы. Поскольку Ntldr не проверяет раздел SafeBoot (считая, что любой драйвер с нулевым значением параметра Start необходим для успешного старта системы), он загружает все загрузочные драйверы, которые впоследствии запускаются Ntoskrnl.
SCM (Services.exe), проводя инициализацию при загрузке, проверяет параметр OptionValue в разделе реестра HKLM\SYSTEM\CurrentControlSet\Cont-rol\SafeBoot\Option, чтобы выяснить, загружается ли система в безопасном режиме. Если да, SCM зеркально воспроизводит действия IopSafeBootDriverLoad. Он обрабатывает все сервисы, перечисленные в HKLM\SYSTEM\CurrentControlSet\Services, но загружает лишь отмеченные в соответствующем подразделе реестра для загрузки в безопасном режиме. Подробнее об инициализации SCM см. раздел «Сервисы» главы 4.
Userinit (\Windows\System32\Userinit.exe) — другой компонент пользовательского режима, которому нужно знать, загружается ли система в безопасном режиме. Userinit, инициализирующий среду для пользователя при его входе в систему, проверяет значение HKLM\SYSTEM\CurrentControlSet\Cont-rol\SafeBoot\UseAlternateValue. Если это значение установлено, в качестве пользовательской оболочки он запускает не Explorer.exe, а программу, указанную в HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\AlternateShell. Когда вы устанавливаете Windows на компьютер, параметру AlternateShell присваивается значение Cmd.exe, и командная строка Windows становится оболочкой по умолчанию для безопасного режима с командной строкой. Ho, даже если текущей оболочкой является командная строка, из нее можно запустить Windows Explorer, введя команду Explorer.exe. Аналогичным образом из командной строки можно запустить любую GUI-программу.
A как приложения узнают о загрузке системы в безопасном режиме? Вызовом Windows-функции GetSystemMetrics (SM_CLEANBOOT). Пакетные сценарии, выполняющие некоторые действия при загрузке системы в безопасном режиме, проверяют наличие переменной окружения SAFEBOOT_OPTION, так как система определяет ее только при загрузке в безопасном режиме.
Если вы загружаете систему в безопасном режиме, Ntldr передает ядру Windows вместе с параметрами, устанавливающими безопасный режим, и параметр /BOOTLOG. При инициализации ядро проверяет наличие параметра /BOOTLOG независимо от того, задан ли безопасный режим. Если ядро обнаруживает соответствующую строку, оно протоколирует все свои действия при загрузке каждого драйвера. Так, если функция IopSafeBootDriverLoad запрещает загрузку какого-либо драйвера, диспетчер ввода-вывода вызывает функцию IopBootLog, регистрируя, что данный драйвер не загружен. Аналогичным образом после успешной загрузки драйвера, входящего в конфигурацию безопасного режима, IopLoadDriver вызывает IopBootLog для внесения записи о загрузке этого драйвера. Изучив файлы протокола загрузки, можно выяснить, какие драйверы являются частью данной конфигурации.
Поскольку ядро избегает изменения данных на диске до запуска Chkdsk, который происходит на более позднем этапе загрузки, IopBootLog не может просто сбрасывать записи в файл. Вместо этого она записывает их в раздел реестра HKLM\SYSTEM\CurrentControlSet\BootLog. Диспетчер сеансов (Smss), первый загружаемый компонент пользовательского режима, запускает Chkdsk для проверки целостности системного диска, а потом завершает инициализацию реестра, вызывая NtInitializeRegistry. Этот вызов указывает ядру, что уже можно безопасно открыть на диске файл протокола, что и делается вызовом IopCopyBootLogRegistryToFile. Эта функция создает в системном каталоге Windows (по умолчанию — \Windows) файл Ntbtlog.txt и копирует в него содержимое раздела реестра BootLog. IopCopyBootLogRegistryToFile также устанавливает флаг, сигнализирующий IopBootLog о возможности записи непосредственно в файл протокола. Ниже показан фрагмент образца такого файла.
Service Pack 1 3 30 2004 14:05:21.500
Loaded driver \WIND0WS\system32\ntoskrnl.exe
Loaded driver \WIND0WS\system32\hal.dll
Loaded driver \WIND0WS\system32\KDC0M.DLL
Loaded driver \WIND0WS\system32\B00TVID.dll
Loaded driver ACPI.sys
Loaded driver \WIND0WS\System32\DRIVERS\WMILIB.SYS
Loaded driver pci.sys
Loaded driver isapnp.sys
Loaded driver intelide.sys
Loaded driver \WIND0WS\System32\DRIVERS\PCIIDEX.SYS
Loaded driver MountMgr.sys
Loaded driver ftdisk.sys
Loaded driver dmload.sys
Loaded driver dmio.sys Microsoft (R)Windows 2000 (R)Version 5.0 (Build 2195) 2 11 2000 10:53:27.500
Loaded driver \WINNT \System32 \ntoskrnl.exe
Loaded driver \WINNT \System32 \hal.dll
Loaded driver \WINNT \System32 \B00TVID.DLL
Loaded driver ACPI.sys
Loaded driver \WINNT \System32 \DRIVERS \WMILIB.SYS
Loaded driver pci.sys
Loaded driver isapnp.sys
Loaded driver compbatt.sys
Loaded driver \WINNT \System32 \DRIVERS \BATTC.SYS
Loaded driver intelide.sys
Loaded driver \WINNT \System32 \DRIVERS \PCIIDEX.SYS
Loaded driver pcmcia.sys
Loaded driver ftdisk.sys
Loaded driver Diskperf.sys
Loaded driver dmload.sys
Loaded driver dmio.sys
Did not load driver \SystemRoot\System32\Drivers\lbrtfdc.SYS
Did not load driver \SystemRoot\System32\Drivers\Sfloppy.SYS
Did not load driver \SystemRoot\System32\Drivers\i2omgmt.SYS
Did not load driver Media Control Devices
Did not load driver Communications Port
Did not load driver Audio Codecs
B безопасном режиме обычно удается восстановить систему, ставшую незагружаемой в нормальном режиме из-за неправильной работы какого-либо драйвера устройства. Однако в некоторых ситуациях это не помогает: система все равно не загружается. Так, если сбойный драйвер входит в группу Safe, загрузиться в безопасном режиме не удастся. Другая ситуация, когда загрузка в безопасном режиме не помогает, — сбои в загрузочном драйвере стороннего поставщика, например в драйвере антивирусного сканера, поскольку загрузочные драйверы стартуют независимо от режима загрузки системы. Аналогичная ситуация возникает при повреждении файлов системных модулей или драйверов, входящих в конфигурацию безопасного режима, а также главной загрузочной записи (MBR) системного диска. Эти проблемы можно решить с помощью Recovery Console (Консоль восстановления). Консоль восстановления позволяет загрузить компактную оболочку командной строки с дистрибутивного компакт-диска Windows (или ранее подготовленных загрузочных дискет) и восстановить систему без загрузки компьютера с жесткого диска.