title: Move file onto network share (via impersonation) C#
body: <p>I have been working on a project in C# (.net4). Project pretty much allows people to upload files from their local machine to a network share.</p>
  
  <p>Network share is secured. It is only accessible by user called "proxy" which is created in active directory.</p>
  
  <p>I did some research and I found this class which I used for impersonation.</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Runtime.InteropServices;
  using System.Security.Principal;
  
  namespace Datacom.CorporateSys.Utilities
  {
      public class ImpersonateUser
      {
          [DllImport("advapi32.dll")]
          public static extern int LogonUserA(String lpszUserName,
              String lpszDomain,
              String lpszPassword,
              int dwLogonType,
              int dwLogonProvider,
              ref IntPtr phToken);
          [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          public static extern int DuplicateToken(IntPtr hToken,
              int impersonationLevel,
              ref IntPtr hNewToken);
  
          [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          public static extern bool RevertToSelf();
  
          [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
          public static extern bool CloseHandle(IntPtr handle);
  
          WindowsImpersonationContext impersonationContext;
  
          public const int LOGON32_LOGON_INTERACTIVE = 2;
          public const int LOGON32_PROVIDER_DEFAULT = 0;
          private string p;
          private string p_2;
          private string p_3;
  
  
          private String UserName
          {
              set;
              get;
          }
  
          private String Domain
          {
              set;
              get;
          }
  
          private String Password
          {
              set;
              get;
          }
  
          /// &lt;summary&gt;
          /// Impersonates the user.
          /// &lt;/summary&gt;
          /// &lt;param name="userName"&gt;Name of the user.&lt;/param&gt;
          /// &lt;param name="domain"&gt;The domain.&lt;/param&gt;
          /// &lt;param name="password"&gt;The password.&lt;/param&gt;
          public ImpersonateUser(string userName, string domain, string password)
          {
              UserName = userName;
              Domain = domain;
              Password = password;
          }
  
          /// &lt;summary&gt;
          /// Impersonates the valid user.
          /// &lt;/summary&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          public bool impersonateValidUser()
          {
              WindowsIdentity tempWindowsIdentity;
              IntPtr token = IntPtr.Zero;
              IntPtr tokenDuplicate = IntPtr.Zero;
  
              if (RevertToSelf())
              {
                  if (LogonUserA(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE,
                      LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                  {
                      if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                      {
                          tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                          impersonationContext = tempWindowsIdentity.Impersonate();
                          if (impersonationContext != null)
                          {
                              CloseHandle(token);
                              CloseHandle(tokenDuplicate);
                              return true;
                          }
                      }
                  }
              }
              if (token != IntPtr.Zero)
                  CloseHandle(token);
              if (tokenDuplicate != IntPtr.Zero)
                  CloseHandle(tokenDuplicate);
              return false;
          }
  
          /// &lt;summary&gt;
          /// Undoes the impersonation.
          /// &lt;/summary&gt;
          public void undoImpersonation()
          {
              impersonationContext.Undo();
          }
      }
  }
  </code></pre>
  
  <p>Note: From memory I think I found this as an example on msdn.</p>
  
  <p>This is how I try to move a file from local path to network</p>
  
  <pre><code> if (imp.impersonateValidUser())
                              {
                                  System.IO.File.Copy(local_file, server_file, true);
                                  imp.undoImpersonation();
                              }
                              else
                              {
                                  throw new Exception("Unable to impersonate for uploading file.");
                              }
  </code></pre>
  
  <p>And it works! I never have issues with impersonation - exception never gets thrown. It works fine and uploads files to the server. However, when I started testing a bit more I found that if proxy user is not logged in to the server (normally I open RDS login and quit - without logging out). </p>
  
  <p><strong>I get different exception - network path not found exception and it only occurs when I have just restarted the server and "proxy" is not logged in.</strong></p>
  
  <p>My first thought was that there is something wrong with impersonation class, however it impersonates fine when it does work (ie. files have ownership of proxy user). Then I thought that maybe "proxy" needs to be logged in so OS can use its permissions to actually access \server\uploads </p>
  
  <p>I'm extremely lost now, not sure how to solve it. 
  Please note: I have no control over the server. Server is win2k8 with desktop experience installed (otherwise i cant access any network locations).</p>
  
  <p>Thanks!</p>