直接写入物理磁盘(Windows-winapi)

时间:2019-04-07 21:36:08

标签: c++ c windows winapi io

我需要直接写一些物理设备。我遵循下面列出的帖子和下面的MSDN页面中给出的指示。但是我的代码仍然在函数writeDisk(HANDLE hDevice)中失败,错误代码为:
[87] The parameter is incorrect
但是问题的根源似乎并不存在。

除此之外。卸载设备后,它无法工作(我仍然可以从系统资源管理器中访问它),锁定设备后也会发生同样的情况。

我已经检查了以下链接:
* Microsoft Docs: Calling DeviceIoControl
* StackOverflow: How to explicitly lock a mounted file system?
* StackOverflow: CreateFile: direct write operation to raw disk "Access is denied"
* StackOverflow: Can I get write access to raw disk sectors under Vista and Windows 7 in user mode?

但可悲的是,它们都不适合我。最有用的线程是前两个。

这是我的代码。编译后,您必须在具有管理员权限的情况下运行该应用程序,以便以WRITE访问权限打开设备:

/* This program attempts to directly write to a device (without respecting the file system) */

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

BOOL dismountDisk(HANDLE hDevice);
BOOL lockDisk(HANDLE hDevice);
BOOL writeDisk(HANDLE hDevice);
void getSystemMessageString(DWORD errorCode, char *decodedMessage, unsigned long size);

/* Main function
   * Access the device
   * Dismount the device
   * Lock the device explicitly
   * Write to the device
   * Close handler
*/
int main()
{
    /* Access the device */
    HANDLE hDevice = CreateFileA(
        "\\\\.\\PHYSICALDRIVE2", /* device id (get it with `$ wmic DISKDRIVE`) */
        FILE_READ_DATA | FILE_WRITE_DATA, /* read/write access */
        FILE_SHARE_READ | FILE_SHARE_WRITE, /* shared */
        NULL, /* default security attributes */
        OPEN_EXISTING, /* only open if the device exists */
        0, /* file attributes */
        NULL); /* do not copy file attributes */

    if (hDevice == INVALID_HANDLE_VALUE) { /* cannot open the physical drive */
        fprintf(stderr, "Cannot open the device\n");
    } else { /* dismount and lock */
        BOOL result = dismountDisk(hDevice) && lockDisk(hDevice); /* try to dismount and lock the device */
        if (!result) { /* device not dismounted/locked */
            abort(); /* abort the operation */
        } else { /* OK */
            fprintf(stderr, "All OK. Check if the device has been dismounted and locked and press return to write.\n");
            getchar();
            writeDisk(hDevice); /* write to the disk */
        }
        CloseHandle(hDevice); /* close the handler to the device */
    }

    return 0;
}

/* Dismount disk */
BOOL dismountDisk(HANDLE hDevice)
{
    DWORD unused;
    BOOL b = DeviceIoControl(hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &unused, NULL);
    if (!b) {
        DWORD errorCode = GetLastError();
        char strBuff[500] = {0}; /* save the error message here */
        getSystemMessageString(errorCode, strBuff, 500);
        fprintf(stderr, "Error dismounting the device: [%lu] %s\n", errorCode, strBuff); /* print the error code and message */
    }
    return b;
}

/* Lock disk */
BOOL lockDisk(HANDLE hDevice)
{
    DWORD unused;
    BOOL b = DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &unused, NULL);
    if (!b) {
        DWORD errorCode = GetLastError();
        char strBuff[500] = {0}; /* save the error message here */
        getSystemMessageString(errorCode, strBuff, 500);
        fprintf(stderr, "Error locking the device: [%lu] %s\n", errorCode, strBuff); /* print the error code and message */
    }
    return b;
}

/* Write disk */
BOOL writeDisk(HANDLE hDevice)
{
    BYTE buffer[1000]; /* write 100 bytes */
    DWORD bytesWritten; /* to get the total amount of bytes written */
    BOOL b = WriteFile(hDevice, buffer, sizeof (buffer), &bytesWritten, NULL);
    if (!b) {
        DWORD errorCode = GetLastError();
        char strBuff[500] = {0}; /* save the error message here */
        getSystemMessageString(errorCode, strBuff, 500);
        fprintf(stderr, "Error writting the device: [%lu] %s\n", errorCode, strBuff); /* print the error code and message */
    } else {
        fprintf(stderr, "%lu bytes written.\n", bytesWritten);
    }
    return b;
}

/* Convert the error code returned by GetLastError into a human-readable string */
void getSystemMessageString(DWORD errorCode, char *decodedMessage, unsigned long size)
{
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
                  NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  decodedMessage, size + 1, NULL);
    SetLastError(0); /* clear the last error */
}

0 个答案:

没有答案