Platform SDK: Exchange Server

Adding Custom Properties to a Message

Information store providers that need to extend property sets typically implement the IMAPIProp::GetIDsFromNames and IMAPIProp::GetNamesFromIDs methods for message objects. Other interfaces derived from IMAPIProp typically return MAPI_E_NO_SUPPORT for calls to these methods.

Once the property exists, you can use the IMAPIProp::SetProps method to to change its value.

To add custom properties to a message

  1. Open a message by calling IMAPISession::OpenEntry.
  2. Create the custom property using IMAPIProp::GetIDsFromNames, passing an LPMAPINAMEID and the MAPI_CREATE flag. This call allocates a property identifier for each named property not registered in the name-to-identifier mapping table and internally registers the identifier in this table.
  3. Save the property on the message by calling IMAPIProp::SaveChanges or IMessage::SubmitMessage.

The following sample code converts a string to Unicode and searches in the name-to-identifier mapping table for previously registered properties. It creates a custom property if it does not already exist, and returns the property tag of the new property:

    
HRESULT ProptagFromString(
    IN LPMAPIFOLDER lpFolder,
    IN LPSTR lpszPropName,
    IN ULONG ulPropType,
    OUT ULONG *pulPropTag)
{
    HRESULT        hr        = NOERROR;
    MAPINAMEID        nameid        = {0};
    MAPINAMEID        *rgpnameid[1]    = {&nameid};
    WCHAR        rgwch[128]    = {0};
    LPSPropTagArray    lpSPropTags    = NULL;

    // Convert property tag string to Unicode
    MultiByteToWideChar(
        CP_ACP,
        MB_PRECOMPOSED,
        lpszPropName,
        -1,
        rgwch,
        sizeof(rgwch));

    nameid.lpguid = (GUID*)&PS_PUBLIC_STRINGS;
    nameid.ulKind = MNID_STRING;
    nameid.Kind.lpwstrName = rgwch;

    hr = MAPICALL( lpFolder)->GetIDsFromNames( lpFolder,
        1,        // number of property tags to look up
        rgpnameid,
        MAPI_CREATE,
        &lpSPropTagsT);
    if ( FAILED(hr))
    {
        hr = HR_LOG( E_FAIL);
        goto cleanup;
    }

    // Success!
    *pulPropTag = lpSPropTags->aulPropTag[0];
    
     // Change PT_UNSPECIFIED to the type required by the user
    *pulPropTag = PROP_TAG( ulPropType, PROP_ID(*pulPropTag));

cleanup:
    MAPIFREEBUFFER( lpSPropTags);

    RETURN( hr);
}