示例#1
0
        public int Write(IntPtr buffer, int todo)
        {
            int done;

            DeviceControl.WriteFile(m_hFile, buffer, todo, out done, IntPtr.Zero);
            return(done);
        }
示例#2
0
        public int Write(byte[] data, int size)
        {
            uint done;

            DeviceControl.WriteFile(m_hFile, data, (uint)size, out done, IntPtr.Zero);
            return((int)done);
        }
示例#3
0
        public int Write(byte[] data)
        {
            uint done;

            DeviceControl.WriteFile(m_hFile, data, (uint)data.Length, out done, IntPtr.Zero);
            int err = Marshal.GetLastWin32Error();

            return((int)done);
        }
示例#4
0
        public uint DeviceIoControl(int ControlCode, byte[] InBuffer, int InBufferSize, byte[] OutBuffer, int OutBufferSize)
        {
            uint returned = 0;

            if (!DeviceControl.DeviceIoControl(m_hFile, (IntPtr)ControlCode, InBuffer, (uint)InBufferSize, OutBuffer, (uint)OutBufferSize, ref returned, IntPtr.Zero))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            return(returned);
        }
示例#5
0
        public byte[] Read(int length)
        {
            byte[] buffer = new byte[length];
            uint   numRead;

            if (!DeviceControl.ReadFile(m_hFile, buffer, (uint)length, out numRead, IntPtr.Zero))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            Array.Resize(ref buffer, (int)numRead);
            return(buffer);
        }
示例#6
0
 public SystemDevice(string DevicePath, bool ReadOnly = false)
 {
     m_hFile = DeviceControl.CreateFile(DevicePath,
                                        DeviceControl.EFileAccess.GenericRead | (ReadOnly ? 0 : DeviceControl.EFileAccess.GenericWrite),
                                        DeviceControl.EFileShare.Read | DeviceControl.EFileShare.Write,
                                        IntPtr.Zero,
                                        DeviceControl.ECreationDisposition.OpenExisting,
                                        DeviceControl.EFileAttributes.Normal,
                                        IntPtr.Zero);
     if (m_hFile.IsInvalid)
     {
         throw new InvalidOperationException("Cannot open device");
     }
 }
示例#7
0
        bool AttemptWrite(ThreadContext ctx, DiskDevice dev)
        {
            long      totalSize = ctx.fs.Length, done = 0;
            const int bufferSize = 1024 * 1024;
            IntPtr    buffer     = IntPtr.Zero;

            var start = DateTime.Now;

            try
            {
                dev.SeekAbs(0);

                byte[] firstSector = null;  //The very first sector will be written in the very end. Otherwise the partition driver might block us from writing the raw disk object.

                buffer = Marshal.AllocCoTaskMem(bufferSize);
                while (done < totalSize)
                {
                    if (_AbortWriting)
                    {
                        throw new OperationCanceledException();
                    }

                    int todo = (int)Math.Min(bufferSize, totalSize - done), cdone;
                    if (!DeviceControl.ReadFile(ctx.fs.SafeFileHandle, buffer, todo, out cdone, IntPtr.Zero) || cdone != todo)
                    {
                        if (!AskRetry("Cannot read image file at offset " + done.ToString()))
                        {
                            throw new OperationCanceledException();
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    if (firstSector == null)
                    {
                        firstSector = new byte[SectorSize];
                        Marshal.Copy(buffer, firstSector, 0, SectorSize);
                        Marshal.Copy(new byte[SectorSize], 0, buffer, SectorSize);
                    }

                    if ((todo % SectorSize) != 0)
                    {
                        //If the image file is not aligned to the sector boundary, the device write would fail unless we manually align it
                        todo = ((todo + SectorSize - 1) / SectorSize) * SectorSize;
                    }

                    if (dev.Write(buffer, todo) != todo)
                    {
                        if (!AskRetry("Cannot write medium at offset " + done.ToString()))
                        {
                            throw new OperationCanceledException();
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    dev.SeekRel(todo);

                    string statusText;
                    long   msec = (long)(DateTime.Now - start).TotalMilliseconds;
                    if (msec < 5000)
                    {
                        statusText = string.Format("Writing ({0}B done)...", StringHelpers.FormatByteCount(done));
                    }
                    else
                    {
                        long bps       = (done * 1000) / msec;
                        long bytesLeft = totalSize - done;
                        if (bps == 0)
                        {
                            bps = 1;
                        }
                        int secEstimated = (int)(bytesLeft / bps);

                        statusText = string.Format("Writing ({0}B done, {1}B/s, {2}:{3:d2} remaining)...", StringHelpers.FormatByteCount(done), StringHelpers.FormatByteCount(bps), secEstimated / 60, secEstimated % 60);
                    }
                    UpdateProgress(statusText, done, totalSize);
                    done += todo;
                }

                if (firstSector == null)
                {
                    throw new Exception("First sector not cached");
                }

                if (ctx.ResizedPartition.HasValue)
                {
                    string resizeDir = Path.Combine(Path.GetTempPath(), "resize2fs." + Process.GetCurrentProcess().Id);
                    Directory.CreateDirectory(resizeDir);
                    string resizer = Path.Combine(resizeDir, "resize2fs.exe");
                    using (var s = Assembly.GetExecutingAssembly().GetManifestResourceStream("WinFlashTool.resize2fs.exe"))
                    {
                        byte[] data = new byte[s.Length];
                        s.Read(data, 0, data.Length);
                        File.WriteAllBytes(resizer, data);
                    }

                    var devLength = dev.QueryLength().Length;
                    if ((ctx.ResizedPartition.Value.StartingLBA + ctx.ResizedPartition.Value.TotalSectorCount) * 512UL > devLength)
                    {
                        throw new ResizeSkippedException("Image is too small");
                    }

                    var pt = ParsedChangeFile.ReadPartitionTable(firstSector);
                    int partitionNumber = -1;
                    for (int i = 0; i < pt.Length; i++)
                    {
                        if (pt[i].Equals(ctx.ResizedPartition.Value))
                        {
                            partitionNumber = i;
                            break;
                        }
                    }

                    if (partitionNumber == -1)
                    {
                        throw new ResizeSkippedException("Matching partition not found in image");
                    }

                    ulong newSizeInBytes     = devLength - ctx.ResizedPartition.Value.StartingLBA * 512UL;
                    int   offsetInBootSector = 0x1BE + partitionNumber * 0x10 + 0x0c;
                    if (BitConverter.ToUInt32(firstSector, offsetInBootSector) != ctx.ResizedPartition.Value.TotalSectorCount)
                    {
                        throw new ResizeSkippedException("Internal error: wrong partition table offset");
                    }
                    BitConverter.GetBytes((int)(newSizeInBytes / 512)).CopyTo(firstSector, offsetInBootSector);

                    UpdateProgress("Resizing file system...", 0, 0);
                    var info = new ProcessStartInfo
                    {
                        FileName        = resizer,
                        Arguments       = string.Format("-f \"{0}@{1}/{2}\"", ctx.FileName, ctx.ResizedPartition.Value.StartingLBA * 512L, newSizeInBytes),
                        CreateNoWindow  = true,
                        UseShellExecute = false,
                    };

                    info.EnvironmentVariables["RESIZE2FS_CHANGE_FILE_DIR"] = resizeDir;
                    string chg = Path.Combine(resizeDir, Path.GetFileName(ctx.FileName) + ".chg");

                    var proc = Process.Start(info);
                    proc.WaitForExit();
                    if (proc.ExitCode != 0)
                    {
                        throw new ResizeSkippedException("Failed to resize Ext2FS - exit code " + proc.ExitCode);
                    }
                    if (!File.Exists(chg))
                    {
                        throw new ResizeSkippedException("Resize change file does not exist: " + chg);
                    }

                    UpdateProgress("Writing resized file system...", 0, 0);
                    using (var chf = new ParsedChangeFile(chg, ctx.ResizedPartition.Value.StartingLBA * 512, devLength))
                    {
                        chf.Apply(dev, (d, t) => UpdateProgress("Writing resized file system...", d, t));
                    }

                    try
                    {
                        Directory.Delete(resizeDir, true);
                    }
                    catch { }
                }

                dev.SeekAbs(0);
                dev.Write(firstSector);
            }
            finally
            {
                if (buffer != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(buffer);
                }
            }

            return(true);
        }