1300 lines
38 KiB
C
1300 lines
38 KiB
C
/*++
|
||
|
||
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;
|
||
}
|