context: //  Copyright (C) 2015, The Duplicati Team
  
  //  http://www.duplicati.com, info@duplicati.com
  //
  //  This library is free software; you can redistribute it and/or modify
  //  it under the terms of the GNU Lesser General Public License as
  //  published by the Free Software Foundation; either version 2.1 of the
  //  License, or (at your option) any later version.
  //
  //  This library is distributed in the hope that it will be useful, but
  //  WITHOUT ANY WARRANTY; without even the implied warranty of
  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  //  Lesser General Public License for more details.
  //
  //  You should have received a copy of the GNU Lesser General Public
  //  License along with this library; if not, write to the Free Software
  //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  using System;
  using System.Linq;
  using System.Collections.Generic;
  using System.Security.AccessControl;
  using System.IO;
  
  
  namespace Duplicati.Library.Snapshots
  {
      public struct SystemIOWindows : ISystemIO
      {
          private const string UNCPREFIX = @"\\?\";
          private static readonly string DIRSEP = System.IO.Path.DirectorySeparatorChar.ToString();
  
          public static bool IsPathTooLong(string path)
          {
              if (path.StartsWith(UNCPREFIX) || path.Length > 260)
                  return true;
  
              return false;
          }
  
          public static string PrefixWithUNC(string path)
          {
              if (!path.StartsWith(UNCPREFIX))
                  return UNCPREFIX + path;
              else
                  return path;
          }
  
          public static string StripUNCPrefix(string path)
          {
              if (path.StartsWith(UNCPREFIX))
                  return path.Substring(UNCPREFIX.Length);
              else
                  return path;
          }
  
          #region ISystemIO implementation
          public void DirectoryDelete(string path)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      System.IO.Directory.Delete(path);
                      return;
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              Alphaleonis.Win32.Filesystem.Directory.Delete(PrefixWithUNC(path));
          }
  
          public void DirectoryCreate(string path)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      System.IO.Directory.CreateDirectory(path);
                      return;
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              Alphaleonis.Win32.Filesystem.Directory.CreateDirectory(PrefixWithUNC(path));
          }
  
          public bool DirectoryExists(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.Directory.Exists(path); }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.Directory.Exists(PrefixWithUNC(path));
          }
  
          public void FileDelete(string path)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      System.IO.File.Delete(path);
                      return;
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              Alphaleonis.Win32.Filesystem.File.Delete(PrefixWithUNC(path));
          }
  
          public void FileSetLastWriteTimeUtc(string path, DateTime time)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      System.IO.File.SetLastWriteTimeUtc(path, time);
                      return;
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              Alphaleonis.Win32.Filesystem.File.SetLastWriteTimeUtc(PrefixWithUNC(path), time);
          }
  
          public void FileSetCreationTimeUtc(string path, DateTime time)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      System.IO.File.SetCreationTimeUtc(path, time);
                      return;
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              Alphaleonis.Win32.Filesystem.File.SetCreationTimeUtc(PrefixWithUNC(path), time);
          }
  
          public DateTime FileGetLastWriteTimeUtc(string path)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      return System.IO.File.GetLastWriteTimeUtc(path);
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.File.GetLastWriteTimeUtc(PrefixWithUNC(path));
          }
  
          public DateTime FileGetCreationTimeUtc(string path)
          {
              if (!IsPathTooLong(path))
                  try 
                  { 
                      return System.IO.File.GetCreationTimeUtc(path);
                  }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.File.GetCreationTimeUtc(PrefixWithUNC(path));
          }
  
          public bool FileExists(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.File.Exists(path); }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.File.Exists(PrefixWithUNC(path));
          }
  
          public System.IO.Stream FileOpenRead(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite); }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.File.Open(PrefixWithUNC(path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
          }
  
          public System.IO.Stream FileOpenWrite(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.File.OpenWrite(path); }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              if (FileExists(path))
                  return Alphaleonis.Win32.Filesystem.File.OpenWrite(PrefixWithUNC(path));
              else
                  return FileCreate(path);
          }
  
          public System.IO.Stream FileOpenReadWrite(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.File.Open(path, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.Read); }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.File.Open(PrefixWithUNC(path), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
          }
  
          public System.IO.Stream FileCreate(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.File.Create(path); }
                  catch (System.IO.PathTooLongException) { }
                  catch (System.ArgumentException) { }
  
              return Alphaleonis.Win32.Filesystem.File.Create(PrefixWithUNC(path));
          }
  
          public System.IO.FileAttributes GetFileAttributes(string path)
          {
              if (!IsPathTooLong(path))
                  try { return System.IO.File.GetAttributes(path); }
                  catch (System.IO.PathTooLongException) { }
  
gt:                 catch (System.ArgumentException) { }