Beispiel #1
0
        /// <summary>
        /// This function query the file and returns a list of allocated ranges (The non-zero ranges!)
        /// Please note that the file can contain zero-written areas but if the is not defined
        /// as sparse and/or the chunks are smaller than 64kb (or 128 kb if the chunk is not
        /// located in a start of a 64 kb chunk) the query will recognize those areas as allocated ones.
        /// PLEASE NOTE! This function is the only one that doesn't work well on 64-bit systems
        /// </summary>
        /// <param name="fs"></param>
        /// <returns></returns>
        public static List <FILE_ALLOCATED_RANGE_BUFFER> QueryAllocatedRanges(FileStream fs)
        {
            FILE_ALLOCATED_RANGE_BUFFER _queryRange;

            _queryRange._offset = 0;
            _queryRange._length = fs.Length;
            FILE_ALLOCATED_RANGE_BUFFER[]      _ranges     = new FILE_ALLOCATED_RANGE_BUFFER[64];
            List <FILE_ALLOCATED_RANGE_BUFFER> _resultList = new List <FILE_ALLOCATED_RANGE_BUFFER>();
            bool _br = false;
            int  _bytesReturned;
            int  _errNumber;

            do
            {
                _br = false; //In case this is not the first cycle of the loop
                if (!DeviceIoControlQueryAllocatedRanges(fs.SafeFileHandle, FSCTL_QUERY_ALLOCATED_RANGES, ref _queryRange, Marshal.SizeOf(_queryRange), out _ranges[0], _ranges.Length * Marshal.SizeOf(_queryRange), out _bytesReturned, IntPtr.Zero))
                {
                    /*If the error accors because there's some data left (the array was not big enough) the whole process will happen again and again untill all the data is transfered*/
                    if ((_errNumber = Marshal.GetLastWin32Error()) == ERROR_MORE_DATA)
                    {
                        _br = true;
                    }
                    else
                    {
                        throw new Win32Exception(_errNumber);
                    }
                }
                int _nBytes = _bytesReturned / Marshal.SizeOf(_queryRange);
                for (int i = 0; i < _nBytes; i++)
                {
                    FILE_ALLOCATED_RANGE_BUFFER _tempBuf;
                    _tempBuf._offset = _ranges[i]._offset;
                    _tempBuf._length = _ranges[i]._length;
                    _resultList.Add(_tempBuf);
                }
                if (_br)
                {
                    _queryRange._offset = _ranges[_nBytes - 1]._offset + _ranges[_nBytes - 1]._length;
                    _queryRange._length = fs.Length - _queryRange._offset;
                }
            } while (_br);
            return(_resultList);
        }
Beispiel #2
0
 static extern bool DeviceIoControlQueryAllocatedRanges([In] SafeFileHandle hDevice, [In] uint dwIoControlCode, [In] ref FILE_ALLOCATED_RANGE_BUFFER fAllocRangeBuffer, [In] int nInBufferSize, [Out] out FILE_ALLOCATED_RANGE_BUFFER fRanges, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped);
       /// <summary>
       /// This function query the file and returns a list of allocated ranges (The non-zero ranges!)
       /// Please note that the file can contain zero-written areas but if the is not defined
       /// as sparse and/or the chunks are smaller than 64kb (or 128 kb if the chunk is not
       /// located in a start of a 64 kb chunk) the query will recognize those areas as allocated ones.
       /// PLEASE NOTE! This function is the only one that doesn't work well on 64-bit systems
       /// </summary>
       /// <param name="fs"></param>
       /// <returns></returns>
        public static List<FILE_ALLOCATED_RANGE_BUFFER> QueryAllocatedRanges(FileStream fs)
        {
            FILE_ALLOCATED_RANGE_BUFFER _queryRange;
            _queryRange._offset = 0;
            _queryRange._length = fs.Length;
            FILE_ALLOCATED_RANGE_BUFFER[] _ranges = new FILE_ALLOCATED_RANGE_BUFFER[64];
            List<FILE_ALLOCATED_RANGE_BUFFER> _resultList = new List<FILE_ALLOCATED_RANGE_BUFFER>();
            bool _br = false;
            int _bytesReturned;
            int _errNumber;
            do
            {
                _br = false; //In case this is not the first cycle of the loop
                if (!DeviceIoControlQueryAllocatedRanges(fs.SafeFileHandle, FSCTL_QUERY_ALLOCATED_RANGES, ref _queryRange, Marshal.SizeOf(_queryRange), out _ranges[0], _ranges.Length * Marshal.SizeOf(_queryRange), out _bytesReturned, IntPtr.Zero))
                {                  
         /*If the error accors because there's some data left (the array was not big enough) the whole process will happen again and again untill all the data is transfered*/
                    if ((_errNumber = Marshal.GetLastWin32Error()) == ERROR_MORE_DATA) 
                        _br = true;
                    else
                    {
                        throw new Win32Exception(_errNumber);
                    }
                }
                int _nBytes = _bytesReturned / Marshal.SizeOf(_queryRange);
                for (int i = 0; i < _nBytes; i++)
                {
                    FILE_ALLOCATED_RANGE_BUFFER _tempBuf;
                    _tempBuf._offset = _ranges[i]._offset;
                    _tempBuf._length = _ranges[i]._length;
                    _resultList.Add(_tempBuf);
                }
                if (_br)
                {
                    _queryRange._offset = _ranges[_nBytes - 1]._offset + _ranges[_nBytes - 1]._length;
                    _queryRange._length = fs.Length - _queryRange._offset;
                }

            } while (_br);
            return _resultList;
        }