DHCPClient.psm1

<#
.SYNOPSIS
Gets an array of DHCP options for a DHCP-enabled network adapter.
 
.DESCRIPTION
The Get-DHCPOptions cmdlet retrieves the DHCP options from the registry for each DHCP-enabled network adapter. (Note that this registry information and format is subject to change.)
 
.PARAMETER Vendor
An optional flag indicating that vendor-specific DHCP options should return.
 
.EXAMPLE
Get-DHCPOptions
 
.EXAMPLE
Get-DHCPOptions -Vendor
#>

Function Get-DHCPOptions() {

    [cmdletbinding()]
    param
    (
            [Parameter(Mandatory=$false)] [Switch]$Vendor = $false
    )

    Process {

        #Iterate through NIC's with IP obtained via DHCP
        $objWin32NAC = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -namespace "root\CIMV2" -computername "." -Filter "IPEnabled = 'True' AND DHCPEnabled ='True'" 
        foreach ($objNACItem in $objWin32NAC) 
        {
            #Read DHCP options
            $DhcpInterfaceOptions = (Get-ItemProperty -Path ("HKLM:\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\{0}" -f $objNACItem.SettingID) -Name DhcpInterfaceOptions).DhcpInterfaceOptions
            $DhcpOptions = @(); for ( $i = 0 ; $i -lt 256; $i++ ) { $DhcpOptions += @("") }
            $DhcpVendorSpecificOptions = @(); for ( $i = 0 ; $i -lt 256; $i++ ) { $DhcpVendorSpecificOptions += @("") }
    
            #Iterate through DHCP options
            $intPosition = 0
            while ($intPosition -lt $DhcpInterfaceOptions.length) 
            {
                #Read Dhcp code
                $DhcpOptionCode = $DhcpInterfaceOptions[$intPosition]
                $intPosition = $intPosition + 8 #shift 8 bytes
        
                #Read length
                $DhcpOptionLength = $DhcpInterfaceOptions[$intPosition]
                $intPosition = $intPosition + 4 #shift 4 bytes
        
                #Is this a vendor specific option?
                $DhcpIsVendorSpecific = $DhcpInterfaceOptions[$intPosition]
                $intPosition = $intPosition + 4 #shift 4 bytes
        
                #Read "unknown data"
                $DhcpUnknownData = ""
                for ($i=0; $i -lt 4; $i++) { $DhcpUnknownData = $DhcpUnknownData + $DhcpInterfaceOptions[$intPosition + $i] }
                $intPosition = $intPosition + 4 #shift 4 bytes
        
                #Read value
                if (($DhcpOptionLength % 4) -eq 0) {$DhcpOptionBytesToRead = ($DhcpOptionLength - ($DhcpOptionLength % 4))} else {$DhcpOptionBytesToRead = ($DhcpOptionLength - ($DhcpOptionLength % 4)+4)}
                $DhcpOptionValue = New-Object Byte[] $DhcpOptionBytesToRead
                for ($i=0; $i -lt $DhcpOptionLength; $i++) { $DhcpOptionValue[$i] = $DhcpInterfaceOptions[$intPosition + $i] }
                $intPosition = $intPosition + $DhcpOptionBytesToRead #shift the number of bytes read
        
                #Add option to (vendor specific) array
                if ($DhcpIsVendorSpecific -eq 0)
                {
                    $DhcpOptions[$DhcpOptionCode] = $DhcpOptionValue
                } else {
                    $DhcpVendorSpecificOptions[$DhcpOptionCode] = $DhcpOptionValue
                }
            }
        }

        if ($Vendor)
        {
            return $DhcpVendorSpecificOptions
        }
        else
        {
            return $DhcpOptions
        }
    }
}

<#
.SYNOPSIS
Gets the value of a particular DHCP option, in string format.
 
.DESCRIPTION
The Get-DHCPOptionString cmdlet retrieves the value of a specific DHCP option, converted to a string.
 
.PARAMETER Vendor
An optional flag indicating that vendor-specific DHCP options should return.
 
.PARAMETER OptionID
The specific DHCP option to retrieve.
 
.EXAMPLE
Get-DHCPOptionString -OptionID 101
 
.EXAMPLE
Get-DHCPOptions -Vendor -Optionid 234
 
#>

Function Get-DHCPOptionString() {

    [cmdletbinding()]
    param
    (
            [Parameter(Mandatory=$false)] [Switch]$Vendor = $false,
            [Parameter(Mandatory=$true)] $OptionID
    )

    Process    {
        $Encode = New-Object "System.Text.ASCIIEncoding"
        if ($vendor)
        {
            $options = Get-DHCPOptions -Vendor
        }
        else
        {
            $options = Get-DHCPOptions
        }
        return $Encode.GetString($options[$OptionID])
    }
}

$tzMap = @{
    "America/Anchorage" = "Alaskan Standard Time";
    "America/Chicago" = "Central Standard Time";
    "America/Denver" = "Mountain Standard Time";
    "America/Los_Angeles" = "Pacific Standard Time";
    "America/New_York" = "Eastern Standard Time";
    "Asia/Jerusalem" = "Israel Standard Time";
    "Asia/Shanghai" = "China Standard Time";
    "Asia/Singapore" = "Singapore Standard Time";
    "Asia/Tokyo" = "Tokyo Standard Time";
    "Australia/Sydney" = "AUS Eastern Standard Time";
    "Europe/Berlin" = "W. Europe Standard Time";
    "Europe/Helsinki" = "FLE Standard Time";
    "Europe/London" = "GMT Standard Time";
    "Europe/Moscow" = "Russian Standard Time";
    "Europe/Paris" = "Romance Standard Time";
    "Europe/Warsaw" = "Central European Standard Time";
    "Pacific/Honolulu" = "Hawaiian Standard Time"
}


<#
.SYNOPSIS
Gets the Windows time zone corresponding to the DHCP TZ option 101 value (TCODE), as described in https://tools.ietf.org/html/rfc4833.
 
.DESCRIPTION
The Get-DHCPTimeZone cmdlet translates the DHCP TCODE values, from the time zone database at https://www.iana.org/time-zones, into a Windows time zone id value, as used by the Set-TimeZone cmdlet.
 
.EXAMPLE
Get-DHCPTimeZone
#>

Function Get-DHCPTimeZone() {

    [cmdletbinding()]
    param
    (
    )

    Begin {
        Start-Process -FilePath "$PSScriptRoot\DHCPClient_TZ.exe" -Wait -WindowStyle hidden
        }

    Process {
        $dhcpTimeZone = Get-DHCPOptionString -OptionID 101
        if ($tzMap[$dhcpTimeZone])
        {
            return $tzMap[$dhcpTimeZone]
        }
        else
        {
            # Return a valid but unexpected value when we do not find a match
            return "Arab Standard Time"
        }        
    }
}