<# 
******************************************************************************
**                            INTEL CONFIDENTIAL                            **
**                                                                          **
**        Copyright 2016 Intel Corporation All Rights Reserved.             **
**                                                                          **
**  The material contained or described herein and all documents related    **
**  to such material ("Material") are owned by Intel Corporation or its     **
**  suppliers or licensors. Title to the Material remains with Intel        **
**  Corporation or its suppliers and licensors. The Material contains trade **
**  secrets and proprietary and confidential information of Intel or its    **
**  suppliers and licensors. The Material is protected by worldwide         **
**  copyright and trade secret laws and treaty provisions. No part of the   **
**  Material may be used, copied, reproduced, modified, published,          **
**  uploaded, posted, transmitted, distributed, or disclosed in any way     **
**  without Intel’s prior express written permission.                       **
**                                                                          **
**  No license under any patent, copyright, trade secret or other           **
**  intellectual property right is granted to or conferred upon you by      **
**  disclosure or delivery of the Materials, either expressly, by           **
**  implication, inducement, estoppel or otherwise. Any license under such  **
**  intellectual property rights must be express and approved by Intel in   **
**  writing.                                                                **
******************************************************************************
#>

<#   
	.SYNOPSIS
		Installs Intel(R) PROSet into Windows Server 2016 Nano

	.DESCRIPTION
		Installs Intel(R) Netcmdlets for Microsoft* Windows PowerShell* and supporting binaries.
        
        Intel(R) Ethernet drivers will _not_ be installed by this script.

		This script is intended to reside within a Nano Server image file, and be invoked directly from setupcomplete.cmd.

		There are no parameters

        To execute manually
        1) Copy this script and supporting .zip file(s) to a directory on your Nano Server
        2) Start server and connect
        3) Execute script

	.EXAMPLE
		.\NanoSetup.ps1

    .NOTES
        Microsoft* C++ redistributable binaries must be present on the server prior to running this script.
		Required binaries must be in the same directory as this script
#>
[CmdLetBinding()]
Param()

function Format-Exception ($exception)
{
<#
    .DESCRIPTION
    Formats an exception object

    .OUTPUTS
    [string]
#>
    [string] $out = $exception.Exception
    $out += "`r`n"
    $out += "`r`n[ln " + $exception.InvocationInfo.ScriptLineNumber
    $out += "] " + $exception.InvocationInfo.Line.Trim()
    $out
}


function CreateTempDir {
<#
    .DESCRIPTION
    Creates a temporary directory for use within the script

    .OUTPUTS
    [System.IO::DirectoryInfo]
    Verbose messages
#>
    Write-Verbose "CreateTempDir"
    $temp = $env:temp
    try {
        $temp = [System.IO.Path]::Combine($temp, [System.IO.Path]::GetRandomFileName())
        [System.IO.Directory]::CreateDirectory($temp) | Out-Null 
    }
    catch {
        Write-Warning "Unable to create temporary directory. Script cannot continue."
        Format-Exception($_) | Write-Error
    }
    Write-Verbose "$temp"
    Write-Verbose "CreateTempDir OK"
    $temp
}

function DeleteDir {
<#
    .DESCRIPTION
    Deletes a directory and does necessary checks to make sure directory exists and is not null.

    .OUTPUTS
    Verbose messages only
#>
    [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
	    [String]$Path
    )
    try {
        if (($Path -ne $null) -and (Test-Path -Path $Path)) {
            Write-Verbose "Deleting $Path"
            Get-ChildItem -Path $Path -Recurse | Remove-Item -force -recurse
            Remove-Item $Path -Force 
        }
    }
    catch
    {
        # We just issue a warning if this failed
        Write-Warning "Unable to delete $Path"
    }
    Write-Verbose "DeleteDir OK"
}

# creates directories needed by application 
function CreateDirectories 
{
<#
    .DESCRIPTION
    Creates all directories required for Intel(R) PROSet

    .PARAMETER OSdrive
	The path to an operating system root drive

    .OUTPUTS
    Verbose messages only
    No return value; exceptions will be passed as terminating Errors
#>
    [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_  -PathType 'Container'})]
	    [String]$OSdrive
    )
    
    Process {
        Write-Verbose "CreateDirectories $OSdrive"
        try {
            New-Item "${OSdrive}Program Files\Intel" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\IntelNetCmdlets" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\NCS2" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\NCS2\Agent" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\NCS2\WMIProv" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\DMIX" -Force -type directory | Write-Verbose
            New-Item "${OSdrive}Program Files\Intel\DMIX\Resource" -Force -type directory | Write-Verbose
        }
        catch {
            Write-Warning "Unable to create required directories. Script cannot continue."
            Format-Exception($_) | Write-Error
        }
        Write-Verbose "CreateDirectories OK"
    }
}

