Shell Extension Handler

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

Shell Extension Handler

Steve Alan Waring
Hi,

I am trying to build a Shell Extension Handler from [1]. I have implemented
the IContextMenu and IShellExtInit COMInterfaces, and a COMInterfaceImp
subclass that implements the two interfaces.

After registering the class factory, and making the necessary changes to the
registry, I can right click on a file in Windows Explorer and it will open
my image. I have uncommented the tracing code in COMObjectStub and see the
following:

=====

a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 1:
Querying interface IMarshal
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 1:
Querying interface IMarshal
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 1:
Querying interface {0000001B-0000-0000-C000-000000000046}
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 1:
Querying interface IUnknown
Answering interface an IUnknown(an ExternalAddress(16r2E63484))
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 3:
Querying interface IStdMarshalInfo
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 3:
Querying interface IExternalConnection
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 2:
Querying interface IClassFactory
Answering interface an IClassFactory(an ExternalAddress(16r2E5EC94))
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 3:
Querying interface IClassFactory
Answering interface an IClassFactory(an ExternalAddress(16r2E5EC94))
a COMObjectStub on a COMClassFactory for COMShellShortcutMenu refs 3:
Querying interface {1C733A30-2A1C-11CE-ADE5-00AA0044773D}
a COMObjectStub on a COMShellShortcutMenu refs 1: Querying interface
IMarshal
a COMObjectStub on a COMShellShortcutMenu refs 1: Querying interface
IMarshal
a COMObjectStub on a COMShellShortcutMenu refs 1: Querying interface
{0000001B-0000-0000-C000-000000000046}
a COMObjectStub on a COMShellShortcutMenu refs 1: Querying interface
IUnknown
Answering interface an IUnknown(an ExternalAddress(16r2E4FDFC))
a COMObjectStub on a COMShellShortcutMenu refs 3: Querying interface
IStdMarshalInfo
a COMObjectStub on a COMShellShortcutMenu refs 3: Querying interface
IExternalConnection
a COMObjectStub on a COMShellShortcutMenu refs 2: Querying interface
IShellExtInit
Answering interface an IShellExtInit(an ExternalAddress(16r2E5E82C))
Server shutdown request

====

The documentation at [1] says that the Shell will call
IShellExtInit::Initialize. I have put trace code in my implementation of
this method and I dont see it being sent.

Is this an indication of a marshalling problem?

The documentation [1] says that I should use the apartment threading model.
When I register my class it uses the default. Can I change this to
apartment?

I have tried registering a type library. Samples I have looked at for C++
(for example [2]) have an idl/tlb that defines an IDispatch interface and a
coclass with this being the default interface. I have followed this pattern
and registered a type library for my coclass, but still see the trace above.
Does my type library need to describe the IShellExtInit and IContextMenu
interfaces?

The wiki page [3] talks about compiling a marshalling DLL. Is there any
information on how to do this?

Thanks,
Steve Waring
[hidden email]
http://www.dolphinharbor.org

[1]
http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersgu
ide/shell_int/shell_int_extending/extensionhandlers/contextmenuhandlers.asp?
frame=true

[2] http://support.microsoft.com/default.aspx?scid=kb;EN-US;q298109

[3] http://www.object-arts.com/wiki/html/Dolphin/BuildingCOMponents.htm


Reply | Threaded
Open this post in threaded view
|

Re: Shell Extension Handler

Blair McGlashan
Steve

You wrote in message news:acg9ni$pfj1d$[hidden email]...
> Hi,
>
> I am trying to build a Shell Extension Handler from [1]. I have
implemented
> the IContextMenu and IShellExtInit COMInterfaces, and a COMInterfaceImp
> subclass that implements the two interfaces.
>
> After registering the class factory, and making the necessary changes to
the

> registry, I can right click on a file in Windows Explorer and it will open
> my image. I have uncommented the tracing code in COMObjectStub and see the
> following:
> ... [snip]...
>
> The documentation at [1] says that the Shell will call
> IShellExtInit::Initialize. I have put trace code in my implementation of
> this method and I dont see it being sent.
>
> Is this an indication of a marshalling problem?

