Copy and Source Embedded Objects

It's sure nice to have cookies in a cookie jar, but that's not the only place you might want to store them. You might want to move some of them from one container to another. Similarly, if end users can paste an embedded object into a container, they will probably expect to be able to copy or cut those same objects from that container and put them into another container. (It would be nice to copy cookies, huh?) To do this, a container must provide the CFSTR_EMBEDDEDOBJECT and CFSTR_OBJECTDESCRIPTOR formats whenever it is a source of data transfer itself, either for the clipboard or for drag and drop.

It might seem as if you could simply use QueryInterface on the embedded object for its IDataObject and use the result for a data transfer, but this is not a good idea. Instead of copying the object, you are passing a pointer to the real object, which could result in unpredictable things happening to it beyond the control of the container. So you truly need to duplicate the whole object.

This affects Patron in CPage::TransferObjectCreate, which is called whenever we need a data object for some transfer operation. The only modification here is to now call CTenant::CopyEmbeddedObject (after we've copied higher-priority formats), which creates both of the new formats and stuffs them into our transfer object. To create CFSTR_EMBEDDEDOBJECT, we create a temporary compound file (with STGM_DELETEONRELEASE) and save the object into it. If the object is dirty, we call OleSave and then IPersistStorage::SaveCompleted(NULL), which makes a copy but doesn't change the underlying storage that the object itself is accessing. (See Chapter 8.) If the object is clean, we can call IStorage::CopyTo. If that succeeds, we then create CFSTR_OBJECTDESCRIPTOR data using a helper function, INOLE_ObjectDescriptorFromOleObject (in INOLE\HELPERS.CPP).

The details of doing all this are plain to see from the source code, so I won't belabor the point here. With this data, other containers (or our own) can paste or drop a copy of the object that is currently in our container.