• 1618阅读
  • 13回复

[讨论]关于windows下对磁盘DeviceIoControl操作时,碰到GetLastError 5的问题 [复制链接]

上一主题 下一主题
离线lwei24
 

只看楼主 倒序阅读 楼主  发表于: 2022-07-12
如题,在Qt中调用DeviceIoControl,控制码为FSCTL_LOCK_VOLUME,结果总是GetLastError 5拒绝访问,这个为啥呢?为啥用MFC就可以,用Qt就不能调用呢?具体代码如下:
  1. char diskPath[DISK_PATH_LEN];
  2.     sprintf(diskPath,"\\\\.\\PhysicalDrive%d",Disk);
  3.     HANDLE hDevice = CreateFileA(
  4.         diskPath,
  5.         GENERIC_READ | GENERIC_WRITE,
  6.         FILE_SHARE_READ | FILE_SHARE_WRITE,
  7.         NULL,           //default security attributes
  8.         OPEN_EXISTING,  // disposition
  9.         0,              // file attributes
  10.         NULL
  11.     );
  12.     DWORD ReturnedByteCount;
  13.     BOOL hDevice = DeviceIoControl(
  14.                 hDisk,
  15.                 FSCTL_LOCK_VOLUME,
  16.                 NULL,
  17.                 0,
  18.                 NULL,
  19.                 0,
  20.                 &ReturnedByteCount,
  21.                 NULL
  22.             );
  23.     qWarning()<<"ret="<<ret<<"err="<<GetLastError();

如上代码,ret=0,err=5,各位大佬,有什么办法可以解决这个问题吗?劳烦各位大佬们帮忙看看,给点解决办法,小弟在此多谢了!
离线feng851

只看该作者 1楼 发表于: 2022-07-12
是否需要提升权限,具体百度
离线lwei24

只看该作者 2楼 发表于: 2022-07-12
回 feng851 的帖子
feng851:是否需要提升权限,具体百度 (2022-07-12 17:52) 

这个,已经以管理员权限运行了,还需要再提升权限吗?
离线feng851

只看该作者 3楼 发表于: 2022-07-12
〖5〗-拒绝访问。

不是你运行时管理员权限,不是那个意思。是有个windows api函数,需要提前执行它以提升权限。
离线feng851

只看该作者 4楼 发表于: 2022-07-12
#define UNICODE 1
#define _UNICODE 1

/* The code of interest is in the subroutine GetDriveGeometry. The
   code in main shows how to interpret the results of the call. */

#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

#define wszDrive L"\\\\.\\PhysicalDrive0"

BOOL GetDriveGeometry(LPWSTR wszPath, DISK_GEOMETRY *pdg)
{
  HANDLE hDevice = INVALID_HANDLE_VALUE;  // handle to the drive to be examined
  BOOL bResult   = FALSE;                 // results flag
  DWORD junk     = 0;                     // discard results

  hDevice = CreateFileW(wszPath,          // drive to open
                        0,                // no access to the drive
                        FILE_SHARE_READ | // share mode
                        FILE_SHARE_WRITE,
                        NULL,             // default security attributes
                        OPEN_EXISTING,    // disposition
                        0,                // file attributes
                        NULL);            // do not copy file attributes

  if (hDevice == INVALID_HANDLE_VALUE)    // cannot open the drive
  {
    return (FALSE);
  }

  bResult = DeviceIoControl(hDevice,                       // device to be queried
                            IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
                            NULL, 0,                       // no input buffer
                            pdg, sizeof(*pdg),            // output buffer
                            &junk,                         // # bytes returned
                            (LPOVERLAPPED) NULL);          // synchronous I/O

  CloseHandle(hDevice);

  return (bResult);
}

