COM/CORBA/DCOP (was: Hello people. I have some questions)

Neil Hodgson nhodgson at
Tue Sep 11 01:39:46 CEST 2001

Alex Martelli:

> Visual Basic, no doubt the most widely deployed implementation of COM,
> seems to do fine in this regard (despite having quite a few bugs of its
> own).  Re books, I don't have it at hand to check, but I think Don Box's
> excellent books (Essential COM and Effective COM, the latter with many
> co-authors) may address the issue.

  Here is some code from "Essential COM" (page 388 but there is similar code
throughout the book):

STDMETHODIMP QueryInterface(REFIID riid, void**ppv) {
   if (riid == IID_IUnknown)
      *ppv = static_cast<IUnknown*>(this);

   This will crash if given a bad ppv pointer.

   Not much about exceptions although around page 88 is a discussion on

> >    The only explanation I can find for "restricted" is that it is not
> > use by macro programmers or end users.
> That's the design-intent, yes.  Stopping the name->dispid translation step
> is one good way to implement that design-intent, and it's exactly how the
> system-provided API's implement it.  Make a toy ATL project called resem
> with just one COM object in it, with an interface (sorry if I don't copy
> and paste, but I'm composing this response on a Linux box and the Win box
> next to it isn't networked right now):
>         [object, uuid(...), dual, etc etc]
>         interface IPeep: IDispatch
>         {
>                 [id(1)] HRESULT Avail();
>                 [id(2), restricted] HRESULT Restr();
>         }
> and here's the result when you use it from Python:
> >>> pp=win32com.client.Dispatch('resem.Peep')
> >>> pp.Avail()
> >>> pp.Restr()
> gets error HRESULT -2147352573, aka 0x80020003, aka

   But that isn't the result from calling GetIDsOfNames. If you try this
code (with appropriate adjustment for whatever names you are using):

// COM blowup demonstration program
#include <stdio.h>
#include "Windows.h"
int main(int, char *[]) {
    // Want to see the trace before crashing
    setvbuf(stdout, 0, _IONBF, 0);

    printf("Starting demo\n");
    HRESULT hr =S_OK;

    hr = ::CoInitialize(0);
    if (FAILED(hr)) {
        printf("Failed CoInitialize %x\n", hr);
        return 1;

    CLSID clsid;
    hr = ::CLSIDFromProgID(L"", &clsid);
    if (FAILED(hr)) {
        printf("Failed CLSIDFromProgID %x\n", hr);
        return 1;
    IDispatch *pdisp = 0;
    hr = ::CoCreateInstance(clsid, 0,
        IID_IDispatch, (void**)&pdisp);
    if (FAILED(hr)) {
        printf("Failed CoCreateInstance %x\n", hr);
        return 1;
    DISPID did = 0;
    OLECHAR *name = L"Restr";
    hr = pdisp->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT,
    if (FAILED(hr)) {
        printf("Failed GetIDsOfNames %x\n", hr);
        return 1;
    } else {
        printf("Succeeded GetIDsOfNames dispid = %d\n", did);

   You will see:

Succeeded GetIDsOfNames dispid = 2

   It is likely that Python's code is looking at the TypeInfo so it can do
the right thing as a 'macro programming' high level language.

> >    So you are prepared to not follow the letter of the specification for
> >    the
> > dispatch identifier? (Of course I can argue both sides :-) )
> Absolutely not!  Where are you reading this?!

Identifies the member. Use GetIDsOfNames or the object's documentation to
obtain the dispatch identifier. """


More information about the Python-list mailing list