| Service (CM_Xxx) | Description | 
| Add_Empty_Log_Conf | Creates an empty logical configuration for a given DEVNODE. First step in defining resource requirements for a device. | 
| Add_ID | Used during CONFIG_SETUP to add a hardware ID or compatible ID to a DEVNODE. | 
| Add_Range | Expand a memory range list by adding one more range description. | 
| Add_Res_Des | Add a resource descriptor to a growing logical configuration. | 
| Call_At_Appy_Time | Arrange an application time callback. | 
| Call_Enumerator_Function | Call the enumerator for a given DEVNODE. | 
| CallBack_Device_Driver | Call a device driver once for each device it manages, passing CONFIG_CALLBACK as the function code. | 
| CallBack_Enumerator | Call an enumerator function once for each device it enumerates, passing CONFIG_CALLBACK as the function code. This makes calls for each bus or controller rather than for each attached device. | 
| Create_DevNode | Create a new DEVNODE. This is the basic function for enumerators to use in expanding the hardware tree. | 
| Create_Range_List | Create an empty memory range list. | 
| Delete_Range | Remove a single memory range description from a range list. | 
| Deregister_Arbitrator | Deregister a resource arbitrator. | 
| Disable_DevNode | Disable a device. That is, stop using it. | 
| Dump_Range_List | Dump a range list for debugging. | 
| Dup_Range_List | Create a copy of a range list. | 
| Enable_DevNode | Reverse the effect of a Disable_DevNode call. | 
| Fail_Change_Config | Used by the Plug and Play BIOS enumerator to cancel a previously planned docking or undocking. | 
| First_Range | Retrieve the first range element in a range list. | 
| Free_Log_Conf | Release the memory used by a logical configuration. | 
| Free_Range_List | Release the memory used by a memory range list. | 
| Free_Res_Des | Release the memory used by a single resource descriptor. | 
| Get_Alloc_Log_Conf | Get the resources actually allocated for a device. This is the main service used by a device driver to learn what resources it may use. | 
| Get_Bus_Info | Retrieve the bus information installed by Set_Bus_Info. | 
| Get_Child | Get a pointer to the first child of a given DEVNODE. | 
| Get_CRC_CheckSum | Calculate a cyclic redundancy check for a given byte string. | 
| Get_DDBs | Locate the device descriptor block(s) for drivers associated with a DEVNODE. This allows the caller to do Directed_Sys_Control calls to those drivers. | 
| Get_Depth | Determine how deep a DEVNODE is in the hardware tree. | 
| Get_Device_Driver_Private_DWord | Retrieve the private value stored in the DEVNODE by Set_Device_Driver_Private_Dword. | 
| Get_Device_ID | Retrieve the ASCII device ID for a DEVNODE. | 
| Get_Device_ID_Size | Get the byte length of the device ID. This allows the caller to allocate memory for a call to Get_Device_ID. | 
| Get_DevNode_Key | Retrieve the ASCII name of the hardware or software registry key for a DEVNODE. | 
| Get_DevNode_Key_Size | Get the byte length of a registry pathname. This allows the caller to allocate memory for a call to Get_DevNode_Key. | 
| Get_DevNode_Status | Retrieve the current status of a DEVNODE. | 
| Get_First_Log_Conf | Get a handle to the first logical configuration for a DEVNODE. This is how the caller starts a loop over configurations. | 
| Get_Hardware_Profile_Info | Retrieve information about a hardware profile. | 
| Get_HW_Prof_Flags | Get configuration-specific flags for a single DEVNODE in a particular hardware profile. | 
| Get_Next_Log_Conf | Get a handle for the next logical configuration in a list of configurations. | 
| Get_Next_Res_Des | Get a handle for the first or next resource descriptor in a logical configuration. | 
| Get_Parent | Get a pointer to the parent of a DEVNODE. | 
| Get_Performance_Info | Retrieve performance information for debugging purposes. | 
| Get_Private_DWord | Retrieve the private DWORD that a driver stored about one DEVNODE in some other DEVNODE. | 
| Get_Res_Des_Data | Copy a resource descriptor given its handle. Used only by Ring 3 callers. | 
| Get_Res_Des_Data_Size | Get the byte length of resource data. This allows a Ring 3 caller to allocate memory for a call to Get_Res_Des_Data. | 
| Get_Sibling | Get the next sibling of a DEVNODE. Used during a loop over children of a given node. | 
| Get_Version | Get the version number (that is, 0x0400) of the CONFIGMG device driver. | 
| Intersect_Range_List | Create the intersection of two range lists. | 
| Invert_Range_List | Create the inversion of a range list. | 
| ISAPNP_To_CM | Convert a device's resource requirements from the format specified in the ISA Plug and Play specification to Configuration Manager's internal resource descriptor format. | 
| Load_DLVxDs | Dynamically load one or more VxDs. | 
| Locate_DevNode | Find a DEVNODE given its ASCII ID. | 
| Merge_Range_List | Create the union of two range lists. | 
| Modify_Res_Des | Modify a resource descriptor. Used only by Ring 3 callers. | 
| Move_DevNode | Used by Device Installer to eliminate duplicate DEVNODEs. | 
| Next_Range | Get the next range descriptor in a range list. | 
| Query_Arbitrator_Free_Data | Determine which resources managed by a resource arbitrator are free. | 
| Query_Arbitrator_Free_Size | Determine the byte length of an arbitrator's free data structure. This allows the caller to allocate memory for a call to Query_Abitrator_Free_Data. | 
| Query_Change_Config | Determine if it's okay to change from one hardware profile to another. | 
| Query_Remove_SubTree | Determine if it's okay to remove a DEVNODE and all of its children. | 
| Read_Registry_Log_Confs | Convert a logical configuration in the registry into Configuration Manager's internal form. Used by the Root Enumerator to configure legacy devices. | 
| Read_Registry_Value | Read a value from the registry. Used by all sorts of Plug and Play drivers to obtain information beyond normal configuration data. | 
| Recompute_HW_Prof | Used by the Plug and Play BIOS enumerator after a docking station change. | 
| Reenumerate_DevNode | Force Configuration Manager to enumerate a DEVNODE. Used, for example, when a bus or controller detects a hot hardware change. | 
| Register_Arbitrator | Register a function as a resource arbitrator. | 
| Register_Device_Driver | Register a device driver for a DEVNODE. Every device driver makes this call. | 
| Register_DevLoader | Indicates that a static VxD that earlier received a PNP_New_DevNode (DEVLOADER) message and returned CR_DEVLOADER_NOT_READY is now ready to be a Device Loader and wants to get the message a second time. Few device loaders make this call. | 
| Register_Enumerator | Register an enumeration function. Every bus or controller enumerator makes this call. | 
| Remove_SubTree | Removes a DEVNODE and its children from the hardware tree. This is part of removing a device from the system. | 
| Remove_Unmarked_Children | Removes DEVNODEs whose preservation marks were cleared by Reset_Children_Marks. | 
| Reset_Children_Marks | Clears the preservation mark for the children of a given DEVNODE. | 
| Run_Detection | Spawns the (Ring 3) detection DLL following insertion of a legacy card. | 
| Set_Bus_Info | Record information about a hardware bus represented by a given DEVNODE. | 
| Set_Device_Driver_Private_DWord | Set the private value in a DEVNODE. | 
| Set_HW_Prof | Used by Control Panel to change the current hardware profile. | 
| Set_HW_Prof_Flags | Set the profile-specific flags for a DEVNODE. | 
| Set_Private_DWord | Record a private value about one DEVNODE in some other DEVNODE. | 
| Set_Private_Problem | Record a "problem" in a DEVNODE so the class installer can diagnose it for the user. | 
| Setup_DevNode | Send a CONFIG_SETUP or CONFIG_READY to a DEVNODE's enumerator. | 
| Sort_NodeList | Used by a resource arbitrator to sort a list of logical configurations according to how easy their requirements will be to satisfy. | 
| Test_Range_Available | Determine if a memory range is available given reservations recorded in a range list. | 
| Write_Registry_Value | Set a value in the registry. | 
| Yield | Yield control until a time-out expires. Used to satisfy hardware timing requirements. | 
| Priority | Description | 
| LCPRI_FORCECONFIG | Configuration manually selected by the user | 
| LCPRI_BOOTCONFIG | Configuration established at boot-time by BIOS or card | 
| LCPRI_DESIRED | Preferred configuration giving better performance | 
| LCPRI_NORMAL | Configuration giving acceptable performance | 
| LCPRI_SUBOPTIMAL | Workable configuration giving poor performance | 
| LCPRI_RESTART | Configuration will require restarting Windows | 
| LCPRI_REBOOT | Configuration will require soft reboot of computer | 
| LCPRI_POWEROFF | Configuration will require hard reboot of computer | 
| LPCRI_HARDRECONFIG | Configuration will require user to change a jumper | 
| LPCRI_HARDWIRED | Only possible configuration | 
Figure 3 Creating a Logical Configuration
 CONFIGRET CM_HANDLER OnEnumerate(CONFIGFUNC cf,
    SUBCONFIGFUNC scf, DEVNODE tonode, DEVNODE aboutnode,
    ULONG flags)
    {                           // OnEnumerate
    CONFIGRET code;
    switch (cf)
        {                       // select on function code
    case CONFIG_ENUMERATE:      // cf == 5
        {                       // CONFIG_ENUMERATE
        DEVNODE device;         // DEVNODE for device
        LOG_CONF logconf;       // logical configuration
        RES_DES resource;       // resource descriptor handle
        static IRQ_DES irq = {{0, 0, 0x00FF, 0}};
        code = CM_Create_DevNode(&device, "SCHOOL\\WCO1234\\0000",tonode, 0);
        if (code == CR_ALREADY_SUCH_DEVNODE)
            return CR_SUCCESS;
        CM_Add_Empty_Log_Conf(&logconf, device,
                              LCPRI_NORMAL,
                              BASIC_LOG_CONF | PRIORITY_EQUAL_LAST);
        CM_Add_Res_Des(&resource, logconf, ResType_IRQ, &irq, sizeof(irq), 0);
        return CR_SUCCESS;
        }                       // CONFIG_ENUMERATE
    default:
        return CR_DEFAULT;
        }                       // select on function code
    }                           // OnEnumerateFigure 4 Possible Alias/Decode Settings for an I/O Resource
