title: Managed to unmanaged code call causes access violation... sometimes
body: <p>This code causes the following exception, <em>sometimes</em>:</p>
  
  <blockquote>
    <p>"Attempted to read or write protected
    memory. This is often an indication
    that other memory is corrupt"</p>
  </blockquote>
  
  <pre><code>private static TOKEN_GROUPS GetTokenGroups(IntPtr tokenHandle)
  {
      var groups = new TOKEN_GROUPS();
      uint tokenInfoLength = 0;
      uint returnLength;
  
      var res = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero,
                                    tokenInfoLength, out returnLength);
  
      if (!res &amp;&amp; returnLength &gt; 0)
      {
          tokenInfoLength = returnLength;
          var tokenInfo = Marshal.AllocHGlobal((int) tokenInfoLength);
          res = GetTokenInformation(tokenHandle,
                                    TOKEN_INFORMATION_CLASS.TokenGroups,
                                    tokenInfo,
                                    tokenInfoLength,
                                    out returnLength);
          if(res)
          {
              groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInfo, typeof (TOKEN_GROUPS));
          }
  
          Marshal.FreeHGlobal(tokenInfo);
          CloseHandle(tokenHandle);
      }
      else
      {
          var error = new Win32Exception(Marshal.GetLastWin32Error());
          _log.WarnFormat("Failed evaluate the call to get process token information. {0}", error.Message);
      }
      return groups;
  }
  </code></pre>
  
  <p>The line that fails is <code>groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInfo, typeof (TOKEN_GROUPS));</code> I would say the exception happens in 1 and every 20 calls to this method. Once it begins happening every call afterwards will throw the exception. Restarting the process causes the error to go away. </p>
  
  <p><code>IntPtr tokenHandle</code> is the result of:</p>
  
  <pre><code>var processId = GetCurrentProcess();
  
              _log.InfoFormat("Process ID [{0}]", processId.ToString());
  
              if (processId != IntPtr.Zero)
              {
                  IntPtr tokenHandle;
                  if (OpenProcessToken(processId, TOKEN_READ, out tokenHandle))
                  {
                      groups = GetTokenGroups(tokenHandle);
                  }
  </code></pre>
  
  <p><strong>EDIT</strong> Hopefully this isn't information overload but here's the pinvoke declarations:</p>
  
  <pre><code>     struct TOKEN_GROUPS
      {
          public uint GroupCount;
          [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4000)]
          public SID_AND_ATTRIBUTES[] Groups;
      }
  
      [StructLayout(LayoutKind.Sequential)]
      struct SID_AND_ATTRIBUTES
      {
          public IntPtr SID;
          public uint Attributes;
      }
  
      [DllImport("advapi32.dll", SetLastError = true)]
      static extern bool GetTokenInformation(
          IntPtr TokenHandle,
          TOKEN_INFORMATION_CLASS TokenInformationClass,
          IntPtr TokenInformation,
          uint TokenInformationLength,
          out uint ReturnLength);
  
      [DllImport("advapi32.dll", SetLastError = true)]
      [return: MarshalAs(UnmanagedType.Bool)]
      static extern bool OpenProcessToken(IntPtr ProcessHandle,
          UInt32 DesiredAccess, out IntPtr TokenHandle);
  
      [DllImport("kernel32.dll")]
      static extern IntPtr GetCurrentProcess();
  
      enum TOKEN_INFORMATION_CLASS
      {
          TokenUser = 1,
          TokenGroups,
          TokenPrivileges,
          TokenOwner,
          TokenPrimaryGroup,
          TokenDefaultDacl,
          TokenSource,
          TokenType,
          TokenImpersonationLevel,
          TokenStatistics,
          TokenRestrictedSids,
          TokenSessionId,
          TokenGroupsAndPrivileges,
          TokenSessionReference,
          TokenSandBoxInert,
          TokenAuditPolicy,
          TokenOrigin
      }
  </code></pre>