C# 以编程方式更改FAT32卷序列号

C# 以编程方式更改FAT32卷序列号,c#,partitioning,fat,volumes,C#,Partitioning,Fat,Volumes,如何以编程方式从C#更改Fat32分区的卷序列。我发现了,但它是用C++写的,我读不好。有人能回答一个C代码片段吗 更新: 从上面的例子中我可以看到C++函数,我认为可以将端口直接导入C<< /p> void cvolumesrialdlg::ChangeSerialNumber(DWORD驱动器,常量DWORD新闻序列) { 常数max_pbsi=3; 结构部分启动扇区信息 { LPSTR Fs;//文件系统名称 DWORD FSOFS;//启动扇区中文件系统名称的偏移量 DWORD Seri

如何以编程方式从C#更改Fat32分区的卷序列。我发现了,但它是用C++写的,我读不好。有人能回答一个C代码片段吗

更新: 从上面的例子中我可以看到C++函数,我认为可以将端口直接导入C<< /p>
void cvolumesrialdlg::ChangeSerialNumber(DWORD驱动器,常量DWORD新闻序列)
{
常数max_pbsi=3;
结构部分启动扇区信息
{
LPSTR Fs;//文件系统名称
DWORD FSOFS;//启动扇区中文件系统名称的偏移量
DWORD SerialOffs;//启动扇区中序列号的偏移量
};
部分引导扇区信息pbsi[最大pbsi]=
{
{“FAT32”,0x52,0x43},
{“FAT”,0x36,0x27},
{“NTFS”,0x03,0x48}
};
TCHAR szDrive[12];
字符扇区[512];
德沃德一世;
sprintf(szDrive,“%c:\\”,Drive&0xFF);
如果(!disk.Open(szDrive))
{
字符串(“无法打开磁盘!”);
返回;
}
//读扇区
如果(!disk.ReadSector(0,扇区))
{
字符串(“无法读取扇区!”);
返回;
}
//尝试搜索有效的启动扇区
对于(i=0;i=max_pbsi)
{
MessageBox(\u T(“无法更改此文件系统的序列号!”),
_T(“错误”),MB_i错误);
返回;
}
//补丁序列号
*(PDWORD)(扇区+pbsi[i].连载)=新闻序列;
//写引导扇区
如果(!disk.WriteSector(0,扇区))
{
字符串(“无法写入扇区!”);
返回;
}
字符串(“卷序列号已成功更改!\r”
“您可能需要重新启动系统以使更改生效!”);
}

不保证,小心点

void ChangeSerialNumber(char volume, uint newSerial)
{
    var fsInfo = new[]
    {
        new { Name = "FAT32", NameOffs = 0x52, SerialOffs = 0x43 },
        new { Name = "FAT", NameOffs = 0x36, SerialOffs = 0x27 },
        new { Name = "NTFS", NameOffs = 0x03, SerialOffs = 0x48 }
    };

    using (var disk = new Disk(volume))
    {
        var sector = new byte[512];
        disk.ReadSector(0, sector);

        var fs = fsInfo.FirstOrDefault(
                f => Strncmp(f.Name, sector, f.NameOffs)
            );
        if (fs == null) throw new NotSupportedException("This file system is not supported");

        var s = newSerial;
        for (int i = 0; i < 4; ++i, s >>= 8) sector[fs.SerialOffs + i] = (byte)(s & 0xFF);

        disk.WriteSector(0, sector);
    }
}

bool Strncmp(string str, byte[] data, int offset)
{
    for(int i = 0; i < str.Length; ++i)
    {
        if (data[i + offset] != (byte)str[i]) return false;
    }
    return true;
}

class Disk : IDisposable
{
    private SafeFileHandle handle;

    public Disk(char volume)
    {
        var ptr = CreateFile(
            String.Format("\\\\.\\{0}:", volume),
            FileAccess.ReadWrite,
            FileShare.ReadWrite,
            IntPtr.Zero,
            FileMode.Open,
            0,
            IntPtr.Zero
            );

        handle = new SafeFileHandle(ptr, true);

        if (handle.IsInvalid) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    }