| Alias | Decode | Meaning | 
| 0 | 0 | Card decodes all 16 bits of I/O address | 
| 4 | 3 | Card decodes 10 bits of I/O address | 
| 16 | 15 | Card decodes 12 bits of I/O address | 
| 255 | 0 | Card is a PCI card that can use ports that would otherwise be reserved as 10-bit synonyms for ISA card ports | 
Figure 5 SCHOOL.VXD
SCHOOL.MAK
 all: school.vxd telepath.vxd
.asm.obj:
   ml -coff -DBLD_COFF -DIS_32 -W2 -Zd -c -Cx -DMASM6 -Zi \
      -DDEBUG $*.asm
.c.obj:
   cl -c -Gs -Zdpl -Od -D_X86_ -YX -W3 -DDEBLEVEL=1 \
      -DBLD_COFF -DDEBUG -DIS_32 $*.c
school.vxd : s_ctl.obj $*.obj $*.def $*.res
   link @<<
-machine:i386 -def:$*.def -out:$@
-debug -debugtype:map
-map:$*.map -vxd vxdwraps.clb -nodefaultlib
s_ctl.obj $*.obj
<<
telepath.vxd: t_ctl.obj $*.obj $*.def
   link @<<
-machine:i386 -def:$*.def -out:$@
-debug -debugtype:map
-map:$*.map -vxd vxdwraps.clb -nodefaultlib
t_ctl.obj $*.obj
<<SCHOOL.DEF
 VXD SCHOOL DYNAMIC
