Skip to content

Commit

Permalink
* Fea #60, 添加Tokio支持
Browse files Browse the repository at this point in the history
  - 添加 SetFileCompletionNotificationModes
  - 添加 GetQueuedCompletionStatusEx
  - 添加 NtCancelIoFileEx
  • Loading branch information
mingkuang-Chuyu committed Oct 1, 2023
1 parent 9847db4 commit 4b45145
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 20 deletions.
7 changes: 7 additions & 0 deletions ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
| GetFirmwareType | 不存在时,调用NtQuerySystemInformation。
| IsNativeVhdBoot | 不存在时,调用NtQuerySystemInformation。
| RtlCaptureStackBackTrace | 调用ntdll.RtlCaptureStackBackTrace。
| SetFileCompletionNotificationModes | 不存在时,什么也不做。
| GetQueuedCompletionStatusEx | 不存在时,调用 GetQueuedCompletionStatus,注意:丢失可警报状态支持。

## mfplat.dll
| 函数 | Fallback
Expand All @@ -305,6 +307,11 @@
| NetGetAadJoinInformation | 不存在时,始终认为没有加入 Azure AD 帐户 账号。
| NetFreeAadJoinInformation | 不存在时,什么也不做。

## ntdll.dll
| 函数 | Fallback
| ---- | -----------
| NtCancelIoFileEx | 不存在时,调用 NtCancelIoFile。注意:将取消此文件的所有IO请求。

## ole32.dll
| 函数 | Fallback
| ---- | -----------
Expand Down
9 changes: 9 additions & 0 deletions src/Shared/km.h
Original file line number Diff line number Diff line change
Expand Up @@ -5104,6 +5104,15 @@ LdrAddRefDll(
IN PVOID BaseAddress
);

EXTERN_C NTSTATUS NTAPI NtCancelIoFileEx(HANDLE handle, IO_STATUS_BLOCK* io, IO_STATUS_BLOCK* io_status);

EXTERN_C
NTSTATUS
NTAPI
NtCancelIoFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock);

#if defined __cplusplus && !defined _Disallow_YY_KM_Namespace
} //namespace YY
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/Thunks/YY_Thunks.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// 忽略非标准的 0 数组警告。
#pragma warning(disable:4200)
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#define _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) \
_APPLY(ntdll, "ntdll" , USING_UNSAFE_LOAD ) \
Expand Down Expand Up @@ -57,6 +58,7 @@
_APPLY(LdrLoadDll, ntdll ) \
_APPLY(RtlDllShutdownInProgress, ntdll ) \
_APPLY(RtlCutoverTimeToSystemTime, ntdll ) \
_APPLY(NtCancelIoFile, ntdll ) \
_APPLY(AddDllDirectory, kernel32 ) \
_APPLY(SystemFunction036, advapi32 )

Expand Down
43 changes: 43 additions & 0 deletions src/Thunks/api-ms-win-core-io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,49 @@ namespace YY
return FALSE;
}
#endif

#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用]
// 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用]
__DEFINE_THUNK(
kernel32,
24,
BOOL,
WINAPI,
GetQueuedCompletionStatusEx,
_In_ HANDLE CompletionPort,
_Out_writes_to_(ulCount,*ulNumEntriesRemoved) LPOVERLAPPED_ENTRY lpCompletionPortEntries,
_In_ ULONG ulCount,
_Out_ PULONG ulNumEntriesRemoved,
_In_ DWORD dwMilliseconds,
_In_ BOOL fAlertable
)
{
if (const auto _pfnGetQueuedCompletionStatusEx = try_get_GetQueuedCompletionStatusEx())
{
return _pfnGetQueuedCompletionStatusEx(CompletionPort, lpCompletionPortEntries, ulCount, ulNumEntriesRemoved, dwMilliseconds, fAlertable);
}

if (ulCount == 0 || lpCompletionPortEntries == nullptr || ulNumEntriesRemoved == nullptr)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}

*ulNumEntriesRemoved = 0;

auto& _Entry = lpCompletionPortEntries[0];

