It is my understanding (and please correct me if I\'m wrong) that the only difference between them is whether the string might be modified by the called function. (PCWSTR ,
A function taking a PCWSTR
parameter can't use that parameter to modify the characters of the string, unlike a function that takes a LPWSTR
parameter. Each character of the string is stored as WCHAR
.
UnmanagedType.LPWStr
is the right marshalling type for such a string.
PCWSTR is a time anachronism, dinosaur-and-humans movie style. Finding a 16-bit program that uses short pointers on a Unicode string is like finding a white elephant. Only the distinct between LPCWSTR and LPWSTR is meaningful.
The C in LPCWSTR is simply annotation for const, a C language keyword. It promises that the called function never modifies the string that you pass. Which is very important to know in that language, it is not safe to pass a string literal to a LPWSTR argument. That is very likely to crash the program when it tries to update the string and fails because the memory page is read-only.
And it matters when you pinvoke. Passing a System.String to a LPCWSTR argument is fine, strings are immutable in .NET so you'll get a guarantee that an interned string literal isn't going to get mangled. A very hard to diagnose problem. Using [MarshalAs(UnmanagedType.LPWStr)]
explicitly should not be necessary in general, you'd use the CharSet.Auto property in the [DllImport] attribute and get the LPWStr marshaling for free.
But if the argument type is LPWSTR then you must pass a StringBuilder instead. With a sufficient Capacity to allow the native code to poke around in the builder buffer to write the string.