如何从QFile或QSaveFile获取Windows Handle以获取ReOpenFile? [英] How to get a windows HANDLE from a QFile or QSaveFile for ReOpenFile?

查看:275
本文介绍了如何从QFile或QSaveFile获取Windows Handle以获取ReOpenFile?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出一个QFileDevice实例(一个QFileQSaveFile)-如何获取文件的本机Windows HANDLE?可以将此手柄与ReOpenFile一起使用吗?

Given a QFileDevice instance (a QFile, or QSaveFile) - how would one get the native Windows HANDLE of the file? And can this handle be used with ReOpenFile?

推荐答案

QFileDevice::handle() 返回从fd-一个小整数). cpp.html#_ZNK20QFSFileEnginePrivate12nativeHandleEv"rel =" nofollow noreferrer> QFSFileEnginePrivate::nativeHandle .该文件描述符就是您从 _open_osfhandle .您需要使用 _get_osfhandle 返回到HANDLE.

The QFileDevice::handle() returns a C file descriptor (fd - a small integer) obtained from QFSFileEnginePrivate::nativeHandle. That file descriptor is what you'd get from _open_osfhandle. You need to use _get_osfhandle to go back to a 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 {};
}

这篇关于如何从QFile或QSaveFile获取Windows Handle以获取ReOpenFile?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