QueryInterface() throws Exception in version 3.3.6

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

Post Reply
incredible_uk
Posts: 6
Joined: Tue May 29, 2007 11:38 pm

QueryInterface() throws Exception in version 3.3.6

Post by incredible_uk »

Hello,

I use the 3DxInput COM API in Borland C++ Builder 2006. I imported the type library und use the following code to connect to device:

IUnknown *m_pDev;
ISimpleDevice *m_pSimpleDev;

m_pDev = CreateComObject(CLSID_Device);
m_pDev->QueryInterface(&m_pSimpleDev);
m_pSimpleDev->Connect();

This code worked fine for me in my former driver version 3.2.2. Now I installed the new driver 3.3.6 and now I get a 'Privileged Instruction' exception as soon as I call m_pDev->QueryInterface(&m_pSimpleDev);

I imported the type library again after the new driver was installed but this did not fix the problem. I then reinstalled version 3.2.2 and everything worked fine again.

Does someone have any idea what is going wrong here or did I miss something?

Thank you in advance

Uwe
ngomes
Moderator
Moderator
Posts: 3334
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Hi incredible_uk,

We do not use Borland tools to test the COM API so there might be something going on there. Just to be on the same page, would it be possible for you to try a sample from our SDK page? You would need to use Visual Studio 2005.

If not, there's a few thing you can check. Are you instantiating the COM object in a thread with a message pump? That's required for the current version. If you are, is there something like a splash banner that gets closed after the COM object is created?
Nuno Gomes
incredible_uk
Posts: 6
Joined: Tue May 29, 2007 11:38 pm

Post by incredible_uk »

Hello,

I instantiate the COM object in the main thread of the application. It is a real windows application (no console application) so I think the main thread should have a message pump. With version 3.2.2 I can also receive and handle sensor input events. There is also no splash banner that gets closed and all the COM object handling is not done in a constructor.

There is a button on my main form and if I hit this butten, then the code from my first post is executed. This works fine for version 3.2.2 but fails for version 3.3.6.

I have Visual Studio 2005 here and will try the SDK examples.
incredible_uk
Posts: 6
Joined: Tue May 29, 2007 11:38 pm

Post by incredible_uk »

Hello,

I've compiled the SDK demo CubePolling and it works fine but the application compiled with C++ Builder still produces an exception (version 3.3.6) - strange. I have to investigate further.
ngomes
Moderator
Moderator
Posts: 3334
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Is it possible for you to send us an executable that gives up the ghost? Something simple (not your entire app)?
If yes, let us know we will contact you on a PM.
incredible_uk
Posts: 6
Joined: Tue May 29, 2007 11:38 pm

Post by incredible_uk »

Hello,

you can download the application here:

http://www.cetoni.de/test_3dxware.exe

It runs fine with driver version 3.2.2 and crashes with version 3.3.6.
The problem is the QueryInterface() call - the creation of the COM object works fine also in version 3.3.6 - the debugger shows two new threads that are created after the call of m_pDev = CreateComObject(CLSID_Device); But when I call hr = m_pDev->QueryInterface(&m_pSimpleDev); in the next step then this call fails for version 3.3.6 - and at the moment I don't have any idea why?!?
ngomes
Moderator
Moderator
Posts: 3334
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Thanks, incredible_uk. It is easily reproducible.

For your reference, I've logged this issue with tracking number 4497. As soon as we have something on that, we will get back to you.
ngomes
Moderator
Moderator
Posts: 3334
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Hi incredible_uk,

It seems that you're releasing the device pointer before the QueryInterface call.

Have you verified if the output of CreateComObject() is valid before using it?
incredible_uk
Posts: 6
Joined: Tue May 29, 2007 11:38 pm

Post by incredible_uk »

Hello,

yes, I verify the device pointer before using it. If I would release the device pointer it also would be invalid in version 3.2.2 - but in this version it works. This is the source:

m_pDev = CreateComObject(CLSID_Device);
if (!m_pDev)
{
return false;
}
hr = m_pDev->QueryInterface(&m_pSimpleDev);

I debugged a little more and have found an intersting difference between the behaviour of CreateComObject(CLSID_Device); in both versions:

This ist the interesting part of CreateComObject():

function CreateComObject(const ClassID: TGUID): IUnknown;
begin
try
OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IUnknown, Result));

The call to CoCreateInstance() instantiates the COM object and returns the pointer in Result. (OleCheck simply checks the HRESULT and raises an execption if HRESULT is != S_OK - but HRESEULT is ok and this is not interesting here). If I single step this function in 3.2.2 then after the call of CoCreateInstance() the execution halts in OleCheck which checks the return value.

But if I single step CreateComObject() in version 3.3.6 then right after execution of CoCreateInstance() the debugger does not halt in OleCheck() but it stops in StdWndProc - that indicates that a windows message is raised rigth after execution of CoCreateInstance(). This does not happen for version 3.2.2. Here are the message parameters: Msg: 0x210 WParam: 0x42BC0001.

If StdWndProc is executed, the program flow follows the same way like in 3.2.2. Right before I leave the function CreateComObject(), I reach this code:

__fastcall ~DelphiInterface<T>()
{
if (intf != 0)
{
intf->Release();
intf = 0;
}
}

This happens for 3.2.2 and 3.3.6. But if I single step the line

intf->Release()

the in version 3.2.2 the execution stops in next line (intf = 0). In version 3.3.6 again it stops in StdWndProc. Now the message parameters (WParam) is slighly different: Msg: 0x210 WParam: 0x42BC0002. After execution of StdWndProc the execution halts in line intf = 0 like in version 3.2.2.

If I leave this function then I'm back in my application. Then the next call, QueryInterface() works in 3.2.2 and fails in 3.3.6. So it looks like the different behaviour causes a damage of the pointer or something else - but this is not aplication specific because everything in CreateComObject() is not part of my application.

This is everything I can say about the stuff. What is your opinion? Does it look like a Borland VCL problem. Do you know the 2 messages (ID 0x210) that occur in version 3.3.6.

Best regards, Uwe
ngomes
Moderator
Moderator
Posts: 3334
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

The transport mechanism (device to application) currently relies on window messages, so it is not a surprise that you're seeing the message callbacks to your win proc.

From what you report, it seems that the line

Code: Select all

 intf->Release(); 
is terminating the object. This can happen if there's a missing AddRef() call.

I do not have access to Borland c++ Builder documentation nor do I have experience with its syntax but perhaps your "m_pDev" variable (an IUnknow*) should be a "smart pointer". Do you see any calls to AddRef() on the "Result" variable? That should happen for simple pointer types before the function CreateComObject() returns.
incredible_uk
Posts: 6
Joined: Tue May 29, 2007 11:38 pm

Post by incredible_uk »

Ok - I finally managed the version 3.3.6 to work in Borland C++ Builder. I replaced the Borland function CreateComObject() by the Windows function CoCreateInstance:

//m_pDev = CreateComObject(CLSID_Device);
CoCreateInstance(CLSID_Device,
0,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IUnknown,
(void**)&m_pDev);

And now it works:o) But StdWndProc is still called right after call to CoCreateInstance(). Something in CreateComObject() does not seem to work like it should do.

Thank you for your support and sorry for the work caused by the Borland guys.
ngomes
Moderator
Moderator
Posts: 3334
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

incredible_uk wrote:Thank you for your support and sorry for the work caused by the Borland guys.
No worries. That's what we're for. We very much appreciate your efforts in supporting our products.

CoCreateInstance() will AddRef() the output interface pointer before returning. I believe that CreateComObject() may be relying on "smart pointers" and that your code may be only using simple types.

The messages that you see being sent to the win proc are normal. That's part of the current implementation of 3DxInput. That will likely change sometime in the future but the interface will -- obviously enough -- remain consistent.
Post Reply