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

GetVolumePathName (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)

  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", _
                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

    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) / 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.")
        End If

        ' 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

        If CBool(Not (PInvoke.GetMountPointsPtr(strVolumeName, lpBuffer, _
                            uintBufferLen, uintRequiredBufferLen))) Then
        Throw New ApplicationException("Exception Occured invoking GetMountPointsPtr()!")
        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

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
Edit This Page
Find References
Show Printable Version
Revisions