Public/Get-WindowsDeviceLinkFirmwareState.ps1
|
function Get-WindowsDeviceLinkFirmwareState { <# .SYNOPSIS Reads local Windows DeviceLink firmware state. .DESCRIPTION Reads the Windows Autopilot Device Preparation Device Association UEFI variables from the local device without returning sensitive raw contents. The cmdlet works in full Windows and AMD64 Windows PE when firmware access is available. It enables SeSystemEnvironmentPrivilege in the current process and returns presence, size, and Win32 error information for each known variable. DeviceLinkCreationTimeUtc has been validated as a UTF-8 ISO-8601 UTC timestamp. Observed valid forms include whole seconds (for example 2026-09-06T12:22:51Z) and fractional seconds (for example 2026-09-15T07:48:22.972Z). For this variable only, the safe decoded timestamp is returned as DecodedValue and ParsedUtc. Raw DeviceLinkId and DeviceLinkJwtCompressed values are intentionally never returned. DeviceLinkJwtCompressed contains sensitive association data. .OUTPUTS PSCustomObject. One object is returned per known DeviceLink firmware variable. .EXAMPLE Get-WindowsDeviceLinkFirmwareState Reads the four known DeviceLink UEFI variables and returns safe metadata plus the decoded DeviceLinkCreationTimeUtc timestamp when present and valid. .EXAMPLE Get-WindowsDeviceLinkFirmwareState | Format-Table Name,Present,Size,DecodedValue,LastError Displays a compact DeviceLink firmware-state overview. .NOTES Current validated UEFI namespace: {B3DE75DA-819C-4FD5-9F01-C3D49E8CBBD7} Current validated variables: DeviceLinkId DeviceLinkJwtCompressed DeviceLinkJwtLastWrite DeviceLinkCreationTimeUtc #> [CmdletBinding()] param() Initialize-WindowsDeviceLinkFirmware $namespace = '{B3DE75DA-819C-4FD5-9F01-C3D49E8CBBD7}' $variables = @( 'DeviceLinkId', 'DeviceLinkJwtCompressed', 'DeviceLinkJwtLastWrite', 'DeviceLinkCreationTimeUtc' ) $environment = if (Test-Path -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\MiniNT') { 'WindowsPE' } else { 'Windows' } foreach ($name in $variables) { $buffer = New-Object byte[] 65536 $size = [WindowsDeviceLink.FirmwareNative]::GetFirmwareEnvironmentVariable( $name, $namespace, $buffer, $buffer.Length ) $lastError = if ($size -eq 0) { [Runtime.InteropServices.Marshal]::GetLastWin32Error() } else { $null } $decodedValue = $null $parsedUtc = $null if ($size -gt 0 -and $name -eq 'DeviceLinkCreationTimeUtc') { $candidate = [Text.Encoding]::UTF8.GetString($buffer, 0, [int]$size) # Keep the accepted firmware representation deliberately narrow: UTC ISO-8601 # with whole seconds or 1-7 fractional-second digits. Use TryParse rather than # the string[] TryParseExact overload because the latter did not parse the # observed fractional form reliably in Windows PowerShell 5.1 / WinPE. if ($candidate -match '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,7})?Z$') { $parsed = [DateTimeOffset]::MinValue if ([DateTimeOffset]::TryParse( $candidate, [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::AssumeUniversal -bor [Globalization.DateTimeStyles]::AdjustToUniversal, [ref]$parsed )) { $decodedValue = $candidate $parsedUtc = $parsed.UtcDateTime } } } [pscustomobject]@{ PSTypeName = 'Windows.DeviceLink.FirmwareState' Environment = $environment Namespace = $namespace Name = $name Present = ($size -gt 0) Size = [int]$size DecodedValue = $decodedValue ParsedUtc = $parsedUtc LastError = $lastError } } } |