function InstallPROSetNS
{
<#
    .DESCRIPTION
    Installs the PROSetNS.zip file to the user system

    .PARAMETER OSdrive
	The path to an operating system root drive. Example,'C:\'

    .OUTPUTS
    Verbose messages only
    No return value; exceptions will be passed as terminating Errors
#>
    [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Container'})]
	    [String]$OSdrive
    )

    Process {
        Write-Verbose "InstallPROSetNS $OSdrive"

        try {
            # create temporary directory
            $TempDir = CreateTempDir            
            Write-Verbose "Extracting PROSetNS.zip..."
            Expand-Archive -Path "${script:Root}PROSetNS.zip" -DestinationPath $TempDir
            
            #copy QV files to System32
            Copy-Item "${TempDir}\IQVw64e.sys" -Destination "${OSdrive}Windows\System32\Drivers\IQVw64e.sys" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IQVw64e.inf" -Destination "${OSdrive}Windows\System32\Drivers\IQVw64e.inf" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IQVw64e.cat" -Destination "${OSdrive}Windows\System32\Drivers\IQVw64e.cat" -Force -ErrorAction Stop -PassThru | Write-Verbose
            
            InstallPROSet "${TempDir}\PROSet.zip" $OSdrive
            InstallPShellHelp "${TempDir}\PShellHelp.zip" $OSdrive
        }
        catch {
            Write-Warning "Unable to install contents of PROSet.zip file. Script cannot continue."
            Format-Exception($_) | Write-Error
        }
        finally {
            DeleteDir $TempDir
        }
        Write-Verbose "InstallPROSetNS OK"
    }
}

