function Install-CertificationAuthority {
<#
.Synopsis
    Installs Active Directory Certificate Services role on local computer.
.Description
    Installs Active Directory Certificate Services (AD CS) role on local computer. A user can choose different options, such
	Certification Authority (CA) type, key pair parameters, CA certificate validity and so on.
	
	The command supports Windows Server 2008 R2 Server Core installations.
.Parameter CAName
    Specifies a custom CA certificate name/subject (what you see in the certificate display UI). If not passed, a '<ComputerName>-CA'
	form is used for workgroup CAs and '<DomainName>-<ComputerName-CA>' form is used for domain CAs. The parameter supports Unicode names.
.Parameter CADNSuffix
	Specifies a DN suffix to specify some additional information. For example, company name, country, city, etc. DN suffix is empty for
	workgroup CAs and includes current domain distinguished name (for example, DC=domain,DC=com). The parameter accepts suffixes in a
	X500 form, for example: OU=Information Systems, O=Sysadmins LV, C=LV.
.Parameter CAType
	Specifies CA type:
	
	Standalone Root,
	Standalone Subordinate,
	Enterprise Root,
	Enterprise Subordinate.
	
	If not passed, for non-domain environments or if you don't have Enterprise Admins rights, Standalone Root is used. If you have
	Enterprise Admins rights and your forest already has installed CAs, Enterprise Subordinate is used. If no Enterprise CAs installed
	in the forest, Enterprise Root is used.
.Parameter ParentCA
	This parameter allows you to specify parent CA location only if you install Enterprise Subordinate CA. For other CA types, the
	parameter is ignored. Parent CA information must be passed in the following form: CAComputerName\CASanitizedName. Sanitized name
	is a sanitized form of CA name (subject). Mostly sanitized name is the same as CA name (unless you use Unicode and/or special
	characters, that are disallowed in X500). If the parameter is not specified, a certificate request will be generated on the root
	of system drive. I've decided to not implement this parameter for Standalone Subordinate CAs, because mostly they are installed
	in a workgroup environments and direct request submission to other CAs is likely unavailable (due of computer authentication
	complexity in the non-domain environments). However, if you need it — contact me.
.Parameter CSP
	Specifies custom cryptographic service provider. By default 'RSA#Microsoft Software Key Storage Provider' is used (in most cases
	you will use default CSP). You need to explicitly specify custom CSP only when you setup completely CNG authority (CSPs with ECDSA
	prefix) or you use HSM. Each HSM uses it's own custom CSP. You must install HSM middleware before CA installation.

	The full list of supportable and available "by default" CSPs for Windows Server 2008+ is:

	Microsoft Base Cryptographic Provider v1.0
	Microsoft Base DSS Cryptographic Provider
	Microsoft Base Smart Card Crypto Provider
	Microsoft Enhanced Cryptographic Provider v1.0
	Microsoft Strong Cryptographic Provider
	RSA#Microsoft Software Key Storage Provider
	DSA#Microsoft Software Key Storage Provider
	ECDSA_P256#Microsoft Software Key Storage Provider
	ECDSA_P384#Microsoft Software Key Storage Provider
	ECDSA_P521#Microsoft Software Key Storage Provider
	RSA#Microsoft Smart Card Key Storage Provider
	ECDSA_P256#Microsoft Smart Card Key Storage Provider
	ECDSA_P384#Microsoft Smart Card Key Storage Provider
	ECDSA_P521#Microsoft Smart Card Key Storage Provider
.Parameter KeyLength
	This parameter specifies the key length. If not specified, a 2048-bit key will be generated. There is a little trick: if you look to
	a CSP list (above), you will see that key length is specified for each ECDSA* provider. I've developed a script logic in that way,
	so the script ignores this parameter if one of ECDSA* CSP is explicitly chosen and uses key length that is supported by the CSP.
	Therefore you will not receive an error if you select 'ECDSA_P256#Microsoft Smart Card Key Storage Provider' CSP with 2048 key length.
	256-bit key will be selected automatically
.Parameter HashAlgorithm
	This parameter specifies hash algorithm that will be used for CA certificate/request hashing. Note that this is important for root
	CA installations. Subordinate CA certificates are hashed and signed by the parent CA with it's own settings. By default 'SHA1' is
	used (though this parameter is applicable for all CA installation types).
.Parameter ValidForYears
	Specifies the validity for root CA installations. By default root CA certificates are valid for 5 years. You can increase this value
	to 10, 20, 50, whatever you need. For any subordinate CA types this parameter is silently ignored. This is because subordinate CA
	validity is determined by the parent CA. This parameter accepts integer values, assuming that the value is specified in years.
.Parameter RequestFileName
	If you setup any sort of subordinate (not root) CAs you can specify custom path to a request file. By default request file is
	generated on the root of system drive.
.Parameter CACertFile
	Specifies the path to a PFX file with CA certificate. Relative paths are allowed. Setup API performs additional checks for the certificate.
	Therefore you must ensure if: this is CA certificate (but not EFS encryption ;)), CA certificate is trusted (for non-root certificates)
	and chains to trusted CA and CA certificate revocation checking can be performed. Otherwise you will unable to setup CA with that CA certificate.
