文件创建失败。第二次成功

Failed to Create File. Second time it succeeds

首先抱歉 - 对于这个问题,完全不可能创建一个最小的示例,因为涉及到一些专用硬件。

所以.. 我们已经构建了一个通过 USB 连接到 PC 并模拟 SD 卡的记录设备(显示为驱动器)。该驱动器最初是只读的 但可以通过写入特殊扇区(在 MBR 和 FAT 之间)切换到 read/write 操作,以便可以在该驱动器上创建文件。

到目前为止一切顺利。现在 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 驱动器实际上没有写保护? 我尝试了一些IO控制代码: IOCTL检查验证 IOCTLUpdateProperties

但没有成功。

我不希望有任何代码,但有些想法会受到高度赞赏。

一点说明: fMK5UsbComm 拥有 2 个句柄:一个指向卷,一个指向与卷关联的物理设备。物理设备句柄首先以只读方式打开,然后进行特殊的读取操作,取消设备中的只读标志,然后重新打开句柄 read/write(以允许与设备进行特殊通信)。

好吧,我想我现在明白了 - 所以这仅适用于最终可能落入同样陷阱的任何人:

  1. 驱动器句柄是通过发出 SYNCHRONIZED 访问标志而不是 GENERIC_READ 或 GENERIC_WRITE 获得的。这加快了设备的检测速度,因为它当时没有完全安装(例如,读取该设备上的 FAT 很慢),但可以进行较低级别的调用。
  2. 我需要关闭驱动器句柄,使用 GENERIC_READ 或 GENERIC_WRITE 重新打开它,发出 FSCTL_DISMOUNT_VOLUME 命令,然后再次重新打开安装驱动器的驱动器句柄并让 windows更新内部卷信息。