Skip to content

Commit

Permalink
Fea Chuyu-Team#51, 新增GetIfTable2、GetIfTable2Ex、GetIfEntry2、GetIfEntry…
Browse files Browse the repository at this point in the history
…2Ex、FreeMibTable
  • Loading branch information
mingkuang-Chuyu committed Mar 11, 2023
1 parent 3563ca2 commit f326816
Show file tree
Hide file tree
Showing 6 changed files with 401 additions and 1 deletion.
7 changes: 6 additions & 1 deletion ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,9 @@
| [SetCoalescableTimer](https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-setcoalescabletimer) | 不存在时,调用SetTimer。
| [EnumResourceLanguagesExW(A)](https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-enumresourcelanguagesexw) | 不存在时,调用EnumResourceLanguagesW(A)。
| [CoGetApartmentType](https://learn.microsoft.com/windows/win32/api/combaseapi/nf-combaseapi-cogetapartmenttype) | 不存在时,调用IComThreadingInfo。
| [BCryptGenRandom](https://learn.microsoft.com/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom) | 不存在时调用,RtlGenRandom。
| [BCryptGenRandom](https://learn.microsoft.com/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom) | 不存在时调用,RtlGenRandom。
| [GetIfTable2](https://learn.microsoft.com/windows/win32/api/netioapi/nf-netioapi-getifentry2) | 不存在时调用,GetIfTable,并使用HeapAlloc申请内存。
| [GetIfTable2Ex](https://learn.microsoft.com/windows/win32/api/netioapi/nf-netioapi-getiftable2ex) | 不存在时调用,GetIfTable,并使用HeapAlloc申请内存。
| [GetIfEntry2](https://learn.microsoft.com/windows/win32/api/netioapi/nf-netioapi-getifentry2) | 不存在时调用,GetIfEntry。
| [GetIfEntry2Ex](https://learn.microsoft.com/windows/win32/api/netioapi/nf-netioapi-getifentry2ex) | 不存在时调用,GetIfEntry2。
| [FreeMibTable](https://learn.microsoft.com/windows/win32/api/netioapi/nf-netioapi-freemibtable) | 不存在时调用,HeapFree。
278 changes: 278 additions & 0 deletions src/Thunks/Iphlpapi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2)

#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

#pragma comment(lib, "Iphlpapi.lib")
#endif

namespace YY
{
namespace Thunks
{
#if defined(YY_Thunks_Implemented)
#if (YY_Thunks_Support_Version < NTDDI_WIN6)

static void MIB_IFROW_To_MIB_IF_ROW2(_In_ const MIB_IFROW* _pRow, _Out_ MIB_IF_ROW2* _pRow2)
{
memset(_pRow2, 0, sizeof(*_pRow2));

_pRow2->InterfaceLuid.Info.NetLuidIndex = _pRow->dwIndex;
_pRow2->InterfaceLuid.Info.IfType = _pRow->dwType;
_pRow2->InterfaceIndex = _pRow->dwIndex;

internal::StringToGuid(wcsrchr(_pRow->wszName, L'{'), &_pRow2->InterfaceGuid);
// memcpy(_pRow2->Alias, _pRow->wszName, sizeof(_pRow->wszName));
const auto _cchDescr = min(sizeof(_pRow->bDescr), _pRow->dwDescrLen);
for (size_t i = 0; i != _cchDescr; ++i)
{
_pRow2->Description[i] = _pRow->bDescr[i];
}
_pRow2->PhysicalAddressLength = _pRow->dwPhysAddrLen;
memcpy(_pRow2->PhysicalAddress, _pRow->bPhysAddr, min(sizeof(_pRow->bPhysAddr), _pRow->dwPhysAddrLen));
memcpy(_pRow2->PermanentPhysicalAddress, _pRow->bPhysAddr, min(sizeof(_pRow->bPhysAddr), _pRow->dwPhysAddrLen));

_pRow2->Mtu = _pRow->dwMtu;
_pRow2->Type = _pRow->dwType;

if (IF_TYPE_SOFTWARE_LOOPBACK == _pRow->dwType)
{
_pRow2->MediaType = NdisMediumLoopback;
_pRow2->AccessType = NET_IF_ACCESS_LOOPBACK;
_pRow2->DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
}
else
{
// 设置一个默认值,都假装自己是普通的网口
_pRow2->MediaType = NdisMedium802_3;
_pRow2->AccessType = NET_IF_ACCESS_BROADCAST;
_pRow2->DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
}

switch (_pRow->dwOperStatus)
{
case IF_OPER_STATUS_OPERATIONAL:
case IF_OPER_STATUS_CONNECTED:
_pRow2->OperStatus = IF_OPER_STATUS::IfOperStatusUp;
_pRow2->MediaConnectState = MediaConnectStateConnected;
break;
default:
_pRow2->OperStatus = IF_OPER_STATUS::IfOperStatusDown;
break;
}

//
_pRow2->AdminStatus = (NET_IF_ADMIN_STATUS)_pRow->dwAdminStatus;
_pRow2->ConnectionType = NET_IF_CONNECTION_DEDICATED;


_pRow2->TransmitLinkSpeed = _pRow->dwSpeed;
_pRow2->ReceiveLinkSpeed = _pRow->dwSpeed;
_pRow2->InOctets = _pRow->dwInOctets;
_pRow2->InUcastPkts = _pRow->dwInUcastPkts;
_pRow2->InNUcastPkts = _pRow->dwInNUcastPkts;
_pRow2->InDiscards = _pRow->dwInDiscards;
_pRow2->InErrors = _pRow->dwInErrors;
_pRow2->InUnknownProtos = _pRow->dwInUnknownProtos;
// 伪造一下 InUcastOctets
_pRow2->InUcastOctets = _pRow->dwInOctets;
_pRow2->InMulticastOctets = 0;
_pRow2->InBroadcastOctets = 0;
_pRow2->OutOctets = _pRow->dwOutOctets;
_pRow2->OutUcastPkts = _pRow->dwOutUcastPkts;
_pRow2->OutNUcastPkts = _pRow->dwOutNUcastPkts;
_pRow2->OutDiscards = _pRow->dwOutDiscards;
_pRow2->OutErrors = _pRow->dwOutErrors;
// 伪造一下 OutUcastOctets
_pRow2->OutUcastOctets = _pRow->dwOutOctets;
_pRow2->OutMulticastOctets = 0;
_pRow2->OutBroadcastOctets = 0;
_pRow2->OutQLen = _pRow->dwOutQLen;
}

static
NETIOAPI_API
GetIfTable2ExDownlevel(
_In_ MIB_IF_TABLE_LEVEL _eLevel,
_Outptr_ PMIB_IF_TABLE2* _ppTable2
)
{
// Windows XP 无法支持_eLevel
// 相比较无法启动,一些状态报告不对就这样凑合吧。
UNREFERENCED_PARAMETER(_eLevel);

if (!_ppTable2)
return ERROR_INVALID_PARAMETER;
*_ppTable2 = nullptr;

const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap;

constexpr DWORD _cbTable = sizeof(MIB_IFTABLE) + 256 * sizeof(MIB_IFROW);
auto _pTable = (MIB_IFTABLE*)HeapAlloc(_hProcessHeap, 0, _cbTable);
if (!_pTable)
return ERROR_NOT_ENOUGH_MEMORY;

LSTATUS _lStatus;
do
{
DWORD _uSize = _cbTable;
_lStatus = ::GetIfTable(_pTable, &_uSize, FALSE);
if (_lStatus != NO_ERROR)
break;

const DWORD _cbTable2 = sizeof(MIB_IF_TABLE2) + _pTable->dwNumEntries * sizeof(MIB_IF_ROW2);
auto _pTable2 = (MIB_IF_TABLE2*)HeapAlloc(_hProcessHeap, 0, _cbTable2);
if (!_pTable2)
{
_lStatus = ERROR_NOT_ENOUGH_MEMORY;
break;
}

_pTable2->NumEntries = _pTable->dwNumEntries;
for (DWORD i = 0; i != _pTable->dwNumEntries; ++i)
{
MIB_IFROW_To_MIB_IF_ROW2(&_pTable->table[i], &_pTable2->Table[i]);
}

*_ppTable2 = _pTable2;
} while (false);

HeapFree(_hProcessHeap, 0, _pTable);

return _lStatus;
}

#endif // (YY_Thunks_Support_Version < NTDDI_WIN6)
#endif // !YY_Thunks_Implemented

#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用]
// 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用]
__DEFINE_THUNK(
iphlpapi,
4,
NETIO_STATUS,
NETIOAPI_API_,
GetIfTable2,
_Outptr_ PMIB_IF_TABLE2 * _ppTable2
)
{
if (auto _pfnGetIfTable2 = try_get_GetIfTable2())
{
return _pfnGetIfTable2(_ppTable2);
}

return GetIfTable2ExDownlevel(MibIfTableNormal, _ppTable2);
}
#endif

#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用]
// 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用]
__DEFINE_THUNK(
iphlpapi,
8,
NETIO_STATUS,
NETIOAPI_API_,
GetIfTable2Ex,
_In_ MIB_IF_TABLE_LEVEL _eLevel,
_Outptr_ PMIB_IF_TABLE2* _ppTable2
)
{
if (auto _pfnGetIfTable2Ex = try_get_GetIfTable2Ex())
{
return _pfnGetIfTable2Ex(_eLevel, _ppTable2);
}

return GetIfTable2ExDownlevel(_eLevel, _ppTable2);
}
#endif

#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用]
// 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用]
__DEFINE_THUNK(
iphlpapi,
4,
NETIO_STATUS,
NETIOAPI_API_,
GetIfEntry2,
_Inout_ PMIB_IF_ROW2 _pRow
)
{
if (auto _pfnGetIfEntry2 = try_get_GetIfEntry2())
{
return _pfnGetIfEntry2(_pRow);
}

if (!_pRow)
return ERROR_INVALID_PARAMETER;

MIB_IFROW _IfRow;
_IfRow.dwIndex = _pRow->InterfaceLuid.Value ? _pRow->InterfaceLuid.Info.NetLuidIndex : _pRow->InterfaceIndex;

auto _lStatus = GetIfEntry(&_IfRow);
if (NO_ERROR != _lStatus)
return _lStatus;

MIB_IFROW_To_MIB_IF_ROW2(&_IfRow, _pRow);
return NO_ERROR;
}
#endif

#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2)

// 最低受支持的客户端 Windows 10版本 1703[仅限桌面应用]
// 最低受支持的服务器 Windows Server 2016[仅限桌面应用]
__DEFINE_THUNK(
iphlpapi,
8,
NETIO_STATUS,
NETIOAPI_API_,
GetIfEntry2Ex,
_In_ MIB_IF_ENTRY_LEVEL _eLevel,
_Inout_ PMIB_IF_ROW2 _pRow
)
{
if (auto _pfnGetIfEntry2Ex = try_get_GetIfEntry2Ex())
{
return _pfnGetIfEntry2Ex(_eLevel, _pRow);
}
// 忽略Level,理论上说 多取了 Statistics信息也没有太大影响。
UNREFERENCED_PARAMETER(_eLevel);

return GetIfEntry2(_pRow);
}
#endif

#if (YY_Thunks_Support_Version < NTDDI_WIN6)

// 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用]
// 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用]
__DEFINE_THUNK(
iphlpapi,
4,
void,
NETIOAPI_API_,
FreeMibTable,
_In_ PVOID _pMemory
)
{
if (auto _pfnFreeMibTable = try_get_FreeMibTable())
{
return _pfnFreeMibTable(_pMemory);
}

if (_pMemory)
{
const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap;
HeapFree(_hProcessHeap, 0, _pMemory);
}
}
#endif
}
}
67 changes: 67 additions & 0 deletions src/Thunks/YY_Thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
_APPLY(shlwapi, "shlwapi" , 0 ) \
_APPLY(setupapi, "setupapi" , 0 ) \
_APPLY(ole32, "ole32" , 0 ) \
_APPLY(iphlpapi, "iphlpapi" , 0 ) \
_APPLY(api_ms_win_core_winrt_l1_1_0, "api-ms-win-core-winrt-l1-1-0" , 0 ) \
_APPLY(api_ms_win_core_winrt_string_l1_1_0, "api-ms-win-core-winrt-string-l1-1-0", 0 ) \
_APPLY(api_ms_win_core_winrt_error_l1_1_0, "api-ms-win-core-winrt-error-l1-1-0" , 0 ) \
Expand Down Expand Up @@ -260,6 +261,72 @@ namespace YY
return TRUE;
}

static unsigned __fastcall CharToHex(_In_ wchar_t _ch)
{
if (_ch >= L'0' && _ch <= L'9')
{
return _ch - L'0';
}
else if (_ch >= L'A' && _ch <= L'F')
{
return _ch - L'A' + 0xA;
}
else if (_ch >= L'a' && _ch <= L'f')
{
return _ch - L'a' + 0xA;
}
else
{
return -1;
}
}

static BOOL __fastcall StringToGuid(_In_z_ const wchar_t* _szInput, _Out_ GUID* _pId)
{
*_pId = GUID{};

if (!_szInput)
return FALSE;

if (*_szInput == L'{')
++_szInput;

#define _IS_HEX_CHAR(C) (CharToHex(C) != (unsigned)-1)

if (!(_IS_HEX_CHAR(_szInput[0]) && _IS_HEX_CHAR(_szInput[1]) && _IS_HEX_CHAR(_szInput[2]) && _IS_HEX_CHAR(_szInput[3])
&& _IS_HEX_CHAR(_szInput[4]) && _IS_HEX_CHAR(_szInput[5]) && _IS_HEX_CHAR(_szInput[6]) && _IS_HEX_CHAR(_szInput[7])
&& _szInput[8] == L'-'
&& _IS_HEX_CHAR(_szInput[9]) && _IS_HEX_CHAR(_szInput[10]) && _IS_HEX_CHAR(_szInput[11]) && _IS_HEX_CHAR(_szInput[12])
&& _szInput[13] == L'-'
&& _IS_HEX_CHAR(_szInput[14]) && _IS_HEX_CHAR(_szInput[15]) && _IS_HEX_CHAR(_szInput[16]) && _IS_HEX_CHAR(_szInput[17])
&& _szInput[18] == L'-'
&& _IS_HEX_CHAR(_szInput[19]) && _IS_HEX_CHAR(_szInput[20]) && _IS_HEX_CHAR(_szInput[21]) && _IS_HEX_CHAR(_szInput[22])
&& _szInput[23] == L'-'
&& _IS_HEX_CHAR(_szInput[24]) && _IS_HEX_CHAR(_szInput[25]) && _IS_HEX_CHAR(_szInput[26]) && _IS_HEX_CHAR(_szInput[27])
&& _IS_HEX_CHAR(_szInput[28]) && _IS_HEX_CHAR(_szInput[29]) && _IS_HEX_CHAR(_szInput[30]) && _IS_HEX_CHAR(_szInput[31])
&& _IS_HEX_CHAR(_szInput[32]) && _IS_HEX_CHAR(_szInput[33]) && _IS_HEX_CHAR(_szInput[34]) && _IS_HEX_CHAR(_szInput[35])))
{
return FALSE;
}
#undef _IS_HEX_CHAR

_pId->Data1 = (CharToHex(_szInput[0]) << 28) | (CharToHex(_szInput[1]) << 24) | (CharToHex(_szInput[2]) << 20) | (CharToHex(_szInput[3]) << 16)
| (CharToHex(_szInput[4]) << 12) | (CharToHex(_szInput[5]) << 8) | (CharToHex(_szInput[6]) << 4) | (CharToHex(_szInput[7]) << 0);

_pId->Data2 = (CharToHex(_szInput[9]) << 12) | (CharToHex(_szInput[10]) << 8) | (CharToHex(_szInput[11]) << 4) | (CharToHex(_szInput[12]) << 0);

_pId->Data3 = (CharToHex(_szInput[14]) << 12) | (CharToHex(_szInput[15]) << 8) | (CharToHex(_szInput[16]) << 4) | (CharToHex(_szInput[17]) << 0);

_pId->Data4[0] = (CharToHex(_szInput[19]) << 4) | (CharToHex(_szInput[20]) << 0);
_pId->Data4[1] = (CharToHex(_szInput[21]) << 4) | (CharToHex(_szInput[22]) << 0);
_pId->Data4[2] = (CharToHex(_szInput[24]) << 4) | (CharToHex(_szInput[25]) << 0);
_pId->Data4[3] = (CharToHex(_szInput[26]) << 4) | (CharToHex(_szInput[27]) << 0);
_pId->Data4[4] = (CharToHex(_szInput[28]) << 4) | (CharToHex(_szInput[29]) << 0);
_pId->Data4[5] = (CharToHex(_szInput[30]) << 4) | (CharToHex(_szInput[31]) << 0);
_pId->Data4[6] = (CharToHex(_szInput[32]) << 4) | (CharToHex(_szInput[33]) << 0);
_pId->Data4[7] = (CharToHex(_szInput[34]) << 4) | (CharToHex(_szInput[35]) << 0);
return TRUE;
}
}
}//namespace Thunks

Expand Down
Loading

0 comments on commit f326816

Please sign in to comment.