.Parameter Password
	Specifies the password to open PFX file. The parameter supports only securestrings! You can't type a password as a simple text. This is made for
	security reasons. There are few ways to pass a password in a securestring form:

	$Password = Read-Host –a
	
	or

	ConvertTo-SecureString <plaintext> –a –f
	
	You can enclose last command in parentheses and pass directly as a parameter value.
.Parameter Thumbprint
	specifies a thumbprint of the certificate to use. The certificate must be installed in Local Machine\Personal store and must be trusted
	(for non-root certificates) and must not be revoked (the issuer revocation information must be available).
.Parameter DBDirectory
	Specifies the path to a folder to store CA database. If not specified, the default path: %windir%\System32\CertLog folder is used. If you
	need to specify custom path (for example, shared storage for CA clusters), you need to specify the next parameter too. The path must be valid.
.Parameter LogDirectory
	Specifies the path to a folderto store CA database log files. By default %windir%\System32\CertLog folder is used. If you use custom path for
	either database or log folders, you must explicitly specify both paths.
.Parameter OverwriteExisting
	Specifies, whether to overwrite any existing database files in the specified directories.
.Parameter AllowCSPInteraction
	Specifies, whether the cryptographic service provider (CSP) is allowed to interact with the desktop. This parameter should be used only if you
	use custom hardware-based CSP (HSM or smart card CSP). In other cases you don't need to allow CSP interactions.
.Parameter Force
	By default, the script explicitly prompts you whether you want to install Certification Authority with selected values. If you want to implement
	silent (quiet) installations — specify this parameter to suppress any prompts during role installation
