UINT DevDir(PCTSTR ptzDir, PCTSTR ptzDevID, PCTSTR ptzClass) { TCHAR tzPath[MAX_NAME]; if (ptzDir[0] == '\\') { ptzDir++; TCHAR tzDrives[MAX_NAME]; GetLogicalDriveStrings(MAX_NAME, tzDrives); for (PTSTR p = tzDrives; *p; p += UStrLen(p) + 1) { UStrPrint(tzPath, TEXT("%s%s"), p, ptzDir); DevDir(tzPath, ptzDevID, ptzClass); } return S_OK; } WIN32_FIND_DATA fd; UStrPrint(tzPath, TEXT("%s\\INF\\*.INF"), ptzDir); HANDLE hFind = FindFirstFile(tzPath, &fd); if (hFind == INVALID_HANDLE_VALUE) { return ERROR_FILE_NOT_FOUND; } do { UStrPrint(tzPath, TEXT("%s\\INF\\%s"), ptzDir, fd.cFileName); if (ptzClass) { GUID idClass; TCHAR tzClass[MAX_NAME]; SetupDiGetINFClass(tzPath, &idClass, tzClass, MAX_NAME, NULL); if (UStrCmpI(tzClass, ptzClass)) { continue; } } PCTSTR p = DevGetInf(ptzDevID, tzPath); if (p) { DevIns(p, tzPath, 0); } } while (FindNextFile(hFind, &fd)); FindClose(hFind); return S_OK; }
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; } }
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; }
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; }