Seems quite likely, though when one can't debug through the client it can be
difficult to tell, therefore it can be a good idea to use your own simple
client. That way you will be able to examine the HRESULT return code from
the QI call for IShellExtInit. One way to do this would be to make another
Dolphin image the client - ensuring it has no class factory registered for
your shell extension component.

>
> The documentation [1] says that I should use the apartment threading
model.
> When I register my class it uses the default. Can I change this to
> apartment?

Not really. An apartment threaded object should be created on the thread
that calls CoCreateInstance (assumed to be an apartment thread). This will
not be the case in Dolphin for an external client. Despite what the docs
say, the threading model should not matter anyway, assuming the client is
obeying the rules of COM and passing around interface pointers correctly.
However a client of apartment threaded in-proc objects will not normally
require marshalling code, assuming it does not attempt to pass those objects
between threads. Therefore the system may not provide marshalling code for
IShellExtInit, etc.

>
> I have tried registering a type library. Samples I have looked at for C++
> (for example [2]) have an idl/tlb that defines an IDispatch interface and
a
> coclass with this being the default interface. I have followed this
pattern
> and registered a type library for my coclass, but still see the trace
above.
> Does my type library need to describe the IShellExtInit and IContextMenu
> interfaces?

Probably not. Type-library marshalling will only support automation
compatible types anyway, so unless the interfaces run through MIDL without
complaint when they have the "oleautomation" attributes, then the type
library won't help. From a casual glance I would say that IShellExtInit is
not automation compatible.

>
> The wiki page [3] talks about compiling a marshalling DLL. Is there any
> information on how to do this?

