I've been working with compartments recently, and I've run across a few 'features' that tripped me up.  I figure if I've run across them, others have too.

Although MSDN says that you can put integers, BSTRs, and interface pointers into a compartment, you can not store interface pointers or strings into a global compartment (that you get from ITfThreadMgr::GetGlobalCompartment).  You can only store integers and empty variants.

Side note:  I would be very cautious about storing interface pointers into a (local) compartment, as well.  If an application has multiple UI threads (e.g., Explorer), TSF will load multiple instances of the text service (one instance per thread).  When each instance retrieves the interface pointer from an event sink and tries to call it, the interface pointer is properly marshalled across the apartment boundaries (COM marshals the IUnknown in the variant returned from ITfCompartment::GetValue), but you do have a proxy in the way, and calls across the interface pointer will be quite slow.