Skip to content

Commit

Permalink
Fea, GetQueuedCompletionStatusEx添加可警告状态支持
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed Oct 4, 2023
1 parent 8b3d2b0 commit b79ce32
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 9 deletions.
2 changes: 1 addition & 1 deletion ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@
| IsNativeVhdBoot | 不存在时,调用NtQuerySystemInformation。
| RtlCaptureStackBackTrace | 调用ntdll.RtlCaptureStackBackTrace。
| SetFileCompletionNotificationModes | 不存在时,什么也不做。
| GetQueuedCompletionStatusEx | 不存在时,调用 GetQueuedCompletionStatus,注意:丢失可警报状态支持
| GetQueuedCompletionStatusEx | 不存在时,调用 GetQueuedCompletionStatus。
| FindFirstFileEx(W/A) | Windows XP、Vista兼容 FIND_FIRST_EX_LARGE_FETCH、FindExInfoStandard参数。

## mfplat.dll
Expand Down
83 changes: 75 additions & 8 deletions src/Thunks/api-ms-win-core-io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,82 @@ namespace YY

auto& _Entry = lpCompletionPortEntries[0];

// TODO: 已知问题:可警报状态丢失!(fAlertable)
auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, dwMilliseconds);
if (_bRet)
{
*ulNumEntriesRemoved = 1;
}
return _bRet;
if (fAlertable)
{
// 使用 WaitForSingleObjectEx 进行等待触发 APC
auto _uStartTick = GetTickCount();
for (;;)
{
const auto _uResult = WaitForSingleObjectEx(CompletionPort, dwMilliseconds, TRUE);
if (_uResult == WAIT_OBJECT_0)
{
// 完成端口有数据了
auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, 0);
if (_bRet)
{
*ulNumEntriesRemoved = 1;
break;
}

if (GetLastError() != WAIT_TIMEOUT)
{
return FALSE;
}

// 无限等待时无脑继续等即可。
if (dwMilliseconds == INFINITE)
{
continue;
}

// 计算剩余等待时间,如果剩余等待时间归零则返回
const DWORD _uTickSpan = GetTickCount() - _uStartTick;
if (_uTickSpan >= dwMilliseconds)
{
SetLastError(WAIT_TIMEOUT);
return FALSE;
}
dwMilliseconds -= _uTickSpan;
_uStartTick += _uTickSpan;
continue;
}
else if (_uResult == WAIT_IO_COMPLETION || _uResult == WAIT_TIMEOUT)
{
// 很奇怪,微软原版遇到 APC唤醒直接会设置 LastError WAIT_IO_COMPLETION
// 遇到超时,LastError WAIT_TIMEOUT(注意不是预期的 ERROR_TIMEOUT)不知道是故意还是有意。
SetLastError(_uResult);
return FALSE;
}
else if (_uResult == WAIT_ABANDONED)
{
SetLastError(ERROR_ABANDONED_WAIT_0);
return FALSE;
}
else if (_uResult == WAIT_FAILED)
{
// LastError
return FALSE;
}
else
{
// LastError ???
return FALSE;
}
}

return TRUE;
}
else
{
auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, dwMilliseconds);
if (_bRet)
{
*ulNumEntriesRemoved = 1;
}
return _bRet;
}
}
#endif
}//namespace Thunks

} //namespace YY
} //namespace YY

0 comments on commit b79ce32

Please sign in to comment.