Custom MTP formats in WPD

The list of supported WPD formats is available in MSDN here. But what if your MTP device supports a brand new format that isn't in the supported list? WPD does allow a way to reference custom/vendor extended formats.

If you take a closer look at the GUID values in PortableDevice.h for all those object formats, you might notice a pattern.

 :
DEFINE_GUID(WPD_OBJECT_FORMAT_MP3, 0x30090000, 0xAE6C, 0x4804, 0x98, 0xBA, 0xC5, 0x7B, 0x46, 0x96, 0x5F, 0xE7 );
DEFINE_GUID(WPD_OBJECT_FORMAT_EXIF, 0x38010000, 0xAE6C, 0x4804, 0x98, 0xBA, 0xC5, 0x7B, 0x46, 0x96, 0x5F, 0xE7 );
DEFINE_GUID(WPD_OBJECT_FORMAT_JFIF, 0x38080000, 0xAE6C, 0x4804, 0x98, 0xBA, 0xC5, 0x7B, 0x46, 0x96, 0x5F, 0xE7 );
:

Other than the upper word of the Data1 field, the GUIDs are identical.

Now if you knew your PTP/MTP spec inside-out, you'd realise right-away that Data1 contains the MTP format codes. Appendix A.1 in the MTP spec provides a list of MTP object format codes and sure enough -

 MP3  = 0x3009
EXIF = 0x3801
JFIF = 0x3808

So if you had to represent your custom MTP format code in WPD, simply replace the upper word of Data1 with your MTP format code and that will work.

 HRESULT MtpToWpdFormat(WORD MtpOpCode, GUID* pWpdFormat)
{
    HRESULT hr = S_OK;

    // Return the MTP format code in the upper WORD of Data1
    *pWpdFormat = WPD_OBJECT_FORMAT_UNSPECIFIED;
    pWpdFormat->Data1 = MtpOpCode << 16;

    return hr;
}

You start off with a real WPD format (just so we don't have to fill in the other GUID fields manually). Then we simply update Data1 with the format that we want.

Conversion of a WPD format to MTP is even easier. It's simply WpdFormat.Data1>>16 where WpdFormat is your WPD object format GUID.