Exemplo n.º 1
0
        /// <summary>
        /// Sets the size of disk the device.
        /// </summary>
        /// <param name="device">The device to query</param>
        /// <param name="token">The cancellation token.</param>
        protected void SetDeviceSize(SystemDevice device, CancellationToken token)
        {
            DISK_GEOMETRY_EX diskGeometry;

            if (DeviceIoControl<int>.IsAccessible(device) == false)
            {
                // Device is not ready
                return;
            }

            token.ThrowIfCancellationRequested();

            diskGeometry = base.GetDriveGeometry(device);

            token.ThrowIfCancellationRequested();

            device.DiskSize = diskGeometry.DiskSize;
            device.BytesPerSector = diskGeometry.Geometry.BytesPerSector;
            device.SectorsCount = diskGeometry.Geometry.SectorsCount;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Extracts the disk to provided file
 /// </summary>
 /// <param name="device">The device to extract from</param>
 /// <param name="outputFileName">Name of the output file including path</param>
 /// <param name="progressCallback">The progress callback.</param>
 /// <param name="token">The cancellation token.</param>
 /// <returns>Task that execute the process and return total number of bytes read from device</returns>
 internal Task<long> ExtractDisk(SystemDevice device, string outputFileName, IProgress<double> progressCallback, CancellationToken token)
 {
     return engine.ExtractDiskAsync(device, outputFileName, progressCallback, token);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Function will query device for unique device number and set it on <see cref="SystemDevice"/> object
        /// </summary>
        /// <param name="device">The device.</param>
        /// <param name="token">The token.</param>
        protected void SetDeviceNumber(SystemDevice device, CancellationToken token)
        {
            STORAGE_DEVICE_NUMBER devNumber;

            if (DeviceIoControl<int>.IsAccessible(device) == false)
            {
                // Device is not ready
                return;
            }

            token.ThrowIfCancellationRequested();

            devNumber = base.GetDeviceNumber(device);

            token.ThrowIfCancellationRequested();

            device.DeviceNumber = devNumber.DeviceNumber;
        }
Exemplo n.º 4
0
        public Task<long> ExtractDiskAsync(SystemDevice device, string outputFile, IProgress<double> progress, CancellationToken token)
        {
            if (deviceBuilder.IfUserAdmin() == false)
            {
                throw new System.Security.SecurityException("User must be administrator to access the hardware. Please re-login");
            }

            //
            // If bufferSize will be tooo small (like: 512 bytes) the iteration of ReadFile will fail with E_FAIL or some SEH exception :(
            int sectorsReadAtOnce = Convert.ToInt32(device.SectorsCount / 100) + 1; // in 'sectors' not bytes !
            int bufferSize = sectorsReadAtOnce * device.BytesPerSector;
            //

            // Align to 512 exactly
            //while (bufferSize % device.BytesPerSector != 0)
            //    bufferSize--;

            byte[] buffer = new byte[bufferSize];
            long bytesRead = 0;
            uint lpNumberOfBytesRead = 0;
            bool functionResult = false;
            int win32err = 0;
            NativeOverlapped nativeOverlapped = new NativeOverlapped();

            SystemDevice device2 = new SystemDevice("\\\\.\\PhysicalDrive" + device.DeviceNumber);
            GCHandle gcHandle = new GCHandle();

            return Task.Factory.StartNew<long>(() => {
                try
                {
                    IntPtr deviceHandle = device2.OpenDeviceHandle();
                    gcHandle = GCHandle.Alloc(deviceHandle);        // So it won't be collected by GC while I'm doing PInvoke

                    BinaryWriter writer = GetOutputStream(outputFile);

                    while(true)
                    {
                        functionResult = UnsafeNativeMethods.ReadFile(deviceHandle, buffer, Convert.ToUInt32(buffer.Length), ref lpNumberOfBytesRead, ref nativeOverlapped);
                        win32err = Marshal.GetLastWin32Error();

                        if (functionResult)
                        {
                            bytesRead += lpNumberOfBytesRead;

                            writer.Write(buffer, 0, buffer.Length);
                        }
                        else
                        {
                            if (win32err == UnsafeNativeMethods.ERROR_SECTOR_NOT_FOUND)
                            {
                                // This is a device black-hole
                                // try to squeeze as much as I can
                                if (bufferSize == device.BytesPerSector)
                                {
                                    // That's the last one
                                    break;
                                }
                                else
                                {
                                    bufferSize = device.BytesPerSector;
                                    buffer = new byte[bufferSize];
                                }
                            }
                            else
                            {
                                throw new System.ComponentModel.Win32Exception(win32err);
                            }
                        }

                        if (progress != null)
                        {
                            progress.Report(Math.Round((double)((bytesRead * 100) / device.DiskSize.Value)));
                        }

                        // Must not (!) increase position - everything will be read to NULL
                        //deviceStream.Position = iCounter;

                        if (bytesRead + bufferSize > device.DiskSize.Value)
                        {
                            if (device.DiskSize.Value == bytesRead)
                            {
                                // all done
                                break;
                            }
                            else
                            {
                                // Collect leftovers
                                buffer = new byte[(bytesRead + bufferSize) - device.DiskSize.Value];
                            }
                        }

                        GC.KeepAlive(deviceHandle);
                    }

                    writer.Flush();

                    gcHandle.Free();

                    device.CloseDeviceHandle();

                    return bytesRead;
                }
                catch (SEHException seh)
                {
                    gcHandle.Free();
                    System.Diagnostics.Trace.WriteLine("[]--- SEHException in ExtractDiskAsync(): " + seh.ToString());
                    return 0;
                }
                catch (Exception exp_gen)
                {
                    gcHandle.Free();

                    if (win32err == 0)
                    {
                        win32err = Marshal.GetLastWin32Error();
                    }

                    var zz = new System.ComponentModel.Win32Exception(win32err);
                    System.Diagnostics.Trace.WriteLine("[]--- Exception in ExtractDiskAsync(): " + exp_gen.ToString());
                    System.Diagnostics.Trace.WriteLine("[]--- Exception in ExtractDiskAsync() (native) : " + zz.ToString());
                    return 0;
                }
            }
            , token);
        }