It is a mechanical process that involves compiling the proxy/stub C files
that MIDL can output into an in-proc server DLL of a standardized form - you
don't actually have to write any code once you have the IDL available.
You'll need access to VC++ (or some other Windows C compiler) to do this.
MSDN has a couple of ATL samples I spotted that have a proxy/stub DLLs
(LABRADOR and ATLDuck), there may be others too. Most of the ground-up
COM/OLE books also explain how to do it (e.g. Rogerson's Inside COM).

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Shell Extension Handler

Steve Alan Waring
Hi Blair,

> the QI call for IShellExtInit. One way to do this would be to make another
> Dolphin image the client - ensuring it has no class factory registered for
> your shell extension component.

I have had trouble doing this, but I wasnt sure that I could. I get the same
problems with the COMRandom sample. The steps to reproduce are;

Create two fresh images; testC and testS in my "Dolphin Smalltalk 5.0"
directory.

Open testC
 - "Evaluate" COMRandomStream unregisterClassFactory; unregister
 - Confirm that the COMClassFactories Factories classVariable is empty.
 - Save image and exit.
Open testS
 - Open the AxtiveX Component Wizard and see RANDOMLib listed as a Library.
 - "Evaluate" COMRandomStream register; registerClassFactory
 - Confirm that the COMClassFactories Factories has an entry for
COMRandomStream.
 - Save image and exit.

My Registry entries are:

HKCR
-CLSID
--{A1D42F35-E6C0-11D2-833B-0020AFAB8EFE}
---Image "C:\Documents and Settings\Steve\My Documents\Dolphin Smalltalk
5.0\testS.img"
---InProcServer32 "C:\Program Files\Object Arts\Dolpin Smalltalk
5.0\IPDolphin.dll"
---LocalServer32 "C:\Program Files\Object Arts\Dolpin Smalltalk
5.0\Dolphin.dll"
---ProgID "Dolphin.RandomStream.1"

I can start "RandomVBClient.exe" and it opens the testS image and works.

If I start testC and evaluate "IRandomStream new" or "IDispatch
createObject: 'Dolphin.RandomStream.1'" the image either crashes and I get
testS.ERRORS crash dump, or locks up, and while locked a testS.ERRORS file
is written. I do not get a crash dump for testC.

If the testS image is open and I start "RandomVBClient.exe", I get the
MessageBox saying "The Image ... testS.img is already open, Are you sure you
want to open the same image again".

If the testS image is open and I start testC and evaluate "IRandomStream
new" I get the same crash/lock behavior in testC. testS stays open and I get
a testS.ERRORS crash dump.

This is on W2K with PL1 images. Is this expected or is there a problem
somewhere?

> It is a mechanical process that involves compiling the proxy/stub C files
> that MIDL can output into an in-proc server DLL of a standardized form -
you
> don't actually have to write any code once you have the IDL available.
> You'll need access to VC++ (or some other Windows C compiler) to do this.
> MSDN has a couple of ATL samples I spotted that have a proxy/stub DLLs
> (LABRADOR and ATLDuck), there may be others too. Most of the ground-up
> COM/OLE books also explain how to do it (e.g. Rogerson's Inside COM).

I tried this with a C++ sample that builds a ContextMenu handler DLL,
switching the InprocServer32 entry in the registry script to point to
"C:\Program Files\Object Arts\Dolphin Smalltalk 5.0\IPDolphin.dll". After
building it, the default interface of my coclass has a
HKCR/Interface/./ProxyStubClsid32 key but the IShellExtInit Interface
does not.

 From your post, I see that this didnt work because the DLL uses the
apartment threading model and does not need marshalling for IShellExtInit.
Time for some fun with MIDL :(

Thanks,
Steve
[hidden email]
http://www.dolphinharbor.org


Reply | Threaded
Open this post in threaded view
|

Re: Shell Extension Handler

Steve Alan Waring
Hi Blair,

I changed the client to not include the CLSCTX_INPROC_SERVER flag in the
CoGetClassObject function call which stopped the image crashes. In the
server image I could see the interface being answered, but the client got
back E_NOINTERFACE.

I was able to get something working by using my own proxy stub to marshal
the IShellExtInit and IContextMenu interfaces, but I think I'll leave this
project in the experiment pile for the moment. From reading MSDN, it was
clear that a number of the types used with the Shell Extension handlers do
not have native marshalling support or helpers and were designed to be used
in the same apartment.

>> When I register my class it uses the default. Can I change this to
>> apartment?

> Not really. An apartment threaded object should be created on the thread
> that calls CoCreateInstance (assumed to be an apartment thread). This will
> not be the case in Dolphin for an external client

Will a future version of Dolphin be able to deploy in-proc DLLs that can use
the apartment threading model?

Thanks,
Steve
[hidden email]
http://www.dolphinharbor.org


Reply | Threaded
Open this post in threaded view
|

Re: Shell Extension Handler

Steve Alan Waring
In reply to this post by Steve Alan Waring
Hi Blair,

I changed the client to not include the CLSCTX_INPROC_SERVER flag in the
CoGetClassObject function call which stopped the image crashes. In the
server image I could see the interface being answered, but the client got
back E_NOINTERFACE.

I was able to get something working by using my own proxy stub to marshal
the IShellExtInit and IContextMenu interfaces, but I think I'll leave this
project in the experiment pile for the moment. From reading MSDN, it was
clear that a number of the types used with the Shell Extension handlers do
not have native marshalling support or helpers and were designed to be used
in the same apartment.

>> When I register my class it uses the default. Can I change this to
>> apartment?

> Not really. An apartment threaded object should be created on the thread
> that calls CoCreateInstance (assumed to be an apartment thread). This will
> not be the case in Dolphin for an external client

Will a future version of Dolphin be able to deploy in-proc DLLs that can use
the apartment threading model?

Thanks,
Steve
[hidden email]
http://www.dolphinharbor.org


Reply | Threaded
Open this post in threaded view
|

Re: Shell Extension Handler

Blair McGlashan
In reply to this post by Steve Alan Waring
"Steve Waring" <[hidden email]> wrote in message
news:acs1qk$s92hj$[hidden email]...
> ...
> Will a future version of Dolphin be able to deploy in-proc DLLs that can
use
> the apartment threading model?

That is the plan, but it requires new VM technology and so it will not be
the subject of a minor release.

Regards

Blair