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.

Can I still be evil? July 15, 2001 Fun

Can I still be evil?

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.


← Newer Entries Older Entries →