title: Still getting duplicate token error after calling DuplicateTokenEx for impersonated token
body: <p>I'm trying to return a <code>Sytem.IntPtr</code> from a service call so that the client can use impersonation to call some code. My imersonation code works properly if not passing the token back from a WCF service. I'm not sure why this is not working. I get the following error: </p>
  
  <blockquote>
    <p>"Invalid token for impersonation - it cannot be duplicated."</p>
  </blockquote>
  
  <p>Here is my code that <em>does</em> work except when I try to pass the token back from a service to a WinForm C# client to then impersonate.</p>
  
  <pre><code>[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
  public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
  
  private IntPtr tokenHandle = new IntPtr(0);
  private IntPtr dupeTokenHandle = new IntPtr(0);
  
  [StructLayout(LayoutKind.Sequential)]
  public struct SECURITY_ATTRIBUTES
  {
      public int Length;
      public IntPtr lpSecurityDescriptor;
      public bool bInheritHandle;
  }
  
  
  
  public enum SecurityImpersonationLevel
  {
      SecurityAnonymous = 0,
      SecurityIdentification = 1,
      SecurityImpersonation = 2,
      SecurityDelegation = 3
  }
  
  public enum TokenType
  {
      TokenPrimary = 1,
      TokenImpersonation = 2
  }
  
  private const int MAXIMUM_ALLOWED = 0x2000000;
  
  
  [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
  public System.IntPtr GetWindowsUserToken(string UserName, string Password, string DomainName)
  {
  
      IntPtr tokenHandle = new IntPtr(0);
      IntPtr dupTokenHandle = new IntPtr(0);
  
      const int LOGON32_PROVIDER_DEFAULT = 0;
      //This parameter causes LogonUser to create a primary token.
      const int LOGON32_LOGON_INTERACTIVE = 2;
  
      //Initialize the token handle            
      tokenHandle = IntPtr.Zero;
  
      //Call LogonUser to obtain a handle to an access token for credentials supplied.
      bool returnValue = LogonUser(UserName, DomainName, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);        
  
      //Make sure a token was returned; if no populate the ResultCode and throw an exception:
      int ResultCode = 0;
      if (false == returnValue)
      {
          ResultCode = Marshal.GetLastWin32Error();
          throw new System.ComponentModel.Win32Exception(ResultCode, "API call to LogonUser failed with error code : " + ResultCode);
      }
  
      SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
      sa.bInheritHandle = true;
      sa.Length = Marshal.SizeOf(sa);
      sa.lpSecurityDescriptor = (IntPtr)0;
  
  
      bool dupReturnValue = DuplicateTokenEx(tokenHandle, MAXIMUM_ALLOWED, ref sa, (int)SecurityImpersonationLevel.SecurityDelegation, (int)TokenType.TokenImpersonation, ref dupTokenHandle);
  
      int ResultCodeDup = 0;
      if (false == dupReturnValue)
      {
          ResultCodeDup = Marshal.GetLastWin32Error();
          throw new System.ComponentModel.Win32Exception(ResultCode, "API call to DuplicateToken failed with error code : " + ResultCode);
      }
  
      //Return the user token
      return dupTokenHandle;
  
  }
  </code></pre>
  
  <p>Any idea if I'm not using the call to <code>DuplicateTokenEx</code> correctly? According to the MSDN documentation I read <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa446617%28v=vs.85%29.aspx" rel="nofollow">here</a> I should be able to create a token valid for delegation and use across the context on remote systems. When 'SecurityDelegation' is used, the server process can impersonate the client's security context on remote systems. </p>
  
  <p>Thanks!</p>