COM+: CoInitialize(NULL) always fails

Posted By: HeelX

COM+: CoInitialize(NULL) always fails - 09/06/11 19:09

Hi,
my client passed me a COM+ DLL, written in VB6, which now works in a standard MS VS2005 console application (click image to enlarge):



Now, in Lite-C I just want to do the same. I read through all pages in the manual regarding COM and also digged the forum. It seems that only a few tried that. My options are either writing the COM connection in Lite-C (preferred) or writing a wrapper DLL in C++/VS2005 (will work for sure, but I really don't want to do that).

Now, if I run CoInitialize, it already fails, it says: "CoInitialize Failed: 1"...:

Code:
#include <acknex.h>
#include <default.c>
#include <com.h>
	
int main ()
{
	// open the COM interface
	HRESULT hr = CoInitialize(NULL);
	if (hr != S_OK)
	{
		printf("CoInitialize Failed: %x\n\n", hr);
		return 0;
	}
	else 
		printf("CoInitialize succeeded\n");
}



So, what is going on? I don't know, since CoInitialize does not fail in my C++ app, but in Lite-C...?
Posted By: Nicholas

Re: COM+: CoInitialize(NULL) already fails - 09/07/11 00:24

I'm guessing you're trying to connect to an external device through a com port.
if not, ignore this :-p
I am trying to do the same thing and am having a lot of luck using the code that EvilSOB came up with.
here's the link
http://www.opserver.de/ubb7/ubbthreads.p...true#Post280484

I got someone to write me a c++ dll for it a few years ago, but never got the flexibility I needed from it.
good luck
Posted By: HeelX

Re: COM+: CoInitialize(NULL) already fails - 09/07/11 07:25

Hi Nicholas,
hmn, in the end it will connect indeed to an external device, but in my case I need to connect to a DLL, which is accessible via COM. The DLL has been written in VB6 and this is the only way to connect to it from a C++ app. If I get not any further with this these days I will write a wrapper DLL.

I am just a bit curious because even the initialization function fails, but in my console application not.

P.S: Happy birthday!
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/07/11 20:47

Hm, no one?
If I get it not to work until Sunday evening, I will have to write a wrapper DLL... frown
Posted By: Myrkling

Re: COM+: CoInitialize(NULL) always fails - 09/07/11 21:48

Isn't S_FALSE (==1) returned if COM is already initialized?

It seems to work when CoUninitialize() is called before CoInitialize(). At least the "CoInitialize succeeded" message is shown then.
Perhaps COM gets initialized automatically by lite-C?
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/07/11 22:55

Originally Posted By: Myrkling
It seems to work when CoUninitialize() is called before CoInitialize(). [...] Perhaps COM gets initialized automatically by lite-C?


Indeed! When I execute CoUninitialize(); before CoInitialize(NULL); it seems to succeed. Weird!!

OK, I will now try to access the DLL functions. In the meantime it would be cool if JCL or alike could tell us / me, why I have to uninitialize it before I initialized it? I thought that CoInitialize has to be called only once on a thread, so it seems that this has been done already by Lite-C.

I have the feeling that the "NETPORT I/O modules over the network" feature could be related to it... Hmmm. At least, it is suspicious grin
Posted By: TechMuc

Re: COM+: CoInitialize(NULL) always fails - 09/07/11 22:57

http://msdn.microsoft.com/en-us/library/ms680582(v=vs.85).aspx

Implement this to get the last error description laugh
PS: though probably the solution of my preposter is correct...
Posted By: jcl

Re: COM+: CoInitialize(NULL) always fails - 09/08/11 08:14

You need neither to uninitilize nor initialize it. COM is already initialized on the engine thread.
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/08/11 10:40

Originally Posted By: jcl
You need neither to uninitilize nor initialize it. COM is already initialized on the engine thread.


Didn't know that. Where is this written in the manual? Because the only COM example in the manual uses actually CoInitialize.

Thanks!
Posted By: jcl

Re: COM+: CoInitialize(NULL) always fails - 09/08/11 10:43

This info will be added to the manual. But the example in the manual is correct; engine programs are not the same as Windows programs, called 'legacy mode'.
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/08/11 12:26

Originally Posted By: jcl
This info will be added to the manual. But the example in the manual is correct; engine programs are not the same as Windows programs, called 'legacy mode'.


Nice to know! Thank you very much smile
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/09/11 16:56

Me again smile I finally made CoCreateInstance to succeed.

Well, my generated header file (I use the #import directive for .tlb type library files) contains named, pre-initialized GUIDs like these:

Code:
extern "C" const GUID __declspec(selectany) IID_iInterface =
    {0xf9f48469,0x68ab,0x3013,{0xb8,0x06,0xdd,0xa2,0x09,0x63,0xda,0xfb}};
extern "C" const GUID __declspec(selectany) CLSID_ComPlusClass =
    {0x2f307f57,0xb30a,0x3bdf,{0x83,0x15,0x95,0x26,0x6f,0x00,0x61,0x48}};


So I tried to use them in Lite-C, too, but

Code:
GUID IID_iInterface =
    {0xf9f48469,0x68ab,0x3013,{0xb8,0x06,0xdd,0xa2,0x09,0x63,0xda,0xfb}};


just throws a syntax error during compilation. Is there a way to overcome this?

Anyway, the file also contained uuid's like these lines:

Code:
struct __declspec(uuid("f9f48469-68ab-3013-b806-dda20963dafb"))
/* dual interface */ iInterface;


and I used them like this:

Code:
GUID CLSID_ComPlusClass;
IIDFromStr("{2f307f57-b30a-3bdf-8315-95266f006148}", &CLSID_ComPlusClass);
	
IID IID_iInterface;
IIDFromStr("{f9f48469-68ab-3013-b806-dda20963dafb}", &IID_iInterface);



and my structs are looking like that:

Code:
typedef struct _iInterfaceVtbl
{
	// COM object standard methods
	HRESULT __stdcall QueryInterface (void* This, IID *riid, void** ppvObject);
	DWORD __stdcall AddRef (void* This);
	DWORD __stdcall Release (void* This);

} iInterfaceVtbl;

typedef interface iInterface {iInterfaceVtbl* lpVtbl;} iInterface;



and CoCreateInstance --succeeds--! Yeah smile

Being happy, I wanted to test out, if the method calls to the classe are working. My header file tells me the following:

Code:
struct __declspec(uuid("f9f48469-68ab-3013-b806-dda20963dafb"))
iInterface : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    long SetHeartCoherence (
        long the_heart_coherence );
    long GetHeartCoherence ( );
    long SetInterbeatIntervalCircleData (
        BSTR data );
    BSTR GetInterbeatIntervalCircleData ( );
    long SetAmplitudeHartritmeVariatie (
        double data );
    double GetAmplitudeHartritmeVariatie ( );
    long SetInterbeatInterval (
        long data );
    long GetInterbeatInterval ( );
    long SetAverageHeartbeat (
        long data );
    long GetAverageHeartbeat ( );
    long SetAdemhalingsFrequentie (
        double data );
    double GetAdemhalingsFrequentie ( );
    long SetFFTArray (
        BSTR data );
    BSTR GetFFTArray ( );

    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall raw_SetHeartCoherence (
        /*[in]*/ long the_heart_coherence,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetHeartCoherence (
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_SetInterbeatIntervalCircleData (
        /*[in]*/ BSTR data,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetInterbeatIntervalCircleData (
        /*[out,retval]*/ BSTR * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_SetAmplitudeHartritmeVariatie (
        /*[in]*/ double data,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetAmplitudeHartritmeVariatie (
        /*[out,retval]*/ double * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_SetInterbeatInterval (
        /*[in]*/ long data,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetInterbeatInterval (
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_SetAverageHeartbeat (
        /*[in]*/ long data,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetAverageHeartbeat (
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_SetAdemhalingsFrequentie (
        /*[in]*/ double data,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetAdemhalingsFrequentie (
        /*[out,retval]*/ double * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_SetFFTArray (
        /*[in]*/ BSTR data,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall raw_GetFFTArray (
        /*[out,retval]*/ BSTR * pRetVal ) = 0;
};



and I wanted to call the method, which is working in my C++ console application, which is looking like this::

Code:
if (hr == S_OK)
	{
		int m_hr = pComInterface->GetHeartCoherence();
		sprintf (stringbuffer, "%d ", m_hr);
		printf ("HeartCoherence result: [%s]", stringbuffer);
	}


So I took it simple and added the "getHeartCoherence" method to the Lite-C _iInterfaceVtbl struct as follows:

Code:
typedef struct _iInterfaceVtbl
{
	// COM object standard methods
	HRESULT __stdcall QueryInterface (void* This, IID *riid, void** ppvObject);
	DWORD __stdcall AddRef (void* This);
	DWORD __stdcall Release (void* This);
	
	// specific methods
	long __stdcall GetHeartCoherence (void* This);
	
} iInterfaceVtbl;


Now, if CoCreateInstance is OK, I just execute

Code:
long hc = pComInterface->GetHeartCoherence();
printf("HeartCoherence result: [%d]", (int)hc);



As soon as a I call the method, the engine simply -!!-crashes-!!-. Now I am not happy anymore wink

So, here are my summarized questions:

1) How do I use the above listed preinitialized GUIDs?
2) What have I forgotten?
3) What could be the reason for the crash?
Posted By: Tobias

Re: COM+: CoInitialize(NULL) always fails - 09/10/11 09:37

Looks as if the function parameter is missing in your GetHeartCoherence declaration?
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/10/11 10:07

Which one?

The declaration is in the vtable struct:
Code:
long __stdcall GetHeartCoherence (void* This);



The This pointer is added because the manual says:
Quote:
Note that each of the methods has an additional parameter called "This". You have to pass the This pointer parameter explicitly in C, but it can be passed automatically in lite-C. Any additional parameters come after This, as above.


So I guess when I call a method with a void parameter, I just call and declare it like I do in the above post...?
Posted By: Tobias

Re: COM+: CoInitialize(NULL) always fails - 09/10/11 10:20

Yes, I looked at the wrong function, SetHeartCoherence that needs a long parameter. I had a similar job last year and found no problem with COM interfacing, so I don't know why it crashes, but you can see an example for a COM interface in pictures.h.

Another idea, the virtual functions in your header look as if those functions must be defined before calling the method, maybe the method crashes when its virtual function is not defined.

Or one little thing, in your typedef the interface name and type name are the same (iInterface), in the examples they are different, maybe that's also causing a problem.
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/10/11 12:39

I added all methods and then I looked into picture.h and there wasn't
Code:
// COM object standard methods
HRESULT __stdcall QueryInterface (void* This, IID *riid, void** ppvObject);
DWORD __stdcall AddRef (void* This);
DWORD __stdcall Release (void* This);



as opposed to what is stated in the manual.. hmmm. After I removed that in my code, the engine didn't crashed anymore. Though, I get a wrong return value for my function - but that could be related to the DLL.

Nevertheless, that DLL uses a BSTR, has anyone successfully send and received a BSTR from a VB6 DLL? I made this typedef chain, I am not sure if this is correct, but it compiles very well:

Code:
// typedef chain for BSTR
typedef unsigned short wchar_t;
typedef wchar_t WCHAR;
typedef WCHAR OLECHAR;
typedef OLECHAR* BSTR;
typedef BSTR* LPBSTR;



@Tobias: do you know how I can use the above posted preinitialized GUIDs?
Posted By: Tobias

Re: COM+: CoInitialize(NULL) always fails - 09/11/11 08:19

Hmm, I had the standard methods also defined in my struct and it worked. Dunno why it crashes for you. In the d3d9.h header there are lots of those interfaces and they all have the standard methods included. I needed them also because I call Release().

You use the preinitialized GUID for the first parameter when you call CoCreateInstance.

I have not yet had a BSTR but believe it is not a char* but a struct similar to CString. In that case your typedef chain would not work.
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/11/11 09:16

Originally Posted By: Tobias
You use the preinitialized GUID for the first parameter when you call CoCreateInstance.


I wrote that
Code:
GUID IID_iInterface =
    {0xf9f48469,0x68ab,0x3013,{0xb8,0x06,0xdd,0xa2,0x09,0x63,0xda,0xfb}};



doesn't compile for me. Try yourself!
Posted By: Joey

Re: COM+: CoInitialize(NULL) always fails - 09/11/11 16:04

BSTR stores the string length in some bytes before the string. Use SysAllocString and SysFreeString for conversion.
Posted By: jcl

Re: COM+: CoInitialize(NULL) always fails - 09/12/11 12:56

HeelX: This line won't even compile - lists are only possible for array definitions. Look in the manual DLL interface chapter for the correct syntax to define a GUID. You had it already right in your previous example. You can also find an example in the pictures.h header as Tobias suggested, and use that as a template.

A GUID is a 16-byte sequence that you use for uniquely identifying a COM interface. You use it for example when you create an instance of that interface.
Posted By: HeelX

Re: COM+: CoInitialize(NULL) always fails - 09/12/11 15:18

Ok, thanks for clarification.

I still have trouble with getting the right results. The GetHeartCoherence function returns a long and the DLL returns always 123 in my VC++ app (because this is a debug version for me), but in Lite-C I get a 2 - and 123 is confirmed by the developer that this is the right return value.

Can you imagine why this could happen?
Posted By: jcl

Re: COM+: CoInitialize(NULL) always fails - 09/13/11 09:07

Not without knowing more of that DLL. If you get a 2, I'd suspect you called a wrong function, as the 2 could be the return value of AddRef. Make sure that your Vtbl contains the same functions in the same order and with the same types as in the orginal DLL; the 3 standard methods must be at the start. If some type is not supported by lite-C, find an equivalent of the same size - usually a long or void* works for everything.

If the class inherits something, be sure to add the inherited methods directly after the 3 standard methods, followed by the specific methods of the class. See the example in the manual.
© 2024 lite-C Forums