WindowsドライバーSetupDiシリーズの機能



Windows Driver Setupdi Series Functions



記事のディレクトリ

1. SetupDiGetClassDevs

1.1デバイス情報を列挙する

HDEVINFO SetupDiGetClassDevs( _In_opt_ const GUID *ClassGuid, _In_opt_ PCTSTR Enumerator, _In_opt_ HWND hwndParent, _In_ DWORD Flags )

SetupDiGetClassDevs指定したカテゴリまたはすべてのカテゴリにインストールされているすべてのデバイスに関する情報を取得します。

1.2パラメータの説明

ClassGuid :特定のカテゴリGUIDへのポインタ(レジストリにクエリを実行する必要があります)。setDIGCF_ALLCLASSES Markの場合、このパラメータは無視され、すべてのタイプの機器情報テーブルが返されます( ここでのGUIDには、デバイスインストールクラスのGUIDとデバイスインターフェイスクラスのGUIDがあります。 )。



Enumerator :列挙されたコンテンツをフィルタリングします。例:PCIはPCIデバイスのみを表示します。

hwndParent :コレクションメンバーのユーザーインターフェイスを関連付けるために使用されるトップレベルウィンドウのハンドル



Flags :デバイス情報テーブルを確立するための制御オプションは、次の値にすることができます

  • DIGCF_ALLCLASSES最も広い範囲:すべてのデバイスクラスまたはインターフェイスクラスをサポートするデバイス
  • DIGCF_DEVICEINTERFACE:デバイスインターフェイスクラスをサポートするデバイスのみを含める
  • DIGCF_DEFAULT:デフォルトのインターフェースクラスをサポートするデバイスのみを含める
  • DIGCF_PRESENT:現在接続されているデバイス
  • DIGCF_PROFILE:ハードウェアプロファイル内のデバイスは、ハードウェアプロファイル内にあるデバイスに応じて、レジストリキーに移動しますHKLM/SYSTEM/CurrentControlSet/Hardware Profiles/Current/System/CurrentControlSet表示します。

1.3戻り値

成功すると、指定されたパラメーターに一致する、インストールされているすべてのデバイス情報を含むハンドルが返されます。

失敗した場合は戻るINVALID_HANDLE_VALUE



1.4原則

主にfrom HKEY_LOCAL_MACHINESYSTEMCurrentControlSetEnum(インターフェースクラスの場合はpass HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlDeviceClasses Get)すべての情報を列挙し、次にget ClassGUIDを実行し、この値に基づいてパラメーターをフィルター処理します。その中で、ここでは主にさまざまなフラグに基づいており、次にさまざまなレジストリを列挙します。

FlagsがDIGCF_DEVICEINTERFACEから開始HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlDeviceClasses関連情報を読み取るように指定されている場合のみ。

結果をフィルタリングした後、結果をグローバルリンクリストDeviceInfoSet Inに入れます。これは、後続の関数トラバーサル用に提供されます。

2つのカテゴリをトラバースできます。

  1. デバイスセットアップクラス制御オプション
  2. デバイスインターフェイスクラス制御オプション。

この関数によって返される結果情報は次のとおりです。
[、、(img-LhivjTKg-1584015865065)(assets / images / 2019-10-21-16-12-23.png)]

その中にDeviceInfoSet /* HDEVINFO */構造は次のとおりで、次のようにLIST_ENTRY ListHeadリンクDeviceInfoがあります。

struct DeviceInfoSet /* HDEVINFO */ { DWORD magic /* SETUP_DEVICE_INFO_SET_MAGIC */ GUID ClassGuid HKEY HKLM HMACHINE hMachine SP_DEVINSTALL_PARAMS_W InstallParams LIST_ENTRY DriverListHead LIST_ENTRY ListHead //DeviceInfo struct DeviceInfo *SelectedDevice struct ClassInstallParams ClassInstallParams HMODULE hmodClassPropPageProvider PVOID pClassPropPageProvider PCWSTR MachineName WCHAR szData[ANYSIZE_ARRAY] }

DeviceInfo構造情報は次のとおりです。

struct DeviceInfo /* Element of DeviceInfoSet.ListHead */ { LIST_ENTRY ListEntry DEVINST dnDevInst struct DeviceInfoSet *set SP_DEVINSTALL_PARAMS_W InstallParams PCWSTR instanceId PCWSTR UniqueId PCWSTR DeviceDescription GUID ClassGuid DWORD CreationFlags LIST_ENTRY DriverListHead /* List of struct DriverInfoElement */ LIST_ENTRY InterfaceListHead /* List of struct DeviceInterface */ struct ClassInstallParams ClassInstallParams HMODULE hmodDevicePropPageProvider PVOID pDevicePropPageProvider WCHAR Data[ANYSIZE_ARRAY] }

DeviceInterfaceデバイスインターフェイスの構造情報は次のとおりです。

struct DeviceInterface /* Element of DeviceInfo.InterfaceListHead */ { LIST_ENTRY ListEntry struct DeviceInfo *DeviceInfo GUID InterfaceClassGuid DWORD Flags WCHAR SymbolicLink[ANYSIZE_ARRAY] }

SetupDiGetClassDevsデバイス情報のコレクションを取得するには、次の2つのインターフェイスを介して同じ目的を達成できます(実際SetupDiGetClassDevs内部もこの関数を介して達成されます)。

  1. SetupDiCreateDeviceInfoList :デバイスコレクションを作成します。
  2. SetupDiCreateDeviceInfo :デバイス情報を作成します。

2. SetupDiEnumDeviceInfo

2.1列挙メンバー

BOOL SetupDiEnumDeviceInfo( _In_ HDEVINFO DeviceInfoSet, _In_ DWORD MemberIndex, _Out_ PSP_DEVINFO_DATA DeviceInfoData )

SetupDiEnumDeviceInfo指定されたデバイス情報コレクションのメンバーを列挙し、データをPSP_DEVINFO_DATA inに配置します

2.2パラメータの説明

DeviceInfoSet :デバイス情報のコレクションへのハンドルを提供します

MemberIndex :取得するデバイス情報のメンバーシリアル番号を0から指定してください。

DeviceInfoData :direction SP_DEVINFO_DATA構造体へのポインター、指定されたメンバーに関する戻り情報が構造体に配置されます

typedef struct _SP_DEVINFO_DATA { DWORD cbSize GUID ClassGuid DWORD DevInst ULONG_PTR Reserved } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA

2.3戻り値

成功した場合はTrueを返し、そうでない場合はFalseを返します。

すべてのデバイス情報メンバーを列挙する場合、ローダーは最初にMemberIndex呼び出しに0に設定SetupDiEnumDeviceInfo、次にインクリメントMemberIndex(forループを使用)、呼び出しSetupDiEnumDeviceInfoすべてのメンバーがトラバースされるまで(この時点で関数はFalseを返し、GetLastError return ERROR_NO_MORE_ITEMS)。

2.4原則

列挙DeviceInfoSetリンクリスト内の要素。

画像

3.SetupDiEnumDeviceInterfaces

3.1列挙型インターフェース

上記の関数は、「デバイス情報コレクション」内のデバイスを列挙するために使用されます。これに対応して、コレクション内のデバイスインターフェイスを列挙する機能があります。

WINSETUPAPI BOOL WINAPI SetupDiEnumDeviceInterfaces( IN HDEVINFO DeviceInfoSet, // Device information collection IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL// Device member IN LPGUID InterfaceClassGuid, // Interface GUID IN DWORD MemberIndex, // Index of the interface in the collection OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData// Returned interface information )

DeviceInfoSet「デバイス情報収集」変数、つまりSetupDiGetClassDevs呼び出しの戻り値です。

DeviceInfoData値を設定する人はほとんどいませんが、この値を設定すると、コレクション内のDeviceInfoDataに含まれているデバイスインターフェイスクラスのみが関数の列挙中に列挙されます。たとえば、DeviceInfoData表示されるデバイスは、GUID1とGUID2の2つのデバイスインターフェイスクラスをサポートし、関数は、他のデバイスに関係なく、コレクション内のこれら2つのデバイスインターフェイスのみを検索します。

この関数はデバイスインターフェイスを取得するために使用され、同じデバイス内の一連の設定には複数のデバイスインターフェイスクラスを含めることができるため、 パラメータInterfaceClassGuidデバイスインターフェイスGUIDを設定するために使用

MemberIndex意味は以前と同じです。呼び出しの初期値を0に設定し、MemberIndex値が設定範囲を超えるまで呼び出しを繰り返して、SetupDiEnumDeviceInterfaces FALSEを返して増分ループを終了する必要があります。

DeviceInterfaceDataデバイスインターフェイス情報はに返されます。

typedef struct _SP_DEVICE_INTERFACE_DATA { DWORD cbSize GUID InterfaceClassGuid DWORD Flags ULONG_PTR Reserved } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA

3.2インターフェースデータの取得

BOOL SetupDiGetDeviceInterfaceDetail( _In_ HDEVINFO DeviceInfoSet, _In_ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, _Out_opt_ PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, _In_ DWORD DeviceInterfaceDetailDataSize, _Out_opt_ PDWORD RequiredSize, _Out_opt_ PSP_DEVINFO_DATA DeviceInfoData ) typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { DWORD cbSize TCHAR DevicePath[ANYSIZE_ARRAY] } SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA

4. SetupDiGetDeviceRegistryProperty

4.1デバイスのプロパティ

BOOL SetupDiGetDeviceRegistryProperty( _In_ HDEVINFO DeviceInfoSet, _In_ PSP_DEVINFO_DATA DeviceInfoData, _In_ DWORD Property, _Out_opt_ PDWORD PropertyRegDataType, _Out_opt_ PBYTE PropertyBuffer, _In_ DWORD PropertyBufferSize, _Out_opt_ PDWORD RequiredSize )

SetupDiGetDeviceRegistryProperty :この関数は、指定されたプラグアンドプレイデバイスの特性を取得するために使用されます(この関数は、主にSystem CurrentControlSet Enumレジストリを使用して関連するハードウェア情報を照会します)

4.2パラメータの説明

DeviceInfoSet :デバイス情報ハンドル。

DeviceInfoDataSP_DEVINFO_DATA構造、含むDeviceInfoSetデバイス情報

Property次の値を取ります。

  • SPDRP_ADDRESS :デバイスのアドレスを照会します
  • SPDRP_BUSNUMBER :デバイスのバス番号を照会します
  • SPDRP_BUSTYPEGUID :デバイスのGUID番号を照会します
  • ……

4.3備考

この機能の主な原則は、レジストリからPnPデバイスの属性を読み取ることです。

5. SetupDiDestroyDeviceInfoList

5.1破壊

SetupDiDestroyDeviceInfoListデバイス情報のコレクションを破棄し、関連するすべてのメモリを解放します

BOOL SetupDiDestroyDeviceInfoList( HDEVINFO DeviceInfoSet )

5.2パラメータ

DeviceInfoSet :リリースされるデバイス情報ハンドル

5.3戻り値

成功した場合はゼロ以外を返し、それ以外の場合はゼロを返します

6.全体の原則

  1. レジストリHKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlClass{4d36e97d-e325-11ce-bfc1-08002be10318}デバイスインストールクラスの列挙情報を取得します。
  2. インスタンスを介してインスタンスIDを取得します。
  3. 入手HKEY_LOCAL_MACHINESYSTEMCurrentControlSetEnum以下の機器関連情報。
  4. HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlClass:現在のデバイスタイプを表す、デバイスインストールカテゴリのGUIDです。
  5. HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlDeviceClasses:デバイスインターフェイスGUID
  6. レジストリを介してHKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlDeviceClassesデバイスインターフェイスの列挙情報を取得します。

6.1デバイスインターフェイスクラス

あらゆる種類のドライバーは、ユーザーまたは他のユーザーに特定の種類の名前を提供する必要があります。また、ユーザーはこの名前を使用して、さまざまなデバイスを区別し、それらを使用してIOを実行します。

Windows NT 4.0以前のバージョンでは、 ドライバは、デバイスオブジェクトの名前を作成し、そのデバイスコネクタを作成して、システムに登録します。

Windows 2000以降、ドライバはデバイスオブジェクトに名前を付けなくなりましたが、デバイスインターフェイスクラスを使用します。 デバイスインターフェイスクラスは、ユーザーにデバイスおよびドライバー機能へのアクセスを提供できます。ドライバーはデバイスインターフェイスクラスを登録し、デバイスオブジェクトのデバイスインターフェイスクラスのインスタンスを作成します

各デバイスインターフェイスクラスにはGUIDがあります。システムは、共通のデバイスクラスとそのGUIDをデバイス固有のヘッダーファイルで定義します。ただし、デバイス開発者はデバイスクラスをカスタマイズできます。

たとえば、3つの異なるタイプのマウスは、それぞれUSBポート、シリアルポート、および赤外線ポートを使用している場合でも、同じデバイスインターフェイスクラスに属することができます。彼らのドライバーは彼をGUID_DEVINTERFACE_MOUSEデバイスインターフェイスクラスとして登録しました。このデバイスインターフェイスクラスのGUIDは、Ntddmou.hで定義されています。

特に、これらのドライバーは1つのデバイスクラスのみを登録します。ただし、さまざまなデバイスのドライバには、標準のインターフェイスクラス以外のインターフェイスクラスを登録するための特別な機能があります。たとえば、インストール可能なディスクドライバを登録する必要があります(GUID_DEVINTERFACE_DISK)インターフェイスクラスおよび(MOUNTDEV_MOUNTED_DEVICE_GUID)インストール可能な機器カテゴリ。

ドライバーがデバイスインターフェイスのインスタンスを登録すると、IOマネージャーはデバイスのGUIDとシンボリックリンク名をデバイスインターフェイスに関連付けます。シンボリックリンク名はレジストリに保存され、システムの起動時に存在します。ユーザーは、このインターフェイスにクエリを実行して、このインターフェイスをサポートするデバイスのシンボリックリンク名を取得できます。ユーザーは、このシンボリックリンク名を使用して、デバイスでIOを実行できます。

6.2機器の設置

デバイスのインストールを容易にするために、同じインストール方法のデバイスは同じデバイスインストールカテゴリに分類されます。たとえば、SCSIメディア変換デバイスは、MediumChangerデバイスセットアップクラスに分類されます。デバイスインストールクラスは、デバイスインストールプロセス中のデバイスインストールを定義します。プログラムとその関連プログラムで使用されるクラス。

Microsoftは、ほとんどのデバイスの標準機器インストールクラスを定義しています。デバイス開発者は機器の設置クラスをカスタマイズできますが、標準の機器の設置クラスを使用できない場合に備えておく必要があります。

各デバイスインストールクラスにはGUIDがあり、システムはDevguid.hで各デバイスインストールクラスのGUIDを提供し、対応するシンボリックリンク名を提供します。

機器設置クラスは、独自の機器用に定義されています..CurrentControlSetControlClassClassGuid次のサブキー。

開発者は、INFファイルを使用して新しいデバイスインストールクラスを作成できます。

6.3デバイスインターフェースクラスの登録

NTSTATUS IoRegisterDeviceInterface( IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName )

InterfaceClassGuidこれはインターフェースクラスのGUIDを指定します。新しいGUIDが指定されると、次のように、デバイスインターフェイスクラスレジストリに新しいエントリが生成されます。

DEFINE_GUID(IOM_RING_INTERFACE, 0xfdcac3d6, 0xe85f, 0x4f22, 0xa2, 0x3c, 0x75, 0xe2, 0xbd, 0xef, 0x7f, 0x62) nStatus = IoRegisterDeviceInterface(PhysicalDeviceObject, &IOM_RING_INTERFACE, NULL, &pDeviceExtension->InterfaceName)

次に、生成されたレジストリキーはHKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlDeviceClasses{fdcac3d6-e85f-4f22-a23c-75e2bdef7f62}です。

7.例

仕事用に開くことができるUSBのデバイスインターフェイスを照会するコードは次のとおりです。

DEFINE_GUID (UsbClassGuid, 0xa5dcbf10L, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed) int _tmain(int argc, _TCHAR* argv[]) { HDEVINFO hDevInfo SP_DEVICE_INTERFACE_DATA spDevData PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail BOOL bRes = TRUE int nCount = 0 hDevInfo = ::SetupDiGetClassDevs(NULL,NULL,NULL,DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE | DIGCF_PRESENT) if (hDevInfo != INVALID_HANDLE_VALUE) { pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT,1024) pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) while (bRes) { spDevData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA) bRes = ::SetupDiEnumDeviceInterfaces(hDevInfo,NULL,(LPGUID)&UsbClassGuid,nCount,&spDevData) if (bRes) { bRes = ::SetupDiGetInterfaceDeviceDetail(hDevInfo,&spDevData,pDetail,1024,NULL,NULL) if (bRes) { wcout << L'success : ' << pDetail->DevicePath << endl nCount ++ } } } ::GlobalFree(pDetail) ::SetupDiDestroyDeviceInfoList(hDevInfo) } return 0 }

このコードの戻り結果は次のとおりです。

success : \?usb#vid_24ae&pid_1813#5&262ed807&1&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed} success : \?usb#vid_0bda&pid_58dd#200901010001#{a5dcbf10-6530-11d2-901f-00c04fb951ed}