public bool Identify(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); if (stream.Length < 512) { return(false); } byte[] pHdrB = new byte[Marshal.SizeOf(pHdr)]; stream.Read(pHdrB, 0, Marshal.SizeOf(pHdr)); pHdr = new ParallelsHeader(); IntPtr headerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pHdr)); Marshal.Copy(pHdrB, 0, headerPtr, Marshal.SizeOf(pHdr)); pHdr = (ParallelsHeader)Marshal.PtrToStructure(headerPtr, typeof(ParallelsHeader)); Marshal.FreeHGlobal(headerPtr); return(parallelsMagic.SequenceEqual(pHdr.magic) || parallelsExtMagic.SequenceEqual(pHdr.magic)); }
// TODO: Support extended public bool Create(string path, MediaType mediaType, Dictionary <string, string> options, ulong sectors, uint sectorSize) { if (sectorSize != 512) { ErrorMessage = "Unsupported sector size"; return(false); } if (!SupportedMediaTypes.Contains(mediaType)) { ErrorMessage = $"Unsupport media format {mediaType}"; return(false); } if ((sectors * sectorSize) / DEFAULT_CLUSTER_SIZE > uint.MaxValue) { ErrorMessage = "Too many sectors for selected cluster size"; return(false); } imageInfo = new ImageInfo { MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors }; try { writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); } catch (IOException e) { ErrorMessage = $"Could not create new image file, exception {e.Message}"; return(false); } uint batEntries = (uint)((sectors * sectorSize) / DEFAULT_CLUSTER_SIZE); if ((sectors * sectorSize) % DEFAULT_CLUSTER_SIZE > 0) { batEntries++; } uint headerSectors = (uint)Marshal.SizeOf <ParallelsHeader>() + (batEntries * 4); if ((uint)Marshal.SizeOf <ParallelsHeader>() + (batEntries % 4) > 0) { headerSectors++; } pHdr = new ParallelsHeader { magic = parallelsMagic, version = PARALLELS_VERSION, sectors = sectors, in_use = PARALLELS_CLOSED, bat_entries = batEntries, data_off = headerSectors, cluster_size = DEFAULT_CLUSTER_SIZE / 512 }; bat = new uint[batEntries]; currentWritingPosition = headerSectors * 512; IsWriting = true; ErrorMessage = null; return(true); }
public bool Open(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); if (stream.Length < 512) { return(false); } byte[] pHdrB = new byte[Marshal.SizeOf(pHdr)]; stream.Read(pHdrB, 0, Marshal.SizeOf(pHdr)); pHdr = new ParallelsHeader(); IntPtr headerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pHdr)); Marshal.Copy(pHdrB, 0, headerPtr, Marshal.SizeOf(pHdr)); pHdr = (ParallelsHeader)Marshal.PtrToStructure(headerPtr, typeof(ParallelsHeader)); Marshal.FreeHGlobal(headerPtr); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.magic = {0}", StringHandlers.CToString(pHdr.magic)); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.version = {0}", pHdr.version); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.heads = {0}", pHdr.heads); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.cylinders = {0}", pHdr.cylinders); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.cluster_size = {0}", pHdr.cluster_size); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.bat_entries = {0}", pHdr.bat_entries); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.sectors = {0}", pHdr.sectors); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.in_use = 0x{0:X8}", pHdr.in_use); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.data_off = {0}", pHdr.data_off); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.flags = {0}", pHdr.flags); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.ext_off = {0}", pHdr.ext_off); extended = parallelsExtMagic.SequenceEqual(pHdr.magic); DicConsole.DebugWriteLine("Parallels plugin", "pHdr.extended = {0}", extended); DicConsole.DebugWriteLine("Parallels plugin", "Reading BAT"); bat = new uint[pHdr.bat_entries]; byte[] batB = new byte[pHdr.bat_entries * 4]; stream.Read(batB, 0, batB.Length); for (int i = 0; i < bat.Length; i++) { bat[i] = BitConverter.ToUInt32(batB, i * 4); } clusterBytes = pHdr.cluster_size * 512; if (pHdr.data_off > 0) { dataOffset = pHdr.data_off * 512; } else { dataOffset = (stream.Position / clusterBytes + stream.Position % clusterBytes) * clusterBytes; } sectorCache = new Dictionary <ulong, byte[]>(); empty = (pHdr.flags & PARALLELS_EMPTY) == PARALLELS_EMPTY; imageInfo.CreationTime = imageFilter.GetCreationTime(); imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); imageInfo.Sectors = pHdr.sectors; imageInfo.SectorSize = 512; imageInfo.XmlMediaType = XmlMediaType.BlockMedia; imageInfo.MediaType = MediaType.GENERIC_HDD; imageInfo.ImageSize = pHdr.sectors * 512; imageInfo.Cylinders = pHdr.cylinders; imageInfo.Heads = pHdr.heads; imageInfo.SectorsPerTrack = (uint)(imageInfo.Sectors / imageInfo.Cylinders / imageInfo.Heads); imageStream = stream; return(true); }