.EXAMPLE
	PS > Install-CertificationAuthority -CAName "My Root CA" -CADNSuffix "OU=Information Systems, O=Sysadmins LV, C=LV" `
	-CAType "Standalone Root" -ValidForYears 10


	In this scenario you setup new Standalone Root CA with "CN=My Root CA, OU=Information Systems, O=Sysadmins LV, C=LV" subject, that will be valid
	for 10 years. The CA will use default paths to CA database and log files and certificate will use 'RSA#Microsoft Software Key Storage Provider'
	CSP with 2048-bit key and SHA1 hashing algorithm.
.EXAMPLE
	PS > Install-CertificationAuthority -CAName "My Root CA" -CADNSuffix "OU=Information Systems, O=Sysadmins LV, C=LV" `
	-CAType "Standalone Root" -ValidForYears 20 -CSP "ECDSA_P256#Microsoft Smart Card Key Storage Provider" `
	-HashAlgorithm SHA512

	This example is similar to previous, with the exception that this CA will be completely CNG/SHA2 root. CA certificate will use CNG (not RSA)
	keys and hashing algorithm will be SHA512.
.EXAMPLE
	PS > Install-CertificationAuthority -CAName "Clustered CA" -CADNSuffix "OU=Information Systems, O=Sysadmins LV, C=LV" `
	-CAType "Enterprise Subordinate" -KeyLength 4096 -DBDirectory "S:\CertDB" -LogDirectory "S:\CertLog" `
	-RequestFileName "S:\Clustered CA.req"

	This example assumes that you setup CA cluster first node (but not necessary). CA database will be stored on a shared storage (attached with S: drive letter).
	CA certificate will use default 'RSA#Microsoft Software Key Storage Provider' with 4096-bit key and default SHA1 hashing algorithm. CA certificate validity
	will be determined by the parent CA. In addition, CA certificate request will be stored on the shared storage.
.EXAMPLE
	PS > $Password = Read-Host -AsSecureString
	PS > Install-CertificationAuthority -CACertFile .\ClusteredCA.pfx -Password $Password `
	-DBDirectory "S:\CertDB" -LogDirectory "S:\CertLog" -OverwriteExisting

	This is two-line example. Say, you have successfully installed CA cluster first node and have exported CA certificate to a PFX, and moved it to the second
	node (to the current directory). At first you will be prompted for a password. Since you type password to a securestring prompt, no characters will be displayed.
	After that you will specify relative path to a PFX file and specify shared storage to store CA database and log files. You overwrite database files that was
	created during first node installation. Actually this command installs CA cluster second node.
.EXAMPLE
	PS > Install-CertificationAuthority -CAName "Company Enterprise CA-2" -CADNSuffix "O=Company, E=companypky@company.com" `
	-CAType "Enterprise Subordinate" -ParentCA "ca01.company.com\Company Enterprise CA-1"

	From best-practices perspective this is not a very good example, because it assumes at least 2 tiers of Enterprise CAs. However, it is still common. In a given
	example, Enterprise Subordinate CA will be installed and certificate request will be sent directly to existing Enterprise CA — 'Company Enterprise CA-1' that is
	hosted on 'ca01.company.com'. Note that existing CA must be online and must issue 'Subordinate Certification Authority' template.
.Inputs
	None.
.Outputs
	None.
.NOTES
	Author: Vadims Podans
	Blog  : http://en-us.sysadmins.lv
#>
[CmdletBinding(
	DefaultParameterSetName = 'NewKeySet',
	ConfirmImpact = 'High',
	SupportsShouldProcess = $true
)]
	param(
		[Parameter(ParameterSetName = 'NewKeySet')]
		[string]$CAName,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[string]$CADNSuffix,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[ValidateSet("Standalone Root","Standalone Subordinate","Enterprise Root","Enterprise Subordinate")]
		[string]$CAType,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[string]$ParentCA,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[string]$CSP,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[int]$KeyLength,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[string]$HashAlgorithm,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[int]$ValidForYears = 5,
		[Parameter(ParameterSetName = 'NewKeySet')]
		[string]$RequestFileName,
		[Parameter(Mandatory = $true, ParameterSetName = 'PFXKeySet')]
		[IO.FileInfo]$CACertFile,
		[Parameter(Mandatory = $true, ParameterSetName = 'PFXKeySet')]
		[Security.SecureString]$Password,
		[Parameter(Mandatory = $true, ParameterSetName = 'ExistingKeySet')]
		[string]$Thumbprint,
		[string]$DBDirectory,
		[string]$LogDirectory,
		[switch]$OverwriteExisting,
		[switch]$AllowCSPInteraction,
		[switch]$Force
	)

#region OS and existing CA checking
	# check if script running on Windows Server 2008 or Windows Server 2008 R2
	$OS = Get-WmiObject Win32_OperatingSystem -Property ProductType
	if ([Environment]::OSVersion.Version.Major -lt 6) {
		Write-Error -Category NotImplemented -ErrorId "NotSupportedException" `
		-Message "Windows XP, Windows Server 2003 and Windows Server 2003 R2 are not supported!"
		return
	}
	if ($OS.ProductType -eq 1) {
		Write-Error -Category NotImplemented -ErrorId "NotSupportedException" `
		-Message "Client operating systems are not supported!"
		return
	}
	$CertConfig = New-Object -ComObject CertificateAuthority.Config
	try {$ExistingDetected = $CertConfig.GetConfig(3)}
	catch {}
	if ($ExistingDetected) {
		Write-Error -Category ResourceExists -ErrorId "ResourceExistsException" `
		-Message "Certificate Services are already installed on this computer. Only one Certification Authority instance per computer is supported."
		return
	}
	
