windowscomwpdptp

How to get parameters of an Picture Transfer Protocol event in Windows Portable Devices?


I'm trying to support a digital camera with WPD. I have working request/data/response communication (PTP types 1,2,3), but have problems with events (type 4). From the event I need a command code (ex. 0xc102) and up to three integer parameters.

I have registered and am receiving events using the code from Microsoft's Portable Devices COM API Sample, and it catches the occurrence of the event easily - but I have no way to get the parameters. The command code is not provided directly, but it is embedded as part of the (supposedly random) CLSID.

I have tried to use the event object's IPortableDeviceValues as I would in parsing a response, but when trying to call GetIPortableDevicePropVariantCollectionValue the API returns a HRESULT of ERROR_NOT_FOUND (0x80070490). This call is used in getting params from the response object.

I tried (code inserted in 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));

I also tried to get WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID and WPD_EVENT_PARAMETER_OBJECT_CREATION_COOKIE from it, but they are not set.

There is also WPD_EVENT_ATTRIBUTE_OPTIONS, WPD_EVENT_ATTRIBUTE_NAME and WPD_EVENT_ATTRIBUTE_PARAMETERS - but I have no idea on how to get to them, nor is there anything of interest inside.

Or maybe what I seek is in the IUNKNOWN that I ignore in the switch case? But what type could it be?

The data is there, I can see it in Wireshark+USBPcap and other PTP applications use it.


Solution

  • Found the answer in https://blogs.msdn.microsoft.com/dimeby8/2006/10/06/listening-to-mtp-events/

    It was the IUnknown, and it's type was IPortableDevicePropVariantCollection with GUID 4D545058-EF88-4E4D-95C3-4F327F728A96.