[IFMON] Add first netsh helper dll

Run 'add helper ifmon.dll' in netsh to load the ifmon helper.
This commit is contained in:
Eric Kohl
2025-09-08 02:00:34 +02:00
parent df01941faf
commit 0793006523
12 changed files with 638 additions and 0 deletions
+1
View File
@@ -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)
+15
View File
@@ -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)
+6
View File
@@ -0,0 +1,6 @@
#define INITGUID
#include <guiddef.h>
#include "guid.h"
+5
View File
@@ -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);
+49
View File
@@ -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 <[email protected]>
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
#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;
}
+19
View File
@@ -0,0 +1,19 @@
#include <windef.h>
#include <winuser.h>
#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 <reactos/version.rc>
#include <reactos/manifest_dll.rc>
/* UTF-8 */
#pragma code_page(65001)
#ifdef LANGUAGE_EN_US
#include "lang/en-US.rc"
#endif
+1
View File
@@ -0,0 +1 @@
@ stdcall InitHelperDll(long ptr)
+106
View File
@@ -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 <[email protected]>
*/
#include "precomp.h"
#include <guiddef.h>
#define NDEBUG
#include <debug.h>
#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;
}
+348
View File
@@ -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 <[email protected]>
*/
#include "precomp.h"
#include <guiddef.h>
#define NDEBUG
#include <debug.h>
#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;
}
+28
View File
@@ -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
+36
View File
@@ -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 <[email protected]>
*/
#ifndef PRECOMP_H
#define PRECOMP_H
/* INCLUDES ******************************************************************/
#define WIN32_NO_STATUS
#include <stdarg.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#define _INC_WINDOWS
#include <winsock2.h>
#include <iphlpapi.h>
#include <ip2string.h>
#include <netsh.h>
extern HINSTANCE hDllInstance;
DWORD
WINAPI
RegisterInterfaceHelper(VOID);
DWORD
WINAPI
RegisterIpHelper(VOID);
#endif /* PRECOMP_H */
+24
View File
@@ -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