Skip to content

Instantly share code, notes, and snippets.

@secabstraction
Created September 26, 2015 17:56
Show Gist options
  • Save secabstraction/0a988a664ffc8421c578 to your computer and use it in GitHub Desktop.
Save secabstraction/0a988a664ffc8421c578 to your computer and use it in GitHub Desktop.
A powershell wrapper around QueryDosDevice
function Get-DosDevice {
[CmdletBinding()]
Param (
[Parameter()]
[ValidateNotNullOrEmpty()]
[String]$Name
)
#region WinAPI
function local:Get-DelegateType {
Param (
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
$TypeBuilder.CreateType()
}
function local:Get-ProcAddress {
Param (
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]$Procedure
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
$GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
#Function QueryDosDevice
$QueryDosDeviceAAddr = Get-ProcAddress kernel32.dll QueryDosDeviceA
$QueryDosDeviceADelegate = Get-DelegateType @([String], [IntPtr], [Int32]) ([Int32])
$QueryDosDeviceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($QueryDosDeviceAAddr, $QueryDosDeviceADelegate)
#endregion WinAPI
if(!$PSBoundParameters.Name) {
$BufferSize = 4096
$TargetPath = [Runtime.InteropServices.Marshal]::AllocHGlobal($BufferSize)
while (($Length = $QueryDosDeviceA.Invoke([Management.Automation.Language.NullString]::Value, $TargetPath, $BufferSize)) -eq 0) {
$TargetPath = [Runtime.InteropServices.Marshal]::ReAllocHGlobal($TargetPath, ($BufferSize += 1024))
}
$ReturnedStrings = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($TargetPath, $Length)
[Runtime.InteropServices.Marshal]::FreeHGlobal($TargetPath)
$Devices = ($ReturnedStrings.TrimEnd("`0")).Split("`0")
}
else { $Devices = $Name }
$BufferSize = 256
$TargetPath = [Runtime.InteropServices.Marshal]::AllocHGlobal($BufferSize)
foreach ($Device in $Devices) {
$StringLength = $QueryDosDeviceA.Invoke($Device, $TargetPath, $BufferSize)
$ReturnedDevice = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($TargetPath)
$Properties = @{
Name = $Device
Device = $ReturnedDevice
}
New-Object -TypeName PSObject -Property $Properties
}
[Runtime.InteropServices.Marshal]::FreeHGlobal($TargetPath)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment