[Post] source code for automatically installing and uninstalling the driver
# Include "stdafx. H"
# Include <tchar. h> // make all functions Unicode safe.
# Include <newdev. h> // For the API updatedriverforplugandplaydevices ().
# Include <setupapi. h> // For setupdixxx functions.
# Include "Install. H"
Int displayerror (tchar * errorname)
{
DWORD err = getlasterror ();
Lpvoid lpmessagebuffer = NULL;
If (formatmessage (
Format_message_allocate_buffer | format_message_from_system,
Null,
Err,
Makelangid (lang_neutral, sublang_default ),
(Lptstr) lpmessagebuffer,
0,
Null ))
NULL; // _ tprintf (text ("% s failure: % s \ n"), errorname, (tchar *) lpmessag
Ebuffer );
Else
NULL; // _ tprintf (text ("% s failure: (0x % 08x) \ n"), errorname, err );
If (lpmessagebuffer) localfree (lpmessagebuffer); // Free System Buffer
Setlasterror (ERR );
Return false;
}
Bool findexistingdevice (in lptstr hardwareid)
{
Hdevinfo deviceinfoset;
Sp_devinfo_data deviceinfodata;
Dword I, err;
Bool found;
//
// Create a device information set with all present devices.
//
Deviceinfoset = setupdigetclassdevs (null, // all classes
0,
0,
Digcf_allclasses | digcf_present); // all devices present on System
If (deviceinfoset = invalid_handle_value)
{
Return displayerror (text ("getclassdevs (all present devices )"));
}
// _ Tprintf (text ("Search for device ID: [% s] \ n"), hardwareid );
//
// Enumerate through all devices.
//
Found = false;
Deviceinfodata. cbsize = sizeof (sp_devinfo_data );
For (I = 0; setupdienumdeviceinfo (deviceinfoset, I, deviceinfodata); I ++)
{
DWORD datat;
Lptstr P, buffer = NULL;
DWORD buffersize = 0;
//
// We won't know the size of the hardwareid buffer until we call
// This function. So call it with a null to begin with, and then
// Use the required buffer size to alloc the nessicary space.
// Keep calling we have success or an unknown failure.
//
While (! Setupdigetdeviceregistryproperty (
Deviceinfoset,
Deviceinfodata,
Spdrp_hardwareid,
Datat,
(Pbyte) buffer,
Buffersize,
Buffersize ))
{
If (getlasterror () = error_invalid_data)
{
//
// May be a legacy device with no hardwareid. Continue.
//
Break;
}
Else if (getlasterror () = error_insufficient_buffer)
{
//
// We need to change the buffer size.
//
If (buffer)
Localfree (buffer );
Buffer = (char *) localalloc (lptr, buffersize );
}
Else
{
//
// Unknown failure.
//
Displayerror (text ("getdeviceregistryproperty "));
Goto cleanup_deviceinfo;
}
}
If (getlasterror () = error_invalid_data)
Continue;
//
// Compare each entry in the buffer multi-SZ list with our hardwareid.
//
For (P = buffer; * P & (P <& buffer [buffersize]); P + = lstrlen (p) + sizeof (tchar ))
{
// _ Tprintf (text ("compare device ID: [% s] \ n"), P );
If (! _ Tcscmp (hardwareid, p ))
{
// _ Tprintf (text ("found! [% S] \ n "), P );
Found = true;
Break;
}
}
If (buffer) localfree (buffer );
If (found) break;
}
If (getlasterror ()! = No_error)
{
Displayerror (text ("enumdeviceinfo "));
}
//
// Cleanup.
//
Cleanup_deviceinfo:
Err = getlasterror ();
Setupdidestroydeviceinfolist (deviceinfoset );
Setlasterror (ERR );
Return err = no_error ;//???
}
Bool
Installrootenumerateddriver (in lptstr hardwareid,
In lptstr inffile,
Out pbool rebootrequired optional
)
{
Hdevinfo deviceinfoset = 0;
Sp_devinfo_data deviceinfodata;
Guid classguid;
Tchar classname [max_class_name_len];
DWORD err;
//
// Use the INF file to extract the class guid.
//
If (! Setupdigetinfclass (inffile, classguid, classname, sizeof (classname), 0 ))
{
Return displayerror (text ("getinfclass "));
}
//
// Create the container for the to-be-created device information element.
//
Deviceinfoset = setupdicreatedeviceinfolist (classguid, 0 );
If (deviceinfoset = invalid_handle_value)
{
Return displayerror (text ("createdeviceinfolist "));
}
//
// Now create the element.
// Use the class guid and name from the INF file.
//
Deviceinfodata. cbsize = sizeof (sp_devinfo_data );
If (! Setupdicreatedeviceinfo (deviceinfoset,
Classname,
Classguid,
Null,
0,
Dicd_generate_id,
Deviceinfodata ))
{
Displayerror (text ("createdeviceinfo "));
Goto cleanup_deviceinfo;
}
//
// Add the hardwareid to the device's hardwareid property.
//
If (! Setupdisetdeviceregistryproperty (deviceinfoset,
Deviceinfodata,
Spdrp_hardwareid,
(Lpbyte) hardwareid,
(Lstrlen (hardwareid) + 1 + 1) * sizeof (tchar )))
{
Displayerror (text ("setdeviceregistryproperty "));
Goto cleanup_deviceinfo;
}
//
// Transform the Registry element into an actual devnode
// In the pnp hw tree.
//
If (! Setupdicallclassinstaller (dif_registerdevice,
Deviceinfoset,
Deviceinfodata ))
{
Displayerror (text ("callclassinstaller (registerdevice )"));
Goto cleanup_deviceinfo;
}
//
// The element is now registered. We must explicitly remove
// Device using dif_remove, If we encounter any failure from now on.
//
//
// Install the driver.
//
If (! Updatedriverforplugandplaydevices (0,
Hardwareid,
Inffile,
Installflag_force,
Rebootrequired ))
{
DWORD err = getlasterror ();
Displayerror (text ("updatedriverforplugandplaydevices "));
If (! Setupdicallclassinstaller (
Dif_remove,
Deviceinfoset,
Deviceinfodata ))
{
Displayerror (text ("callclassinstaller (remove )"));
}
Setlasterror (ERR );
}
//
// Cleanup.
//
Cleanup_deviceinfo:
Err = getlasterror ();
Setupdidestroydeviceinfolist (deviceinfoset );
Setlasterror (ERR );
Return err = no_error;
}
Int installdriver (_ tchar * infname, _ tchar * hardwareid)
{
Win32_find_data findfiledata;
Bool rebootrequired = 0; // must be cleared.
_ Tchar * fname, * hwid;
Fname = infname;
Hwid = hardwareid;
If (findfirstfile (fname, findfiledata) = invalid_handle_value)
{
// _ Tprintf (text ("file not found. \ n "));
// _ Tprintf (text ("Usage: install <inf_file> Return 2; // install failure
}
//
// Look to see if this device allready exists.
//
If (findexistingdevice (hwid ))
{
//
// No need to create a device node, just call our API.
//
If (! Updatedriverforplugandplaydevices (0, // No window handle
Hwid, // hardware ID
Fname, // filename
Installflag_force,
Rebootrequired ))
{
Displayerror (text ("updatedriverforplugandplaydevices "));
Return 2; // install failure
}
}
Else
{
If (getlasterror ()! = Error_no_more_items)
{
//
// An unknown failure from findexistingdevice ()
//
// _ Tprintf (text ("(ierror_no_more_items) \ n "));
// _ Tprintf (text ("(install failure! Code = 2) \ n "));
Return 2; // install failure
}
//
// Driver does not exist, create and call the API.
// Hardwareid must be a multi-SZ string, which argv [2] is.
//
If (! Installrootenumerateddriver (hwid, // hardwareid
Fname, // filename
Rebootrequired ))
{
// _ Tprintf (text ("(installrootenumerateddriver failure! Code = 2) \ n
"));
Return 2; // install failure
}
}
// _ Tprintf (text ("driver installed successfully. \ n "));
If (rebootrequired)
{
// _ Tprintf (text ("(reboot required) \ n "));
Return 1; // install success, reboot required.
}
Return 0; // install success, no reboot required.
}
Int removedriver (_ tchar * hardwareid)
{
Hdevinfo deviceinfoset;
Sp_devinfo_data deviceinfodata;
Dword I, err;
Deviceinfoset = setupdigetclassdevs (null, // all classes
0,
0,
Digcf_allclasses | digcf_present); // all devices present on System
If (deviceinfoset = invalid_handle_value)
{
Displayerror (text ("getclassdevs (all present devices )"));
Return 1;
}
//
// Enumerate through all devices.
//
Deviceinfodata. cbsize = sizeof (sp_devinfo_data );
For (I = 0; setupdienumdeviceinfo (deviceinfoset, I, deviceinfodata); I ++)
{
DWORD datat;
Lptstr P, buffer = NULL;
DWORD buffersize = 0;
//
// We won't know the size of the hardwareid buffer until we call
// This function. So call it with a null to begin with, and then
// Use the required buffer size to alloc the nessicary space.
// Keep calling we have success or an unknown failure.
//
While (! Setupdigetdeviceregistryproperty (
Deviceinfoset,
Deviceinfodata,
Spdrp_hardwareid,
Datat,
(Pbyte) buffer,
Buffersize,
Buffersize ))
{
If (getlasterror () = error_invalid_data)
{
//
// May be a legacy device with no hardwareid. Continue.
//
Break;
}
Else if (getlasterror () = error_insufficient_buffer)
{
//
// We need to change the buffer size.
//
If (buffer)
Localfree (buffer );
Buffer = (char *) localalloc (lptr, buffersize );
}
Else
{
//
// Unknown failure.
//
Displayerror (text ("getdeviceregistryproperty "));
Goto cleanup_deviceinfo;
}
}
If (getlasterror () = error_invalid_data)
Continue;
//
// Compare each entry in the buffer multi-SZ list with our hardwareid.
//
For (P = buffer; * P & (P <& buffer [buffersize]); P + = lstrlen (p) + sizeof (tchar ))
{
// _ Tprintf (text ("compare device ID: [% s] \ n"), P );
If (! _ Tcscmp (hardwareid, p ))
{
// _ Tprintf (text ("found! [% S] \ n "), P );
//
// Worker function to remove device.
//
If (! Setupdicallclassinstaller (dif_remove,
Deviceinfoset,
Deviceinfodata ))
{
Displayerror (text ("callclassinstaller (remove )"));
}
Break;
}
}
If (buffer) localfree (buffer );
}
If (getlasterror ()! = No_error) & (getlasterror ()! = Error_no_more_items ))
{
Displayerror (text ("enumdeviceinfo "));
}
//
// Cleanup.
//
Cleanup_deviceinfo:
Err = getlasterror ();
Setupdidestroydeviceinfolist (deviceinfoset );
Return err;
}