I/O系统的初始化是在内核的阶段1初始化过程中完成的。主要函数是Phase1InitializationDiscard,它调用IoInitSystem 来初始化I/O系统。
IoInitSystem 初始化工作:
- 调用IopCreateObjectTypes ,创建7种类型对象:Adapter、DeviceHandler、Controller、Device、Driver、IoCompletion、File,并存放在相应的全局变量中。
WRK中的全局类型对象变量,如下表:
CmpKeyObjectType |
ExWindowStationObjectType |
ObpDeviceMapObjectType |
DbgkDebugObjectType |
IoAdapterObjectType |
ObpDirectoryObjectType |
ExCallbackObjectType |
IoCompletionObjectType |
ObpSymbolicLinkObjectType |
ExDesktopObjectType |
IoControllerObjectType |
ObpTypeObjectType |
ExEventObjectType |
IoDeviceHandlerObjectType |
PsJobType |
ExEventPairObjectType |
IoDriviceObjectType |
PsProcessType |
ExMutantObjectType |
IoDriverObjectType |
PsThreadType |
ExpKeyedEventObjectType |
IoFileObjectType |
SeTokenObjectType |
ExProfileObjectType |
LpcPortObjectType |
WmipGuidObjectType |
ExSemaphoreObjectType |
LpcWaitablePortObjectType |
|
ExTimerObjectType |
MmSectionObjectType |
|
- 调用IopCreateRootDirectories ,在对象管理器的根目录下创建3个目录对象:\Driver、\FileSystem 、\FileSystem\Filters
- 调用IopInitializePlugPlayServices,执行即插即用管理器的阶段0初始化。
- 调用PoInitDriverServices,执行电源管理器的阶段0初始化
- 调用HalInitPnpDirver,执行HAL的即插即用总线驱动程序初始化
- 调用WMIInitialize,执行WMI的阶段0 初始化
- 再次调用IopInitializePlugPlayServices,执行即插即用管理器的阶段1初始化
- 调用IopInitialBootDrivers,初始化“引导-启动”类型的驱动类型
- 调用PpLastGoodDoBootProcessing,执行“最近一次的正确配置(LKG)”的处理
- 调用PsLocateSystemDll,初始化系统DLL(ntdll.dll),并映射到System进程中
- 调用IopInitializeSystemDrivers,加载“系统-启动”类型的驱动程序,并对它们进行初始化
- 调用IopCallDriverReinitializationRoutines,处理需要重新初始化的驱动程序
- 调用IopReassignSystemRoot,将系统根目录(\SystemRoot)替换成NT路径名,这是一个符号连接(symbolic link)名称
- 调用IopProtectSystemPartition,保护系统分区
- 调用IoAssignDriveLetters,为磁盘分区和CD-ROM驱动器分配DOS驱动器字母
- 再次调用WMII逆天李泽,执行WMI的阶段1初始化
- 再次调用PoInitDriverServices,执行电源管理器的阶段1初始化
Windows 的每一个驱动程序(和服务)在安装是都被指定了一个启动类型,存放在注册表中。
启动类型如下:
#define SERVICE_BOOT_START 0x00000000
#define SERVICE_SYSTEM_START 0x00000001
#define SERVICE_AUTO_START 0x00000002
#define SERVICE_DEMAND_START 0x00000003
#define SERVICE_DISABLED 0x00000004
在HKLM\System\CurrentControlSet\Serbices\<DriverName> 键的Start 值,表示启动类型。
4
种类型的驱动程序的加载和初始化过程。
“
引导-启动
”
类型的驱动程序是由系统加载器即ntldr程序,加载到系统空间种的,内核无需加载,直接初始化。这些驱动程序初始化过程是在IopInitializeBootDrivers中完成的,内部调用IopInitializeBuiltinDriver完成实际的初始化工作。原型如下:
NTSTATUS IopInitializeBuiltinDriver(
IN PUNICODE_STRING DriverName,//驱动名称
IN PUNICODE_STRING RegistryPath,//注册表键的路径
IN PDRIVER_INITIALIZE DriverInitializeRoutine,//初始化程序例程
IN PKLDR_DATA_TABLE_ENTRY DriverEntry,//加载参数块中的相应表项
IN BOOLEAN IsFilter,是否为过滤驱动程序,“引导-启动”的驱动程序IsFilter为FALSE
IN PDRIVER_OBJECT *Result //若初始化成功,则执行一个驱动程序对象
)
IopInitializeBuiltinDriver
基本流程如下:
-
根据参数中指定的驱动程序名称,创建一个驱动程序对象,其类型是IoInitSystem 已经注册的IoDriverObjectType
-
初始化该驱动程序对象,设置它的DriverInit为参数中指定的初始化例程
-
将驱动程序对象插入到当前进程(即System 进程)的句柄表中
-
搜索系统的已加载模块列表(全局变量PsLoadedModuleList),找到该驱动程序所在的模块项,并初始化驱动程序对象中与映像模块有关的域
-
将驱动程序的名称复制到驱动程序对象的名称缓冲区中
-
记录下驱动程序注册表键的名称
-
调用驱动程序的初始化函数(DriverEntry)
-
调用IopReadyDeviceObjects,将该驱动程序创建的设备对象设置成已初始化,从而可被其他驱动程序或客户访问
“系统-启动“类型的驱动程序初始化是在IopInitializeSystemDrivers 中完成的,内部调用CmGetSystemDriverList ,获得为SERVICE_SYSTEM_START的”Start“值,对尚未加载的驱动程序逐个调用IopLoadDriver,将其加载到系统地址空间,并执行初始化。
NTSTATUS IopLoadDriver(
IN HANDLE KeyHandle, //驱动程序的注册表键值
IN BOOLEAN CheckForSafeBoot, //是否要检查安全模式
IN BOOLEAN IsFilter,//是否为过滤驱动程序
OUT NTSTATUS *DriverEntryStatus //返回参数
)
IopLoadDriver
基本流程如下:
-
根据参数中指定的注册表键,构造出驱动程序的全路径名
-
调用MmLoadSystemImage,将驱动程序加载到系统地址空间
-
创建一个驱动程序对象,初始化该对象的域
-
将该对象插入到当前进程的句柄表中
-
完成对象成员初始化后,调用驱动程序的初始化函数,即DriverInit,并将驱动程序对象和注册表路径传递进去
IopLoadDriver
和IopInitializeBuiltinDriver 都必须在System 进程中运行。
“
自动-启动
”
类型的启动程序,即注册表中
”
Start
”
值为SERVICE_AUTO_START的驱动程序,由SCM(服务控制管理器,Service Control manager,services.exe 进程)加载,通过NtLoadDriver 来完成。
NTSYSCALLAPI NTSTATUS NTAPI NtLoadDriver (
__in PUNICODE_STRING DriverServiceName //待加载的驱动程序在注册表中的名称
);
如果用户模式调用NtLoadDriver,则检查当前进程是否由加载驱动的特权。
若是System 进程,则直接调用IopLoadUnloadDriver 完成驱动程序初始化。
“
按需-启动
”
类型的驱动程序是通过SCM来加载和初始化的。