(1) Show the definition of ReadName. What is happening inside it?
(2) What is a wstring in your non-C# code? Surely it's not a C++ std::wstring, because you're exporting it as C code. You need to give more details, but I think this is the main problem.
A common way to do this is to pass a pre-allocated char/wide-char buffer to the DLL function instead of returning a C++ string. On the C# side you can use a StringBuilder.
Dealing with memory/pointers between unmanaged land and managed land is tricky.
I don't suggest using _wcsdup because if I'm not mistaken, you're basically creating a memory leak each time you call ReadName, since you can't free the memory from the C# side.
Again, I would have a parameter in ReadName that is a pre-allocated buffer on the C# side, that way you aren't allocating any memory within ReadName.
But for your current code, to convert the pointer from C++ to a proper C# string, you need to use a function like PtrToStringAuto, which takes in the pointer (the wchar_t* on the C++ side).