From 07930065234b6482c8a2dd4fe5e9b82ac9a3bf8d Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Mon, 8 Sep 2025 02:00:34 +0200 Subject: [PATCH] [IFMON] Add first netsh helper dll Run 'add helper ifmon.dll' in netsh to load the ifmon helper. --- dll/win32/CMakeLists.txt | 1 + dll/win32/ifmon/CMakeLists.txt | 15 ++ dll/win32/ifmon/guid.c | 6 + dll/win32/ifmon/guid.h | 5 + dll/win32/ifmon/ifmon.c | 49 +++++ dll/win32/ifmon/ifmon.rc | 19 ++ dll/win32/ifmon/ifmon.spec | 1 + dll/win32/ifmon/interface.c | 106 ++++++++++ dll/win32/ifmon/ip.c | 348 +++++++++++++++++++++++++++++++++ dll/win32/ifmon/lang/en-US.rc | 28 +++ dll/win32/ifmon/precomp.h | 36 ++++ dll/win32/ifmon/resource.h | 24 +++ 12 files changed, 638 insertions(+) create mode 100644 dll/win32/ifmon/CMakeLists.txt create mode 100644 dll/win32/ifmon/guid.c create mode 100644 dll/win32/ifmon/guid.h create mode 100644 dll/win32/ifmon/ifmon.c create mode 100644 dll/win32/ifmon/ifmon.rc create mode 100644 dll/win32/ifmon/ifmon.spec create mode 100644 dll/win32/ifmon/interface.c create mode 100644 dll/win32/ifmon/ip.c create mode 100644 dll/win32/ifmon/lang/en-US.rc create mode 100644 dll/win32/ifmon/precomp.h create mode 100644 dll/win32/ifmon/resource.h diff --git a/dll/win32/CMakeLists.txt b/dll/win32/CMakeLists.txt index 4c0e2396e2d..03d0bdb7f91 100644 --- a/dll/win32/CMakeLists.txt +++ b/dll/win32/CMakeLists.txt @@ -57,6 +57,7 @@ add_subdirectory(iccvid) add_subdirectory(icmp) add_subdirectory(ieframe) add_subdirectory(iernonce) +add_subdirectory(ifmon) add_subdirectory(imaadp32.acm) add_subdirectory(imagehlp) add_subdirectory(inetcomm) diff --git a/dll/win32/ifmon/CMakeLists.txt b/dll/win32/ifmon/CMakeLists.txt new file mode 100644 index 00000000000..79b8a5a4dbd --- /dev/null +++ b/dll/win32/ifmon/CMakeLists.txt @@ -0,0 +1,15 @@ + +spec2def(ifmon.dll ifmon.spec) + +list(APPEND SOURCE + guid.c + ifmon.c + ifmon.rc + interface.c + ip.c + ${CMAKE_CURRENT_BINARY_DIR}/ifmon.def) + +add_library(ifmon MODULE ${SOURCE}) +set_module_type(ifmon win32dll UNICODE) +add_importlibs(ifmon netsh iphlpapi msvcrt kernel32 ntdll) +add_cd_file(TARGET ifmon DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/ifmon/guid.c b/dll/win32/ifmon/guid.c new file mode 100644 index 00000000000..6c44c329871 --- /dev/null +++ b/dll/win32/ifmon/guid.c @@ -0,0 +1,6 @@ + +#define INITGUID +#include + +#include "guid.h" + diff --git a/dll/win32/ifmon/guid.h b/dll/win32/ifmon/guid.h new file mode 100644 index 00000000000..15caf59deb5 --- /dev/null +++ b/dll/win32/ifmon/guid.h @@ -0,0 +1,5 @@ + +DEFINE_GUID(GUID_IFMON_INTERFACE, 0x0705eca1, 0x7aac, 0x11d2, 0x89, 0xdc, 0x00, 0x60, 0x08, 0xb0, 0xe5, 0xb9); +//DEFINE_GUID(GUID_IFMON_INTERFACE, 0x0705ECB2, 0x7AAC, 0x11D2, 0x89, 0xDC, 0x00, 0x60, 0x08, 0xB0, 0xE5, 0xB9); +DEFINE_GUID(GUID_IFMON_IP, 0x725588AC, 0x7A11, 0x4220, 0xA1, 0x21, 0xC9, 0x2C, 0x91, 0x5E, 0x8B, 0x73); + diff --git a/dll/win32/ifmon/ifmon.c b/dll/win32/ifmon/ifmon.c new file mode 100644 index 00000000000..00d765bf2db --- /dev/null +++ b/dll/win32/ifmon/ifmon.c @@ -0,0 +1,49 @@ +/* + * PROJECT: ReactOS IF Monitor DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: NetSh Helper main functions + * COPYRIGHT: Copyright 2025 Eric Kohl + */ + +#include "precomp.h" + +#define NDEBUG +#include + +#include "guid.h" +#include "resource.h" + +HINSTANCE hDllInstance; + +DWORD +WINAPI +InitHelperDll( + _In_ DWORD dwNetshVersion, + _Out_ PVOID pReserved) +{ + DWORD dwError; + + dwError = RegisterInterfaceHelper(); + if (dwError == ERROR_SUCCESS) + dwError = RegisterIpHelper(); + + return dwError; +} + + +BOOL WINAPI +DllMain( + _In_ HINSTANCE hinstDLL, + _In_ DWORD dwReason, + _In_ LPVOID lpvReserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + hDllInstance = hinstDLL; + DisableThreadLibraryCalls(hinstDLL); + break; + } + + return TRUE; +} diff --git a/dll/win32/ifmon/ifmon.rc b/dll/win32/ifmon/ifmon.rc new file mode 100644 index 00000000000..56766158f0d --- /dev/null +++ b/dll/win32/ifmon/ifmon.rc @@ -0,0 +1,19 @@ +#include +#include + +#include "resource.h" + +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS IF Monitor DLL" +#define REACTOS_STR_INTERNAL_NAME "ifmon" +#define REACTOS_STR_ORIGINAL_FILENAME "ifmon.dll" +#include + +#include + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif diff --git a/dll/win32/ifmon/ifmon.spec b/dll/win32/ifmon/ifmon.spec new file mode 100644 index 00000000000..28322dd35f1 --- /dev/null +++ b/dll/win32/ifmon/ifmon.spec @@ -0,0 +1 @@ +@ stdcall InitHelperDll(long ptr) diff --git a/dll/win32/ifmon/interface.c b/dll/win32/ifmon/interface.c new file mode 100644 index 00000000000..daa5fefff3d --- /dev/null +++ b/dll/win32/ifmon/interface.c @@ -0,0 +1,106 @@ +/* + * PROJECT: ReactOS IF Monitor DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: NetSh Helper interface context functions + * COPYRIGHT: Copyright 2025 Eric Kohl + */ + +#include "precomp.h" + +#include + +#define NDEBUG +#include + +#include "guid.h" +#include "resource.h" + +static +DWORD +WINAPI +InterfaceShowInterface( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone); + +static +CMD_ENTRY +InterfaceShowCommands[] = +{ + {L"interface", InterfaceShowInterface, IDS_HLP_INTERFACE_SHOW_INTERFACE, IDS_HLP_INTERFACE_SHOW_INTERFACE_EX, 0} +}; + +static +CMD_GROUP_ENTRY +InterfaceGroups[] = +{ + {L"show", IDS_HLP_INTERFACE_SHOW, sizeof(InterfaceShowCommands) / sizeof(CMD_ENTRY), 0, InterfaceShowCommands, NULL}, +}; + + +static +DWORD +WINAPI +InterfaceShowInterface( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone) +{ + PrintMessage(L"InterfaceShowInterface(): Not implemented yet!\n"); + + return ERROR_SUCCESS; +} + + +DWORD +WINAPI +InterfaceStart( + _In_ const GUID *pguidParent, + _In_ DWORD dwVersion) +{ + NS_CONTEXT_ATTRIBUTES ContextAttributes; + + DPRINT1("InterfaceStart()\n"); + + ZeroMemory(&ContextAttributes, sizeof(ContextAttributes)); + ContextAttributes.dwVersion = 1; + ContextAttributes.pwszContext = L"interface"; + ContextAttributes.guidHelper = GUID_IFMON_INTERFACE; + + ContextAttributes.ulNumTopCmds = 0; + ContextAttributes.pTopCmds = NULL; + + ContextAttributes.ulNumGroups = sizeof(InterfaceGroups) / sizeof(CMD_GROUP_ENTRY); + ContextAttributes.pCmdGroups = InterfaceGroups; + + RegisterContext(&ContextAttributes); + + return ERROR_SUCCESS; +} + + +DWORD +WINAPI +RegisterInterfaceHelper(VOID) +{ + NS_HELPER_ATTRIBUTES HelperAttributes; + + DPRINT1("RegisterInterfaceHelper()\n"); + + ZeroMemory(&HelperAttributes, sizeof(HelperAttributes)); + HelperAttributes.dwVersion = 1; + HelperAttributes.guidHelper = GUID_IFMON_INTERFACE; + HelperAttributes.pfnStart = InterfaceStart; + HelperAttributes.pfnStop = NULL; + RegisterHelper(NULL, &HelperAttributes); + + return ERROR_SUCCESS; +} diff --git a/dll/win32/ifmon/ip.c b/dll/win32/ifmon/ip.c new file mode 100644 index 00000000000..5e2ba63f986 --- /dev/null +++ b/dll/win32/ifmon/ip.c @@ -0,0 +1,348 @@ +/* + * PROJECT: ReactOS IF Monitor DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: IP context functions + * COPYRIGHT: Copyright 2025 Eric Kohl + */ + +#include "precomp.h" + +#include + +#define NDEBUG +#include + +#include "guid.h" +#include "resource.h" + +#define DISPLAY_ADRESSES 0x1 +#define DISPLAY_DNS 0x2 + +static +DWORD +WINAPI +IpShowAddresses( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone); + +static +DWORD +WINAPI +IpShowConfig( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone); + +static +DWORD +WINAPI +IpShowDns( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone); + + +static +CMD_ENTRY +IpShowCommands[] = +{ + {L"addresses", IpShowAddresses, IDS_HLP_ADDRESSES, IDS_HLP_ADDRESSES_EX, 0}, + {L"config", IpShowConfig, IDS_HLP_CONFIG, IDS_HLP_CONFIG_EX, 0}, + {L"dns", IpShowDns, IDS_HLP_DNS, IDS_HLP_DNS_EX, 0} +}; + + +static +CMD_GROUP_ENTRY +IpGroups[] = +{ + {L"show", IDS_HLP_IP_SHOW, sizeof(IpShowCommands) / sizeof(CMD_ENTRY), 0, IpShowCommands, NULL}, +}; + + +static +BOOL +FormatIPv4Address( + _Out_ PWCHAR pBuffer, + _In_ PSOCKET_ADDRESS SocketAddress) +{ + if (SocketAddress->lpSockaddr->sa_family == AF_INET) + { + struct sockaddr_in *si = (struct sockaddr_in *)(SocketAddress->lpSockaddr); + RtlIpv4AddressToStringW(&(si->sin_addr), pBuffer); + return TRUE; + } + + return FALSE; +} + + +static +DWORD +IpShowAdapters( + _In_ DWORD DisplayFlags) +{ + PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL, Ptr; + PIP_ADAPTER_UNICAST_ADDRESS pUnicastAddress; + PIP_ADAPTER_PREFIX pPrefix; + PIP_ADAPTER_DNS_SERVER_ADDRESS pDnsServer; + WCHAR IpBuffer[17]; + BOOL First; + ULONG adaptOutBufLen = 15000; + DWORD Error = ERROR_SUCCESS; + ULONG Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX; + + /* set required buffer size */ + pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc(adaptOutBufLen); + if (pAdapterAddresses == NULL) + { + Error = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + Error = GetAdaptersAddresses(AF_INET, Flags, NULL, pAdapterAddresses, &adaptOutBufLen); + if (Error == ERROR_BUFFER_OVERFLOW) + { + free(pAdapterAddresses); + pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc(adaptOutBufLen); + if (pAdapterAddresses == NULL) + { + Error = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + } + + Error = GetAdaptersAddresses(AF_INET, Flags, NULL, pAdapterAddresses, &adaptOutBufLen); + if (Error != ERROR_SUCCESS) + goto done; + + Ptr = pAdapterAddresses; + while (Ptr) + { + PrintMessageFromModule(hDllInstance, IDS_IP_HEADER, Ptr->FriendlyName); + + if (DisplayFlags & DISPLAY_ADRESSES) + { + PrintMessageFromModule(hDllInstance, (Ptr->Flags & IP_ADAPTER_DHCP_ENABLED) ? IDS_DHCP_ON : IDS_DHCP_OFF); + + if (Ptr->FirstUnicastAddress == NULL) + { + PrintMessageFromModule(hDllInstance, IDS_NOIPADDRESS); + } + else + { + First = TRUE; + pUnicastAddress = Ptr->FirstUnicastAddress; + while (pUnicastAddress) + { + if (FormatIPv4Address(IpBuffer, &pUnicastAddress->Address)) + { + if (First) + { + PrintMessageFromModule(hDllInstance, (pUnicastAddress->Next)? IDS_IPADDRESSES : IDS_IPADDRESS, IpBuffer); + } + else + { + PrintMessageFromModule(hDllInstance, IDS_EMPTYLINE, IpBuffer); + } + First = FALSE; + } + + pUnicastAddress = pUnicastAddress->Next; + } + } + + if (Ptr->FirstPrefix == NULL) + { + PrintMessage(L" SubnetMask: %s\n", L"None"); + } + else + { + First = TRUE; + pPrefix = Ptr->FirstPrefix; + while (pPrefix) + { + if (FormatIPv4Address(IpBuffer, &pPrefix->Address)) + { + if (First) + { + if (pPrefix->Next) + PrintMessage(L" SubnetMasks: %s/%lu\n", IpBuffer, pPrefix->PrefixLength); + else + PrintMessage(L" IP Address: %s/%lu\n", IpBuffer, pPrefix->PrefixLength); + } + else + { + PrintMessage(L" %s/%lu\n", IpBuffer, pPrefix->PrefixLength); + } + First = FALSE; + } + + pPrefix = pPrefix->Next; + } + } + +// PrintMessage(L" Default Gateway: %s\n", L"---"); +// PrintMessage(L" Gateway Metric: %s\n", L"---"); +// PrintMessage(L" Interface Metric: %s\n", L"---"); + } + + if (DisplayFlags & DISPLAY_DNS) + { + if (Ptr->FirstDnsServerAddress == NULL) + { + if (Ptr->Flags & IP_ADAPTER_DHCP_ENABLED) + PrintMessage(L" DNS servers configured through DHCP: %s\n", L"None"); + else + PrintMessage(L" Statically configured DNS Servers: %s\n", L"None"); + } + else + { + First = TRUE; + pDnsServer = Ptr->FirstDnsServerAddress; + while (pDnsServer) + { + if (FormatIPv4Address(IpBuffer, &pDnsServer->Address)) + { + if (First == TRUE) + { + if (Ptr->Flags & IP_ADAPTER_DHCP_ENABLED) + PrintMessage(L" DNS servers configured through DHCP: %s\n", IpBuffer); + else + PrintMessage(L" Statically configured DNS Servers: %s\n", IpBuffer); + } + else + { + PrintMessage(L" %s\n", IpBuffer); + } + + First = FALSE; + } + + pDnsServer = pDnsServer->Next; + } + } + +// PrintMessage(L" Register with which suffix:\n"); + } + + Ptr = Ptr->Next; + } + + PrintMessage(L"\n"); + +done: + if (pAdapterAddresses) + free(pAdapterAddresses); + + return Error; +} + + +static +DWORD +WINAPI +IpShowAddresses( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone) +{ + return IpShowAdapters(DISPLAY_ADRESSES); +} + + +static +DWORD +WINAPI +IpShowConfig( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone) +{ + return IpShowAdapters(DISPLAY_ADRESSES | DISPLAY_DNS); +} + + +static +DWORD +WINAPI +IpShowDns( + LPCWSTR pwszMachine, + LPWSTR *argv, + DWORD dwCurrentIndex, + DWORD dwArgCount, + DWORD dwFlags, + LPCVOID pvData, + BOOL *pbDone) +{ + return IpShowAdapters(DISPLAY_DNS); +} + + +static +DWORD +WINAPI +IpStart( + _In_ const GUID *pguidParent, + _In_ DWORD dwVersion) +{ + NS_CONTEXT_ATTRIBUTES ContextAttributes; + + DPRINT1("IpStart()\n"); + + ZeroMemory(&ContextAttributes, sizeof(ContextAttributes)); + ContextAttributes.dwVersion = 1; + ContextAttributes.pwszContext = L"ip"; + ContextAttributes.guidHelper = GUID_IFMON_IP; + + ContextAttributes.ulNumTopCmds = 0; + ContextAttributes.pTopCmds = NULL; + + ContextAttributes.ulNumGroups = sizeof(IpGroups) / sizeof(CMD_GROUP_ENTRY); + ContextAttributes.pCmdGroups = IpGroups; + + RegisterContext(&ContextAttributes); + + return ERROR_SUCCESS; +} + + +DWORD +WINAPI +RegisterIpHelper(VOID) +{ + NS_HELPER_ATTRIBUTES HelperAttributes; + GUID guidParent = GUID_IFMON_INTERFACE; + + DPRINT1("RegisterIpHelper()\n"); + + ZeroMemory(&HelperAttributes, sizeof(HelperAttributes)); + HelperAttributes.dwVersion = 1; + HelperAttributes.guidHelper = GUID_IFMON_IP; + HelperAttributes.pfnStart = IpStart; + HelperAttributes.pfnStop = NULL; + RegisterHelper(&guidParent, &HelperAttributes); + + return ERROR_SUCCESS; +} diff --git a/dll/win32/ifmon/lang/en-US.rc b/dll/win32/ifmon/lang/en-US.rc new file mode 100644 index 00000000000..dc138966dce --- /dev/null +++ b/dll/win32/ifmon/lang/en-US.rc @@ -0,0 +1,28 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_HLP_INTERFACE_SHOW "Displays information.\n" + IDS_HLP_INTERFACE_SHOW_INTERFACE "Displays interfaces.\n" + IDS_HLP_INTERFACE_SHOW_INTERFACE_EX "\nUsage:\n" + + IDS_HLP_IP_SHOW "Displays IP information." + IDS_HLP_ADDRESSES "Displays IP address configuration." + IDS_HLP_ADDRESSES_EX "Usage: addresses\n\n Display IP address configuration.\n" + IDS_HLP_CONFIG "Displays IP address and additional information." + IDS_HLP_CONFIG_EX "Usage: config\n\n Display IP address and additional information.\n" + IDS_HLP_DNS "Displays the DNS server addresses." + IDS_HLP_DNS_EX "Usage: dns\n\n Display DNS server adresses.\n" + + IDS_IP_HEADER "\nConfiguration for interface ""%s""\n" + IDS_DHCP_ON " DHCP enabled: Yes\n" + IDS_DHCP_OFF " DHCP enabled: No\n" + IDS_NOIPADDRESS " IP Address: None\n" + IDS_IPADDRESS " IP Address: %s\n" + IDS_IPADDRESSES " IP Addresses: %s\n" + IDS_NOSUBNETMASK " Subnet Mask: None\n" + IDS_SUBNETMASK " Subnet Mask: %s\n" + IDS_SUBNETMASKS " Subnet Masks: %s\n" + + IDS_EMPTYLINE " %s\n" +END diff --git a/dll/win32/ifmon/precomp.h b/dll/win32/ifmon/precomp.h new file mode 100644 index 00000000000..a024a1f8a41 --- /dev/null +++ b/dll/win32/ifmon/precomp.h @@ -0,0 +1,36 @@ +/* + * PROJECT: ReactOS IF Monitor DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Network Shell main header file + * COPYRIGHT: Copyright 2025 Eric Kohl + */ + +#ifndef PRECOMP_H +#define PRECOMP_H + +/* INCLUDES ******************************************************************/ + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#define _INC_WINDOWS +#include +#include +#include + + +#include + +extern HINSTANCE hDllInstance; + +DWORD +WINAPI +RegisterInterfaceHelper(VOID); + +DWORD +WINAPI +RegisterIpHelper(VOID); + +#endif /* PRECOMP_H */ diff --git a/dll/win32/ifmon/resource.h b/dll/win32/ifmon/resource.h new file mode 100644 index 00000000000..fdb530d9e6a --- /dev/null +++ b/dll/win32/ifmon/resource.h @@ -0,0 +1,24 @@ + +#define IDS_HLP_INTERFACE_SHOW 200 +#define IDS_HLP_INTERFACE_SHOW_INTERFACE 201 +#define IDS_HLP_INTERFACE_SHOW_INTERFACE_EX 202 + +#define IDS_HLP_IP_SHOW 210 +#define IDS_HLP_ADDRESSES 211 +#define IDS_HLP_ADDRESSES_EX 212 +#define IDS_HLP_CONFIG 213 +#define IDS_HLP_CONFIG_EX 214 +#define IDS_HLP_DNS 215 +#define IDS_HLP_DNS_EX 216 + +#define IDS_IP_HEADER 300 +#define IDS_DHCP_ON 301 +#define IDS_DHCP_OFF 302 +#define IDS_NOIPADDRESS 303 +#define IDS_IPADDRESS 304 +#define IDS_IPADDRESSES 305 +#define IDS_NOSUBNETMASK 306 +#define IDS_SUBNETMASK 307 +#define IDS_SUBNETMASKS 308 + +#define IDS_EMPTYLINE 400