需要支持在多线程环境中打开有无 FILE_FLAG_OVERLAPPED
的句柄。我想出了以下方法,但是想知道是否有更好的方法,尤其是是否有一种方法可以在文件句柄上重置事件并再次等待而不是旋转(即使我不希望有很多冲突)?
//
// Helper for device opened with or without FILE_FLAG_OVERLAPPED
//
static inline BOOL DeviceIoControlFlex(
_In_ HANDLE hdevice,
_In_ DWORD dwiocontrolcode,
_In_opt_ LPVOID lpinbuffer,
_In_ DWORD ninbuffersize,
_Out_opt_ LPVOID lpoutbuffer,
_In_ DWORD noutbuffersize,
_Out_opt_ LPDWORD lpbytesreturned,
_Inout_opt_ LPOVERLAPPED lpoverlapped
)
{
volatile OVERLAPPED overlapped={ 0 };
BOOL diocresult=DeviceIoControl(hdevice,
dwiocontrolcode,
lpinbuffer,
ninbuffersize,
lpoutbuffer,
noutbuffersize,
lpbytesreturned,
lpoverlapped ? lpoverlapped : (LPOVERLAPPED) &overlapped);
// complete operation synchronously if opened in overlapped mode
if (!diocresult && GetLastError()==ERROR_IO_PENDING) {
// check if we wait
if (lpoverlapped==NULL) {
DWORD bytesreturned=0;
diocresult=GetOverlappedResult(hdevice, (LPOVERLAPPED) &overlapped, &bytesreturned, TRUE);
// make sure actually completed since waiting on file handle. If not spin
if (overlapped.Internal==STATUS_PENDING) {
while (overlapped.Internal==STATUS_PENDING) {
CPUPAUSE;
}
bytesreturned=overlapped.InternalHigh;
if (!NT_SUCCESS((NTSTATUS)overlapped.Internal)) {
diocresult=FALSE;
SetLastError(RtlNtStatusToDosError((NTSTATUS)overlapped.Internal));
}
else diocresult=TRUE;
}
// handle optional bytes to return
if (lpbytesreturned) {
*lpbytesreturned=bytesreturned;
}
}
}
return diocresult;
}
注意:这实际上可能不起作用,具体取决于内部处理方式GetOverlappedResult
,如果它在检查结果之前获取了字节数,则可能返回的字节数是错误的(在访问该字段之后立即完成)
TIA !!