on getting IOleCommandTarget wrong (and a bit in the middle about ActiveX controls)

IOleCommandTarget is very useful.  It provides a generic way of sending commands between objects.  IE makes extensive use of IOleCommandTarget, both publically and internally.  And, like IUnknown, people frequently get it wrong.

Each command is composed of a GUID (Command Group Identifier) and a DWORD (Command Identifier). 

First, what is wrong with this code:

HRESULT CFoo::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
   if (IsEqualGUID(CGID_FooCommands, *pguidCmdGroup))

The answer is obvious: pguidCmdGroup might be NULL and you crash.  Furthermore, pguidCmdGroup is frequently NULL, since NULL is how you specify the standard group

You might say to yourself, “Self, I don’t need to worry about NULL, since I am the only consumer of this particular implementation,”  and that may be the case.  However, if you can be CoCreate()’ed, than it is definitively not the case.  Remember, any control on your machine can be instantiated as an ActiveX control.  During the ActiveX control instantiation process, mshtml will query your object for certain well-known interfaces, like IObjectSafety, IOleObject, and, you guessed it, IOleCommandTarget.  If your control responds to IOleCommandTarget, mshtml will attempt to Exec() standard commands.  If you do not guard for NULL, you will cause Internet Explorer (and other hosts) to crash.

The second set of common errors come in the form of returning incorrect error codes.  The documentation outlines the rules and you must be careful to implement them.  If you recognize the group but not the command, OLECMDERR_E_NOTSUPPORTED is the correct return value.  If you do not recognize the group, OLECMDERR_E_UNKNOWNGROUP is correct.  There is a special case though, which is when the group is NULL and the command is not supported; in this case the correct return value is OLECMDERR_E_NOTSUPPORTED.

Comments (7)

  1. PatriotB says:

    IOleCommandTarget is interesting, but the documentation of the standard commands (OLECMDID) is sorely lacking–what arguments does the command take, who sends it to whom, etc.  Also, some of the "internal" command groups (e.g. CGID_ShellDocView and friends) are "mentioned" documented (see the "WebBrowser Customization" article on MSDN)… it would be great if this info could be fleshed out more.

  2. LMHP says:


    Can u elaborte how the Exec must be implemented along with the essentials for the QueryStatus.I guess i am suggeting a huge task.ok,.explain how this interface muat be done for invoking some task when a custom toolbar button is pressed. The button is something like the Mail button on IE.

    Can u give a safe procedure to do this?



  3. jeffdav says:

    I was planning on doing a whole series of posts around this topic, so I’m glad there is interest.  I agree that the documentation is a bit lacking in places; I will endevour to speed the process.