Click here to Skip to main content
11,709,375 members (39,794 online)
Click here to Skip to main content

Enumerate Installed Devices Using Setup API

, 16 Mar 2004 226.9K 5.8K 98
Rate this:
Please Sign up or sign in to vote.
Enumerate installed devices on a local or remote computer.

Sample Image - EnumDevices.jpg

Introduction

Windows has a rich collection of APIs to get useful information about installed devices. In this article, I will show how you can enumerate devices on a machine using Setup API.

The program has a simple GUI: only a list control that shows all of the installed devices. All the information about a device (such as name and its icon) is grabbed from Windows Setup API.

Setup API

The Setup application programming interface (API) provides a set of functions that your setup application can call to perform installation operations or get several information about installed devices, their class and also their GUID (a unique identifier for every device).

The application requires the following APIs (description of these APIs was taken from MSDN):

WINSETUPAPI BOOL WINAPI SetupDiGetClassImageList(
        OUT CLASSIMAGELIST_DATA ClassImageListData);

The SetupDiGetClassImageList function builds an image list that contains bitmaps for every installed class and returns the list in a data structure.

WINSETUPAPI BOOL WINAPI SetupDiDestroyClassImageList(
        IN PSP_CLASSIMAGELIST_DATA ClassImageListData);

The SetupDiDestroyClassImageList function destroys a class image list that was built by a call to SetupDiGetClassImageList.

WINSETUPAPI BOOL WINAPI SetupDiGetClassImageIndex(
        IN PSP_CLASSIMAGELIST_DATA ClassImageListData, 
        IN LPGUID ClassGuid, 
        OUT PINT ImageIndex);

The SetupDiGetClassImageIndex function retrieves the index within the class image list of a specified class.

CMAPI CONFIGRET WINAPI CM_Connect_Machine(
            IN PCTSTR  UNCServerName,
            OUT PHMACHINE  phMachine);

CMAPI CONFIGRET WINAPI CM_Disconnect_Machine(
            IN HMACHINE  hMachine);

The CM_Connect_Machine function creates a connection to a local or remote machine. The CM_Disconnect_Machine function removes a connection to a local or remote machine.

CMAPI CONFIGRET WINAPI CM_Locate_DevNode_Ex(
        OUT PDEVINST  pdnDevInst,
        IN DEVINSTID  pDeviceID,  OPTIONAL
        IN ULONG  ulFlags,
        IN HMACHINE  hMachine);

The CM_Locate_DevNode_Ex function obtains a device instance handle to the device node that is associated with a specified device instance identifier, on a local or a remote machine.

pDeviceID represents a device instance identifier. If this value is NULL, or if it points to a zero-length string, the function supplies a device instance handle to the device node at the top of the device tree. The PnP Manager maintains a device tree that keeps track of the devices in the system. The following figure shows the device tree for a sample system configuration. The device tree contains information about the devices present on the system. The PnP Manager builds this tree when the machine boots, using information from drivers and other components, and updates the tree as devices are added or removed. Each node of the device tree is called a device node, or devnode. A devnode consists of the device objects for the device's drivers, plus internal information maintained by the system. Therefore, there is a devnode for each device stack.

Device Tree

CMAPI CONFIGRET WINAPI CM_Get_Child_Ex(
        OUT PDEVINST  pdnDevInst,
        IN DEVINST  dnDevInst,
        IN ULONG  ulFlags,
        IN HMACHINE  hMachine);

The CM_Get_Child_Ex function is used to retrieve a device instance handle to the first child node of a specified device node, in a local or a remote machine's device tree.

CMAPI CONFIGRET WINAPI CM_Get_Sibling_Ex(
        OUT PDEVINST  pdnDevInst,
        IN DEVINST  DevInst,
        IN ULONG  ulFlags,
        IN HMACHINE  hMachine);

The CM_Get_Sibling_Ex function obtains a device instance handle to the next sibling node of a specified device node, in a local or a remote machine's device tree.

Solution

According to the above functions, we should first establish a connection to our computer (local or remote), then get the top node of the device tree (Root device). After this, we should enumerate the installed devices by a simple loop. The application uses three function: EnumDevices(), RetrieveSubNodes() and GetDeviceName(). Following is the source of them:

void EnumDevices()
{
    TCHAR LocalComputer[MAX_PATH];
    DWORD Size = MAX_PATH - 2;
    
    GetComputerName(LocalComputer + 2, &Size);
    LocalComputer[0] = _T('\\');
    LocalComputer[1] = _T('\\');
    
    CONFIGRET cr;
    cr = CM_Connect_Machine(LocalComputer, &m_hMachine);
    
    if (cr != CR_SUCCESS)
    {
        TCHAR Text[MAX_PATH];
        wsprintf(Text, _T("Machine Connection failed, cr= %lx(hex)\n"), cr);
    ::MessageBox(m_hWnd, Text, _T("Error"), MB_ICONSTOP | MB_OK);
        return;
    }    
    
    //Set Image List 
    m_ImageListData.cbSize = sizeof(m_ImageListData);
    SetupDiGetClassImageList(&m_ImageListData);

    m_ImageList.Attach(m_ImageListData.ImageList);
    m_Devices.SetImageList(&m_ImageList, LVSIL_SMALL);
    m_Devices.SetImageList(&m_ImageList, LVSIL_NORMAL);

    DEVNODE dnRoot;
    CM_Locate_DevNode_Ex(&dnRoot, NULL, 0, m_hMachine);
    
    DEVNODE dnFirst;
    CM_Get_Child_Ex(&dnFirst, dnRoot, 0, m_hMachine);    

    RetrieveSubNodes(dnRoot, NULL, dnFirst);

    CM_Disconnect_Machine(m_hMachine);
}

void RetrieveSubNodes(DEVINST parent, DEVINST sibling, DEVNODE dn)
{
    DEVNODE dnSibling, dnChild;
    
    do
    {
        CONFIGRET cr = CM_Get_Sibling_Ex(&dnSibling, dn, 0, m_hMachine);
        
        if (cr != CR_SUCCESS)
        dnSibling = NULL;
        
    TCHAR GuidString[MAX_GUID_STRING_LEN];
    ULONG Size = sizeof(GuidString);
        
    cr = CM_Get_DevNode_Registry_Property_Ex(dn, CM_DRP_CLASSGUID, NULL,
        GuidString, &Size, 0,  m_hMachine);
        
    if (cr == CR_SUCCESS)
    {
        GUID Guid;
        GuidString[MAX_GUID_STRING_LEN - 2] = _T('\0');
        UuidFromString(&GuidString[1], &Guid);
        int Index;
        if (SetupDiGetClassImageIndex(&m_ImageListData, &Guid, &Index))
        {
                CString DeviceName=GetDeviceName(dn);
        m_Devices.InsertItem(m_Devices.GetItemCount(), DeviceName, Index);
        }
    }
        
    cr = CM_Get_Child_Ex(&dnChild, dn, 0, m_hMachine);
    if (cr == CR_SUCCESS)
    {
        RetrieveSubNodes(dn, NULL, dnChild);
    }
        
    dn = dnSibling;
        
    } while (dn != NULL);
}

CString GetDeviceName(DEVNODE DevNode)
{
    CString    strType;
    CString    strValue;
    CString DisplayName;
    LPTSTR    Buffer;
    
    int  BufferSize = MAX_PATH + MAX_DEVICE_ID_LEN;
    ULONG  BufferLen = BufferSize * sizeof(TCHAR);
    
    Buffer  = strValue.GetBuffer(BufferSize);
    if (CR_SUCCESS == CM_Get_DevNode_Registry_Property_Ex(DevNode,
        CM_DRP_FRIENDLYNAME, NULL,
        Buffer, &BufferLen, 0, m_hMachine))
    {
    DisplayName = Buffer;
    }
    else
    {
    BufferLen = BufferSize * sizeof(TCHAR);
        
    if (CR_SUCCESS == CM_Get_DevNode_Registry_Property_Ex(DevNode,
        CM_DRP_DEVICEDESC, NULL,
        Buffer, &BufferLen, 0, m_hMachine))
    {
        DisplayName = Buffer;
    }
    else
    {
        DisplayName=_T("Unknown Device");
    }
    }
    
    return DisplayName;
}

