public int Write(IntPtr buffer, int todo) { int done; DeviceControl.WriteFile(m_hFile, buffer, todo, out done, IntPtr.Zero); return(done); }
public int Write(byte[] data, int size) { uint done; DeviceControl.WriteFile(m_hFile, data, (uint)size, out done, IntPtr.Zero); return((int)done); }
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); }
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); }
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); }
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"); } }
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); }