Introduction

This article explains:

How to identify third party “.inf” files related to a “.sys” file

How to uninstall/force uninstall selected inf file

How the application works

During third party driver installation, related inf files get renamed to Oemxx.inf and get installed
in the “Windows Root\Inf” folder (e.g.: C:\Windows\Inf).
Windows also creates a .PNF file and stores it at the same location. To identify a driver for a device,
the OS goes through these inf files.

This application uses the above mentioned information to figure out the oem*.inf files that
are related to a driver and list them in the listview.
These files can be opened in Notepad by right clicking on their entry in listview.
A file in the list can be right clicked in the listview and uninstalled as well.

When a sys file is selected, the application iterates through the inf folder mentioned above and searches for files using
the following search wild card: Oem*.inf.
Each of the inf file obtained in the search is opened and the following section and key are searched for in the inf file:

[SourceDisksFile] section is searched

Under the [SourceDisksFile] section, a key with the .sys file name selected is searched

For example, if the .sys file selected is “scvscv.sys”, then we open the first
Oemxx.inf file obtained in the search and looks for the [SourceDisksFiles] section. Under that section, the application looks for a key with name “scvscv.sys”. If we are able to get a value for this key, then we know that this inf file is related to
the selected driver “scvscv.sys”.

The user can then right click on the inf file shown in the list and view the content in the richedit box on the right bottom of the screen or open it in
Notepad by right clicking on the particular entry in listview. Once the user is sure that the
inf can be uninstalled, they can right click and select Uninstall.

In some cases, it might not be possible to uninstall the inf file as it might be in use. In such cases, if the user is sure that the
inf file can be uninstalled, they can select the checkbox “Force Inf Uninstall”. This would ensure that the
inf file would get uninstalled forcefully. A screenshot of the UI is shown below:

Only Oemxx.inf files are searched as these are the ones that will be part of
the third party driver installation. Microsoft suggests leaving the driver file untouched even after uninstalling
the inf file as the driver files might be used by other applications. Due to this reason, this application will not delete the selected sys file.

Classes to accomplish the task

Entire logic to accomplish the task mentioned in this article is enveloped in these three classes;
CInfNDriverDelete, CInfNDriverDeleteData, and CInfNDriverDeleteView.
The responsibility of each class is shown below:

CInfNDriverDelete – This class contains member elements representing
the Data and View by means of the CInfNDriverDeleteData and CInfNDriverDeleteView classes, respectively.
A child window gets created in this class.

CInfNDriverDeleteData – This stores the data that should be shown in the view.

CInfNDriverDeleteView – This class is used to initialize the listview/other UI elements and fill in data that is available in
CInfNDriverDeleteData into the listview/other required UI elements.

UI elements

Details of UI elements used and the calls to create those are detailed below.

On the UI, a static box is drawn first. Then the controls are drawn after that so that
a proper background color to the window is obtained. Otherwise, the groupbox and checkbox will have
their own color and the screen will look patchy.
I did try setting the background color in many different ways, but nothing worked and hence used the static control as a canvas.

All calls to create UI elements are present within the following function in the source code:
CInfNDriverDeleteView::Draw().

Creating a Groupbox

To create a groupbox, CreateWindowEx() should be called with the style
BW_GROUPBOX. The window class parameter should be “BUTTON”. The code snippet is shown below:

Creating a Listview

To create a listbox, CreateWindowEx() should be called. The style can be
LVS_REPORT.
The window class parameter should be WC_LISTVIEW. The ID should be assigned to
the HMENU parameter. This will be later used to get
control events. The code snippet is shown below:

Creating a button

To create the Browse button, CreateWindowEx() should be called with
a window class as “BUTTON”. ID should be assigned
to the HMENU parameter. This will be later used to get control events.
The code snippet is shown below:

Creating a checkbox

To create a checkbox button, CreateWindowEx() should be called with
a window class as “BUTTON”. ID should be assigned to the HMENU parameter. This will be later used to get
the control events. The style flag should contain BS_AUTOCHECKBOX.
The code snippet is shown below:

WM_NOTIFY message

