This article explains the following:
- How to get the list of drivers running on a Windows machine
- How to display the list of drivers in a ListView using pure Win32 calls
Note: This article has the latest code for an earlier article, and is updated with the features explained in this article. Please click here to reach my earlier article.
How to get the list of drivers on the machine
Drivers are, in fact, services which run on the OS. To get the list of services, first open the SCM (Service Control Manager) and then call
EnumServicesStatus() to enumerate the services.
If more information is required than the ones returned by
EnumServicesStatus() (which is the case here), then the service will have to be opened using
OpenService() to query some of the required details using
QueryServiceConfig(). These calls are made in the function
EnumServicesStatus() will get following information:
- Driver name
- Driver description
- Current state of Driver
- Number of Drivers installed in the system
- Driver type
Here is the code snippet to enumerate the services:
BOOL b_RetVal = FALSE;
DWORD dw_ResumeHandle = 0;
dw_ServiceType = SERVICE_DRIVER;
dw_ServiceState = SERVICE_STATE_ALL;
b_RetVal = ::EnumServicesStatus(h_SCM,
DWORD dw_Error = GetLastError();
if ((b_RetVal == FALSE) || dw_Error == ERROR_MORE_DATA)
DWORD dw_Bytes = dw_BytesNeeded + sizeof(ENUM_SERVICE_STATUS);
lpServiceStatus = new ENUM_SERVICE_STATUS [dw_Bytes];
EnumServicesStatus(), the driver startup type and path of the driver is still missing. For this,
OpenService() will have to be used to open the service and query the information regarding the service using
QueryServiceConfig(), the following additional information will be obtained:
- Driver startup type
- Path of driver file
The code snippet to open the service and query the services is shown below:
h_ServiceHandle = NULL;
h_ServiceHandle = OpenService(h_SCM,
if(NULL != h_ServiceHandle)
lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
if (lpqscBuf == NULL)
bSuccess = FALSE;
Meaning of each field in the Driver Information child window
- Serial No.: Sequence number of list of drivers, just allows interested users to see the count of drivers.
- Driver Name: This is the driver name and is mostly the same as the driver file name.
- Description: Description of the driver.
- Driver Type: Shows the type of driver, whether it’s a Kernel driver or a File System driver.
- Start Type: Shows the kind of start up. There are four types of startup modes plus one disable state. They are:
- Auto start- Automatically started by SCM during system startup.
- Boot start- Started by the system loader in case of drivers.
- Demand start- Started on demand by calling
- System start- Started by the
IoInitSystem() call in the case of drivers.
- Disabled- This state mentions that the driver is disabled.
- Status: Shows the current status of the driver. The driver could be in one of the following states: Not Running, Starting, Running, Pause is pending, Paused, Continue is pending, Stopping.
- Image Path: Path of the driver file.
How to create, add headers, and add elements to the list view
The listview is created in the
CDriverInfoView class in the function
CDriverInfoView::Draw(). The call to create the list view is shown below. The
LVS_REPORT style is required to get the header for the columns.
The listview is created by the following call.
WC_LISTVIEW should be used as the class name. This is done in the function
bool CDriverInfoView::Draw(). The code snippet to do this is shown below:
m_hwndListView = CreateWindowEx(WS_EX_CLIENTEDGE,
"", WS_CHILD | WS_VISIBLE | LVS_REPORT,
rect.right, rect.bottom, m_hwndParent,
(HINSTANCE) GetWindowLong (m_hwndParent, GWL_HINSTANCE),
Adding column headers is done by calling
wParam represents the column number. This is done in the function
bool CDriverInfoView::FillData(CDriverInfoData &pDriverInfoData) as shown below:
memset((void*)&ListviewCol, 0, sizeof(ListviewCol));
ListviewCol.mask = LVCF_TEXT | LVCF_WIDTH; ListviewCol.cx = 0x40; ListviewCol.pszText = "Serial No";
ListviewCol.pszText = "Driver Name";
Inserting rows is done by first inserting the first cell in a row with the value and then subsequent cells are set with values.
SendMessage with the
LVM_SETITEM messages are used to achieve this. The code snippet to do the same is shown below:
memset((void*)&structDriverInfo, 0, sizeof(structDriverInfo));
int i_Col = 0;
ListviewItem.iItem = i_Col;
ListviewItem.iSubItem = DRIVERINFO_SERIALNO_COL;
memset((void*)szSlNo, 0, sizeof(TCHAR));
sprintf(szSlNo, "%d", i_Col + 1);
ListviewItem.pszText = TEXT(szSlNo);
ListviewItem.iItem = i_Col;
ListviewItem.iSubItem = DRIVERINFO_NAME_COL; ListviewItem.pszText = TEXT(structDriverInfo.DriverName);
Creation of Driver Information MDI child window
The MDI child window which shows Driver Information is created on getting the command message of
ID_INFORMATION_DRIVERINFORMATION in the main frame window proc of
SigmaFrameWndProc. Here, a
CDriverInfo object is created on the heap. This
g_pDriverInfo object is then used to create the window and fill in the list control.
CDriverInfo::CreateDriverInfoWindow() registers the child window and creates the MDI child window. The code snippet is shown below:
MDIChildCreateStruct.szClass = TEXT("SigmaDriverInfoWnd");
MDIChildCreateStruct.szTitle = TEXT("Driver Information");
MDIChildCreateStruct.hOwner = ghInstance;
MDIChildCreateStruct.x = CW_USEDEFAULT;
MDIChildCreateStruct.y = CW_USEDEFAULT;
MDIChildCreateStruct.cx = CW_USEDEFAULT;
MDIChildCreateStruct.cy = CW_USEDEFAULT;
MDIChildCreateStruct.style = 0;
MDIChildCreateStruct.lParam = 0;
m_hwndDriverInformation = (HWND) SendMessage(ghMDIClientArea,
(LPARAM) (LPMDICREATESTRUCT) &MDIChildCreateStruct) ;
if(NULL == m_hwndDriverInformation)
MDICREATESTRUCT is used to set the child window parameters. This is passed as the last parameter of
SendMessage is used to send
WM_MDICREATE messages to the client area of the main frame window.
InitCommonControlsEx() is called to initialize the common controls. This is required for the list control to be created.
Classes and their functionality
CDriverInfo – This class holds member elements representing Data and View by means of the
CDriverInfoView classes, respectively. A child window is created in this class.
CDriverInfoData – This stores the data that should be shown in the listview.
CDriverInfoView – This class is used to initialize the listview and fill in data that is available in
CDriverInfoData into the listview.
This article had been developed and tested under the following environment only: Lenovo T61 laptop, VC++ 6.0, UNICODE, C++, and XP SP3.