@msdn=http://search.microsoft.com/search/results.aspx?qu=$$$ @pinvoke=http://pinvoke.net/$$$.htm 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); !!!!C# Signature 3: [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetVolumePathNamesForVolumeName(string lpszVolumeName, char[] lpszVolumePathNames, uint cchBuferLength, out 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 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 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 @ 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 Documentation: GetVolumePathNamesForVolumeName@msdn on MSDN
Edit kernel32.getvolum...
You do not have permission to change this page. If you feel this is in error, please send feedback with the contact link on the main page.