Is COM aggregation by an external object meant to work?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Is COM aggregation by an external object meant to work?

Antony Blakey-4
Apologoies if this isn't a question for this NG i.e. if D4->D5 hasn't
changed this mechanism. I'm due to release a product on the 26th. Time
is tight and I sure hope D5 goes gold before then :) Risky, I know!

I have an object implementing IInternetProtocol (i.e. Pluggable Protocol
Handlers for IE) that's being aggregated into an external OS supplied
object. COMObjectStub sees a QI for that IID which it delegates to its
OuterUnknown, but the innerQI never gets called, and Dolphin dies with a
native stack overflow in URLMon, which could be an aggregate problem.
I'd expect to NOT see a call for that interface on the delegating QI,
but rather only the inner non-delegating QI, because I'm not exposing my
object except via the external aggregation. I have instrumented all the
inner and outer QIs in COMObjectStub and that's the only request for
that IID. My ability to track this down is compromised because I can't
cross into the VM, to see if the last param to CoCreateInstance is being
used to return a non-delegating IUnknown.

So the nub is: is this known, definitively, to work (in D5) for other
cases where a non-ST object aggregates an ST object? I've been chasing
this for the last 12 hours, so I thought I'd better check.

-------------------------
Antony Blakey
mailto:[hidden email]
Linkuistics Pty Ltd
Adelaide, South Australia


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work?

Blair McGlashan
"Antony Blakey" <[hidden email]> wrote in message
news:[hidden email]...
> Apologoies if this isn't a question for this NG i.e. if D4->D5 hasn't
> changed this mechanism. I'm due to release a product on the 26th. Time
> is tight and I sure hope D5 goes gold before then :) Risky, I know!

We are aiming to ship a release candidate before Smalltalk Solutions (i.e.
by the end of this week). This should be very close to the final product. We
really had hoped to ship the product before then, but despite a lot of hard
work we have not been able to get it done. I'm sure we can come to some
arrangement to supply you with a non-expiring key to meet your product
deadline, e.g. if you have recently purchased D4 then you would be entitled
to a free upgrade to D5 in which case we would gladly send you a full D5
key.

>
> I have an object implementing IInternetProtocol (i.e. Pluggable Protocol
> Handlers for IE) that's being aggregated into an external OS supplied
> object. COMObjectStub sees a QI for that IID which it delegates to its
> OuterUnknown, but the innerQI never gets called, and Dolphin dies with a
> native stack overflow in URLMon, which could be an aggregate problem.
> I'd expect to NOT see a call for that interface on the delegating QI,
> but rather only the inner non-delegating QI, because I'm not exposing my
> object except via the external aggregation. I have instrumented all the
> inner and outer QIs in COMObjectStub and that's the only request for
> that IID. My ability to track this down is compromised because I can't
> cross into the VM, to see if the last param to CoCreateInstance is being
> used to return a non-delegating IUnknown.
>
> So the nub is: is this known, definitively, to work (in D5) for other
> cases where a non-ST object aggregates an ST object? I've been chasing
> this for the last 12 hours, so I thought I'd better check.

The honest answer is "No, it is not known to work in D4 or D5". I don't
think it has changed between the two. In fact aggregation is so little used,
that I'm really not sure it is implemented 100% correctly. Furthermore I'm
not sure that I would know whether it is correct off the top of my head, not
having looked at it for some time :-). However, the entire implementation of
all the COM stuff is visible within the image. The VM has no knowledge of
the COM objects served by the image whatsoever. Just about the only service
it supplies is a generic virtual table which serves to bounce the interface
calls back into the image through a common entry point. There is also a
primitive which maps the arguments off the callstack into objects and
invokes a COM interface implementation method, but it performs no
translations on return. Therefore if there is a problem, it must be in the
image. External calls to CoCreateInstance() will come through to
COMClassFactory>>CreateInstance:riid:ppvObject:. In that method you can see
that it should be returning a non-delegating unknown in response to
aggregation requests, and it would appear to be correctly add ref'd.

Regards

Blair

>
> -------------------------
> Antony Blakey
> mailto:[hidden email]
> Linkuistics Pty Ltd
> Adelaide, South Australia
>


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work?

Bill Schwab-2
Blair,

> We are aiming to ship a release candidate before Smalltalk Solutions (i.e.
> by the end of this week). This should be very close to the final product.
We
> really had hoped to ship the product before then, but despite a lot of
hard
> work we have not been able to get it done. I'm sure we can come to some
> arrangement to supply you with a non-expiring key to meet your product
> deadline, e.g. if you have recently purchased D4 then you would be
entitled
> to a free upgrade to D5 in which case we would gladly send you a full D5
> key.

Hmmm.  We're getting to the point that I sorta need to "take the plunge" on
my servers, but, I make no claim re an external deadline.  If buying another
copy of D4 now is the answer, then I'd gladly go that route.  Whatever's
easier for you - if that's to wait until release, that's ok too.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work?

