devconの中身を見る②(cmdListClass)

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

devconで、

devcon listclass <クラス名>

とパラメータを渡して実行したときの処理の中身を追いかけたい。

クラス名とは、devcon classesで取れるクラス名のこと。たとえはMouseなど。

出力例

PS C:\Users\masa\Desktop\Windows-driver-samples-main\Windows-driver-samples-main\setup\devcon\x64\Debug> ./devcon listclass Mouse
Listing 3 devices in setup class "Mouse" (マウスとそのほかのポインティング デバイス).
HID\CRAZYREMOTEHIDDEVICE&COL02\1&2D595CA7&0&0001            : HID 準拠マウス
HID\VID_046D&PID_C52E&MI_01&COL01\8&39B8ABAE&0&0000         : HID 準拠マウス
HID\VID_04F3&PID_0235\6&35218DED&2&0000                     : HID 準拠マウス

該当コード

ここ。

https://github.com/microsoft/Windows-driver-samples/blob/b968cfbed5566a3a9597f5368334beb3b6dad4d2/setup/devcon/cmds.cpp#L112https://github.com/microsoft/Windows-driver-samples/blob/b968cfbed5566a3a9597f5368334beb3b6dad4d2/setup/devcon/cmds.cpp#L188

やってることの流れ

SetupDiClassGuidsFromNameEx

SetupDiClassGuidsFromNameEx()で、ユーザー指定のクラス名(今回は「Mouse」)から、クラスのGUIDを取得する

while(!SetupDiClassGuidsFromNameEx(argv[argIndex],guids,reqGuids,&numGuids,Machine,NULL)) {

https://learn.microsoft.com/ja-jp/windows/win32/api/setupapi/nf-setupapi-setupdiclassguidsfromnameexw

SetupDiGetClassDevsEx

SetupDiGetClassDevsEx()で、指定のクラスのGUIDに含まれるデバイスのためのハンドル(HDEVINFO)を取得する。

devs = SetupDiGetClassDevsEx(&guids[index],NULL,NULL,DIGCF_PRESENT,NULL,Machine,NULL);

https://learn.microsoft.com/ja-jp/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdevsexa

そのハンドルを使って、下でそのクラスに含まれるデバイスの情報を取る。

※今のところ、NULLにしている引数の意味は不明。いろいろいじってみたが、いじるとdevsの戻り値がINVALID_HANDLE_VALUEになってしまったので、上記以外の使い方は不明。

SetupDiEnumDeviceInfo

SetupDiEnumDeviceInfo() の、

  • 第一引数に、SetupDiGetClassDevsEx()で取ったハンドルを渡す
  • 第二引数に、最初0を渡す
  • とやると、第三引数にデバイス情報(SP_DEVINFO_DATA)が載ってくる。
  • 第二引数を++しながら、戻り値が0になるまで繰り返せば、全デバイスの情報が取れる。

但し、今回のdevconの"listclass"コマンドでは、第三引数で取れるデバイス情報は見てなくて、何回デバイスが取れたかのカウントだけをしていた。 第三引数のDWORD DevInstは、CM_Get_DevNode_Status()などの関数に渡すとまた別の情報が取れる。それを(なぜか)ちょっと後ろ↓でやる。(一緒にやったらあかんのか?)

SetupDiClassNameFromGuidEx

devconの中身を見る①(cmdClasses)でやったのと同じ。

SetupDiGetClassDescriptionEx

devconの中身を見る①(cmdClasses)でやったのと同じ。

改めてSetupDiEnumDeviceInfoでデバイス情報(SP_DEVINFO_DATA)をとって、その内容を表示

SetupDiGetDeviceRegistryProperty

上で取った

  • 取りたいプロパティの種類を指定するDWORD値(例えばSPDRP_FRIENDLYNAME)

SetupDiGetDeviceRegistryProperty()に渡して、そのデバイスの欲しい情報を取る。

情報は、戻り値として文字列で帰る。

SetupDiGetDeviceInfoListDetail

上でとったデバイスハンドルを与えて、デバイスの詳細情報(SP_DEVINFO_LIST_DETAIL_DATA)を取る。

詳細情報というが、少なくともローカルPCの情報を取るだけだと、全然情報量多くないっぽい。

詳細情報を取るためというより、この後のCM_Get_Device_ID_Ex の引数に渡すための情報(RemoteMachineHandle)を取るために呼んでる?

CM_Get_Device_ID_Ex

ここで、CM_Get_Device_ID_Ex()の第一引数に、上で取ったSP_DEVINFO_DATAのDevInstを渡して、このデバイスデバイスインスタンスIDを取得する。

SetupDiDestroyDeviceInfoList

SetupDiGetClassDevsEx()でとったハンドルを破棄する。

#以上

これで終わり。

昔から、どういう値なのかが謎だった「デバイスインスタンスID」を取ってる奴が出てきた。

下に書いたが、デバイスインスタンスIDがなんなのか?の説明ページを見つけた。そこを見て、どういう値なのか調べたい。

※デバマネ見たら、デバイスインスタンス「パス」って書いてるけど、listclassで取れる値とこの画面の値が同じだったので、どちらも同じ意味だと思われる...

メモ

クラスは「種類」みたいなもの

1つのクラスの中に、複数のデバイスがある

下記のページに、デバイスマネージャーに出てくる値の説明がありそう!

https://learn.microsoft.com/ja-jp/windows-hardware/drivers/install/device-instance-ids

バイスの名前などは、下記で取れる。

desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_FRIENDLYNAME);
desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_DEVICEDESC);

バイスインスタンスパスは、下記で取れる。

CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)

listclassは、これでとった値を表示してる。

★これのつぎ、「hwids」を調べたい。デバイスIDとはなにか?が気になる