// TODO: 已知问题:可警报状态丢失!(fAlertable)
auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, dwMilliseconds);
if (_bRet)
{
*ulNumEntriesRemoved = 1;
}
return _bRet;
}
#endif
}//namespace Thunks

} //namespace YY
25 changes: 25 additions & 0 deletions src/Thunks/api-ms-win-core-kernel32-legacy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,31 @@ namespace YY
}
#endif

#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 支持的最低客户端 Windows Vista [桌面应用程序 |UWP 应用]
// 支持的最低服务器 Windows Server 2008 [桌面应用程序 |UWP 应用]
__DEFINE_THUNK(
kernel32,
8,
BOOL,
WINAPI,
SetFileCompletionNotificationModes,
_In_ HANDLE FileHandle,
_In_ UCHAR Flags
)
{
if (const auto _pfnSetFileCompletionNotificationModes = try_get_SetFileCompletionNotificationModes())
{
return _pfnSetFileCompletionNotificationModes(FileHandle, Flags);
}

// 初步看起来没有什么的,只是会降低完成端口的效率。
// 至少需要 Vista才支持 FileIoCompletionNotificationInformation
// 只能假定先返回成功。
return TRUE;
}
#endif
}//namespace Thunks

} //namespace YY
36 changes: 36 additions & 0 deletions src/Thunks/ntdll.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace YY
{
namespace Thunks
{
#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用]
// 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用]
__DEFINE_THUNK(
ntdll,
12,
NTSTATUS,
NTAPI,
NtCancelIoFileEx,
HANDLE handle,
IO_STATUS_BLOCK* io,
IO_STATUS_BLOCK* io_status
)
{
if (const auto _pfnNtCancelIoFileEx = try_get_NtCancelIoFileEx())
{
return _pfnNtCancelIoFileEx(handle, io, io_status);
}

// 最坏打算,清除所有的调用
if (const auto _pfnNtCancelIoFile = try_get_NtCancelIoFile())
{
return _pfnNtCancelIoFile(handle, io_status);
}

// 正常来说不应该走到这里
return STATUS_NOT_SUPPORTED;
}
#endif
}
}
1 change: 1 addition & 0 deletions src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@
<ClInclude Include="..\Thunks\Iphlpapi.hpp" />
<ClInclude Include="..\Thunks\mfplat.hpp" />
<ClInclude Include="..\Thunks\netapi32.hpp" />
<ClInclude Include="..\Thunks\ntdll.hpp" />
<ClInclude Include="..\Thunks\Pdh.hpp" />
<ClInclude Include="..\Thunks\powrprof.hpp" />
<ClInclude Include="..\Thunks\ThreadRunner.h" />
Expand Down
3 changes: 3 additions & 0 deletions src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@
<ClInclude Include="..\Thunks\api-ms-win-core-rtlsupport.hpp">
<Filter>Thunks</Filter>
</ClInclude>
<ClInclude Include="..\Thunks\ntdll.hpp">
<Filter>Thunks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\def\x86\PSAPI2Kernel32.def">
Expand Down
4 changes: 2 additions & 2 deletions src/YY-Thunks.UnitTest/api-ms-win-core-fibers.UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ namespace api_ms_win_core_fibers

for (auto hHandle : hHandles)
{
Assert::AreEqual(WaitForSingleObject(hHandle, 1000), WAIT_OBJECT_0);
Assert::AreEqual(WaitForSingleObject(hHandle, 1000), (DWORD)WAIT_OBJECT_0);

CloseHandle(hHandle);
}
Expand Down Expand Up @@ -158,7 +158,7 @@ namespace api_ms_win_core_fibers

for (auto hHandle : hHandles)
{
Assert::AreEqual(WaitForSingleObject(hHandle, 1000), WAIT_OBJECT_0);
Assert::AreEqual(WaitForSingleObject(hHandle, 1000), (DWORD)WAIT_OBJECT_0);

CloseHandle(hHandle);
}
Expand Down
8 changes: 4 additions & 4 deletions src/YY-Thunks.UnitTest/api-ms-win-core-synch.UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ namespace api_ms_win_core_synch

for (auto hThreadHandle : hThreadHandles)
{
Assert::AreEqual(WaitForSingleObject(hThreadHandle, 500), WAIT_OBJECT_0);
Assert::AreEqual(WaitForSingleObject(hThreadHandle, 500), (DWORD)WAIT_OBJECT_0);
}

Assert::AreEqual(100l, (long)Data.RunCount);
Expand Down Expand Up @@ -157,7 +157,7 @@ namespace api_ms_win_core_synch

for (auto hThreadHandle : hThreadHandles)
{
Assert::AreEqual(WaitForSingleObject(hThreadHandle, 500), WAIT_OBJECT_0);
Assert::AreEqual(WaitForSingleObject(hThreadHandle, 500), (DWORD)WAIT_OBJECT_0);
}

Assert::AreEqual(100l, (long)Data.RunCount);
Expand Down Expand Up @@ -205,7 +205,7 @@ namespace api_ms_win_core_synch
auto _nRet = WaitForSingleObject(_hThreadHandle, 5 * 1000);
::ReleaseSRWLockExclusive(&_SRWLock);

Assert::AreEqual(WAIT_OBJECT_0, _nRet);
Assert::AreEqual((DWORD)WAIT_OBJECT_0, _nRet);

DWORD _uCode = -1;
GetExitCodeThread(_hThreadHandle, &_uCode);
Expand Down Expand Up @@ -237,7 +237,7 @@ namespace api_ms_win_core_synch

auto _nRet = WaitForSingleObject(_hThreadHandle, 5 * 1000);

Assert::AreEqual(WAIT_OBJECT_0, _nRet);
Assert::AreEqual((DWORD)WAIT_OBJECT_0, _nRet);

DWORD _uCode = -1;
GetExitCodeThread(_hThreadHandle, &_uCode);
Expand Down
28 changes: 14 additions & 14 deletions src/YY-Thunks.UnitTest/api-ms-win-core-threadpool.UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ namespace api_ms_win_core_threadpool

Assert::IsNotNull(h);

Assert::AreEqual(WaitForSingleObject(h, 2 * 1000), WAIT_OBJECT_0, L"2秒内必须完成,这是预期。");
Assert::AreEqual(WaitForSingleObject(h, 2 * 1000), (DWORD)WAIT_OBJECT_0, L"2秒内必须完成,这是预期。");

CloseHandle(h);

Expand All @@ -165,7 +165,7 @@ namespace api_ms_win_core_threadpool

Assert::IsNotNull(h);

Assert::AreEqual(WaitForSingleObject(h, 6 * 1000), WAIT_OBJECT_0, L"6秒内必须完成,这是预期。");
Assert::AreEqual(WaitForSingleObject(h, 6 * 1000), (DWORD)WAIT_OBJECT_0, L"6秒内必须完成,这是预期。");

CloseHandle(h);

Expand Down Expand Up @@ -446,7 +446,7 @@ namespace api_ms_win_core_threadpool

::SetThreadpoolTimer(pTimer, &ftDueTime, 1'500, 0);

Assert::AreEqual(WaitForSingleObject(Data.hEvent, 1 * 1000), WAIT_OBJECT_0, L"1秒内必须完成,这是预期。");
Assert::AreEqual(WaitForSingleObject(Data.hEvent, 1 * 1000), (DWORD)WAIT_OBJECT_0, L"1秒内必须完成,这是预期。");

auto h = (HANDLE)_beginthreadex(nullptr, 0, [](void* Work) -> unsigned
{
Expand All @@ -457,7 +457,7 @@ namespace api_ms_win_core_threadpool

Assert::IsNotNull(h);

Assert::AreEqual(WaitForSingleObject(h, 30 * 1000), WAIT_OBJECT_0, L"6秒内必须完成,这是预期。");
Assert::AreEqual(WaitForSingleObject(h, 30 * 1000), (DWORD)WAIT_OBJECT_0, L"6秒内必须完成,这是预期。");
CloseHandle(h);

Assert::AreEqual(Data.RunCount, 1l);
Expand Down Expand Up @@ -522,7 +522,7 @@ namespace api_ms_win_core_threadpool

::SubmitThreadpoolWork(Work);

Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), (DWORD)WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(Data.RunCount, 1l);

CloseThreadpoolWork(Work);
Expand Down Expand Up @@ -550,7 +550,7 @@ namespace api_ms_win_core_threadpool
FILETIME ftDueTime = {};
::SetThreadpoolTimer(pTimer, &ftDueTime, 0, 0);

Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), (DWORD)WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(Data.RunCount, 1l);

::CloseThreadpoolTimer(pTimer);
Expand Down Expand Up @@ -612,7 +612,7 @@ namespace api_ms_win_core_threadpool

::SubmitThreadpoolWork(Work);

Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), (DWORD)WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(Data.RunCount, 1l);

