WPD API如何检测设备是否为手机?

12

编辑:已请求完整源代码。以下是一个简单的实现,以便复制错误。 内容枚举已被删除,但崩溃仍会在第一个对象调用时发生。在这种情况下,是WPD_DEVICE_OBJECT_ID对象。

CPP链接(错误开始于103行)

QMAKE.PRO链接(我正在使用Qt)


在我的项目中,我使用WPD API读取移动设备的内容。我完全按照API的要求实现了内容枚举。
但是,如果连接了USB驱动器,WPD API有时也会将其检测为设备。我的程序将继续进行内容枚举。我不想这样做。我只想枚举移动设备。
问题是,在内容枚举期间,当我的程序尝试检索USB驱动器上对象的属性时,它会崩溃。以下是崩溃详细信息:
Problem Event Name: BEX
Application Name:   UniversalMC.exe
Application Version:    0.0.0.0
Application Timestamp:  5906a8a3
Fault Module Name:  MSVCR100.dll
Fault Module Version:   10.0.40219.325
Fault Module Timestamp: 4df2be1e
Exception Offset:   0008af3e
Exception Code: c0000417
Exception Data: 00000000
OS Version: 6.1.7601.2.1.0.768.3
Locale ID:  1033
Additional Information 1:   185e
Additional Information 2:   185ef2beb7eb77a8e39d1dada57d0d11
Additional Information 3:   a852
Additional Information 4:   a85222a7fc0721be22726bd2ca6bc946

崩溃发生在这个调用上:

hr = pObjectProperties->GetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, &objectName);

hr返回了“失败”,然后我的程序崩溃了。

经过一些研究,我发现异常代码c0000417意味着发生了缓冲区溢出?如果我错了,请纠正我,这是WPD API中的漏洞吗?如果是,我怎样才能提前检测到这个设备不是移动设备呢?

感谢您的时间!


1
没有看到完整的内容枚举函数,帮助起来会比较困难。请您提供详细信息。 - IsakBosman
@kryptogeek 抱歉耽擱了,我在處理其他事情。我已經創建了一個獨立的C++應用程序來複製問題。如果連接這個特定的TOSHIBA USB驅動器,該程序就會崩潰。如果連接安卓手機,一切運行正常。 - mrg95
2个回答

1

最终我花钱请了人帮忙找出问题所在。

问题是根对象(WPD_DEVICE_OBJECT_ID)无论如何都不会返回对象名称(并非所有设备都是这样)。

解决方法很简单,只需从根对象开始枚举内容,并仅检查其子项的名称。在我的原始实现中,我假设每个对象都有一个名称,但显然并非如此。根对象是例外情况。

以下是代码片段:

CComPtr<IEnumPortableDeviceObjectIDs> pEnumObjectIDs;

// Print the object identifier being used as the parent during enumeration.
//qDebug("%ws\n",pszObjectID);

// Get an IEnumPortableDeviceObjectIDs interface by calling EnumObjects with the
// specified parent object identifier.
hr = pContent->EnumObjects(0,               // Flags are unused
                                   WPD_DEVICE_OBJECT_ID,     // Starting from the passed in object
                                   NULL,            // Filter is unused
                                   &pEnumObjectIDs);

// Enumerate content starting from the "DEVICE" object.
if (SUCCEEDED(hr))
{
    // Loop calling Next() while S_OK is being returned.
    while(hr == S_OK)
    {
        DWORD  cFetched = 0;
        PWSTR  szObjectIDArray[NUM_OBJECTS_TO_REQUEST] = {0};
        hr = pEnumObjectIDs->Next(NUM_OBJECTS_TO_REQUEST,   // Number of objects to request on each NEXT call
                                  szObjectIDArray,          // Array of PWSTR array which will be populated on each NEXT call
                                  &cFetched);               // Number of objects written to the PWSTR array
        if (SUCCEEDED(hr))
        {
            // Traverse the results of the Next() operation and recursively enumerate
            // Remember to free all returned object identifiers using CoTaskMemFree()
            for (DWORD dwIndex = 0; dwIndex < cFetched; dwIndex++)
            {
                //RECURSIVE CONTENT ENUMERATION CONTINUES HERE
                //OBJECT NAME CHECKING CONTINUES IN THE RECURSIVE FUNCTION

                // Free allocated PWSTRs after the recursive enumeration call has completed.
                CoTaskMemFree(szObjectIDArray[dwIndex]);
                szObjectIDArray[dwIndex] = NULL;
            }
        }
    }

}

解决方案与示例项目所展示的完全相同,但是我犯了一个错误,就是检查根对象的名称。所以不要这样做。

0

如果没有“原始文件名”,则获取对象名称

hr = pObjectProperties->GetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, &objectName);

if(FAILED(hr)) {
   hr = pObjectProperties->GetStringValue(WPD_OBJECT_NAME, &objectName);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接