CM_Get_Parentは、指定のデバイスのDevInstから、親のデバイスのDevInstを取得する。
CM_Get_Parent関数 (cfgmgr32.h) - Win32 apps | Microsoft Learn
これを使う前に、これまでのAPIなどを使って、いくつか関数を作る。
まず、
ドライブレターからボリュームのデバイスナンバーを取得する関数。
これを使って、
int _tmain(int argc, TCHAR *argv[]){
_tprintf(_T("argc = %d\n"), argc);
if (argc != 2){
_tprintf(_T("error: argc != 2\n"));
return -1;
}
int iDeviceNumber = GetVolumeDeviceNumber(argv[1]);
if (iDeviceNumber != -1){
_tprintf(_T("iDeviceNumber = %d\n"), iDeviceNumber);
}
return 0;
}
とすると、
Dドライブのデバイスナンバーは1Dドライブのデバイスナンバーは1。(DドライブはUSBHDD。)
次に、
デバイスパスからデバイスナンバーを取得するGetDeviceNumberByDevicePath、そしてそれを呼び出すGetVolumeDeviceNumberAndDevInst、こちらはドライブレターからボリュームのデバイスナンバーとDevInstを取得する関数。
int _tmain(int argc, TCHAR *argv[]){
_tprintf(_T("argc = %d\n"), argc);
if (argc != 2){
_tprintf(_T("error: argc != 2\n"));
return -1;
}
DWORD dwDeviceNumber = 0;
DWORD dwDevInst = 0;
BOOL bRet = GetVolumeDeviceNumberAndDevInst(argv[1], dwDeviceNumber, dwDevInst);
if (bRet){
_tprintf(_T("dwDeviceNumber = %d\n"), dwDeviceNumber);
_tprintf(_T("dwDevInst = %d\n"), dwDevInst);
}
return 0;
}
とすると、
Dのデバイスナンバーが1に加えて、DevInstが3だとわかる。Dのデバイスナンバーが1に加えて、DevInstが3だとわかる。
ドライブレターからボリュームのDevInstだけ取得する方法は他にもある。
で、
int _tmain(int argc, TCHAR *argv[]){
_tprintf(_T("argc = %d\n"), argc);
if (argc != 2){
_tprintf(_T("error: argc != 2\n"));
return -1;
}
int iDevInst = GetVolumeDevInst(argv[1]);
if (iDevInst != -1){
_tprintf(_T("iDevInst = %d\n"), iDevInst);
}
return 0;
}
とすると、
こうなるこうなる。
そして実は、ボリュームのデバイスナンバーと、そのボリュームがあるディスクのデバイスナンバーは同一らしい。
デバイスナンバーからディスクのDevInstを取得する関数で、
int _tmain(int argc, TCHAR *argv[]){
_tprintf(_T("argc = %d\n"), argc);
if (argc != 2){
_tprintf(_T("error: argc != 2\n"));
return -1;
}
int iDeviceNumber = 1;
if (iDeviceNumber != -1){
int iDiskDevInst = GetDiskDevInst((DWORD)iDeviceNumber);
if (iDiskDevInst != -1){
_tprintf(_T("iDiskDevInst = %d\n"), iDiskDevInst);
}
}
return 0;
}
これで、
ディスクのDevInstは2。ディスクのDevInstは2。
さて、ここまでやってきたのは、指定のドライブレターのUSBデバイスを取り出すためである。
CM_Request_Device_Eject 実行時に"コンピュータから安全に取り外すことができます。"が表示されない。
上記リンクによると、ディスクのDevInstの親のDevInstに、CM_Request_Device_Ejectを投げればいいらしい。
親のDevInstは、
CM_Get_Parent関数 (cfgmgr32.h) - Win32 apps | Microsoft Learn
CM_Get_Parentで取れる。
CM_Request_Device_Eject 実行時に"コンピュータから安全に取り外すことができます。"が表示されない。
このページのサンプルを動かしたら、ディスクのDevInstは2、親のDevInstは3だとわかった。
"3"ということは、親デバイスはボリュームなのか?
これまでの関数を全部呼び出して、
int _tmain(int argc, TCHAR *argv[]){
_tprintf(_T("argc = %d\n"), argc);
if (argc != 2){
_tprintf(_T("error: argc != 2\n"));
return -1;
}
int iDeviceNumber = GetVolumeDeviceNumber(argv[1]);
if (iDeviceNumber != -1){
_tprintf(_T("iDeviceNumber = %d\n"), iDeviceNumber);
}
DWORD dwDeviceNumber = 0;
DWORD dwDevInst = 0;
BOOL bRet = GetVolumeDeviceNumberAndDevInst(argv[1], dwDeviceNumber, dwDevInst);
if (bRet){
_tprintf(_T("dwDeviceNumber = %d\n"), dwDeviceNumber);
_tprintf(_T("dwDevInst = %d\n"), dwDevInst);
}
int iDevInst = GetVolumeDevInst(argv[1]);
if (iDevInst != -1){
_tprintf(_T("iDevInst = %d\n"), iDevInst);
}
int iDiskDevInst = -1;
if (iDeviceNumber != -1){
iDiskDevInst = GetDiskDevInst((DWORD)iDeviceNumber);
if (iDiskDevInst != -1){
_tprintf(_T("iDiskDevInst = %d\n"), iDiskDevInst);
}
}
DWORD dwDevInstParent;
if (iDiskDevInst != -1){
CM_Get_Parent(&dwDevInstParent, (DWORD)iDiskDevInst, 0);
_tprintf(_T("dwDevInstParent = %lu\n"), dwDevInstParent);
}
return 0;
}
としてみた。
すると、
なんと、ディスクのDevInstは6、親のDevInstは7になった。なんと、ディスクのDevInstは6、親のDevInstは7になった。
いろいろいじってみたら、どうもSetupDiGetClassDevsを使う関数を2回以上呼ぶとこうなってしまう。
そこで、
SetupDiGetClassDevsを1回しか使わない方法でやったら、
親のDevInstが3になった。親のDevInstが3になった。
"3"はボリュームではないのか?
親のデバイスは何なのか?
謎は深まるばかり・・・。
Sample/winapi/CM_Get_Parent/CM_Get_Parent/src/CM_Get_Parent at master · bg1bgst333/Sample · GitHub