Created
January 23, 2024 06:15
-
-
Save Still34/3b6184e1fb70b693a2f36e628fe65268 to your computer and use it in GitHub Desktop.
Lookup Win32 APIs from pwsh
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
# Made with <3 by Still/Azaka | |
# https://links.azaka.fun | |
#Requires -Module ps-menu | |
#Requires -Version 7 | |
$msftDocsCacheDir = [System.IO.Path]::Combine(($env:HOME ?? $env:USERPROFILE), '.msftdocs-cache') | |
function Update-MsDocsCache | |
{ | |
$win32Categories = "_ad", "_adam", "_rm", "_adsi", "_alljoyn", "_amsi", "_setup", "_recovery", "_audio", "_automat", "_bits", "_backup", "_battery", "_bltooth", "_bluetooth", "_cimfs", "_cimwin32", "_cloudapi", "_cos", "_com", "_cmpapi", "_coreaudio", "_fs", "_dedup", "_dataxchg", "_debug", "_dwm", "_devlic", "_winprog", "_deviceaccess", "_devinst", "_dlgbox", "_directmanipulation", "_direct2d", "_direct3d10", "_direct3d11", "_direct3d12", "_direct3d9", "_directcomp", "_directdraw", "_directml", "_directwrite", "_dxmath", "_display", "_dfs", "_msdtcwmi", "_dns", "_devtest", "_dxcore", "_direct3ddxgi", "_dhcp", "_enstor", "_etw", "_eventlogprov", "_eaphost", "_eap", "_cluswmi", "_clushyperv", "_fax", "_fsrm", "_gamemode", "_gamingdvcinfo", "_gdiplus", "_policy", "_gpmc", "_hcp", "_hidpi", "_direct3dhlsl", "_http", "_hid", "_hyperv", "_virtual", "_imapi", "_indexsrv", "_input_ink", "_input_feedback", "_input_sourceid", "_ifsk", "_input_intcontext", "_intl", "_iphlp", "_iscsidisc", "_iscsitarg", "_kernel", "_inputdev", "_lwef", "_ldap", "_winlocation", "_magapi", "_mib", "_menurc", "_htmlhelp", "_mmc", "_mf", "_mbn", "_mdmreg", "_mdmsettingsprov", "_monitor", "_mschap", "_madcap", "_nwifi", "_netbios", "_netshell", "_nap", "_ndf", "_netxp", "_netvista", "_nla", "_netmgmt", "_nps", "_of", "_windowssetupandmigration", "_opengl", "_oprec", "_ncd", "_appxpkg", "_opc", "_parcon", "_p2p", "_perf", "_pla", "_picacq", "_input_pointerdevice", "_inputmsg", "_powermeter", "_print", "_proc_snap", "_psapi", "_projfs", "_qos", "_input_radial", "_remoteassist", "_termserv", "_rdc", "_rpc", "_rstmgr", "_rras", "_security", "_winsensors", "_sensors", "_serports", "_smi", "_snmp", "_swdevice", "_spellcheck", "_storage", "_vdswmi", "_stream", "_stg", "_sens", "_sysmon", "_sr", "_base", "_tablet", "_tapi2", "_taskschd", "_tapi3", "_tspi", "_tsf", "_shell", "_win32_tile_badge_notif", "_tcui", "_toolhelp", "_input_touchhittest", "_input_touchinjection", "_wintouch", "_tbs", "_tracelogging", "_upnp", "_buses", "_ual", "_vhd", "_vstor", "_w_graph_fx", "_w_ui_comp", "_webdav", "_websock", "_whqlprov", "_wia", "_winstation", "_winauto", "_wab", "_winmsg", "_uianimation", "_secbiomet", "_mscs", "_wcs", "_wcn", "_wcm", "_wincontacts", "_controls", "_wdacwmiprov", "_wds", "_rdp", "_wer", "_wec", "_wes", "_fwp", "_ics", "_gdi", "_winhttp", "_wic", "_edp", "_msiprov", "_wininet", "_machinelearning", "_wmi_v2", "_wmi", "_wmdm", "_mapi", "_winmessenger", "_mixedreality", "_multimedia", "_wnv", "_wnet", "_properties", "_winrm", "_windowsribbon", "_winrt", "_search", "_wsb", "_winsock", "_wsl", "_winsync", "_winsat", "_wua", "_wsw", "_winlocation_com_ref", "_winsensors_com_ref", "_wlbsprov", "_nfswmi", "_wpdsdk", "_wpdauto", "_wibe", "_xaml_diagnostics", "_xaudio2", "_xblidp", "_xinput", "_ixhr2", "_xps", "winsvc", "processthreadsapi", "sysinfoapi", "console", "errhandlingapi",'winhttp', "memoryapi", 'winuser' | |
New-Item -ItemType Directory $msftDocsCacheDir -Force | |
$origin = @{} | |
$configs = [System.Collections.ArrayList]::new() | |
$jobId = 0 | |
foreach ($category in $win32Categories) | |
{ | |
$config = [PSCustomObject]@{ | |
Id = $jobId | |
Progress = @{} | |
Category = $Category | |
TargetPath = [System.IO.Path]::Combine($msftDocsCacheDir, "$Category.json") | |
} | |
$origin.($config.Id) = $config | |
$configs += $config | |
$jobId++; | |
} | |
$syncHashtable = [hashtable]::Synchronized($origin) | |
$jobs = $configs | ForEach-Object -AsJob -Parallel { | |
$syncConfig = $using:syncHashtable | |
$config = $PSItem | |
$process = $syncConfig[$config.Id].Progress | |
$process.Id = $config.Id | |
$process.Activity = "Downloading TOC for $($config.Category)" | |
$process.Status = "Downloading $($config.Category) to $($config.TargetPath)..." | |
Invoke-RestMethod "https://docs.microsoft.com/en-us/windows/win32/api/$($config.Category)/toc.json" -OutFile $config.TargetPath | |
$process.PercentComplete = 100 | |
$process.Completed = $true | |
} | |
while ($jobs.State -eq 'Running') | |
{ | |
$syncHashtable.Keys | Foreach-Object { | |
if (![string]::IsNullOrEmpty($syncHashtable.$_.Progress.Activity)) | |
{ | |
$param = $syncHashtable.$_.Progress | |
Write-Progress @param | |
} | |
} | |
Start-Sleep 0.1 | |
} | |
Write-Host "Finished updating MS docs TOC cache." | |
} | |
function Get-MsDocs | |
{ | |
param( | |
[string] | |
[Parameter(Mandatory = $true)] | |
[ValidateNotNullOrEmpty] | |
$Query, | |
[switch] | |
$Raw | |
) | |
begin | |
{ | |
if (-not (Test-Path $msftDocsCacheDir)) | |
{ | |
throw [System.IO.DirectoryNotFoundException]::new("Microsoft Docs cache has not been created yet. Run Update-MsDocsCache first!") | |
} | |
$baseUrl = "https://docs.microsoft.com/en-us/windows/win32/api/undefined_category" | |
} | |
process | |
{ | |
$searchMatches = (Get-ChildItem -Filter "*.json" -File -Path $msftDocsCacheDir | ForEach-Object -ThrottleLimit 8 -Parallel { | |
Write-Debug $_.FullName | |
$tocList = Get-Content $_.FullName | ConvertFrom-Json | |
$expandedChildren = $tocList | Select-Object -ExpandProperty items | Select-Object -ExpandProperty children | |
if ($expandedChildren | Get-Member -Name children -MemberType NoteProperty) | |
{ | |
$expandedChildren = $expandedChildren | Select-Object -ExpandProperty children | |
} | |
$expandedChildren | Where-Object { $_.toc_title -match $using:Query } | |
}) | |
if ($searchMatches.Length -eq 0) | |
{ | |
throw [System.Exception]::new("Matching docs not found.") | |
} | |
$finalUrl = '' | |
$path = '' | |
Write-Debug "Base URL: $baseUrl" | |
if ($searchMatches.Length -eq 1) | |
{ | |
$path = ($searchMatches[0] | Select-Object -exp href) | |
} | |
else | |
{ | |
Write-Host "Found multiple matches:" | |
$targetArticle = menu ($searchMatches | Select-Object -exp toc_title) | |
$path = $searchMatches | Where-Object { $_.toc_title -eq $targetArticle } | Select-Object -Unique | Select-Object -exp href | Select-Object -First 1 | |
} | |
if (-not $path.StartsWith('../')) | |
{ | |
$path = $path.Insert(0, '../../../..') | |
} | |
Write-Debug "Target path: $path" | |
$finalUrl = [System.IO.Path]::Combine($baseUrl, $path) | |
Write-Debug "Combined URL: $finalUrl" | |
} | |
end | |
{ | |
$finalUrl = $finalUrl.replace('\', '/') | |
Write-Debug "Formatted URL: $finalUrl" | |
if ([uri]::IsWellFormedUriString($finalUrl, [System.UriKind]::RelativeOrAbsolute) -and (-not [string]::IsNullOrEmpty($finalUrl))) | |
{ | |
Write-Debug "Final URL: $finalUrl" | |
$Raw ? (Write-Host $finalUrl) : (Start-Process $finalUrl) | |
} | |
else | |
{ | |
throw [System.UriFormatException]::new("$finalUrl is not a valid URI.") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment