Search code examples
c#64-bitpinvoke

DllImport PathCanonicalize on 64bit causes memory corruption


I am trying to use the function PathCanonicalize using DllImport (PInvoke) on a 64 bit .NET assembly, and it causes memory corruption leading to all kinds bad behaviors (crash, exceptions out of nowhere, etc...). (For example : System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.)

    [DllImport("shlwapi", CharSet = CharSet.Auto, EntryPoint="PathCanonicalize", SetLastError = true)]
    private static extern bool PathCanonicalize( [Out] StringBuilder lpszDst,[In] string lpszSrc );

    public static string MyPathCanonicalize(string path)
    {
        StringBuilder builder = new StringBuilder();
        if (!PathCanonicalize(builder, path))
            return path;
        return builder.ToString();
    }

I saw in this thread that I should probably be using IntPtr instead of directly strings. Can anybody show me how to marshal those in the input and output strings in PathCanonicalize?

The prototype is:

BOOL PathCanonicalize(
  __out  LPTSTR lpszDst,
  __in   LPCTSTR lpszSrc
);

Solution

  • From the SDK documentation:

    lpszDst
    [out] A pointer to a string that receives the canonicalized path. You should set the size of this buffer to MAX_PATH to ensure that it is large enough to hold the returned string.

    Which you didn't do. Fix:

        StringBuilder builder = new StringBuilder(260);