如何以编程方式从C#更改Fat32分区的卷序列。我找到了this example,但是它是用C ++编写的,我不太清楚。有人可以回答C#代码段吗?
更新:
我可以从上面的示例中看到C ++函数,我认为可以将端口定向到C#
void CVolumeSerialDlg::ChangeSerialNumber(DWORD Drive, const DWORD newSerial)
{
const max_pbsi = 3;
struct partial_boot_sector_info
{
LPSTR Fs; // file system name
DWORD FsOffs; // offset of file system name in the boot sector
DWORD SerialOffs; // offset of the serialnumber in the boot sector
};
partial_boot_sector_info pbsi[max_pbsi] =
{
{"FAT32", 0x52, 0x43},
{"FAT", 0x36, 0x27},
{"NTFS", 0x03, 0x48}
};
TCHAR szDrive[12];
char Sector[512];
DWORD i;
sprintf(szDrive, "%c:\\", Drive & 0xFF);
if (!disk.Open(szDrive))
{
ShowErrorString("Could not open disk!");
return;
}
// read sector
if (!disk.ReadSector(0, Sector))
{
ShowErrorString("Could not read sector!");
return;
}
// try to search for a valid boot sector
for (i=0;i<max_pbsi;i++)
{
if (strncmp(pbsi[i].Fs, Sector+pbsi[i].FsOffs, strlen(pbsi[i].Fs)) == 0)
{
// we found a valid signature
break;
}
}
if (i >= max_pbsi)
{
MessageBox(_T("Cannot change serial number of this file system!"),
_T("Error"), MB_ICONERROR);
return;
}
// patch serial number
*(PDWORD)(Sector+pbsi[i].SerialOffs) = newSerial;
// write boot sector
if (!disk.WriteSector(0, Sector))
{
ShowErrorString("Could not write sector!");
return;
}
ShowErrorString("Volume serial number changed successfully!\r"
"You might want to restart your system for changes to take effect!");
}
最佳答案
没有保证,要小心。
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);
}
使用例如
ChangeSerialNumber('D', 0x12345678);