DeviceIoControl是否能够处理重叠和不重叠的句柄?

时间:2019-07-18 06:12:05

标签: windows winapi storage

需要支持在多线程环境中打开有无 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 !!

0 个答案:

没有答案