#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiStatusBar.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>

Local $exStyles = BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_CHECKBOXES)
Dim $DriverList[255][8], $DriverCount = 0 
Global $DRIList,$StatusBar1


Func _driver()
$Driver = GUICreate("驱动备份", 540, 350, -1, -1, -1, -1, $window)
GUISetBkColor(0xEFF0F2)
$MenuItem1 = GUICtrlCreateMenu("搜索驱动(&F)")
$MenuItem2 = GUICtrlCreateMenuItem("搜索需要备份的驱动", $MenuItem1)
$MenuItem3 = GUICtrlCreateMenuItem("搜索系统中的所有驱动", $MenuItem1)
$MenuItem4 = GUICtrlCreateMenuItem("", $MenuItem1)
$MenuItem5 = GUICtrlCreateMenuItem("退出(&X)", $MenuItem1)
$MenuItem6 = GUICtrlCreateMenu("备份驱动(&B)")
$MenuItem7 = GUICtrlCreateMenuItem("备份选择的驱动", $MenuItem6)
$MenuItem8 = GUICtrlCreateMenuItem("", $MenuItem6)
$MenuItem9 = GUICtrlCreateMenuItem("备份建议驱动", $MenuItem6)
$MenuItem10 = GUICtrlCreateMenuItem("备份所有驱动", $MenuItem6)
$DRIList = GUICtrlCreateListView("驱动程序名称|驱动类型|备注", 0, 0, 540, 304)
_GUICtrlListView_SetColumnWidth($DRIList, 0, 290)
_GUICtrlListView_SetColumnWidth($DRIList, 1, 150)
_GUICtrlListView_SetColumnWidth($DRIList, 2, 50)
_GUICtrlListView_SetExtendedListViewStyle($DRIList, $exStyles + $LVS_EX_GRIDLINES) 
$StatusBar1 = _GUICtrlStatusBar_Create($Driver)
Dim $StatusBar1_PartsWidth[1] = [-1]
_GUICtrlStatusBar_SetParts($StatusBar1, $StatusBar1_PartsWidth)
_GUICtrlStatusBar_SetText($StatusBar1, "", 0)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

_SearchDriverAll()
_MnuSearch_Click()

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			GUIDelete($Driver)
			ExitLoop
		Case $MenuItem5
			GUIDelete($Driver)
			ExitLoop
		Case $MenuItem7
			_BtnBackUp_Click()
		Case $MenuItem9
			_MnuSearch_Click()
			_GUICtrlListView_SetItemChecked($DRIList, -1)
			_BtnBackUp_Click()
		Case $MenuItem10
			_MnuSearchAll_Click()
			_GUICtrlListView_SetItemChecked($DRIList, -1)
			_BtnBackUp_Click()
		Case $MenuItem2
			_MnuSearch_Click()
		Case $MenuItem3
			_MnuSearchAll_Click()
		Case $MenuItem6
			_BtnBackUp_Click()

	EndSwitch
WEnd
EndFunc

Func _SearchDriverAll()
        Local $i = 1, $GetReg
        Local $HKLM = "HKLM\SYSTEM\CurrentControlSet\Control\Class" 
        While 1
                $GetReg = $HKLM & "\" & RegEnumKey($HKLM, $i)
                If @error = -1 Then ExitLoop
                _GetDriverInfo($GetReg)
                $i = $i + 1
        WEnd
        SetError(0)
EndFunc 
 

