Registering DLL's

John K. Hohm jhohm at acm.org
Tue Jan 7 23:37:01 CST 2003


On Wed, Dec 04, 2002 at 05:14:23PM -0800, Alexandre Julliard wrote:

> "John K. Hohm" <jhohm at acm.org> writes:
> 
> > I posted my idea for representing the registration data, accidentally from
> > "jhohm at happyhappy.dyndns.org" rather than my usual "jhohm at acm.org" (see
> > http://www.winehq.com/hypermail/wine-devel/2002/11/1409.html), but I haven't
> > gotten any responses, not even "looks fine" or "you are a moron".  I guess I'll
> > just start submitting patches, then.
> 
> Sorry, I must have missed that one. I don't really like the ASCII
> description of the registry keys; I think it would be better to do it
> at a more symbolic level. For instance you shouldn't hardcode the
> ASCII form of the CLSID, you should have some kind of "register CLSID"
> function that takes a CLSID and uses StringFromCLSID or whatever to
> create the corresponding registry key.

The types of things that a COM server DLL is likely to register are fairly
limited; essentially just classes and interfaces.  I have come up with
a different interface, that accepts a list of structures more closely
matching the requirements of registering and unregistering a COM server.

This is the interface in regsvr.h for use by Dll[Un]RegisterServer:

struct regsvr_interface
{
    IID const *iid;             /* NULL for end of list */
    LPCSTR name;                /* can be NULL to omit */
    IID const *base_iid;        /* can be NULL to omit */
    int num_methods;            /* can be <0 to omit */
    CLSID const *ps_clsid;      /* can be NULL to omit */
    CLSID const *ps_clsid32;    /* can be NULL to omit */
};

HRESULT register_interfaces(struct regsvr_interface const *list);
HRESULT unregister_interfaces(struct regsvr_interface const *list);

struct regsvr_coclass
{
    CLSID const *clsid;         /* NULL for end of list */
    LPCSTR name;                /* can be NULL to omit */
    LPCSTR ips;                 /* can be NULL to omit */
    LPCSTR ips32;               /* can be NULL to omit */
    LPCSTR ips32_tmodel;        /* can be NULL to omit */
};

HRESULT register_coclasses(struct regsvr_coclass const *list);
HRESULT unregister_coclasses(struct regsvr_coclass const *list);

Here is an example of its use in comcat_main.c; this is admittedly much
less than would appear on ole32_main.c, but everything required there
should be included in the structures:

static struct regsvr_coclass coclass_list[] = {
    {   &CLSID_StdComponentCategoriesMgr,
        "StdComponentCategoriesMgr",
        NULL,
        "comcat.dll",
        "Both"
    },
    { NULL }                    /* list terminator */
};

HRESULT WINAPI COMCAT_DllRegisterServer()
{
    TRACE("\n");
    return register_coclasses(coclass_list);
}

HRESULT WINAPI COMCAT_DllUnregisterServer()
{
    TRACE("\n");
    return unregister_coclasses(coclass_list);
}

Alexandre, feel free to disapprove of this interface also; most of my
experience writing interfaces to library pieces has either been big, complex
Automation stuff to support VB database apps, or object-oriented C++.

I would also like suggestions on whether an interface like this should
be exported via a static library like libwine_unicode.a (can that work
when I call advapi32 exports?), via a new wine-specific dll in src/dlls,
or simply by copying the implementation around to all the COM server dlls
(my least favorite option).

-- 
John Hohm <jhohm at acm.org>
I once had sufficient wisdom to value an absent .sig over a lame one.



More information about the wine-devel mailing list