reactos操作系统实现(83)

前面已经分析了函数IopInitializeSystemDrivers的过程,在这个函数里加载注册表里指定的驱动程序。遍历了所有驱动程序,并通过调用函数IopLoadDriver来实现加载。也许你会问,驱动程序一般什么时候加载呢?其实在ReactOS里有三种情况,一种是在Freeloader引导时,加载内核时一起加载的驱动程序。一种是函数IopInitializeSystemDrivers里根据注册表来加载,最后一种是动态地加载,也即是PnP加载。那么驱动程序到底是什么样的程序呢?其实驱动程序就是一个动态连接库,只不过它只能调用内核的基本函数,而不能调用其它系统的DLL函数。加载一个驱动程序的过程,其实就是把驱动程序读取到内存,然后调用它的入口函数。IopLoadDriver函数的实现代码如下:

#001 static INIT_FUNCTION NTSTATUS

#002 IopLoadDriver(PSERVICE Service)

#003 {

#004 NTSTATUS Status = STATUS_UNSUCCESSFUL;

#005

把正在加载的驱动程序名称显示到屏幕上。

#006 IopDisplayLoadingMessage(Service->ServiceName.Buffer, TRUE);

下面调用函数ZwLoadDriver来加载这个驱动程序。这里要指出的一点,就是ZwLoadDriver函数是一个对外面名称的API函数,其实它就是函数NtLoadDriver

#007 Status = ZwLoadDriver(&Service->RegistryPath);

在引导的LOG文件里写上是否加载成功的消息。

#008 IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE);

#009 if (!NT_SUCCESS(Status))

#010 {

#011 DPRINT("IopLoadDriver() failed (Status %lx)/n", Status);

#012 #if 0

#013 if (Service->ErrorControl == 1)

#014 {

#015 /* Log error */

#016 }

#017 else if (Service->ErrorControl == 2)

#018 {

#019 if (IsLastKnownGood == FALSE)

#020 {

#021 /* Boot last known good configuration */

#022 }

#023 }

#024 else if (Service->ErrorControl == 3)

#025 {

#026 if (IsLastKnownGood == FALSE)

#027 {

#028 /* Boot last known good configuration */

#029 }

#030 else

#031 {

#032 /* BSOD! */

#033 }

#034 }

#035 #endif

#036 }

#037 return Status;

#038 }

从上面的函数可以知道,需要进一步去分析函数NtLoadDriver的代码,才可以继续地深入地了解加载过程,它的代码如下:

#001 NTSTATUS NTAPI

#002 NtLoadDriver(IN PUNICODE_STRING DriverServiceName)

#003 {

#004 UNICODE_STRING CapturedDriverServiceName = { 0, 0, NULL };

#005 KPROCESSOR_MODE PreviousMode;

#006 LOAD_UNLOAD_PARAMS LoadParams;

#007 NTSTATUS Status;

#008

检查是否使用分页特权级。

#009 PAGED_CODE();

#010

获取当前系统的运行模式。

#011 PreviousMode = KeGetPreviousMode();

#012

检查特权级,是否允许加载驱动程序。

#013 /*

#014 * Check security privileges

#015 */

#016

#017 /* FIXME: Uncomment when privileges will be correctly implemented. */

#018 #if 0

#019 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))

#020 {

#021 DPRINT("Privilege not held/n");

#022 return STATUS_PRIVILEGE_NOT_HELD;

#023 }

#024 #endif

#025

获取驱动程序的名称。

#026 Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,

#027 PreviousMode,

#028 DriverServiceName);

#029 if (!NT_SUCCESS(Status))

#030 {

#031 return Status;

#032 }

#033

#034 DPRINT("2009 NtLoadDriver('%wZ')/n", &CapturedDriverServiceName);

#035

#036 LoadParams.ServiceName = &CapturedDriverServiceName;

#037 LoadParams.DriverObject = NULL;

初始化加载驱动程序的事件。

#038 KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);

#039

根据当前进程是否为系统初始化进程来决定调用的方式。

#040 /* Call the load/unload routine, depending on current process */

#041 if (PsGetCurrentProcess() == PsInitialSystemProcess)

#042 {

这里是系统进程调用,直接调用就可以。

#043 /* Just call right away */

#044 DPRINT("NtLoadDriver( IopLoadUnloadDriver )/n");

#045

#046 IopLoadUnloadDriver(&LoadParams);

#047 }

#048 else

#049 {

这是用户模式的进程调用,采用工作消息的方式通知系统进程调用。

#050 /* Load/Unload must be called from system process */

#051 ExInitializeWorkItem(&LoadParams.WorkItem,

#052 (PWORKER_THREAD_ROUTINE)IopLoadUnloadDriver,

#053 (PVOID)&LoadParams);

#054

#055 /* Queue it */

#056 ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);

#057

#058 /* And wait when it completes */

#059 KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode,

#060 FALSE, NULL);

#061 }

#062

#063 ReleaseCapturedUnicodeString(&CapturedDriverServiceName,

#064 PreviousMode);

#065

#066 return LoadParams.Status;

#067 }

#068

接着下来分析函数IopLoadUnloadDriver的代码,如下:

#001 VOID NTAPI

#002 IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)

#003 {

#004 RTL_QUERY_REGISTRY_TABLE QueryTable[3];

#005 UNICODE_STRING ImagePath;

#006 UNICODE_STRING ServiceName;

#007 NTSTATUS Status;

#008 ULONG Type;

#009 PDEVICE_NODE DeviceNode;

#010 PDRIVER_OBJECT DriverObject;

#011 PLDR_DATA_TABLE_ENTRY ModuleObject;

#012 PVOID BaseAddress;

#013 WCHAR *cur;

#014

检查是否卸载驱动程序。

#015 /* Check if it's an unload request */

#016 if (LoadParams->DriverObject)

#017 {

这里是卸载驱动程序。

#018 (*LoadParams->DriverObject->DriverUnload)(LoadParams->DriverObject);

#019

#020 /* Return success and signal the event */

#021 LoadParams->Status = STATUS_SUCCESS;

#022 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#023 return;

#024 }

#025

把驱动程序的路径名称转换为UNICODE字符串。

#026 RtlInitUnicodeString(&ImagePath, NULL);

#027

从注册表的键值里分解出来路径名称。

#028 /*

#029 * Get the service name from the registry key name.

#030 */

#031 ASSERT(LoadParams->ServiceName->Length >= sizeof(WCHAR));

#032

#033 ServiceName = *LoadParams->ServiceName;

#034 cur = LoadParams->ServiceName->Buffer +

#035 (LoadParams->ServiceName->Length / sizeof(WCHAR)) - 1;

#036 while (LoadParams->ServiceName->Buffer != cur)

#037 {

#038 if(*cur == L'//')

#039 {

#040 ServiceName.Buffer = cur + 1;

#041 ServiceName.Length = LoadParams->ServiceName->Length -

#042 (USHORT)((ULONG_PTR)ServiceName.Buffer -

#043 (ULONG_PTR)LoadParams->ServiceName->Buffer);

#044 break;

#045 }

#046 cur--;

#047 }

#048

获取驱动程序的类型。

#049 /*

#050 * Get service type.

#051 */

#052

#053 RtlZeroMemory(&QueryTable, sizeof(QueryTable));

#054

#055 RtlInitUnicodeString(&ImagePath, NULL);

#056

#057 QueryTable[0].Name = L"Type";

#058 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;

#059 QueryTable[0].EntryContext = &Type;

#060

#061 QueryTable[1].Name = L"ImagePath";

#062 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;

#063 QueryTable[1].EntryContext = &ImagePath;

#064

#065 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,

#066 LoadParams->ServiceName->Buffer, QueryTable, NULL, NULL);

#067

#068 if (!NT_SUCCESS(Status))

#069 {

#070 DPRINT("RtlQueryRegistryValues() failed (Status %lx)/n", Status);

#071 ExFreePool(ImagePath.Buffer);

#072 LoadParams->Status = Status;

#073 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#074 return;

#075 }

#076

把驱动程序路径名称进行规格化。

#077 /*

#078 * Normalize the image path for all later processing.

#079 */

#080

#081 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);

#082

#083 if (!NT_SUCCESS(Status))

#084 {

#085 DPRINT("IopNormalizeImagePath() failed (Status %x)/n", Status);

