This is a list of funny behavior found in the IContact APIs. Feel free to add and update as appropriate.
(To avoid accidental markup tags, some _'s are displayed at -'s)
  • IContactProperties
    • CreateArrayNode
      • The fAppend parameter only accepts 1 (TRUE) and 0 (FALSE). This is a stricter interpretation of the BOOL type than is generally used. Using any other value will return E_INVALIDARG.
    • DeleteArrayNode/DeleteProperty
      • These two can generally be used interchangeably. If validation is needed generally checking whether the last character is ']' should be sufficient.
    • GetLabels
      • Returns S-OK with an empty label-set for properties that don't exist in the contact (even ones that don't represent array nodes, like "Notes"). According to documentation (and reasonable expectations) it should return HRESULT-FROM-WIN32(ERROR-PATH-NOT-FOUND). If it matters, check for whether the property exists before requesting its labels.
      • Returns E_FAIL for simple extension array nodes that don't exist in the contact.
    • GetString
      • Returns S-OK for existing simple extension array nodes when there are child values. It's supposed to return S-FALSE, as that's the way to check for an array-node's existence. In addition, the concatenated child values are returned as the result of the GetString call.
    • SetBinary
      • The provided stream must both support Stat and have its Seek pointer set to the beginning of the stream, otherwise the function will return E_UNEXPECTED. This isn't currently documented in the IDL file or on MSDN.
      • The provided stream must also be non-empty.
    • SetString
      • Calls on simple extension array nodes return S-OK. It should return HRESULT-FROM-WIN32(ERROR-INVALID-DATA-TYPE). I haven't checked where it ends up in the backing XML or whether GetString returns the data, callers just shouldn't call SetString this way. The reason for calling this out is that the error code is a fast way of catching the mistake of setting the string on the return value of CreateArrayNode and forgetting to append an L3 property, so clients need to be a bit more proactively aware.
  • Contact's implementation of IPersistStream
    • Load
      • The internal implementation takes a reference to the provided stream via AddRef. It basically assumes that the stream is immutable, so in some circumstances it may reparse the stream. Callers need to be careful not to change it after it's been passed to the Load call. Managed callers need to be careful to respect the AddRef semantics and not dispose of the stream.
    • Save
      • For this call to work right clients need to ensure that the seek pointer of the stream being saved to is at the beginning of the stream and that the starting size of the stream is not larger than the contact data. If the contact is smaller than the original content then the garbage is left at the end and the stream won't contain valid XML.
  • IContactPropertyCollection
    • Next
      • IContactPropertyCollection will sometimes skip over hierarchically stored simple extension properties. The rub of whether it gets skipped or not depends on whether the backing contact is in read-only mode. If the contact instance hasn't modified any data since it was loaded then generally it won't skip these values; otherwise it generally does. The workaround is to reload the contact for the enumeration, but I realize this isn't possible or pragmatic for most uses. A way to work around this is to save the contact to disk somewhere and then load the copy, performing the enumeration on that snapshot. (This is the way some versions of Contacts.Net hide the behavior).
  • Regarding Labels
    • Note that the following is about conventions. The following is not enforced by the APIs, native or managed.
    • Contacts use labels on hierarchical properties to provide additional context about data. For example, a physical address with the label "Personal" would indicate a home address. To avoid situations where a third party program's addition of a label changes the attributes of a property--e.g. adding "Summer House" to the "Personal" address doesn't necessarily make it no longer the home address--additional labels may be required on general properties to prevent ambiguities. This makes more sense with examples:
      • Use the "Voice" label for standard phone numbers. This disambiguates a "Business" phone number from a "Business" "Fax" phone number. Generally "Fax", "Pager", "Voice", "Video", and "TTY" are mutually exclusive and exactly one should be on any phone number.
      • To make a Photo appear as a user tile in programs, add the "UserTile" label.

Last edited Aug 10, 2007 at 8:11 PM by JoeCastro, version 8


No comments yet.