DESCRIPTION 'Sample Device'
SEGMENTS
    _LPTEXT CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _LTEXT  CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _LDATA  CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _TEXT   CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _DATA   CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    CONST   CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _TLS    CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _BSS    CLASS 'LCODE'   PRELOAD NONDISCARDABLE
    _MSGTABLE CLASS 'MCODE'   PRELOAD NONDISCARDABLE IOPL
    _MSGDATA  CLASS 'MCODE'   PRELOAD NONDISCARDABLE IOPL
    _IMSGTABLE CLASS 'MCODE'   PRELOAD DISCARDABLE IOPL
    _IMSGDATA CLASS 'MCODE'   PRELOAD DISCARDABLE IOPL
    _ITEXT    CLASS 'ICODE'   DISCARDABLE
    _IDATA    LASS 'ICODE'   DISCARDABLE
    _PTEXT    CLASS 'PCODE'   NONDISCARDABLE
    _PDATA    CLASS 'PDATA'   NONDISCARDABLE SHARED
    _STEXT    CLASS 'SCODE'   RESIDENT
    _SDATA    CLASS 'SCODE'   RESIDENT
    _DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
    _DBOCODE  CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
     DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
    _16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE
    _RCODE   CLASS 'RCODE'
EXPORTS
        SCHOOL_DDB @1S_CTL.ASM
          .386p
         include vmm.inc
         include debug.inc
Declare_Virtual_Device SCHOOL, 1, 0, SCHOOL_Control, \
        Undefined_Device_ID, Undefined_Init_Order
Begin_Control_Dispatch SCHOOL
    Control_Dispatch Sys_Dynamic_Device_Init,         \
        _OnSysDynamicDeviceInit, cCall
    Control_Dispatch Sys_Dynamic_Device_Exit,         \
        _OnSysDynamicDeviceExit, cCall
    Control_Dispatch PNP_New_Devnode, _OnPnpNewDevnode, \
        cCall, <ebx, edx>
End_Control_Dispatch SCHOOL
         endSCHOOL.C
 #define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <debug.h>