#086 LoadParams->Status = Status;

#087 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#088 return;

#089 }

#090

#091 DPRINT("FullImagePath: '%wZ'/n", &ImagePath);

#092 DPRINT("Type: %lx/n", Type);

#093

创建设备节点。

#094 /*

#095 * Create device node

#096 */

#097

把驱动程序创建的节点保存到IopRootDeviceNode根节点里。

#098 /* Use IopRootDeviceNode for now */

#099 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);

#100

#101 if (!NT_SUCCESS(Status))

#102 {

#103 DPRINT("IopCreateDeviceNode() failed (Status %lx)/n", Status);

#104 LoadParams->Status = Status;

#105 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#106 return;

#107 }

#108

检查这个驱动程序是否已经加载和初始化。

#109 /* Get existing DriverObject pointer (in case the driver has

#110 already been loaded and initialized) */

#111 Status = IopGetDriverObject(

#112 &DriverObject,

#113 &ServiceName,

#114 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||

#115 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */));

#116

#117 if (!NT_SUCCESS(Status))

#118 {

下面调用函数MmLoadSystemImage来加载驱动程序到内存里。

#119 /*

#120 * Load the driver module

#121 */

#122

#123 Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);

#124 if (!NT_SUCCESS(Status) && Status != STATUS_IMAGE_ALREADY_LOADED)

#125 {

#126 DPRINT("MmLoadSystemImage() failed (Status %lx)/n", Status);

#127 IopFreeDeviceNode(DeviceNode);

#128 LoadParams->Status = Status;

#129 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#130 return;

#131 }

#132

加载驱动程序文件成功,就可以给驱动程序节点分配服务的名称。

#133 /*

#134 * Set a service name for the device node

#135 */

#136

#137 RtlCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer);

#138

#139 /*

#140 * Initialize the driver module if it's loaded for the first time

#141 */

#142 if (Status != STATUS_IMAGE_ALREADY_LOADED)

#143 {

加载驱动程序后,首先要对它初始化,这是通过函数IopInitializeDriverModule来实现。

#144 Status = IopInitializeDriverModule(

#145 DeviceNode,

#146 ModuleObject,

#147 &DeviceNode->ServiceName,

#148 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||

#149 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),

#150 &DriverObject);

#151

#152 if (!NT_SUCCESS(Status))

#153 {

#154 DPRINT("IopInitializeDriver() failed (Status %lx)/n", Status);

#155 MmUnloadSystemImage(ModuleObject);

#156 IopFreeDeviceNode(DeviceNode);

#157 LoadParams->Status = Status;

#158 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#159 return;

#160 }

#161 }

#162

保存驱动程序模块对象,以便卸载时使用。

#163 /* Store its DriverSection, so that it could be unloaded */

#164 DriverObject->DriverSection = ModuleObject;

#165 }

#166

初始化驱动程序。

#167 IopInitializeDevice(DeviceNode, DriverObject);

启用驱动程序。

#168 LoadParams->Status = IopStartDevice(DeviceNode);

#169 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);

#170 }

上面可以看到先要调用函数MmLoadSystemImage把驱动程序文件加载到内存,然后调用函数IopInitializeDriverModule来初始化。驱动程序和一般的应用程序是不一样的,它没有作为入口的WinMain函数。与DLL相类似,它向操作系统提供了一个入口函数,叫做DriverEntry的函数,在启动驱动程序的时候,操作系统就调用这个入口。那么ReactOS是怎么样调用这个入口函数的呢?在那里调用的呢?要解开这个谜底,就需要分析函数IopInitializeDriverModule的代码实现了,如下:

#001 NTSTATUS FASTCALL

#002 IopInitializeDriverModule(

#003 IN PDEVICE_NODE DeviceNode,

#004 IN PLDR_DATA_TABLE_ENTRY ModuleObject,

#005 IN PUNICODE_STRING ServiceName,

#006 IN BOOLEAN FileSystemDriver,

#007 OUT PDRIVER_OBJECT *DriverObject)

#008 {

设置服务的键名称。

#009 const WCHAR ServicesKeyName[] = L"//Registry//Machine//System//CurrentControlSet//Services//";

#010 WCHAR NameBuffer[MAX_PATH];