Func _GetDriverInfo($HKLM)
        Local $i = 1, $GetReg
        While 1
                $GetReg = $HKLM & "\" & RegEnumKey($HKLM, $i)
                If @error = -1 Then ExitLoop
                If _IsTrue($GetReg, "DriverDesc") Then
                        If Not _SearchName(RegRead($GetReg, "DriverDesc")) Then
                                $DriverType = RegRead($HKLM, "")
                                $DriverList[$DriverCount][0] = $DriverType
                                $DriverList[$DriverCount][1] = RegRead($GetReg, "DriverDesc")  
                                $DriverList[$DriverCount][2] = RegRead($GetReg, "DriverVersion")
                                $DriverList[$DriverCount][3] = RegRead($GetReg, "DriverDate") 
                                $DriverList[$DriverCount][4] = RegRead($GetReg, "ProviderName")
                                $DriverList[$DriverCount][7] = RegRead($GetReg, "InfPath")
                                $DriverList[$DriverCount][6] = IniRead(@WindowsDir & "\inf\" & $DriverList[$DriverCount][7], "Version", "CatalogFile", "无")
                                $DriverList[$DriverCount][5] = _SearchListCount($DriverList[$DriverCount][7])
                                $DriverCount = $DriverCount + 1
                        EndIf
                EndIf
                $i = $i + 1
        WEnd
        SetError(0)
EndFunc
 

Func _IsTrue($GetReg, $KeyName)
        Local $Boolen
        RegRead($GetReg, $KeyName)
        If @error Then
                $Boolen = False
        Else
                $Boolen = True
        EndIf
        SetError(0)
        Return $Boolen
EndFunc
 

Func _SearchName($DriverDesc)
        Local $i, $Boolen
        For $i = 0 To $DriverCount
                If $DriverList[$i][1] = $DriverDesc Then
                        $Boolen = True
                        ExitLoop
                EndIf
        Next
        Return $Boolen
EndFunc 
 
Func _SearchListCount($iniPath)
        $DisksFiles = IniReadSection(@WindowsDir & "\inf\" & $iniPath, "SourceDisksFiles")
        If @error Then
                Return 1
        Else
                Return $DisksFiles[0][0] + 1
        EndIf
        SetError(0)
EndFunc

Func _MnuSearch_Click()
        Local $i
        _GUICtrlListView_DeleteAllItems($DRIList)
        For $i = 0 To $DriverCount - 1
                If $DriverList[$i][4] <> "Microsoft" Then
                        GUICtrlCreateListViewItem($DriverList[$i][1] & "|" & $DriverList[$i][0] & "|" & "建议备份", $DRIList)
                EndIf
        Next
        _GUICtrlStatusBar_SetText($StatusBar1, "总共搜索到" & _GUICtrlListView_GetItemCount($DRIList) & "个驱动设备", 0, 0)
EndFunc
 
Func _MnuSearchAll_Click()
        Local $i
        _GUICtrlListView_DeleteAllItems($DRIList)
        For $i = 0 To $DriverCount - 1
                If $DriverList[$i][4] <> "Microsoft" Then
                        GUICtrlCreateListViewItem($DriverList[$i][1] & "|" & $DriverList[$i][0] & "|" & "建议备份", $DRIList)
                Else
                        GUICtrlCreateListViewItem($DriverList[$i][1] & "|" & $DriverList[$i][0] & "|" & "系统自带", $DRIList)
                EndIf
        Next
        _GUICtrlStatusBar_SetText($StatusBar1, "总共搜索到" & _GUICtrlListView_GetItemCount($DRIList) & "个驱动设备", 0, 0)
EndFunc
 
 
Func _BtnBackUp_Click()
        Local $i, $j, $k, $DrvList[255][9], $DriverName

        For $i = 0 To _GUICtrlListView_GetItemCount($DRIList)
                If _GUICtrlListView_GetItemChecked($DRIList, $i) Then
                        $index = _GetListIndex(_GUICtrlListView_GetItemText($DRIList, $i))
                        For $j = 0 To 7
                                $DrvList[$k][$j] = $DriverList[$index][$j]
                        Next
                        $k = $k + 1
                EndIf
        Next
 
        If $k = 0 Then
                MsgBox(8192 + 64, "提示", "请选择要备份的驱动.")
        Else
                For $i = 0 To $k - 1 
                        _GUICtrlStatusBar_SetText($StatusBar1, "正在备份 " & $DrvList[$i][1] & " 请稍后...", 0, 0)
                        $FileName = ""
                        $FileName = IniReadSection(@WindowsDir & "\inf\" & $DrvList[$i][7], "SourceDisksFiles")
                        If $FileName = 1 Then
                                FileCopy(@WindowsDir & "\inf\" & $DrvList[$i][7], _CreateDriverPath($DrvList[$i][1]), 9)
                                ContinueLoop
                        EndIf
                        $FileName[0][0] = $DrvList[$i][7]
                        _CopyDriverFiles($FileName, _CreateDriverPath($DrvList[$i][1]))
                Next
                _GUICtrlStatusBar_SetText($StatusBar1, "备份完成!", 0, 0)
        EndIf
EndFunc
 

Func _GetListIndex($DriverDesc)
        Local $i
        For $i = 0 To 255
                If $DriverDesc = $DriverList[$i][1] Then ExitLoop
        Next
        Return $i
EndFunc
 

Func _CreateDriverPath($DriverName)
        Local $BackUp = @ScriptDir & "\DriverBack\" & $DriverName
        $BackUp = StringRegExpReplace($BackUp,"[/]"," ")
        If Not FileExists($BackUp) Then
                DirCreate($BackUp)
        EndIf
        Return $BackUp
EndFunc
 
Func _CopyDriverFiles($FileName, $BackUp)
        Local $i, $j, $SearchPath[5]
        $SearchPath[0] = @WindowsDir & "\"
        $SearchPath[1] = @WindowsDir & "\inf\"
        $SearchPath[2] = @WindowsDir & "\help\"
        $SearchPath[3] = @WindowsDir & "\System32\"
        $SearchPath[4] = @WindowsDir & "\System32\Drivers\"
        For $i = 0 To UBound($FileName) - 1
                For $j = 0 To 4
                        If FileExists($SearchPath[$j] & $FileName[$i][0]) Then
                                FileCopy($SearchPath[$j] & $FileName[$i][0], $BackUp, 9)
                                ExitLoop
                        EndIf
                Next
        Next
EndFunc