4

ユーザーが複数のUSBハブを使用してコンピューターに大量に接続したい場合があるデバイスを製造および販売しています。これは、ヒューマンインターフェイス(HID)とマスストレージ(MSD)の両方のインターフェイスを備えたUSB複合デバイスです。Windowsは、「Z:」の文字がなくなるまで、各デバイスのファイルシステムを自動的にマウントします。

PnP Configuration Managerデバイスインストール機能の組み合わせを使用して、デバイスツリーをたどり、HIDおよびUSBSTORインターフェイスのデバイスインスタンス識別子を取得できます。USBストレージデバイスのパスを使用して、ディスク番号(つまり\\.\PhysicalDrive1)も取得できます。

次のステップは、デバイスと通信するときにドライブ文字を循環させて、必要に応じてこれらのディスクをマウントすることです。さらに、C:ドライブの一時ディレクトリにマウントすることをお勧めします。このタスクにDefineDosDeviceを使用しようとすると問題が発生し、デバイスがマウントされるまでボリュームGUIDがないため、 SetVolumeMountPointで前進できません。それは鶏が先か卵が先かという問題を引き起こします。

私たちの顧客だけがunixを使用した場合!!!

4

2 に答える 2

8

Windows はディスクをマウントしません。ボリュームをマウントします。ただし、USBSTOR クラス デバイスのボリュームは、デバイス ツリーの子ノードとして表示されません。したがって、すべてのボリュームを列挙し、一連の文字列操作と比較を行って、STORAGE\VOLUME ノードと USBSTOR ノードを一致させる必要があります。

すべてのボリューム GUID 値は、関数のFindFirstVolumeセットで列挙されます。先頭の「\.\」と末尾の「\」文字を削除して、結果の文字列をQueryDosDeviceに渡すことができます。これにより、デバイス名が提供されます。

次に、GUID_DEVINTERFACE_VOLUME とSetupDiGetClassDevsおよびその仲間を使用して、すべてのボリュームを列挙する必要があります。IOCTL_STORAGE_GET_DEVICE_NUMBERを使用して、各ボリュームのデバイス タイプと数を探している USBSTOR デバイスと比較します。それらが一致したら、ボリュームからデバイス名を取得し、それをデバイス名の他のリストと比較して、ボリューム GUID を見つけることができます。

最後に、ボリューム GUID はSetVolumeMountPointで正常に使用できます。

私の質問へのコメントで非常に有益な支援をしてくれたゲイブに感謝します。


コード スニペット

デバイス パスからデバイス タイプと番号を取得します。

STORAGE_DEVICE_NUMBER sdn;
HANDLE handle = CreateFile(devInterfaceDetail->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL);
DWORD len = 0;
DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof (sdn), &len, NULL);

すべてのボリューム インターフェイスを反復処理し、上記のスニペットのディスク番号を比較して、対応する USBSTOR インスタンスのデバイス名を見つけます。

std::string deviceName;
HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA devInterface = { 0 };
devInterface.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
for (int i = 0; SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &GUID_DEVINTERFACE_VOLUME, i, &devInterface); ++i) {
    SP_DEVINFO_DATA devInfoData = { 0 };
    devInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
    DWORD len;
    SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, NULL, 0, &len, &devInfoData);
    std::vector<char> buf(len);
    SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA *) &buf[0];
    devInterfaceDetail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
    if (SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, devInterfaceDetail, len, NULL, &devInfoData)) {
        if (DEVICE_NUMBER == this->getDeviceNumber(devInterfaceDetail->DevicePath)) {
            std::vector<BYTE> buf(MAX_PATH + 1);
            DWORD type, len;
            if (SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &type, &buf[0], buf.size(), &len)) {
                deviceName.assign(buf.begin(), buf.begin() + len);
                break;
            }
        }
    }
}
于 2010-09-24T21:17:44.173 に答える
0

を使用する必要があるようIOCTL_MOUNTMGR_CREATE_POINTです。残念ながら、使用されるほとんどの例IOCTL_MOUNTMGR_XXXはカーネル モード ドライバー用に記述されていますが、必須ではありません。おそらく私の古い答え(を使用IOCTL_MOUNTMGR_QUERY_POINTS)と別の答えがこれを行うのに役立ちます。http://msdn.microsoft.com/en-us/library/ff567603.aspxおよびhttp://support.microsoft.com/kb/836662も参照してください。

使用方法をよりよく理解した後、 SetVolumeMountPointIOCTL_MOUNTMGR_CREATE_POINTに関する問題を解決できるようになる可能性があります。

于 2010-09-27T00:05:10.527 に答える