#011 UNICODE_STRING DriverName;

#012 UNICODE_STRING RegistryKey;

#013 PDRIVER_INITIALIZE DriverEntry;

#014 PDRIVER_OBJECT Driver;

#015 PDEVICE_OBJECT DeviceObject;

#016 NTSTATUS Status;

#017

获取驱动程序入口。

#018 DriverEntry = ModuleObject->EntryPoint;

#019

把驱动程序服务名称写到注册表里。

#020 if (ServiceName != NULL && ServiceName->Length != 0)

#021 {

#022 RegistryKey.Length = 0;

#023 RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length;

#024 RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength);

#025 if (RegistryKey.Buffer == NULL)

#026 {

#027 return STATUS_INSUFFICIENT_RESOURCES;

#028 }

#029 RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName);

#030 RtlAppendUnicodeStringToString(&RegistryKey, ServiceName);

#031 }

#032 else

#033 {

#034 RtlInitUnicodeString(&RegistryKey, NULL);

#035 }

#036

创建驱动程序的名称字符串。

#037 /* Create ModuleName string */

#038 if (ServiceName && ServiceName->Length > 0)

#039 {

#040 if (FileSystemDriver == TRUE)

#041 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);

#042 else

#043 wcscpy(NameBuffer, DRIVER_ROOT_NAME);

#044

#045 RtlInitUnicodeString(&DriverName, NameBuffer);

#046 DriverName.MaximumLength = sizeof(NameBuffer);

#047

#048 RtlAppendUnicodeStringToString(&DriverName, ServiceName);

#049

#050 DPRINT("Driver name: '%wZ'/n", &DriverName);

#051 }

#052 else

#053 DriverName.Length = 0;

#054

调用函数IopCreateDriver来创建驱动程序对象。

#055 Status = IopCreateDriver(

#056 DriverName.Length > 0 ? &DriverName : NULL,

#057 DriverEntry,

#058 &RegistryKey,

#059 ModuleObject->DllBase,

#060 ModuleObject->SizeOfImage,

#061 &Driver);

#062 RtlFreeUnicodeString(&RegistryKey);

#063

保存返回的驱动程序对象。

#064 *DriverObject = Driver;

#065 if (!NT_SUCCESS(Status))

#066 {

#067 DPRINT("IopCreateDriver() failed (Status 0x%08lx)/n", Status);

#068 return Status;

#069 }

#070

设置这个驱动程序初始化完成。

#071 /* Set the driver as initialized */

#072 Driver->Flags |= DRVO_INITIALIZED;

#073 DeviceObject = Driver->DeviceObject;

#074 while (DeviceObject)

#075 {

#076 /* Set every device as initialized too */

#077 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

#078 DeviceObject = DeviceObject->NextDevice;

#079 }

#080

重新刷新要初始化的驱动程序。

#081 IopReinitializeDrivers();

#082

#083 return STATUS_SUCCESS;

#084 }

接着来分析函数IopCreateDriver,它是怎么样创建驱动程序对象的,如下:

#001 NTSTATUS

#002 NTAPI

#003 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,

#004 IN PDRIVER_INITIALIZE InitializationFunction,

#005 IN PUNICODE_STRING RegistryPath,

#006 IN PVOID DllBase,

#007 IN ULONG SizeOfImage,

#008 OUT PDRIVER_OBJECT *pDriverObject)

#009 {

#010 WCHAR NameBuffer[100];

#011 USHORT NameLength;

#012 UNICODE_STRING LocalDriverName;

#013 NTSTATUS Status;

#014 OBJECT_ATTRIBUTES ObjectAttributes;

#015 ULONG ObjectSize;

#016 PDRIVER_OBJECT DriverObject;

#017 UNICODE_STRING ServiceKeyName;

#018 HANDLE hDriver;

#019 ULONG i, RetryCount = 0;

#020

#021 try_again:

如果驱动程序没有名称,就需要使用随机时间创建一个名称。

#022 /* First, create a unique name for the driver if we don't have one */

#023 if (!DriverName)

#024 {

#025 /* Create a random name and set up the string*/

#026 NameLength = (USHORT)swprintf(NameBuffer,

#027 L"//Driver//%08u",