m_Devices is a list control, m_ImageList is an image list of device icons and m_hMachine is a handle of the connected machine.

Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

A. Riazi
CEO Misbah3Com
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
I was born in Shiraz, a very beautiful famous city in Iran. I started programming when I was 12 years old with GWBASIC. Since now, I worked with various programming languages from Basic, Foxpro, C/C++, Visual Basic, Pascal to MATLAB and now Visual C++.
I graduated from Iran University of Science & Technology in Communication Eng., and now work as a system programmer for a telecommunication industry.
I wrote several programs and drivers for Synthesizers, Power Amplifiers, GPIB, GPS devices, Radio cards, Data Acqusition cards and so many related devices.
I'm author of several books like Learning C (primary and advanced), Learning Visual Basic, API application for VB, Teach Yourself Object Oriented Programming (OOP) and etc.
I'm winner of January, May, August 2003 and April 2005 best article of month competetion, my articles are:

You can see list of my articles, by clicking here


You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
Amir Mohammad Nasrollahi9-Aug-13 20:25
professionalAmir Mohammad Nasrollahi9-Aug-13 20:25 
GeneralMy vote of 5 Pin
manoj kumar choubey26-Feb-12 19:55
membermanoj kumar choubey26-Feb-12 19:55 
QuestionLicense for this code Pin
mikejurka30-Apr-09 5:36
membermikejurka30-Apr-09 5:36 
GeneralFinding a specific device... Pin
Sharath Madhuranath14-Apr-09 1:50
memberSharath Madhuranath14-Apr-09 1:50 
Generalserial number of a connected mass storage device Pin
madddi9-Mar-09 7:56
membermadddi9-Mar-09 7:56 
QuestionCan you tell me how to enumerate 3G device from PC Pin
alert091927-Jul-08 23:30
memberalert091927-Jul-08 23:30 
QuestionCM_Get_DevNode_Registry_Property_Ex not safe Pin
Ingeer13-Nov-07 13:25
memberIngeer13-Nov-07 13:25 
QuestionHow to detect if a network card is disabled Pin
samaruf9-May-07 1:05
membersamaruf9-May-07 1:05 
Generalhard disk serial Pin
nicolas20027-Apr-07 13:34
membernicolas20027-Apr-07 13:34 
GeneralRe: hard disk serial Pin
A. Riazi30-Apr-07 23:31
memberA. Riazi30-Apr-07 23:31 
GeneralRe: hard disk serial Pin
nicolas2002-May-07 4:39
membernicolas2002-May-07 4:39 
GeneralRe: hard disk serial Pin
nicolas20014-May-07 7:00
membernicolas20014-May-07 7:00 
Generalthank A.Riazi! Pin
brocean30-Mar-07 23:53
memberbrocean30-Mar-07 23:53 
GeneralRe: thank A.Riazi! Pin
A. Riazi2-Apr-07 0:38
memberA. Riazi2-Apr-07 0:38 
QuestionLinker error mfc42ud.lib not found Pin
Rahul U. Kate7-Mar-07 1:36
memberRahul U. Kate7-Mar-07 1:36 
Questionbackup drivers Pin
mohcin15-Jan-06 23:30
membermohcin15-Jan-06 23:30 
QuestionBackup drivers Pin
mohcin13-Jan-06 22:50
membermohcin13-Jan-06 22:50 
GeneralEnumerate devices on Windows NT Pin
prabhakarks25-Nov-05 2:26
memberprabhakarks25-Nov-05 2:26 
AnswerRe: Enumerate devices on Windows NT Pin
A. Riazi28-Nov-05 3:09
memberA. Riazi28-Nov-05 3:09 
QuestionHow can I enumerate uninstalled devices? Pin
guang peng13-Nov-05 16:25
memberguang peng13-Nov-05 16:25 
AnswerRe: How can I enumerate uninstalled devices? Pin
A. Riazi13-Nov-05 22:32
memberA. Riazi13-Nov-05 22:32 
GeneralRe: How can I enumerate uninstalled devices? Pin
guang peng15-Nov-05 14:41
memberguang peng15-Nov-05 14:41 
GeneralEnumerate Devices without DDK Pin
inf00910-Nov-05 4:16
memberinf00910-Nov-05 4:16 
GeneralUuidFromString error Pin
rovan27-Sep-05 2:30
sussrovan27-Sep-05 2:30 
AnswerRe: UuidFromString error Pin
A. Riazi13-Nov-05 22:36
memberA. Riazi13-Nov-05 22:36 
QuestionCM_CONNECT_MACHINE failed Pin
Cosmixx2-Sep-05 23:45
memberCosmixx2-Sep-05 23:45 
GeneralConvert MFC to console mode... Pin
oliverfg25-Aug-05 15:17
memberoliverfg25-Aug-05 15:17 
AnswerRe: Convert MFC to console mode... Pin
A. Riazi27-Aug-05 20:26
memberA. Riazi27-Aug-05 20:26 
GeneralUsing VS6 Pin
ronannaughton24-Aug-05 20:01
memberronannaughton24-Aug-05 20:01 
GeneralRe: Using VS6 Pin
renjwjx2-Apr-09 1:06
memberrenjwjx2-Apr-09 1:06 
GeneralI need help !!! Pin
oliverfg21-Aug-05 7:08
memberoliverfg21-Aug-05 7:08 
GeneralError compiling !!! Pin
oliverfg14-Aug-05 15:46
memberoliverfg14-Aug-05 15:46 
GeneralRe: Error compiling !!! Pin
Christian Graus14-Aug-05 16:54
memberChristian Graus14-Aug-05 16:54 
GeneralRe: Error compiling !!! Pin
A. Riazi14-Aug-05 23:00
memberA. Riazi14-Aug-05 23:00 
GeneralRe: Error compiling !!! Pin
oliverfg15-Aug-05 12:37
memberoliverfg15-Aug-05 12:37 
GeneralRe: Error compiling !!! Pin
oliverfg15-Aug-05 12:44
memberoliverfg15-Aug-05 12:44 
GeneralRe: Error compiling !!! Pin
oliverfg16-Aug-05 13:21
memberoliverfg16-Aug-05 13:21 
GeneralRe: Error compiling !!! Pin
jsaer@hotmail.com26-Sep-05 2:02
memberjsaer@hotmail.com26-Sep-05 2:02 
AnswerRe: Error compiling !!! Pin
Dragan Knezevic28-May-06 23:52
memberDragan Knezevic28-May-06 23:52 
GeneralRe: Error compiling !!! Pin
Rabin Lin17-Dec-06 21:48
memberRabin Lin17-Dec-06 21:48 
GeneralRe: Error compiling !!! Pin
Dragan Knezevic28-Jan-07 11:23
memberDragan Knezevic28-Jan-07 11:23 
GeneralRe: Error compiling !!! Pin
feeling1-Jul-06 17:02
memberfeeling1-Jul-06 17:02 
GeneralRe: Error compiling !!! [modified] Pin
Andy Byron5-Apr-07 19:54
memberAndy Byron5-Apr-07 19:54 
GeneralGet username of remote computer Pin
Tailana13-Jun-05 22:05
memberTailana13-Jun-05 22:05 
GeneralRe: Get username of remote computer Pin
A. Riazi13-Jun-05 22:25
memberA. Riazi13-Jun-05 22:25 
GeneralRead the properties of a device that is connected through Bluetooth Serial Communications port Pin
ddas7729-Apr-05 3:13
memberddas7729-Apr-05 3:13 
Questioncan be running on WinME and Win98? Pin
StoreErin20-Feb-05 14:23
sussStoreErin20-Feb-05 14:23 
GeneralNeed some information Pin
neelimakrishna21-Nov-04 18:28
memberneelimakrishna21-Nov-04 18:28 
GeneralRe: Need some information Pin
A. Riazi22-Nov-04 5:11
memberA. Riazi22-Nov-04 5:11 
Generalplease help Pin
bondofuk10-Jun-04 18:54
memberbondofuk10-Jun-04 18:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150819.1 | Last Updated 17 Mar 2004
Article Copyright 2004 by A. Riazi
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid