July 19, 2001·
Tools
Smart IEnumVARIANT
Visual Basic and its variants (sic) use IEnumVARIANT to implement the For-Each
statement. Unfortunately, they only ask for 1 element at a time, leading to
terrible performance across apartments. I propose two solutions. One allows you
to wrap any collection in a CollectionBuffer object and set the buffering
yourself, e.g.
Dim collBuffer As Object
Set collBuffer = CreateObject("SmartEnumSvr.CollectionBuffer")
collBuffer.Collection = coll ' coll is an interface on any collection
collBuffer.BufferSize = 1024 ' How many items would you like buffered?
c = 0
For Each v In collBuffer ' Uses SmartEnumVARIANT to buffer items
c = c + 1
Next v
MsgBox "Counted " & c
The second solution allows you to leverage SmartEnumVARIANT on the server-side,
seamlessly to the client. A detailed explanation and code
is available here.
July 18, 2001·
Tools
Implementing Marshal-by-Value using ATL
July 18, 2001
Not too long ago, Jonathan Borden, jborden@MEDIAONE.NET,
posted a nifty class called IMarshalByValueImpl that
implemented IMarshal for objects interested in being marshaled by value . It
was built in the ATL style, i.e. it used fun template tricks, and depended on
the COM class also implementing either IPersistStream or IPersistStreamImpl.
And, in fact, ATL provides an implementation of IPersistStreamInit called
IPersistStreamInitImpl. However, IPersistStreamInitImpl has one fatal flaw: it
implements GetSizeMax by returning E_NOTIMPL. This breaks Jonathan’s
IMarshalByValueImpl, which depends on a sane implementation of GetSizeMax from
the class.
IPersistStreamInitImpl2 leverages the property map of
ATL’s IPersistStreamInitImpl to build GetSizeMax. The code is not pretty. It’s
just pieced together from ATL’s implementation of IPersistStreamInit::Save and
CComVariant::WriteToStream, but it seems to work (thanks to Dharma Shukla,
v-dharsh@microsoft.com, for testing it!).
Here’s the usage for giving a class MBV:
class PassByValue :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<PassByValue, &CLSID_PassByValue>,
public IDispatchImpl<IPassByValue, &IID_IPassByValue>,
public IMarshalByValueImpl<PassByValue>,
public IPersistStreamInitImpl2<PassByValue>
{
public:
BEGIN_COM_MAP(PassByValue)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IPassByValue)
COM_INTERFACE_ENTRY(IMarshal)
// Don't need to expose these to the world
//COM_INTERFACE_ENTRY(IPersist)
//COM_INTERFACE_ENTRY
(IPersistStreamInit)
END_COM_MAP()
BEGIN_PROP_MAP(PassByValue)
// List of properties to marshal-by-value
...
END_PROP_MAP()
// IPassByValue methods
...
private:
// Whatever data members you wish to marshal
...
public:
BOOL m_bRequiresSave; // Required by IPersistStreamInitImpl2
};
July 17, 2001·
Tools
Implementing dispatch-based interfaces in ATL
July 17, 2001
There are three kinds of ways to declare a dispatch-based interface in IDL, but
ATL (as of version 3.0), only supports the implementation of 1.5 of them (duals
and a raw dispinterfaces for handling events). The
ATL Dispatch Sampledemonstrations the use of three ATL-based classes,
one for implementing each type of dispatch-based interface. The header file
that defines these classes, dispimpl2.h, is provided
for use in your own projects.
BTW, thanks to Ehab Kashkash for making this code work under VS.NET as
well as VC6.
July 16, 2001·
Tools
MeowMoniker
If you’re into COM Monikers, here’s one that I like.
July 15, 2001·
Tools
Basic Monikers
Wish there was a moniker that did CoCreateInstance just like the Class Moniker
calls CoGetClassObject? Wish you were able to compose the Class Moniker with a
host name? Then you’ll want the BasicMonikers
project, which bundles together the New moniker and the Host moniker.
Sample syntax follows:
dm.newmk.1:Excel.Application
dm.newmk.1:00024500-0000-0000-C000-000000000046:
dm.hostmk.1:frodo:!dm.newmk.1:00024500-0000-0000-C000-000000000046:
dm.hostmk.1:frodo:!clsid:00024500-0000-0000-C000-000000000046:
July 14, 2001·
Tools
regsvr.reg
July 14, 2001
regsvr.reg is a regedit script file that adds Register
COM Server and Unregister COM Server to the context menu for DLLs, OCXs and
EXEs under Win95+ and NT4+. In addition, it’s also been updated to add Register
TypeLib and Unregister TypeLib commands to .tlb, .odl, .dll, .ocx and .exe
files, using VC6′s new regtlib tool.
July 13, 2001·
Tools
ATL Composition
July 13, 2001
I’ve developed a set of macros to support implementing interfaces using nested
composition in ATL (the one common way of implementing interfaces they
neglected). The benefit of composition is that it is easy to implement multiple
interfaces with methods with the same name but that require different behavior,
e.g.
interface IArtist : IUnknown {
HRESULT Draw();
}
interface ICowboy : IUnknown {
HRESULT Draw();
}
The benefit of this particular implementation is that it has no object size
overhead. Interfaces implemented using nested composition have no greater
overhead than using multiple-inheritance. Feel free to
download atlcompose.h for your own use.