private static unsafe FileStream createNewFloppyImage(FileInfo image) { FileStream fStream = image.Create(); FAT12_BOOT_SECTOR bootSector = new FAT12_BOOT_SECTOR(); bootSector.Bpb.OEMName[0] = (byte)'T'; bootSector.Bpb.OEMName[1] = (byte)'i'; bootSector.Bpb.OEMName[2] = (byte)'m'; bootSector.Bpb.OEMName[3] = 0; bootSector.Bpb.OEMName[4] = 0; bootSector.Bpb.OEMName[5] = 0; bootSector.Bpb.OEMName[6] = 0; bootSector.Bpb.OEMName[7] = 0; bootSector.Bpb.BytesPerSector = 512; bootSector.Bpb.SectorsPerCluster = 1; bootSector.Bpb.ReservedSectors = 1; bootSector.Bpb.NumberOfFats = 2; bootSector.Bpb.NumDirEntries = 224; bootSector.Bpb.NumSectors = 2880; bootSector.Bpb.Media = 0xf0; bootSector.Bpb.SectorsPerFat = 9; bootSector.Bpb.SectorsPerTrack = 12; bootSector.Bpb.HeadsPerCyl = 2; bootSector.Bpb.HiddenSectors = 0; byte[] buf = new byte[sizeof(FAT12_BOOT_SECTOR)]; GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); Marshal.StructureToPtr(bootSector, pinnedBuf.AddrOfPinnedObject(), true); fStream.Write(buf, 0, buf.Length); fStream.Seek(510, SeekOrigin.Begin); fStream.WriteByte(0x55); fStream.WriteByte(0xAA); fStream.Seek(1474559, SeekOrigin.Begin); fStream.WriteByte(0); return fStream; }
private static void DeleteFile(string fileName, FileStream fStream, FAT12_BOOT_SECTOR bootSector, FAT12_MOUNT_INFO mountInfo) { byte[] buf = new byte[512]; FAT12_FILE_ENTRY fat12FileEntry; /* Get 8.3 directory name */ char[] DosFileName = new char[12]; ToDosFileName(fileName, ref DosFileName); DosFileName[11] = '\0'; /* 16 entries per sector, 14 sectors total */ for (int sector = 0; sector < 14; sector++) { /* Read in sector */ fStream.Seek((mountInfo.rootOffset + sector) * 512, SeekOrigin.Begin); fStream.Read(buf, 0, 512); /* Get file info */ GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); int count = 0; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } for (int i = 0; i < 16; i++) { /* Get current filename */ char[] name = new char[12]; unsafe { for (int j = 0; j < 11; j++) name[j] = (char)fat12FileEntry.Filename[j]; } name[11] = '\0'; /* Find a match? */ if (String.Compare(String.Concat(DosFileName), String.Concat(name)) == 0) { FreeClusterChain(fat12FileEntry.FirstCluster, fStream); unsafe { fat12FileEntry.Filename[0] = 0xE5; fStream.Seek((mountInfo.rootOffset + sector) * 512 + (count * sizeof(FAT12_FILE_ENTRY)), SeekOrigin.Begin); Marshal.StructureToPtr(fat12FileEntry, pinnedBuf.AddrOfPinnedObject(), true); fStream.Write(buf, 0, sizeof(FAT12_FILE_ENTRY)); } return; } count++; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } } pinnedBuf.Free(); } return; }
static void SaveFileToDiskImage(string fileName, FileStream fStream, FAT12_BOOT_SECTOR bootSector, FAT12_MOUNT_INFO mountInfo) { /* First delete the file if it exists */ DeleteFile(fileName, fStream, bootSector, mountInfo); byte[] buf = new byte[512]; FAT12_FILE_ENTRY fat12FileEntry; /* Get 8.3 directory name */ char[] DosFileName = new char[12]; ToDosFileName(fileName, ref DosFileName); DosFileName[11] = '\0'; /* 16 entries per sector, 14 sectors total */ for (int sector = 0; sector < 14; sector++) { /* Read in sector */ fStream.Seek((mountInfo.rootOffset + sector) * 512, SeekOrigin.Begin); fStream.Read(buf, 0, 512); /* Get file info */ GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); int count = 0; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } for (int i = 0; i < 16; i++) { /* I'm looking for an entry beginning with \0 or 0xE5 */ unsafe { if (fat12FileEntry.Filename[0] == '\0' || fat12FileEntry.Filename[0] == 0xE5) { /* Found a blank file entry */ for (int j = 0; j < 8; j++) fat12FileEntry.Filename[j] = (byte)DosFileName[j]; for (int j = 0; j < 3; j++) fat12FileEntry.Ext[j] = (byte)DosFileName[j + 8]; fat12FileEntry.Attrib = 0; /* TODO: Set the date and times */ fat12FileEntry.DateCreated = 0; fat12FileEntry.DateLastAccessed = 0; fat12FileEntry.LastModDate = 0; fat12FileEntry.LastModTime = 0; fat12FileEntry.TimeCreated = 0; fat12FileEntry.TimeCreatedMs = 0; fat12FileEntry.FileSize = 0; fat12FileEntry.FirstCluster = GetFirstFreeCluster(fStream, 2); UInt16 currentCluster = fat12FileEntry.FirstCluster; FileStream inputFile = new FileStream(fileName, FileMode.Open); byte[] inputBuffer = new byte[512]; int readBytes = 0; while ((readBytes = inputFile.Read(inputBuffer, 0, 512)) > 0) { fat12FileEntry.FileSize += (uint)readBytes; fStream.Seek((31 + currentCluster) * 512, SeekOrigin.Begin); fStream.Write(inputBuffer, 0, readBytes); if (fStream.Length > fat12FileEntry.FileSize) { /* Allocate next block */ UInt16 nextBlock = GetFirstFreeCluster(fStream, (UInt16)(currentCluster + 1)); MarkBlockChain(fStream, currentCluster, nextBlock); currentCluster = nextBlock; } } MarkBlockChain(fStream, currentCluster, 0xFFF); fStream.Seek((mountInfo.rootOffset + sector) * 512 + (count * sizeof(FAT12_FILE_ENTRY)), SeekOrigin.Begin); Marshal.StructureToPtr(fat12FileEntry, pinnedBuf.AddrOfPinnedObject(), true); fStream.Write(buf, 0, sizeof(FAT12_FILE_ENTRY)); return; } count++; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } } } pinnedBuf.Free(); } }
private static FAT12_BOOT_SECTOR LoadBootSector(FileStream fStream) { FAT12_BOOT_SECTOR retVal = new FAT12_BOOT_SECTOR(); fStream.Seek(0, SeekOrigin.Begin); unsafe { byte[] buf = new byte[sizeof(FAT12_BOOT_SECTOR)]; fStream.Read(buf, 0, sizeof(FAT12_BOOT_SECTOR)); GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); retVal = (FAT12_BOOT_SECTOR)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject(), typeof(FAT12_BOOT_SECTOR)); pinnedBuf.Free(); } return retVal; }