Link to home
Start Free TrialLog in
Avatar of barrett
barrett

asked on

ADO Recordsets as DISPPARAMS in C++?

I have an MTS component authored in VB (it's a remote server), and I'd like to call methods on it from C++ (ATL). I can get an IUnknown pointer from CoCreateInstance, then an IDispatch pointer from CComQIPtr, then I can get the dispId of a method from pDisp->GetIDsOfNames (dispId comes back as 0x60030003), but I don't know how to set up the DISPPARAMS to call Invoke correctly.

The signature of the method is:
GetSessionID( [out] _Recordset** ppSessionRS, [out] _Recordset** ppErrorRS) in IDL style, or

GetSessionID( Recordset SessionRS, Recordset ppErrorRS) in VB style.

So I'm setting up my DISPPARAMS like this:

DISPPARAMS dispParams;
VARIANTARG vtArgs[2];
dispParams.rgvarg = vtArgs;
dispParams.rgvarg[0] = VT_DISPATCH; // do I need | VT_BYREF?
dispParams.rgvarg[1] = VT_DISPATCH;
dispParams.cArgs = 2;
dispParams.cArgs = 0; // 2?

hr = pDisp->Invoke( dispID // 0x6003003, a reasonable value?
                    IID_NULL,
                    GetUserDefaultLCID(),
                    DISPATCH_METHOD,
                    &dispParams,
                    NULL,
                    NULL,
                    NULL );

I get back 0xc0000005 (Access Violation) in hr. How do I set up dispParams correctly?



Avatar of jhance
jhance

0x60030003 is an odd value for a dispid.  What HRESULT is GetIDsOfNames returning?  If it's not S_OK, then you cannot use the dispid returned.

The most common mistake I've seen with GetIDsOfNames is not converting the name you want to find to a proper OLE string.
Avatar of barrett

ASKER

GetIDsOfNames is returning S_OK, although I though that dispId looked weird as well. Here's my declaration for the name:

OLECHAR* szName = L"GetSessionID";

The example I was using wanted it to look like:

OLECHAR* szName = _T( "GetSessionID" );

but that wouldn't compile...
I'd have to conclude that if GetIDsOfNames is returning S_OK, that it's the right dispid.  Have you looked at the object in the OLE Viewer and check the dispids?
> do I need | VT_BYREF?

Yes, you have to.
Since it is an out pointer to pointer.
So you have to pass reference.

> dispParams.cArgs = 2;

It should be 2.

> I get back 0xc0000005 (Access >Violation) in hr. How do I set up >dispParams correctly?


The following problems can happen.

You should Initialize the variant to
VT_EMPTY for being safe side though
it is not an input parameter.


You are getting access violation
as you are not using the
VT_DISPATH | VT_BYREF.

Avatar of barrett

ASKER

Unfortunately, I still get the same behavior when I use VT_DISPATCH | VT_BYREF.

In answer to jhance's question, when I look at the object in the OLE/COM Viewer, the dispId is, in fact, 0x60030003, so that much is working correctly.

I just discovered the solution, however. I've declared two Recordset objects:

_RecordsetPtr pSessionRS(__uuidof(Recordset) );

_RecordsetPtr pErrorsRS(__uuidof(Recordset) );

In addition to setting the variant type to VT_DISPATCH|VT_BYREF, I need to set the ppdispVal value, like so:

vtArgs[0].ppdispVal = (IDispatch**)&pSessionRS;
vtArgs[1].ppdispVal = (IDispatch**)&pErrorsRS;

Now the Invoke call succeeds. Seems rather obvious now...

Thanks for the help, everybody!
ASKER CERTIFIED SOLUTION
Avatar of basant
basant

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial