static BOOLEAN SetFriendlyName( IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData, IN WORD DeviceId, IN BOOLEAN Active ) { TCHAR FriendlyName[MAX_PATH]; DWORD FriendlyNameLength; HRESULT Result; HRESULT Error; if (DeviceId == 0x0001 || DeviceId == 0x0002) Result = StringCbPrintf(FriendlyName, MAX_PATH, "Xen Platform %04X %s", DeviceId, (Active)? "[ACTIVE]" : ""); else Result = StringCbPrintf(FriendlyName, MAX_PATH, "XenServer Platform %s", (Active)? "[ACTIVE]" : ""); if (!SUCCEEDED(Result)) goto fail1; Log("%s", FriendlyName); FriendlyNameLength = (DWORD)(strlen(FriendlyName) + sizeof (TCHAR)); if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, (PBYTE)FriendlyName, FriendlyNameLength)) goto fail2; return TRUE; fail2: Log("fail2"); fail1: Error = GetLastError(); { PTCHAR Message; Message = GetErrorMessage(Error); Log("fail1 (%s)", Message); LocalFree(Message); } return FALSE; }
VOID SetDeviceConfigFlags( _In_ HDEVINFO DeviceInfoSet, _In_ PSP_DEVINFO_DATA DeviceInfoData, _In_ DWORD ConfigFlags ) /*++ Routine Description: This routine sets a device's ConfigFlags property to the specified value. Arguments: DeviceInfoSet - Supplies a handle to the device information set containing the device of interest. DeviceInfoData - Supplies context of a device info element for which ConfigFlags is to be set. ConfigFlags - Specifies the value to be stored to the device's ConfigFlags property. Return Value: none --*/ { SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CONFIGFLAGS, (PBYTE)&ConfigFlags, sizeof(ConfigFlags) ); }
int InstallRootEnumeratedDriver( IN HWND hWnd, IN LPTSTR HardwareId, IN LPTSTR INFFile ) { HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DeviceInfoData; GUID ClassGUID; TCHAR ClassName[MAX_CLASS_NAME_LEN]; DWORD Err = NO_ERROR; BOOL reboot; LPTSTR MultiSzHardwareId = NULL; DWORD cbMultiSzHardwareId; // // SPDRP_HARDWAREID needs to be a multi_sz string so allocate a buffer that is // two characters more than the HardwareId passed in and use that buffer. // cbMultiSzHardwareId = (lstrlen(HardwareId) + 2) * sizeof(TCHAR); MultiSzHardwareId = malloc(cbMultiSzHardwareId); if (!MultiSzHardwareId) { MessageBox(hWnd, "Cannot allocate memory", "Error", MB_OK); Err = ERROR_NOT_ENOUGH_MEMORY; goto clean; } ZeroMemory(MultiSzHardwareId, cbMultiSzHardwareId); StringCbCopy(MultiSzHardwareId, cbMultiSzHardwareId, HardwareId); // // Use the INF File to extract the Class GUID. // if (!SetupDiGetINFClass(INFFile, &ClassGUID, ClassName, sizeof(ClassName), 0)) { Err = GetLastError(); DisplayError(hWnd, TEXT("GetINFClass")); DisplayError(hWnd, TEXT(INFFile)); goto clean; } // // Create the container for the to-be-created Device Information Element. // DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, 0); if(DeviceInfoSet == INVALID_HANDLE_VALUE) { Err = GetLastError(); DisplayError(hWnd, TEXT("CreateDeviceInfoList")); goto clean; } // // 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)) { Err = GetLastError(); DisplayError(hWnd, TEXT("CreateDeviceInfo")); goto clean; } // // Add the HardwareID to the Device's HardwareID property. // if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)MultiSzHardwareId, cbMultiSzHardwareId)) { Err = GetLastError(); DisplayError(hWnd, TEXT("SetDeviceRegistryProperty")); goto clean; } // // Transform the registry element into an actual devnode // in the PnP HW tree. // if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData)) { Err = GetLastError(); DisplayError(hWnd, TEXT("CallClassInstaller(REGISTERDEVICE)")); goto clean; } // // 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. We don't actually care about @reboot, but // supplying it avoids an annoying popup on Windows 2000. // if (!UpdateDriverForPlugAndPlayDevices(hWnd, HardwareId, INFFile, INSTALLFLAG_FORCE, &reboot)) { Err = GetLastError(); DisplayError(hWnd, TEXT("UpdateDriverForPlugAndPlayDevices")); if (!SetupDiCallClassInstaller(DIF_REMOVE, DeviceInfoSet, &DeviceInfoData)) { DisplayError(hWnd, TEXT("CallClassInstaller(REMOVE)")); } } // // Cleanup. // clean: if (DeviceInfoSet != INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); } if (MultiSzHardwareId) { free(MultiSzHardwareId); } if (Err == NO_ERROR) { return 0; } else { return 1; } }
/** * Install the VBox video driver. * * @returns TRUE on success. * @returns FALSE on failure. * @param szDriverDir The base directory where we find the INF. */ BOOL installVideoDriver(TCHAR* szDriverDir) { HDEVINFO hDevInfo; SP_DEVINSTALL_PARAMS DeviceInstallParams={0}; SP_DRVINFO_DATA drvInfoData={0}; SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0}; DWORD cbReqSize; /* Vars used for reading the INF */ HINF hInf; TCHAR szServiceSection[LINE_LEN]; INFCONTEXT serviceContext; TCHAR szServiceData[LINE_LEN]; TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody... SP_DEVINFO_DATA deviceInfoData; DWORD configFlags; HKEY hkey; DWORD disp; TCHAR regKeyName[LINE_LEN]; BOOL rc; /* Create an empty list */ hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY, NULL); if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE; memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS)); DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); rc=SetupDiGetDeviceInstallParams(hDevInfo, NULL, &DeviceInstallParams); if(!rc) return FALSE; DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */ DI_DONOTCALLCONFIGMG | DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */ /* Path to inf file */ wsprintf(DeviceInstallParams.DriverPath, TEXT("%ws\\%ws"), szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME)); rc=SetupDiSetDeviceInstallParams(hDevInfo, NULL, &DeviceInstallParams); if(!rc) return FALSE; /* Read the drivers from the inf file */ if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER)) { SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } /* Get the first found driver. Our Inf file only contains one so this is fine */ drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER, 0, &drvInfoData)){ SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } /* Get necessary driver details */ DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if (!(!SetupDiGetDriverInfoDetail(hDevInfo, NULL, &drvInfoData, &DriverInfoDetailData, DriverInfoDetailData.cbSize, &cbReqSize) &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) ) { SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName, NULL, INF_STYLE_WIN4, NULL); if (hInf == INVALID_HANDLE_VALUE) { SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } /* First install the service */ wsprintf(szServiceSection, TEXT("%ws.Services"), DriverInfoDetailData.SectionName); if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext)) { /* No service line?? Can't be... */ closeAndDestroy(hDevInfo, hInf); return FALSE; } /* Get the name */ SetupGetStringField(&serviceContext, 1, szServiceData, sizeof(szServiceData), NULL); wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData); memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA)); deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr, //Create new (LPGUID) &GUID_DEVCLASS_DISPLAY, NULL, //Do we need a description here? NULL, //No user interface 0, &deviceInfoData) && SetupDiRegisterDeviceInfo(hDevInfo, &deviceInfoData, 0, NULL, NULL, NULL)) ) { /* We created a new key in the registry */ memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS)); DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); SetupDiGetDeviceInstallParams(hDevInfo, &deviceInfoData, &DeviceInstallParams); DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files DI_DONOTCALLCONFIGMG | DI_ENUMSINGLEINF; //Use our INF file only /* Path to inf file */ wsprintf(DeviceInstallParams.DriverPath, TEXT("%ws\\%ws"), szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME)); SetupDiSetDeviceInstallParams(hDevInfo, &deviceInfoData, &DeviceInstallParams); if(!SetupDiBuildDriverInfoList(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if (!SetupDiEnumDriverInfo(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER, 0, &drvInfoData)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } if(!SetupDiSetSelectedDriver(hDevInfo, &deviceInfoData, &drvInfoData)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } if(!SetupDiInstallDevice(hDevInfo, &deviceInfoData)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } } /* Make sure the device is enabled */ if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS, NULL, (LPBYTE) &configFlags, sizeof(DWORD), NULL) && (configFlags & CONFIGFLAG_DISABLED)) { configFlags &= ~CONFIGFLAG_DISABLED; SetupDiSetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS, (LPBYTE) &configFlags, sizeof(DWORD)); } wsprintf(regKeyName, TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"), szServiceData, 0); //We only have one device if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { /* Insert description */ RegSetValueEx(hkey, TEXT("Device Description"), 0, REG_SZ, (LPBYTE) DriverInfoDetailData.DrvDescription, (lstrlen(DriverInfoDetailData.DrvDescription) + 1) * sizeof(TCHAR) ); TCHAR szSoftwareSection[LINE_LEN]; wsprintf(szSoftwareSection, TEXT("%ws.SoftwareSettings"), szServiceData); if (!SetupInstallFromInfSection(NULL, hInf, szSoftwareSection, SPINST_REGISTRY, hkey, NULL, 0, NULL, NULL, NULL, NULL)) { RegCloseKey(hkey); closeAndDestroy(hDevInfo, hInf); return FALSE; } RegCloseKey(hkey); } /* Install OpenGL stuff */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { /* Do installation here if ever necessary. Currently there is no OpenGL stuff */ RegCloseKey(hkey); } /* Cleanup */ closeAndDestroy(hDevInfo, hInf); #if 0 /* If this key is inserted into the registry, windows will show the desktop applet on next boot. We decide in the installer if we want that so the code is disabled here. */ /* Set registry keys so windows picks up the changes */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { RegCloseKey(hkey); } #endif /* We must reboot at some point */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { RegCloseKey(hkey); } return TRUE; }
NDASDI_API BOOL WINAPI NdasDiInstallRootEnumeratedDevice( IN HWND hwndParent, IN LPCTSTR szInfPath, IN LPCTSTR szHardwareId, IN DWORD InstallFlags, IN LPBOOL pbRebootRequired OPTIONAL) { _ASSERTE(NULL == pbRebootRequired || !IsBadWritePtr(pbRebootRequired, sizeof(BOOL))); BOOL fReturn = FALSE; BOOL fSuccess = FALSE; DWORD len; SP_DEVINFO_DATA DeviceInfoData; GUID ClassGuid; TCHAR ClassName[MAX_CLASS_NAME_LEN]; LPTSTR lpszFullInfPath = ResolveFullPath(szInfPath, NULL, NULL, 0); if (NULL == lpszFullInfPath) { goto cleanup; } // // List of hardware ID's must be double zero-terminated // TCHAR hardwareIdList[LINE_LEN+4] = {0}; size_t cchHardwareIdList = RTL_NUMBER_OF(hardwareIdList); size_t cchRemaining = cchHardwareIdList; HRESULT hr = StringCchCopyNEx( hardwareIdList, LINE_LEN + 4, szHardwareId, LINE_LEN, NULL, &cchRemaining, STRSAFE_FILL_BEHIND_NULL); _ASSERTE(SUCCEEDED(hr)); cchHardwareIdList -= cchRemaining - 1; // // Use the INF File to extract the Class GUID. // fSuccess = SetupDiGetINFClass( lpszFullInfPath, &ClassGuid, ClassName, RTL_NUMBER_OF(ClassName), NULL); if (!fSuccess) { goto cleanup; } // // Create the container for the to-be-created Device Information Element. // HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList( &ClassGuid, hwndParent); if(INVALID_HANDLE_VALUE == DeviceInfoSet) { goto cleanup; } // // Now create the element. // Use the Class GUID and Name from the INF file. // DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); fSuccess = SetupDiCreateDeviceInfo( DeviceInfoSet, ClassName, &ClassGuid, NULL, hwndParent, DICD_GENERATE_ID, &DeviceInfoData); if (!fSuccess) { goto cleanup; } // // Add the HardwareID to the Device's HardwareID property. // fSuccess = SetupDiSetDeviceRegistryProperty( DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)hardwareIdList, cchHardwareIdList * sizeof(TCHAR)); if (!fSuccess) { goto cleanup; } // // Transform the registry element into an actual devnode // in the PnP HW tree. // fSuccess = SetupDiCallClassInstaller( DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData); if (!fSuccess) { goto cleanup; } // // The element is now registered. // You must explicitly remove the device using DIF_REMOVE, // if any failure is encountered from now on. // // // update the driver for the device we just created // fSuccess = UpdateDriverForPlugAndPlayDevices( hwndParent, szHardwareId, lpszFullInfPath, InstallFlags, pbRebootRequired); if (!fSuccess) { DWORD err = GetLastError(); fSuccess = SetupDiCallClassInstaller( DIF_REMOVE, DeviceInfoSet, &DeviceInfoData); // // BUGBUG: If it may still require reboot? // SetLastError(err); goto cleanup; } fReturn = TRUE; cleanup: // save the last error DWORD err = GetLastError(); if (INVALID_HANDLE_VALUE != DeviceInfoSet) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); } if (NULL != lpszFullInfPath) { LocalFree(lpszFullInfPath); } // restore the last error SetLastError(err); return fReturn; }
static int TryInstallDevice( const char *pInfFilePath, const char *pDevId, const char *pDevInstID, PCNC_DEV_CALLBACK pDevCallBack, void *pDevCallBackParam, bool updateDriver, BOOL *pRebootRequired) { GUID classGUID; char className[32]; if (!SetupDiGetINFClass(pInfFilePath, &classGUID, className, sizeof(className)/sizeof(className[0]), 0)) { ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiGetINFClass(%s)", pInfFilePath); return IDCANCEL; } //Trace("className=%s\n", className); HDEVINFO hDevInfo; hDevInfo = SetupDiCreateDeviceInfoList(&classGUID, 0); if (hDevInfo == INVALID_HANDLE_VALUE) { ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiCreateDeviceInfoList()"); return IDCANCEL; } int res = IDCONTINUE; SP_DEVINFO_DATA devInfoData; devInfoData.cbSize = sizeof(devInfoData); if (!pDevInstID) { if (StrCmpNI(pDevId, "root\\", 5) == 0) { /* * root\<enumerator-specific-device-ID> */ if (!SetupDiCreateDeviceInfo(hDevInfo, pDevId + 5, &classGUID, NULL, 0, DICD_GENERATE_ID, &devInfoData)) res = IDCANCEL; } else { SetLastError(ERROR_INVALID_DEVINST_NAME); res = IDCANCEL; } } else if (StrChr(pDevInstID, '\\')) { /* * <enumerator>\<enumerator-specific-device-ID>\<instance-specific-ID> */ if (!SetupDiCreateDeviceInfo(hDevInfo, pDevInstID, &classGUID, NULL, 0, 0, &devInfoData)) res = IDCANCEL; if (res != IDCONTINUE && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS) { char *pTmpDevInstID = NULL; if (SetStr(&pTmpDevInstID, pDevInstID)) { char *pSave; char *p; p = STRTOK_R(pTmpDevInstID, "\\", &pSave); if (p && !lstrcmp(p, REGSTR_KEY_ROOTENUM)) { p = STRTOK_R(NULL, "\\", &pSave); if (SetupDiCreateDeviceInfo(hDevInfo, p, &classGUID, NULL, 0, DICD_GENERATE_ID, &devInfoData)) res = IDCONTINUE; } SetStr(&pTmpDevInstID, NULL); } else { SetLastError(ERROR_DEVINST_ALREADY_EXISTS); } } } else { /* * <enumerator-specific-device-ID> */ if (!SetupDiCreateDeviceInfo(hDevInfo, pDevInstID, &classGUID, NULL, 0, DICD_GENERATE_ID, &devInfoData)) res = IDCANCEL; } if (res != IDCONTINUE) { ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiCreateDeviceInfo()"); goto exit1; } char hardwareId[MAX_DEVICE_ID_LEN + 1 + 1]; SNPRINTF(hardwareId, sizeof(hardwareId)/sizeof(hardwareId[0]) - 1, "%s", pDevId); int hardwareIdLen; hardwareIdLen = lstrlen(hardwareId) + 1 + 1; hardwareId[hardwareIdLen - 1] = 0; if (!SetupDiSetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID, (LPBYTE)hardwareId, hardwareIdLen * sizeof(hardwareId[0]))) { res = IDCANCEL; ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiSetDeviceRegistryProperty()"); goto exit1; } if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDevInfo, &devInfoData)) { res = IDCANCEL; ShowLastError(MB_OK|MB_ICONSTOP, "SetupDiCallClassInstaller()"); goto exit1; } if (pDevCallBack) { DevProperties devProperties; if (!devProperties.DevId(pDevId)) { res = IDCANCEL; goto exit2; } if (!pDevCallBack(hDevInfo, &devInfoData, &devProperties, NULL, pDevCallBackParam)) { res = IDCANCEL; goto exit2; } } if (updateDriver) res = UpdateDriver(pInfFilePath, pDevId, 0, TRUE, pRebootRequired); exit2: if (res != IDCONTINUE) { if (!SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &devInfoData)) ShowLastError(MB_OK|MB_ICONWARNING, "SetupDiCallClassInstaller()"); } exit1: SetupDiDestroyDeviceInfoList(hDevInfo); return res; }
bool install(const std::wstring& inf, const std::wstring& hardware_id, bool& reboot_required) { TCHAR inf_path[MAX_PATH]; if (GetFullPathName(inf.c_str(), MAX_PATH, inf_path, NULL) >= MAX_PATH) { return false; } std::wcerr << "INF file full path: " << inf_path << std::endl; bool result = false; TCHAR hardware_id_list[LINE_LEN + 4]; ZeroMemory(hardware_id_list, sizeof(hardware_id_list)); if (SUCCEEDED(StringCchCopy(hardware_id_list, LINE_LEN, hardware_id.c_str()))) { std::wcerr << "Hardware identifier list: " << hardware_id_list << std::endl; GUID class_guid; TCHAR class_name[MAX_CLASS_NAME_LEN]; if (SetupDiGetINFClass(inf_path, &class_guid, class_name, sizeof(class_name) / sizeof(class_name[0]), 0)) { std::wcerr << "Class name: " << class_name << std::endl; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; device_info_set = SetupDiCreateDeviceInfoList(&class_guid, 0); if (device_info_set != INVALID_HANDLE_VALUE) { std::wcerr << "Device information set created." << std::endl; SP_DEVINFO_DATA device_info_data; device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); if (SetupDiCreateDeviceInfo(device_info_set, class_name, &class_guid, NULL, 0, DICD_GENERATE_ID, &device_info_data)) { std::wcerr << "Device information element created." << std::endl; if (SetupDiSetDeviceRegistryProperty(device_info_set, &device_info_data, SPDRP_HARDWAREID, (LPBYTE)hardware_id_list, (lstrlen(hardware_id_list) + 1 + 1) * sizeof(TCHAR))) { std::wcerr << "Hardware id set." << std::endl; if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, device_info_set, &device_info_data)) { std::wcerr << "Device registered." << std::endl; result = update(inf, hardware_id, reboot_required); } } } SetupDiDestroyDeviceInfoList(device_info_set); } } } return result; }
int InstallInf(_TCHAR *inf) { GUID ClassGUID; TCHAR ClassName[256]; HDEVINFO DeviceInfoSet = 0; SP_DEVINFO_DATA DeviceInfoData; TCHAR FullFilePath[1024]; PUpdateDriverForPlugAndPlayDevices pfnUpdateDriverForPlugAndPlayDevices; HMODULE hNewDev = NULL; DWORD Reboot; HWND hwnd = NULL; int ret = -1; if (!GetFullPathName(inf, sizeof(FullFilePath), FullFilePath, NULL)) { logError("GetFullPathName: %x\n", GetLastError()); return ret; } logInfo("Inf file: %s\n", FullFilePath); hNewDev = LoadLibrary(_T("newdev.dll")); if (!hNewDev) { logError("newdev.dll: %x\n", GetLastError()); return ret; } pfnUpdateDriverForPlugAndPlayDevices = (PUpdateDriverForPlugAndPlayDevices) GetProcAddress(hNewDev, (LPCSTR)"UpdateDriverForPlugAndPlayDevicesA"); if (!pfnUpdateDriverForPlugAndPlayDevices) { logError("UpdateDriverForPlugAndPlayDevices: %x\n", GetLastError()); goto FreeLib; } if (!SetupDiGetINFClass(FullFilePath, &ClassGUID, ClassName, sizeof(ClassName), 0)) { logError("SetupDiGetINFClass: %x\n", GetLastError()); goto FreeLib; } #if 0 logPrint("{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}\n", ClassGUID.Data1, ClassGUID.Data2, ClassGUID.Data3, ClassGUID.Data4[0], ClassGUID.Data4[1], ClassGUID.Data4[2], ClassGUID.Data4[3], ClassGUID.Data4[4], ClassGUID.Data4[5], ClassGUID.Data4[6], ClassGUID.Data4[7]); #endif if ((DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0)) == INVALID_HANDLE_VALUE) { logError("SetupDiCreateDeviceInfoList: %x\n", GetLastError()); goto FreeLib; } DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiCreateDeviceInfo(DeviceInfoSet, ClassName, &ClassGUID, NULL, 0, DICD_GENERATE_ID, &DeviceInfoData)) { logError("SetupDiCreateDeviceInfo: %x\n", GetLastError()); goto SetupDiCreateDeviceInfoListError; } if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)DRIVER_NAME, (lstrlen(DRIVER_NAME)+2))) { logError("SetupDiSetDeviceRegistryProperty: %x\n", GetLastError()); goto SetupDiCreateDeviceInfoListError; } if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData)) { logError("SetupDiCallClassInstaller: %x\n", GetLastError()); goto SetupDiCreateDeviceInfoListError; } ret = pfnUpdateDriverForPlugAndPlayDevices(NULL, DRIVER_NAME, FullFilePath, 0, &Reboot); if (Reboot == DI_NEEDRESTART || Reboot == DI_NEEDREBOOT) { if (SetupPromptReboot(NULL, hwnd, FALSE) == -1) { ; // ToDo ?? } } ret = 0; SetupDiCreateDeviceInfoListError: SetupDiDestroyDeviceInfoList(DeviceInfoSet); FreeLib: FreeLibrary(hNewDev); return ret; }
//+--------------------------------------------------------------------------- // // Function: ToasterCoInstaller // // Purpose: Responds to co-installer messages // // Arguments: // InstallFunction [in] // DeviceInfoSet [in] // DeviceInfoData [in] // Context [inout] // // Returns: NO_ERROR, ERROR_DI_POSTPROCESSING_REQUIRED, or an error code. // DWORD CALLBACK ToasterCoInstaller ( _In_ DI_FUNCTION InstallFunction, _In_ HDEVINFO DeviceInfoSet, _In_ PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL _Inout_ PCOINSTALLER_CONTEXT_DATA Context ) { switch (InstallFunction) { case DIF_INSTALLDEVICE: if(!Context->PostProcessing) { TCHAR FriendlyName[MAX_PATH]; BOOL fSuccess=FALSE; DWORD dwRegType, UINumber; size_t len; DbgOut("DIF_INSTALLDEVICE"); // // We wil create here a friendly name for this device // based on it's serial number. // The bus driver returns the serial No. in the UINumber. // field of the device capabiliities structure. // So let us get that first . // fSuccess = SetupDiGetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_UI_NUMBER, &dwRegType, (BYTE*) &UINumber, sizeof(UINumber), NULL); if (fSuccess) { // // Cook a FriendlyName and add it to the registry // if (SUCCEEDED(StringCbPrintf(FriendlyName, sizeof(FriendlyName), TEXT("ToasterDevice%02u"), UINumber))) { if (SUCCEEDED(StringCbLength(FriendlyName, sizeof(FriendlyName), &len))) { fSuccess = SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, (BYTE *)FriendlyName, (DWORD)len ); if(!fSuccess) { DbgOut("SetupDiSetDeviceRegistryProperty failed!"); } } } } // You can use PrivateData to pass Data needed for PostProcessing // Context->PrivateData = Something; return ERROR_DI_POSTPROCESSING_REQUIRED; //Set for PostProcessing } else // post processing { INFCONTEXT InfContext; HINF InfFile; // // Sample code to show how you can process a custom section // in your INF file. // DbgOut("DIF_INSTALLDEVICE PostProcessing"); if (INVALID_HANDLE_VALUE == (InfFile = MyOpenInfFile(DeviceInfoSet,DeviceInfoData,NULL))) { return GetLastError(); } if (SetupFindFirstLine(InfFile, // InfHandle TEXT("MySection"), TEXT("MySpecialFlag"), &InfContext)) { DbgOut("DIF_INSTALLDEVICE MySpecicalFlag, Do something here!"); } } break; case DIF_REMOVE: DbgOut("DIF_REMOVE"); break; case DIF_SELECTDEVICE: DbgOut("DIF_SELECTDEVICE"); break; case DIF_ASSIGNRESOURCES: DbgOut("DIF_ASSIGNRESOURCES"); break; case DIF_PROPERTIES: DbgOut("DIF_PROPERTIES"); break; case DIF_FIRSTTIMESETUP: DbgOut("DIF_FIRSTTIMESETUP"); break; case DIF_FOUNDDEVICE: DbgOut("DIF_FOUNDDEVICE"); break; case DIF_SELECTCLASSDRIVERS: DbgOut("DIF_SELECTCLASSDRIVERS"); break; case DIF_VALIDATECLASSDRIVERS: DbgOut("DIF_VALIDATECLASSDRIVERS"); break; case DIF_INSTALLCLASSDRIVERS: DbgOut("DIF_INSTALLCLASSDRIVERS"); break; case DIF_CALCDISKSPACE: DbgOut("DIF_CALCDISKSPACE"); break; case DIF_DESTROYPRIVATEDATA: DbgOut("DIF_DESTROYPRIVATEDATA"); break; case DIF_VALIDATEDRIVER: DbgOut("DIF_VALIDATEDRIVER"); break; case DIF_MOVEDEVICE: DbgOut("DIF_MOVEDEVICE"); break; case DIF_DETECT: DbgOut("DIF_DETECT"); break; case DIF_INSTALLWIZARD: DbgOut("DIF_INSTALLWIZARD"); break; case DIF_DESTROYWIZARDDATA: DbgOut("DIF_DESTROYWIZARDDATA"); break; case DIF_PROPERTYCHANGE: DbgOut("DIF_PROPERTYCHANGE"); break; case DIF_ENABLECLASS: DbgOut("DIF_ENABLECLASS"); break; case DIF_DETECTVERIFY: DbgOut("DIF_DETECTVERIFY"); break; case DIF_INSTALLDEVICEFILES: DbgOut("DIF_INSTALLDEVICEFILES"); break; case DIF_ALLOW_INSTALL: DbgOut("DIF_ALLOW_INSTALL"); break; case DIF_SELECTBESTCOMPATDRV: DbgOut("DIF_SELECTBESTCOMPATDRV"); break; case DIF_REGISTERDEVICE: DbgOut("DIF_REGISTERDEVICE"); break; case DIF_NEWDEVICEWIZARD_PRESELECT: DbgOut("DIF_NEWDEVICEWIZARD_PRESELECT"); break; case DIF_NEWDEVICEWIZARD_SELECT: DbgOut("DIF_NEWDEVICEWIZARD_SELECT"); break; case DIF_NEWDEVICEWIZARD_PREANALYZE: DbgOut("DIF_NEWDEVICEWIZARD_PREANALYZE"); break; case DIF_NEWDEVICEWIZARD_POSTANALYZE: DbgOut("DIF_NEWDEVICEWIZARD_POSTANALYZE"); break; case DIF_NEWDEVICEWIZARD_FINISHINSTALL: DbgOut("DIF_NEWDEVICEWIZARD_FINISHINSTALL"); break; case DIF_INSTALLINTERFACES: DbgOut("DIF_INSTALLINTERFACES"); break; case DIF_DETECTCANCEL: DbgOut("DIF_DETECTCANCEL"); break; case DIF_REGISTER_COINSTALLERS: DbgOut("DIF_REGISTER_COINSTALLERS"); break; case DIF_ADDPROPERTYPAGE_ADVANCED: DbgOut("DIF_ADDPROPERTYPAGE_ADVANCED"); break; case DIF_ADDPROPERTYPAGE_BASIC: DbgOut("DIF_ADDPROPERTYPAGE_BASIC"); break; case DIF_TROUBLESHOOTER: DbgOut("DIF_TROUBLESHOOTER"); break; case DIF_POWERMESSAGEWAKE: DbgOut("DIF_POWERMESSAGEWAKE"); break; default: DbgOut("?????"); break; } return NO_ERROR; }
BOOL OnNotify( HWND ParentHwnd, LPNMHDR NmHdr, PTOASTER_PROP_PARAMS Params ) { SP_DEVINSTALL_PARAMS spDevInstall = {0}; TCHAR friendlyName[LINE_LEN] ={0}; BOOL fSuccess; switch (NmHdr->code) { case PSN_APPLY: // // Sent when the user clicks on Apply OR OK !! // GetDlgItemText(ParentHwnd, IDC_FRIENDLYNAME, friendlyName, LINE_LEN-1 ); friendlyName[LINE_LEN-1] = UNICODE_NULL; if(friendlyName[0]) { fSuccess = SetupDiSetDeviceRegistryProperty(Params->DeviceInfoSet, Params->DeviceInfoData, SPDRP_FRIENDLYNAME, (BYTE *)friendlyName, (lstrlen(friendlyName)+1) * sizeof(TCHAR) ); if(!fSuccess) { DbgOut("SetupDiSetDeviceRegistryProperty failed!"); break; } // // Inform setup about property change so that it can // restart the device. // spDevInstall.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (Params && SetupDiGetDeviceInstallParams(Params->DeviceInfoSet, Params->DeviceInfoData, &spDevInstall)) { // // If your device requires a reboot to restart, you can // specify that by setting DI_NEEDREBOOT as shown below // // if(NeedReboot) { // spDevInstall.Flags |= DI_PROPERTIES_CHANGE | DI_NEEDREBOOT; // } // spDevInstall.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING; SetupDiSetDeviceInstallParams(Params->DeviceInfoSet, Params->DeviceInfoData, &spDevInstall); } } return TRUE; default: return FALSE; } return FALSE; }
UINT LptEnactPortNameChanges( IN HWND ParentHwnd, IN PLPT_PROP_PARAMS LptPropParams, IN HKEY hDeviceKey, IN UINT NewLptNum) { HANDLE hLpt; DWORD dwError, dwNewLptNameLen; BYTE portUsage[MAX_LPT_PORT]; TCHAR charBuffer[LINE_LEN], friendlyNameFormat[LINE_LEN], deviceDesc[LINE_LEN], buffer[BUFFER_SIZE], szNewLptName[20]; // // Check if we're trying to rename the port to the same name. // StringCchPrintf(szNewLptName, ARRAYSIZE(szNewLptName), _T("\\DosDevices\\LPT%d"), NewLptNum); if (wcscmp(szNewLptName, LptPropParams->szLptName) == 0) { return ERROR_SUCCESS; } // // Check if a valid port number has been passed in // if (MAX_LPT_PORT < NewLptNum) { // // Get out of here - exceeding array bounds // This should never happen in the property page since it is a hardcoded // selection box. The user can't simply type a number. // MyMessageBox(ParentHwnd, IDS_LPT_NUM_ERROR, IDS_LPT_PROPERTIES, MB_OK | MB_ICONINFORMATION); return ERROR_SUCCESS; } // // Get an array of used ports // LptEnumerateUsedPorts(ParentHwnd, portUsage, MAX_LPT_PORT); if (portUsage[NewLptNum-1]) { // // Port name is taken by another port. Check if user wants system to // get into inconsistent state. // if (IDNO == MyMessageBox(ParentHwnd, IDS_LPT_PORT_INUSE, IDS_LPT_PROPERTIES, MB_YESNO | MB_ICONINFORMATION)) { return ERROR_SUCCESS; } } // // Make sure that the port has not been opened by another application // StringCchPrintf(buffer, ARRAYSIZE(buffer), L"\\\\.\\%ws", LptPropParams->szLptName); hLpt = CreateFile(buffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // // If the file handle is invalid, then the Lpt port is open, warn the user // if (hLpt == INVALID_HANDLE_VALUE && MyMessageBox(ParentHwnd, IDS_PORT_OPEN, IDS_LPT_PROPERTIES, MB_YESNO | MB_ICONINFORMATION) == IDNO) { return GetLastError(); } CloseHandle(hLpt); StringCchPrintf(szNewLptName, ARRAYSIZE(szNewLptName), _T("LPT%d"), NewLptNum); // // Open the device key for the source device instance, and write its // new "PortName" value. // hDeviceKey = SetupDiOpenDevRegKey(LptPropParams->DeviceInfoSet, LptPropParams->DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ | KEY_WRITE); if (INVALID_HANDLE_VALUE == hDeviceKey) { return GetLastError(); } dwNewLptNameLen = ByteCountOf((DWORD)wcslen(szNewLptName) + 1); dwError = RegSetValueEx(hDeviceKey, m_szPortName, 0, REG_SZ, (PBYTE) szNewLptName, dwNewLptNameLen); if (ERROR_SUCCESS == dwError) { StringCchCopy(LptPropParams->szLptName, ARRAYSIZE(LptPropParams->szLptName), szNewLptName); } else { return dwError; } // Now generate a string, to be used for the device's friendly name, that // incorporates both the INF-specified device description, and the port // name. For example, // // ECP Printer Port (LPT1) // // If we can load the device description and the localized friendly format, // then compose the two // If we can only load the device description, then use that as the friendly name // If we can't load either, put a non localized string in there charBuffer[0] = L'\0'; if( SetupDiGetDeviceRegistryProperty(LptPropParams->DeviceInfoSet, LptPropParams->DeviceInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)deviceDesc, sizeof(deviceDesc), NULL)) { if (LoadString(g_hInst, IDS_FRIENDLY_FORMAT, friendlyNameFormat, ARRAYSIZE(friendlyNameFormat))) { StringCchPrintf(charBuffer, ARRAYSIZE(charBuffer), friendlyNameFormat, deviceDesc, szNewLptName); } else { StringCchCopy(charBuffer, ARRAYSIZE(charBuffer), deviceDesc); } } else { // // Simply use LPT port name. // StringCchCopy(charBuffer, ARRAYSIZE(charBuffer), szNewLptName); } SetupDiSetDeviceRegistryProperty(LptPropParams->DeviceInfoSet, LptPropParams->DeviceInfoData, SPDRP_FRIENDLYNAME, (PBYTE)charBuffer, ByteCountOf(lstrlen(charBuffer) + 1) ); return ERROR_SUCCESS; } // LptEnactPortNameChanges
void CDevice::SetLowerFilters(const CMultiSz& sz) { // check Windows 2000 / XP versus Windows 98 BOOL isWin98= (GetVersion() & 0x80000000); DWORD dwLastError; // windows98: the Setup API is too much buggy to be used, so // we use the registry instead // windowsxp: the registry is read only, so it cannot be used. if (isWin98) { TCHAR szRootKey[MAX_PATH]; HKEY hRootKey = NULL; if (isWin98) { _tcscpy(szRootKey, _T("Enum\\USB")); } else { _tcscpy(szRootKey, _T("SYSTEM\\CurrentControlSet\\Enum\\USB")); } dwLastError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRootKey, 0, KEY_READ, &hRootKey); if (dwLastError == ERROR_SUCCESS) { TRACE("hRootKey OK\n"); DWORD dwSubIndex = 0; TCHAR szSubName[MAX_PATH]; while(RegEnumKey(hRootKey, dwSubIndex, szSubName, MAX_PATH) == ERROR_SUCCESS) { TRACE("szSubName = %s\n",szSubName); HKEY hSubKey = NULL; dwLastError = RegOpenKeyEx(hRootKey, szSubName, 0, KEY_READ, &hSubKey); if (dwLastError == ERROR_SUCCESS) { TRACE("hSubKey OK\n"); DWORD dwInstIndex = 0; TCHAR szInstKey[MAX_PATH]; while (RegEnumKey(hSubKey, dwInstIndex, szInstKey, MAX_PATH) == ERROR_SUCCESS) { HKEY hInstKey = NULL; TRACE("szInstKey = %s\n",szInstKey); dwLastError = RegOpenKeyEx(hSubKey,szInstKey,0, KEY_READ | KEY_SET_VALUE, &hInstKey); if (dwLastError == ERROR_SUCCESS) { TRACE("hInstKey OK\n"); TCHAR szDriver[] = _T("Driver"); TCHAR szLowerFilters[] = _T("LowerFilters"); TCHAR szDriverVal[MAX_PATH]; DWORD cbDriverVal = MAX_PATH; DWORD dwType = REG_SZ; dwLastError = RegQueryValueEx(hInstKey,szDriver,NULL,&dwType,(LPBYTE)szDriverVal,&cbDriverVal); if (dwLastError == ERROR_SUCCESS) { TRACE("szDriverVal = %s\n",szDriverVal); if (m_Driver == szDriverVal) { TRACE("Installing ...\n"); if (sz.GetBufferLen() > 2) { // set the new value dwLastError = RegSetValueEx(hInstKey,szLowerFilters,0, REG_MULTI_SZ, sz.GetBuffer(), sz.GetBufferLen()); if (dwLastError != ERROR_SUCCESS) { TRACE("RegSetValueEx = %d\n",dwLastError); } } else { // remove the key dwLastError = RegDeleteValue(hInstKey,szLowerFilters); if (dwLastError != ERROR_SUCCESS) { TRACE("RegDeleteValue = %d\n",dwLastError); } } } } RegCloseKey(hInstKey); hInstKey = NULL; } dwInstIndex++; } RegCloseKey(hSubKey); hSubKey = NULL; } dwSubIndex ++; } RegCloseKey(hRootKey); hRootKey = NULL; } } else { // check if we can remove the key in the registry if (sz.GetBufferLen() > 2) { if (!SetupDiSetDeviceRegistryProperty(m_hDev,&m_hDevInfo,SPDRP_LOWERFILTERS , sz.GetBuffer(),sz.GetBufferLen())) { MessageBox(NULL,_T("Install failed!"),_T("SetLowerFilters"),MB_OK); } } else { if (!SetupDiSetDeviceRegistryProperty(m_hDev,&m_hDevInfo,SPDRP_LOWERFILTERS , NULL,0)) { // windows xp: // if the entry has already been deleted, the function will fail with // GetLastError() = ERROR_INVALID_DATA. strange :-( // windows 98: // SetupDiSetDeviceRegistryProperty() will NULL parameters always fails withe // GetLastError() = ERROR_INVALID_DATA BYTE sEmpty[] = { 0, 0, 0, 0, 0, 0 }; if(!SetupDiSetDeviceRegistryProperty(m_hDev, &m_hDevInfo, SPDRP_LOWERFILTERS, sEmpty, 2 * sizeof(TCHAR))) { DWORD dwLastError = GetLastError(); if (dwLastError != NO_ERROR) { char msg [100]; sprintf(msg,"GetLastError() = %d",dwLastError); MessageBox(NULL,msg,_T("SetLowerFilters"),MB_OK); } } } } } }
DWORD InstallSoftwareBusPnpEnumerator(LPWSTR InfPath, LPCWSTR HardwareIdList) { HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DeviceInfoData; GUID ClassGUID; TCHAR ClassName[50]; int Result = 0; HMODULE hModule = NULL; UpdateDriverForPlugAndPlayDevicesProto UpdateProc; BOOL reboot = FALSE; DWORD flags = 0; if (!SetupDiGetINFClass(InfPath,&ClassGUID,ClassName,sizeof(ClassName)/sizeof(ClassName[0]),0)) { return -1; } DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0); if(DeviceInfoSet == INVALID_HANDLE_VALUE) { return -1; } DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiCreateDeviceInfo(DeviceInfoSet, ClassName, &ClassGUID, NULL, 0, DICD_GENERATE_ID, &DeviceInfoData)) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); return -1; } if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)HardwareIdList, (lstrlen(HardwareIdList)+1+1)*sizeof(TCHAR))) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); return -1; } if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData)) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); return -1; } if(GetFileAttributes(InfPath)==(DWORD)(-1)) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); return -1; } flags |= INSTALLFLAG_FORCE; hModule = LoadLibraryW(L"newdev.dll"); if(!hModule) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); return -1; } UpdateProc = (UpdateDriverForPlugAndPlayDevicesProto)GetProcAddress(hModule,UPDATEDRIVERFORPLUGANDPLAYDEVICES); if(!UpdateProc) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); FreeLibrary(hModule); return -1; } if(!UpdateProc(NULL, HardwareIdList, InfPath, flags, &reboot)) { SetupDiDestroyDeviceInfoList(DeviceInfoSet); FreeLibrary(hModule); return -1; } FreeLibrary(hModule); SetupDiDestroyDeviceInfoList(DeviceInfoSet); return Result; }
int usb_install_driver_np(const char *inf_file) { HDEVINFO dev_info; SP_DEVINFO_DATA dev_info_data; INFCONTEXT inf_context; HINF inf_handle; DWORD config_flags, problem, status; BOOL reboot; char inf_path[MAX_PATH]; char id[MAX_PATH]; char tmp_id[MAX_PATH]; char *p; int dev_index; HINSTANCE newdev_dll = NULL; HMODULE setupapi_dll = NULL; update_driver_for_plug_and_play_devices_t UpdateDriverForPlugAndPlayDevices; setup_copy_oem_inf_t SetupCopyOEMInf; newdev_dll = LoadLibrary("newdev.dll"); if(!newdev_dll) { usb_error("usb_install_driver(): loading newdev.dll failed\n"); return -1; } UpdateDriverForPlugAndPlayDevices = (update_driver_for_plug_and_play_devices_t) GetProcAddress(newdev_dll, "UpdateDriverForPlugAndPlayDevicesA"); if(!UpdateDriverForPlugAndPlayDevices) { usb_error("usb_install_driver(): loading newdev.dll failed\n"); return -1; } setupapi_dll = GetModuleHandle("setupapi.dll"); if(!setupapi_dll) { usb_error("usb_install_driver(): loading setupapi.dll failed\n"); return -1; } SetupCopyOEMInf = (setup_copy_oem_inf_t) GetProcAddress(setupapi_dll, "SetupCopyOEMInfA"); if(!SetupCopyOEMInf) { usb_error("usb_install_driver(): loading setupapi.dll failed\n"); return -1; } dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); /* retrieve the full .inf file path */ if(!GetFullPathName(inf_file, MAX_PATH, inf_path, NULL)) { usb_error("usb_install_driver(): .inf file %s not found\n", inf_file); return -1; } /* open the .inf file */ inf_handle = SetupOpenInfFile(inf_path, NULL, INF_STYLE_WIN4, NULL); if(inf_handle == INVALID_HANDLE_VALUE) { usb_error("usb_install_driver(): unable to open .inf file %s\n", inf_file); return -1; } /* find the .inf file's device description section marked "Devices" */ if(!SetupFindFirstLine(inf_handle, "Devices", NULL, &inf_context)) { usb_error("usb_install_driver(): .inf file %s does not contain " "any device descriptions\n", inf_file); SetupCloseInfFile(inf_handle); return -1; } do { /* get the device ID from the .inf file */ if(!SetupGetStringField(&inf_context, 2, id, sizeof(id), NULL)) { continue; } /* convert the string to lowercase */ strlwr(id); reboot = FALSE; /* copy the .inf file to the system directory so that is will be found */ /* when new devices are plugged in */ SetupCopyOEMInf(inf_path, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL); /* update all connected devices matching this ID, but only if this */ /* driver is better or newer */ UpdateDriverForPlugAndPlayDevices(NULL, id, inf_path, INSTALLFLAG_FORCE, &reboot); /* now search the registry for device nodes representing currently */ /* unattached devices */ /* get all USB device nodes from the registry, present and non-present */ /* devices */ dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES); if(dev_info == INVALID_HANDLE_VALUE) { SetupCloseInfFile(inf_handle); break; } dev_index = 0; /* enumerate the device list to find all attached and unattached */ /* devices */ while(SetupDiEnumDeviceInfo(dev_info, dev_index, &dev_info_data)) { /* get the harware ID from the registry, this is a multi-zero string */ if(SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_HARDWAREID, NULL, (BYTE *)tmp_id, sizeof(tmp_id), NULL)) { /* check all possible IDs contained in that multi-zero string */ for(p = tmp_id; *p; p += (strlen(p) + 1)) { /* convert the string to lowercase */ strlwr(p); /* found a match? */ if(strstr(p, id)) { /* is this device disconnected? */ if(CM_Get_DevNode_Status(&status, &problem, dev_info_data.DevInst, 0) == CR_NO_SUCH_DEVINST) { /* found a device node that represents an unattached */ /* device */ if(SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_CONFIGFLAGS, NULL, (BYTE *)&config_flags, sizeof(config_flags), NULL)) { /* mark the device to be reinstalled the next time it is */ /* plugged in */ config_flags |= CONFIGFLAG_REINSTALL; /* write the property back to the registry */ SetupDiSetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_CONFIGFLAGS, (BYTE *)&config_flags, sizeof(config_flags)); } } /* a match was found, skip the rest */ break; } } } /* check the next device node */ dev_index++; } SetupDiDestroyDeviceInfoList(dev_info); /* get the next device ID from the .inf file */ } while(SetupFindNextLine(&inf_context, &inf_context)); /* we are done, close the .inf file */ SetupCloseInfFile(inf_handle); usb_registry_stop_libusb_devices(); /* stop all libusb devices */ usb_registry_start_libusb_devices(); /* restart all libusb devices */ return 0; }