Creating an MTP string

In some of our later examples, we'll have to send MTP strings to the device. MTP strings are defined in the MTP spec in section 3.2.3. Briefly, the first byte is the number of Unicode characters to follow (including the NULL terminator), the remaining bytes are the characters.

The conversion is pretty simple and is illustrated below. We'll end up reusing this helper function in our later examples as well.

Helper to create an MTP-style string

 #include <portabledevice.h>
#include <portabledeviceapi.h>
#include <wpdmtpextensions.h>

// Helper to pack a C-string into a MTP string buffer - returns memory
// that must be freed using CoTaskMemFree
HRESULT PackString(LPCWSTR pwszString, BYTE** ppbBuffer, DWORD* pcbBufferSize)
{
    HRESULT hr = S_OK;

    *ppbBuffer = NULL;
    *pcbBufferSize = 0;

    // Get the number of characters plus the NULL terminator
    DWORD dwNumChars = wcslen(pwszString) + 1;

    // Allocate memory for the MTP string 
    // 1 leading byte + 2*number of characters
    DWORD cbBufferSize = 1 + (dwNumChars*2);
    BYTE* pbBuffer = NULL;
    pbBuffer = (BYTE*) CoTaskMemAlloc(cbBufferSize);

    if (pbBuffer == NULL)
    {
        hr = E_OUTOFMEMORY;
    }

    if (hr == S_OK)
    {
        // Set the leading byte
        pbBuffer[0] = (BYTE)dwNumChars;

        // Copy the input string into the buffer
        // The input string is Unicode, so it's safe to copy as-is
        memcpy(pbBuffer + 1, pwszString, cbBufferSize - 1);
    }

    if (hr == S_OK)
    {
        *ppbBuffer = pbBuffer;
        *pcbBufferSize = cbBufferSize;
    }
    else
    {
        CoTaskMemFree(pbBuffer);
    }

    return hr;
}