Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. C++ ActiveX project worked with VB6, broken in later versions

C++ ActiveX project worked with VB6, broken in later versions

Scheduled Pinned Locked Moved C / C++ / MFC
helpc++visual-studiocom
5 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Burl Rice
    wrote on last edited by
    #1

    I have an ActiveX control (written originally in VC6, and later upgraded to VC 2010). When we first released it, I included a VB6 demo program to show how to use it. This all still works. Recently, a customer requested sample code in VB 2017, and I have found that it crashes in this environment. I have also checked VB 2015 and VB 2010, and they also crash in the same place. Here is a simplified overview of the ActiveX library:

    library BoxWriter
    {
    interface ILine : IDispatch
    {
    [propget, id(8), helpstring("property m_lCount")] HRESULT m_lCount([out, retval] long *pVal);
    };
    interface IPrinter : IDispatch
    {
    [propget, id(1), helpstring("property m_line")] HRESULT m_line([optional, defaultvalue ("")] BSTR strLine, [out, retval] ILine* *pVal);
    };
    };

    Here is a VB code snippet that causes the crash:

    Dim printer As New BoxWriter.PRINTER
    printer.Connect(“192.168.1.3”)
    MsgBox(m_printer.m_line.m_lCount) ‘ <—crashes here

    This is the error it gives:

    An unhandled exception of type 'System.AccessViolationException' occurred in demo.exe
    Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    The reference returned by CPrinter::get_m_line seems to be what it is complaining about. When I debug, I see the reference is set correctly by CPrinter::get_m_line, but after the function returns, something is calling the destructor for the CLine class.

    STDMETHODIMP CPrinter::get_m_line(BSTR bstrLine, ILine **pVal)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    CString strLine = (LPCTSTR)\_bstr\_t (bstrLine);
    CComObject \* pLine = GetLine (strLine);
    
    if (!pLine) {
        return E\_INVALIDARG;
    }
    
    \* pVal = pLine;
    
    return S\_OK;
    

    }

    I have tried creating a new ActiveX project in VC2010, and it also exhibits the same behavior. I tried returning the reference in several different ways (property vs method), and still have not been able to solve this. Surely I am not the first person to encounter this. Can anyone suggest how to fix this?

    L 1 Reply Last reply
    0
    • B Burl Rice

      I have an ActiveX control (written originally in VC6, and later upgraded to VC 2010). When we first released it, I included a VB6 demo program to show how to use it. This all still works. Recently, a customer requested sample code in VB 2017, and I have found that it crashes in this environment. I have also checked VB 2015 and VB 2010, and they also crash in the same place. Here is a simplified overview of the ActiveX library:

      library BoxWriter
      {
      interface ILine : IDispatch
      {
      [propget, id(8), helpstring("property m_lCount")] HRESULT m_lCount([out, retval] long *pVal);
      };
      interface IPrinter : IDispatch
      {
      [propget, id(1), helpstring("property m_line")] HRESULT m_line([optional, defaultvalue ("")] BSTR strLine, [out, retval] ILine* *pVal);
      };
      };

      Here is a VB code snippet that causes the crash:

      Dim printer As New BoxWriter.PRINTER
      printer.Connect(“192.168.1.3”)
      MsgBox(m_printer.m_line.m_lCount) ‘ <—crashes here

      This is the error it gives:

      An unhandled exception of type 'System.AccessViolationException' occurred in demo.exe
      Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

      The reference returned by CPrinter::get_m_line seems to be what it is complaining about. When I debug, I see the reference is set correctly by CPrinter::get_m_line, but after the function returns, something is calling the destructor for the CLine class.

      STDMETHODIMP CPrinter::get_m_line(BSTR bstrLine, ILine **pVal)
      {
      AFX_MANAGE_STATE(AfxGetStaticModuleState())

      CString strLine = (LPCTSTR)\_bstr\_t (bstrLine);
      CComObject \* pLine = GetLine (strLine);
      
      if (!pLine) {
          return E\_INVALIDARG;
      }
      
      \* pVal = pLine;
      
      return S\_OK;
      

      }

      I have tried creating a new ActiveX project in VC2010, and it also exhibits the same behavior. I tried returning the reference in several different ways (property vs method), and still have not been able to solve this. Surely I am not the first person to encounter this. Can anyone suggest how to fix this?

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      At a guess your object is going out of scope and getting destroyed. You need to allocate a fixed block of memory (malloc or new) and copy the data to that block which you can then return. But that also means that the calling method will need to clean up after itself.

      B 1 Reply Last reply
      0
      • L Lost User

        At a guess your object is going out of scope and getting destroyed. You need to allocate a fixed block of memory (malloc or new) and copy the data to that block which you can then return. But that also means that the calling method will need to clean up after itself.

        B Offline
        B Offline
        Burl Rice
        wrote on last edited by
        #3

        I thought that was what CComObject::AddRef was supposed to do?

        L 1 Reply Last reply
        0
        • B Burl Rice

          I thought that was what CComObject::AddRef was supposed to do?

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          Quite possibly but it is not clear in your code where that occurs, and if it applies to the pointer you are passing back.

          B 1 Reply Last reply
          0
          • L Lost User

            Quite possibly but it is not clear in your code where that occurs, and if it applies to the pointer you are passing back.

            B Offline
            B Offline
            Burl Rice
            wrote on last edited by
            #5

            After some experimentation (mostly due to this article: CComObject Class[^]), I have made some progress towards a fix. It seems this line, which was OK in VB6, is no longer appropriate:

            CComObject * pLine = new CComObject ();

            I replaced it with this logic, and my VB 2017 app no longer crashes:

            	CComObject \* pLine;
            
            	HRESULT hRes = CComObject::CreateInstance(&pLine);
            	ATLASSERT(SUCCEEDED(hRes));
            	pLine->AddRef ();
            
            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups