Named MAPI properties - where is the mapping?

Jul 28, 2011 at 9:41 PM

When I retrieve properties from the property bag, there are a number of properties in the range 0x8000 upwards, which are in the "User-defined name-to-ID mapped property" range for MAPI tags. One example is 0x8017 which maps to OutlookInternalVersion; this is particularly vexing because it appears to be mapped to MAPI property 0x819d on an Outlook 10 (Office XP/2002) system. Can I count on these remaining static for all PST files? Or is there some way to associate tag names with these IDs?

Coordinator
Jul 28, 2011 at 10:05 PM

No, you definately can not count on them being static (although they tend to be because of creation order).

Mapping back and forth is what the name_id_map class and the lookup_prop_id/lookup_name_prop helper methods on the PST are for.

Jul 29, 2011 at 10:01 PM
Edited Jul 30, 2011 at 12:49 AM

So I should be able to get the name as follows:

 

pstsdk::name_id_map *gNamedProps;	// pointer to named properties table

// ... deletia ...

        pstsdk::pst myFile(lpstF);
	// have to get property mapping table for pst as well
	gNamedProps = & myFile.get_name_id_map();

// ... deletia ...
int dump_property_bag (const pstsdk::property_bag &bag)
{
	std::vector<pstsdk::prop_id> props = bag.get_prop_list();
	wchar_t wPropFmt[100];

	for(std::vector<pstsdk::prop_id>::iterator i = props.begin(); i != props.end(); ++i) {

		bool bHaveString = false;
		if (gNamedProps->prop_id_exists(*i))	// Special handling: named properties
		{
			pstsdk::named_prop pNamed = gNamedProps->lookup(*i);
			if (pNamed.is_string())
			{
				::StringCchCopyW(wPropFmt, 100, pNamed.get_name().c_str());
				::StringCchCatW(wPropFmt, 100, L":");
				bHaveString = true;
			}
		}

Because it looks at the moment as though every nominally named property is coming up is_string() == false...

Coordinator
Jul 30, 2011 at 11:41 PM

That looks about right. Check the nameid sample, as well.

Named properties are more ID and guid based, rather than string based. So it doesn't surprise me that you're not finding many string ids. If you ran that on a message that came across SMTP into Outlook you should see a ton of string named properties - I think Outlook creates one for each MIME header (at least the header fields that don't directly translate to MAPI props, of which there are a ton I believe).

Aug 4, 2011 at 1:52 AM

Hmm.

So I have a PST that was exported, using Outlook, from an Exchange mailbox. So I have a contact, say. I note that there is a property 0x812B, which by inspection I can see is Business Street Address. If I use another (non-MS) tool to inspect that same entry in the Exchange mailbox, I see that the tag is 0x80a6, BusinessAddressStreet, and the Named Property is id 0x8045, GUID {00062004-0000-0000-c000-000000000064}. Which seems to imply rather strongly that I can't rely on anything. There is nothing I can see that indicates how the MAPI property number gets back-translated to the name, and none of the IDs I have match up to anything else.

Can you point me at a document which will shed some illumination? Because at this point I must confess that I find myself in the dark.

Coordinator
Aug 4, 2011 at 2:31 AM

Named properties are defined by an ID/GUID pair (or String/GUID pair). For any given store, an id/guid pairs maps to some arbitrary property id in the 0x8000 range. Mapping back and forth between id/guid and property id for a given store is a method on the store object. This mapping (which is a global map to the store) is what is visualized by the named prop sample in pstsdk.

When a message is moved between stores (exported, etc), part of the exporting process reads all of the named properties off the message, calls GetIdsFromNames (in MAPI) on the destination store to change their proptag, and then sets those properties with the new property tag on the new store.

So, in theory, any given named property can change the actually MAPI property id when moved between stores. However, Outlook deterministically creates a certain set of named properties everytime it creates a store. It also turns out that the named property creation code in the PST is deterministic - this is why, for a this set of properties, the property id appears to be fixed giving people the false impression that all named properties have a specific MAPI property id associated with them.

Also causing confusion; the name id structure has an "id" field (or a string name field), and MAPI has a concept of basic property tag/ids. These are not the same thing. Perhaps that's whats tripping you up.

See this link.

Does that help?

Aug 4, 2011 at 9:12 PM

So I get an ID from the property bag that turns out to be a named property, and if it is a string I can use the string, but if it is not I have to base the property name on the named property's ID / GUID pair? So the MNID [id 0x8045, GUID {00062004-0000-0000-c000-000000000064}] will always be BusinessAddressStreet for all PSTs? The link that you gave me seems to suggest that. And do I need to compare against both parts of the MNID, or is the property name's ID sufficient -- will 0x8045 always be the ID of the name for the property BusinessAddressStreet?

Coordinator
Aug 4, 2011 at 10:13 PM

You always have to compare both the named ID (or string) and the name GUID. It's the pair that makes a unique named prop.