0
votes

Why this error is occurred? References count is increased, threading models is single appartment. Coll-object and EmptyColl-function both located inside one dll. Default calling conversion of ATL project is __stdcall. Same error occured with other objects inside this dll.

VariantClear throws exception when clearing VARIANT with NULL-object:
Exception thrown at 0x75C14974 (oleaut32.dll) in VB6.EXE: 0xC0000005:
Access violation reading location 0x00000008.

frmMain.frm (error, see below why):

Private Sub Form_Load()
  Dim c As Coll
  Set c = EmptyColl
  'error when ends here with variable "c" in the watch window.
End Sub

frmMain.frm (no error):

Private Sub Form_Load()
  Dim c2 As Coll 'instead of Coll can be any object of same library
  Set c2 = New Coll 'creation
  Set c2 = Nothing 'destroying (optionaly)
  Dim c As Coll
  Set c = EmptyColl
  'no error
End Sub

filyus.idl:

[
  object,
  uuid(6FA7FAEB-5CE3-4A80-9288-2667EE5E7596),
  dual,
  nonextensible,
  pointer_default(unique)
]
interface IColl : IDispatch{
  //some methods
};

[
  uuid(157F3D2F-A427-4D5A-B908-87868297EA43),
  version(1.0),
]
library Filyus
{
  importlib("stdole2.tlb");
  [
    dllname("Filyus")
  ]
  module Filyus{
    [entry("EmptyColl")]
    HRESULT EmptyColl([out, retval] IColl** Coll);
  }
};

filyus.def:

LIBRARY

EXPORTS
  DllCanUnloadNow       PRIVATE
  DllGetClassObject PRIVATE
  DllRegisterServer PRIVATE
  DllUnregisterServer   PRIVATE
  DllInstall        PRIVATE
  EmptyColl

ole.h:

extern HRESULT EmptyColl(IColl** Coll);

ole.cpp:

HRESULT EmptyColl(IColl** Coll) {
  HRESULT hr; CComObject<CColl>* Object;
  if (Coll != nullptr) {
    hr = CComObject<CColl>::CreateInstance(&Object);
    if (hr == S_OK) {
      Object->AddRef();
      *Coll = Object; //same error with using QueryInterface
    }
  }
  else hr = E_POINTER;
  return hr;
}
2
"Same error occured with other objects inside this dll" - then clearly you are doing something fundamentally wrong inside your DLL. Please provide a Minimal, Complete, and Verifiable example showing more of your DLL's code. In particular, how it is declaring and setting up the CColl class, and other classes you are having trouble with.Remy Lebeau

2 Answers

0
votes

EmptyColl() needs to use the __stdcall calling convention:

extern HRESULT __stdcall EmptyColl(IColl** Coll);

HRESULT __stdcall EmptyColl(IColl** Coll) {
    //...
}

Alternatively, use the STDMETHODCALLTYPE macro, which resolves to __stdcall:

extern HRESULT STDMETHODCALLTYPE EmptyColl(IColl** Coll);

HRESULT STDMETHODCALLTYPE EmptyColl(IColl** Coll) {
    //...
}

Without a calling convention declared, by default a C/C++ compiler will use __cdecl instead unless configured differently. __cdecl and __stdcall manage the call stack differently. You will corrupt the call stack if you don't use the correct calling convention. COM standards require __stdcall, and that is what VB expects.

0
votes

The error is occurred because of wrong access to the object.
CComPtr is for client side, CComObject is for server side (direct access, obtain it only when you already created any object of this library).

Correct ole.cpp:

HRESULT EmptyColl(IColl** Coll) {
  HRESULT hr; CComPtr<IColl> Object;
  if (Coll != nullptr) {
    hr = Object.CoCreateInstance(CLSID_Coll);
    if (hr == S_OK) {
      Object.CopyTo(Coll);
    }
  }
  else hr = E_POINTER;
  return hr;
}