#endregion

#region Binaries checking and installation if necessary
	if ([Environment]::OSVersion.Version.Major -eq 6 -and [Environment]::OSVersion.Version.Minor -eq 0) {
		cmd /c "servermanagercmd -install AD-Certificate 2> null" | Out-Null
	} else {
		try {Import-Module ServerManager -ErrorAction Stop}
		catch {
			ocsetup 'ServerManager-PSH-Cmdlets' /quiet | Out-Null
			Start-Sleep 1
			Import-Module ServerManager -ErrorAction Stop
		}
		$status = (Get-WindowsFeature -Name AD-Certificate).Installed
		# if still no, install binaries, otherwise do nothing
		if (!$status) {$retn = Add-WindowsFeature -Name AD-Certificate -ErrorAction Stop
			if (!$retn.Success) {
				Write-Error -Category NotInstalled -ErrorId "NotInstalledException" `
				-Message "Unable to install ADCS installation packages due of the following error: $($retn.breakCode)"
				return
			}
		}
	}
	try {$CASetup = New-Object -ComObject CertOCM.CertSrvSetup.1}
	catch {
		Write-Error -Category NotImplemented -ErrorId "NotImplementedException" `
		-Message "Unable to load necessary interfaces. Your Windows Server operating system is not supported!"
		return
	}
	# initialize setup binaries
	try {$CASetup.InitializeDefaults($true, $false)}
	catch {
		Write-Error -Category InvalidArgument -ErrorId ParameterIncorrectException `
		-ErrorAction Stop -Message "Cannot initialize setup binaries!"
	}
#endregion

#region Property enums
	$CATypesByName = @{"Enterprise Root" = 0; "Enterprise Subordinate" = 1; "Standalone Root" = 3; "Standalone Subordinate" = 4}
	$CATypesByVal = @{}
	$CATypesByName.keys | ForEach-Object {$CATypesByVal.Add($CATypesByName[$_],$_)}
	$CAPRopertyByName = @{"CAType"=0;"CAKeyInfo"=1;"Interactive"=2;"ValidityPeriodUnits"=5;
		"ValidityPeriod"=6;"ExpirationDate"=7;"PreserveDataBase"=8;"DBDirectory"=9;"Logdirectory"=10;
		"ParentCAMachine"=12;"ParentCAName"=13;"RequestFile"=14;"WebCAMachine"=15;"WebCAName"=16
	}
	$CAPRopertyByVal = @{}
	$CAPRopertyByName.keys | ForEach-Object {$CAPRopertyByVal.Add($CAPRopertyByName[$_],$_)}
	$ValidityUnitsByName = @{"years" = 6}
	$ValidityUnitsByVal = @{6 = "years"}
#endregion
	$ofs = ", "
#region Key set processing functions

#region NewKeySet
function NewKeySet ($CAName, $CADNSuffix, $CAType, $ParentCA, $CSP, $KeyLength, $HashAlgorithm, $ValidForYears, $RequestFileName) {

#region CSP, key length and hashing algorithm verification
	$CAKey = $CASetup.GetCASetupProperty(1)
	if ($CSP -ne "") {
		if ($CASetup.GetProviderNameList() -notcontains $CSP) {
			# TODO add available CSP list
			Write-Error -Category InvalidArgument -ErrorId "InvalidCryptographicServiceProviderException" `
			-ErrorAction Stop -Message "Specified CSP '$CSP' is not valid!"
		} else {
			$CAKey.ProviderName = $CSP
		}
	} else {
		$CAKey.ProviderName = "RSA#Microsoft Software Key Storage Provider"
	}
	if ($KeyLength -ne 0) {
		if ($CASetup.GetKeyLengthList($CSP).Length -eq 1) {
			$CAKey.Length = $CASetup.GetKeyLengthList($CSP)[0]
		} else {
			if ($CASetup.GetKeyLengthList($CSP) -notcontains $KeyLength) {
				Write-Error -Category InvalidArgument -ErrorId "InvalidKeyLengthException" `
				-ErrorAction Stop -Message @"
The specified key length '$KeyLength' is not supported by the selected CSP '$CSP' The following
key lengths are supported by this CSP: $($CASetup.GetKeyLengthList($CSP))
"@
			}
			$CAKey.Length = $KeyLength
		}
	}
	if ($HashAlgorithm -ne "") {
		if ($CASetup.GetHashAlgorithmList($CSP) -notcontains $HashAlgorithm) {
				Write-Error -Category InvalidArgument -ErrorId "InvalidHashAlgorithmException" `
				-ErrorAction Stop -Message @"
The specified hash algorithm is not supported by the selected CSP '$CSP' The following
hash algorithms are supported by this CSP: $($CASetup.GetHashAlgorithmList($CSP))
"@
		}
		$CAKey.HashAlgorithm = $HashAlgorithm
	}
	$CASetup.SetCASetupProperty(1,$CAKey)
#endregion

#region Setting CA type
	if ($CAType) {
		$SupportedTypes = $CASetup.GetSupportedCATypes()
		$SelectedType = $CATypesByName[$CAType]
		if ($SupportedTypes -notcontains $CATypesByName[$CAType]) {
			Write-Error -Category InvalidArgument -ErrorId "InvalidCATypeException" `
			-ErrorAction Stop -Message @"
Selected CA type: '$CAType' is not supported by current Windows Server installation.
The following CA types are supported by this installation: $([int[]]$CASetup.GetSupportedCATypes() | %{$CATypesByVal[$_]})
"@
		} else {$CASetup.SetCASetupProperty($CAPRopertyByName.CAType,$SelectedType)}
	}
#endregion

#region setting CA certificate validity
	if ($SelectedType -eq 0 -or $SelectedType -eq 3 -and $ValidForYears -ne 0) {
		try{$CASetup.SetCASetupProperty(6,$ValidForYears)}
		catch {
			Write-Error -Category InvalidArgument -ErrorId "InvalidCAValidityException" `
			-ErrorAction Stop -Message "The specified CA certificate validity period '$ValidForYears' is invalid."
		}
	}
#endregion

#region setting CA name
	if ($CAName -ne "") {
		if ($CADNSuffix -ne "") {$Subject = "CN=$CAName" + ",$CADNSuffix"} else {$Subject = "CN=$CAName"}
		$DN = New-Object -ComObject X509Enrollment.CX500DistinguishedName
		# validate X500 name format
		try {$DN.Encode($Subject,0x0)}
		catch {
			Write-Error -Category InvalidArgument -ErrorId "InvalidX500NameException" `
			-ErrorAction Stop -Message "Specified CA name or CA name suffix is not correct X.500 Distinguished Name."
		}
		$CASetup.SetCADistinguishedName($Subject, $true, $true, $true)
	}
#endregion

#region set parent CA/request file properties
	if ($CASetup.GetCASetupProperty(0) -eq 1 -and $ParentCA) {
		[void]($ParentCA -match "^(.+)\\(.+)$")
		try {$CASetup.SetParentCAInformation($ParentCA)}
		catch {
			Write-Error -Category ObjectNotFound -ErrorId "ObjectNotFoundException" `
			-ErrorAction Stop -Message @"
The specified parent CA information '$ParentCA' is incorrect. Make sure if parent CA
information is correct (you must specify existing CA) and is supplied in a 'CAComputerName\CASanitizedName' form.
"@
		}
	} elseif ($CASetup.GetCASetupProperty(0) -eq 1 -or $CASetup.GetCASetupProperty(0) -eq 4 -and $RequestFileName -ne "") {
		$CASetup.SetCASetupProperty(14,$RequestFileName)
	}
#endregion
}

#endregion

#region PFXKeySet
function PFXKeySet ($CACertFile, $Password) {
	$FilePath = Resolve-Path $CACertFile -ErrorAction Stop
	try {[void]$CASetup.CAImportPFX(
		$FilePath.Path,
		[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)),
		$true)
	} catch {Write-Error $_ -ErrorAction Stop}
}
#endregion