function InstallPROSet
{
<#
    .DESCRIPTION
    Installs the PROSet.zip file to the user system

    .PARAMETER Source
	The location of the PROSet.zip file; must be path to file.

    .PARAMETER OSdrive
	The operating system root drive; must be root drive path.

    .OUTPUTS
    Verbose messages only
    No return value; exceptions will be passed as terminating Errors
#>
    [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Leaf'})]
	    [String]$Source,
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Container'})]
	    [String]$OSdrive
    )

    Process {

        Write-Verbose "InstallPROSet $Source $OSdrive"

        try {
            # create temporary directory
            $TempDir = CreateTempDir
         
            # extact to temporary directory
            Write-Verbose "Extracting archive..."
            Expand-Archive -Path $Source -DestinationPath $TempDir
			
			#store the version info for VC Runtime dlls
			$msvcp_new = (Get-Item "${TempDir}\msvcp140.dll").VersionInfo.ProductVersion
			$msvcp_new = $msvcp_new.Split(".")
			$msvcp_new = $msvcp_new[2]
			$vcrun_new = (Get-Item "${TempDir}\vcruntime140.dll").VersionInfo.ProductVersion
			$vcrun_new = $vcrun_new.Split(".")
			$vcrun_new = [int]$vcrun_new[2]
			
            Write-Verbose "Copying files..."

            # VC Runtime
			if (Test-Path "${OSDrive}Windows\System32\msvcp140.dll")
			{
				$msvcp_old = (Get-Item "${OSDrive}Windows\System32\msvcp140.dll").VersionInfo.ProductVersion
				$msvcp_old = $msvcp_old.Split(".")
				$msvcp_old = [int]$msvcp_old[2]
				if ($msvcp_old -lt $msvcp_new)
                {
					Write-Verbose "Overwriting msvcp140.dll"
					Copy-Item "${TempDir}\msvcp140.dll" -Destination "${OSDrive}Windows\System32\msvcp140.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
			    }
            }
			else
			{
				Copy-Item "${TempDir}\msvcp140.dll" -Destination "${OSDrive}Windows\System32\msvcp140.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
			}
			
			if (Test-Path "${OSDrive}Windows\System32\vcruntime140.dll")
			{
				$vcrun_old = (Get-Item "${OSDrive}Windows\System32\vcruntime140.dll").VersionInfo.ProductVersion
				$vcrun_old = $vcrun_old.Split(".")
				$vcrun_old = [int]$vcrun_old[2]
				if ($vcrun_old -lt $vcrun_new)
                {
					Write-Verbose "Overwriting vcruntime140.dll"
					Copy-Item "${TempDir}\vcruntime140.dll" -Destination "${OSDrive}Windows\System32\vcruntime140.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
			    }
            }
			else
			{
				Copy-Item "${TempDir}\vcruntime140.dll" -Destination "${OSDrive}Windows\System32\vcruntime140.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
			}

			# Windows\System32
            Copy-Item "${TempDir}\NcsColib.dll" -Destination "${OSdrive}Windows\System32\NcsColib.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\NCS2InstUtility.dll" -Destination "${OSdrive}Windows\System32\NCS2InstUtility.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IPROSetMonitor.exe" -Destination "${OSdrive}Windows\System32\IPROSetMonitor.exe" -Force -ErrorAction Stop -PassThru | Write-Verbose
   
            # Program Files\Intel\NCS2\Agent"
            Copy-Item "${TempDir}\AdapterAgnt.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\AdapterAgnt.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\BootAgnt.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\BootAgnt.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\CoreAgnt.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\CoreAgnt.dll " -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\DiagAgnt.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\DiagAgnt.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\Rule.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\Rule.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\Rules.dat" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\Rules.dat" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\Rules.Map" -Destination "${OSdrive}Program Files\Intel\NCS2\Agent\Rules.Map" -Force -ErrorAction Stop -PassThru | Write-Verbose
    
            # Program Files\Intel\NCS2\WMIProv
            Copy-Item "${TempDir}\NCS2Core.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\NCS2Core.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\NCS2Diag.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\NCS2Diag.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\NCS2Boot.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\NCS2Boot.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\NCS2Provider.dll" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\NCS2Provider.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
   
            # Program Files\Intel\NCS2\WMIProv\MOF"
            Copy-Item "${TempDir}\ICmLn.mof" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICmLn.mof" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\ICmEnu.mfl" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICmEnu.mfl" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\ICoreLn.mof" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICoreLn.mof" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\ICoreEnu.mfl" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICoreEnu.mfl" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IDiagLn.mof" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IDiagLn.mof" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IDiagEnu.mfl" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IDiagEnu.mfl" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IBootLn.mof" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IBootLn.mof" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IBootEnu.mfl" -Destination "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IBootEnu.mfl" -Force -ErrorAction Stop -PassThru | Write-Verbose

            # Program Files\Intel\IntelNetCmdlets"
            Copy-Item "${TempDir}\IntelNetcmdlets.dll" -Destination "${OSdrive}Program Files\Intel\IntelNetCmdlets\IntelNetcmdlets.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IntelNetcmdlets.format.ps1xml" -Destination "${OSdrive}Program Files\Intel\IntelNetCmdlets\IntelNetcmdlets.format.ps1xml" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IntelNetcmdlets.psd1" -Destination "${OSdrive}Program Files\Intel\IntelNetCmdlets\IntelNetcmdlets.psd1" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\IntelNetcmdletsx86.psd1" -Destination "${OSdrive}Program Files\Intel\IntelNetCmdlets\IntelNetcmdletsx86.psd1" -Force -ErrorAction Stop -PassThru | Write-Verbose

            # Program Files\Intel\DMIX
            # !dont copy right now doesnt work! Copy-Item ${TempDir}\SaveRestore.ps1 -Destination "${OSdrive}Program Files\Intel\DMIX\SaveRestore.ps1" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\DMIXSetpENU.reg" -Destination "${OSdrive}Program Files\Intel\DMIX\DMIXSetpENU.reg" -Force -ErrorAction Stop -PassThru | Write-Verbose

            # Resolve source location of oemver.reg; local copies override .zip file content
            if (Test-Path "${Script:Root}oemver.reg") {
                Write-Verbose "Using custom oemver.reg"
    			Copy-Item "${Script:Root}oemver.reg" -Destination "${OSdrive}Program Files\Intel\DMIX\OemVer.reg" -Force -ErrorAction Stop -PassThru | Write-Verbose
            }
            else {
    			Copy-Item ${TempDir}\OEMVer.reg -Destination "${OSdrive}Program Files\Intel\DMIX\OemVer.reg" -Force -ErrorAction Stop -PassThru | Write-Verbose
            }

            # Resolve source location of perf.xml; local copies override .zip file content
            if (Test-Path "${Script:Root}perf.xml") {
                Write-Verbose "Using custom perf.xml"
    			Copy-Item "${Script:Root}perf.xml" -Destination "${OSdrive}Program Files\Intel\DMIX\perf.xml" -Force -ErrorAction Stop -PassThru | Write-Verbose
            }
            else {
    			Copy-Item "${TempDir}\perf.xml" -Destination "${OSdrive}Program Files\Intel\DMIX\perf.xml" -Force -ErrorAction Stop -PassThru | Write-Verbose
            }
            
            # Program Files\Intel\DMIX\Resource
            Copy-Item "${TempDir}\CommonResENU.dll" -Destination "${OSdrive}Program Files\Intel\DMIX\Resource\CommonResENU.dll" -Force -ErrorAction Stop -PassThru | Write-Verbose
        }
        catch {
            Write-Warning "Unable to install contents of PROSet.zip file. Script cannot continue."
            Format-Exception($_) | Write-Error
        }
        finally {
            DeleteDir $TempDir
        }
        Write-Verbose "InstallPROSet OK"
    }
}

