代码实现利用inf文件安装硬件驱动

代码参考了网上资料并进行了整理:

#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 "DirAndFile .h"
#include <string>

using namespace std;

#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "Newdev.lib")

#define  MAX_CLASS_NAME_LEN 1024

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 *)lpMessageBuffer);
	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_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 the
	// 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_DeviceInfo:
	err = GetLastError();
	SetupDiDestroyDeviceInfoList(DeviceInfoSet);
	SetLastError(err);

	return err == NO_ERROR;
}

/************************************************************************** 
* 函数名:InstallDriver 
* 功  能:安装驱动
* 参  数:_TCHAR *InfName,inf文件的文件路径
*         _TCHAR *HardwareID,硬件设备ID
* 返回值:int ,0为成功
**************************************************************************/
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> <Hardware_ID>/n"));
		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)
	{
		return 1; // Install Success, reboot required.
	}

	return 0; // Install Success, no reboot required.
}

/************************************************************************** 
* 函数名:RemoveDriver 
* 功  能:卸载驱动
* 参  数:_TCHAR *HardwareID,硬件设备ID
* 返回值:int ,0为成功
**************************************************************************/
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;
}
调用方法:

//注意安装64位驱动的时候需要编译成64位应用程序才能安装成功
int _tmain(int argc, _TCHAR* argv[])
{
	string infPath = "D:\\systest\\siusbxp.inf";
	string hardwareId = "USB\\VID_xxxx&PID_xxxx";

	InstallDriver((_TCHAR *)infPath.c_str(), (_TCHAR *)hardwareId.c_str());
	
	return 0;
}

注意在安装64位驱动的时候需要编译成64位应用程序才能安装成功。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DPInst.exe: installs and uninstalls driver packages. DPInst.exe: 安装及删除驱动程序包。 By default, the tools searches the current directory and tries to install all driver packages found. 默认情况下,此工具会搜索当前目录并尝试安装找到的驱动程序包。 Usage: DPInst.exe [/U INF-file][/S | /Q][/LM][/P][/F][/SH][/SA][/A][/PATH Path][/EL][/L LanguageID][/C][/D][/LogTitle Title][/SW][/? | /h | /help] 用法:DPInst.exe [/U INF-file][/S | /Q][/LM][/P][/F][/SH][/SA][/A][/PATH Path][/EL][/L LanguageID][/C][/D][/LogTitle Title][/SW][/? | /h | /help] /U path to INF file Uninstall a driver package (INF-file). /U 指定 INF 文件 删除一个驱动程序包(INF-文件)。 /S | /Q Silent (Quiet) mode. Suppresses the Device Installation Wizard and any dialogs popped-up by the operating system. /LM Legacy mode. Accepts unsigned driver packages and packages with missing files. These packages won't install on the latest version of Windows. /LM 传统模式。接受未签名的驱动包(缺少.cat文件)以及包中有文件丢失。 /P Prompt if the driver package to be installed is not better than the current one. /P 如果驱动包已经安装以及比当前使用的版本要旧就发出提示。 /F Force install inf the driver package is not better than the current one. /F 强制安装比当前使用的版本要旧的驱动包。 /SH Scans hardware for matching devices and only copies and installs those drivers for which a device is present. Only valid for Plug and Play drivers. /SH 仅仅对已插入的匹配的硬件设备进行扫描。 /SA Suppress the Add/Remove Programs entry normally created for each driver package. /SA 禁止“添加或删除程序”创建卸载项。 /A Install all or none. /PATH Path Search for driver packages under the given path. /PATH 路径 在指定的路径下搜索驱动程序包。 /EL Enables all languages not explicitly listed in the XML file. /L LanguageID Tries to use the given language in all UI. Useful for localization tests. /SE Suppress the EULA. /SE 禁止最终用户许可协议。 /C Dump logging output to attached Console (Windows XP and above). /C 转存日志文件输出到附加控

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值