File Stream C#

/*==
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
*/
using System;
using System.IO;
using System.Text;
using System.Transactions;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
namespace BlueCurve.Search.Common.IO
{
    /// 
    /// Fournit des méthodes de gestions du système de fichier
    /// 

    public class CommonStream
    {
        #region Import native methods
        /// 
        /// Méthode native vérifiant si un répertoire est vide
        /// 

        /// Chemin du répertoire à tester
        /// bool
        [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
        private extern static bool PathIsDirectoryEmpty(string pszPath);
        #region 'Kernel transaction manager api management'
        /// 
        /// Represente un handle de transaction
        /// 

        public sealed class SafeTransactionHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            private SafeTransactionHandle()
                : base(true)
            {
            }
            public SafeTransactionHandle(IntPtr preexistingHandle, bool ownsHandle)
                : base(ownsHandle)
            {
                SetHandle(preexistingHandle);
            }
            public enum FileAccess
            {
                GENERIC_READ = unchecked((int)0x80000000),
                GENERIC_WRITE = 0x40000000
            }
            [Flags]
            public enum FileShare
            {
                FILE_SHARE_NONE = 0x00,
                FILE_SHARE_READ = 0x01,
                FILE_SHARE_WRITE = 0x02,
                FILE_SHARE_DELETE = 0x04
            }
            public enum FileMode
            {
                CREATE_NEW = 1,
                CREATE_ALWAYS = 2,
                OPEN_EXISTING = 3,
                OPEN_ALWAYS = 4,
                TRUNCATE_EXISTING = 5
            }
            [DllImport("Kernel32.dll", SetLastError = true)]
            private static extern bool CloseHandle(IntPtr handle);
            override protected bool ReleaseHandle()
            {
                return CloseHandle(handle);
            }
        }
        /// 
        /// Importation de la fonction native CreateFileTransacted() permettant
        /// de créer une transaction ntfs
        /// 

        /// SafeFileHandle
        [DllImport("Kernel32.Dll", EntryPoint = "CreateFileTransacted", CharSet = CharSet.Unicode, SetLastError = true)]
        protected static extern SafeFileHandle CreateFileTransacted(
               [In] String lpFileName,
               [In] SafeTransactionHandle.FileAccess dwDesiredAccess,
               [In] SafeTransactionHandle.FileShare dwShareMode,
               [In] IntPtr lpSecurityAttributes,
               [In] SafeTransactionHandle.FileMode dwCreationDisposition,
               [In] int dwFlagsAndAttributes,
               [In] IntPtr hTemplateFile,
               [In] SafeTransactionHandle txHandle,
               [In] IntPtr miniVersion,
               [In] IntPtr extendedOpenInformation
           );
        /// 
        /// Importation de l'interface KTM
        /// 

