If you followed the HCosmo example in the previous sections, you now have a complete basic handler that is fully functional for rendering your object on a variety of displays, without depending on the cache or a local server. Anything else you do now is an added benefit to your handler—like giving it an extra paycheck at the end of the year.
There are many possibilities for improvement. You might want to implement IDataObject::GetData and GetDataHere, for example, to further reduce the need to launch a local server. After all, you already know how to draw your data in the handler, as well as how to save it to an IStorage, so you'd need to add only a bit of code to draw into a metafile or bitmap and to save into a different IStorage. You might think of ways to reduce your dependence on the cache, possibly managing it all yourself. You might consider adding features through a custom interface, given that you have a DLL and can provide a custom interface without the need for marshaling support. These new interfaces can do whatever you like. You can also implement a Play verb in OleObject::DoVerb if your object supports that sort of concept, again greatly improving performance and reducing your need for a server.
But eventually you cross the line. Give the handler too much extra pay and it decides to buy a yacht—for which it has to pay luxury tax. At that point, it ceases to rely on a local server for anything by implementing all of IDataObject and all of IOleObject, thus providing full editing services. The handler is now qualified to be an in-process server. But before it is confirmed as such, there are a number of points to consider.