6

I am trying to call DeviceIO functions asynchronously by using the OVERLAPPED structure as described on MSDN. I am using the FSCTL_ENUM_USN_DATA control code to enumerate the MFT of NTFS drives but i am not able to run it asynchronously. The file handle is created with FILE_FLAG_OVERLAPPED but there is no difference whether I use the overlapped structure with FILE_FLAG_OVERLAPPED or not. The function does not return immediately. Is seems to be synchronous in both cases. The example below shows the enumeration of the first 100.000 MFT entries on the C:\ drive. Since I am not so familiar with the usage of overlapped structures maybe I did something wrong. My question: How can I execute DeviceIoControl(hDevice, FSCTL_ENUM_USN_DATA,...) asynchronously? Thanks for any help.

#include "stdafx.h"
#include <Windows.h>

typedef struct {
  DWORDLONG  nextusn;
  USN_RECORD FirstUsnRecord;
  BYTE Buffer[500];
}TDeviceIoControlOutputBuffer, *PTDeviceIoControlOutputBuffer;

int _tmain(int argc, _TCHAR* argv[])
{
    MFT_ENUM_DATA lInputMftData;
    lInputMftData.StartFileReferenceNumber = 0;
    lInputMftData.MinMajorVersion = 2;
    lInputMftData.MaxMajorVersion = 3;
    lInputMftData.LowUsn = 0;
    lInputMftData.HighUsn = 0;

    TDeviceIoControlOutputBuffer lOutputMftData;
    DWORD lOutBytesReturned = 0;
    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    OVERLAPPED  lOverlapped = { 0 };
    lOverlapped.hEvent = hEvent;
    LPCWSTR path = L"\\\\.\\C:";
    HANDLE hDevice = CreateFile(path, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (hDevice != INVALID_HANDLE_VALUE) {
        lOutputMftData.nextusn = 0;
        while (lOutputMftData.nextusn < 100000) {
            lInputMftData.StartFileReferenceNumber = lOutputMftData.nextusn;
            BOOL result = DeviceIoControl(hDevice, FSCTL_ENUM_USN_DATA, &lInputMftData, sizeof(lInputMftData), &lOutputMftData, sizeof(lOutputMftData), &lOutBytesReturned, &lOverlapped);
        }
    }
}
4

2 回答 2

2

TL:DR - 如果收到您的请求的驱动程序将其挂起,您只会获得异步行为。

当您调用 DeviceIoControl 并传递一个重叠结构时,它不保证操作将是异步的。这意味着它可以是异步的。这取决于将接收您的请求的驱动程序的实现方式。当您运行 DeviceIoControl 时,它会创建一个 irp 并将其发送给驱动程序。DeviceIoControl 会将您的线程提升到内核模式以创建和调度 irp。将在该线程上调用驱动程序的回调来处理请求。如果驱动程序决定立即处理(并完成)请求,则请求同步完成。在此流程中,是否使用 FILE_FLAG_OVERLAPPED 打开驱动程序没有区别。如果驱动程序决定挂起请求,那么您将看到真正的异步行为。DeviceIoControl 将返回 FALSE,GetLastError 将返回 ERROR_IO_PENDING。

于 2020-01-28T11:50:34.817 回答
0
HEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
OVERLAPPED  lOverlapped = { 0 };
lOverlapped.hEvent = hEvent;

...

BOOL result = DeviceIoControl(hDevice, FSCTL_ENUM_USN_DATA, &lInputMftData, sizeof(lInputMftData), &lOutputMftData, sizeof(lOutputMftData), &lOutBytesReturned, &lOverlapped);

// If operation is asynchronous, wait for hEvent here or somewhere else
于 2014-07-08T14:50:41.947 回答