        [ComImport]
        [Guid("79427A2B-F895-40e0-BE79-B57DC82ED231")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        protected interface IKernelTransaction
        {
            void GetHandle(out SafeTransactionHandle ktmHandle);
        }
        #endregion
        #endregion
        /// 
        /// Copie un stream dans un autre
        /// de façon asynchrone
        /// http://msdn.microsoft.com/fr-fr/magazine/cc337900.aspx
        /// 

        /// Stream source
        /// Stream destination
        /// Action()
        public static void CopyStreamToStream(FileStream source, FileStream destination,
                                              Action completed)
        {
            byte[] buffer = new byte[0x1024];
            System.ComponentModel.AsyncOperation asyncOp = System.ComponentModel.AsyncOperationManager.CreateOperation(null);
          
            Action done = e =>
            {
                if (completed != null) asyncOp.Post(delegate
                {
                    completed(source, destination, e);
                }, null);
            };
            AsyncCallback rc = null;
            rc = readResult =>
            {
                try
                {
                    int read = source.EndRead(readResult);
                    if (read > 0)
                    {
                        destination.BeginWrite(buffer, 0, read, writeResult =>
                        {
                            try
                            {
                                destination.EndWrite(writeResult);
                                source.BeginRead(
                                    buffer, 0, buffer.Length, rc, null);
                            }
                            catch (Exception exc) { done(exc); }
                        }, null);
                    }
                    else done(null);
                }
                catch (Exception exc) { done(exc); }
            };
            source.BeginRead(buffer, 0, buffer.Length, rc, null);
        }
        /// 
        /// Vérifie qu'un répertoire est vide
        /// 

        /// Chemin de fichier du répertoire
        /// bool
        public static bool DirectoryIsEmpty(string path)
        {
            return PathIsDirectoryEmpty(path);
        }
        #region Transactional methods
        /// 
        /// Ecrit un fichier de façon transactionnel
        /// 

        /// Données à écrire
        /// Chemin du fichier dans lequel écrire les données
        /// Statut de l'opération
        public static bool WriteFileTransacted(object data, string path)
        {
            if (data == null)
                return false;
            SafeTransactionHandle txHandle = null;
            SafeFileHandle fileHandle = null;
            bool response = true;
            try
            {
                IKernelTransaction kernelTx = (IKernelTransaction)TransactionInterop.GetDtcTransaction(System.Transactions.Transaction.Current);
                kernelTx.GetHandle(out txHandle);
                fileHandle
                    = CreateFileTransacted(
                        path
                        , SafeTransactionHandle.FileAccess.GENERIC_WRITE
                        , SafeTransactionHandle.FileShare.FILE_SHARE_NONE
                        , IntPtr.Zero
                        , SafeTransactionHandle.FileMode.CREATE_ALWAYS
                        , 0
                        , IntPtr.Zero
                        , txHandle
                        , IntPtr.Zero
                        , IntPtr.Zero);
                if (fileHandle.IsInvalid)
                    throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
                using (FileStream stream = new FileStream(fileHandle, FileAccess.Write, 1024, false))
                {
                    BinaryFormatter writer = new BinaryFormatter();
                    writer.Serialize(stream, data);
                    stream.Close();
                }
            }
            catch
            {
                System.Transactions.Transaction.Current.Rollback();
                response = false;
            }
            finally
            {
                if (fileHandle != null && !fileHandle.IsInvalid)
                {
                    fileHandle.Close();
                    fileHandle.Dispose();
                }
                if (txHandle != null && !txHandle.IsInvalid)
                {
                    txHandle.Close();
                    txHandle.Dispose();
                }
            }
            return response;
        }
        /// 
        /// Lit un fichier de façon transactionnel
        /// 

        /// Chemin du fichier à lire
        /// Données lu
        public object ReadFileTransacted(string path)
        {
            if (!File.Exists(path))
                return null;
            SafeTransactionHandle txHandle = null;
            SafeFileHandle fileHandle = null;
            object raw = null;
            try
            {
                IKernelTransaction kernelTx = (IKernelTransaction)TransactionInterop.GetDtcTransaction(System.Transactions.Transaction.Current);
                kernelTx.GetHandle(out txHandle);
                fileHandle
                    = CreateFileTransacted(
                        path
                        , SafeTransactionHandle.FileAccess.GENERIC_READ
                        , SafeTransactionHandle.FileShare.FILE_SHARE_READ
                        , IntPtr.Zero
                        , SafeTransactionHandle.FileMode.OPEN_ALWAYS
                        , 0
                        , IntPtr.Zero
                        , txHandle
                        , IntPtr.Zero
                        , IntPtr.Zero);
                if (fileHandle.IsInvalid)
                    throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
                using (FileStream stream = new FileStream(fileHandle, FileAccess.Read, 1024, false))
                {
                    BinaryFormatter reader = new BinaryFormatter();
                    raw = reader.Deserialize(stream);
                }
            }
            catch
            {
                raw = null;
            }
            finally
            {
                if (fileHandle != null && !fileHandle.IsInvalid)
                {
                    fileHandle.Close();
                    fileHandle.Dispose();
                }
                if (txHandle != null && !txHandle.IsInvalid)
                {
                    txHandle.Close();
                    txHandle.Dispose();
                }
            }
            return raw;
        }
        #endregion
    }
}