You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1299 lines
39 KiB
1299 lines
39 KiB
/*++
|
|
|
|
Copyright (c) 1999, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
net\routing\netsh\ip\protocols\vrrphlpopt.c
|
|
|
|
Abstract:
|
|
|
|
VRRP command options implementation.
|
|
This module contains handlers for the configuration commands
|
|
supported by the VRRP Protocol.
|
|
|
|
Author:
|
|
|
|
Peeyush Ranjan (peeyushr) 1-Mar-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include <ipcmp.h>
|
|
|
|
#define Malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
|
#define Free(x) HeapFree(GetProcessHeap(), 0, (x))
|
|
|
|
//
|
|
// Forward declarations
|
|
//
|
|
|
|
ULONG
|
|
QueryTagArray(
|
|
PTCHAR ArgumentArray[],
|
|
ULONG ArgumentCount,
|
|
TAG_TYPE TagTypeArray[],
|
|
ULONG TagTypeCount,
|
|
OUT PULONG* TagArray
|
|
);
|
|
|
|
ULONG
|
|
ValidateTagTypeArray(
|
|
TAG_TYPE TagTypeArray[],
|
|
ULONG TagTypeCount
|
|
);
|
|
|
|
|
|
DWORD
|
|
HandleVrrpAddVRID(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG BitVector;
|
|
ULONG Error;
|
|
ULONG ErrorIndex = 0;
|
|
ULONG i;
|
|
VRRP_VROUTER_CONFIG VRouterGiven;
|
|
PULONG TagArray;
|
|
WCHAR InterfaceName[MAX_INTERFACE_NAME_LEN + 1];
|
|
ULONG InfoSize;
|
|
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_INTERFACE_NAME, TRUE, FALSE },
|
|
{ TOKEN_OPT_VRID, TRUE, FALSE },
|
|
{ TOKEN_OPT_IPADDRESS, TRUE, FALSE }
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
BitVector = 0;
|
|
|
|
//
|
|
// Make the default info
|
|
//
|
|
//
|
|
MakeVrrpVRouterInfo((PUCHAR) &VRouterGiven);
|
|
|
|
// We now scan the argument list, converting the arguments
|
|
// into information in our 'VrouterGiven' structure.
|
|
//
|
|
|
|
for (i = 0; i < ArgumentsLeft; i++) {
|
|
switch(TagArray ? TagArray[i] : i) {
|
|
case 0: {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
Error =
|
|
IpmontrGetIfNameFromFriendlyName(
|
|
ArgumentArray[i + ArgumentIndex], InterfaceName, &Length
|
|
);
|
|
if (Error) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_NO_INTERFACE,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 1: {
|
|
ULONG VRIDGiven;
|
|
VRIDGiven = _tcstoul(ArgumentArray[i + ArgumentIndex], NULL, 10);
|
|
|
|
if (VRIDGiven > 255) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_INVALID_VRID,
|
|
VRIDGiven
|
|
);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VRouterGiven.VRID = (BYTE) VRIDGiven;
|
|
BitVector |= VRRP_INTF_VRID_MASK;
|
|
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 2: {
|
|
ULONG AddressSpecified;
|
|
//
|
|
// If the IP address has been specified, the VRID should have been
|
|
// specified already
|
|
//
|
|
if (!(BitVector & VRRP_INTF_VRID_MASK)){
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
|
|
AddressSpecified = GetIpAddress(ArgumentArray[i + ArgumentIndex]);
|
|
if (!AddressSpecified || AddressSpecified == INADDR_NONE) {
|
|
DisplayMessage(
|
|
g_hModule,
|
|
MSG_IP_BAD_IP_ADDR,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
ErrorIndex = i;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VRouterGiven.IPCount = 1;
|
|
VRouterGiven.IPAddress[0] = AddressSpecified;
|
|
BitVector |= VRRP_INTF_IPADDR_MASK;
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
default: {
|
|
i = ArgumentsLeft;
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Error) {
|
|
//
|
|
// Ensure that all required parameters are present.
|
|
//
|
|
Error =
|
|
ValidateTagTypeArray(TagTypeArray, NUM_TAGS_IN_TABLE(TagTypeArray));
|
|
}
|
|
if (Error == ERROR_TAG_ALREADY_PRESENT) {
|
|
DisplayMessage(g_hModule, EMSG_TAG_ALREADY_PRESENT);
|
|
} else if (Error == ERROR_INVALID_PARAMETER && TagArray) {
|
|
DispTokenErrMsg(
|
|
g_hModule,
|
|
EMSG_BAD_OPTION_VALUE,
|
|
TagTypeArray[TagArray[ErrorIndex]],
|
|
ArgumentArray[ErrorIndex + ArgumentIndex]
|
|
);
|
|
} else if (!Error && (BitVector)) {
|
|
//
|
|
// Update the configuration with the new settings.
|
|
// Note that the update routine may perform additional validation
|
|
// in the process of reconciling the new settings
|
|
// with any existing settings.
|
|
//
|
|
Error =
|
|
UpdateVrrpInterfaceInfo(
|
|
InterfaceName, &VRouterGiven, BitVector, FALSE
|
|
);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
HandleVrrpAddInterface(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG BitVector;
|
|
ULONG Error;
|
|
ULONG ErrorIndex = 0;
|
|
ULONG i;
|
|
VRRP_VROUTER_CONFIG VRouterGiven;
|
|
PULONG TagArray;
|
|
WCHAR InterfaceName[MAX_INTERFACE_NAME_LEN + 1];
|
|
ULONG InfoSize;
|
|
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_INTERFACE_NAME, TRUE, FALSE },
|
|
{ TOKEN_OPT_VRID, FALSE, FALSE },
|
|
{ TOKEN_OPT_IPADDRESS, FALSE, FALSE }
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
BitVector = 0;
|
|
|
|
//
|
|
// We now scan the argument list, converting the arguments
|
|
// into information in our 'VrouterGiven' structure.
|
|
//
|
|
|
|
for (i = 0; i < ArgumentsLeft; i++) {
|
|
switch(TagArray ? TagArray[i] : i) {
|
|
case 0: {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
Error =
|
|
IpmontrGetIfNameFromFriendlyName(
|
|
ArgumentArray[i + ArgumentIndex], InterfaceName, &Length
|
|
);
|
|
if (Error) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_NO_INTERFACE,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 1: {
|
|
ULONG VRIDGiven;
|
|
VRIDGiven = _tcstoul(ArgumentArray[i + ArgumentIndex], NULL, 10);
|
|
|
|
if (VRIDGiven > 255) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_INVALID_VRID,
|
|
VRIDGiven
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VRouterGiven.VRID = (BYTE) VRIDGiven;
|
|
BitVector |= VRRP_INTF_VRID_MASK;
|
|
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 2: {
|
|
ULONG AddressSpecified;
|
|
//
|
|
// If the IP address has been specified, the VRID should have been
|
|
// specified already
|
|
//
|
|
if (!(BitVector & VRRP_INTF_VRID_MASK)){
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
|
|
AddressSpecified = GetIpAddress(ArgumentArray[i + ArgumentIndex]);
|
|
if (!AddressSpecified || AddressSpecified == INADDR_NONE) {
|
|
DisplayMessage(
|
|
g_hModule,
|
|
MSG_IP_BAD_IP_ADDR,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
ErrorIndex = i;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
|
|
VRouterGiven.IPCount = 1;
|
|
VRouterGiven.IPAddress[0] = AddressSpecified;
|
|
BitVector |= VRRP_INTF_IPADDR_MASK;
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
default: {
|
|
i = ArgumentsLeft;
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
}
|
|
}
|
|
}
|
|
if ((BitVector) && (!(BitVector & VRRP_INTF_VRID_MASK)
|
|
|| !(BitVector & VRRP_INTF_IPADDR_MASK))) {
|
|
//
|
|
// You can either have no VRID, or both VRID and IP address, not only one of them
|
|
//
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
if (!Error) {
|
|
//
|
|
// Ensure that all required parameters are present.
|
|
//
|
|
Error =
|
|
ValidateTagTypeArray(TagTypeArray, NUM_TAGS_IN_TABLE(TagTypeArray));
|
|
}
|
|
if (Error == ERROR_TAG_ALREADY_PRESENT) {
|
|
DisplayMessage(g_hModule, EMSG_TAG_ALREADY_PRESENT);
|
|
} else if (Error == ERROR_INVALID_PARAMETER && TagArray) {
|
|
DispTokenErrMsg(
|
|
g_hModule,
|
|
EMSG_BAD_OPTION_VALUE,
|
|
TagTypeArray[TagArray[ErrorIndex]],
|
|
ArgumentArray[ErrorIndex + ArgumentIndex]
|
|
);
|
|
} else if (!Error) {
|
|
//
|
|
// Update the configuration with the new settings.
|
|
// Note that the update routine may perform additional validation
|
|
// in the process of reconciling the new settings
|
|
// with any existing settings.
|
|
//
|
|
Error =
|
|
UpdateVrrpInterfaceInfo(
|
|
InterfaceName, &VRouterGiven, BitVector, TRUE
|
|
);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleVrrpDeleteInterface(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG BitVector;
|
|
ULONG Error;
|
|
ULONG ErrorIndex = 0;
|
|
ULONG i;
|
|
VRRP_VROUTER_CONFIG VRouterGiven;
|
|
PULONG TagArray;
|
|
WCHAR InterfaceName[MAX_INTERFACE_NAME_LEN + 1];
|
|
ULONG InfoSize;
|
|
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_INTERFACE_NAME, TRUE, FALSE }
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
BitVector = 0;
|
|
|
|
//
|
|
// We now scan the argument list, converting the arguments
|
|
// into information in our 'VrouterGiven' structure.
|
|
//
|
|
|
|
for (i = 0; i < ArgumentsLeft; i++) {
|
|
switch(TagArray ? TagArray[i] : i) {
|
|
case 0: {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
Error =
|
|
IpmontrGetIfNameFromFriendlyName(
|
|
ArgumentArray[i + ArgumentIndex], InterfaceName, &Length
|
|
);
|
|
if (Error) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_NO_INTERFACE,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
default: {
|
|
i = ArgumentsLeft;
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Error) {
|
|
//
|
|
// Ensure that all required parameters are present.
|
|
//
|
|
Error =
|
|
ValidateTagTypeArray(TagTypeArray, NUM_TAGS_IN_TABLE(TagTypeArray));
|
|
}
|
|
if (Error == ERROR_TAG_ALREADY_PRESENT) {
|
|
DisplayMessage(g_hModule, EMSG_TAG_ALREADY_PRESENT);
|
|
} else if (Error == ERROR_INVALID_PARAMETER && TagArray) {
|
|
DispTokenErrMsg(
|
|
g_hModule,
|
|
EMSG_BAD_OPTION_VALUE,
|
|
TagTypeArray[TagArray[ErrorIndex]],
|
|
ArgumentArray[ErrorIndex + ArgumentIndex]
|
|
);
|
|
} else if (!Error) {
|
|
//
|
|
// Update the configuration with the new settings.
|
|
// Note that the update routine may perform additional validation
|
|
// in the process of reconciling the new settings
|
|
// with any existing settings.
|
|
//
|
|
Error =
|
|
DeleteVrrpInterfaceInfo(
|
|
InterfaceName, &VRouterGiven, BitVector, TRUE
|
|
);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleVrrpDeleteVRID(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG BitVector;
|
|
ULONG Error;
|
|
ULONG ErrorIndex = 0;
|
|
ULONG i;
|
|
VRRP_VROUTER_CONFIG VRouterGiven;
|
|
PULONG TagArray;
|
|
WCHAR InterfaceName[MAX_INTERFACE_NAME_LEN + 1];
|
|
ULONG InfoSize;
|
|
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_INTERFACE_NAME, TRUE, FALSE },
|
|
{ TOKEN_OPT_VRID, TRUE, FALSE }
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
BitVector = 0;
|
|
|
|
//
|
|
// We now scan the argument list, converting the arguments
|
|
// into information in our 'VrouterGiven' structure.
|
|
//
|
|
|
|
for (i = 0; i < ArgumentsLeft; i++) {
|
|
switch(TagArray ? TagArray[i] : i) {
|
|
case 0: {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
Error =
|
|
IpmontrGetIfNameFromFriendlyName(
|
|
ArgumentArray[i + ArgumentIndex], InterfaceName, &Length
|
|
);
|
|
if (Error) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_NO_INTERFACE,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 1: {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
DWORD VRIDGiven;
|
|
VRIDGiven = _tcstoul(ArgumentArray[i + ArgumentIndex], NULL, 10);
|
|
|
|
if (VRIDGiven > 255) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_INVALID_VRID,
|
|
VRIDGiven
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VRouterGiven.VRID = (BYTE) VRIDGiven;
|
|
BitVector |= VRRP_INTF_VRID_MASK;
|
|
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
default: {
|
|
i = ArgumentsLeft;
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Error) {
|
|
//
|
|
// Ensure that all required parameters are present.
|
|
//
|
|
Error =
|
|
ValidateTagTypeArray(TagTypeArray, NUM_TAGS_IN_TABLE(TagTypeArray));
|
|
}
|
|
if (Error == ERROR_TAG_ALREADY_PRESENT) {
|
|
DisplayMessage(g_hModule, EMSG_TAG_ALREADY_PRESENT);
|
|
} else if (Error == ERROR_INVALID_PARAMETER && TagArray) {
|
|
DispTokenErrMsg(
|
|
g_hModule,
|
|
EMSG_BAD_OPTION_VALUE,
|
|
TagTypeArray[TagArray[ErrorIndex]],
|
|
ArgumentArray[ErrorIndex + ArgumentIndex]
|
|
);
|
|
} else if (!Error && (BitVector)) {
|
|
//
|
|
// Update the configuration with the new settings.
|
|
// Note that the update routine may perform additional validation
|
|
// in the process of reconciling the new settings
|
|
// with any existing settings.
|
|
//
|
|
Error =
|
|
DeleteVrrpInterfaceInfo(
|
|
InterfaceName, &VRouterGiven, BitVector, FALSE
|
|
);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DumpVrrpInformation(VOID)
|
|
{
|
|
PMPR_INTERFACE_0 Array;
|
|
ULONG Count = 0;
|
|
ULONG Error;
|
|
ULONG i;
|
|
PUCHAR Information;
|
|
ULONG Length;
|
|
ULONG Total;
|
|
ULONG Type;
|
|
|
|
DisplayMessage(g_hModule,DMP_VRRP_HEADER);
|
|
DisplayMessageT(DMP_VRRP_PUSHD);
|
|
DisplayMessageT(DMP_VRRP_UNINSTALL);
|
|
//
|
|
// Show the global info commands
|
|
//
|
|
|
|
ShowVrrpGlobalInfo(INVALID_HANDLE_VALUE);
|
|
//
|
|
// Now show every interface
|
|
//
|
|
Error = IpmontrInterfaceEnum((PUCHAR*)&Array, &Count, &Total);
|
|
if (Error) {
|
|
DisplayError(g_hModule, Error);
|
|
return NO_ERROR;
|
|
}
|
|
for (i = 0; i < Count; i++) {
|
|
Error =
|
|
IpmontrGetInfoBlockFromInterfaceInfo(
|
|
Array[i].wszInterfaceName,
|
|
MS_IP_VRRP,
|
|
&Information,
|
|
&Length,
|
|
&Total,
|
|
&Type
|
|
);
|
|
if (!Error) {
|
|
Free(Information);
|
|
ShowVrrpInterfaceInfo(INVALID_HANDLE_VALUE, Array[i].wszInterfaceName);
|
|
}
|
|
}
|
|
|
|
DisplayMessageT(DMP_POPD);
|
|
DisplayMessage(g_hModule, DMP_VRRP_FOOTER);
|
|
|
|
Free(Array);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleVrrpInstall(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG Error;
|
|
PUCHAR GlobalInfo;
|
|
ULONG Length;
|
|
if (ArgumentIndex != ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
//
|
|
// To install the VRRP, we construct the default configuration
|
|
// and add it to the global configuration for the router.
|
|
//
|
|
Error = MakeVrrpGlobalInfo(&GlobalInfo, &Length);
|
|
if (Error) {
|
|
DisplayError(g_hModule, Error);
|
|
} else {
|
|
Error =
|
|
IpmontrSetInfoBlockInGlobalInfo(
|
|
MS_IP_VRRP,
|
|
GlobalInfo,
|
|
Length,
|
|
1
|
|
);
|
|
Free(GlobalInfo);
|
|
if (!Error) {
|
|
DEBUG("Added VRRP");
|
|
} else {
|
|
DisplayError(g_hModule, Error);
|
|
}
|
|
Error = SetArpRetryCount(0);
|
|
}
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
HandleVrrpSetGlobal(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG Error;
|
|
PULONG TagArray;
|
|
PVRRP_GLOBAL_CONFIG pVrrpNewGlobalConfig;
|
|
DWORD LoggingLevel;
|
|
ULONG i;
|
|
ULONG ErrorIndex;
|
|
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_LOGGINGLEVEL, FALSE, FALSE }
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) {
|
|
return ERROR_SHOW_USAGE;
|
|
}
|
|
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
for (i = 0; i < ArgumentsLeft; i++) {
|
|
switch(TagArray ? TagArray[i] : i) {
|
|
case 0: {
|
|
TOKEN_VALUE TokenArray[] = {
|
|
{ TOKEN_OPT_VALUE_NONE, VRRP_LOGGING_NONE },
|
|
{ TOKEN_OPT_VALUE_ERROR, VRRP_LOGGING_ERROR },
|
|
{ TOKEN_OPT_VALUE_WARN, VRRP_LOGGING_WARN },
|
|
{ TOKEN_OPT_VALUE_INFO, VRRP_LOGGING_INFO }
|
|
};
|
|
Error =
|
|
MatchEnumTag(
|
|
g_hModule,
|
|
ArgumentArray[i + ArgumentIndex],
|
|
NUM_TOKENS_IN_TABLE(TokenArray),
|
|
TokenArray,
|
|
&LoggingLevel
|
|
);
|
|
if (Error) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
ErrorIndex = i;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
default: {
|
|
i = ArgumentsLeft;
|
|
Error = ERROR_INVALID_SYNTAX;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Error) {
|
|
//
|
|
// Ensure that all required parameters are present.
|
|
//
|
|
Error =
|
|
ValidateTagTypeArray(TagTypeArray, NUM_TAGS_IN_TABLE(TagTypeArray));
|
|
}
|
|
if (Error == ERROR_TAG_ALREADY_PRESENT) {
|
|
DisplayMessage(g_hModule, EMSG_TAG_ALREADY_PRESENT);
|
|
} else if (Error == ERROR_INVALID_PARAMETER && TagArray) {
|
|
DispTokenErrMsg(
|
|
g_hModule,
|
|
EMSG_BAD_OPTION_VALUE,
|
|
TagTypeArray[TagArray[ErrorIndex]],
|
|
ArgumentArray[ErrorIndex + ArgumentIndex]
|
|
);
|
|
} else if (!Error){
|
|
Error = CreateVrrpGlobalInfo(&pVrrpNewGlobalConfig,LoggingLevel);
|
|
|
|
if (!Error) {
|
|
//
|
|
// Update the configuration with the new settings.
|
|
// Note that the update routine may perform additional validation
|
|
// in the process of reconciling the new settings
|
|
// with any existing settings.
|
|
//
|
|
Error = UpdateVrrpGlobalInfo(pVrrpNewGlobalConfig);
|
|
Free(pVrrpNewGlobalConfig);
|
|
}
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleVrrpSetInterface(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG BitVector;
|
|
ULONG Error;
|
|
ULONG ErrorIndex = 0;
|
|
ULONG i;
|
|
VRRP_VROUTER_CONFIG VrouterInfo;
|
|
PULONG TagArray;
|
|
WCHAR InterfaceName[MAX_INTERFACE_NAME_LEN + 1];
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_INTERFACE_NAME, TRUE, FALSE },
|
|
{ TOKEN_OPT_VRID, TRUE, FALSE },
|
|
{ TOKEN_OPT_AUTH, FALSE, FALSE},
|
|
{ TOKEN_OPT_PASSWD, FALSE, FALSE},
|
|
{ TOKEN_OPT_ADVTINTERVAL, FALSE, FALSE},
|
|
{ TOKEN_OPT_PRIO, FALSE, FALSE},
|
|
{ TOKEN_OPT_PREEMPT, FALSE, FALSE}
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) {
|
|
return ERROR_SHOW_USAGE;
|
|
}
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
BitVector = 0;
|
|
ZeroMemory(&VrouterInfo, sizeof(VrouterInfo));
|
|
|
|
//
|
|
// We now scan the argument list, converting the arguments
|
|
// into information in our 'VrouterInfo' structure.
|
|
//
|
|
|
|
for (i = 0; i < ArgumentsLeft; i++) {
|
|
switch(TagArray ? TagArray[i] : i) {
|
|
case 0: {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
Error =
|
|
IpmontrGetIfNameFromFriendlyName(
|
|
ArgumentArray[i + ArgumentIndex], InterfaceName, &Length
|
|
);
|
|
if (Error) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_NO_INTERFACE,
|
|
ArgumentArray[i + ArgumentIndex]
|
|
);
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 1:{
|
|
BYTE VRIDGiven;
|
|
|
|
VRIDGiven =
|
|
(UCHAR)_tcstoul(ArgumentArray[i + ArgumentIndex], NULL, 10);
|
|
|
|
if (VRIDGiven > 255) {
|
|
DisplayMessage(
|
|
g_hModule, EMSG_INVALID_VRID,
|
|
VRIDGiven
|
|
);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VrouterInfo.VRID = (BYTE) VRIDGiven;
|
|
BitVector |= VRRP_INTF_VRID_MASK;
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 2:{
|
|
TOKEN_VALUE TokenArray[] = {
|
|
{ TOKEN_OPT_VALUE_AUTH_NONE, VRRP_AUTHTYPE_NONE },
|
|
{ TOKEN_OPT_VALUE_AUTH_SIMPLE_PASSWORD, VRRP_AUTHTYPE_PLAIN },
|
|
{ TOKEN_OPT_VALUE_AUTH_MD5, VRRP_AUTHTYPE_IPHEAD }
|
|
};
|
|
DWORD dwAuthType;
|
|
|
|
Error =
|
|
MatchEnumTag(
|
|
g_hModule,
|
|
ArgumentArray[i + ArgumentIndex],
|
|
NUM_TOKENS_IN_TABLE(TokenArray),
|
|
TokenArray,
|
|
&dwAuthType
|
|
);
|
|
VrouterInfo.AuthenticationType = (BYTE) dwAuthType;
|
|
if (Error) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
ErrorIndex = i;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
BitVector |= VRRP_INTF_AUTH_MASK;
|
|
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 3:{
|
|
UINT Index;
|
|
UINT PassByte;
|
|
PTCHAR Token;
|
|
PTCHAR Password;
|
|
|
|
#if 0
|
|
//
|
|
// Allocate more space for the tokenizing NULL
|
|
//
|
|
|
|
Password = Malloc((2+_tcslen(ArgumentArray[i + ArgumentIndex])) *
|
|
sizeof(TCHAR));
|
|
|
|
if (!Password) {
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
_tcscpy(Password,ArgumentArray[i + ArgumentIndex]);
|
|
|
|
ZeroMemory(VrouterInfo.AuthenticationData,VRRP_MAX_AUTHKEY_SIZE);
|
|
Token = _tcstok(Password,L"-");
|
|
for (Index = 0; Index < VRRP_MAX_AUTHKEY_SIZE; Index++) {
|
|
PassByte = _tcstoul(Token, NULL, 10);
|
|
if (PassByte > 255) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VrouterInfo.AuthenticationData[Index] = PassByte & 0xff;
|
|
Token = _tcstok(NULL,"-");
|
|
if (!Token) {
|
|
break;
|
|
}
|
|
}
|
|
Free(Password);
|
|
if (Error) {
|
|
break;
|
|
}
|
|
#else
|
|
Password = ArgumentArray[i + ArgumentIndex];
|
|
for (Index = 0; Index < VRRP_MAX_AUTHKEY_SIZE; Index++) {
|
|
PassByte = _tcstoul(Password, NULL, 10);
|
|
if (PassByte > 255) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VrouterInfo.AuthenticationData[Index] = PassByte & 0xff;
|
|
Password = _tcschr(Password,_T('-'));
|
|
if (!Password) {
|
|
break;
|
|
}
|
|
Password ++;
|
|
}
|
|
#endif
|
|
|
|
BitVector |= VRRP_INTF_PASSWD_MASK;
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 4:{
|
|
BYTE AdvtIntvl;
|
|
AdvtIntvl = (UCHAR)
|
|
_tcstoul(ArgumentArray[i + ArgumentIndex], NULL, 10);
|
|
|
|
if (AdvtIntvl > 255) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VrouterInfo.AdvertisementInterval = (BYTE) AdvtIntvl;
|
|
BitVector |= VRRP_INTF_ADVT_MASK;
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 5:{
|
|
BYTE ConfigPrio;
|
|
ConfigPrio = (UCHAR)
|
|
_tcstoul(ArgumentArray[i + ArgumentIndex], NULL, 10);
|
|
|
|
if (ConfigPrio > 255) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
VrouterInfo.ConfigPriority = (BYTE) ConfigPrio;
|
|
BitVector |= VRRP_INTF_PRIO_MASK;
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
case 6:{
|
|
TOKEN_VALUE TokenArray[] = {
|
|
{ TOKEN_OPT_VALUE_ENABLE, TRUE },
|
|
{ TOKEN_OPT_VALUE_DISABLE, FALSE }
|
|
};
|
|
Error =
|
|
MatchEnumTag(
|
|
g_hModule,
|
|
ArgumentArray[i + ArgumentIndex],
|
|
NUM_TOKENS_IN_TABLE(TokenArray),
|
|
TokenArray,
|
|
&VrouterInfo.PreemptMode
|
|
);
|
|
if (Error) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
ErrorIndex = i;
|
|
i = ArgumentsLeft;
|
|
break;
|
|
}
|
|
BitVector |= VRRP_INTF_PREEMPT_MASK;
|
|
|
|
TagTypeArray[TagArray ? TagArray[i] : i].bPresent = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!Error) {
|
|
//
|
|
// Ensure that all required parameters are present.
|
|
//
|
|
Error =
|
|
ValidateTagTypeArray(TagTypeArray, NUM_TAGS_IN_TABLE(TagTypeArray));
|
|
}
|
|
if (Error == ERROR_TAG_ALREADY_PRESENT) {
|
|
DisplayMessage(g_hModule, EMSG_TAG_ALREADY_PRESENT);
|
|
} else if (Error == ERROR_INVALID_PARAMETER && TagArray) {
|
|
DispTokenErrMsg(
|
|
g_hModule,
|
|
EMSG_BAD_OPTION_VALUE,
|
|
TagTypeArray[TagArray[ErrorIndex]],
|
|
ArgumentArray[ErrorIndex + ArgumentIndex]
|
|
);
|
|
} else if (!Error && (BitVector)) {
|
|
//
|
|
// Update the configuration with the new settings.
|
|
// Note that the update routine may perform additional validation
|
|
// in the process of reconciling the new settings
|
|
// with any existing settings.
|
|
//
|
|
Error =
|
|
UpdateVrrpInterfaceInfo(
|
|
InterfaceName, &VrouterInfo, BitVector, FALSE
|
|
);
|
|
}
|
|
if (TagArray) { Free(TagArray); }
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
HandleVrrpShowGlobal(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
if (ArgumentIndex != ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
ShowVrrpGlobalInfo(NULL);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleVrrpShowInterface(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG ArgumentsLeft;
|
|
ULONG Error;
|
|
PULONG TagArray;
|
|
WCHAR InterfaceName[MAX_INTERFACE_NAME_LEN + 1];
|
|
TAG_TYPE TagTypeArray[] = {
|
|
{ TOKEN_OPT_INTERFACE_NAME, TRUE, FALSE }
|
|
};
|
|
|
|
VERIFY_INSTALLED(MS_IP_VRRP, L"VRRP");
|
|
|
|
if (ArgumentIndex >= ArgumentCount) {
|
|
return ERROR_SHOW_USAGE;
|
|
}
|
|
ArgumentsLeft = ArgumentCount - ArgumentIndex;
|
|
|
|
//
|
|
// We convert the optional tags into an array of 'TagTypeArray' indices
|
|
// which guide is in our scanning of the argument list.
|
|
// Since the tags are optional, this process may result in no tags at all,
|
|
// in which case we assume that arguments are specified in exactly the order
|
|
// given in 'TagTypeArray' above.
|
|
//
|
|
|
|
Error =
|
|
QueryTagArray(
|
|
&ArgumentArray[ArgumentIndex],
|
|
ArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&TagArray
|
|
);
|
|
if (Error) { return Error; }
|
|
|
|
//
|
|
// If any tags were specified, the only one present must refer
|
|
// to the interface name which is index '0' in 'TagTypeArray'.
|
|
// If no tags were specified, we assume the argument is an interface name,
|
|
// and we retrieve its friendly name in order to delete it.
|
|
//
|
|
|
|
if (TagArray && TagArray[0] != 0) {
|
|
Free(TagArray);
|
|
return ERROR_SHOW_USAGE;
|
|
} else {
|
|
ULONG Length = sizeof(InterfaceName);
|
|
Error =
|
|
IpmontrGetIfNameFromFriendlyName(
|
|
ArgumentArray[ArgumentIndex], InterfaceName, &Length
|
|
);
|
|
}
|
|
if (!Error) {
|
|
Error = ShowVrrpInterfaceInfo(NULL, InterfaceName);
|
|
}
|
|
if (TagArray) { Free(TagArray); }
|
|
return Error;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleVrrpUninstall(
|
|
PWCHAR MachineName,
|
|
PTCHAR* ArgumentArray,
|
|
DWORD ArgumentIndex,
|
|
DWORD ArgumentCount,
|
|
DWORD CmdFlags,
|
|
PVOID Data,
|
|
BOOL* CommandDone
|
|
)
|
|
{
|
|
ULONG Error;
|
|
if (ArgumentIndex != ArgumentCount) { return ERROR_SHOW_USAGE; }
|
|
Error = IpmontrDeleteProtocol(MS_IP_VRRP);
|
|
if (!Error) { DEBUG("Deleted VRRP"); }
|
|
Error = SetArpRetryCount(3);
|
|
return Error;
|
|
}
|
|
|
|
ULONG
|
|
QueryTagArray(
|
|
PTCHAR ArgumentArray[],
|
|
ULONG ArgumentCount,
|
|
TAG_TYPE TagTypeArray[],
|
|
ULONG TagTypeCount,
|
|
OUT PULONG* TagArray
|
|
)
|
|
{
|
|
ULONG Error;
|
|
ULONG i;
|
|
|
|
if (!_tcsstr(ArgumentArray[0], ptszDelimiter)) {
|
|
*TagArray = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
*TagArray = Malloc(ArgumentCount * sizeof(ULONG));
|
|
if (!*TagArray) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
Error =
|
|
MatchTagsInCmdLine(
|
|
g_hModule,
|
|
ArgumentArray,
|
|
0,
|
|
ArgumentCount,
|
|
TagTypeArray,
|
|
TagTypeCount,
|
|
*TagArray
|
|
);
|
|
if (Error) {
|
|
Free(*TagArray);
|
|
*TagArray = NULL;
|
|
if (Error == ERROR_INVALID_OPTION_TAG) {
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
ULONG
|
|
ValidateTagTypeArray(
|
|
TAG_TYPE TagTypeArray[],
|
|
ULONG TagTypeCount
|
|
)
|
|
{
|
|
ULONG i;
|
|
//
|
|
// Verify that all required tokens are present.
|
|
//
|
|
for (i = 0; i < TagTypeCount; i++) {
|
|
if ((TagTypeArray[i].dwRequired & NS_REQ_PRESENT)
|
|
&& !TagTypeArray[i].bPresent) {
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
}
|
|
return NO_ERROR;
|
|
}
|