主要有四个步骤:
1. 根据“协作安装程序应用一例”编写dll
2. 函数实现dll的注册
3. 然后预安装
4. 插入设备测试
1. 根据“协作安装程序应用一例”编写dll
Dll是基于win32的dll程序,入口函数的声明如下:
extern "C"__declspec(dllexport)HRESULT NACoInstallEntryPoint( //HRESULT IN DI_FUNCTION InstallFunction, IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL IN OUT PCOINSTALLER_CONTEXT_DATAContext );
实现如下:
HRESULT NACoInstallEntryPoint(
__in DI_FUNCTION InstallFunction,
__in HDEVINFO DeviceInfoSet,
__in PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
__inout PCOINSTALLER_CONTEXT_DATA Context
)
{ MessageBox(NULL, L"OK", L"Test", MB_OK);
switch (InstallFunction)
{
case DIF_UNREMOVE:
break;
case DIF_SELECTBESTCOMPATDRV:
MessageBox(NULL, L"DIF_SELECTBESTCOMPATDRV", L"Test", MB_OK);
if (DeviceInfoData)
{
SP_DRVINFO_DATA sDrvInfoData;
DWORD MemberIndex = 0;
memset((void*)&sDrvInfoData, 0, sizeof(SP_DRVINFO_DATA));
sDrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
if(SetupDiEnumDriverInfo(DeviceInfoSet, DeviceInfoData, SPDIT_COMPATDRIVER, MemberIndex++, &sDrvInfoData))
{
SP_DRVINSTALL_PARAMS sDrvInstallParams;
memset((void*)&sDrvInstallParams, 0, sizeof(SP_DRVINSTALL_PARAMS));
sDrvInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
OutputDebugString(sDrvInfoData.Description);
if(!SetupDiGetDriverInstallParams(DeviceInfoSet, DeviceInfoData, &sDrvInfoData, &sDrvInstallParams))
{
MessageBox(NULL, L"SetupDiGetDriverInstallParams error", L"Test", MB_OK);
}
else
{
MessageBox(NULL, L"SetupDiGetDriverInstallParams ok", L"Test", MB_OK);
}
sDrvInstallParams.Rank = 0;
if(!SetupDiSetDriverInstallParams(DeviceInfoSet, DeviceInfoData, &sDrvInfoData, &sDrvInstallParams))
{
MessageBox(NULL, L"SetupDiSetDriverInstallParams error", L"Test", MB_OK);
}
else
{
MessageBox(NULL, L"SetupDiSetDriverInstallParams OK", L"Test", MB_OK);
}
}
else
{
if(GetLastError() == ERROR_INVALID_USER_BUFFER)
MessageBox(NULL, L"SetupDiEnumDriverInfo error11", L"Test", MB_OK);
MessageBox(NULL, L"SetupDiEnumDriverInfo error", L"Test", MB_OK);
}
}
else
{
MessageBox(NULL, L"DeviceInfoData error", L"Test", MB_OK);
}
break;
}
return NO_ERROR;
}
2. 函数实现dll的注册
dll的注册我是写函数实现的,DDK里面说是修改inf文件实现但是我改了以后没成功,所以才自己写函数实现的。
1)写注册表
WriteReg();
2)拷贝dll文件到系统目录
bool flag = CopyFile(strRoot+L"\\NACoinstaller.dll", "C:\\WINDOWS\\system32\\NACoinstaller.dll", FALSE);
void WriteReg(void) { HKEY hReg; char szName[MAX_PATH]; strcpy(szName, "{25DBCE51-6C8F-4A72-8A6D-B54C2B4FC835}"); char szData[MAX_PATH]; // strcpy(szData, "NACoinstall.dll, NACoInstallEntryPoint"); strcpy(szData, "NACoinstaller.dll, NACoInstallEntryPoint"); DWORD dw;//-1表示创建失败 0表示创建成功 dw = RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",0,KEY_WRITE,&hReg); if(dw != ERROR_SUCCESS) { AfxMessageBox("RegOpenKeyExA失败"); } dw = RegSetValueEx(hReg, szName, 0, REG_MULTI_SZ, (LPBYTE)szData, strlen(szData)); if(dw != ERROR_SUCCESS) { AfxMessageBox("RegSetValueEx失败"); } RegCloseKey(hReg); }
3. 然后预安装
原装设备是调用SetupCopyOEMInf实现的。代码如下:
其中
szInfFile表示inf文件的全路径,asDesName是成功后生产的oemx.inf文件名
if(FALSE == SetupCopyOEMInf( szInfFile, NULL, // 和SPOST_PATH一起使用时设为NULL,表示和inf文件同目录即c:/tmp SPOST_PATH, SP_COPY_NOOVERWRITE, (PSTR)asDesPath, MAX_PATH, NULL, (PSTR *)&asDesName)) { if(GetLastError() == ERROR_FILE_EXISTS) { nResult = 1; // 已安装 AfxMessageBox("已安装"); } else { nResult = -1; // 失败 AfxMessageBox("失败"); } } else { nResult = 0; // 成功 AfxMessageBox("成功"); } CString str; str.Format("%s", asDesName); m_oemName.SetWindowTextA(str);
4. 插入设备测试
经过以上3步,写dll, 注册dll, 预安装,插入设备,依次弹出下列对话框,说明rank值已经被修改了
但是接下来又弹出,提示“句柄无效”
点击完成以后,弹出
安装失败!!!!
如果不注册dll,直接预安装后插入设备。依次弹出下列对话框:
本来直接预安装以后点击下一步可以成功安装的,估计是我测试太多次了,某些地方没卸载干净导致了这个错误。不知道如何才能把系统恢复干净。