title: pin_ptr & PtrToStringChars vs. StringToHGlobalAnsi: Why does PtrToStringChars var loose its value?
body: <p>I am using C++/CLI and I want to call the function <code>WNetAddConnection2</code> from Windows Networking.<br>
  <em>First, I know that C++/CLI is not the language of choice for my work, but I have no possibility to change that right now and e.g. use C# instead.</em></p>
  
  <p>The problem now is, that this function takes wchar_t*, so I need to convert System::String^ to wchar_t*.<br>
  Solution 1): use <code>pin_ptr</code> and <code>PtrToSTringChars</code> from <code>vcclr.h</code><br>
  Solution 2): use <code>StringToHGlobalUni</code>. (The title mentions <code>StringHToGlobalAnsi</code> because more people are searching for that so they might find this post and it's answers faster).</p>
  
  <p>I have found out that both solutions work. But #1 does not really. I have put the WNet-functions into a ref class <code>CWNetShare</code> with following constructor:  </p>
  
  <pre><code>CWNetShare::CWNetShare (String^ i_sLocalDrive, ...) {
    pin_ptr&lt;const wchar_t&gt; wszTemp;
    wszTemp = PtrToStringChars(i_sLocalDrive);
    m_wszLocalDrive = const_cast&lt;wchar_t*&gt;(wszTemp);
  </code></pre>
  
  <p>where <code>m_wszLocalDrive</code> is a private <code>CWNetShare</code> member of type <code>wchar_t*</code>.  </p>
  
  <p>The real problem: while calling the constructor by <code>m_oWNetShare = gcnew CWNetShare</code> from a Winform class constructor (I know, C++/CLI and Winforms...), everything seems fine. The string <code>i_sLocalDrive</code> and others are converted and assigned correctly. But when accessing <code>m_oWNetShare</code> later, the values in all m_wsz... variables are lost. It looks like the object was moved around by the GC.<br>
  Therefore I have made a test:</p>
  
  <pre><code>ref class CManaged {
  public:
    wchar_t* m_wszNothing;
    wchar_t* m_wszPinned;
    wchar_t* m_wszMarshal;
    System::String^ m_sTest;
  
    CManaged ()
    {
      m_sTest = "Hello";
      m_wszNothing = L"Test";
  
      pin_ptr&lt;const wchar_t&gt; wszTemp;
      wszTemp = PtrToStringChars(m_sTest);
      m_wszPinned = const_cast&lt;wchar_t*&gt;(wszTemp);
      m_wszMarshal = static_cast&lt;wchar_t*&gt;(System::Runtime::InteropServices::Marshal::StringToHGlobalUni (m_sTest).ToPointer());
    }
  };
  </code></pre>
  
  <p>Again a winform with <code>m_oManaged = gcnew CManaged;</code> in its constructor. When accessing m_oManaged later, then if m_oManaged was not moved, <code>m_wszPinned</code> is ok.<br>
  <img src="https://i.stack.imgur.com/2TkFs.png" alt="enter image description here"><br>
  But after GCing, it's showing nonsense. BUT m_wsznothing keeps it's value, so it's not a problem of <code>wchar_t*</code>, but of the pin_ptr somehow. The address of <code>m_oManaged</code> has changed, but the address of <code>m_wszPinned</code> is the same, so why is the value lost then?<br>
  <img src="https://i.stack.imgur.com/IP6sj.png" alt="enter image description here">  </p>
  
  <p>What is going wrong here?<br>
  Does pin_ptr and PtrToSTringChars have a use at all then?</p>
  
  <p>I'm using marshalling now, which works.</p>