0

So I have tried to debug the program and as soon as I get into the Windows API function calls things get a little crazy, plus there isn't much help with debugging those files because I can't change them anyways. Basically what I am stuck on is the following two functions that I can change (FYI this is really old code and the program works in 32bit versions but when converted to 64bit this problem occurred):

void CSalvoPage::AdviseScrollingButtonPanel()
{
    if ( m_SBPCookie == 0 )
    {
        IUnknown * pSinkUnk;
        long * pCookie = &m_SBPCookie;
        m_spSBPControlSink->QueryInterface(IID_IUnknown, (void **) &pSinkUnk);

        if (pSinkUnk != NULL)
        {
            m_SalvoButtons.AddListener(pSinkUnk, pCookie);//here is the problem~~~~
            pSinkUnk->Release();
        }
    }
}

Then we have the AddListener call which does this

void CNvButtonPanel::AddListener(LPUNKNOWN pUnk, long* pCookie)
{
    static BYTE parms[] =
        VTS_UNKNOWN VTS_PI4;
    InvokeHelper(0x16, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
         pUnk, pCookie);
}

I know for a fact that the InvokeHelper function throws the exception through debugging. All I seem to understand is that parms[] lets the InvokeHelper know what types of parameters it's getting and how many. I looked up the definitions and found that in fact

VTS_UNKNOWN = "\x0D" //IUNKNOWN*

and

VTS_PI4 = "\x43" //a 'long*'

Therefore I am telling the InvokeHelper the correct types of parameters to expect so I don't understand why I get a Type Mismatch Error in a popup window everytime I run the program... Any ideas as to why my InvokeHelper throws the Type Mismatch Error?

I have tried to look into the InvokeHelper method documentation and it's really confusing... What I do know is that it throws the COleException mentioned in the documentation and the SCODE returned from the Invoke method is -2147352571

[id(22), helpstring("method AddListener")] 
            HRESULT AddListener(
                [in] IUnknown * pUnk,
                [out] IUnknown ** pCookie
                );
RAZ_Muh_Taz
  • 4,059
  • 1
  • 13
  • 26
  • show how is calling method(0x16) is declared in `IDL` . which is his signature ? – RbMm Jan 06 '17 at 19:20
  • there is a nvbuttonpanel.h header file and the .cpp for the class but i don't have a .idl file fore the class... I was trying to find how that 0x16 mapped to the AddListener function but the only correlation I see is that the AddListener method is the 22nd method in the header file... @RbMm – RAZ_Muh_Taz Jan 06 '17 at 19:30
  • ok, show `nvbuttonpanel.h` - need understand how is called method declared – RbMm Jan 06 '17 at 19:34
  • no, you not understand me. not this. I mean definition of dispinterface wich method(dispid=0x16) called by `Invoke` – RbMm Jan 06 '17 at 19:45
  • you have some control, which implement `IDispatch` and you call it method (0x16) via `IDispatch::Invoke` - i mean declaration on this interface – RbMm Jan 06 '17 at 19:48
  • I searched the project for IDispatch::Invoke and Invoke and the only thing I get back is InvokeHelper... I have no idea how the InvokeHelper method is supposed to know that 0x16 corresponds to the AddListener function... @RbMm I'm sorry but this code is confusing to me... – RAZ_Muh_Taz Jan 06 '17 at 19:54
  • `m_pCtrlSite->m_dispDriver.m_lpDispatch` in your `CWnd` point to what ? to which OLE control ? you understand whom you call by Invoke ? control implementation is some `DLL` I think. usually this `DLL` have embedded `TLB` - so you can got `IDL` from it with OleView – RbMm Jan 06 '17 at 19:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132530/discussion-between-raz-muh-taz-and-rbmm). – RAZ_Muh_Taz Jan 06 '17 at 20:09
  • look - you have `clsid={ 0x7efdb1b7-` you used it in `CNvButtonPanel::CreateControl` - look in registry which DLL (or OCX does not matter registred under this `clsid` – RbMm Jan 06 '17 at 20:10
  • 1
    Ok i found it in the DLL i'll post it @RbMm – RAZ_Muh_Taz Jan 06 '17 at 20:13
  • One problem is that your parms[] array is not null terminated. Online documentation says it should be null terminated. Makes sense because you are not passing the count of the array, so it must be relying on the null terminator. So, add a 0 as the last member of the parms[] array. – Joseph Willcoxson Jan 06 '17 at 21:48
  • There's something seriously wrong with the pCookie argument. It is *long* in the original code, that makes sense for a listener cookie. But it is IUnknown* in the server. That can still kinda work in 32-bit mode, in 64-bit mode you try to hammer an 8-byte square pointer into a 4-byte round hole. How this got so out of sync is impossible to guess. – Hans Passant Jan 06 '17 at 23:12
  • trust me, i am at awe with how bad this code is and how old it is. It's painful trying to fix it. I was wondering if you knew what the purpose is for the listener cookie? @HansPassant I fixed the issue by changing the AddListener header to match the IDL definition but have no idea what the cookie is for... – RAZ_Muh_Taz Jan 06 '17 at 23:47
  • It is just a wrapper for the IConnectionPoint interface. The returned cookie needs to be used again to call the Unadvise() function. It *really* is a 32-bit variable. You'll have to fix the server and type library to get ahead. The only way that *long* could have showed up at all is that the original programmer got this right 10+ years ago. Then it was touched by somebody that didn't understand it. Well, hopefully it wasn't you and you've got a good source control history :) – Hans Passant Jan 07 '17 at 01:13
  • Yeah this code is exactly that, 10 years old and no one who worked on it originally is still working at the company. it's been "fun" trying to fix bugs in it @HansPassant Thank you for the explanation. – RAZ_Muh_Taz Jan 09 '17 at 16:41

1 Answers1

-1

I was able to fix the issue by doing what RbMm suggested which was to change the function AddListener and RemoveListener functions to match the types declared in the .idl file.

void AddListener(LPUNKNOWN pUnk, LPUNKNOWN* pCookie);
void RemoveListener(LPUNKNOWN pCookie);

The functions now correctly match the types defined in the .idl file

[id(22), helpstring("method AddListener")] 
    HRESULT AddListener(
        [in] IUnknown * pUnk,
        [out] IUnknown ** pCookie
        );

[id(23), helpstring("method RemoveListener")] 
    HRESULT RemoveListener(
        [in] IUnknown * pCookie
        );
RAZ_Muh_Taz
  • 4,059
  • 1
  • 13
  • 26