0

In C++, I'm trying to call an OLE method which looks like this:

HRESULT GetFirstMono(
       [out] BSTR* name, 
       [out, retval] BSTR* monoID);

I use the following code to call it (adapted from http://www.codeproject.com/KB/office/MSOfficeAuto.aspx ):

int cArgs = 1;
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
VARIANT *pArgs = new VARIANT[cArgs+1];
// Extract arguments...
for(int i=0; i<cArgs; i++) {
    pArgs[i] = va_arg(marker, VARIANT);
}

// Build DISPPARAMS
dp.cArgs = cArgs;
dp.rgvarg = pArgs;

// Make the call!
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp,
        pvResult, NULL, NULL);
    if(cArgs == 1) {
        std::cout << "oleCall()" << std::endl;
        std::cout << "vt: " << dp.rgvarg[0].vt << std::endl;
    }

The program excecutes without crashing, and I receive the monoId output BSTR* in pvResult (and I get the value that I expect). But instead of finding name, I only get an empty variant in dp:rgvarg[0], i.e. on my terminal I see

oleCall()
vt: 0

. The exact same method works fine when I call it from LabView, so I figure the problem is somewhere in my code. How can I recover the name output?

xqrp
  • 137
  • 13
  • Shouldn't `dp.cArgs` contain the value `2` (I mean`dp.cArgs = cArgs+1`)? Because the method expects two parameters. If that does not help: check the `HRESULT` return value of `Invoke`. – vstm Nov 25 '11 at 10:24
  • I'm not quite sure why, but if I set `dp.cArgs = cArgs+1`, the program crashes. As far as I can tell, the parameter marked as *retval* is returned with the variant `pvResult`; the other one should be returned via `dp`. I'm pretty sure that the result I want won't be in the HRESULT, because that's only used for error management etc. – xqrp Nov 25 '11 at 11:00

2 Answers2

0

In case someone else is having the same problem: I wasn't able to solve it, but here's a workaround. Instead of using the Invoke method of the IDispatch interface, I made a header file for the interface in which GetFirstMono is declared, using a Microsoft program called MIDL - but one can also do it by hand (simply look up the methods of the interface with the ole/com viewer and write a corresponding header file). Then, the call to the method is quite simple:

BSTR name, monoId;
HRESULT hr = interfacePointer->GetFirstMono(name, monoId);

There's more information at codeguru.com . Hope it helps.

BTW: I'm still interested in the original question. If you know the answer, please post it!

xqrp
  • 137
  • 13
0

Try to set type VT_BSTR|VT_BYREF to argument 0.

CComBSTR bstrName;
V_VT(&dp.rgvarg[0]) = VT_BSTR | VT_BYREF;
V_BSTRREF(&dp.rgvarg[0]) = &bstrName;
KAdot
  • 1,997
  • 13
  • 21