Antony Blakey-4
In reply to this post by Blair McGlashan
Blair McGlashan wrote:

> "Antony Blakey" <[hidden email]> wrote in message
> news:[hidden email]...
>>So the nub is: is this known, definitively, to work (in D5) for other
>>cases where a non-ST object aggregates an ST object? I've been chasing
>>this for the last 12 hours, so I thought I'd better check.
>
>
> The honest answer is "No, it is not known to work in D4 or D5". I don't
> think it has changed between the two. In fact aggregation is so little used,
> that I'm really not sure it is implemented 100% correctly. Furthermore I'm
> not sure that I would know whether it is correct off the top of my head, not
> having looked at it for some time :-). However, the entire implementation of
> all the COM stuff is visible within the image. The VM has no knowledge of
> the COM objects served by the image whatsoever. Just about the only service
> it supplies is a generic virtual table which serves to bounce the interface
> calls back into the image through a common entry point. There is also a
> primitive which maps the arguments off the callstack into objects and
> invokes a COM interface implementation method, but it performs no
> translations on return. Therefore if there is a problem, it must be in the
> image. External calls to CoCreateInstance() will come through to
> COMClassFactory>>CreateInstance:riid:ppvObject:. In that method you can see
> that it should be returning a non-delegating unknown in response to
> aggregation requests, and it would appear to be correctly add ref'd.

Bugger. How I'd love some docs on the flow through your COM
infrastructure. Looks like I'm going into the trenches, which would be
fun if not for the deadlines! I'm sure you know how that feels right now  :)

-------------------------
Antony Blakey
mailto:[hidden email]
Linkuistics Pty Ltd
Adelaide, South Australia


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work?

Blair McGlashan
"Antony Blakey" <[hidden email]> wrote in message
news:[hidden email]...
> ...
> Bugger. How I'd love some docs on the flow through your COM
> infrastructure. Looks like I'm going into the trenches, which would be
> fun if not for the deadlines! I'm sure you know how that feels right now
:)

I found an old sample package from Dolphin 2.1 (it was an old binary package
which D5 warned me was last saved on the 2.1 VM) which illustrates
aggregation following an example in Dale Rogerson's "Inside COM". As the
package comment says the sample is rather lacklustre but is chosen just to
be able to follow it through from the book really.

Anyway, it exhibits exactly the behaviour you have found - i.e. a stack
overflow occurs. If you set a halt in ProcessorScheduler>>stackOverflow: you
can take a peak in the debugger to see where it is coming from. I'm afraid I
haven't got time to look at it right now, but it would seem that something
has changed in Dolphin's COM framework which has broken aggregation -
clearly some SUnit tests are needed!

I'm not sure how much this helps, but it is very simplistic and all internal
to Dolphin (both outer and inner objects are implemented in St) so it might
help you find the problem if you need to do that in a hurry. Otherwise I
will try to find some time to look at it next week while at Smalltalk
Solutions.

Regards

Blair


