- Unpack INF files from 7z DriverPacks bundles and scan them for HWIDs
- Put a list of HWIDs and where they came from in a file and add the DeviceInstall app in the folder containing the DriverPacks
- DeviceInstall does the installation work
REQUIREMENTS:
Download the drivers from http://driverpacks.net/driverpacks/latest for the type of Windows install you want.
If you are compiling DeviceInstall from the source, you must have the following files in the script directory:
DeviceAPI.AU3 available at http://www.autoitscript.com/forum/index.php?showtopic=77731&hl=deviceapi&st=0 (I am using Alpha6, latest as of posting)
7z.exe (I am using V4.65.0.0)
7z.dll (I am using V4.65.0.0) (both can be pulled from the 7z installation folder)
dpinst.exe (32 and 64 bit versions) as well as dpinst.xml (I am using V2.1.0.0 available as part of Windows Driver Kit Version 7.1.0 available at http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=36a2630f-5d56-43b5-b996-7633f2ec14ff)
*name the 64 bit build of dpinst as "dpinst64.exe"
If you are compiling INFSniff from the source, you must have the following files in the script directory:
DeviceInstall.exe compiled
7z.exe
7z.dll
Source for INFSniff
#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Run_Tidy=y #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ;~ DriverPacks.net HWID extractor ;~ AKA ;~ INFSniff ;~ Coded by Ian Maxwell (llewxam @ www.driverpacks.net & www.autoitscript.com forums) ;~ AutoIt 3.3.6.1 ;~ Folder recursion routine by weaponx @ www.autoitscript.com forum #include "Array.au3" #include "StaticConstants.au3" Local $foundINF, $HWIDsplit, $HWIDArray[1] $startDir = FileSelectFolder("Select the folder containing the DriverPacks", "") $DP = FileFindFirstFile($startDir & "\*.7z") FileInstall("7z.exe", @TempDir & "\7z.exe", 1) FileInstall("7z.dll", @TempDir & "\7z.dll", 1) FileInstall("DeviceInstall.exe", $startDir & "\DeviceInstall.exe", 1) $showProg = GUICreate("INFSniff - MaxImuM AdVaNtAgE SofTWarE © 2010", 600, 50, @DesktopWidth / 2 - 300, @DesktopHeight / 2 - 100) $showCurrentName = GUICtrlCreateLabel("", 5, 5, 590, 20, $SS_CENTER) $prog = GUICtrlCreateProgress(5, 25, 590, 20) GUISetState(@SW_SHOW, $showProg) Do $file = FileFindNextFile($DP) If @error Then ExitLoop ;create a temp folder for cleanup later $rand = Random(200, 5000, 1) $folder = @TempDir & "\" & $rand $trimLength = StringLen($folder) + 1 GUICtrlSetData($showCurrentName, "Please wait, extracting INFs from " & $startDir & "\" & $file) RunWait(@TempDir & "\7z.exe x " & Chr(34) & $startDir & "\" & $file & Chr(34) & " -o" & Chr(34) & $folder & Chr(34) & " *.inf -r -y", "", @SW_HIDE) ;extract all INFs from the current DriverPack $foundINF = "" _Recursion($folder) ;find the INFs $INFList = StringSplit(StringTrimRight($foundINF, 1), Chr(2)) ;break the string in to an array For $a = 1 To $INFList[0] GUICtrlSetData($prog, $a / $INFList[0] * 100) GUICtrlSetData($showCurrentName, $INFList[$a]) $namePrep = StringTrimLeft($INFList[$a], $trimLength) ;lists the name of the current INF and it's path in the DP archive $where = StringInStr($namePrep, "\", 0, -1) - 1 $listName = StringMid($namePrep, 1, $where) ;strips the path from the current INF $index = _ArraySearch($HWIDArray, $file & Chr(2) & $listName & Chr(2)) If $index < 1 Then _ArrayAdd($HWIDArray, $file & Chr(2) & $listName & Chr(2)) $listNameIndex = _ArraySearch($HWIDArray, $file & Chr(2) & $listName & Chr(2)) $man = IniReadSection($INFList[$a], "Manufacturer") If @error <> 1 Then For $b = 1 To $man[0][0] $manList = $man[$b][1] If StringInStr($manList, ",") Then ;multiple items in [Manufacturer] $manBreak = StringSplit($manList, ",") $mainMan = $manBreak[1] ;"primary" manufacuter item, is used later $HWID = IniReadSection($INFList[$a], $mainMan) If @error <> 1 Then For $c = 1 To $HWID[0][0] _Rip() ;gets info from first item in [Manufacturer] Next For $d = 2 To $manBreak[0] $indivMan = StringStripWS($manBreak[$d], 8) $HWID = IniReadSection($INFList[$a], $mainMan & "." & $indivMan) If @error <> 1 Then For $c = 1 To $HWID[0][0] _Rip() ;gets the remaining items from [Manufacturer] Next EndIf Next EndIf Else ;only one item in [Manufacturer] $HWID = IniReadSection($INFList[$a], $manList) If @error <> 1 Then For $c = 1 To $HWID[0][0] _Rip() Next EndIf EndIf Next EndIf Next DirRemove($folder, 1) GUICtrlSetData($prog, 0) Until 1 = 2 GUIDelete($showProg) ;delete previous repository if already present FileDelete($startDir & "\HWIDrepository.txt") $output = FileOpen($startDir & "\HWIDrepository.txt", 1) FileWriteLine($output, _ArrayToString($HWIDArray, Chr(4), 1)) FileClose($output) MsgBox(0, "Done", "Finished sniffing the INFs, the output has been saved to:" & @CR & $startDir & "\HWIDrepository.txt") Exit Func _Rip() If StringInStr($HWID[$c][1], ",") = 0 And StringInStr($HWID[$c][1], "\") <> 0 Then If StringInStr($HWID[$c][1], ";") = 0 Then $HWIDArray[$listNameIndex] &= StringStripWS($HWID[$c][1], 8) & Chr(3) If StringInStr($HWID[$c][1], ";") Then $semiTrim = StringSplit($HWID[$c][1], ";") $HWIDArray[$listNameIndex] &= StringStripWS($semiTrim[1], 8) & Chr(3) EndIf EndIf If StringInStr($HWID[$c][1], ",") Then $HWIDsplit = StringSplit($HWID[$c][1], ",") For $l = 1 To $HWIDsplit[0] If StringInStr($HWIDsplit[$l], "\") Then If StringInStr($HWIDsplit[$l], ";") = 0 Then $HWIDArray[$listNameIndex] &= StringStripWS($HWIDsplit[$l], 8) & Chr(3) If StringInStr($HWIDsplit[$l], ";") Then $semiTrim = StringSplit($HWIDsplit[$l], ";") $HWIDArray[$listNameIndex] &= StringStripWS($semiTrim[1], 8) & Chr(3) EndIf EndIf Next EndIf EndFunc ;==>_Rip Func _Recursion($folder, $depth = 0) If $depth = 0 Then Global $RFSstring = "" $search = FileFindFirstFile($folder & "\*.*") If @error Then Return ;Search through all files and folders in directory While 1 $next = FileFindNextFile($search) If @error Then ExitLoop ;If folder, recurse If StringInStr(FileGetAttrib($folder & "\" & $next), "D") Then _Recursion($folder & "\" & $next, $depth + 1) Else ;Append filename to master string If StringLower(StringRight($folder & "\" & $next, 3)) = "inf" Then $foundINF &= $folder & "\" & $next & Chr(2) EndIf WEnd FileClose($search) If $depth = 0 Then Return StringSplit(StringTrimRight($RFSstring, 1), "*") EndFunc ;==>_Recursion
Source for DeviceInstall:
#RequireAdmin #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_outfile=DeviceInstall.exe #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Run_Tidy=y #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ;~ Driver Installer V2 ;~ Coded by Ian Maxwell (llewxam @ www.driverpacks.net & www.autoitscript.com forums) ;~ AutoIt 3.3.6.1 ;~ DeviceAPI & folder recursion routines by weaponx @ www.autoitscript.com forum #include "DeviceAPI.au3" #include "Array.au3" #include "GUIConstantsEx.au3" #include "StaticConstants.au3" If @OSVersion == "WIN_2000" Then MsgBox(0, "Unsupported OS", "Due to API issues, Windows 2000 is not supported at this time.") Exit EndIf Local $HWID, $foundLocations, $installed, $matches, $OSArch = @OSArch FileInstall("7z.exe", @TempDir & "\7z.exe", 1) FileInstall("7z.dll", @TempDir & "\7z.dll", 1) $rand = Random(200, 5000, 1) $folder = @TempDir & "\" & $rand DirCreate($folder) ;Build list of devices _DeviceAPI_GetClassDevices() ;Loop through all devices by index, strip out ones without a HWID While _DeviceAPI_EnumDevices() $haveHWID = _DeviceAPI_GetDeviceRegistryProperty($SPDRP_HARDWAREID) If $haveHWID <> "" Then $HWID &= _DeviceAPI_GetDeviceRegistryProperty($SPDRP_DEVICEDESC) & Chr(2) & _DeviceAPI_GetDeviceRegistryProperty($SPDRP_HARDWAREID) & Chr(2) EndIf WEnd $localHWID = StringSplit(StringTrimRight($HWID, 1), Chr(2)) $GUIWidth = @DesktopWidth - 100 $main = GUICreate("Driver Installer v2 - MaxImuM AdVaNtAgE SofTWarE © 2010", $GUIWidth, 145, 50, 1) $currentDeviceName = GUICtrlCreateLabel("", 5, 5, $GUIWidth - 10, 20) $currentDeviceID = GUICtrlCreateLabel("", 5, 25, $GUIWidth - 10, 20, $SS_NOPREFIX) $info = GUICtrlCreateLabel("", 5, 65, $GUIWidth - 10, 40) $prog = GUICtrlCreateProgress(5, 120, $GUIWidth - 10, 20) GUISetState(@SW_SHOW, $main) $input = FileOpen("HWIDrepository.txt", 0) $HWIDRead = FileRead($input) FileClose($input) $HWIDArray = StringSplit($HWIDRead, Chr(4)) For $a = 1 To $localHWID[0] Step 2 GUICtrlSetData($prog, $a / $localHWID[0] * 100) GUICtrlSetData($currentDeviceName, "Device Name: " & $localHWID[$a]) GUICtrlSetData($currentDeviceID, "HWID: " & StringUpper($localHWID[$a + 1])) GUICtrlSetData($info, "Looking for device driver matches") $specific = "" ;not used, but could be to further refine the results $generic = $localHWID[$a + 1] If StringInStr($generic, "SUBSYS") Then $break = StringSplit($generic, "SUBSYS", 1) $generic = StringTrimRight($break[1], 1) $specific = $break[2] EndIf For $b = 1 To $HWIDArray[0] $description = StringSplit($HWIDArray[$b], Chr(2)) If $description[3] <> "" Then $actualHWID = StringSplit($description[3], Chr(3)) For $c = 1 To $actualHWID[0] - 1 If StringInStr($actualHWID[$c], $generic) Then $matches &= $description[1] & Chr(2) & $description[2] & Chr(2) & $localHWID[$a] & Chr(3) ContinueLoop (2) EndIf Next EndIf Next Next $splitMatches = StringSplit(StringTrimRight($matches, 1), Chr(3)) $unique = _ArrayUnique($splitMatches, 1, 1) GUICtrlSetData($prog, 0) GUICtrlSetData($currentDeviceName, "") GUICtrlSetData($currentDeviceID, "") If $unique[0] > 1 Then For $a = 1 To $unique[0] $location = StringSplit($unique[$a], Chr(2)) GUICtrlSetData($info, "Found matches, extracting " & $location[2] & " from " & $location[1]) RunWait(@TempDir & "\7z.exe x " & $location[1] & " -o" & $folder & " " & $location[2] & " -r -y", "", @SW_HIDE) ;extract the current driver from the DriverPack If $OSArch = "X86" Then FileInstall("dpinst.exe", $folder & "\" & $location[2] & "\dpinst.exe", 1) If $OSArch = "X64" Then FileInstall("dpinst64.exe", $folder & "\" & $location[2] & "\dpinst.exe", 1) FileInstall("dpinst.xml", $folder & "\" & $location[2] & "\dpinst.xml", 1) $foundLocations &= $folder & "\" & $location[2] & Chr(2) & $location[1] & Chr(2) & $location[3] & Chr(2) GUICtrlSetData($prog, $a / $unique[0] * 100) Next GUICtrlSetData($currentDeviceName, "") GUICtrlSetData($currentDeviceID, "") GUICtrlSetData($prog, 0) $breakLocations = StringSplit(StringTrimRight($foundLocations, 1), Chr(2)) For $a = 1 To $breakLocations[0] Step 3 GUICtrlSetData($info, "Installing " & $breakLocations[$a + 2] & " driver") ShellExecuteWait($breakLocations[$a] & "\dpinst.exe", "/S /SA /SE /SW") GUICtrlSetData($prog, $a / $unique[0] * 100) $installed &= $breakLocations[$a + 2] & Chr(2) Next $showInstalled = StringSplit(StringTrimRight($installed, 1), Chr(2)) GUIDelete($main) $showGUI = GUICreate("Installed Divers", 600, 200, 1, 1) $showList = GUICtrlCreateList("", 5, 5, 590, 190) GUISetState(@SW_SHOW, $showGUI) For $a = 1 To $showInstalled[0] GUICtrlSetData($showList, $showInstalled[$a]) Next Else MsgBox(0, "Nothing to update", "There are no drivers avaiable that are compatible with your computer.") DirRemove($folder, 1) Exit EndIf Do $msg = GUIGetMsg() If $msg = $gui_event_close Then DirRemove($folder, 1) Exit EndIf Until 1 = 2
It is tested but only on a handful of machines, I thought it would be more fun to release it now as-is rather than sit on it for a while
Enjoy
Ian





