AnsweredAssumed Answered

vrf QueryInterface Functionality in VEE

Question asked by VRFuser on Apr 22, 2003
Christina -

> We are trying to use COM components
> that have multiple interfaces.

Your question *must* be a sign from god that I'm supposed to finish up my
little surprise for yall. For several weeks now I've been investigating the
ins and outs of using COM in VEE and, in a phrase, it ain't easy.

Actually *using* the interface pointer is quite difficult, but it looks like
you are more interested in simply getting an interface pointer and using it
outside of VEE. In that case, the following information will be of help.

In case you really just want a simple explanation, press Ctrl-End now

The VEE function CreateObject returns an IDispatch pointer retrieved from
CoCreateInstance(Ex) with the REFIID parameter set to IID_IDispatch (aka
{00020400-0000-0000-C000-000000000046}) and the CLSID from the CLSID key of
the corresponding ProgId entry in the registry. Though you theoretically
*could* call QueryInterface with this pointer, it's not something you'd
really want to do given that you have to generate all the machine code to do
so by yourself, chuck it into memory and then find some way to coerce VEE
into calling it.

It's far easier to call CoCreateInstance yourself with the IID of the
interface you actually want in the first place. For instance, let's say you
want the IClipbrd interface of the Clip.Clipbrd library. I recently posted
this library for clipboard access in VEE. First, open the registry key:

HKCRClip.Clipbrd

where HKCR is short for HKEY_CLASSES_ROOT. This is how ProgIds are
associated with class objects. To illustrate an example often used on the
reflector, open your own registry to:

HKCRExcel.Application

This is how VEE translates:

CreateObject("Excel.Application");
            or
CreateObject("Clip.Clipbrd");

into something it can actually use. You'll see a sub key called CLSID: CLaSs
object IDentifier. This is the first piece of information you'll need. In
the Excel example, version 9's CLSID is:

{00024500-0000-0000-C000-000000000046}

Clip.Clipbrd's CLSID is:

{0AF66734-CB6C-4E97-B24D-9A280AB5B5F6}

Having said all that, there is a function called CLSIDFromProgId that can
save you the trouble of looking in the registry. You first have to convert
the ANSI ProgId string to an OLESTR string with MultiByteToWideChar though.

Now, you need the IID of the interface you're after. Every interface
registered on your machine is listed in the registry as sub keys of the key:

HKCRInterface

To get the IID, you enumerate sub keys of this key looking for the ASCII IID
your after. I don't know any for Excel, but the Clipboard control implements
the IClipbrd interface. I made it a dual-interface library because I'll be
using it as a follow-up to the last clipboard post. Anyway, we have:

HKEY_CLASSES_ROOTInterface{8084CC80-5602-450E-8966-931851660763}

The default value of this key is IClipbrd. The key name is the IID we're
after. So now we have the information we need to call CoCreateInstance:

CLSID: {0AF66734-CB6C-4E97-B24D-9A280AB5B5F6} = Clip.Clipbrd
IID  : {8084CC80-5602-450E-8966-931851660763} = IClipbrd

The next step is to translate the string representations of these
identifiers into their actual GUID representations. A GUID is a structure
consisting of a DWORD (unsigned long), two WORDs (unsigned short) and an
array of eight BYTEs (unsigned char). I use a VEE array of 4 int32s to
emulate this structure. That leaves the actual conversion. Fortunately the
API function CLSIDFromString does this. The matching function is more aptly
named: StringFromGUID2. Don't let the names fool you. A CLSID is an IID is a
GUID. They're all formally GUIDs, they're just named differently to indicate
their meaning:

GUID  - Globally Unique IDentifier
CLSID - CLaSs object IDentifier
IID   - Interface IDentifier

At any rate, the CLSIDFromString function only takes OLESTR strings, not
ANSI strings. The function MultiByteToWideChar converts an ANSI string to an
OLESTR string. Once you have the CLSID and IID as actual GUIDs, you can call
CoCreateInstance and get your interface pointer. All of this can be done
quite neatly in VEE. If you're still interested in doing this, I have a
working example that I can email to you next week if you like. I had planned
on posting it to the list when I get parts 2 and 3 of the series done, but
that could take a while as the busy season is upon us now.

To sum up, the steps are:

  1) Open HKCR<ProgId>CLSID and read default value.
     RegOpenKeyEx, RegQueryValueEx, RegCloseKey

  2) Open HKCRInterface and enumerate sub keys, looking for interface name.
     RegOpenKeyEx, RegQeryInfoKey, RegEnumKey, RegQueryValueEx, RegCloseKey

  3) Using array of int32, convert ANSI CLSID and IID to raw GUIDs.
     MultiByteToWideChar, CLSIDFromString, IIDFromString
     [NOTE: theoretically, the last two functions are identical
            but I've learned it's not wise to mess with the
            Windows gods]

  4) Call CoCreateInstance.

And yes, I swear on my mother's grave that all this is really not at all
difficult and works out very neatly in VEE thanks to VEE wrapper functions
(which hopefully will shortly be mentioned in T&MW - plug plug).

Now I bet that's really a hell of a lot more than you wanted to know
-SHAWN-


---
You are currently subscribed to vrf as: rsb@soco.agilent.com
To subscribe send a blank email to "join-vrf@it.lists.it.agilent.com".
To unsubscribe send a blank email to "leave-vrf@it.lists.it.agilent.com".
To send messages to this mailing list,  email "vrf@it.lists.it.agilent.com". 
If you need help with the mailing list send a message to "owner-vrf@it.lists.it.agilent.com".

Outcomes