int wmain(int argc, wchar_t *argv[])
{
  DISK_GEOMETRY pdg = { 0 }; // disk drive geometry structure
  BOOL bResult = FALSE;      // generic results flag
  ULONGLONG DiskSize = 0;    // size of the drive, in bytes

  bResult = GetDriveGeometry (wszDrive, &pdg);

  if (bResult)
  {
    wprintf(L"Drive path      = %ws\n",   wszDrive);
    wprintf(L"Cylinders       = %I64d\n", pdg.Cylinders);
    wprintf(L"Tracks/cylinder = %ld\n",   (ULONG) pdg.TracksPerCylinder);
    wprintf(L"Sectors/track   = %ld\n",   (ULONG) pdg.SectorsPerTrack);
    wprintf(L"Bytes/sector    = %ld\n",   (ULONG) pdg.BytesPerSector);

    DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *
               (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
    wprintf(L"Disk size       = %I64d (Bytes)\n"
            L"                = %.2f (Gb)\n",
            DiskSize, (double) DiskSize / (1024 * 1024 * 1024));
  }
  else
  {
    wprintf (L"GetDriveGeometry failed. Error %ld.\n", GetLastError ());
  }

  return ((int)bResult);
}

你的sprintf(diskPath,"\\\\.\\PhysicalDrive%d",Disk);是不是不存在啊?
离线lwei24

只看该作者 5楼 发表于: 2022-07-12
回 feng851 的帖子
feng851:#define UNICODE 1
#define _UNICODE 1
/* The code of interest is in the subroutine GetDriveGeometry. The
   code in main shows how to interpret the results of the call. */
....... (2022-07-12 17:59) 

这个是有的sprintf(diskPath,"\\\\.\\PhysicalDrive%d",Disk);,就是在Qt下,不知道怎么好像不太适应,即获取到\\.\PhysicalDrive%d这个路径,后面FSCTL_LOCK_VOLUME的时候总会GetLastError 5错误。
离线lwei24

只看该作者 6楼 发表于: 2022-07-12
回 feng851 的帖子
feng851:#define UNICODE 1
#define _UNICODE 1
/* The code of interest is in the subroutine GetDriveGeometry. The
   code in main shows how to interpret the results of the call. */
....... (2022-07-12 17:59) 

其实在FSCTL_LOCK_VOLUME前,我还调用了IOCTL_DISK_GET_DRIVE_LAYOUT_EX、IOCTL_DISK_DELETE_DRIVE_LAYOUT这两个控制码,也没有看见它报错GetLastError 5,不知道为什么到了FSCTL_LOCK_VOLUME这个控制码,它就报错5 - 拒绝访问
离线feng851

只看该作者 7楼 发表于: 2022-07-13
FSCTL_LOCK_VOLUME IOCTL (winioctl.h)

Locks a volume if it is not in use. A locked volume can be accessed only through handles to the file object (*hDevice) that locks the volume. For more information, see the Remarks section.


你插个优盘,不打开它,然后FSCTL_LOCK_VOLUME IOCTL这个优盘的试试?
离线lwei24

只看该作者 8楼 发表于: 2022-07-22
回 feng851 的帖子
feng851:FSCTL_LOCK_VOLUME IOCTL (winioctl.h)
Locks a volume if it is not in use. A locked volume can be accessed only through handles to the file object (*hDevice) that locks the volume. For more information, see the Remarks section.
....... (2022-07-13 08:32) 

试了很多次,还是GetLastError 5
离线feng851

只看该作者 9楼 发表于: 2022-07-22
会不会在之前先要调用FSCTL_DISMOUNT_VOLUME?
离线lwei24

只看该作者 10楼 发表于: 2022-07-22
回 feng851 的帖子
feng851:会不会在之前先要调用FSCTL_DISMOUNT_VOLUME?[表情]  (2022-07-22 17:17) 

在MFC上的项目迁移到Qt上,MFC运行是没有问题,但是到了Qt上的FSCTL_LOCK_VOLUME 锁盘操作就报错GetLastError 5。即使是刚刚插入的硬盘,什么也没有操作,直接调试,仍然是在锁盘位置GetLastError 5。其实在锁盘之前还创建句柄、销毁分区IOCTL_DISK_DELETE_DRIVE_LAYOUT、刷新IOCTL_DISK_UPDATE_PROPERTIES也没有问题,不知道为啥一到锁盘就报错5了……
离线feng851

只看该作者 11楼 发表于: 2022-07-22
都是调用winapi,不可能mfc换成了qt就会出现什么问题,根子上还是win sdk,要么你FSCTL_LOCK_VOLUME 操作之前,是不是做了其它的FSCTL操作未完成导致拒绝了LOCK_VOLUME,要么就是你插入硬盘后,你电脑系统某些软件自动访问了该硬盘的文件导致。
离线lwei24

只看该作者 12楼 发表于: 2022-07-25
回 feng851 的帖子
feng851:都是调用winapi,不可能mfc换成了qt就会出现什么问题,根子上还是win sdk,要么你FSCTL_LOCK_VOLUME 操作之前,是不是做了其它的FSCTL操作未完成导致拒绝了LOCK_VOLUME,要么就是你插入硬盘后,你电脑系统某些软件自动访问了该硬盘的文件导致。 (2022-07-22 18:00) 

锁盘之前,只做了IOCTL_DISK_DELETE_DRIVE_LAYOUT、IOCTL_DISK_UPDATE_PROPERTIES这两个操作,MFC下同等的代码,Qt的确是不行呀,我都试了很多次了,目前还没有找到问题所在……
离线feng851

只看该作者 13楼 发表于: 2022-07-25
你编译器用的Mingw还是vc?mfc下的tchar是wchar么?是不是同qt中的设置的相同?是不是unicode的设置的不同?
快速回复
限100 字节
 
上一个 下一个