释放驱动程序分配的资源
驱动程序如何使用注册表、在其设备扩展、控制器扩展或驱动程序分配的非分页池中设置系统对象和资源的具体细节因驱动程序而异。 但是,任何 Unload 例程都必须分阶段释放驱动程序正在使用的资源。
任何驱动程序的 Unload 例程都必须确保在释放该资源之前,没有其他驱动程序例程当前正在使用或可能很快使用特定资源。
通常, Unload 例程在以下阶段释放所有驱动程序分配的资源:
如果驱动程序尚未这样做,请尽可能在任何物理设备上禁用中断,然后在禁用中断后立即调用 IoDisconnectInterrupt 。
确保没有其他驱动程序例程可以引用 Unload 例程打算释放的资源。
例如,如果当前为特定设备对象启用了驱动程序的 IoTimer 例程,Unload 例程必须调用 IoStopTimer。 它必须确保没有线程正在等待驱动程序的任何调度程序对象,并且其计时器对象在释放其调度程序对象的存储之前不会排队调用其 CustomTimerDpc 例程。 如果具有 ISR 可能已排队的 CustomDpc 例程,则它必须调用 KeRemoveQueueDpc,依此调用。
如果驱动程序调用 了 IoQueueWorkItem,它必须确保工作项已完成。 IoQueueWorkItem 对关联的设备对象进行引用;如果存在任何此类引用,则无法卸载驱动程序。
如果驱动程序名为 PsCreateSystemThread, 则 Unload 例程还必须使驱动程序创建的线程运行,以便线程本身可以在卸载驱动程序之前调用 PsTerminateSystemThread 。 驱动程序无法使用 PsCreateSystemThread 返回的 ThreadHandle 调用 ZwClose 来释放驱动程序创建的系统线程。
释放驱动程序分配的任何特定于设备的资源。 这样做可能涉及调用以下系统支持例程:
如果 DriverEntry 或 Reinitialize 例程名为 IoCreateSymbolicLink 或 IoCreateUnprotectedSymbolicLink,则 IoDeleteSymbolicLink;如果驱动程序调用 IoAssignArcName,则为 IoDeassignArcName。
ExFreePool 如果 DriverEntry 或任何其他名为 ExAllocatePoolWithTag 的驱动程序例程,并且驱动程序尚未释放分配的内存。
如果 DriverEntry 或 Reinitialize 例程名为 MmMapIoSpace,则为 MmUnmapIoSpace。
MmFreeNonCachedMemory 如果 DriverEntry 或 Reinitialize 例程名为 MmAllocateNonCachedMemory。
如果 DriverEntry 或 Reinitialize 例程名为 MmAllocateContiguousMemory,则为 MmFreeContiguousMemory。
如果 DriverEntry 或 Reinitialize 例程名为 AllocateCommonBuffer,则为 FreeCommonBuffer。
IoAssignResources 或 IoReportResourceUsage 如果 DriverEntry 或 Reinitialize 例程调用了其中一个支持例程或 HalAssignSlotResources ,以单独声明配置注册表中的自身和/或其物理设备的硬件资源。
如果 DriverEntry 或 Reinitialize 例程在设备对象的设备扩展或控制器对象的控制器扩展 (创建了一个) ,则释放 DriverEntry 或 Reinitialize 例程设置的系统对象和资源。 具体而言,驱动程序必须先执行以下操作,然后才能尝试删除 IoDeleteDevice (设备对象) 或控制器对象 (IoDeleteController) :
- 调用 IoDisconnectInterrupt 以释放存储在相应设备或控制器扩展中的中断对象指针。
- 调用 ObDereferenceObject ,如果它调用 了 IoGetDeviceObject 并将此指针存储在设备或控制器扩展中,则使用指向下一个较低驱动程序的文件对象的指针。
- 如果 IoDetachDevice 调用 IoAttachDeviceToDeviceStack 并将此指针存储在设备或控制器扩展中,则使用指向较低驱动程序的设备对象的指针调用 IoDetachDevice。
释放 DriverEntry 或 Reinitialize 例程在 \Registry\Machine\Hardware\ResourceMap 树下的注册表中为驱动程序的物理设备(如果有)声明的硬件资源。
删除 DriverEntry 或 Reinitialize 例程存储在 \Registry 下的注册表中的设备的任何名称 。\DeviceMap 树,以及。
驱动程序释放设备、系统和硬件资源后,可以删除其设备和控制器对象,如 释放设备和控制器对象中所述。