如何在 Windows 便携式设备中获取图片传输协议事件的参数?
How to get parameters of an Picture Transfer Protocol event in Windows Portable Devices?
我正在尝试支持带有 WPD 的数码相机。我正在进行 request/data/response 通信(PTP 类型 1、2、3),但事件(类型 4)有问题。从事件中我需要一个命令代码(例如 0xc102
)和最多三个整数参数。
我已经注册并正在使用 Microsoft's Portable Devices COM API Sample 的代码接收事件,它很容易捕捉到事件的发生 - 但我无法获取参数.命令代码未直接提供,但作为(假定为随机的)CLSID 的一部分嵌入。
我尝试像解析响应一样使用事件对象的 IPortableDeviceValues
,但是在尝试调用 GetIPortableDevicePropVariantCollectionValue
时 API returns a [= ERROR_NOT_FOUND
的 15=] (0x80070490
)。此调用用于从响应对象获取参数。
我试过了(代码插入CPortableDeviceEventsCallback::OnEvent):
HRESULT hr;
// Try to get all available data from the event:
DWORD pcelt{};
pEventParameters->GetCount(&pcelt);
printf("pEventParameters->GetCount: %d\n", pcelt);
for (unsigned int i = 0; i < pcelt; i++)
{
PROPERTYKEY pk;
PROPVARIANT pv;
pEventParameters->GetAt(i, &pk, &pv);
printf("PARAM %ws %d -> ", (PWSTR)CGuidToString(pk.fmtid), pk.pid);
switch (pv.vt)
{
case VT_UNKNOWN: printf("unknown\n"); break;
case VT_LPWSTR: printf("VT_LPWSTR: %ws\n", pv.pwszVal); break;
case VT_CLSID:
{
// note that OLECHAR is a typedef'd wchar_t
WCHAR szGUID[64] = { 0 };
_GUID guid = *pv.puuid;
(void)StringFromGUID2(guid, szGUID, 64);
printf("VT_CLSID: %ws\n", szGUID);
break;
}
default: printf("not supported vt %d\n", pv.vt); break;
}
}
// PRINTED: pEventParameters->GetCount: 3
// PRINTED: PARAM {15AB1953-F817-4FEF-A921-5676E838F6E0} 3 -> VT_CLSID: {C1020000-5738-4FF2-8445-BE3126691059}
// PRINTED: PARAM {4D545058-EF88-4E4D-95C3-4F327F728A96} 1011 -> VT_IUNKNOWN
// PRINTED: PARAM {15AB1953-F817-4FEF-A921-5676E838F6E0} 2 -> VT_LPWSTR: \?\usb#vid_04da&pid_2382#0000000000000000000xhr1805180002#{6ac27878-a6fa-4155-ba85-f98f491d4f33}
// Try to get response code as if this was response (PTP type 3) - ERROR_NOT_SUPPORTED
DWORD dwResponseCode{};
hr = pEventParameters->GetUnsignedIntegerValue(WPD_PROPERTY_MTP_EXT_RESPONSE_CODE, &dwResponseCode);
assert(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
// Try to get params as if this was response (PTP type 3) - ERROR_NOT_SUPPORTED
CComPtr<IPortableDevicePropVariantCollection> spRespParams;
hr = pEventParameters->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_MTP_EXT_RESPONSE_PARAMS, &spRespParams);
assert(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
我也尝试从中获取 WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID
和 WPD_EVENT_PARAMETER_OBJECT_CREATION_COOKIE
,但它们没有设置。
还有 WPD_EVENT_ATTRIBUTE_OPTIONS
、WPD_EVENT_ATTRIBUTE_NAME
和 WPD_EVENT_ATTRIBUTE_PARAMETERS
- 但我不知道如何找到它们,里面也没有任何有趣的东西。
或者我在 IUNKNOWN
中寻求的是我在 switch
情况下忽略的?但它会是什么类型呢?
数据在那里,我可以在Wireshark+USBPcap和其他PTP应用程序中看到它。
在https://blogs.msdn.microsoft.com/dimeby8/2006/10/06/listening-to-mtp-events/
中找到了答案
它是 IUnknown
,它的类型是 IPortableDevicePropVariantCollection
,GUID 4D545058-EF88-4E4D-95C3-4F327F728A96
。
我正在尝试支持带有 WPD 的数码相机。我正在进行 request/data/response 通信(PTP 类型 1、2、3),但事件(类型 4)有问题。从事件中我需要一个命令代码(例如 0xc102
)和最多三个整数参数。
我已经注册并正在使用 Microsoft's Portable Devices COM API Sample 的代码接收事件,它很容易捕捉到事件的发生 - 但我无法获取参数.命令代码未直接提供,但作为(假定为随机的)CLSID 的一部分嵌入。
我尝试像解析响应一样使用事件对象的 IPortableDeviceValues
,但是在尝试调用 GetIPortableDevicePropVariantCollectionValue
时 API returns a [= ERROR_NOT_FOUND
的 15=] (0x80070490
)。此调用用于从响应对象获取参数。
我试过了(代码插入CPortableDeviceEventsCallback::OnEvent):
HRESULT hr;
// Try to get all available data from the event:
DWORD pcelt{};
pEventParameters->GetCount(&pcelt);
printf("pEventParameters->GetCount: %d\n", pcelt);
for (unsigned int i = 0; i < pcelt; i++)
{
PROPERTYKEY pk;
PROPVARIANT pv;
pEventParameters->GetAt(i, &pk, &pv);
printf("PARAM %ws %d -> ", (PWSTR)CGuidToString(pk.fmtid), pk.pid);
switch (pv.vt)
{
case VT_UNKNOWN: printf("unknown\n"); break;
case VT_LPWSTR: printf("VT_LPWSTR: %ws\n", pv.pwszVal); break;
case VT_CLSID:
{
// note that OLECHAR is a typedef'd wchar_t
WCHAR szGUID[64] = { 0 };
_GUID guid = *pv.puuid;
(void)StringFromGUID2(guid, szGUID, 64);
printf("VT_CLSID: %ws\n", szGUID);
break;
}
default: printf("not supported vt %d\n", pv.vt); break;
}
}
// PRINTED: pEventParameters->GetCount: 3
// PRINTED: PARAM {15AB1953-F817-4FEF-A921-5676E838F6E0} 3 -> VT_CLSID: {C1020000-5738-4FF2-8445-BE3126691059}
// PRINTED: PARAM {4D545058-EF88-4E4D-95C3-4F327F728A96} 1011 -> VT_IUNKNOWN
// PRINTED: PARAM {15AB1953-F817-4FEF-A921-5676E838F6E0} 2 -> VT_LPWSTR: \?\usb#vid_04da&pid_2382#0000000000000000000xhr1805180002#{6ac27878-a6fa-4155-ba85-f98f491d4f33}
// Try to get response code as if this was response (PTP type 3) - ERROR_NOT_SUPPORTED
DWORD dwResponseCode{};
hr = pEventParameters->GetUnsignedIntegerValue(WPD_PROPERTY_MTP_EXT_RESPONSE_CODE, &dwResponseCode);
assert(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
// Try to get params as if this was response (PTP type 3) - ERROR_NOT_SUPPORTED
CComPtr<IPortableDevicePropVariantCollection> spRespParams;
hr = pEventParameters->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_MTP_EXT_RESPONSE_PARAMS, &spRespParams);
assert(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
我也尝试从中获取 WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID
和 WPD_EVENT_PARAMETER_OBJECT_CREATION_COOKIE
,但它们没有设置。
还有 WPD_EVENT_ATTRIBUTE_OPTIONS
、WPD_EVENT_ATTRIBUTE_NAME
和 WPD_EVENT_ATTRIBUTE_PARAMETERS
- 但我不知道如何找到它们,里面也没有任何有趣的东西。
或者我在 IUNKNOWN
中寻求的是我在 switch
情况下忽略的?但它会是什么类型呢?
数据在那里,我可以在Wireshark+USBPcap和其他PTP应用程序中看到它。
在https://blogs.msdn.microsoft.com/dimeby8/2006/10/06/listening-to-mtp-events/
中找到了答案它是 IUnknown
,它的类型是 IPortableDevicePropVariantCollection
,GUID 4D545058-EF88-4E4D-95C3-4F327F728A96
。