#requires -version 2 function Get-NetShare { <# .SYNOPSIS Gets share information for a specified server. Author: @harmj0y License: BSD 3-Clause .DESCRIPTION This function will execute the NetShareEnum Win32API call to query a given host for open shares. This is a replacement for "net share \\hostname" .PARAMETER HostName The hostname to query for shares. .OUTPUTS SHARE_INFO_1 structure. A representation of the SHARE_INFO_1 result structure which includes the name and note for each share. .EXAMPLE > Get-NetShare Returns active shares on the local host. .EXAMPLE > Get-NetShare -HostName sqlserver Returns active shares on the 'sqlserver' host #> [CmdletBinding()] param( [string] $HostName = 'localhost' ) If ($PSBoundParameters['Debug']) { $DebugPreference = 'Continue' } # arguments for NetShareEnum $QueryLevel = 1 $ptrInfo = [IntPtr]::Zero $EntriesRead = 0 $TotalRead = 0 $ResumeHandle = 0 # get the share information $Result = $Netapi32::NetShareEnum($HostName, $QueryLevel,[ref]$ptrInfo,-1,[ref]$EntriesRead,[ref]$TotalRead,[ref]$ResumeHandle) # Locate the offset of the initial intPtr $offset = $ptrInfo.ToInt64() Write-Debug "Get-NetShare result: $Result" # 0 = success if (($Result -eq 0) -and ($offset -gt 0)) { # Work out how mutch to increment the pointer by finding out the size of the structure $Increment = $SHARE_INFO_1::GetSize() # parse all the result structures for ($i = 0; ($i -lt $EntriesRead); $i++){ # create a new int ptr at the given offset and cast # the pointer as our result structure $newintptr = New-Object system.Intptr -ArgumentList $offset $Info = $newintptr -as $SHARE_INFO_1 # return all the sections of the structure $Info | Select-Object * $offset = $newintptr.ToInt64() $offset += $increment } # free up the result buffer $Netapi32::NetApiBufferFree($ptrInfo) | Out-Null } else { switch ($Result) { (5) {Write-Debug 'The user does not have access to the requested information.'} (124) {Write-Debug 'The value specified for the level parameter is not valid.'} (87) {Write-Debug 'The specified parameter is not valid.'} (234) {Write-Debug 'More entries are available. Specify a large enough buffer to receive all entries.'} (8) {Write-Debug 'Insufficient memory is available.'} (2312) {Write-Debug 'A session does not exist with the computer name.'} (2351) {Write-Debug 'The computer name is not valid.'} (2221) {Write-Debug 'Username not found.'} (53) {Write-Debug 'Hostname could not be found'} } } } $Mod = New-InMemoryModule -ModuleName Win32 # all of the Win32 API functions we need $FunctionDefinitions = @( (func netapi32 NetShareEnum ([Int]) @([string], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])) ) # the NetShareEnum result structure $SHARE_INFO_1 = struct $Mod SHARE_INFO_1 @{ shi1_netname = field 0 String -MarshalAs @('LPWStr') shi1_type = field 1 UInt32 shi1_remark = field 2 String -MarshalAs @('LPWStr') } $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' $Netapi32 = $Types['netapi32']