Type a page name and press Enter. You'll jump to the page if it exists, or you can create it if it doesn't.
To create a page in a module other than kernel32, prefix the name with the module name and a period.
Updated: VB code now uses IntPtr instead of StringBuilder - see sample below
Using StringBuilder for the buffer does not work since this function returns the names as a bunch of strings separated by the null character ('\0'). So StringBuilder would only report the first item. Therefore we store it in a char array, which can later be converted to a bunch of strings.
Tips & Tricks:
Please add some!
Sample Code:
UInt32 dwRequired = 0;
char[] buffer = new char[260];
if (!GetVolumePathNamesForVolumeName(volumeName, buffer, (uint)buffer.Length, ref dwRequired))
{
// Not enough room in buffer perhaps? Try a bigger one
buffer = new char[dwRequired];
if (!GetVolumePathNamesForVolumeName(volumeName, buffer, (uint)buffer.Length, ref dwRequired))
throw new Win32Exception();
}
Sample Code 2:
public List<string> GetMountPointsForVolume(string volumeDeviceName)
{
List<string> result = new List<string>();
// GetVolumePathNamesForVolumeName is only available on Windows XP/2003 and above
int osVersionMajor = Environment.OSVersion.Version.Major;
int osVersionMinor = Environment.OSVersion.Version.Minor;
if (osVersionMajor < 5 || (osVersionMajor == 5 && osVersionMinor < 1))
{
return result;
}
if (!GetVolumePathNamesForVolumeNameW(volumeDeviceName, buffer, lpcchReturnLength, ref lpcchReturnLength))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
string[] mounts = buffer.Split('\0');
foreach (string mount in mounts)
{
if (mount.Length > 0)
{
result.Add(mount);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return result;
}
Sample VB.Net Code (.Net Framework 3.5sp1)
Imports System.Runtime.InteropServices
Private Sub ListMountPoints(Optional strVolumeName As String = "")
' if no Volume GUID passed to sub, use this one (corresponds to my USB stick)
If strVolumeName = "" Then
strVolumeName = "\\?\Volume{9a615499-414c-11e0-bd72-78e7d1722cbc}\"
End If
' make this a static in order to stop race condition/thread lock - suspect garbage collector
Static lpBuffer As IntPtr = Marshal.AllocHGlobal(1)
Dim uintBufferLen As UInteger = 0, uintBuffReqLen As UInteger = 0
Const ERROR_MORE_DATA = 234, ERROR_FILE_NOT_FOUND = 2
Dim retval As Boolean = False
Module Module1
Partial Public Class PInvoke
Try
' call function to get Required Buffer Length first
retval = Win32Methods.GetMountPointsIntPtr(strVolumeName, lpBuffer, uintBufferLen, uintBuffReqLen)
If Not retval Then
Dim errVal As Integer = Marshal.GetLastWin32Error()
If errVal = ERROR_MORE_DATA Then
'MsgBox("The last Win32 error was: ERROR_MORE_DATA")
ElseIf errVal = ERROR_FILE_NOT_FOUND Then
MsgBox("File not found, did you remember to plug in the USB drive?")
Exit Sub
Else
MsgBox("Error! The last Win32 error was: " + CStr(errVal))
End If
End If
' now set the buffer length
uintBufferLen = uintBuffReqLen
'zero out the length indicator
uintBuffReqLen = 0
' Have to use Pointer to return pathnames, StringBuilder only returns first NULL-terminated stgring
<DllImportAttribute("kernel32.dll", _
CharSet:=CharSet.Unicode, _
EntryPoint:="GetVolumePathNamesForVolumeNameW", _
SetLastError:=True)>
Public Shared Function GetMountPointsPtr(ByVal sVolumeName As String, _
ByVal lpBuffer As IntPtr, _
ByVal uintBufferLen As UInteger, _
ByRef uintReturnLen As UInteger) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
Catch ex As Exception
Dim errVal As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error()
MsgBox(ex.Message + ". The last Win32 error was: " + CStr(errVal))
End Try
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}\")
' now call the function again with the right buffer length
lpBuffer = Runtime.InteropServices.Marshal.ReAllocHGlobal(lpBuffer, CType(uintBuffReqLen, IntPtr))
' uintBufferLen = uintBuffReqLen
uintBuffReqLen = 0
Try
Dim uintBufferLen As UInteger = CUInt((IntPtr.Size) / 2)
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
Throw New ApplicationException("Invalid volume specified?")
Else
Throw New ApplicationException("Exception getting required buffer size.")
If CBool(Not (Win32Methods.GetMountPointsIntPtr(strVolumeName, lpBuffer, uintBufferLen, uintBuffReqLen))) Then
Dim errVal As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error()
MsgBox("The last Win32 error was: " + CStr(errVal))
End If
Catch ex As Exception
Dim errVal As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error()
MsgBox(ex.Message + ". The last Win32 error was: " + CStr(errVal))
End Try
' reallocate the IntPtr with the right size
lpBuffer = Marshal.ReAllocHGlobal(lpBuffer, CType(uintRequiredBufferLen * 2, IntPtr))
' now set the buffer length
uintBufferLen = uintRequiredBufferLen
'zero out the length indicator
uintRequiredBufferLen = 0
' reset errVal
Win32ErrVal = 0
Dim strOutput As String = Runtime.InteropServices.Marshal.PtrToStringUni(lpBuffer, CInt(uintBuffReqLen))
Dim tmp As Integer = InStr(strOutput, vbNullChar)
strOutput = Strings.Replace(strOutput, vbNullChar, vbCrLf, , , vbBinaryCompare)
' Free the buffer.
Runtime.InteropServices.Marshal.FreeHGlobal(lpBuffer)
lpBuffer = IntPtr.Zero
MsgBox(strVolumeName + vbCrLf + " has the following mountpoints: " + vbCrLf + strOutput.ToString)
If CBool(Not (PInvoke.GetMountPointsPtr(strVolumeName, lpBuffer, _
uintBufferLen, uintRequiredBufferLen))) Then
Throw New ApplicationException("Exception Occured @ line 54!")
End If
' retrieve the mountpoints(s)
Dim strOutput As String = Marshal.PtrToStringUni(lpBuffer, CInt(uintRequiredBufferLen))
If Not (CBool(lpBuffer = IntPtr.Zero)) Then
Marshal.FreeHGlobal(lpBuffer)
lpBuffer = IntPtr.Zero
End If
Console.WriteLine(strVolumeName + " has the following mountpoints: " _
+ vbCrLf + strOutput.ToString)
Catch ex As Exception
Dim errVal As Integer = Marshal.GetLastWin32Error()
Console.WriteLine(ex.Message + " The last Win32 error was: " + CStr(errVal))
End Try
End Sub
End Module
End Sub
Click to read this page
10/2/2011 2:35:57 AM - txzhgh-89.110.151.174
An IntPtr is a pointer to a memory location (unmanaged) that adapts to the platform it is running on (64-bit, etc.) UNLIKE a standard int/Integer. You should always use this type for unmanaged calls that require it, even though an int will appear to work on your development machine.
1/13/2008 4:00:13 AM - Damon Carr-72.43.165.29
Click to read this page
10/2/2011 2:35:57 AM - txzhgh-89.110.151.174
Click to read this page
10/2/2011 2:35:57 AM - txzhgh-89.110.151.174
Click to read this page
10/2/2011 2:35:57 AM - txzhgh-89.110.151.174
Please edit this page!
Do you have...
helpful tips or sample code to share for using this API in managed code?
corrections to the existing content?
variations of the signature you want to share?
additional languages you want to include?
Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).