#Test script to uninstall Drivers, UWP Apps and delete files
#Script will remove all versions of drivers
#Will return to Inbox driver, if available


Function Get-IniContents 
{
    [CmdletBinding()]
    Param ([string] $IniFilePath)
    Process
    {
        $ini = @{}  
        switch -regex -file $IniFilePath
        {  
            "^\[(.+)\]$" # Section  
            {  
                $section = $matches[1]  
                $ini[$section] = @{}  
                $CommentCount = 0  
            }  

            "^(;.*)$" # Comment  
            {  
                $section = "Comment" 

                if($ini.Keys -notcontains "Comment")
                {
                    $ini[$section] = @{}  
                }
                  
                $value = $matches[1]  
                $CommentCount = $CommentCount + 1  
                $name = "Comment" + $CommentCount  
                $ini[$section][$name] = $value  
            }  
         
            "(.+?)\s*=\s*(.*)" # Key  
            {  
                if (!($section))  
                {  
                    $section = "No-Section"  
                    $ini[$section] = @{}  
                }  
                $name,$value = $matches[1..2]  
                $ini[$section][$name] = $value  
            }  
        }  
        
        return $ini  
    }
}

Function Write-LogFile
{
    [CmdletBinding()]
    Param([Parameter(ValueFromPipeline)] $logEvent)
    Process
    {
        Add-Content -Path $logPath -Value $logEvent
    }

}

Function Remove-Driver
{   
    [CmdletBinding()]
    Param([hashtable] $infs)
    Process
    {
        Write-LogFile "[Uninstall Drivers]"

        $retCode = 0
        $extensionInfs = @{}

        if($infs.Count -eq 0)
        {
            Write-LogFile ">> No driver to remove"
            return $retCode
        }
    
        #Re-order keys (01,02...); else it will be on a random order
        $ordInfs = $infs.GetEnumerator() | sort key
       
        #Get driver list; 
        $drv = PnpUtil.exe /enum-drivers

        #Can't use the ff as it doesn't list the original driver name
        #$DevName = Get-WmiObject Win32_PnPSignedDriver| select * | where {$_.DeviceName -like "*Realtek*"}

     
        foreach($i in $ordInfs)
        {                       
            Write-LogFile ("> Uninstalling " + $i.Value)
            
            #Get Published Name (Ex. oem1.inf) and Class Name (ex. Extension)
            $publishedName = $drv | Select-String -Pattern $i.Value -Context 2,2 | ForEach { @{ "Inf" = ($_.Context.PreContext[1] -split ':')[1].trim() ; "ClassName" = ($_.Context.PostContext[1] -split ':')[1].trim()} } 

            


            if ($publishedName.Count -eq 0)
            {
                Write-LogFile "...Cannot find inf`r`n" 
                $retCode = -1
            }

            foreach($p in $publishedName)
            {
                if($p["ClassName"] -contains "Extensions")
                {
                    Write-LogFile "...Found Extension INF; To remove later`r`n"
                
                    #Add into Extension Inf List
                    $extensionInfs.Add($p["Inf"], $i.Value)

                }
                else
                {    

                    #----start of the removal of devices script-----#
                    $stringInfName = "InfName = '" + $p["Inf"] + "'"
                    
                    $deviceIDQuery = Get-CimInstance win32_PnPSignedDriver -Filter $stringInfName | Select DeviceID  
                   
                    
                    if(![string]::IsNullOrEmpty($deviceIDQuery))
                    {
                       $multipleDeviceHolder = $deviceIDQuery.DeviceID.split()
                       $numOfDevices = $multipleDeviceHolder.count 
                       Write-LogFile ($numOfDevices)
            
                       for($ib = 0; $ib -lt $numOfDevices; $ib++)
                       {
                          Write-LogFile ("...Removing " + $multipleDeviceHolder[$ib])
                          PnpUtil.exe /remove-device $multipleDeviceHolder[$ib]
                       } 
                       PnpUtil.exe /remove-device $deviceIDQuery.DeviceID
                    }
                    #----end of the removal of devices script-----#

                    Write-LogFile ("...Deleting " + $p["Inf"])
                        
                    #Uninstall driver
                    PnpUtil.exe /delete-driver $p["Inf"] /uninstall /force | Write-LogFile

                    switch ($LASTEXITCODE)
                    {
                        0: {} #success
                        259: {} #reboot
                        default: { $retCode = $LASTEXITCODE }
                    }

                    Write-LogFile "`n"
                }

            }        

         }

         foreach($e in $extensionInfs.Keys)
         { 
            #----start of the removal of devices script-----#
            $stringextInfName = "InfName = '" + $e + "'"
           
            $extdeviceIDQuery = Get-CimInstance win32_PnPSignedDriver -Filter $stringextInfName | Select DeviceID  
        
            if(![string]::IsNullOrEmpty($extdeviceIDQuery))
            {
                $multipleExtDeviceHolder = $extdeviceIDQuery.DeviceID.Split()
                $numOfExtDevices = $multipleExtDeviceHolder.count 
                Write-LogFile ($numOfExtDevices)
            
                for($ie = 0; $ie -lt $numOfExtDevices; $ie++)
                { 
                   Write-LogFile ("...Removing " + $multipleExtDeviceHolder[$ie])
                   PnpUtil.exe /remove-device $multipleExtDeviceHolder[$ie]
                }
            }      
            #----end of the removal of devices script-----#
        
            Write-LogFile ("> Uninstalling Extension INF: " + $extensionInfs[$e])
            Write-LogFile ("`...Deleting " + $e)

            #Uninstall Extension Inf
            PnpUtil.exe /delete-driver $e /uninstall /force | Write-LogFile

            switch ($LASTEXITCODE)
            {
                0: {} #success
                259: {} #reboot
                default: { $retCode = $LASTEXITCODE }
            }

            Write-LogFile "`n"
         }

        return $retCode
    }
}


