IRP_MN_QUERY_INTERFACE

IRP_MN_QUERY_INTERFACE要求可讓驅動程式將直接呼叫介面匯出至其他驅動程式。

匯出介面的匯流排驅動程式必須針對其子裝置處理此要求, (子 PDO) 。 函式和篩選可以選擇性地處理此要求。

此內容中的「介面」是由驅動程式或一組驅動程式匯出的一或多個常式,以及可能的資料所組成。 介面的結構描述其內容,以及識別其類型的 GUID。

例如,PCMCIA 匯流排驅動程式會匯出類型為 GUID_PCMCIA_INTERFACE_STANDARD 的介面,其中包含作業的常式,例如取得 PCMCIA 記憶卡的寫入保護條件。 這類記憶卡的函式驅動程式可以將 IRP_MN_QUERY_INTERFACE 要求傳送給父 PCMCIA 匯流排驅動程式,以取得 PCMCIA 介面常式的指標。

注意

引進新版的現有介面時,請建立新的 GUID,而不是修改INTERFACE結構的[大小] 或 [版本] 欄位。 如需詳細資訊,請參閱 使用 Driver-Defined 介面

本節描述查詢介面 IRP 做為一般機制。 公開介面的驅動程式應該提供有關其特定介面的其他資訊。

0x08

主要程式碼

IRP_MJ_PNP

傳送時

驅動程式或系統元件會傳送此 IRP,以取得裝置驅動程式所匯出介面的相關資訊。

驅動程式或系統元件會在 IRQL = PASSIVE_LEVEL在任意執行緒內容中傳送此 IRP。

驅動程式在為裝置呼叫驅動程式的 AddDevice 常式之後,隨時都可以接收此 IRP。 當傳送此 IRP (即,您無法假設驅動程式已成功完成裝置 ) IRP_MN_START_DEVICE 要求時啟動。

輸入參數

IO_STACK_LOCATION結構的Parameters.QueryInterface成員本身是一個結構,描述所要求的介面。 結構包含下列資訊:

CONST GUID *InterfaceType;
USHORT Size;
USHORT Version;
PINTERFACE Interface;
PVOID InterfaceSpecificData

結構的成員定義如下:

InterfaceType
指向識別所要求介面的 GUID。 GUID 可以是系統定義的介面,例如GUID_BUS_INTERFACE_STANDARD或自訂介面。 系統定義介面的 GUID 會列在 Wdmguid.h 中。 自訂介面的 GUID 應該使用 Uuidgen 產生。

大小
指定要要求之介面的大小。 處理此 IRP 的驅動程式不得傳回大於Size位元組的INTERFACE結構。

Version
指定要要求之介面的版本。

如果驅動程式支援一個以上的介面版本,驅動程式會傳回最接近的支援版本,而不會超過要求的版本。 傳送 IRP 的元件應該檢查傳回的 Interface.Version 欄位,並根據該值決定要執行的動作。

Interface
指向要在其中傳回所要求介面的結構。 這個結構必須包含 INTERFACE 結構做為其第一個成員。 傳送 IRP 的元件會從分頁記憶體配置此結構。

匯出介面的驅動程式會定義包含 INTERFACE 結構的新結構類型,以及介面中常式和/或資料的成員。 (驅動程式也會定義 介面的 GUID,如上述 InterfaceType 成員所述。)

匯出介面的驅動程式會定義介面中每個常式的執行環境,包括可呼叫常式的 IRQL 等等。

InterfaceSpecificData
指定所要求介面的其他資訊。

對於某些介面,傳送 IRP 的元件會在此欄位中指定其他資訊。 一般而言,此欄位為 Null而 InterfaceTypeVersion 就足以識別所要求的介面。

輸出參數

成功時,驅動程式會填入 Parameters.QueryInterface.Interface 結構的成員。

I/O 狀態欄塊

驅動程式會將 Irp-IoStatus.Status > 設定為STATUS_SUCCESS或適當的錯誤狀態。

成功時,匯流排驅動程式會將 Irp-IoStatus.Information > 設定為零。

如果函式或篩選驅動程式未處理此 IRP,它會呼叫 IoSkipCurrentIrpStackLocation ,並將 IRP 向下傳遞至下一個驅動程式。 這類驅動程式不得修改 Irp-IoStatus.Status > ,且不得完成 IRP。

