Hello all. I'm using an API function via PInvoke, with the interesting data being returned to a pointer. My application crashes when attempting to free the pointer. If run with no breakpoints, the application hangs on Line 61 below. After the first run, it will then throw a memory exception whether run at full speed or stepping through.
Please look over the code below and point me in the right direction.
Thanks!
Imports System.Runtime.InteropServices
Module Module1
Partial Public Class PInvoke
' Have to use Pointer to return pathnames
' StringBuilder only returns first NULL-terminated string
<DllImportAttribute("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode, _
EntryPoint:="GetVolumePathNamesForVolumeNameW")> _
Public Shared Function _
GetMountPointsPtr(<[In]()> <MarshalAs(UnmanagedType.LPTStr)> _
ByVal sVolumeName As String, _
ByVal lpBuffer As IntPtr, _
ByVal uintBufferLen As UInteger, _
<Out()> ByRef uintReturnLen As UInteger) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
Sub Main()
ListMountPoints()
End Sub
' if no Volume GUID passed to sub, use the one corresponding to my USB stick
Private Sub ListMountPoints(Optional strVolumeName As String = _
"\\?\Volume{9a615499-414c-11e0-bd72-78e7d1722cbc}\")
Try
Dim uintBufferLen As UInteger = CUInt(IntPtr.Size)
Dim uintRequiredBufferLen As UInteger = 0
Dim Win32ErrVal As Integer = 0
Dim lpBuffer As IntPtr = Marshal.AllocHGlobal(IntPtr.Size)
' call function to get Required Buffer Length first
PInvoke.GetMountPointsPtr(strVolumeName, lpBuffer, uintBufferLen, uintRequiredBufferLen)
Win32ErrVal = Marshal.GetLastWin32Error()
If Win32ErrVal = 234 Then
'expected return value (ERROR_MORE_DATA), as our initial buffer is not large enough
ElseIf Win32ErrVal = 2 Then
' oops
MsgBox("File not found, invalid volume specified?")
Exit Sub
Else
Throw New ApplicationException("Exception getting required buffer size from GetMountPointsPtr")
End If
' reallocate the IntPtr with the right size
lpBuffer = Marshal.ReAllocHGlobal(lpBuffer, CType(uintRequiredBufferLen, IntPtr))
' now set the buffer length
uintBufferLen = uintRequiredBufferLen
'zero out the length indicator
uintRequiredBufferLen = 0
' reset errVal
Win32ErrVal = 0
If CBool(Not (PInvoke.GetMountPointsPtr(strVolumeName, lpBuffer, uintBufferLen, uintRequiredBufferLen))) Then
Throw New ApplicationException("Exception Occured @ line 51!")
End If
' retrieve the mountpoints(s)
Dim strOutput As String = Marshal.PtrToStringUni(lpBuffer, CInt(uintRequiredBufferLen))
'
' the app either hangs on FreeHGlobal or throws an exception
' (System Error Code 998, ERROR_NOACCESS, Invalid access to memory location.)
'
Marshal.FreeHGlobal(lpBuffer)
lpBuffer = IntPtr.Zero
Console.WriteLine(strVolumeName + " has the following mountpoints: " + vbCrLf + strOutput.ToString)
' on my system this produces the following output:
' "\\?\Volume{9a615499-414c-11e0-bd72-78e7d1722cbc}\ has the following mountpoints: _
' F:\ C:\mount\ D:\mount\"
Catch ex As Exception
' have to declare new errVal, Try block out of scope now?
Dim errVal As Integer = Marshal.GetLastWin32Error()
MsgBox(ex.Message + " The last Win32 error was: " + CStr(errVal))
End Try
End Sub
End Module