#include <vmmreg.h>
#include <vwin32.h>
#include <vxdwraps.h>
#include <configmg.h>
#include <regstr.h>
#ifdef DEBUG
    #define ASSERT(e) if(!(e))\
        {Debug_Printf("Assertion failure in " __FILE__ \
                      ", line %d: " #e "\r\n", __LINE__);\
        _asm int 1\
        }
#else
    #define ASSERT(e)
#endif
#define ResType_Telepath ((0x10 << 5) | 5)
typedef struct
    {
    int allocated;   // index of allocated channel (-1 => none)
    ULONG requested; // mask for requested channels
    } TELEPATH_RESOURCE;
#pragma CM_PAGEABLE_DATA
#pragma CM_PAGEABLE_CODE
CONFIGRET CM_HANDLER OnEnumerate(CONFIGFUNC cf, CONFIGFUNC scf, DEVNODE tonode,
                                 DEVNODE aboutnode, ULONG flags);
CONFIGRET CM_HANDLER OnArbitrateTelepath(ARBFUNC af, ULONG refdata,
                                         DEVNODE devnode, NODELIST_HEADER h);
REGISTERID arbid;
BOOL OnSysDynamicDeviceInit()
    {                           // OnSysDynamicDeviceInit
    CM_Register_Arbitrator(&arbid, ResType_Telepath, OnArbitrateTelepath, 0,
                           NULL, ARB_GLOBAL);
    return TRUE;
    }                           // OnSysDynamicDeviceInit
BOOL OnSysDynamicDeviceExit()
    {                           // OnSysDynamicDeviceExit
    if (arbid)
        CM_Deregister_Arbitrator(arbid, 0);
    return TRUE;
    }                           // OnSysDynamicDeviceExit
CONFIGRET OnPnpNewDevnode(DEVNODE devnode, DWORD loadtype)
    {                           // OnPnpNewDevnode
    CONFIGRET code;
    switch (loadtype)
        {                       // select function to perform
    case DLVXD_LOAD_DEVLOADER:  // loadtype == 1
        code = CM_Register_Enumerator(devnode, OnEnumerate,
                                      CM_REGISTER_ENUMERATOR_HARDWARE);
        if (code != CR_SUCCESS)
            return code;
        return CM_Register_Device_Driver(devnode, NULL, 0,
                                         CM_REGISTER_DEVICE_DRIVER_REMOVABLE);
        }                       // select function to perform
    return CR_DEFAULT;
    }                           // OnPnpNewDevnode
CONFIGRET CM_HANDLER OnEnumerate(CONFIGFUNC cf, SUBCONFIGFUNC scf, 
                                 DEVNODE tonode, DEVNODE aboutnode,
    ULONG flags)
    {                           // OnEnumerate
    CONFIGRET code;
#ifdef DEBUG
    char toid[MAX_DEVICE_ID_LEN], aboutid[MAX_DEVICE_ID_LEN];
    DEBUG_CONFIG_NAMES
    char *subfunc = "";
    static char *substart[] = {"DYNAMIC_START", "FIRST_START"};
    static char *substop[] = {"DYNAMIC_STOP", "HAS_PROBLEM"};
    static char *subremove[] = {"DYNAMIC", "SHUTDOWN", "REBOOT"};
    static char *subtest[] = {"CAN_STOP", "CAN_REMOVE"};
    static char *subapm[] = {"TEST_STANDBY", "TEST_SUSPEND",
                             "TEST_STANDBY_FAILED", "TEST_SUSPEND_FAILED",
                             "TEST_STANDBY_SUCCEEDED","TEST_SUSPEND_SUCCEEDED",
                             "RESUME_STANDBY", "RESUME_SUSPEND",
                             "RESUME_CRITICAL", "UI_ALLOWED"};
    CM_Get_Device_ID(tonode, toid, sizeof(toid), 0);
    CM_Get_Device_ID(aboutnode, aboutid, sizeof(aboutid), 0);
    switch (cf)
        {                       // get subfunction name
    case CONFIG_START:
        subfunc = substart[scf];
        break;
    case CONFIG_STOP:
        subfunc = substop[scf];
        break;
    case CONFIG_REMOVE:
        subfunc = subremove[scf];
        break;
    case CONFIG_TEST:
        subfunc = subtest[scf];
        break;
    case CONFIG_APM:
        subfunc = subapm[scf];
        break;
        }                       // get subfunction name
    if (cf < NUM_CONFIG_COMMANDS)
        Debug_Printf("SCHOOL ENUMERATOR: %s(%s), to %s, about %s\r\n",
                     lpszConfigName[cf], subfunc, toid, aboutid);
    else
        Debug_Printf("SCHOOL ENUMERATOR: %X(%X), to %s, about %s\r\n",
                     cf, toid, aboutid);
#endif
    switch (cf)
        {                       // select on function code
case CONFIG_SETUP:
        {                       // CONFIG_SETUP
        ULONG length;           // length of class name
        char class[64];         // device class
        length = sizeof(class);
        code = CM_Read_Registry_Value(aboutnode, NULL, "Class", REG_SZ, class,
                                      &length, CM_REGISTRY_HARDWARE);
        if (code == CR_NO_SUCH_VALUE)
            {                   // new device
            CM_Write_Registry_Value(aboutnode, NULL, "Class", REG_SZ, "System",
                                    6, CM_REGISTRY_HARDWARE);
            CM_Write_Registry_Value(aboutnode, NULL, "HardwareID", REG_SZ,
                                    "WCO1234", 6, CM_REGISTRY_HARDWARE);
            }                   // new device
        return CR_SUCCESS;
        }                       // CONFIG_SETUP
    case CONFIG_ENUMERATE:      // cf == 5
        {                       // CONFIG_ENUMERATE
        DEVNODE device;         // DEVNODE for device
        ULONG length;           // length of class name
        char class[64];         // device class
        LOG_CONF logconf;       // logical configuration
        RES_DES resource;       // resource descriptor handle
        static IRQ_RESOURCE irq = {{0, 0, 0xFFFF, 0}};
        static TELEPATH_RESOURCE telepath = {-1, 0xFF};
        code = CM_Create_DevNode(&device, "SCHOOL\\WCO1234\\0000", tonode, 0);
        if (code == CR_ALREADY_SUCH_DEVNODE)
            return CR_SUCCESS;
        CM_Add_Empty_Log_Conf(&logconf, device, LCPRI_NORMAL,
            BASIC_LOG_CONF | PRIORITY_EQUAL_LAST);
        CM_Add_Res_Des(&resource, logconf, ResType_IRQ, &irq, sizeof(irq), 0);
        CM_Add_Res_Des(&resource, logconf, ResType_Telepath, &telepath,
                       sizeof(telepath), 0);
        return CR_SUCCESS;
        }                       // CONFIG_ENUMERATE
    default:
        return CR_DEFAULT;
        }                       // select on function code
    }                           // OnEnumerate
///////////////////////////////////////////////////////////////
// Telepathic I/O channel resource arbitrator
typedef struct nodelistheader_s *NODELISTHEADER;
typedef struct nodelist_s *PNODE;
typedef struct
    {                           // allocation placeholder
    PNODE node;                 // current node
    TELEPATH_RESOURCE* pres;    // current resource descriptor
    } ALLOCPLACE, *PALLOCPLACE; // allocation placeholder
int bitcount(ULONG mask)
    {                           // bitcount
    int nbits = 0;
    while (mask)
        {                       // count bits
        if (mask & 1)
            ++nbits;
        mask >>= 1;
        }                       // count bits
    return nbits;
    }                           // bitcount
void sortnodes(NODELISTHEADER h)
    {                           // sortnodes
    PNODE node = h->nlh_Head;
    while (node)
        {                       // for each node
        RES_DES hres = (RES_DES) node->nl_Test_Req;
        #define pres ((TELEPATH_RESOURCE *) hres)
        node->nl_ulSortDWord = 0;
        while (CM_Get_Next_Res_Des(&hres, hres, ResType_Telepath, NULL, 0) ==
                                                                     CR_SUCCESS)
            node->nl_ulSortDWord += bitcount(pres->requested);
        node = node->nl_Next;
        #undef pres
        }                       // for each node
    CM_Sort_NodeList((NODELIST_HEADER) h, 0);
    }                           // sortnodes
void release(NODELISTHEADER h, PULONG pmap)
    {                           // release
    PNODE node = h->nlh_Head;
    while (node)
        {                       // for each node
        LOG_CONF logconf;
        if (CM_Get_First_Log_Conf(&logconf,(DEVNODE) node->nl_ItsDevNode,
                                  ALLOC_LOG_CONF)== CR_SUCCESS)
            {                   // release channel(s)
            RES_DES hres = (RES_DES) logconf;
            #define pres ((TELEPATH_RESOURCE *) hres)
            while (CM_Get_Next_Res_Des(&hres, hres, ResType_Telepath, NULL, 0)
                                                                 == CR_SUCCESS)
                if (pres->allocated >= 0)
                    *pmap |= 1 << pres->allocated; 
            #undef pres
            }                   // release channel(s)
        node = node->nl_Next;
        }                       // for each node
    }                           // release
BOOL nextres(PALLOCPLACE p)
    {                           // nextres
    ASSERT(p->node && p->node->nl_Test_Req);
    if (!p->pres)
        p->pres = (TELEPATH_RESOURCE *) p->node->nl_Test_Req;
    while (CM_Get_Next_Res_Des((RES_DES*) &p->pres, (RES_DES) p->pres,
           ResType_Telepath, NULL, 0) != CR_SUCCESS)
        {                       // no more of our resource
        if (!(p->node = p->node->nl_Next))
            return FALSE;       // no more nodes in the list
        p->pres = (TELEPATH_RESOURCE *) p->node->nl_Test_Req;
        }                       // no more of our resource
    return TRUE;
    }                           // nextres
BOOL allocate(PALLOCPLACE p, PULONG pmap)
    {                           // allocate
    int channel;
    if (!nextres(p))
        return TRUE;
    for (p->pres->allocated = -1, channel = 0; channel < 32; ++channel)
        {                       // try to allocate a channel
        ALLOCPLACE place = *p;
        ULONG mask = 1 << channel;
        ULONG tempmap = *pmap;
        if ( !(tempmap & mask)  ||  !(place.pres->requested & mask) )
            continue;
        tempmap &= ~mask;       // do trial allocation
        if (allocate(&place, &tempmap))
            {                   // successful allocation
            *pmap = tempmap;
            p->pres->allocated = channel;
            return TRUE;
            }                   // successful allocation
        }                       // try to allocate a channel
    }                           // allocate
BOOL reallocate(NODELISTHEADER h, PULONG pmap, BOOL forced)
    {                           // reallocate
    PNODE node = h->nlh_Head;
    
    while (node)
        {                       // for each node
        RES_DES hres = (RES_DES) node->nl_Test_Req;
        #define pres ((TELEPATH_RESOURCE *) hres)
        while (CM_Get_Next_Res_Des(&hres, hres,ResType_Telepath, NULL, 0) ==
                                                                     CR_SUCCESS)
            {                   // requires our resource
            ULONG mask;
            ASSERT(pres->allocated >= 0);
            mask = 1 << pres->allocated;
            if ((*pmap & mask) && !forced)
                return FALSE;    // one or more still in use
            *pmap &= ~mask;
            }                   // requires our resource
        node = node->nl_Next;
        #undef pres
        }                       // for each node
    return TRUE;
    }                           // reallocate
CONFIGRET CM_HANDLER OnArbitrateTelepath(ARBFUNC af, ULONG refdata,
                                         DEVNODE devnode, NODELIST_HEADER h)
    {                           // OnArbitrateTelepath
    static ULONG free_map = 0xFF; // real allocation map
    static ULONG free_copy = 0xDEADBEEF; // copy of map
    switch (af)
        {                       // select on function
    case ARB_TEST_ALLOC:        // af == 0
        {                       // ARB_TEST_ALLOC
        ALLOCPLACE place = {((NODELISTHEADER)h)->nlh_Head, NULL};
        sortnodes((NODELISTHEADER) h);
        free_copy = free_map;
        release((NODELISTHEADER) h, &free_copy);
        if (allocate(&place, &free_copy))
            return CR_SUCCESS;
        else
            return CR_FAILURE;
        }                       // ARB_TEST_ALLOC
    case ARB_RETEST_ALLOC:      // af == 1
    case ARB_FORCE_ALLOC:       // af == 6
        free_copy = free_map;
        release((NODELISTHEADER) h, &free_copy);
        if (reallocate((NODELISTHEADER) h, &free_copy, af == ARB_FORCE_ALLOC))
            return CR_SUCCESS;
        else
            return CR_FAILURE;
    case ARB_SET_ALLOC:         // af == 2
        ASSERT(free_copy != 0xDEADBEEF);
        free_map = free_copy;
        free_copy = 0xDEADBEEF;
        return CR_SUCCESS;
    case ARB_RELEASE_ALLOC:     // af == 3
        free_copy = 0xDEADBEEF;
        return CR_SUCCESS;
    case ARB_QUERY_FREE:        // af == 4
        {                       // ARB_QUERY_FREE
        struct arbitfree_s *p = (struct arbitfree_s *) h;
        p->af_SizeOfInfo = sizeof(ULONG);
        p->af_PointerToInfo = (PVOID*) &free_map;
        return CR_SUCCESS;
        }                       // ARB_QUERY_FREE
    case ARB_REMOVE:            // af == 5
        return CR_SUCCESS;
    default:
        return CR_DEFAULT;
        }                       // select on function
    }                           // OnArbitrateTelepathTELEPATH.DEF
T_CTL.ASM
These two files are essentially the same as SCHOOL.DEF and S_CTL.ASM, respectively. SCHOOL.MAK also builds TELEPATH.VXD.
TELEPATH.C
 #define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <debug.h>
#include <vmmreg.h>
#include <vxdwraps.h>
#include <configmg.h>
#include <regstr.h>
static BYTE irq;            // allocated IRQ
CONFIGRET OnConfigure(CONFIGFUNC cf, SUBCONFIGFUNC scf, DEVNODE devnode,
                      DWORD refdata, ULONG flags);
BOOL OnSysDynamicDeviceInit()
    {                           // OnSysDynamicDeviceInit
    return TRUE;
    }                           // OnSysDynamicDeviceInit
BOOL OnSysDynamicDeviceExit()
    {                           // OnSysDynamicDeviceExit
    return TRUE;
    }                           // OnSysDynamicDeviceExit
CONFIGRET OnPnpNewDevnode(DEVNODE devnode, DWORD loadtype)
    {                           // OnPnpNewDevnode
    switch (loadtype)
        {                       // select function to perform
    case DLVXD_LOAD_DEVLOADER:      // loadtype == 2
        return CM_Register_Device_Driver(devnode, OnConfigure, 0,
                                         (CM_REGISTER_DEVICE_DRIVER_REMOVABLE |
                                          CM_REGISTER_DEVICE_DRIVER_DISABLEABLE));
        }                       // select function to perform
    return CR_DEFAULT;
    }                           // OnPnpNewDevnode
CONFIGRET OnConfigure(CONFIGFUNC cf, SUBCONFIGFUNC scf, DEVNODE devnode,
                      DWORD refdata, ULONG flags)
    {                           // OnConfigure
#ifdef DEBUG
    char id[MAX_DEVICE_ID_LEN];
    DEBUG_CONFIG_NAMES
    char *subfunc = "";
    static char *substart[] = {"DYNAMIC_START", "FIRST_START"};
    static char *substop[] = {"DYNAMIC_STOP", "HAS_PROBLEM"};
    static char *subremove[] = {"DYNAMIC", "SHUTDOWN",
        "REBOOT"};
    static char *subtest[] = {"CAN_STOP", "CAN_REMOVE"};
    static char *subapm[] ={"TEST_STANDBY", "TEST_SUSPEND",
                            "TEST_STANDBY_FAILED", "TEST_SUSPEND_FAILED",
                            "TEST_STANDBY_SUCCEEDED", "TEST_SUSPEND_SUCCEEDED",
                            "RESUME_STANDBY", "RESUME_SUSPEND",
                            "RESUME_CRITICAL", "UI_ALLOWED"};
    switch (cf)
        {                       // get subfunction name
    case CONFIG_START:
        subfunc = substart[scf];
        break;
    case CONFIG_STOP:
        subfunc = substop[scf];
        break;
    case CONFIG_REMOVE:
        subfunc = subremove[scf];
        break;
    case CONFIG_TEST:
        subfunc = subtest[scf];
        break;
    case CONFIG_APM:
        subfunc = subapm[scf];
        break;
        }                       // get subfunction name
    CM_Get_Device_ID(devnode, id, sizeof(id), 0);
    if (cf < NUM_CONFIG_COMMANDS)
        Debug_Printf("TELEPATH DRIVER: %s(%s), %s\r\n", lpszConfigName[cf],
                     subfunc, id);
    else
        Debug_Printf("TELEPATH DRIVER: %X(%X), %s\r\n", cf, scf, id);
#endif
    switch (cf)
        {                       // select on function code
    case CONFIG_START:          // cf == 1
        {                       // CONFIG_START
        CMCONFIG config;
        CM_Get_Alloc_Log_Conf(&config, devnode, CM_GET_ALLOC_LOG_CONF_ALLOC);
        irq = config.bIRQRegisters[0];
        {
        #define ResType_Telepath ((0x10 << 5) | 5)
        typedef struct
            {                    // telepath resource
            ULONG allocated;     // mask for allocated channel
            ULONG requested;     // mask for requested channels
            } TELEPATH_RESOURCE; // telepath resource
        LOG_CONF logconf;
        RES_DES hres;
        #define pres ((TELEPATH_RESOURCE*) hres)
        CM_Get_First_Log_Conf(&logconf, devnode, ALLOC_LOG_CONF);
        if (CM_Get_Next_Res_Des(&hres, (RES_DES) logconf, ResType_Telepath,
                                                        NULL, 0) == CR_SUCCESS)
            {                       // has telepath channel
            // do something with pres->allocated
            }                       // has telepath channel
        #undef pres
        }
        // Here we would initialize the device, doing things
        // like VPICD_Virtualize_IRQ, etc.
        return CR_SUCCESS;
        }                       // CONFIG_START
    case CONFIG_REMOVE:         // cf == 4
    case CONFIG_STOP:           // cf == 2
        
        irq = 255;
        return CR_SUCCESS;
    default:
        return CR_DEFAULT;
        }                       // select on function code
    }                           // OnConfigure
Figure 6 Arbitrator Function Codes
| Function Code | Description | 
| ARB_TEST_ALLOC | Perform trial allocation of resource | 
| ARB_RETEST_ALLOC | Verify previous trial allocation | 
| ARB_FORCE_ALLOC | Retest but don't fail previous trial allocation | 
| ARG_SET_ALLOC | Commit previous trial allocation | 
| ARB_RELEASE_ALLOC | Discard previous trial allocation | 
| ARB_QUERY_FREE | Return information about free resources | 
| ARB_REMOVE | Prepare for removal of arbitrator | 
Figure 7 nodelistheader_s and nodelist_s Structures
 struct nodelistheader_s
    {                               // node list header
    struct nodelist_s* nlh_Head;    // 00 head of list
    struct nodelist_s* nlh_Tail;    // 04 tail of list
    };                              // 08 node list header
struct nodelist_s
    {                                // node list element
    struct nodelist_s* nl_Next;      // 00 chain to next element
    struct nodelist_s* nl_Prev;      // 04 chain to previous element
    struct devnode_s* nl_ItsDevNode; // 08 a device node that needs resources
    struct Log_Conf* nl_Test_Req;    // 0C a logical configuration for that 
                                     // DEVNODE
    ULONG nl_ulSortDWord;            // 10 sort order for CM_Sort_NodeList
    };                               // 14 node list elementFigure 8 Configuration Functions for Device Drivers
| Function | Description | 
| CONFIG_APM | Power management event is occurring | 
| CONFIG_CALLBACK | Someone did a CM_CallBack_-Device_Driver | 
| CONFIG_FILTER | Filter (restrict) logical configurations | 
| CONFIG_PREREMOVE | Prepare for removal of device | 
| CONFIG_PREREMOVE2 | Prepare for removal of device | 
| CONFIG_PRESHUTDOWN | System is about to shut down | 
| CONFIG_REMOVE | Device is being removed from the system | 
| CONFIG_SHUTDOWN | System is shutting down | 
| CONFIG_START | Start using the allocated configuration | 
| CONFIG_STOP | Stop using the current configuration | 
| CONFIG_TEST | Can you stop using configuration, or can you be removed? | 
| CONFIG_TEST_FAILED | Previous CONFIG_TEST failed | 
| CONFIG_TEST_SUCCEEDED | Previous CONFIG_TEST succeeded | 
| CONFIG_VERIFY_DEVICE | Is your legacy card present? | 
Figure 9 Getting a Device's Configuration
 CONFIGRET OnConfigure(CONFIGFUNC cf, SUBCONFIGFUNC scf,
    DEVNODE devnode, DWORD refdata, ULONG flags)
    {                           // OnConfigure
    switch (cf)
        {                       // select on function code
    case CONFIG_START:          // cf == 1
        {                       // CONFIG_START
        CMCONFIG config;
        CM_Get_Alloc_Log_Conf(&config, devnode,
                              CM_GET_ALLOC_LOG_CONF_ALLOC);
        irq = config.bIRQRegisters[0]; // for example
        // [virtualize IRQ and do other initialization]
        return CR_SUCCESS;
        }                       // CONFIG_START
    
    default:
        return CR_DEFAULT;
        }                       // select on function code
    }                           // OnConfigureFigure 10 CMCONFIG Structure
 typedef struct Config_Buff_s {
WORD    wNumMemWindows;                 // 00 Num memory windows
DWORD   dMemBase[MAX_MEM_REGISTERS];    // 02 Memory window base [9]
DWORD   dMemLength[MAX_MEM_REGISTERS];  // 26 Memory window length [9]
WORD    wMemAttrib[MAX_MEM_REGISTERS];  // 4A Memory window Attrib [9]
WORD    wNumIOPorts;                    // 5C Num IO ports
WORD    wIOPortBase[MAX_IO_PORTS];      // 5E I/O port base [20]
WORD    wIOPortLength[MAX_IO_PORTS];    // 86 I/O port length [20]
WORD    wNumIRQs;                       // AE Num IRQ info
BYTE    bIRQRegisters[MAX_IRQS];        // B0 IRQ list [7]
BYTE    bIRQAttrib[MAX_IRQS];           // B7 IRQ Attrib list [7]
WORD    wNumDMAs;                       // BE Num DMA channels
BYTE    bDMALst[MAX_DMA_CHANNELS];      // C0 DMA list [7]
WORD    wDMAAttrib[MAX_DMA_CHANNELS];   // C7 DMA Attrib list [7]
BYTE    bReserved1[3];                  // D5 Reserved
} CMCONFIG;                             // D8Figure 14 SCHOOLUI.DLL
SCHOOLUI.DEF
 LIBRARY   SCHOOLUI
EXETYPE   WINDOWS
CODE      PRELOAD MOVEABLE DISCARDABLE
DATA      PRELOAD MOVEABLE SINGLE
HEAPSIZE  1024
EXPORTS
          WEP PRIVATE
              EnumPropPages @1SCHOOLUI.RC
 //Microsoft App Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
///////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_STATUS DIALOG DISCARDABLE  0, 0, 142, 106
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | 
    WS_SYSMENU
CAPTION "Status"
FONT 8, "MS Sans Serif"
BEGIN
    LTEXT           "Telepathic Channel:",IDC_STATIC,3,9,74,8
    LTEXT           "(None)",IDC_CHANNEL,93,9,35,7
END
#ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END
3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END
///////////////////////////////////////////////////////////////
#endif    // APSTUDIO_INVOKED
#ifndef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
///////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKEDRESOURCE.H
 //{{NO_DEPENDENCIES}}
// App Studio generated include file.
// Used by SCHOOLUI.RC
//
#define SCHOOL                          101
#define IDD_STATUS                      103
#define IDC_CHANNEL                     1000
#define IDC_STATIC                      -1
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        105
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endifSCHOOLUI.C
 #include <windows.h>
#include <commctrl.h>
#include <setupx.h>
#define EXPORT __export
#define Not_VxD   // to get ring-3 dcls
#include <vmm.h>
#define MIDL_PASS  // suppress 32-bit only #pragma pack(push)
#include <configmg.h>
#include "resource.h"
BOOL WINAPI EXPORT StatusDlgProc(HWND, UINT, WPARAM, LPARAM);
///////////////////////////////////////////////////////////////
BOOL WINAPI EXPORT EnumPropPages(LPDEVICE_INFO pdi,
    LPFNADDPROPSHEETPAGE AddPage, LPARAM lParam)
    {    // EnumPropPages
    PROPSHEETPAGE status; // status property page
    HPROPSHEETPAGE hstatus;
    status.dwSize = sizeof(PROPSHEETPAGE);
    status.dwFlags = PSP_USETITLE;
    _asm mov status.hInstance, ds
    status.pszTemplate = MAKEINTRESOURCE(IDD_STATUS);
    status.hIcon = NULL;
    status.pszTitle = "Status";
    status.pfnDlgProc = StatusDlgProc;
    status.lParam = (LPARAM) pdi->dnDevnode;
    status.pfnCallback = NULL;
    hstatus = CreatePropertySheetPage(&status);
    if (!hstatus)
    return TRUE;
    if (!AddPage(hstatus, lParam))
        DestroyPropertySheetPage(hstatus);
    return TRUE;
    }                           // EnumPropPages
///////////////////////////////////////////////////////////////
BOOL WINAPI EXPORT StatusDlgProc(HWND hdlg, UINT msg,
    WPARAM wParam, LPARAM lParam)
    {                           // StatusDlgProc
    switch (msg)
        {                       // process message
    case WM_INITDIALOG:
        {                       // WM_INITDIALOG
    
        #define ResType_Telepath ((0x10 << 5) | 5)
        
        typedef struct
            {                   // telepath resource
            ULONG allocated;    // mask for allocated channel
            ULONG requested;    // mask for requested channels
            } TELEPATH_RESOURCE;// telepath resource
            
        LOG_CONF logconf;
        RES_DES hres;
        DEVNODE devnode = (DEVNODE) ((LPPROPSHEETPAGE) lParam)->lParam;
            
        if (CM_Get_First_Log_Conf(&logconf, devnode, ALLOC_LOG_CONF)== CR_SUCCESS
            && CM_Get_Next_Res_Des(&hres, (RES_DES) logconf,
            ResType_Telepath, NULL, 0) == CR_SUCCESS)
            {                   // has telepath channel
            TELEPATH_RESOURCE res;
            CM_Get_Res_Des_Data(hres, &res, sizeof(res), 0);
            if (res.allocated >= 0)
                SetDlgItemInt(hdlg, IDC_CHANNEL, res.allocated, FALSE);
            }                   // has telepath channel
        }                       // WM_INITDIALOG
        
        }                       // process message
    return FALSE;
    }                           // StatusDlgProc