ドライバーによって割り当てられたリソースの解放
ドライバーによるレジストリの使用方法、システム オブジェクトのセットアップ方法、そのデバイス拡張機能、コントローラー拡張機能、またはドライバーによって割り当てられた非ページ プールのリソースの詳細はドライバーによって異なります。 ただし、どの Unload ルーチンでも、ドライバーが段階的に使用しているリソースを解放する必要があります。
どのドライバーの Unload ルーチンでも、リソースを解放するときは、その前に他のドライバー ルーチンが現在そのリソースを使用していないか、あるいは近々そのリソースを使用する予定がないかを確認する必要があります。
一般に、Unload ルーチンは、次の段階ですべてのドライバー割り当てリソースを解放します。
ドライバーがまだ行っていない場合は、可能であれば、任意の物理デバイスの割り込みを無効にし、割り込みが無効になったらすぐに IoDisconnectInterrupt を呼び出します。
Unload ルーチンで解放される予定のリソースを他のドライバー ルーチンが参照できないことを確認します。
たとえば、ドライバーの IoTimer ルーチンが特定のデバイス オブジェクトに対して現在有効になっている場合、Unload ルーチンは IoStopTimer を呼び出す必要があります。 どのドライバーのディスパッチャー オブジェクトの記憶域を解放するときも、事前に、そのドライバーのディスパッチャー オブジェクトを待機しているスレッドがないことを確認し、そのタイマー オブジェクトが CustomTimerDpc ルーチンの呼び出しのキューに登録されていないことを確認する必要があります。 ISR でキュー待ちになっている可能性がある CustomDpc ルーチンがある場合は、KeRemoveQueueDpc を呼び出す必要があります。
ドライバーが IoQueueWorkItem を呼び出す場合、作業項目が完了していることを確認する必要があります。 IoQueueWorkItem は、関連付けられているデバイス オブジェクトの参照を取り出します。このような参照が残っている場合、ドライバーはアンロードできません。
ドライバーが PsCreateSystemThread を呼び出す場合は、ドライバーがアンロードされる前にスレッド自体が PsTerminateSystemThread を呼び出すことができるように、Unload ルーチンで、ドライバーが作成したスレッドを実行する必要もあります。 ドライバーによって作成されたシステム スレッドは、ZwCloseを、PsCreateSystemThread によって返された ThreadHandle とともに呼び出して、ドライバーで解放することはできません。
ドライバーが割り当てたデバイス固有のリソースをすべて解放します。 これを行うには、以下のシステム サポート ルーチンを呼び出す必要があります。
IoDeleteSymbolicLink: DriverEntry ルーチンまたは Reinitialize ルーチンがIoCreateSymbolicLink または IoCreateUnprotectedSymbolicLink を呼び出した場合。IoDeassignArcName: ドライバーが IoAssignArcName を呼び出した場合。
ExFreePool: DriverEntry または、任意の他のルーチンが ExAllocatePoolWithTag を呼び出しており、割り当てられたメモリをドライバーがまだ解放していない場合。
MmMapIoSpace: DriverEntry ルーチンまたは Reinitialize ルーチンが MmUnmapIoSpace を呼び出したる場合。
MmAllocateNonCachedMemory: DriverEntry ルーチンまたは Reinitialize ルーチンが MmFreeNonCachedMemory を呼び出した場合。
MmAllocateContiguousMemory: DriverEntry ルーチンまたは Reinitialize ルーチンが MmFreeContiguousMemory を呼び出した場合。
FreeCommonBuffer: DriverEntry ルーチンまた はReinitialize ルーチンが AllocateCommonBuffer を呼び出した場合。
IoAssignResources または IoReportResourceUsage: DriverEntry ルーチンまたは Reinitialize ルーチンが、これらサポート ルーチンのどれかひとつまたは HalAssignSlotResources を呼び出して、それ自体または物理デバイス用に個別に構成レジストリ内のハードウェア リソースを要求した場合。
DriverEntry ルーチンまたは Reinitialize ルーチンでデバイス オブジェクトのデバイス拡張またはコントローラー オブジェクトのコントローラー拡張にセットアップしたシステム オブジェクトとリソースを (どれか作成した場合は) 解放します。 特に、ドライバーでは、デバイス オブジェクト (IoDeleteDevice) またはコントローラー オブジェクト (IoDeleteController) の削除を試みる前に、次の操作を行う必要があります。
- IoDisconnectInterrupt を呼び出して、対応するデバイスまたはコントローラー拡張機能に格納されている割り込みオブジェクト ポインターを解放する。
- ドライバーが、IoGetDeviceObjectPointer を呼び出し、このポインターをデバイスまたはコントローラー拡張機能に格納した場合は、次の下位ドライバーのファイル オブジェクトへのポインターで ObDereferenceObject を呼び出します。
- ドライバーが IoAttachDevice または IoAttachDeviceToDeviceStack を呼び出し、デバイスまたはコントローラー拡張機能にこのポインターを格納した場合、下位ドライバーのデバイス オブジェクトへのポインターで IoDetachDevice を呼び出します。
DriverEntry ルーチンまたは Reinitialize ルーチンがドライバーの物理デバイスのために要求したハードウェア リソースが \Registry\Machine\Hardware\ResourceMap ツリーの下にあれば解放します。
DriverEntry ルーチンまたは Reinitialize ルーチンがレジストリで \Registry..\DeviceMap ツリーの下に保存したデバイスの名前を削除します。
ドライバーが、デバイス、システム、およびハードウェア リソースを解放すると、「デバイス オブジェクトとコントローラー オブジェクトの解放」にあるようにドライバーはそのデバイス オブジェクトとコントローラー オブジェクトを削除できます。