【问题标题】:How to get a windows HANDLE from a QFile or QSaveFile for ReOpenFile?如何从 QFile 或 QSaveFile 获取 Windows HANDLE 以用于 ReOpenFile?
【发布时间】:2018-05-05 16:11:47
【问题描述】:

给定一个QFileDevice 实例(QFileQSaveFile) - 如何获得文件的本机 Windows HANDLE?这个句柄可以和ReOpenFile一起使用吗?

【问题讨论】:

    标签: windows qt winapi handle qfile


    【解决方案1】:

    QFileDevice::handle() 返回从QFSFileEnginePrivate::nativeHandle 获得的 C 文件描述符(fd - 一个小整数)。那个文件描述符就是你从_open_osfhandle 得到的。您需要使用_get_osfhandle 回到HANDLE

    struct FdHandle {
      int fd = -1;
      HANDLE handle = INVALID_HANDLE_VALUE;
      operator HANDLE() const { return handle; }
      bool isFdValid() const { return fd != -1; }
      bool isHandleValid() const { return handle != INVALID_HANDLE_VALUE; }
    };
    
    FdHandle windowsHandleOf(QFileDevice* dev) {
      auto fd = dev->handle(); 
      return {fd, (HANDLE)_get_osfhandle(fd)};
    }
    

    ReOpenFile 可能会返回不同的文件句柄,因此您可能需要为它重新打开文件。一个重载的ReOpenFile 处理它:

    struct ReOpenResult {
      enum { OK = 0, FileClosed = 10, NoHandle = 20, 
             OldHandle = 30, OpenFailed = 40 } rc;
      HANDLE handle = INVALID_HANDLE_VALUE;
      operator HANDLE() const { return handle; }
      explicit operator bool() const { return rc == OK; }
      bool isHandleValid() const { return handle != INVALID_HANDLE_VALUE; }
    };
    
    ReOpenResult ReOpenFile(QFile *file, DWORD access, DWORD shareMode, DWORD flags) {
      if (!file->isOpen())
        return {ReOpenResult::FileClosed};
      auto oldHandle = windowsHandleOf(file);
      if (oldHandle == INVALID_HANDLE_VALUE)
        return {ReOpenResult::NoHandle};
      auto newHandle = ReOpenFile(oldHandle, access, shareMode, flags);
      if (newHandle == INVALID_HANDLE_VALUE)
        return {ReOpenResult::OldHandle, oldHandle};
      if (!open(file, file->openMode(), newHandle))
        return {ReOpenResult::OpenFailed, oldHandle};
      return {ReOpenResult::OK, newHandle};
    }
    

    采用HANDLE 的“缺失”open 是:

    struct OpenResult {
      enum { OK = 0, SameHandleOK = 1, InvalidHandle = 10, CCloseFailed = 20,
             InvalidFd = 30, OpenFailed = 40 } rc = OK;
      explicit operator bool() const { return rc < InvalidHandle; };
    };
    
    OpenResult open(QFile* file, QIODevice::OpenMode mode, HANDLE handle) {
      if (handle == INVALID_HANDLE_VALUE)
        return {OpenResult::InvalidHandle};
      if (file->isOpen() && windowsHandleOf(file) == handle)
        return {OpenResult::SameHandleOK};
      file->close();
      if (auto fd = file->handle() != -1)
        if (_close(fd)) // the C handle is still open, don't leak it
          return {OpenResult::CCloseFailed};
      int flags = 0;
      if (mode & QIODevice::Append)
        flags |= _O_APPEND;
      if (!(mode & QIODevice::WriteOnly))
        flags |= _O_RDONLY;
      auto fd = _open_osfhandle((intptr_t)handle, flags);
      if (fd == -1)
        return {OpenResult::InvalidFd};
      if (!file->open(fd, mode, QFileDevice::AutoCloseHandle))
        return {OpenResult::OpenFailed};
      return {};
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多