Created
July 11, 2023 22:27
-
-
Save Bill-Stewart/ae21669dedbd4d5d11fbba62baf9dd1b to your computer and use it in GitHub Desktop.
Get-Message.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Get-Message.ps1 | |
# Written by Bill Stewart (bstewart AT iname.com) | |
# Version history: | |
# | |
# 0.1.0 (2023-07-11) | |
# * Initial version. | |
#requires -version 3 | |
<# | |
.SYNOPSIS | |
Gets the Windows message string for a specified message ID number. | |
.DESCRIPTION | |
Gets the Windows message string for a specified message ID number. A Windows message ID can be a 32-bit value, where the high (most significant) 16 bits are a "facility code" and the low (least significant) 16 bits are the Windows message ID. The Windows message string is obtained by providing the low 16 bits of the Windows message ID number to the FormatMessageW API. | |
.PARAMETER MessageID | |
Specifies the message ID number. This parameter must be in the range -2147483648 to 2147483647 (i.e., a 32-bit signed integer). A larger value can be passed as a hex value (e.g., 0x80070035 rather than 2147942453). | |
.OUTPUTS | |
Objects with the following properties: | |
* ID_Dec_Signed - Message ID as a signed decimal 32-bit value | |
* ID_Dec_Unsigned Message ID as an unsigned decimal 32-bit value | |
* ID_Hex - Message ID as a hexadecimal value | |
* LowWord_Dec - Low 16 bits of message ID (decimal) | |
* LowWord_Hex - Low 16 bits of message ID (hex) | |
* Message - Message string (if found) | |
.EXAMPLE | |
PS C:\> Get-Message -2147024843 | |
This command converts the signed decimal value to unsigned decimal value 2147942453, which is hex 0x80070035. The low 16 bits of this value is 0x35 (decimal 53), which corresponds to the English message string "The network path was not found." | |
.EXAMPLE | |
PS C:\> Get-Message 1325 | |
Message ID 1325 is hex 0x052D, which corresponds to the English message string "Unable to update the password. The value provided for the new password does not meet the length, complexity, or history requirements of the domain." | |
.EXAMPLE | |
PS C:\> Get-Message 0x57 | |
Message ID 0x57 is decimal code 87, which corresponds to the English message string "The parameter is incorrect." | |
.LINK | |
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessagew | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory,ValueFromPipeline)] | |
[Int[]] | |
$MessageID | |
) | |
begin { | |
# Windows API constants | |
$LOAD_LIBRARY_AS_DATAFILE = 0x00000002 | |
$FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100 | |
$FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200 | |
$FORMAT_MESSAGE_FROM_HMODULE = 0x00000800 | |
$FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 | |
# C# P/Invoke | |
$APIDefs = @" | |
// [B4E431E4639B4B6680D2827F8EEF8ED2.Win32API]::LoadLibraryExW() | |
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern IntPtr LoadLibraryExW( | |
string lpLibFileName, | |
IntPtr hFile, | |
uint dwFlags); | |
// [B4E431E4639B4B6680D2827F8EEF8ED2.Win32API]::FormatMessageW() | |
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern int FormatMessageW( | |
uint dwFlags, | |
IntPtr lpSource, | |
int dwMessageId, | |
int dwLanguageId, | |
ref IntPtr lpBuffer, | |
int nSize, | |
IntPtr[] Arguments); | |
// [B4E431E4639B4B6680D2827F8EEF8ED2.Win32API]::FreeLibrary() | |
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern bool FreeLibrary( | |
IntPtr hLibModule | |
); | |
// [B4E431E4639B4B6680D2827F8EEF8ED2.Win32API]::LocalFree() | |
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern IntPtr LocalFree(IntPtr hMem); | |
"@ | |
Add-Type -Name Win32API ` | |
-MemberDefinition $APIDefs ` | |
-Namespace "B4E431E4639B4B6680D2827F8EEF8ED2" ` | |
-ErrorAction Stop | |
$Win32API = [B4E431E4639B4B6680D2827F8EEF8ED2.Win32API] | |
function Get-Low16Bits { | |
param( | |
$value | |
) | |
$bytes = [BitConverter]::GetBytes($value) | |
(($bytes[1] -as [Int]) -shl 8) -bor $bytes[0] | |
} | |
function Get-WindowsMessage { | |
param( | |
[Int] | |
$messageID | |
) | |
$fullMessageID = [BitConverter]::ToUInt32([BitConverter]::GetBytes($messageID),0) | |
$messageID = Get-Low16Bits $fullMessageID | |
$flags = $FORMAT_MESSAGE_ALLOCATE_BUFFER -bor | |
$FORMAT_MESSAGE_IGNORE_INSERTS -bor | |
$FORMAT_MESSAGE_FROM_SYSTEM | |
$hMod = [IntPtr]::Zero | |
if ( ($fullMessageID -ge 2100) -and ($fullMessageID -lt 2999) ) { | |
$flags = $flags -bor $FORMAT_MESSAGE_FROM_HMODULE | |
$hMod = $Win32API::LoadLibraryExW("netmsg.dll", # lpLibFileName | |
[IntPtr]::Zero, # hFile | |
$LOAD_LIBRARY_AS_DATAFILE) # dwFlags | |
} | |
if ( ($fullMessageID -ge 12000) -and ($fullMessageID -le 12176) ) { | |
$flags = $flags -bor $FORMAT_MESSAGE_FROM_HMODULE | |
$hMod = $Win32API::LoadLibraryExW("wininet.dll", # lpLibFileName | |
[IntPtr]::Zero, # hFile | |
$LOAD_LIBRARY_AS_DATAFILE) # dwFlags | |
} | |
$message = $null | |
$pBuf = [IntPtr]::Zero | |
$numChars = $Win32API::FormatMessageW($flags, # dwFlags | |
$hMod, # lpSource | |
$messageID, # dwMessageId | |
0, # dwLanguageId | |
[ref] $pBuf, # lpBuffer | |
0, # nSize | |
[IntPtr]::Zero) # Arguments | |
if ( $numChars -gt 0 ) { | |
$message = ([Runtime.InteropServices.Marshal]::PtrToStringAuto($pBuf)).Trim() -replace '\r\n',' ' | |
[Void] $Win32API::LocalFree($pBuf) | |
} | |
if ( $hMod -ne [IntPtr]::Zero ) { | |
[Void] $Win32API::FreeLibrary($hMod) | |
} | |
[PSCustomObject] @{ | |
"ID_Dec_Signed" = [BitConverter]::ToInt32([BitConverter]::GetBytes($fullMessageID),0) | |
"ID_Dec_Unsigned" = $fullMessageID | |
"ID_Hex" = "0x{0:X8}" -f $fullMessageID | |
"LowWord_Dec" = $messageID | |
"LowWord_Hex" = "0x{0:X4}" -f $messageID | |
"Message" = $message | |
} | |
} | |
} | |
process { | |
foreach ( $MessageIDItem in $MessageID ) { | |
Get-WindowsMessage $MessageIDItem | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment