Хотя ответ @MSalters имеет смысл, это не то, как работает мой код.На самом деле это настолько нелогично, что я потратил несколько дней, чтобы убедиться, что код на самом деле работает.
Эти фрагменты кода находятся в проверенном программном продукте массового рынка.Когда ему нужно изменить структуру на диске, он отключает том win32, чтобы он мог изменять структуры файловой системы NTFS или FAT.Интересно, что дескриптор доступа к тому доступен только для чтения:
char fn [30];
snprintf (fn, sizeof fn, "\\\\.\\%s:", vol -> GetVolName ());
vol_handle = CreateFile (fn, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS,
NULL);
if (vol_handle == INVALID_HANDLE_VALUE)
{
// show error message and exit
}
Если не удается получить доступ на запись к тому или разделу, этот код принудительно отключается, если пользователь разрешает такое после строгого предупреждения:
if (!DeviceIoControl (vol_handle, FSCTL_DISMOUNT_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
{
DWORD err = GetLastError ();
errormsg ("Error %d attempting to dismount volume: %s",
err, w32errtxt (err));
}
// lock volume
if (!DeviceIoControl (vol_handle, FSCTL_LOCK_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
{
// error handling; not sure if retrying is useful
}
Запись тогда довольно проста, за исключением позиционирования указателя файла по 512-байтному сектору:
long hipart = sect >> (32-9);
long lopart = sect << 9;
long err;
SetLastError (0); // needed before SetFilePointer post err detection
lopart = SetFilePointer (vol_handle, lopart, &hipart, FILE_BEGIN);
if (lopart == -1 && NO_ERROR != (err = GetLastError ()))
{
errormsg ("HWWrite: error %d seeking drive %x sector %ld: %s",
err, drive, sect, w32errtxt (err));
return false;
}
DWORD n;
if (!WriteFile (vol_handle, buf, num_sects*512, &n, NULL))
{
err = GetLastError ();
errormsg ("WriteFile: error %d writing drive %x sectors %lu..%lu: %s",
err, drv, sect, sect + num_sects - 1,
w32errtxt (err));
return false;
}