Win32Interop icon indicating copy to clipboard operation
Win32Interop copied to clipboard

Kernel32.GetVolumePathName() incorrectly marshalls strings

Open olivierdagenais opened this issue 10 years ago • 0 comments

Consider the following wrapper:

internal static string GetVolumePathName(string fileName)
{
    const int length = 256;
    var sb = new StringBuilder(length);
    var success = Kernel32.GetVolumePathName(fileName, sb, length);
    if (!success)
    {
        var exceptionForHr = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
        throw new Exception("Unable to determine volume path name", exceptionForHr);
    }
    var s = sb.ToString();
    return s;
}

...using it, I get results like "ã©£\".

Your signature current looks like:

[DllImport("kernel32.dll", EntryPoint = "GetVolumePathName")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetVolumePathName(
    [In] [MarshalAs(UnmanagedType.LPTStr)] string lpszFileName, [Out] [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszVolumePathName,
    uint cchBufferLength);

...but if you either take out [MarshalAs(UnmanagedType.LPTStr)] from the lpszVolumePathName parameter OR you add CharSet = CharSet.Unicode to the DllImport attribute, I get results as I expect them.

I'm on Windows 7 in 64 bits.

olivierdagenais avatar May 26 '14 15:05 olivierdagenais