The control elements will send a WM_NOTIFY message on events.
The lParam of WM_NOTIFY would contain a pointer to
NMHDR. The layout of the NMHDR structure is as shown below:

typedefstruct tagNMHDR
{
HWNDhwndFrom; // handle of the control sending the message
UINT_PTR idFrom; // id of the control sending the message
UINTcode; // notification code used to identify the event. // This is used to idenfity if it is a right click // or a click in the control
} NMHDR;

The NMHDR structure contains the details on the control ID and
the control hwnd. This is where the control ID that we assigned earlier to
the Listview and Richedit is useful.

Creating the RichEdit control

To create a RichEdit control RichEd32.dll should be loaded into the memory.
A CreateWindowEx call should follow. A call to load the library and create the control is shown:

Note: Freeing the richedit library via
FreeLibrary() was causing the application to crash.
I did not get time to spend on it further, but I will look into it when I get time. For now, I
have commented out the FreeLibrary() call.

Creating Context menu over Listview

Once the listview gets populated, right clicking on it would bring up a context menu with
the option to view the inf in Notepad and to uninstall the inf.

Right click on the control was trapped via the NM_RCLICK notification from the control.
The following calls were used to create the context menu:

Editbox subclassing

When a user copies and pastes a sys file path to the editbox and presses Enter, the inf file list should get populated. For this reason, the editbox
was sub classed. In the sub classed proc, Enter key was sensed and a user message sent to the parent window to look for
the relevant file and update
the listview based on the path pasted by the user. The user message sent from
the Editbox proc to the parent window is WM_SIGMA_SELECTFILE.

To subclass the editbox, the default Winproc of the editbox will have to be replaced by calling
SetWindowLong(). Following is the code to do that:

Selecting a driver file

To select a driver file, the Win32 API GetOpenFileName() has been used. This will open the Select File dialog. This call is housed inside
the SelectDriverFile()
function in InfDriverDelete.cpp. _wsplitpath_s is used to split and get
the .sys file name. This function was really helpful
as there was no need to write any code to do this parsing.

Getting the list of inf files

Once the sys file is selected, FindFirstFile() is used to iterate through
the inf directory under the SYSTEMROOT directory. The wild card filter used during the
search is OEM*.inf files. From the list of OEM*.inf files that is obtained, each
inf file is searched using the INI file function GetPrivateProfileString to
search for the [SourceDisksFiles] section. Under the section the key equal to
the sys file name selected is searched for. If such a key is present, then this is
added to the data array. Finally, this data array will have the list of oem*.inf files for the particular “.sys” file that was selected.

GetEnvironmentVariable(_T("SYSTEMROOT")) is used to get
the Windows root directory (e.g. C:\Windows).

Loading the selected inf file in a RichEdit control

The selected inf file from the listview will be loaded into the RichEdit control. To load a file into the RichEdit control, streaming will be used. The following
two functions in InfNDriverDeleteView.cpp do this work:

CInfNDriverDeleteView::FillRichEditFromInfFile() opens the inf file and sends
the EM_STREAMIN message to the RichEdit handle. The LPARAM will contains
the address to the EDITSTREAM structure. EDITSTREAM will contain
a handle to the Inf file opened and a callback function (EditStreamCallback()) which will actually read the inf
file and load it into the RichEdit control. Both the functions are shown below for clarity:

Uninstall of inf can be forced via the “Force INF Uninstall” checkbox available on the UI.
The dw_ForceInfUninstall variable value depends on the status
of this checkbox.

Environment

This article has been developed and tested under the following environment only: Lenovo T410 Laptop, VC++ 2005, Unicode, C++,
and Windows 7 Enterprise (English language). This article uses the code base from my earlier articles. Earlier I had
a VC++ 6.0 workspace, which has been upgraded to a VS2005 solution with this article.

Comments and Discussions

Hi, Since last of couple of days I developed USB based Modem by using usebser.sys driver. While developing I created lot of inf files to test functionality. I always go and manual delete inf files with some registry cleaning. I thought this application best suitable to find and delete unnecessary inf files. When I give "C:\WINDOWS\system32\drivers\usbser.sys" path in application, it does not showing any inf files. Am I missing any steps?