Function Remove-Device
{   
    [CmdletBinding()]
    Param([hashtable] $devs)
    Process
    {
        Write-LogFile "[Remove Device]"

        $retCode = 0
        $removedevs = @{}

        if($devs.Count -eq 0)
        {
            Write-LogFile ">> No device to remove"
            return $retCode
        }
    
        #Re-order keys (01,02...); else it will be on a random order
        $ordDevs = $devs.GetEnumerator() | sort key

     
        foreach($i in $ordDevs)
        {                       
            Write-LogFile ("> Removing " + $i.Value)

            #Add into Remove Device List
            $removedevs.Add($i.Value, $i.Value)
        }

        foreach($e in $removedevs.Keys)
        { 
            #----start of the removal of devices script-----#
            Write-LogFile ("> Removing Device: " + $removedevs[$e])
            PnpUtil.exe /remove-device /deviceid $e
            #----end of the removal of devices script-----#

            switch ($LASTEXITCODE)
            {
                0: {} #success
                259: {} #reboot
                default: { $retCode = $LASTEXITCODE }
            }

            Write-LogFile "`n"
        }
        PnpUtil.exe /scan-devices

        return $retCode
    }
}

#Getting list for driver removal .ini file which was indicated as a parameter.
$param1 = $args[0]

#Get contents of ini file
$curLoc = Split-Path -Parent $MyInvocation.MyCommand.Definition 
$targetFile = $curLoc + "\" + $param1
$iniContent = Get-IniContents $targetFile

#Create log file
$timestmp = Get-Date -Format yyyyMMdd-HHmmss
$logName = "\Result_" + $timestmp + ".log"

$logFile = New-Item -Path $curLoc -Name $logName -ItemType "file" 
$logPath = $curLoc +"\"+$logName

#Remove drivers, apps and files
$removeINF = Remove-Driver $iniContent["INF"]
$removeDEVICE = Remove-Device $iniContent["DEVICE"]

if($removeINF -ne 0)
{
    #TODO
}

if($removeDEVICE -ne 0)
{
    #TODO
}