begin 666 Inside COM Ch8 Ex2.pac
M?"!P86-K86=E('P-"G!A8VMA9V4@.CT@4&%C:V%G92!N86UE.B G26YS:61E
M($-/32!#:#@@17@R)RX-"G!A8VMA9V4@<&%X5F5R<VEO;CH@,#L-"@EB87-I
M8T-O;6UE;G0Z("=);7!L96UE;G1A=&EO;B!O9B!A9V=R96=A=&EO;B!E>&%M
M<&QE(#(L("!#:&%P=&5R(#@L(&]F($1A;&4@4F]G97)S;VXG)W,@(DEN<VED
M92!#3TTB+@T*#0I&<F%N:VQY('1H:7,@97AA;7!L92!I<R!R871H97(@;&%C
M:VQU<W1R92P@8G5T(&ET(&1O97,@870@;&5A<W0@86QL;W<@;VYE('1O(&5A
M<VEL>2!R96QA=&4@=&AE(&EM<&QE;65N=&%T:6]N(&]F(&%G9W)E9V%T:6]N
M(&EN('1H92!$;VQP:&EN($-/32!F<F%M97=O<FL@=&\@=&AE(')A=R!#*RL@
M0T]-(&EM<&QE;65N=&%T:6]N(&EN(%)O9V5R<V]N)R=S(&)O;VLN#0H-"E1O
M('1E<W0Z#0H-"C$I($9I<G-T(&-R96%T92!A(&1Y;F%M:6,@<F5G:7-T<F%T
M:6]N(&]F($1O;'!H:6X@87,@=&AE('-E<G9E<B!F;W(@=&AI<R!C;&%S<SH-
M"@E#3TU#;&%S<T9A8W1O<GD@;VXZ($-!#0H-"C(I($YO=R!I;G-T86YT:6%T
M92!A;B!I;G-T86YC92!V:6$@0V]#<F5A=&5);G-T86YC93H-"@EP:5@@.CT@
M25@@;VY#3%-)1#H@0T$@8VQS:60-"@T*,RD@26YV;VME(&$@;65T:&]D(&]F
M('1H92!O=71E<B!O8FIE8W0@*'-E92!T:&4@5')A;G-C<FEP="D-"@EP:5@@
M1G@-"@T*-"D@475E<GD@;V9F('1H92!I;FYE<B H86=G<F5G871E9"D@:6YT
M97)F86-E#0H)<&E9(#H]('!I6"!Q=65R>4EN=&5R9F%C93H@25D-"@T*-2D@
M06YD(')U;B!A(&UE=&AO9"!O9B!T:&4@:6YN97(@8V]M<&]N96YT("AS964@
M=&AE(%1R86YS8W)I<'0I#0H)<&E9($9Y)RX-"@T*<&%C:V%G92!B87-I8U-C
M<FEP=$%T.B C<&]S=&EN<W1A;&P@<'5T.B G0T$@<F5G:7-T97)#;&%S<T9A
M8W1O<GDN#0I#0B!R96=I<W1E<D-L87-S1F%C=&]R>2<N#0IP86-K86=E(&)A
M<VEC4V-R:7!T070Z("-P;W-T=6YI;G-T86QL('!U=#H@)R<N#0IP86-K86=E
M(&)A<VEC4V-R:7!T070Z("-P<F5I;G-T86QL('!U=#H@)R<N#0IP86-K86=E
M(&)A<VEC4V-R:7!T070Z("-P<F5U;FEN<W1A;&P@<'5T.B G)RX-"@T*<&%C
M:V%G92!C;&%S<TYA;65S#0H)861D.B C0T$[#0H)861D.B C0T([#0H)861D
M.B C25@[#0H)861D.B C25D[#0H)>6]U<G-E;&8N#0H-"G!A8VMA9V4@8FEN
M87)Y1VQO8F%L3F%M97,Z("A3970@;F5W#0H)>6]U<G-E;&8I+@T*#0IP86-K
M86=E(&=L;V)A;$%L:6%S97,Z("A3970@;F5W#0H)>6]U<G-E;&8I+@T*#0IP
M86-K86=E(&%L;%)E<V]U<F-E3F%M97,Z("A3970@;F5W#0H)>6]U<G-E;&8I
M+@T*#0IP86-K86=E('-E=%!R97)E<75I<VET97,Z("A)9&5N=&ET>5-E="!N
M97<-"@EA9&0Z("<N+EPN+EPN+EQ$;VQP:&EN7$)A<V5<1&]L<&AI;B<[#0H)
M861D.B G+BY<+BY<+BY<1&]L<&AI;EQ!8W1I=F587$-/35Q/3$4@0T]-)SL-
M"@EY;W5R<V5L9BDN#0H-"G!A8VMA9V4A#0H-"B)#;&%S<R!$969I;FET:6]N
M<R(A#0H-"D-/34EN=&5R9F%C94EM<"!S=6)C;&%S<SH@(T-!#0H):6YS=&%N
M8V5687)I86)L94YA;65S.B G;5]P56YK;F]W;DEN;F5R(&U?<$E9)PT*"6-L
M87-S5F%R:6%B;&5.86UE<SH@)R<-"@EP;V]L1&EC=&EO;F%R:65S.B G)PT*
M"6-L87-S26YS=&%N8V5687)I86)L94YA;65S.B G)R$-"D-/34EN=&5R9F%C
M94EM<"!S=6)C;&%S<SH@(T-"#0H):6YS=&%N8V5687)I86)L94YA;65S.B G
M)PT*"6-L87-S5F%R:6%B;&5.86UE<SH@)R<-"@EP;V]L1&EC=&EO;F%R:65S
M.B G)PT*"6-L87-S26YS=&%N8V5687)I86)L94YA;65S.B G)R$-"DE5;FMN
M;W=N('-U8F-L87-S.B C25@-"@EI;G-T86YC959A<FEA8FQE3F%M97,Z("<G
M#0H)8VQA<W-687)I86)L94YA;65S.B G)PT*"7!O;VQ$:6-T:6]N87)I97,Z
M("<G#0H)8VQA<W-);G-T86YC959A<FEA8FQE3F%M97,Z("<G(0T*255N:VYO
M=VX@<W5B8VQA<W,Z("-)60T*"6EN<W1A;F-E5F%R:6%B;&5.86UE<SH@)R<-
M"@EC;&%S<U9A<FEA8FQE3F%M97,Z("<G#0H)<&]O;$1I8W1I;VYA<FEE<SH@
M)R<-"@EC;&%S<TEN<W1A;F-E5F%R:6%B;&5.86UE<SH@)R<A#0H-"B)';&]B
M86P@06QI87-E<R(A#0H-"@T*(DQO;W-E($UE=&AO9',B(0T*#0HB16YD(&]F
M('!A8VMA9V4@9&5F:6YI=&EO;B(A#0H-"B)3;W5R8V4@1VQO8F%L<R(A#0H-
M"B)#;&%S<V5S(B$-"@T*0T$@9W5I9#H@*$=5240@9G)O;5-T<FEN9SH@)WM&
M,30Y-C0P,BTY,D8T+30Y1C8M048Q1BU"-#DU-4-!-D$X1D-])RDA#0I#02!C
M;VUM96YT.B G26UP;&5M96YT871I;VX@;V8@86=G<F5G871I;F<@*&]U=&5R
M*2!C;VUP;VYE;G0@9G)O;2!#:&%P=&5R(#@L(&5X86UP;&4@,BP@;V8@1&%L
M92!2;V=E<G-O;B<G<R B26YS:61E($-/32(-"@T*1FER<W0@8W)E871E(&$@
M9'EN86UI8R!R96=I<W1R871I;VX@;V8@1&]L<&AI;B!A<R!T:&4@<V5R=F5R
M(&9O<B!T:&ES(&-L87-S.@T*"4-/34-L87-S1F%C=&]R>2!O;CH@0T$-"@T*
M3F]W(&EN<W1A;G1I871E(&%N(&EN<W1A;F-E('9I82!#;T-R96%T94EN<W1A
M;F-E.@T*"7!I6" Z/2!)6"!O;D-,4TE$.B!#02!C;'-I9"<A#0HA0T$@8V%T
M96=O<FEE<T9O<D-L87-S(4YO(&-A=&5G;W)Y(2 A#0HA0T$@;65T:&]D<T9O
M<B$-"@T*86=G<F5G871E90T*"2)!;G-W97(@=&AE($E5;FMN;W=N("AW:&EC
M:"!M=7-T(&)E(&$@;F]N+61E;&5G871I;F<@=6YK;F]W;B!I;7!L96UE;G1A
M=&EO;BD-"@EO9B!A;GD@86=G<F5G871E92!O9B!T:&4@<F5C96EV97(L(&]R
M(&YI;"!I9B!T:&5R92!I<R!N;VYE+B(-"@T*"5YM7W!5;FMN;W=N26YN97(A
M#0H-"D9X#0H)(DEM<&QE;65N="!T:&4@25@Z.D9X*"D@:6YT97)F86-E(&9U
M;F-T:6]N+B(-"@T*"5Y4<F%N<V-R:7!T('-H;W<Z("=!9V=R96=A=&EN9R H
M;W5T97(I(&-O;7!O;F5N="!&>"@I)SL@8W(A#0H-"FEN:71I86QI>F4-"@DB
M26YI=&EA;&EZ92!T:&4@8V]M<&]N96YT(&)Y(&-R96%T:6YG('1H92!C;VYT
M86EN960@8V]M<&]N96YT+@T*"5EO=2!W:6QL(&YO=&4@=&AA="!N;R!(4D53
M54Q4(&5R<F]R(&AA;F1L:6YG(&-O9&4@:7,@<F5Q=6ER960@;&EK92!T:&%T
M(&EN("=);G-I9&4@0T]-)PT*"7=H:6-H(&UA:V5S('1H:7,@;75C:"!C;&5A
M<F5R(&%N9"!S:6UP;&5R+B!!;'-O('=E(&1E86P@97AC;'5S:79E;'D@:6X@
M=&5R;7,@;V8@8VQA<W-E<PT*"7)A=&AE<B!T:&%N($=5241S+B(-"@T*"7P@
M<%5N:VYO=VY/=71E<B!\#0H)<%5N:VYO=VY/=71E<B Z/2!S96QF('%U97)Y
M26YT97)F86-E.B!)56YK;F]W;BX-"@E.;W1I9FEC871I;VX@<VEG;F%L.B G
M0W)E871E(&EN;F5R(&-O;7!O;F5N="<N#0H);5]P56YK;F]W;DEN;F5R(#H]
M($E5;FMN;W=N(&]N0TQ3240Z($-"(&-L<VED(&]U=&5R255N:VYO=VXZ('!5
M;FMN;W=N3W5T97(N#0H);5]P25D@.CT@;5]P56YK;F]W;DEN;F5R('%U97)Y
M26YT97)F86-E.B!)62X-"@DB5')I8VMY.B!296UO=F4@<F5F+B!T;R!S96QF
M(&-R96%T960@8GD@86)O=F4@44D@*&-O;G1A:6YE9"!O8FIE8W0@861D<R!R
M968N('1O('-E;&8-"@EF;W(@=&AE('%U97)I960@:6YT97)F86-E('=I=&@@
M061D4F5F*"DL('=H:6-H(&ET(&1E;&5G871E<R!B86-K('1O('1H:7,@;V)J
M96-T(2$I+B(-"@EP56YK;F]W;D]U=&5R(%)E;&5A<V4N#0H)(FU?<$E9(&1O
M97,@;F]T(&YE960@4F5L96%S:6YG(@T*"6U?<$E9(&)E56YF:6YA;&EZ86)L
M92$-"@T*<W5P<&]R=&5D26YT97)F86-E<PT*"2)!;G-W97(@=&AE('-E="!O
M9B!I;G1E<F9A8V4@8VQA<W-E<R!S=7!P;W)T960@8GD@=&AE(')E8V5I=F5R
M+@T*"4XN0BX@0GD@=&AE(')U;&5S(&]F($-/32P@=&AI<R!S970@;75S="!R
M96UA:6X@8V]N<W1A;G0N($%L; T*"6EN=&5R9F%C97,@86QS;R!S=7!P;W)T
M($E5;FMN;W=N+B(-"@T*"5Y!<G)A>2!W:71H.B!)6"$@(0T*(4-!(&-A=&5G
M;W)I97-&;W(Z("-A9V=R96=A=&5E(6%C8V5S<VEN9R%P<FEV871E(2 A#0HA
M0T$@8V%T96=O<FEE<T9O<CH@(T9X(4-/32!);G1E<F9A8V5S+4E8(7!R:79A
M=&4A("$-"B%#02!C871E9V]R:65S1F]R.B C:6YI=&EA;&EZ92%I;FET:6%L
M:7II;F<A<')I=F%T92$@(0T*(4-!(&-A=&5G;W)I97-&;W(Z("-S=7!P;W)T
M961);G1E<F9A8V5S(6-O;G-T86YT<R%P<FEV871E(2 A#0H-"B%#02!C;&%S
M<R!M971H;V1S1F]R(0T*#0IC;'-I9 T*"2)!;G-W97(@=&AE(')E8V5I=F5R
M)W,@0TQ3240N(@T*#0H)7D-,4TE$(&9R;VU3=')I;F<Z("=[13!%-T(Q.30M
M1CA"1"TQ,40Q+4%!-CDM-T-#1# P,# P,# P?2<A("$-"B%#02!C;&%S<R!C
M871E9V]R:65S1F]R.B C8VQS:60A8V]N<W1A;G1S(7!R:79A=&4A("$-"@T*
M0T(@9W5I9#H@*$=5240@9G)O;5-T<FEN9SH@)WM!-3@X-#5&,"TW,48S+30U
M1#,M03%$1BU$14(Y.$4S0D)$1D1])RDA#0I#0B!C;VUM96YT.B G)R$-"B%#
M0B!C871E9V]R:65S1F]R0VQA<W,A3F\@8V%T96=O<GDA("$-"B%#0B!M971H
M;V1S1F]R(0T*#0I&>0T*"2));7!L96UE;G0@=&AE($E9.CI&>2@I(&EN=&5R
M9F%C92!F=6YC=&EO;BXB#0H-"@E>5')A;G-C<FEP="!S:&]W.B G06=G<F5G
M871E9" H:6YN97(I(&-O;7!O;F5N="!&>2@I)SL@8W(A#0H-"G-U<'!O<G1E
M9$EN=&5R9F%C97,-"@DB06YS=V5R('1H92!S970@;V8@:6YT97)F86-E(&-L
M87-S97,@<W5P<&]R=&5D(&)Y('1H92!R96-E:79E<BX-"@E.+D(N($)Y('1H
M92!R=6QE<R!O9B!#3TTL('1H:7,@<V5T(&UU<W0@<F5M86EN(&-O;G-T86YT
M+B!!;&P-"@EI;G1E<F9A8V5S(&%L<V\@<W5P<&]R="!)56YK;F]W;BXB#0H-
M"@E>07)R87D@=VET:#H@25DA("$-"B%#0B!C871E9V]R:65S1F]R.B C1GDA
M0T]-($EN=&5R9F%C97,M25DA<')I=F%T92$@(0T*(4-"(&-A=&5G;W)I97-&
M;W(Z("-S=7!P;W)T961);G1E<F9A8V5S(6-O;G-T86YT<R%P<FEV871E(2 A
M#0H-"B%#0B!C;&%S<R!M971H;V1S1F]R(0T*#0IC;'-I9 T*"2)!;G-W97(@
M=&AE(')E8V5I=F5R)W,@0TQ3240N(@T*#0H)7D-,4TE$(&9R;VU3=')I;F<Z
M("=[13!%-T(Q.34M1CA"1"TQ,40Q+4%!-CDM-T-#1# P,# P,# P?2<A("$-
M"B%#0B!C;&%S<R!C871E9V]R:65S1F]R.B C8VQS:60A8V]N<W1A;G1S(7!R
M:79A=&4A("$-"@T*25@@9W5I9#H@*$E)1"!F<F]M4W1R:6YG.B G>T4P13="
M,3DR+48X0D0M,3%$,2U!038Y+3=#0T0P,# P,# P,'TG*2$-"DE8(&-O;6UE
M;G0Z("<G(0T*(4E8(&-A=&5G;W)I97-&;W)#;&%S<R%.;R!C871E9V]R>2$@
M(0T*(4E8(&UE=&AO9'-&;W(A#0H-"D9X#0H)(D-A;&QO=70@9F]R('1H92!)
M6#HZ1G@H*2!I;G1E<F9A8V4@9G5N8W1I;VXN#0H)3BY"+B!4:&ES(&UE=&AO
M9"!H87,@8F5E;B!A=71O;6%T:6-A;&QY(&=E;F5R871E9"!F<F]M( T*"71H
M92!V=&%B;&4@9&5F:6YE9"!I;B!)6#X^9&5F:6YE1G5N8W1I;VYS+B!$3R!.
M3U0@34]$2499(2$B#0H-"@D\=FER='5A;"!S=&1C86QL.B!V;VED(#0@/@T*
M"5YS96QF(&EN=F%L:61#86QL(2 A#0HA25@@8V%T96=O<FEE<T9O<CH@(T9X
M(4-/32!);G1E<F9A8V5S+4E8(7!R:79A=&4A("$-"@T*(4E8(&-L87-S(&UE
M=&AO9'-&;W(A#0H-"F1E9FEN949U;F-T:6]N<PT*"2)$96-L87)E('1H92!V
M:7)T=6%L(&9U;F-T:6]N<R!S=7!P;W)T960@8GD@=&AE(')E8V5I=F5R+@T*
M"0E)6"!C;VUP:6QE1G5N8W1I;VYS#0H)(@T*#0H)<V5L9@T*"0ED969I;F5&
M=6YC=&EO;CH@(T9X(')E='5R;E1Y<&4Z("=V;VED)R$-"@T*:6YI=&EA;&EZ
M90T*"2)0<FEV871E("T@26YI=&EA;&EZ92!T:&4@<F5C96EV97(N#0H)1V5N
M97)A=&4@=&AE($E)1"!F<F]M(&ET<R!S=')I;F<@<F5P<F5S96YT871I;VXN
M#0H)"4E8(&EN:71I86QI>F4-"@DB#0H-"@ES96QF(&EI9%-T<FEN9SH@)WM%
M,$4W0C$Y,BU&.$)$+3$Q1#$M04$V.2TW0T-$,# P,# P,#!])R$@(0T*(4E8
M(&-L87-S(&-A=&5G;W)I97-&;W(Z("-D969I;F5&=6YC=&EO;G,A:6YI=&EA
M;&EZ:6YG(7!R:79A=&4A("$-"B%)6"!C;&%S<R!C871E9V]R:65S1F]R.B C
M:6YI=&EA;&EZ92%I;FET:6%L:7II;F<A<')I=F%T92$@(0T*#0I)62!G=6ED
M.B H24E$(&9R;VU3=')I;F<Z("=[13!%-T(Q.3,M1CA"1"TQ,40Q+4%!-CDM
M-T-#1# P,# P,# P?2<I(0T*25D@8V]M;65N=#H@)R<A#0HA25D@8V%T96=O
M<FEE<T9O<D-L87-S(4YO(&-A=&5G;W)Y(2 A#0HA25D@;65T:&]D<T9O<B$-
M"@T*1GD-"@DB0V%L;&]U="!F;W(@=&AE($E9.CI&>2@I(&EN=&5R9F%C92!F
M=6YC=&EO;BX-"@E.+D(N(%1H:7,@;65T:&]D(&AA<R!B965N(&%U=&]M871I
M8V%L;'D@9V5N97)A=&5D(&9R;VT@#0H)=&AE('9T86)L92!D969I;F5D(&EN
M($E9/CYD969I;F5&=6YC=&EO;G,N($1/($Y/5"!-3T1)1EDA(2(-"@T*"3QV
M:7)T=6%L('-T9&-A;&PZ('9O:60@-" ^#0H)7G-E;&8@:6YV86QI9$-A;&PA
M("$-"B%)62!C871E9V]R:65S1F]R.B C1GDA0T]-($EN=&5R9F%C97,M25DA
M<')I=F%T92$@(0T*#0HA25D@8VQA<W,@;65T:&]D<T9O<B$-"@T*9&5F:6YE
M1G5N8W1I;VYS#0H)(D1E8VQA<F4@=&AE('9I<G1U86P@9G5N8W1I;VYS('-U
M<'!O<G1E9"!B>2!T:&4@<F5C96EV97(N#0H)"4E9(&-O;7!I;&5&=6YC=&EO
M;G,-"@DB#0H-"@ES96QF#0H)"61E9FEN949U;F-T:6]N.B C1GD@<F5T=7)N
M5'EP93H@)W9O:60G(0T*#0II;FET:6%L:7IE#0H)(E!R:79A=&4@+2!);FET
M:6%L:7IE('1H92!R96-E:79E<BX-"@E'96YE<F%T92!T:&4@24E$(&9R;VT@
M:71S('-T<FEN9R!R97!R97-E;G1A=&EO;BX-"@D)25D@:6YI=&EA;&EZ90T*
M"2(-"@T*"7-E;&8@:6ED4W1R:6YG.B G>T4P13=",3DS+48X0D0M,3%$,2U!
M038Y+3=#0T0P,# P,# P,'TG(2 A#0HA25D@8VQA<W,@8V%T96=O<FEE<T9O
M<CH@(V1E9FEN949U;F-T:6]N<R%I;FET:6%L:7II;F<A<')I=F%T92$@(0T*
M(4E9(&-L87-S(&-A=&5G;W)I97-&;W(Z("-I;FET:6%L:7IE(6EN:71I86QI
M>FEN9R%P<FEV871E(2 A#0H-"B)":6YA<GD@1VQO8F%L<R(A#0H-"B)297-O
+=7)C97,B(0T*#0H`
`
end


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work?

Antony Blakey-4
Blair McGlashan wrote:

> "Antony Blakey" <[hidden email]> wrote in message
> news:[hidden email]...
>
>>...
>>Bugger. How I'd love some docs on the flow through your COM
>>infrastructure. Looks like I'm going into the trenches, which would be
>>fun if not for the deadlines! I'm sure you know how that feels right now
>
> :)
>
> I found an old sample package from Dolphin 2.1 (it was an old binary package
> which D5 warned me was last saved on the 2.1 VM) which illustrates
> aggregation following an example in Dale Rogerson's "Inside COM". As the
> package comment says the sample is rather lacklustre but is chosen just to
> be able to follow it through from the book really.
>
> Anyway, it exhibits exactly the behaviour you have found - i.e. a stack
> overflow occurs. If you set a halt in ProcessorScheduler>>stackOverflow: you
> can take a peak in the debugger to see where it is coming from. I'm afraid I
> haven't got time to look at it right now, but it would seem that something
> has changed in Dolphin's COM framework which has broken aggregation -
> clearly some SUnit tests are needed!
>
> I'm not sure how much this helps, but it is very simplistic and all internal
> to Dolphin (both outer and inner objects are implemented in St) so it might
> help you find the problem if you need to do that in a hurry. Otherwise I
> will try to find some time to look at it next week while at Smalltalk
> Solutions.

I think I have found the problem (and a solution), but given that until
8 weeks ago I had never used COM (or Smalltalk), my understanding may be
suspect. With that disclaimer... I'll document my understanding of the
way it is now, what's wrong, and how I'll fix it.

1. How it works

For each ST object exported as a COM object a COMObjectStub ('stub') is
created and registered in the IdentityRegistry, which maps from ST
object to the stub. The stub is the thing that handles all the COM
calls. An incoming com call is routed from the VM to the stub using
cookies that are integers that map into tables i.e. a form of object
identity marshalling. Each COM Interface supported by the exported
object is represented by an instance of the corresponding COMInterface
class, where that instance has a reference to the object. The
COMInterface instance also holds the vtable which allows mapping from
the external COM invocation index to the selector. These interface
instances are created on-demand and stored by the stub in it's
interfaces slot. Each stub can have only one instance of any given
COMInterface class.

2. What's wrong.

COMClassFactory>>CreateInstance..., when asked to create an aggregated
instance, indirectly creates a stub and sets it's outerUnknown using
IUnknown>>on:outerUnknown:. This delegating stub is registered as *the*
one and only stub for the object, which is right and proper, because it
means that all IUnknown behaviour will be delegated. Unfortunately this
delegating stub is then returned to the container, when in fact a
seperate non-delegating stub needs to be returned. Problem is, you can't
create more than one COMObjectStub per server object because of the
IdentityRegistry.

3. To fix.

It seems to me that *any* solution requires that two stubs are created
for any aggregated object. In order to return a seperate non-delegating
stub, a seperate COMObjectStub needs to be returned that routes QI to
innerQI on the delegating stub, except for IUnknown requests for which
it should return it's own IUnknown, that will then route to itself. This
second stub has a reference to the delegating stub. I propose as a first
step to subclass COMObjectStub to create COMObjectNonDelegatingStub that
doesn't map object->stub but rather delegating-stub->nondelegating-stub,
and routes QI/AddRef/Release to inner* for all except a QI of IUnknown,
for which it returns it's own IUnknown. Obviously most of the class
methods need to be stubbed out. This would then be refactored.

I'd like to fix this in a way that can be incorporated back into the
base product, which is why I've outline a proposed solution for comment.

-------------------------
Antony Blakey
mailto:[hidden email]
Linkuistics Pty Ltd
Adelaide, South Australia


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work?

Blair McGlashan
"Antony Blakey" <[hidden email]> wrote in message
news:[hidden email]...

> ...
> It seems to me that *any* solution requires that two stubs are created
> for any aggregated object. In order to return a seperate non-delegating
> stub, a seperate COMObjectStub needs to be returned that routes QI to
> innerQI on the delegating stub, except for IUnknown requests for which
> it should return it's own IUnknown, that will then route to itself. This
> second stub has a reference to the delegating stub. I propose as a first
> step to subclass COMObjectStub to create COMObjectNonDelegatingStub that
> doesn't map object->stub but rather delegating-stub->nondelegating-stub,
> and routes QI/AddRef/Release to inner* for all except a QI of IUnknown,
> for which it returns it's own IUnknown. Obviously most of the class
> methods need to be stubbed out. This would then be refactored.

I can see your reasoning, but I don't think that is necessary. The sample
did use to work in an earlier version of Dolphin, as I recall, so there has
been a change which has stopped it doing so. I think it might well be due to
an optimization that removed some of the overhead of the basic IUnknown
calls, probably occurring in D4. Anyway there is quite a lot of flexibility
about who actually implements a particular interface in Dolphin's COM
framework - the COMObjectStub is the usual implementor of IUnknown, but that
need not be the case, and presumably at some point it wasn't. Note that the
COM callbacks go first to the stub, and then are delegated to the interface,
which in turn delegates them to a function object held in a table specific
to its class (one function object per virtual function). I am at the edges
of my memory here but I seem to recall that the idea is that the
non-delegating IUnknown is a created separately and not registered with the
stub as the provider of IUnknown, and is supposed to be of a distinct
"IInnerUnknown" class. This class no longer seems to exist.

Ah yes, a search through the news group archives found this from a June 1998
thread entitled "Aggregated COM Components" initiated by James Howe. It
seems that Dolphin 2.1 was patched to make aggregation work, or possibly
Dolphin 3.0, and it has been broken since.

If we are going to get the release candidate out, then I really can't spend
any more time on this now, but I promise I will take a look next week to try
an make sure it is working in the actual release (this time with some SUnit
tests to ensure it stays working).

Regards

Blair

--------------------
James

You wrote in message <[hidden email]>...
>...
>First of all, it doesn't look like there is a common framework
>implementation to support aggregation.  The
>COMInterfaceImp>>queryInterface:ifNone: seems to be written assuming
>that the subclass will implement all interfaces it supports.  A
>subclass which uses aggregation would have to override this method to
>work correctly unless I'm missing something.

Current support for aggregation is embryonic. This is not a widely used
feature of COM (in fact you are the first to report problems with it,
perhaps even the first person to use it!) and therefore it has not been a
high priority to date.

Support for aggregation is embodied in the design, but is not
fully/correctly implemented. The framework is designed to provide its
support for aggregation in the COMObjectStub class, in conjunction with the
non-delegating unknown, IInnerUnknown. COMObjectStub is a wrapper object
which implements basic COM support for other Smalltalk objects, and it
implements the three methods in IUnknown. These implementations delegate as
necessary, though some of the delegating methods are currently omitted.

COMInterfaceImp>>queryInterface:ifNone: is called only when there is no
outer unknown, so the implementation of that method is correct, i.e.
COMObjectStub is intended to take care of all basic IUnknown boilerplate
such as aggregation, reference counting, and fundament support for
QueryInterface. The idea is that the required behaviour in COMInterfaceImp
is very small and simple, since the framework does not require that COM
objects be subclassed from there. Any object can become a COM server by
implementing a small protocol (actually off the top of my head, I think it
is only #queryInterface:ifNone: which must be implemented, although a class
factory registration may also be required) which removes the restriction of
subclassing from a particular point in the hierarchy.

>...  My
>question is this, is this a bug in the implementation or am I using it
>incorrectly?  Is there a way to do aggregation in Dolphin or has that
>yet to be implemented?

It is a combination of both: COMInterface and IInnerUnknown need some minor
modifications to enable aggregation, (and as someone is now
using/experimenting with this, it is time it all worked), and your example
doesn't use the framework quite correctly. We'll put together a patch to be
released sometime later this week. I'll also see about putting a simple
sample in that demonstrates the correct usage, probably an implementation of
a Rogerson example.

Thanks for bringing this to my attention

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Is COM aggregation by an external object meant to work? (Finish)

Antony Blakey-4
Blair McGlashan wrote:

> Anyway there is quite a lot of flexibility
> about who actually implements a particular interface in Dolphin's COM
> framework - the COMObjectStub is the usual implementor of IUnknown, but that
> need not be the case, and presumably at some point it wasn't. Note that the
> COM callbacks go first to the stub, and then are delegated to the interface,
> which in turn delegates them to a function object held in a table specific
> to its class (one function object per virtual function). I am at the edges
> of my memory here but I seem to recall that the idea is that the
> non-delegating IUnknown is a created separately and not registered with the
> stub as the provider of IUnknown, and is supposed to be of a distinct
> "IInnerUnknown" class. This class no longer seems to exist.

I've looked further, your mechanism seems way better, and trivially easy
:) I'll do that.

> If we are going to get the release candidate out, then I really can't spend
> any more time on this now

Sure.

> but I promise I will take a look next week to try
> an make sure it is working in the actual release (this time with some SUnit
> tests to ensure it stays working).

No worries, you've given me enough to fix it. Thanks.

-------------------------
Antony Blakey
mailto:[hidden email]
Linkuistics Pty Ltd
Adelaide, South Australia