如果匯流排驅動程式未匯出要求的介面,因此不會處理子 PDO 的這個 IRP,則匯流排驅動程式會將 Irp-IoStatus.Status > 保持原狀,並完成 IRP。

作業

如果參數指定驅動程式支援的介面,驅動程式會處理此 IRP。

如果 IRP 要求驅動程式不支援的介面,則驅動程式不得將此 IRP 排入佇列。 驅動程式必須在其IO_STACK_LOCATION結構中檢查Parameters.QueryInterface.InterfaceType。 如果介面不是驅動程式支援的介面,驅動程式必須將 IRP 傳遞至裝置堆疊中的下一個較低驅動程式,而不會封鎖。

每個介面都必須提供 InterfaceReferenceInterfaceDereference 常式,而且匯出介面的驅動程式必須在 INTERFACE 結構中提供這些常式的位址。 在驅動程式傳回介面以回應 IRP 之前,它必須藉由呼叫其 InterfaceReference 常式來遞增介面的參考計數。 當要求介面的驅動程式使用它完成時,該驅動程式必須藉由呼叫介面的 InterfaceDereference 常式來遞減參考計數。

如果傳送 IRP (驅動程式 x) 的驅動程式稍後會將介面傳遞給另一個驅動程式 (驅動程式 y) ,則驅動程式 x 必須遞增介面的參考計數,而驅動程式 y 必須遞減它。

處理此 IRP 的驅動程式應該避免將 IRP 傳遞至另一個裝置堆疊,以取得要求的介面。 這類設計會在難以管理的裝置堆疊之間建立相依性。 例如,除非第一個堆疊中的適當驅動程式取值介面,否則無法移除第二個裝置堆疊所代表的裝置。

介面可以是匯流排特定或與匯流排無關。 匯流排特定的介面定義在這些匯流排的標頭檔中。 系統會定義與匯流排無關的介面 BUS_INTERFACE_STANDARD,以匯出標準匯流排界面。

如需處理隨插即用次要 IRP的一般規則,請參閱隨插即用

此 IRP 特別用來傳遞裝置分層核心模式驅動程式之間的例行進入點。 請勿將此 IRP 所公開的 介面與裝置介面混淆。 裝置介面主要用於公開裝置的路徑,以供使用者模式元件或其他核心元件使用。 如需裝置介面的詳細資訊,請參閱 裝置介面類別別

傳送此 IRP

如需傳送 IRP 的相關資訊,請參閱 處理 IRP 。 下列步驟特別適用于此 IRP:

  • 從分頁集區配置 INTERFACE 結構,並將其初始化為零。 如果介面將在 IRQL > = DISPATCH_LEVEL呼叫,根據介面合約,呼叫端可以將內容複寫到從非分頁集區配置的記憶體。

  • 在 IRP 的下一個 I/O 堆疊位置中設定值:將 MajorFunction 設定為 IRP_MJ_PNP、將 MinorFunction 設定為 IRP_MN_QUERY_INTERFACE,然後在 Parameters.QueryInterface中設定適當的值。

  • IoStatus.Status 初始化為 STATUS_NOT_SUPPORTED。

  • 不再需要 IRP 和 INTERFACE 結構時,解除配置它們。

  • 使用介面常式和內容參數,如 介面的規格中所述。

  • 當不再需要介面時,使用 InterfaceDereference 常式遞減參考計數。 在取值介面之後,請勿呼叫任何介面常式。

驅動程式通常會將此 IRP 傳送至驅動程式所連接的裝置堆疊頂端。 如果驅動程式將此 IRP 傳送至不同的裝置堆疊,如果另一個裝置不是驅動程式正在維護之裝置的上階,則驅動程式必須在另一部裝置上註冊目標裝置通知。 這類驅動程式會使用EventCategoryTargetDeviceChangeEventCategory呼叫IoRegisterPlugPlayNotification。 當驅動程式收到類型為 GUID_TARGET_DEVICE_QUERY_REMOVE 的通知時,驅動程式必須取值 介面。 如果驅動程式收到後續的GUID_TARGET_DEVICE_REMOVE_CANCELLED通知,驅動程式可以重新查詢介面。

規格需求

標頭

Wdm.h (包括 Wdm.h、Ntddk.h 或 Ntifs.h)

另請參閱

BUS_INTERFACE_STANDARD

介面

IoRegisterPlugPlayNotification