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

Alex Martelli aleaxit at yahoo.com
Sun Sep 9 05:39:09 EDT 2001


Neil Hodgson wrote:
        ...
>> It's not an interpretation, it's the literal text of the COM specs.
>    You are interpreting the text. Nothing is ever read with zero context.

Ah, deconstructionists in our midst -- well, go talk it up with Derrida, 
I've got a girlfriend who's a deconstructionist in her spare time and 
that's quite sufficient to fill my quota of deconst. exposure, you know.

>> > is referring to C++ exceptions rather than SEH or crashing. No COM
        ...
> return error status. It says that error statuses should be returned by
> using HRESULTs rather than throwing excptions because of the lack of
> portability of exceptions between languages and environments.

It says that, in any language and operating system, if your interface hands 
its caller an exception your interface is buggy, period.  In particular 
this applies to Win32 environments (by far the dominant platform for COM 
deployment as it happens) and exceptions of the SEH kind (which are known 
as "signals" on some other platforms, and aren't quite as structured nor as 
handy).

>    There is much source code and quite a few books available which
>    implement
> COM. Can you point to an example that implements COM in a way that is
> compliant with your interpretation of this section?

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.

>    There are several problems with using SEH here - it adds to code bulk,
> obfuscates the code and is not portable. 

Your source code will not be portable to platforms not supporting SEH, 
where you'll have to use signals instead (or whatever the platform gives 
you for graceful handling of errors), but that's not really an issue for 
COM servers.  There is no obfuscation at all in wrapping your code in a 
needed try/except (or __try &c:-), and the "bulk" is about 2 extra lines.

Of course one may use alternative approaches for many typical problems 
(checking a dispid to ensure it's in a range we can handle is, as I 
mentioned, typically 2 machine instructions -- cheap!), but SEH (or other 
ways to handle exceptions and avoid propagating them to the caller) is an 
important safety net for issues we're not specifically checking.

> There is also the question of how
> far do you go? Just having one __try around the method that returns
> E_POINTER is not as explanatory as producing a error info object that

Sure, but the specs don't mandate "being as explanatory as feasible", as 
long as you do diagnose all errors via HRESULT's rather than exceptions.  
So, the tradeoff between speed, convenience, and detailed error info to 
allow client code debugging, is a completely different issue than sticking 
to the specs.

>    The only explanation I can find for "restricted" is that it is not for
> 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
DISP_E_MEMBERNOTFOUND

If you implement your own IDispatch, you don't *have* to give member not 
found for restricted attributes (other HRESULT's might be OK too, at the 
letter of the specs), but it's by far simplest and handiest for client code 
to do so.  In any case, the point is that client code needing to access a 
predefined restricted attribute *cannot* rely on doing so just as it would 
for an unrestricted one -- so your implementation must return HRESULT 
diagnostic to avoid crashing perfectly-correct client code that is probing 
to check if your interface is enumerable, has a default property, etc etc.

>>  Microsoft has not designated any
>> specific *names* duplicating the purposes of the various DISPID_NEWENUM,
>> DISPID_VALUE (the default-property of an Automation object, if any),
>> and so on, which it *has* reserved and designated.
> 
>    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?!  Follow the letter of the 
specification: e.g. if you have a default property, call it however you 
wish, but make sure DISPID_VALUE is the dispid for that property, and avoid 
using DISPID_VALUE for any other attribute; client code wishing to access 
your default property if any *has* to directly use DISPID_VALUE, rather 
than trying to guess at what name you might have chosen.  (Using name Value 
is typical, but nowhere near universal -- e.g. a textlabel control is 
likelier to name its default-property Text or Caption -- it's NOT up to 
client code to try and guess about this, rather, DISPID_VALUE should be 
used directly -- it's as easy as this!).  This implies that perfectly 
correct client code may perfectly well call your Invoke with dispids you do 
not know about, so that having Invoke crash when called with unknown 
dispids is not just an obvious violation of the letter of the COM specs, 
it's also a particularly nasty bug that's quite likely to crash *perfectly 
correct* client code.  How perverse can you get?!


>> In the abstract, you could make a case that a function must not
>> waste effort trying to validate its preconditions -- that's not
>> the function's job.  Meyers is as hot as usual in defending this
>> stance in his PbC materials.
> 
>    I was expecting to be the one that first brought up PbC ;)

Djikstra actually introduced the notion (in "A Discipline for 
Programming"), but not having a marketing knack he didn't give it a catchy 
name (he called it "the weakest precondition approach") nor did he bother 
to "divulge" it.  But it's far more reasonable in Djikstra's context (an 
excellent mathematical approach to provably-correct programming) than in 
everyday practice *except where you control both sides of an interface*, 
which is rarely the case these days (more often than not, you're coding 
your components to the specs of some framework, for reuse and for 
interchangeability, so you are constrained by the framework's specs).

For example, network servers may very well specify preconditions such as 
"this message is no longer than 256 octets" -- but since the clients for 
that interface may be coded separately (and may well have hostile intent), 
the "PbC" approach of "it's not my job to check that my preconditions are 
in fact met" can only lead to security weaknesses and exploits.  For any 
interface that is exposed on the outside of any I-control-it-all subsystem, 
one test the component SHOULD pass is surviving an 'attack' with totally 
random data (and, ideally, also one with data specifically designed to 
probe its weaknesses) -- that IS the world we live in, after all.  Of 
course, we all know server-programmers are not as thorough as they should 
be (and we've all been guilty of imperfect security at some point, I'm 
sure), but that's no reason to _encourage_ such laxity at exposed 
interfaces:-).  One day your component WILL be running with high privileges 
in a very hostile environment (if the component is any good...:-), so, why 
not minimize the vulnerable interfaces it exposes to the outside and be 
properly paranoid about what happens on those interfaces?-)


>    I no longer hang out on COM mailing lists. Is the current consensus in
> agreement with you?

I wouldn't know, really, since my "free" time these days goes to Python, 
.NET, OpenBSD, and Linux, roughly in this order of interest.  COM (and 
Win32 API's, Visual C++, ATL, and other MS'ish stuff, as well as C++ 
language lawyering and so on) is what I do, teach, consult on, and mentor 
on, for a living (while trying to squeeze in as much of my free-time 
interest stuff into the job:-) -- and so much other extremely interesting 
stuff (Haskell and other FP languages, for example) has to stay on the 
shelf for lack of time, that, like you, I've also shelved most active 
participation in public debate of these job-only issues:-).


Alex




More information about the Python-list mailing list