function InstallPShellHelp {
<#
    .DESCRIPTION
    Installs the PShellHelp.zip file to the user system

    .PARAMETER Source
	The location of the PROSet.zip file; must be path to file.

    .PARAMETER OSdrive
	The path to an operating system root OSdrive

    .OUTPUTS
    Verbose messages only
    No return value; exceptions will be passed as terminating Errors
#>
    [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Leaf'})]
	    [String]$Source,
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Container'})]
	    [String]$OSdrive
    )

    Process {

        Write-Verbose "InstallPROSet $Source $OSdrive"

        try {
            # create temporary directory
            $TempDir = CreateTempDir
         
            # extact to temporary directory
            Write-Verbose "Extracting archive..."
            Expand-Archive -Path $Source -DestinationPath $TempDir

            Write-Verbose "Copying files..."

            Copy-Item "${TempDir}\ENU_about_IntelNetcmdlets.help.txt" -Destination "${OSdrive}Program Files\Intel\IntelNetCmdlets\about_IntelNetcmdlets.help.txt" -Force -ErrorAction Stop -PassThru | Write-Verbose
            Copy-Item "${TempDir}\ENU_IntelNetcmdlets.dll_Help.xml" -Destination "${OSdrive}Program Files\Intel\IntelNetCmdlets\IntelNetcmdlets.dll-Help.xml" -Force -ErrorAction Stop -PassThru | Write-Verbose
        }
        catch {
            Write-Warning "Unable to install contents of PROSet.zip file. Script cannot continue."
            Format-Exception($_) | Write-Error
        }
        finally {
            DeleteDir $TempDir
        }
        Write-Verbose "InstallPShellHelp OK"
    }
}

function AddRegistryFile {
<#
    .DESCRIPTION
    Adds registry file to operating system registry hive while being able to filter out 
	certain changes (passed in through arguments).

    .NOTES
	Intel(R) PROSet uses multiple .reg files for different operating systems. To avoid having
	unnecessary registry entries created for Nano Server, we provide a filter mechanism to remove
	these requests from the source .reg file.

    .PARAMETER Path
	The path to a registry file

    .PARAMETER Filter
	An array of strings to be compared to registry KEY entries and values

    .OUTPUTS
    Verbose messages only
    No return value; exceptions will be passed as terminating Errors
#>
    [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Leaf'})]
	    [String]$Path
	,
		[parameter(Mandatory=$false)]
		[string[]]$Filter
    )
    
    Process {
        Write-Verbose "AddRegistryFile $Path $Filter"
        try {
			if ($Filter) {

				Write-Verbose "Applying filter"
				Write-Verbose "Creating temporary .reg file"

				# create a temporary file name
				$tempfile = [System.IO.Path]::GetTempFileName() + ".reg"
				
				# read entire file into a string
				$content = [IO.File]::ReadAllText($Path) 

				# split file contents on bracket and, for each, check filter
				$content.Split("[") | ForEach-Object { 
					ForEach ($s in $Filter) {
						if (-not $_.Contains($s)) {
							if ($_.Contains("]")) {
								Add-Content $tempfile "[$_"; break
							}
							else {
								Add-Content $tempfile "$_"; break
							}
						}
					}
				 }
		
				# print contents of new file to verbose
				Write-Verbose "Adding $tempfile to registry"
				Get-Content $tempfile | Write-Verbose

				# import temporary file
				reg import "$tempfile"

				# remove file
				Write-Verbose "Removing $tempfile"
				Remove-Item $tempfile
            }
			else {
				#no filter just import entire file
				reg import "$Path"
			}
        }
        catch {

			if ($_ -imatch "operation completed successfully") {
				write-Verbose "Import successful"
			}
			else {
				Write-Warning "Unable to add registry file $Path. Script cannot continue."
				Format-Exception($_) | Write-Error
			}
        }
        Write-Verbose "AddRegistryFile OK"
    }
}

