前面已经分析了函数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,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,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,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,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,&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,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,(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,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,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,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
#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
#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有两个基本的属性,即MajorFunction和MinorFunction,分别记录IRP的主类型和子类型。操作系统根据MajorFunction决定将IRP分发到哪个派遣例程,然后派遣例程根据MinorFunction进行细分处理。
IRP的概念类似于ReactOS应用程序中“消息”的概念。在ReactOS编程中,程序由“消息”驱动,不同的消息被分发到不同的处理函数中,否则由系统默认处理。
文件I/O的相关函数例如CreateFile、ReadFile、WriteFile、CloseHandle等分别会引发操作系统产生IRP_MJ_CREATE、IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_CLOSE等不同的IRP,这些IRP会被传送到驱动程序的相应派遣例程中。