我试图通过使用MSDN上描述的OVERLAPPED结构异步调用DeviceIO函数。 我使用FSCTL_ENUM_USN_DATA控制代码枚举NTFS驱动器的MFT,但我无法异步运行它。文件句柄是使用FILE_FLAG_OVERLAPPED创建的,但是我是否使用FILE_FLAG_OVERLAPPED的重叠结构没有区别。该功能不会立即返回。在这两种情况下似乎都是同步的。 下面的示例显示了C:\驱动器上前100.000个MFT条目的枚举。 由于我不太熟悉重叠结构的使用,我可能做错了。我的问题:如何异步执行DeviceIoControl(hDevice,FSCTL_ENUM_USN_DATA,...)?感谢您的帮助。
#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);
}
}
}
答案 0 :(得分:1)
TL:DR-仅当收到请求的驱动程序将其挂起时,您才会获得异步行为。
当您调用DeviceIoControl并传递一个重叠的结构时,它不能保证该操作将是异步的。这意味着它可以是异步的。这取决于将接收您的请求的驱动程序的实现方式。 运行DeviceIoControl时,它将创建一个IRP并将其发送到驱动程序。 DeviceIoControl会将您的线程提升为内核模式,以创建和调度irp。驱动程序的回调将在该线程上被调用以处理请求。如果驱动程序决定立即处理(并完成)该请求,则该请求将同步完成。在此流程中,是否使用FILE_FLAG_OVERLAPPED打开驱动程序之间没有区别。 如果驱动程序决定请求,那么您将看到真正的异步行为。 DeviceIoControl将返回FALSE,而GetLastError将返回ERROR_IO_PENDING。这意味着IRP即将完成,并且在IRP完成时会发出信号通知您在OVERLAPPED结构中提供的事件。
答案 1 :(得分: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