Не удалось создать файл. Второй раз это удается - PullRequest
0 голосов
/ 09 мая 2018

Извините сначала - для этой проблемы совершенно невозможно создать минимальный пример, так как задействовано какое-то специализированное оборудование.

Итак. Мы создали записывающее устройство, которое подключается к ПК через USB и имитирует SD-карту (отображается как диск). Диск изначально только для чтения но его можно переключать на операции чтения / записи, записывая в специальный сектор (между MBR и FAT), чтобы на этом диске можно было создавать файлы.

Пока все хорошо. Теперь кажется, что Windows создает некоторые всплески, когда файл создается, жалуясь, что носитель только для чтения. Вторая попытка создать файл действительно удалась.

Вот код, который выполняется:

 if not (fMK5UsbComm as TMK5USBComm).IsWritable then
    raise Exception.Create('WTF');

 try
 fs:=TFileStream.Create(fMK5UsbComm.DriveLetter + ':\Tom24.ini', fmCreate   or fmOpenReadWrite);
 try
    fs.WriteBuffer(ss[1], length(ss));
 finally
        fs.Free;
 end;
 except
 fs:=TFileStream.Create(fMK5UsbComm.DriveLetter + ':\Tom24.ini', fmCreate   or fmOpenReadWrite);
 try
    fs.WriteBuffer(ss[1], length(ss));
 finally
        fs.Free;
 end;

 end;

IsWritable определяется как:

 function TVolume.IsWritable: boolean;
 var numBytesReturned : DWORD;
 begin
      numBytesReturned := 0;

      Result := DeviceIoControl( fHandle,
                                 IOCTLDiskIsWritable,
                                 nil,
                                 0,
                                 nil,
                                 0,
                                 numBytesReturned,
                                 nil);

      if not Result then
      begin
           if GetLastError <> ERROR_WRITE_PROTECT then
              RaiseLastOSError;
      end;
 end;

Итак, вопрос в том, почему вторая попытка прошла успешно, а первая - нет?

Как я могу сообщить Windows, что диск на самом деле не защищен от записи? Я попробовал несколько управляющих кодов ввода-вывода: IOCTLCheckVerify IOCTLUpdateProperties

но безуспешно.

Я не ожидаю какого-либо кода, но некоторые мысли будут высоко оценены.

Небольшое уточнение: fMK5UsbComm содержит 2 дескриптора: один для тома и один для физического устройства, связанного с томом. Сначала дескриптор физического устройства открывается только для чтения, выполняется специальная операция чтения, которая отменяет флаг «только чтение» в устройстве, а затем ручка вновь открывается для чтения / записи (чтобы обеспечить специальную связь с устройством).

1 Ответ

0 голосов
/ 15 мая 2018

Хорошо, я думаю, что получил это сейчас - так что это только для тех, кто может в конечном итоге попасть в ту же ловушку:

  1. Дескриптор диска был получен путем выдачи флага доступа SYNCHRONIZED вместо GENERIC_READ или GENERIC_WRITE. Это ускоряет обнаружение устройства, так как оно не полностью смонтировано в это время (например, чтение FAT, которое медленно на этом устройстве), но возможны вызовы более низкого уровня.
  2. Мне нужно было закрыть дескриптор диска, снова открыть его с помощью GENERIC_READ или GENERIC_WRITE, выполнить команду FSCTL_DISMOUNT_VOLUME, а затем снова открыть дескриптор диска, который монтирует диск и позволяет окнам обновлять информацию внутреннего тома.
...