CloseThreadpoolWork(Work);
Expand Down Expand Up @@ -644,7 +644,7 @@ namespace api_ms_win_core_threadpool
FILETIME ftDueTime = {};
::SetThreadpoolTimer(pTimer, &ftDueTime, 0, 0);

Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), (DWORD)WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(Data.RunCount, 1l);

::CloseThreadpoolTimer(pTimer);
Expand Down Expand Up @@ -698,7 +698,7 @@ namespace api_ms_win_core_threadpool
Assert::IsNotNull(Context);
auto& Data = *(UserData*)Context;
auto dwWaitResult = WaitForSingleObject(Data.hHandle, 1000);
Assert::AreEqual(dwWaitResult, WAIT_OBJECT_0);
Assert::AreEqual(dwWaitResult, (DWORD)WAIT_OBJECT_0);
::ReleaseMutexWhenCallbackReturns(Instance, Data.hHandle);
InterlockedIncrement(&Data.RunCount);

Expand All @@ -709,7 +709,7 @@ namespace api_ms_win_core_threadpool
::SubmitThreadpoolWork(Work);
Sleep(100);

Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), (DWORD)WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(Data.RunCount, 1l);

CloseThreadpoolWork(Work);
Expand All @@ -728,7 +728,7 @@ namespace api_ms_win_core_threadpool
Assert::IsNotNull(Context);
auto& Data = *(UserData*)Context;
auto dwWaitResult = WaitForSingleObject(Data.hHandle, 1000);
Assert::AreEqual(dwWaitResult, WAIT_OBJECT_0);
Assert::AreEqual(dwWaitResult, (DWORD)WAIT_OBJECT_0);
::ReleaseMutexWhenCallbackReturns(Instance, Data.hHandle);
InterlockedIncrement(&Data.RunCount);
}, &Data, nullptr);
Expand All @@ -739,7 +739,7 @@ namespace api_ms_win_core_threadpool
::SetThreadpoolTimer(pTimer, &ftDueTime, 0, 0);
Sleep(100);

Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(WaitForSingleObject(Data.hHandle, 5 * 1000), (DWORD)WAIT_OBJECT_0, L"5秒内句柄必须有信号");
Assert::AreEqual(Data.RunCount, 1l);

::CloseThreadpoolTimer(pTimer);
Expand Down Expand Up @@ -1040,7 +1040,7 @@ namespace api_ms_win_core_threadpool
_In_ TP_WAIT_RESULT WaitResult
)
{
Assert::AreEqual(WaitResult, WAIT_OBJECT_0);
Assert::AreEqual(WaitResult, (DWORD)WAIT_OBJECT_0);

Assert::IsNotNull(Context);

Expand Down Expand Up @@ -1353,7 +1353,7 @@ namespace api_ms_win_core_threadpool

Assert::IsNotNull(h);

Assert::AreEqual(WaitForSingleObject(h, 10 * 1000), WAIT_OBJECT_0, L"10秒内必须完成,这是预期。");
Assert::AreEqual(WaitForSingleObject(h, 10 * 1000), (DWORD)WAIT_OBJECT_0, L"10秒内必须完成,这是预期。");



Expand Down
8 changes: 8 additions & 0 deletions src/YY-Thunks.UnitTest/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@
#ifndef PCH_H
#define PCH_H

#include <sal.h>

// 添加要在此处预编译的标头
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define UMDF_USING_NTSTATUS
#define _Disallow_YY_KM_Namespace
#include <km.h>

#include <Windows.h>

#include <atltime.h>

#include "CppUnitTest.h"
#include <process.h>

Expand Down

0 comments on commit 4b45145

Please sign in to comment.