Question about COM QueryInterface
Before my question I explain my situation.
Situation:
I have a microsoft dll that I wish to use from my mingw C++ project. The dll is a microsoft COM creature. Means the following:
1) I have an IDL (Interface Description Language) file which is a text file describing all the interfaces found inside the dll.
2) All the interfaces are inherited from IUnknown.
3) The IDL file tells me the IID (some identification) of every interface and also the names and parameters of all the functions found inside the dll
Here is how I try to make use of the dll:
1. I initialize the COM with "hr = CoInitialize();" So far so good.
2. I load the dll with "hdll = LoadLibrary("litgen.dll"); No problem.
3. Now to some real work:
Code:
typedef HRESULT (*CreateWriterFType)(IUnknown**);
CreateWriterFType CreateWriter;
CreateWriter = (CreateWriterFType)GetProcAddress( hdll, "CreateWriter" );
hr = CreateWriter( &pUnkLitWriter );
which also compiles and executes nicely.
4. In order to eventually use the functions in the dll I should load some interface with QueryInterface... like this :
Code:
hr = pUnkLitWriter->QueryInterface( IID_ILITWriter, &pLitWriter );
but here is the trouble. In my code the IID_ILITWriter is just placeholder without real value. It's type is REFIID, but this tells me nothing. I can see that it defines the COM interface that I wish to load but how can I initialize it?
So the QUESTION:
How do I get valid REFIID parameter for QueryInterface function??
Re: Question about COM QueryInterface
It's a long time since I had to use COM and I didn't really like it back then (although it is still used extensively, and is at least better than MFC), but I don't think you are supposed to load COM DLLs that way.
Normally the GUID, i.e. that funny looking reference id, is stored in the registry when you register your COM component (DLL) and then when you wish to load it, you use the COM method to create a component (can't remember what it is) with your GUID and it uses the DLL to create it.
When you've done it this way, you can call QueryInterface on your component giving another interface GUID to see if your component implements it. This is, in reality, a type of dynamic_cast.
If you do use COM you should probably use ATL with it. And if you have visual components, use WTL.
By the way, this is probably also in the wrong forum.
Re: Question about COM QueryInterface
Ok About the loading of the dll I followed the instructions in MSDN:
http://msdn.microsoft.com/library/de...interfaces.asp
They explain there that for litgen.dll there is no need to load litgen to register or anything like that. But I admit that they mention i should generate litgen.h for my project with their "midl.exe" program... but anyways i have no "midl.exe" in my harddrive and no way to get it from internet.
But if I knew how to generate a valid REFIID to give for the QueryInterface my problem should be solved. Besides I think that the missing midl.exe just creates the REFIID constants from the IDL file and puts this info into the header.
About the ATL and WTL I think it requires me to use Visual C++. Remember that I am doing my project with mingw which is a gcc variant. And that is also why I posted my question here in the C++ (Non-Visual C++ Issues) forum.
Re: Question about COM QueryInterface
There are three ways you can go about this. You can try to get .h files compiled by midl (there may be other IDL compilers, not sure though), you could try to use IDispatch or you could write the headers by hand.
I guess the IDispatch route would be OK for a start (it's slightly slower and has more overhead than calling the objects directly, but you don't even need an idl for it).
Here is some code that uses IDispatch to get a handle to Word's Application object.
Code:
CLSID w;
memset(&w, 0, sizeof(w));
// You may want to use CoInitializeEx instead
CoInitialize(0);
HRESULT hr = CLSIDFromProgID(L"Word.Application", &w);
IUnknown *p = 0;
hr = CoCreateInstance(w, 0, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void **) &p);
IDispatch *pD = 0;
hr = p->QueryInterface(IID_IDispatch, (void **) &pD);
// Now pD points to a Word.Application object (in case nothing went wrong)
Re: Question about COM QueryInterface
How about writing the headers by hand. I think my DLL doesn't have that IDispatch interface, meaning perhaps it's not a full featured COM.
I think I can manage writing the interfaces... Nothing too difficult there.
but I think I should write to the header something like following:
Code:
REFIID IID_ILITCallback = ??????????????????;
where the ?????????????????? part is the problem .. I don't know what to write here.
I assume that the answer comes from the .idl file: where
Code:
[object, uuid(6BC62165-B91C-4993-8002-5BC30B2D1196)]
interface ILITCallback : IUnknown
{
but how to convert this uuid(6BC62165-B91C-4993-8002-5BC30B2D1196) into type REFIID ????
1 Attachment(s)
Re: Question about COM QueryInterface
I downloaded the content sdk, took a look through the samples and it seems pretty straightforward if you are using Visual C++, although it's really quite strange to have to use LoadLibrary. There's also appears to be a memory leak in the line:
Code:
ILITCallbackPtr pCallback(new ErrHandler);
How is the 'new' released? Is the com object suppose to do it? Pretty non-standard.
Anyway, I've attached the midl output of litgen.idl (litgen.h, litgen_i.c, and ligen_p.c).
Hopefully this helps.
Arjay
Re: Question about COM QueryInterface
Many Thanks for your answer and trouble.. I think this helps me to get on with my project.