Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

GetVolumePathNamesForVolumeName (kernel32)
 
.
Summary
Retrieves a list of path names for the specified volume name.

C# Signature:

[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetVolumePathNamesForVolumeNameW(string lpszVolumeName,
        char [] lpszVolumePathNames, uint cchBuferLength,
        ref UInt32 lpcchReturnLength);

C# Signature 2:

[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetVolumePathNamesForVolumeNameW(
        [MarshalAs(UnmanagedType.LPWStr)]
        string lpszVolumeName,
        [MarshalAs(UnmanagedType.LPWStr)]
        string lpszVolumePathNames,
        uint cchBuferLength,
        ref UInt32 lpcchReturnLength);

VB Signature:

Declare Function GetVolumePathNamesForVolumeName Lib "kernel32.dll" (TODO) As TODO

VB Signature #2:

Imports System.Runtime.InteropServices

Partial Public Class Win32Methods

'''Return Type: BOOL->int
'''param0: LPCTSTR->LPCWSTR->WCHAR*
'''param1: LPTSTR->LPWSTR->WCHAR*
'''param2: DWORD->unsigned int
'''param3: PDWORD->DWORD*
  <DllImportAttribute("kernel32.dll", _
    SetLastError:=True, _
    EntryPoint:="GetVolumePathNamesForVolumeNameW")> _
  Public Shared Function GetVolumePathNamesForVolumeNameW(
                               <[In]()> <MarshalAs(UnmanagedType.LPTStr)>
                                ByVal sVolumeName As String, _
                                <MarshalAs(UnmanagedType.LPWStr)> _
                                ByVal lpBuffer As IntPtr, _
                                ByVal uintBufferLen As UInteger, _
                                <Out()> ByRef uintReturnLen As UInteger) _
                             As <MarshalAs(UnmanagedType.Bool)> Boolean
  End Function

End Class

User-Defined Types:

None.

Alternative Managed API:

Do you know one? Please contribute it!

Notes:

The VB Code was generated by the tool at http://clrinterop.codeplex.com/releases/view/14120. I believe this to be the same tool referenced at http://blogs.msdn.com/b/vbteam/archive/2008/03/14/making-pinvoke-easy.aspx. The StringBuilder limitation appears to apply to this code as well, and it will only return the first path/mountpoint found, but the method does work inside that limitation. I will post updated code as soon as I code and test.

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.

S.M.
The first C# signature would not work for me. I would get an ERROR_INVALID_PARAMETER error. The second signature works with the second example below.

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;
        }

        try
        {
        uint lpcchReturnLength = 0;
        string buffer = "";

        GetVolumePathNamesForVolumeNameW(volumeDeviceName, buffer, (uint)buffer.Length, ref lpcchReturnLength);
        if (lpcchReturnLength == 0)
        {
            return result;
        }

        buffer = new string(new char[lpcchReturnLength]);

        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)

  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

    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

    Catch ex As Exception
        Dim errVal As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error()
        MsgBox(ex.Message + ". The last Win32 error was: " + CStr(errVal))
    End Try

    ' now call the function again with the right buffer length
    lpBuffer = Runtime.InteropServices.Marshal.ReAllocHGlobal(lpBuffer, CType(uintBuffReqLen, IntPtr))
    ' uintBufferLen = uintBuffReqLen
    uintBuffReqLen = 0
    Try
        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

    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)

  End Sub

Documentation

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).

 
Access PInvoke.net directly from VS:
Terms of Use
Find References
Show Printable Version
Revisions