#region ExistingKeySet
function ExistingKeySet ($Thumbprint) {
	$ExKeys = $CASetup.GetExistingCACertificates() | ?{
		([Security.Cryptography.X509Certificates.X509Certificate2]$_.ExistingCACertificate).Thumbprint -eq $Thumbprint
	}
	if (!$ExKeys) {
		Write-Error -Category ObjectNotFound -ErrorId "ElementNotFoundException" `
		-ErrorAction Stop -Message "The system cannot find a valid CA certificate with thumbprint: $Thumbprint"
	} else {$CASetup.SetCASetupProperty(1,@($ExKeys)[0])}
}
#endregion

#endregion

#region set database settings
	if ($DBDirectory -ne "" -and $LogDirectory -ne "") {
		try {$CASetup.SetDatabaseInformation($DBDirectory,$LogDirectory,$null,$OverwriteExisting)}
		catch {
			Write-Error -Category InvalidArgument -ErrorId "InvalidPathException" `
			-ErrorAction Stop -Message "Specified path to either database directory or log directory is invalid."
		}
	} elseif ($DBDirectory -ne "" -and $LogDirectory -eq "") {
		Write-Error -Category InvalidArgument -ErrorId "InvalidPathException" `
		-ErrorAction Stop -Message "CA Log file directory cannot be empty."
	} elseif ($DBDirectory -eq "" -and $LogDirectory -ne "") {
		Write-Error -Category InvalidArgument -ErrorId "InvalidPathException" `
		-ErrorAction Stop -Message "CA database directory cannot be empty."
	}

#endregion
	# process parametersets.
	switch ($PSCmdlet.ParameterSetName) {
		"ExistingKeySet" {ExistingKeySet $Thumbprint}
		"PFXKeySet" {PFXKeySet $CACertFile $Password}
		"NewKeySet" {NewKeySet $CAName $CADNSuffix $CAType $ParentCA $CSP $KeyLength $HashAlgorithm $ValidForYears $RequestFileName}
	}
	try {
		Write-Host "Installing Certification Authority role on $env:computername ..." -ForegroundColor Cyan
		if ($Force -or $PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Install Certification Authority")) {
			$CASetup.Install()
			$PostRequiredMsg = @"
Certification Authority role was successfully installed, but not completed. To complete installation submit
request file '$($CASetup.GetCASetupProperty(14))' to parent Certification Authority
and install issued certificate by running the following command: certutil -installcert 'PathToACertFile'
"@
			if ($CASetup.GetCASetupProperty(0) -eq 1 -and $ParentCA -eq "") {
				Write-Host $PostRequiredMsg -ForegroundColor Yellow -BackgroundColor Black
			} elseif ($CASetup.GetCASetupProperty(0) -eq 1 -and $PSCmdlet.ParameterSetName -eq "NewKeySet" -and $ParentCA -ne "") {
				$CASName = (Get-ItemProperty HKLM:\System\CurrentControlSet\Services\CertSvc\Configuration).Active
				$SetupStatus = (Get-ItemProperty HKLM:\System\CurrentControlSet\Services\CertSvc\Configuration\$CASName).SetupStatus
				$RequestID = (Get-ItemProperty HKLM:\System\CurrentControlSet\Services\CertSvc\Configuration\$CASName).RequestID
				if ($SetupStatus -ne 1) {
					Write-Host $PostRequiredMsg -ForegroundColor Yellow -BackgroundColor Black
				}
			} elseif ($CASetup.GetCASetupProperty(0) -eq 4) {
				Write-Host $PostRequiredMsg -ForegroundColor Yellow -BackgroundColor Black
			} else {Write-Host "Certification Authority role is successfully installed!" -ForegroundColor Green}
		}
	} catch {Write-Error $_ -ErrorAction Stop}
	Remove-Module ServerManager -ErrorAction SilentlyContinue
}

