Figure 1   Delay-loading a DLL

 //Function pointer type for LookUpWord
typedef BOOL (WINAPI *PFNLOOKUP)(wchar_t *);

void OnToolsSpelling(void)
    {
    HINSTANCE  hMod;
    PFNLOOKUP  pfnLookup;
    wchar_t   *pszWord;

    hMod=LoadLibrary("BASICSPL.DLL");

    if (NULL==hMod)
        [Spell-checker not found, show error]

    //Get address of ordinal 10
    pfnLookup=(PFNLOOKUP)GetProcAddress(hMod, MAKEINTRESOURCE(10));

    if (NULL!=pfnLookup)
        {
        pszWord=GetFirstWord();  //Retrieve first word in text

        while (NULL!=pszWord)
            {
            if (FALSE==(*pfnLookup)(pszWord)) //Check if word is in dictionary
                [Alert user]

            pszWord=GetNextWord(pszWord);  //Go to next word in text
            }
        }
    else
        [Export not found, invalid spell checker!]

    FreeLibrary(hMod);
    return;
    }

Figure 3   Using COM to Access a Service

 void OnToolsSpelling(void)
    {
    ISpellChecker *pSC;
    CLSID          clsID;

    //This hypothetical function uses the registry or invokes UI
    GetCLSIDOfSpellChecker(&clsID);

    if (SUCCEEDED(CoCreateInstance(clsID, NULL, CLSCTX_SERVER
        , IID_ISpellChecker, (void **)&pSC)))
        [Spell-checker not found, show error]

    pszWord=GetFirstWord();  //Retrieve first word in text

    while (NULL!=pszWord)
        {
        if (FAILED(=pSC->LookUpWord(pszWord)))  //Check for word in dictionary
            [Alert user]

        pszWord=GetNextWord(pszWord);  //Go to next word in text
        }

    pSC->Release();  //Release is a member function of IUnknown
    return;
    }

Figure 4   Hypothetical Specifications for SpellCheck2.0

Ordinal

Prototype

Description

10

BOOL WINAPI LookUpWord

(wchar_t *pszWord)

Checks whether or not a particular word exists in the current dictionary

11

BOOL WINAPI AddWord

(wchar_t *pszWord)

Adds a custom word to the dictionary

12

BOOL WINAPI RemoveWord

(wchar_t *pszWord)

Removes a custom word from the dictionary

Figure 5   Caching Module Handles

 #define CMODULES           10  //Number of DLLs

#define DLL_ID_SPELLCHECK  0   //Array indices
#define DLL_ID_THESAURUS   1
[other defines here]

typedef BOOL (WINAPI *PFNLOOKUP)(wchar_t *);

HINSTANCE g_rghMods[CMODULES];  //Initialized to NULL on startup.

HINSTANCE ModHandle(UINT id)
    {
    ASSERT(id >=0 && id < CMODULES);

    if (NULL==g_rghMods[id])
        {
        g_rghMods[id]=LoadLibrary([name of DLL]);

        if (NULL==g_rghMods[id])
            [Throw exception]
        }

    return g_rghMods[id];
    }

void OnToolsSpelling(void)
    {
    PFNLOOKUP  pfnLookup;
    [Other locals]

    pfnLookup=(PFNLOOKUP)GetProcAddress(ModHandle(DLL_ID_SPELLCHECK)
        , MAKEINTRESOURCE(10)); 

    if (NULL!=pfnLookup)
        {
        [do stuff]
        }
    else
        [error]

    return;
    }

Figure 6   COM Solutions to DLL Problems

Problem

Solution

Path dependencies, multiple providers of a service

Use the registry to map from abstract class identifiers to absolute server locations as well as mapping between categories and class identifiers

Decentralized definition of identifiers

Use GUIDs generated by an algorithm that guarantees uniqueness across time and space, eliminating the need for centralized identifier allocation

Specific management APIs for each service category

Supply a very simple generic and universal management API that accommodates all service categories, called Implementation Location

Sharing instances across process/machine boundaries

Marshaling of interface pointers, Location Transparency providing the ability to implement a server as an EXE or DLL

Different in-process, local, and remote programming models

A single model for all types of client-object connections supported through the interface structure, Location Transparency

Lifetime management of servers and objects

Universal reference counting through the base interface IUnknown that all objects support and from which all other interfaces are derived

Multiple services per server module

Use CLSID:IID:table_offset to absolutely identify functions instead of module:ordinal

Versioning well as interfaces that are strongly typed at both compile time and run time

Support the concept of multiple immutable interfaces as