[.net2] lecture des flux caches dans un fichier d'un lecteur ntfs

Description

Cette démo permet de voir les flux cachés sur les fichiers d'un lecteur NTFS.

Clin d'oeil à la source de ShareVB: http://www.vbfrance.com/code.aspx?ID=39672.
Et également aux précieuses infos de JC.Bellamy sur le sujet: http://jc.bellamy.free.fr/fr/stream.html

API utilisées pour la lecture:
-BackupRead: http://msdn2.microsoft.com/en-us/library/aa362509.aspx
-BackupSeek: http://msdn2.microsoft.com/en-us/library/aa362510.aspx

La démo se divise en 2 classes:

-NtfsStream: Classe statiques proposant 2 méthodes.
--IsStreamNamedExists: Indique si un fichier contient un flux nommé.
--DeleteNamedStream: Supprime un flux nommé sur un fichier.

-NtfsStreamReader: Classe de lecture des flux.
--Open: Ouvre le fichier.
--Read: Lecture des flux.
--Close: Ferme le fichier.

Le code est encore une fois blindé de commentaires.

PS: Ne fonctionne pas sur une platforme non NT.

Source / Exemple :


using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;

namespace NTFSStreams
{
    public class NtfsStreamReader
    {
        private FileStream _fs;

        /// <summary>
        /// Ouvre le fichier en lecture.
        /// </summary>
        /// <param name="file">Fichier quelconque.</param>
        /// <returns>True si le fichier est ouvert; False si échec.</returns>
        public bool Open(string file)
        {
            _fs = new FileStream(file, FileMode.Open);

            return _fs.SafeFileHandle.IsInvalid | _fs.SafeFileHandle.IsClosed ? false : true;
        }

        /// <summary>
        /// Ferme le flux ouvert sur le fichier.
        /// </summary>
        public void Close()
        {
            _fs.Close();
            _fs.Dispose();
        }

        /// <summary>
        /// Lecture des flux NTFS du fichier.
        /// </summary>
        /// <param name="StreamsArray">Retourne un tableau StreamInfo contenant les infos sur chaque flux.</param>
        public void ReadStream(ref StreamInfo[] StreamsArray )
        {
            List<StreamInfo> listSI = new List<StreamInfo>();   //Liste recevant les infos des flux.
            bool ret = false;                                   //Valeur de retour des appels BackupRead/Seek.
            IntPtr pContext = IntPtr.Zero;                      //Pointeur vers une structure interne utilisée BackupRead/Seek
                                                                //maintenant les infos sur le context de l'opération.
            int retlow = 0, rethigh = 0;                                                      

            //Itération tant que la lecture des flux n'est pas terminée.
            do
            {
                WIN32_STREAM_ID wstreamID = new WIN32_STREAM_ID();      //Recoit les infos de flux.
                int size = Marshal.SizeOf(typeof(WIN32_STREAM_ID));     //Taille à réserver en mémoire.
                int bytesRead = 0;                                      //Octets lut.

                IntPtr pStreamID = Marshal.AllocHGlobal(size);          //Pointeur vers l'emplacement mémoire réservée.

                //Lecture du flux (prise en compte du flux de sécurité)
                ret = NativeMethods.BackupRead(_fs.SafeFileHandle, pStreamID, size, ref bytesRead, false, true, ref pContext);

                //Marshal les données en mémoire (non managée) vers notre structure.
                wstreamID = (WIN32_STREAM_ID)Marshal.PtrToStructure(pStreamID, typeof(WIN32_STREAM_ID));

                //Si lecture Ok + données lus.
                if (ret && (bytesRead == size))
                {
                    //Instancie un nouvel objet StreamInfo et renseignement de ces membres.
                    StreamInfo si = new StreamInfo();
                    si.Type = wstreamID.dwStreamId;
                    si.Attr = wstreamID.dwStreamAttributes;
                    si.Size = wstreamID.Size;

                    //Si nous avons à faire à un flux nommé.
                    if (wstreamID.dwStreamNameSize > 0)
                    {
                        si.Unnamed = false;

                        IntPtr pName = Marshal.AllocHGlobal(wstreamID.dwStreamNameSize);    //Pointeur sur l'espace mémoire réservé pour recevoir le nom

                        //Lecture du nom
                        ret = NativeMethods.BackupRead(_fs.SafeFileHandle, pName, wstreamID.dwStreamNameSize, ref bytesRead, false, false, ref pContext);

                        string szvalue = Marshal.PtrToStringAuto(pName, wstreamID.dwStreamNameSize);
                        int ipos = szvalue.LastIndexOf(":");
                        si.Name = szvalue.Substring(0, ipos);

                        //Si données présente.
                        if (wstreamID.Size.LowPart > 0)
                        {
                            IntPtr pDatas = Marshal.AllocHGlobal(wstreamID.Size.LowPart); //Pointeur sur l'espace réservé.

                            //Lecture des données.
                            ret = NativeMethods.BackupRead(_fs.SafeFileHandle, pDatas, wstreamID.Size.LowPart, ref bytesRead,
                                false, false, ref pContext);

                            //Puis copie de celles-ci.
                            si.StreamContent = new byte[wstreamID.Size.LowPart];
                            Marshal.Copy(pDatas, si.StreamContent, 0, wstreamID.Size.LowPart);
                        }
                    }
                    //Flux non nommés
                    else
                    {
                        si.Unnamed = true;

                        //Passe au flux suivant.
                        ret = NativeMethods.BackupSeek(_fs.SafeFileHandle, wstreamID.Size.LowPart, wstreamID.Size.HighPart,
                            ref retlow, ref rethigh, ref pContext);
                    }

                    listSI.Add(si);
                }
                else
                    ret = false;
            } while (ret);

            //Retourne le tableau de flux.
            StreamsArray = listSI.ToArray();
        }
    }
}

Conclusion :


J'espère que cette source vous en apprendra sur la manipulation des flux part les API Windows fournie.

Bon dév à tous.

Et n'hésitez pas à commenter, à noter.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.