function Uninstall-CertificationAuthority {
<#
.Synopsis
    Uninstalls Active Directory Certificate Services role from the local computer.
.Description
    Uninstalls Active Directory Certificate Services role from the local computer.
	
	The command supports Windows Server 2008 R2 Server Core installations.
.Parameter AutoRestart
    Automatically restarts computer to complete CA role removal. Otherwise you will have to restart the server manually.
.Parameter Force
	By default, the commands prompts you whether you want to remove CA role. Use –Force switch to suppress all prompts.
.EXAMPLE
	PS > Uninstall-CertificationAuthority -AutoRestart -Force

	The command will uninstall CA role, suppresses all prompts and automatically restarts the server upon completion.
.Inputs
	None.
.Outputs
	None.
.NOTES
	Author: Vadims Podans
	Blog  : http://en-us.sysadmins.lv
#>
[CmdletBinding(
	ConfirmImpact = 'High',
	SupportsShouldProcess = $true
)]
	param(
		[switch]$AutoRestart,
		[switch]$Force
	)

#region OS and existing CA checking
	# check if script running on Windows Server 2008 or Windows Server 2008 R2
	$OS = Get-WmiObject Win32_OperatingSystem -Property ProductType
	if ([Environment]::OSVersion.Version.Major -lt 6) {
		Write-Error -Category NotImplemented -ErrorId "NotSupportedException" `
		-Message "Windows XP, Windows Server 2003 and Windows Server 2003 R2 are not supported!"
		return
	}
	if ($OS.ProductType -eq 1) {
		Write-Error -Category NotImplemented -ErrorId "NotSupportedException" `
		-Message "Client operating systems are not supported!"
		return
	}
	$CertConfig = New-Object -ComObject CertificateAuthority.Config
    try {$ExistingDetected = $CertConfig.GetConfig(3)}
    catch {
        Write-Error -Category ObjectNotFound -ErrorId "ElementNotFoundException" `
        -ErrorAction Stop -Message "Certificate Services are not installed on this computer."
    }

#endregion

#region Binaries checking and removal stuff
	try {$CASetup = New-Object -ComObject CertOCM.CertSrvSetup.1}
	catch {
		Write-Error -Category NotImplemented -ErrorId "NotImplementedException" `
		-Message "Unable to load necessary interfaces. Your Windows Server operating system is not supported!"
		return
	}
	if ([Environment]::OSVersion.Version.Major -eq 6 -and [Environment]::OSVersion.Version.Minor -eq 0) {
		cmd /c "servermanagercmd -remove ADCS-Cert-Authority 2> null" | Out-Null
	} else {
		try {Import-Module ServerManager -ErrorAction Stop}
		catch {
			ocsetup 'ServerManager-PSH-Cmdlets' /quiet | Out-Null
			Start-Sleep 2
			Import-Module ServerManager
		}
		$status = (Get-WindowsFeature -Name ADCS-Cert-Authority).Installed
		if ($status) {
			$WarningPreference = "SilentlyContinue"
			if ($Force -or $PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Uninstall Certification Authority")) {
				$CASetup.PreUninstall($false)
				$retn = Remove-WindowsFeature -Name ADCS-Cert-Authority -ErrorAction Stop
			}
		}
	}
	if ($AutoRestart) {
		#Restart-Computer -Force
	} else {
		Write-Host "Certification Authority role was removed successfully. You must restart this server to complete role removal." `
		-ForegroundColor Yellow -BackgroundColor Black
	}
#endregion
}
