[IFMON] Add the 'delete address', 'delete dns' and 'reset' commands to the 'interface ip' context

The 'reset' command is just a stub.
This commit is contained in:
Eric Kohl
2026-06-21 00:35:46 +02:00
parent 332331ce1b
commit a6133d2b44
3 changed files with 529 additions and 5 deletions

View File

@@ -31,15 +31,19 @@
#define REGISTER_PRIMARY 2
#define REGISTER_BOTH 3
#define ADDRESS_ALL 1
static FN_HANDLE_CMD IpAddAddress;
static FN_HANDLE_CMD IpAddDns;
static FN_HANDLE_CMD IpDeleteAddress;
static FN_HANDLE_CMD IpDeleteArpCache;
static FN_HANDLE_CMD IpDeleteDns;
static FN_HANDLE_CMD IpSetAddress;
static FN_HANDLE_CMD IpSetDns;
static FN_HANDLE_CMD IpShowAddresses;
static FN_HANDLE_CMD IpShowConfig;
static FN_HANDLE_CMD IpShowDns;
static FN_HANDLE_CMD IpReset;
static
CMD_ENTRY
@@ -53,7 +57,9 @@ static
CMD_ENTRY
IpDeleteCommands[] =
{
{L"arpcache", IpDeleteArpCache, IDS_HLP_IP_DELETE_ARPCACHE, IDS_HLP_IP_DELETE_ARPCACHE_EX, 0}
{L"address", IpDeleteAddress, IDS_HLP_IP_DELETE_ADDRESS, IDS_HLP_IP_DELETE_ADDRESS_EX, 0},
{L"arpcache", IpDeleteArpCache, IDS_HLP_IP_DELETE_ARPCACHE, IDS_HLP_IP_DELETE_ARPCACHE_EX, 0},
{L"dns", IpDeleteDns, IDS_HLP_IP_DELETE_DNS, IDS_HLP_IP_DELETE_DNS_EX, 0}
};
static
@@ -83,6 +89,13 @@ IpGroups[] =
{L"show", IDS_HLP_IP_SHOW, sizeof(IpShowCommands) / sizeof(CMD_ENTRY), 0, IpShowCommands, NULL},
};
static
CMD_ENTRY
IpTopCommands[] =
{
{L"reset", IpReset, IDS_HLP_IP_RESET, IDS_HLP_IP_RESET_EX, 0}
};
static
HRESULT
@@ -446,6 +459,51 @@ AppendParameterValue(
return TRUE;
}
static
BOOL
DeleteParameterValue(
PWSTR pszParameters,
PWSTR pszParameter,
PWSTR pszValue)
{
PWSTR pToken, pStart, pEnd, pValStart, pValEnd;
pToken = wcsstr(pszParameters, pszParameter);
if (pToken == NULL)
return FALSE;
pEnd = wcschr(pToken, L';');
if (pEnd == NULL)
return FALSE;
pStart = pToken + wcslen(pszParameter) + 1;
if (pStart == pEnd)
return TRUE;
if (pszValue == NULL)
{
MoveMemory(pStart, pEnd, (wcslen(pEnd) + 1) * sizeof(WCHAR));
}
else
{
pValStart = wcsstr(pStart, pszValue);
if ((pValStart >= pStart) & (pValStart < pEnd))
{
pValEnd = pValStart + wcslen(pszValue);
if (*pValEnd == L',')
pValEnd++;
else if ((*pValEnd == L';') && (*(pValStart - 1) == L','))
pValStart--;
MoveMemory(pValStart, pValEnd, (wcslen(pValEnd) + 1) * sizeof(WCHAR));
}
else
{
return FALSE;
}
}
return TRUE;
}
static
DWORD
@@ -900,6 +958,228 @@ done:
}
static
DWORD
WINAPI
IpDeleteAddress(
LPCWSTR pwszMachine,
LPWSTR *argv,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
LPCVOID pvData,
BOOL *pbDone)
{
TAG_TYPE pttTags[] = {{L"name", NS_REQ_ZERO, FALSE},
{L"addr", NS_REQ_ZERO, FALSE},
{L"gateway", NS_REQ_ZERO, FALSE}};
GUID InterfaceGUID;
PDWORD pdwTagType = NULL;
DWORD i;
BOOL bHaveName = FALSE, bHaveAddress = FALSE, bHaveGateway = FALSE;
IN_ADDR Address, Gateway;
PWSTR pszName = NULL, pszAddress = NULL, pszGateway = NULL;
PWSTR pszNewIpAddress = NULL, pszNewSubnetMask = NULL, pszNewParameters = NULL;
// DWORD dwLength;
PCWSTR Term;
PTCPIP_PROPERTIES pProperties = NULL;
TCPIP_PROPERTIES NewProperties;
HRESULT hr;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
DPRINT("IpDeleteAddress()\n");
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
(dwArgCount - dwCurrentIndex) * sizeof(DWORD));
if (pdwTagType == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
dwError = MatchTagsInCmdLine(hDllInstance,
argv,
dwCurrentIndex,
dwArgCount,
pttTags,
ARRAYSIZE(pttTags),
pdwTagType);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("MatchTagsInCmdLine() failed (Error %lu)\n", dwError);
HeapFree(GetProcessHeap(), 0, pdwTagType);
return dwError;
}
for (i = 0; i < (dwArgCount - dwCurrentIndex); i++)
{
DPRINT("Tag %lu: %lu\n", i, pdwTagType[i]);
switch (pdwTagType[i])
{
case 0: /* name */
DPRINT("Tag: name (%S)\n", argv[i + dwCurrentIndex]);
dwError = NhGetGuidFromInterfaceName(argv[i + dwCurrentIndex],
&InterfaceGUID,
0, 0);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("NhGetGuidFromInterfaceName() failed (Error %lu)\n", dwError);
PrintMessageFromModule(hDllInstance,
IDS_ERROR_INVALID_INTERFACE,
argv[i + dwCurrentIndex]);
dwError = ERROR_SUPPRESS_OUTPUT;
break;
}
pszName = argv[i + dwCurrentIndex];
DPRINT("Interface: {%08lx-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
InterfaceGUID.Data1, InterfaceGUID.Data2, InterfaceGUID.Data3, InterfaceGUID.Data4[0], InterfaceGUID.Data4[1],
InterfaceGUID.Data4[2], InterfaceGUID.Data4[3], InterfaceGUID.Data4[4], InterfaceGUID.Data4[5], InterfaceGUID.Data4[6], InterfaceGUID.Data4[7]);
bHaveName = TRUE;
break;
case 1: /* addr */
DPRINT("Tag: addr (%S)\n", argv[i + dwCurrentIndex]);
Status = RtlIpv4StringToAddressW(argv[i + dwCurrentIndex],
TRUE,
&Term,
&Address);
if (Status != 0 /*STATUS_SUCCESS*/)
{
DPRINT("RtlIpv4StringToAddressW() failed (Status 0x%08lx)\n", Status);
PrintMessageFromModule(hDllInstance,
IDS_ERROR_BAD_VALUE,
argv[i + dwCurrentIndex],
pttTags[pdwTagType[i]].pwszTag);
dwError = ERROR_SUPPRESS_OUTPUT;
break;
}
DPRINT("IP Address: %u.%u.%u.%u\n",
Address.S_un.S_un_b.s_b1, Address.S_un.S_un_b.s_b2, Address.S_un.S_un_b.s_b3, Address.S_un.S_un_b.s_b4);
pszAddress = argv[i + dwCurrentIndex];
DPRINT("IP Address: %S\n", pszAddress);
bHaveAddress = TRUE;
break;
case 2: /* gateway */
DPRINT("Tag: gateway (%S)\n", argv[i + dwCurrentIndex]);
Status = RtlIpv4StringToAddressW(argv[i + dwCurrentIndex],
TRUE,
&Term,
&Gateway);
if (Status != 0 /*STATUS_SUCCESS*/)
{
DPRINT("RtlIpv4StringToAddressW() failed (Status 0x%08lx)\n", Status);
PrintMessageFromModule(hDllInstance,
IDS_ERROR_BAD_VALUE,
argv[i + dwCurrentIndex],
pttTags[pdwTagType[i]].pwszTag);
dwError = ERROR_SUPPRESS_OUTPUT;
break;
}
pszGateway = argv[i + dwCurrentIndex];
DPRINT("Gateway: %u.%u.%u.%u\n",
Gateway.S_un.S_un_b.s_b1, Gateway.S_un.S_un_b.s_b2, Gateway.S_un.S_un_b.s_b3, Gateway.S_un.S_un_b.s_b4);
bHaveGateway = TRUE;
break;
default:
DPRINT1("Unknown tag type %lu\n", pdwTagType[i]);
break;
}
}
if (pdwTagType)
HeapFree(GetProcessHeap(), 0, pdwTagType);
if (dwError != ERROR_SUCCESS)
return dwError;
/* Check parameters */
/* The interface name is mandatory */
if (bHaveName == FALSE)
return ERROR_INVALID_SYNTAX;
hr = GetInterfaceProperties(&InterfaceGUID, &pProperties);
if (FAILED(hr))
{
PrintMessageFromModule(hDllInstance,
IDS_ERROR_GET_PROPERTIES,
pszName);
return ERROR_SUPPRESS_OUTPUT;
}
if (bHaveAddress && pszAddress)
{
#if 0
dwLength = wcslen(pProperties->pszIpAddress) + 1;
pszNewIpAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR));
if (pszNewIpAddress == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
wcscpy(pszNewIpAddress, pProperties->pszIpAddress);
/* TODO */
dwLength = wcslen(pProperties->pszSubnetMask) + 1;
pszNewSubnetMask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR));
if (pszNewSubnetMask == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
wcscpy(pszNewSubnetMask, pProperties->pszSubnetMask);
/* TODO */
#endif
}
if (bHaveGateway && pszGateway)
{
#if 0
dwLength = wcslen(pProperties->pszParameters) + 1;
pszNewParameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR));
if (pszNewParameters == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
wcscpy(pszNewParameters, pProperties->pszParameters);
/* TODO */
#endif
}
NewProperties.dwDhcp = 0;
NewProperties.pszIpAddress = pszNewIpAddress ? pszNewIpAddress : pProperties->pszIpAddress;
NewProperties.pszSubnetMask = pszNewSubnetMask ? pszNewSubnetMask : pProperties->pszSubnetMask;
NewProperties.pszParameters = pszNewParameters ? pszNewParameters : pProperties->pszParameters;
SetInterfaceProperties(&InterfaceGUID, &NewProperties);
//done:
if (pszNewIpAddress)
HeapFree(GetProcessHeap(), 0, pszNewIpAddress);
if (pszNewSubnetMask)
HeapFree(GetProcessHeap(), 0, pszNewSubnetMask);
if (pszNewParameters)
HeapFree(GetProcessHeap(), 0, pszNewParameters);
CoTaskMemFree(pProperties);
pProperties = NULL;
DPRINT("IpDeleteAddress() done (Error %lu)\n", dwError);
return dwError;
}
static
DWORD
WINAPI
@@ -1020,6 +1300,186 @@ IpDeleteArpCache(
}
static
DWORD
WINAPI
IpDeleteDns(
LPCWSTR pwszMachine,
LPWSTR *argv,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
LPCVOID pvData,
BOOL *pbDone)
{
TAG_TYPE pttTags[] = {{L"name", NS_REQ_ZERO, FALSE},
{L"addr", NS_REQ_ZERO, FALSE}};
TOKEN_VALUE ptvAddress[] = {{L"all", ADDRESS_ALL}};
GUID InterfaceGUID;
PDWORD pdwTagType = NULL;
DWORD i;
BOOL bHaveName = FALSE, bHaveAddress = FALSE;
IN_ADDR Address;
PWSTR pszName = NULL, pszAddress = NULL;
PWSTR pszNewParameters = NULL;
DWORD dwAddress, dwLength;
PCWSTR Term;
PTCPIP_PROPERTIES pProperties = NULL;
TCPIP_PROPERTIES NewProperties;
HRESULT hr;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
DPRINT1("IpDeleteDns()\n");
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
(dwArgCount - dwCurrentIndex) * sizeof(DWORD));
if (pdwTagType == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
dwError = MatchTagsInCmdLine(hDllInstance,
argv,
dwCurrentIndex,
dwArgCount,
pttTags,
ARRAYSIZE(pttTags),
pdwTagType);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("MatchTagsInCmdLine() failed (Error %lu)\n", dwError);
HeapFree(GetProcessHeap(), 0, pdwTagType);
return dwError;
}
for (i = 0; i < (dwArgCount - dwCurrentIndex); i++)
{
DPRINT1("Tag %lu: %lu\n", i, pdwTagType[i]);
switch (pdwTagType[i])
{
case 0: /* name */
DPRINT1("Tag: name (%S)\n", argv[i + dwCurrentIndex]);
dwError = NhGetGuidFromInterfaceName(argv[i + dwCurrentIndex],
&InterfaceGUID,
0, 0);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("NhGetGuidFromInterfaceName() failed (Error %lu)\n", dwError);
PrintMessageFromModule(hDllInstance,
IDS_ERROR_INVALID_INTERFACE,
argv[i + dwCurrentIndex]);
dwError = ERROR_SUPPRESS_OUTPUT;
break;
}
pszName = argv[i + dwCurrentIndex];
DPRINT1("Interface: {%08lx-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
InterfaceGUID.Data1, InterfaceGUID.Data2, InterfaceGUID.Data3, InterfaceGUID.Data4[0], InterfaceGUID.Data4[1],
InterfaceGUID.Data4[2], InterfaceGUID.Data4[3], InterfaceGUID.Data4[4], InterfaceGUID.Data4[5], InterfaceGUID.Data4[6], InterfaceGUID.Data4[7]);
bHaveName = TRUE;
break;
case 1: /* addr */
DPRINT1("Tag: addr (%S)\n", argv[i + dwCurrentIndex]);
dwError = MatchEnumTag(hDllInstance,
argv[i + dwCurrentIndex],
ARRAYSIZE(ptvAddress),
ptvAddress,
&dwAddress);
if (dwError == ERROR_SUCCESS)
{
pszAddress = NULL;
}
else
{
dwError = ERROR_SUCCESS;
Status = RtlIpv4StringToAddressW(argv[i + dwCurrentIndex],
TRUE,
&Term,
&Address);
if (Status != 0 /*STATUS_SUCCESS*/)
{
DPRINT1("RtlIpv4StringToAddressW() failed (Status 0x%08lx)\n", Status);
PrintMessageFromModule(hDllInstance,
IDS_ERROR_BAD_VALUE,
argv[i + dwCurrentIndex],
pttTags[pdwTagType[i]].pwszTag);
dwError = ERROR_SUPPRESS_OUTPUT;
break;
}
DPRINT1("IP Address: %u.%u.%u.%u\n",
Address.S_un.S_un_b.s_b1, Address.S_un.S_un_b.s_b2, Address.S_un.S_un_b.s_b3, Address.S_un.S_un_b.s_b4);
pszAddress = argv[i + dwCurrentIndex];
DPRINT1("IP Address: %S\n", pszAddress);
}
bHaveAddress = TRUE;
break;
default:
DPRINT1("Unknown tag type %lu\n", pdwTagType[i]);
break;
}
}
if (pdwTagType)
HeapFree(GetProcessHeap(), 0, pdwTagType);
if (dwError != ERROR_SUCCESS)
return dwError;
/* Check parameters */
/* The interface name is mandatory */
if (bHaveName == FALSE)
return ERROR_INVALID_SYNTAX;
/* The address is mandatory */
if (!bHaveAddress)
return ERROR_INVALID_SYNTAX;
hr = GetInterfaceProperties(&InterfaceGUID, &pProperties);
if (FAILED(hr))
{
PrintMessageFromModule(hDllInstance,
IDS_ERROR_GET_PROPERTIES,
pszName);
return ERROR_SUPPRESS_OUTPUT;
}
dwLength = wcslen(pProperties->pszParameters) + 1;
pszNewParameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR));
if (pszNewParameters == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
wcscpy(pszNewParameters, pProperties->pszParameters);
DeleteParameterValue(pszNewParameters, L"DNS", pszAddress);
NewProperties.dwDhcp = 0;
NewProperties.pszIpAddress = pProperties->pszIpAddress;
NewProperties.pszSubnetMask = pProperties->pszSubnetMask;
NewProperties.pszParameters = pszNewParameters;
SetInterfaceProperties(&InterfaceGUID, &NewProperties);
done:
if (pszNewParameters)
HeapFree(GetProcessHeap(), 0, pszNewParameters);
CoTaskMemFree(pProperties);
pProperties = NULL;
DPRINT("IpDeleteDns() done (Error %lu)\n", dwError);
return dwError;
}
static
DWORD
WINAPI
@@ -1774,6 +2234,23 @@ IpShowDns(
}
static
DWORD
WINAPI
IpReset(
LPCWSTR pwszMachine,
LPWSTR *argv,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
LPCVOID pvData,
BOOL *pbDone)
{
DPRINT1("IpReset()\n");
return ERROR_SUCCESS;
}
static
DWORD
WINAPI
@@ -1903,8 +2380,8 @@ IpStart(
ContextAttributes.pwszContext = L"ip";
ContextAttributes.guidHelper = GUID_IFMON_IP;
ContextAttributes.ulNumTopCmds = 0;
ContextAttributes.pTopCmds = NULL;
ContextAttributes.ulNumTopCmds = sizeof(IpTopCommands) / sizeof(CMD_ENTRY);
ContextAttributes.pTopCmds = IpTopCommands;
ContextAttributes.ulNumGroups = sizeof(IpGroups) / sizeof(CMD_GROUP_ENTRY);
ContextAttributes.pCmdGroups = IpGroups;

View File

@@ -44,7 +44,22 @@ Examples:\n\n\
%1!s! ""Local Area Connection"" 10.0.0.1\n\
%1!s! ""Local Area Connection"" 10.0.0.3 index=2\n"
IDS_HLP_IP_DELETE "Deletes a configuration entry from a table.\n"
IDS_HLP_IP_DELETE "Deletes a configuration entry from a table.\n"
IDS_HLP_IP_DELETE_ADDRESS "Deletes an IP address or default gateway from the specified interface.\n"
IDS_HLP_IP_DELETE_ADDRESS_EX "\nUsage: %1!s! [name=]<string> [[addr=]IP address] [[gateway=]IP address|ALL]\n\n\
Parameters:\n\n\
Tag Value\n\
name - The name of the interface.\n\
addr - A static IP address for the interface specified by name.\n\
gateway - One of the following values:\n\
<IP address>: A specific default gateway IP address for\n\
the static IP address you are deleting.\n\
ALL: Deletes all default gateway IP addresses for\n\
the static IP address you are deleting.\n\n\
Remarks: Deletes an IP address from an interface with multiple static IP\n\
addresses, or deletes a default gateway from a specified interface.\n\n\
Examples:\n\n\
%1!s! ""Local Area Connection"" addr=10.0.0.1 gateway=all\n"
IDS_HLP_IP_DELETE_ARPCACHE "Flushes the ARP cache for one or all interfaces.\n"
IDS_HLP_IP_DELETE_ARPCACHE_EX "\nUsage: %1!s! [name=]<string>\n\n\
@@ -59,6 +74,21 @@ Examples:\n\n\
%1!s!\n\
%1!s! name=""Local Area Connection""\n"
IDS_HLP_IP_DELETE_DNS "Deletes the DNS server from the specified interface.\n"
IDS_HLP_IP_DELETE_DNS_EX "\nUsage: %1!s! [name=]<string> [[addr=]<IP address>|ALL ]\n\n\
Parameters:\n\n\
Tag Value\n\
name - The name of the interface where DNS servers are deleted.\n\
addr - One of the following values:\n\
<IP address>: A specific IP address of a DNS server\n\
you are deleting.\n\
ALL: Deletes all configured IP addresses for DNS. servers.\n\n\
Remarks: Deletes statically configured DNS server IP addresses for a\n\
specific interface.\n\n\
Examples:\n\n\
%1!s! ""Local Area Connection"" 10.0.0.1\n\
%1!s! ""Local Area Connection"" all\n"
IDS_HLP_IP_SET "Sets configuration information.\n"
IDS_HLP_IP_SET_ADDRESS "Sets the IP address or default gateway to the specified interface.\n"
IDS_HLP_IP_SET_ADDRESS_EX "\nUsage: %1!s! [name=]<string> \n\
@@ -142,6 +172,16 @@ Remarks: Displays the DNS server configuration for a specific interface\nor inte
Examples:\n\n\
%1!s! ""Local Area Network""\n"
IDS_HLP_IP_RESET "Resets TCP/IP and related components to a clean state.\n"
IDS_HLP_IP_RESET_EX "\nUsage: %1!s! [name=]<string>\n\n\
Parameters:\n\n\
Tag Value\n\
name - The name of a file to which to append information\n\
regarding what settings were reset.\n\n\
Remarks: Resets TCP/IP and related components to a clean state.\n\n\
Examples:\n\n\
%1!s! resetlog.txt\n"
IDS_HLP_WINSOCK_RESET "Resets the Winsock Catalog to a clean state.\n"
IDS_HLP_WINSOCK_RESET_EX "\nUsage: %1!s!\n\n\
Remarks: Resets the Winsock Catalog to a clean state.\n"

View File

@@ -10,8 +10,12 @@
#define IDS_HLP_IP_ADD_DNS_EX 204
#define IDS_HLP_IP_DELETE 205
#define IDS_HLP_IP_DELETE_ADDRESS 206
#define IDS_HLP_IP_DELETE_ADDRESS_EX 207
#define IDS_HLP_IP_DELETE_ARPCACHE 208
#define IDS_HLP_IP_DELETE_ARPCACHE_EX 209
#define IDS_HLP_IP_DELETE_DNS 210
#define IDS_HLP_IP_DELETE_DNS_EX 211
#define IDS_HLP_IP_SET 212
#define IDS_HLP_IP_SET_ADDRESS 213
@@ -27,6 +31,9 @@
#define IDS_HLP_IP_SHOW_DNS 225
#define IDS_HLP_IP_SHOW_DNS_EX 226
#define IDS_HLP_IP_RESET 227
#define IDS_HLP_IP_RESET_EX 228
#define IDS_HLP_WINSOCK_RESET 250
#define IDS_HLP_WINSOCK_RESET_EX 251
#define IDS_HLP_WINSOCK_SHOW 252