function Initialize {
<#
    .DESCRIPTION
    Performs run time initialization of software after OS setup completes. 

    .NOTES
    This intended to run once, after installation. This should be invoked through the setupcomplete.cmd
	startup file in an OS configuration.
#>
  [cmdletbinding()]
    Param( 
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_  -PathType 'Container'})]
	    [String]$OSdrive
    )
    
    Process {
        Write-Verbose "Initialize $OSdrive"

        try {
            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel]
            New-Item -Path HKLM:\Software -Name "Intel" -Force | Write-Verbose
    
            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES]
            New-Item -Path HKLM:\Software\Intel -Name "NETWORK_SERVICES" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES -Name "Sync" -Value "Sync" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES -Name "Timeout" -Value 3000 -PropertyType "dword"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\DMIX]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES -Name "DMIX" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\DMIX -Name "LCID" -Value "409" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\DMIX -Name "LocalLanguage" -Value "ENU" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\DMIX -Name "InstallDir" -Value "${OSdrive}Program Files\Intel\" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\DMIX -Name "ResDllName" -Value "${OSdrive}Program Files\Intel\DMIX\Resource\DMIXRes" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\DMIX -Name "TRACE" -Value 0 -PropertyType "dword"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES -Name "NCS2" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "LCID" -Value "409" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "InstallDir" -Value "${OSdrive}Program Files\Intel" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "ResourcePath" -Value "${OSdrive}Program Files\Intel\DMIX\Resource" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "TRACE" -Value 0 -PropertyType "dword"  | Write-Verbose
        
            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "Agents" -Force | Write-Verbose
 
            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents\AdapterAgnt]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents -Name "AdapterAgnt" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\AdapterAgnt -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\AdapterAgnt.dll" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents\BootAgnt]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents -Name "BootAgnt" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\BootAgnt -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\BootAgnt.dll" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents\CoreAgnt]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents -Name "CoreAgnt" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\CoreAgnt -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\CoreAgnt.dll" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\CoreAgnt -Name "Timeout" -Value "0" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\CoreAgnt -Name "ResourcePrefix" -Value "Core_" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents\DiagAgnt]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents -Name "DiagAgnt" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\DiagAgnt -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\DiagAgnt.dll" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\DiagAgnt -Name "ResourcePrefix" -Value "Diag_" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents\NcsCoLib]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents -Name "NcsCoLib" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\NcsCoLib -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\NcsCoLib.dll" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\NcsCoLib -Name "ResourcePrefix" -Value "Core_" -PropertyType "string"  | Write-Verbose
    
            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Agents\Rules]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents -Name "Rules" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\Rules -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\Rule.dll" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\Rules -Name "InstalledData" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\Rules.dat" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\Rules -Name "InstalledMap" -Value "${OSdrive}Program Files\Intel\NCS2\Agent\Rules.map" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Agents\Rules -Name "ResourcePrefix" -Value "Diag_" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Wmi]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2 -Name "Wmi" -Force | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi -Name "Providers" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers -Name "InstalledDir" -Value "${OSdrive}Program Files\Intel\NCS2\WMIProv" -PropertyType "string"  | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers -Name "Namespace" -Value "IntelNCS2" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers\Ncs2InstCore]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers -Name "Ncs2InstCore" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers\Ncs2InstCore -Name "ResDllName" -Value "${OSdrive}Program Files\Intel\NCS2\CommonRes" -PropertyType "string"  | Write-Verbose
    
            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers\Ncs2InstUtility]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers -Name "Ncs2InstUtility" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers\Ncs2InstUtility -Name "ResDllName" -Value "${OSdrive}Program Files\Intel\NCS2\CommonRes" -PropertyType "string"  | Write-Verbose

            #[HKEY_LOCAL_MACHINE\SOFTWARE\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers\Ncs2Prov]
            New-Item -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers -Name "Ncs2Prov" -Force | Write-Verbose
            New-ItemProperty -Path HKLM:\Software\Intel\NETWORK_SERVICES\NCS2\Wmi\Providers\Ncs2Prov -Name "ResDllName" -Value "${OSdrive}Program Files\Intel\NCS2\CommonRes" -PropertyType "string"  | Write-Verbose

            # Add DMIXSetpENU.reg then remove it
            AddRegistryFile "${OSdrive}Program Files\Intel\DMIX\DMIXSetpENU.reg"
            Write-Verbose "Deleting ${OSdrive}Program Files\Intel\DMIX\DMIXSetpENU.reg"
            Remove-Item "${OSdrive}Program Files\Intel\DMIX\DMIXSetpENU.reg"

            # Add OEMVer.reg then remove it
            AddRegistryFile "${OSdrive}Program Files\Intel\DMIX\OEMVer.reg" "Install"
            Write-Verbose "Deleting ${OSdrive}Program Files\Intel\DMIX\OEMVer.reg"
            Remove-Item "${OSdrive}Program Files\Intel\DMIX\OEMVer.reg"
        }
        catch {
            Write-Warning "Unable to complete modifications to system registry. Script cannot continue."
            Format-Exception($_) | Write-Error
        }

        # compile mof files and register provider
        try {
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICmLn.mof" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICoreLn.mof" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IDiagLn.mof" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IBootLn.mof" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICmEnu.mfl" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\ICoreEnu.mfl" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IDiagEnu.mfl" | Write-Verbose
            mofcomp "${OSdrive}Program Files\Intel\NCS2\WMIProv\MOF\IBootEnu.mfl" | Write-Verbose

            #register wmi provider
            regsvr32 "C:\Program Files\Intel\NCS2\WMIProv\ncs2provider.dll" /s

            # check success
            if ($lastexitcode -ne 0) {
                Write-Error "Provider registration failed"
            }
        }
        catch {
            Write-Warning "Unable to register the Intel(R) PROSet WMI provider"
            Format-Exception($_) | Write-Error
        }

        # run provider to update drivers for coinstaller
        try {
            Write-Host "Enumerating physical adapters...."
            $dump = Get-CimInstance -ClassName "IANet_PhysicalEthernetAdapter" -Namespace "root\Intelncs2"
            Write-Host "Done"
        }
        catch {
            Write-Warning "Unable to query for instances of IANet_PhysicalEthernetAdapter"
            Format-Exception($_) | Write-Error
        }

        # create and Start IPROSetMonitor service
        try {
            Write-Host "Enabling IPROSetMonitor service"
            $dump = New-Service -Name IPROSetMonitor.exe -BinaryPathName "${OSdrive}Windows\System32\IPROSetMonitor.exe" 
            $dump = Start-Service IPROSetMonitor.exe
            Write-Host "Done"
        }
        catch {
            Write-Warning "Unable to start IPROSetMonitor"
            Format-Exception($_) | Write-Error
        }

        Write-Verbose "OK"
    }
}

# ~ SCRIPT BEGIN ~
$ErrorActionPreference = "Stop"

# save input variables
$script:Err = $false
$script:Drive = "$($pwd.drive.name):\"

# $PSScriptRoot doesnt work on TP5, workaround:
$script:Root = Split-Path $script:MyInvocation.MyCommand.Path
$script:Root = $script:Root + '\'
$script:Root.Trimend('\') | Out-Null

Write-Verbose "script:Drive = ${script:Drive}"
Write-Verbose "script:Root = ${script:Root}"

# install
try {
    
    # verify PROSetNS.zip
    if (-not (Test-Path "${script:Root}PROSetNS.zip")) {
        Write-Error "PROSetNS.zip is missing cannot run script"
    }

    Write-Output "Installing..."

    # check prerequisites
    
        CreateDirectories $script:Drive
        InstallPROSetNS $script:Drive        
        Initialize $script:Drive
        Write-Output "Installation successful"
}    
catch {
        Write-Error $_.Exception
        Write-Output "Installation failed"
}
