private void CheckError(string methodName)
 {
     Int32 err = Marshal.GetLastWin32Error();
     if (err != 0)
     {
         var tempToGetMessage = new System.ComponentModel.Win32Exception(err);
         throw new System.ComponentModel.Win32Exception(err, methodName + ": " + tempToGetMessage.ToString());
     }
 }
Example #2
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));
        }
Example #3
0
        private void CheckError(string methodName)
        {
            Int32 err = Marshal.GetLastWin32Error();

            if (err != 0)
            {
                var tempToGetMessage = new System.ComponentModel.Win32Exception(err);
                throw new System.ComponentModel.Win32Exception(err, methodName + ": " + tempToGetMessage.ToString());
            }
        }
Example #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);
        }