title: Cannot copy file, even though FileIOPermission is granted in C#
body: <p>I was trying out the <code>FileIOPermission</code> in Windows 7 in .NET 3.5. I have been a Windows XP user and was granted this permission as I was an administrator</p>
  
  <p>I wrote the following code, testing to see if I could write to C:\Program Files\Outlook......</p>
  
  <pre><code>static void Main(string[] args)
  {
      Console.WriteLine("Am I an administrator? " + new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
  
      //  Try and open a file in C:\Program Files\Microsoft Office\Office14\BCSLaunch.dll
      string path = @"C:\Program Files\Microsoft Office\Office14\BCSLaunch.dll";
  
      try
      {
          FileIOPermission ioPerm = new FileIOPermission(FileIOPermissionAccess.Read, path);
          ioPerm.Demand();
  
          string backupPath = Path.ChangeExtension(path, ".bak");
          FileIOPermission writeAccess = new FileIOPermission(FileIOPermissionAccess.AllAccess, backupPath);
          writeAccess.Demand();
  
          Console.WriteLine("Read access is permitted: {0} =&gt; {1}",path,SecurityManager.IsGranted(ioPerm));
          Console.WriteLine("Write backup file is permitted: {0} =&gt; {1}", backupPath, SecurityManager.IsGranted(writeAccess));
  
          File.Copy(path, backupPath);
  
          Console.WriteLine("File copied! {0}",backupPath);
          Console.WriteLine("Deleting file.....");
          File.Delete(path);
      }
      catch (UnauthorizedAccessException uae)
      {
          Console.WriteLine(uae.ToString());
      }
  
      Console.ReadLine();
  }
  </code></pre>
  
  <p>So the program causes an <code>UnauthorizedAccessException</code> (which I expected), but what I don't understand is that the <code>Demand()</code> allows the permission, <code>SecurityManager</code> confirms that the permission is granted, but when performing the <code>File.Copy()</code> I do get the exception.</p>
  
  <p>Although I am happy to see .NET is stopping me, why didn't it notify me earlier when I called <code>Demand()</code>?</p>
  
  <p>I get the following output:</p>
  
  <pre>
  Am I an administrator? False
  Read access is permitted: C:\Program Files\Microsoft Office\Office14\BCSLaunch.dll => True
  Write backup file is permitted: C:\Program Files\Microsoft Office\Office14\BCSLaunch.bak => True
  System.UnauthorizedAccessException: Access to the path 'C:\Program Files\Microsoft Office\Office14\BCSLaunch.bak' is denied.
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
     at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite)
     at System.IO.File.Copy(String sourceFileName, String destFileName)
     at TryAndGetUACPrompt.Program.Main(String[] args) in C:\Users\..............
  </pre>
  
  <p>Please can someone help me understand why I am getting conflicting information?</p>
  
  <p>--</p>
  
  <p>Update - 19:30 GMT</p>
  
  <p>I have looked through the ACLs of the source file using the following code:</p>
  
  <pre><code>Console.WriteLine("ACL Permissions for Source....");
  FileSecurity fileSecurityForOriginalPath = new FileSecurity(path, AccessControlSections.Access);
  
  foreach (FileSystemAccessRule rule in fileSecurityForOriginalPath.GetAccessRules(true,true,typeof(NTAccount)))
  {
     Console.WriteLine("{0} =&gt; {1}", rule.FileSystemRights, rule.AccessControlType);
  }
  </code></pre>
  
  <p>The output is as follows:</p>
  
  <pre>
  ACL Permissions for Source....
  FullControl => Allow
  FullControl => Allow
  ReadAndExecute, Synchronize => Allow
  </pre>
  
  <p>Therefore, I do have access to read it. However, I tried to use this code to view the permissions of the backup path and <i>obviously</i>, I get an exception as my backup (destination) file doesn't physically exist, so I can't check permissions on it.</p>
  
  <p>I will next try another suggestion to move this check into another method.</p>
  
  <p>Update - 19:45 GMT</p>
  
  <p>I have refactored the Read/Write demands into another method:</p>
  
  <pre><code>private static FileIOPermission CheckWriteAccess(string backupPath)
  {
      FileIOPermission writeAccess = new FileIOPermission(FileIOPermissionAccess.AllAccess, backupPath);
      writeAccess.Demand();
      return writeAccess;
  }
  
  private static FileIOPermission CheckReadAccess(string path)
  {
      FileIOPermission ioPerm = new FileIOPermission(FileIOPermissionAccess.Read, path);
      ioPerm.Demand();
      return ioPerm;
  }
  </code></pre>
  
  <p>These both return fine without exception.</p>
  
  <p>Therefore if the .NET Security augments the DACLs, I wonder why it thinks it will be successful, if in reality it isn't.</p>
  
  <p>--</p>
  
  <p>Update 19:57 GMT</p>
  
  <p>Okay, I checked the permissions of the Directory, not the backupFile (destination file) and got this as output (using a foreach on the AuthorizationRuleCollection from .GetAccessRules())</p>
  
  <pre>
  Checking write access in this directory....
  FullControl => Allow
  268435456 => Allow
  FullControl => Allow
  268435456 => Allow
  FullControl => Allow
  268435456 => Allow
  ReadAndExecute, Synchronize => Allow
  -1610612736 => Allow
  268435456 => Allow
  </pre>
  
  <p>I used an <code>Enum.Format(typeof(FileSystemAccessRights),rule,"G")</code> to get the formatting, effectively doing the ToString(), but I just wasn't sure these numbers were correct.</p>
  
  <p>Code to output the above:</p>
  
  <pre><code>private static DirectorySecurity CheckWriteAccess(string backupPath)
  {
      DirectorySecurity writeAccess = new DirectorySecurity( Path.GetDirectoryName(backupPath),AccessControlSections.Access);
  
      Console.WriteLine("Checking write access in this directory....");
      foreach (FileSystemAccessRule rule in writeAccess.GetAccessRules(true, true, typeof(NTAccount)))
      {
          Console.WriteLine("{0} =&gt; {1}", Enum.Format(typeof(FileSystemRights),rule.FileSystemRights,"G"), rule.AccessControlType);
      }
  
      return writeAccess;
  }
  </code></pre>