    public void ReadSector(uint sector, byte[] buffer)
    {
        if (buffer == null) throw new ArgumentNullException("buffer");
        if (SetFilePointer(handle, sector, IntPtr.Zero, EMoveMethod.Begin) == INVALID_SET_FILE_POINTER) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        uint read;
        if (!ReadFile(handle, buffer, buffer.Length, out read, IntPtr.Zero)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        if (read != buffer.Length) throw new IOException();
    }

    public void WriteSector(uint sector, byte[] buffer)
    {
        if (buffer == null) throw new ArgumentNullException("buffer");
        if (SetFilePointer(handle, sector, IntPtr.Zero, EMoveMethod.Begin) == INVALID_SET_FILE_POINTER) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        uint written;
        if (!WriteFile(handle, buffer, buffer.Length, out written, IntPtr.Zero)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        if (written != buffer.Length) throw new IOException();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (handle != null) handle.Dispose();
        }
    }

    enum EMoveMethod : uint
    {
        Begin = 0,
        Current = 1,
        End = 2
    }

    const uint INVALID_SET_FILE_POINTER = 0xFFFFFFFF;

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
        [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        int flags,
        IntPtr template);

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern uint SetFilePointer(
         [In] SafeFileHandle hFile, 
         [In] uint lDistanceToMove,
         [In] IntPtr lpDistanceToMoveHigh,
         [In] EMoveMethod dwMoveMethod);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool ReadFile(SafeFileHandle hFile, [Out] byte[] lpBuffer,
        int nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

    [DllImport("kernel32.dll")]
    static extern bool WriteFile(SafeFileHandle hFile, [In] byte[] lpBuffer,
        int nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
        [In] IntPtr lpOverlapped);
}
void ChangeSerialNumber(字符卷,uint新闻序列)
{
var fsInfo=new[]
{
新的{Name=“FAT32”,nameoff=0x52,SerialOffs=0x43},
新的{Name=“FAT”,nameoff=0x36,SerialOffs=0x27},
新的{Name=“NTFS”,nameoff=0x03,SerialOffs=0x48}
};
使用(var磁盘=新磁盘(卷))
{
var扇区=新字节[512];
磁盘读取扇区(0,扇区);
var fs=fsInfo.FirstOrDefault(
f=>Strncmp(f.Name,扇区,f.nameoff)
);
如果(fs==null)抛出新的NotSupportedException(“此文件系统不受支持”);
var s=新闻序列;
对于(inti=0;i<4;++i,s>>=8)扇区[fs.SerialOffs+i]=(字节)(s&0xFF);
disk.WriteSector(0,扇区);
}
}
bool Strncmp(字符串str,字节[]数据,整数偏移量)
{
对于(int i=0;i

使用例如
ChangeSerialNumber('D',0x12345678)

下面是一个小示例,用于读取和写入 FAT32卷。为了保持样本较小,省略了所有错误处理

请注意,直接访问
void ChangeSerialNumber(char volume, uint newSerial)
{
    var fsInfo = new[]
    {
        new { Name = "FAT32", NameOffs = 0x52, SerialOffs = 0x43 },
        new { Name = "FAT", NameOffs = 0x36, SerialOffs = 0x27 },
        new { Name = "NTFS", NameOffs = 0x03, SerialOffs = 0x48 }
    };

    using (var disk = new Disk(volume))
    {
        var sector = new byte[512];
        disk.ReadSector(0, sector);

        var fs = fsInfo.FirstOrDefault(
                f => Strncmp(f.Name, sector, f.NameOffs)
            );
        if (fs == null) throw new NotSupportedException("This file system is not supported");

        var s = newSerial;
        for (int i = 0; i < 4; ++i, s >>= 8) sector[fs.SerialOffs + i] = (byte)(s & 0xFF);

        disk.WriteSector(0, sector);
    }
}

bool Strncmp(string str, byte[] data, int offset)
{
    for(int i = 0; i < str.Length; ++i)
    {
        if (data[i + offset] != (byte)str[i]) return false;
    }
    return true;
}

class Disk : IDisposable
{
    private SafeFileHandle handle;

    public Disk(char volume)
    {
        var ptr = CreateFile(
            String.Format("\\\\.\\{0}:", volume),
            FileAccess.ReadWrite,
            FileShare.ReadWrite,
            IntPtr.Zero,
            FileMode.Open,
            0,
            IntPtr.Zero
            );

        handle = new SafeFileHandle(ptr, true);

        if (handle.IsInvalid) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    }

    public void ReadSector(uint sector, byte[] buffer)
    {
        if (buffer == null) throw new ArgumentNullException("buffer");
        if (SetFilePointer(handle, sector, IntPtr.Zero, EMoveMethod.Begin) == INVALID_SET_FILE_POINTER) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        uint read;
        if (!ReadFile(handle, buffer, buffer.Length, out read, IntPtr.Zero)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        if (read != buffer.Length) throw new IOException();
    }

    public void WriteSector(uint sector, byte[] buffer)
    {
        if (buffer == null) throw new ArgumentNullException("buffer");
        if (SetFilePointer(handle, sector, IntPtr.Zero, EMoveMethod.Begin) == INVALID_SET_FILE_POINTER) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        uint written;
        if (!WriteFile(handle, buffer, buffer.Length, out written, IntPtr.Zero)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        if (written != buffer.Length) throw new IOException();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (handle != null) handle.Dispose();
        }
    }

    enum EMoveMethod : uint
    {
        Begin = 0,
        Current = 1,
        End = 2
    }

    const uint INVALID_SET_FILE_POINTER = 0xFFFFFFFF;

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
        [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        int flags,
        IntPtr template);

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern uint SetFilePointer(
         [In] SafeFileHandle hFile, 
         [In] uint lDistanceToMove,
         [In] IntPtr lpDistanceToMoveHigh,
         [In] EMoveMethod dwMoveMethod);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool ReadFile(SafeFileHandle hFile, [Out] byte[] lpBuffer,
        int nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

    [DllImport("kernel32.dll")]
    static extern bool WriteFile(SafeFileHandle hFile, [In] byte[] lpBuffer,
        int nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
        [In] IntPtr lpOverlapped);
}
static uint GenericRead = 0x80000000;
static uint GenericWrite = 0x40000000;                       
static uint OpenExisting = 3;

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr SecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool GetDiskFreeSpace(string lpRootPathName, out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters, out uint lpTotalNumberOfClusters);

static void ReadAndSetSerialNumber()
{
  const string driveLetter = "e:"; // Drive with FAT32 file system.

  uint sectorsPerCluster;
  uint bytesPerSector;
  uint numberOfFreeClusters;
  uint totalNumberOfClusters;

  GetDiskFreeSpace(String.Format(@"{0}\", driveLetter), out sectorsPerCluster, out bytesPerSector,
    out numberOfFreeClusters, out totalNumberOfClusters);

  Console.Out.WriteLine("Info for drive {0}", driveLetter);
  Console.Out.WriteLine("Bytes per sector: {0}", bytesPerSector);

  const int fatSerialOffset = 0x43;
  const int fatIdOffset = 0x52;
  const string fatFileSystemId = "FAT32";

  using (SafeFileHandle sfh = CreateFile(String.Format("\\\\.\\{0}", driveLetter), GenericRead | GenericWrite,
    (uint)FileShare.ReadWrite, IntPtr.Zero, OpenExisting, 0, IntPtr.Zero))
  {
    using (FileStream fs = new FileStream(sfh, FileAccess.ReadWrite))
    {
      byte[] firstSector = new byte[bytesPerSector];

      fs.Read(firstSector, 0, (int)bytesPerSector);

      if (Encoding.ASCII.GetString(firstSector, fatIdOffset, fatFileSystemId.Length) == fatFileSystemId)
      {
        Console.Out.WriteLine("FAT32 file system found...");

        uint serial = BitConverter.ToUInt32(firstSector, fatSerialOffset);

        Console.Out.WriteLine("Read serial number: {0:X4}-{1:X4}", serial >> 16, serial & 0xFFFF);

        // Write new serial number.
        byte[] newserial = BitConverter.GetBytes((uint)10000123);

        Array.Copy(newserial, 0, firstSector, fatSerialOffset, newserial.Length);
        fs.Seek(0, SeekOrigin.Begin);
        fs.Write(firstSector, 0, (int)bytesPerSector); 
      }                   
    }
  }
}