2

SetupAPI を使用して Windows XP で USB デバイスを列挙するコードがあります。

    HDEVINFO hDevInfo = SetupDiGetClassDevs( &_DEVINTERFACE_USB_DEVICE, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

    for (DWORD i = 0; ; ++i)
    {
        SP_DEVINFO_DATA devInfo;
        devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
        BOOL succ = SetupDiEnumDeviceInfo(hDevInfo, i, &devInfo);
        if (GetLastError() == ERROR_NO_MORE_ITEMS)
            break;
        if (!succ) continue;

        DWORD devClassPropRequiredSize = 0;
        succ = SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfo, SPDRP_COMPATIBLEIDS, NULL, NULL, 0, &devClassPropRequiredSize);
        if (!succ)
        {
           // This shouldn't happen!
           continue;
        }
    }

以前は何年も機能していましたが、今でFALSESetupDiGetDeviceRegistryProperty、最後のエラーは「システムコールに渡されたデータ領域が小さすぎます」です。私の呼び出しパラメーターは、この関数のドキュメントに対応しているようです: http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967(v=vs.85).aspx

何が問題なのですか?

4

1 に答える 1

3

問題は元のコードにありました:必要なプロパティが存在しない場合 (またはそのデータが無効な場合、適切なエラー コードを選択するのが面倒な場合)、SetupDiGetDeviceRegistryProperty関数が返されるFALSE(そして最後のエラーを に設定する) 可能性があるため、常にチェックする必要があります。 (そうERROR_INSUFFICIENT_BUFFERERROR_INSUFFICIENT_BUFFERはない)特別なケースとして:

DWORD devClassPropRequiredSize = 0;
succ = SetupDiGetDeviceRegistryProperty(
    hDevInfo,
    &devInfo,
    SPDRP_COMPATIBLEIDS,
    NULL, 
    NULL, 
    0,
    &devClassPropRequiredSize);

if (!succ) {
    if (ERROR_INSUFFICIENT_BUFFER == GetLastError() {
        // I may ignore this property or I may simply
        // go on, required size has been set in devClassPropRequiredSize
        // so next call should work as expected (or fail in a managed way).
    } else {
        continue; // Cannot read property size
    }
}

通常、プロパティのサイズを読み取るときは、このエラーを単に無視することができます (devClassPropRequiredSizeまだゼロの場合は、最大許容長の適切な定数にデフォルト設定できます)。プロパティを読み取ることができない場合、次の呼び出しSetupDiGetDeviceRegistryPropertyは失敗します (そこでエラーを管理します) が、多くの場合、値を読み取ることができ、コードはスムーズに動作します。

于 2014-01-15T09:34:46.497 に答える