I've written what I thought would be a very simple atl object. coclass
CWrapRecs exposes two interfaces: IWrapRecs is vtable only and Recordset is
dual. The idea is that Recordset is taken from the dao library, so that this
object can look like a Recordset to anything I wish.
The problem seems to be in ATL's IDispatchImpl not being able to find a DAO
type library at run time. What I believe is supposed to happen is that it
queries the type library for the mapping of dispatch ids to vtable
positions. Thus, given a vtable interface, it can implement a dispatch one.
I then try to use my object in vb, using difference variables to access the
different interfaces, like this:
Dim CWr As New CWrapRecs
Dim wr As IWrapRecs
Set wr = CWr
wr.TraceActivity = True
'etc for other members of IWrapRecs interface
Dim recs As Recordset
Set recs = CWr 'NOT wr.Recs; it's an interface change we want
Set f.Data1.Recordset = recs
'and recs.BOF, etc, for other members of Recordset interface
The accesses I've written above, and CTRL+J member listing, all seem to work
fine; I'd guess vb is using vtable access in the former case and the
referenced type library for my object in the latter (there's also a
Reference to DAO).
What doesn't work is the Data control trying to use my recordset. It seems
not to see it. Through experimentation, I discovered that the Locals window
expanding of properties definitely uses the dispatch interface (since it
stopped happening for IWrapRecs when I changed that interface from dual to
vtable only). When I try to expand the list for recs, I get errors, of two
kinds depending on what LIBID I set the DispatchImpl derivation up with.
Thus it looks like the DispatchImpl code is getting properly called to walk
the member list, but is failing to find the type library it wants.
My derivation list for CWrapRecs looks like this:
class ATL_NO_VTABLE CWrapRecs :
public CComCoClass<CWrapRecs, &CLSID_CWrapRecs>,
public IDispatchImpl<Recordset, &IID_Recordset, &LIBID_DAOCompat>,
public IProvideClassInfo2Impl<&CLSID_CWrapRecs, &IID__IWrapRecsEvents,
In place of LIBID_DAOCompat, I've tried three different ids:
which I believe is the DAO 2.5/3.5 Compatibility library, dao2535.tlb, one
of the libraries I can use as the interface source compiling my C++ code.
This gives an "object library not registered" message box when I try my test
this is the id extracted even from dao2535.tlb by #import, but I think more
precisely it's the LIBID of the actual database engine, dao350.dll. Again, I
can build my source code off interfaces from this file too. Again, it gives
"object library not registered" in vb.
LIBID_WRAPRECORDSETLib, the actual id for my library, as declared in the
uuid attribute of the library statement in WrapRecordset.idl. The idl file
importlib's one of the above two files, so I'd guess it should be an equally
good source of the interface information. However, in the vb test, this one
gives "32811 - unexpected error", which I'm guessing is some other error
code from atl or the type library com components it calls.
I've made copious use of the OLE/COM object viewer, and these cover the main
"type library" entries for DAO that I can find. That's getting its info from
the registry. The Object Browser in vb tells me the DAO library I'm
referencing is the same dao350.dll (same path) as above, and I got its uuid
through #import. So what's going wrong?!!
I'm tearing my hair out over this one...