#028 KeTickCount);

#029 LocalDriverName.Length = NameLength * sizeof(WCHAR);

#030 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);

#031 LocalDriverName.Buffer = NameBuffer;

#032 }

#033 else

#034 {

#035 /* So we can avoid another code path, use a local var */

#036 LocalDriverName = *DriverName;

#037 }

#038

初始化驱动程序对象的属性。

#039 /* Initialize the Attributes */

#040 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);

#041 InitializeObjectAttributes(&ObjectAttributes,

#042 &LocalDriverName,

#043 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,

#044 NULL,

#045 NULL);

#046

创建驱动程序对象。

#047 /* Create the Object */

#048 Status = ObCreateObject(KernelMode,

#049 IoDriverObjectType,

#050 &ObjectAttributes,

#051 KernelMode,

#052 NULL,

#053 ObjectSize,

#054 0,

#055 0,

#056 (PVOID*)&DriverObject);

#057 if (!NT_SUCCESS(Status)) return Status;

#058

#059 DPRINT("IopCreateDriver(): created DO %p/n", DriverObject);

#060

设置驱动程序对象。

#061 /* Set up the Object */

#062 RtlZeroMemory(DriverObject, ObjectSize);

#063 DriverObject->Type = IO_TYPE_DRIVER;

#064 DriverObject->Size = sizeof(DRIVER_OBJECT);

#065 DriverObject->Flags = DRVO_BUILTIN_DRIVER;

#066 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);

#067 DriverObject->DriverExtension->DriverObject = DriverObject;

这里设置驱动程序入口函数DriverEntry

#068 DriverObject->DriverInit = InitializationFunction;

#069

初始化所有主要调用函数为非法调用的回调函数。

#070 /* Loop all Major Functions */

#071 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)

#072 {

#073 /* Invalidate each function */

#074 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;

#075 }

#076

#077 /* Set up the service key name buffer */

#078 ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool,

#079 LocalDriverName.Length +

#080 sizeof(WCHAR),

#081 TAG_IO);

#082 if (!ServiceKeyName.Buffer)

#083 {

#084 /* Fail */

#085 ObMakeTemporaryObject(DriverObject);

#086 ObDereferenceObject(DriverObject);

#087 return STATUS_INSUFFICIENT_RESOURCES;

#088 }

#089

#090 /* Fill out the key data and copy the buffer */

#091 ServiceKeyName.Length = LocalDriverName.Length;

#092 ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength;

#093 RtlCopyMemory(ServiceKeyName.Buffer,

#094 LocalDriverName.Buffer,

#095 LocalDriverName.Length);

#096

#097 /* Null-terminate it and set it */

#098 ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;

#099 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;

#100

#101 /* Also store it in the Driver Object. This is a bit of a hack. */

#102 RtlCopyMemory(&DriverObject->DriverName,

#103 &ServiceKeyName,

#104 sizeof(UNICODE_STRING));

#105

添加对象到驱动程序管理器。

#106 /* Add the Object and get its handle */

#107 Status = ObInsertObject(DriverObject,

#108 NULL,

#109 FILE_READ_DATA,

#110 0,

#111 NULL,

#112 &hDriver);

#113

如果第一次初始化不成功,就再次尝试初始化。

#114 /* Eliminate small possibility when this function is called more than

#115 once in a row, and KeTickCount doesn't get enough time to change */

#116 if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100))

#117 {

#118 RetryCount++;

#119 goto try_again;

#120 }

#121

#122 if (!NT_SUCCESS(Status)) return Status;

#123

#124 /* Now reference it */

#125 Status = ObReferenceObjectByHandle(hDriver,

#126 0,

#127 IoDriverObjectType,

#128 KernelMode,

#129 (PVOID*)&DriverObject,

#130 NULL);

#131 if (!NT_SUCCESS(Status))

#132 {

#133 /* Fail */

#134 ObMakeTemporaryObject(DriverObject);

#135 ObDereferenceObject(DriverObject);

#136 return Status;

#137 }

#138

#139 /* Close the extra handle */

#140 ZwClose(hDriver);

#141

设置驱动程序硬件信息和驱动程序的文件信息。

#142 DriverObject->HardwareDatabase = &IopHardwareDatabaseKey;

#143 DriverObject->DriverStart = DllBase;

#144 DriverObject->DriverSize = SizeOfImage;

#145

在这里就会调用驱动程序的入口点函数DriverEntry来运行,也就是设置了驱动程序对象里所写的回调函数,达到调用用户编写的程序的目标。

#146 /* Finally, call its init function */

#147 DPRINT("RegistryKey: %wZ/n", RegistryPath);

#148 DPRINT("Calling driver entrypoint at %p/n", InitializationFunction);

#149 Status = (*InitializationFunction)(DriverObject, RegistryPath);

#150 if (!NT_SUCCESS(Status))

#151 {

#152 /* If it didn't work, then kill the object */

#153 DPRINT1("'%wZ' initialization failed, status (0x%08lx)/n", DriverName, Status);

#154 ObMakeTemporaryObject(DriverObject);

#155 ObDereferenceObject(DriverObject);

#156 }

#157 else

#158 {

#159 /* Returns to caller the object */

#160 *pDriverObject = DriverObject;

#161 }

#162

#163 /* Return the Status */

#164 return Status;

#165 }

通过上面的分析,就已经了解驱动程序在那里调用入口函数了。接着下来,驱动程序就需要进一步初始化是否有即插即用的设备,最后开始启动整个设备开始工作了。主要通过函数IopInitializeDevice和函数IopStartDevice来实现的。具体代码如下:

#001 NTSTATUS

#002 FASTCALL

#003 IopInitializeDevice(PDEVICE_NODE DeviceNode,

#004 PDRIVER_OBJECT DriverObject)

#005 {

#006 PDEVICE_OBJECT Fdo;

#007 NTSTATUS Status;

#008

如果没有添加设备功能,就退出。

#009 if (!DriverObject->DriverExtension->AddDevice)

#010 return STATUS_SUCCESS;

#011

这是一个即插即用的驱动程序初始化。

#012 /* This is a Plug and Play driver */

#013 DPRINT("Plug and Play driver found/n");

#014 ASSERT(DeviceNode->PhysicalDeviceObject);

#015

检查这个驱动程序是否以前旧式驱动程序。

#016 /* Check if this plug-and-play driver is used as a legacy one for this device node */

#017 if (IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER))

#018 {

#019 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);

#020 return STATUS_SUCCESS;

#021 }

#022

下面开始调用即插即用的函数AddDevice来添加设备。

#023 DPRINT("Calling %wZ->AddDevice(%wZ)/n",

#024 &DriverObject->DriverName,

#025 &DeviceNode->InstancePath);

#026 Status = DriverObject->DriverExtension->AddDevice(

#027 DriverObject, DeviceNode->PhysicalDeviceObject);

#028 if (!NT_SUCCESS(Status))

#029 {

#030 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);

#031 return Status;

#032 }

#033

检查驱动程序的PDO上面是否有FDO的功能。

#034 /* Check if driver added a FDO above the PDO */

#035 Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);

#036 if (Fdo == DeviceNode->PhysicalDeviceObject)

#037 {

#038 /* FIXME: What do we do? Unload the driver or just disable the device? */

#039 DPRINT1("An FDO was not attached/n");

#040 ObDereferenceObject(Fdo);

#041 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);

#042 return STATUS_UNSUCCESSFUL;

#043 }

#044

检查设备是否有高级电源管理功能ACPI

#045 /* Check if we have a ACPI device (needed for power management) */

#046 if (Fdo->DeviceType == FILE_DEVICE_ACPI)

#047 {

#048 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;

#049

系统电源管理设备创建。

#050 /* There can be only one system power device */

#051 if (!SystemPowerDeviceNodeCreated)

#052 {

#053 PopSystemPowerDeviceNode = DeviceNode;

#054 ObReferenceObject(PopSystemPowerDeviceNode);

#055 SystemPowerDeviceNodeCreated = TRUE;

#056 }

#057 }

#058

添加引用对象。

#059 ObDereferenceObject(Fdo);

#060

#061 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);

#062 IopDeviceNodeSetFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);

#063

#064 return STATUS_SUCCESS;

#065 }

下面来分析启动设备函数IopStartDevice,实现代码如下:

#001 NTSTATUS

#002 IopStartDevice(

#003 PDEVICE_NODE DeviceNode)

#004 {

#005 IO_STATUS_BLOCK IoStatusBlock;

#006 IO_STACK_LOCATION Stack;

#007 ULONG RequiredLength;

#008 NTSTATUS Status;

#009

设置设备节点已经分配资源。

#010 IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);

#011 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack/n");

#012 Stack.Parameters.FilterResourceRequirements.IoResourceRequirementList = DeviceNode->ResourceRequirements;

发送一个IRP包,需要请求分配资源。

#013 Status = IopInitiatePnpIrp(

#014 DeviceNode->PhysicalDeviceObject,

#015 &IoStatusBlock,

#016 IRP_MN_FILTER_RESOURCE_REQUIREMENTS,

#017 &Stack);

#018 if (!NT_SUCCESS(Status) && Status != STATUS_NOT_SUPPORTED)

#019 {

#020 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed/n");

#021 return Status;

#022 }

#023 DeviceNode->ResourceRequirements = Stack.Parameters.FilterResourceRequirements.IoResourceRequirementList;

#024

分配资源。

#025 Status = IopAssignDeviceResources(DeviceNode, &RequiredLength);

#026 if (NT_SUCCESS(Status))

#027 {

#028 Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);

#029 if (NT_SUCCESS(Status))

#030 {

#031 IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);

#032 }

#033 else

#034 {

#035 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)/n", Status);

#036 }

#037 }

#038 else

#039 {

#040 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)/n", Status);

#041 }

#042 IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);

#043

#044 DPRINT("Sending IRP_MN_START_DEVICE to driver/n");

#045 Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList;

#046 Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated;

#047

发送启动设备的IRP消息。

#048 /*

#049 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and

#050 * actually _depend_ on this!. This is because NT will lock the Device Node

#051 * with an ERESOURCE, which of course requires APCs to be disabled.

#052 */

#053 KeEnterCriticalRegion();

#054

#055 //

#056 DPRINT("IopInitiatePnpIrp to driver/n");

#057

#058 Status = IopInitiatePnpIrp(

#059 DeviceNode->PhysicalDeviceObject,

#060 &IoStatusBlock,

#061 IRP_MN_START_DEVICE,

#062 &Stack);

#063

#064 KeLeaveCriticalRegion();

#065

#066 //

#067 DPRINT("IopInitiatePnpIrp to driver NT_SUCCESS/n");

#068

#069

#070 if (!NT_SUCCESS(Status))

#071 {

#072 DPRINT("IopInitiatePnpIrp() failed/n");

#073 }

#074 else

#075 {

#076 if (IopDeviceNodeHasFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY))

#077 {

#078 DPRINT("Device needs enumeration, invalidating bus relations/n");

#079 /* Invalidate device relations synchronously

#080 (otherwise there will be dirty read of DeviceNode) */

#081 IopEnumerateDevice(DeviceNode->PhysicalDeviceObject);

#082 IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);

#083 }

#084 }

#085

#086 if (NT_SUCCESS(Status))

#087 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);

#088

#089 //

#090 DPRINT("IopInitiatePnpIrp to driver Finish/n");

#091

#092 return Status;

#093 }

#094

IRP的全名是I/O Request Package,即输入输出请求包,它是ReactOS内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求,操作系统将相应的I/O请求转换成相应的IRP,不同的IRP会根据类型被分派到不同的派遣例程中进行处理。

IRP有两个基本的属性,即MajorFunctionMinorFunction,分别记录IRP的主类型和子类型。操作系统根据MajorFunction决定将IRP分发到哪个派遣例程,然后派遣例程根据MinorFunction进行细分处理。

IRP的概念类似于ReactOS应用程序中“消息”的概念。在ReactOS编程中,程序由“消息”驱动,不同的消息被分发到不同的处理函数中,否则由系统默认处理。

文件I/O的相关函数例如CreateFileReadFileWriteFileCloseHandle等分别会引发操作系统产生IRP_MJ_CREATEIRP_MJ_READIRP_MJ_WRITEIRP_MJ_CLOSE等不同的IRP,这些IRP会被传送到驱动程序的相应派遣例程中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值