Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1107 lines
29 KiB

/*++
Copyright (c) 1999, Microsoft Corporation
Module Name:
sample\rmapi.c
Abstract:
The file contains IP router manager API implementations.
--*/
#include "pchsample.h"
#pragma hdrstop
DWORD
WINAPI
StartProtocol (
IN HANDLE NotificationEvent,
IN PSUPPORT_FUNCTIONS SupportFunctions,
IN LPVOID GlobalInfo,
IN ULONG StructureVersion,
IN ULONG StructureSize,
IN ULONG StructureCount
)
/*++
Routine Description
After the protocol has been registered, the IP Router Manager calls
this function to tell the protocol to start. Most of the startup code
is executed here.
Arguments
NotificationEvent Event to Set if the IP Router Manager needs to
be notified to take any action on our behalf
SupportFunctions Some functions exported by IP Router Manager
GlobalInfo Our global configuration which was setup by our
setup/admin DLL
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE3(ENTER, "Entering StartProtocol 0x%08x 0x%08x 0x%08x",
NotificationEvent, SupportFunctions, GlobalInfo);
do // breakout loop
{
// validate parameters
if (!NotificationEvent or
!SupportFunctions or
!GlobalInfo)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = CM_StartProtocol(NotificationEvent,
SupportFunctions,
GlobalInfo);
} while(FALSE);
TRACE1(LEAVE, "Leaving StartProtocol: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
StartComplete (
VOID
)
{
TRACE0(ENTER, "Entering StartComplete");
TRACE0(LEAVE, "Leaving StartComplete");
return NO_ERROR;
}
DWORD
WINAPI
StopProtocol (
VOID
)
/*++
Routine Description
This function is called by the IP Router Manager to tell the protocol
to stop. We set the protocol state to IPSAMPLE_STATUS_STOPPING to
prevent us from servicing any more requests and wait for all pending
threads to finish. Meanwhile we return PENDING to the IP Router
Manager.
Arguments
None
Return Value
ERROR_PROTOCOL_STOP_PENDING Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE0(ENTER, "Entering StopProtocol");
dwErr = CM_StopProtocol();
TRACE1(LEAVE, "Leaving StopProtocol: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
GetGlobalInfo (
IN PVOID GlobalInfo,
IN OUT PULONG BufferSize,
OUT PULONG StructureVersion,
OUT PULONG StructureSize,
OUT PULONG StructureCount
)
/*++
Routine Description
The function is called by the IP Router Manager, usually because of a
query by the admin utility. We see if we have space enough to return
our global config. If we do, we return it, otherwise we return the size
needed.
Arguments
GlobalInfo Pointer to allocated buffer to store our config
BufferSize Size of config.
Return Value
NO_ERROR Success
ERROR_INSUFFICIENT_BUFFER If the size of the buffer is too small
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE2(ENTER, "Entering GetGlobalInfo: 0x%08x 0x%08x",
GlobalInfo, BufferSize);
do // breakout loop
{
// validate parameters
if (!BufferSize)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = CM_GetGlobalInfo(GlobalInfo,
BufferSize,
StructureVersion,
StructureSize,
StructureCount);
} while(FALSE);
TRACE1(LEAVE, "Leaving GetGlobalInfo: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
SetGlobalInfo (
IN PVOID GlobalInfo,
IN ULONG StructureVersion,
IN ULONG StructureSize,
IN ULONG StructureCount
)
/*++
Routine Description
Called by the IP Router Manager usually in response to an admin utility
changing the global config. We verify the info and set it.
Arguments
GlobalInfo Our globals configuration
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE1(ENTER, "Entering SetGlobalInfo: 0x%08x", GlobalInfo);
do // breakout loop
{
// validate parameters
if (!GlobalInfo)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = CM_SetGlobalInfo(GlobalInfo);
} while(FALSE);
TRACE1(LEAVE, "Leaving SetGlobalInfo: %u", dwErr);
return NO_ERROR;
}
DWORD
WINAPI
AddInterface (
IN LPWSTR InterfaceName,
IN ULONG InterfaceIndex,
IN NET_INTERFACE_TYPE InterfaceType,
IN DWORD MediaType,
IN WORD AccessType,
IN WORD ConnectionType,
IN PVOID InterfaceInfo,
IN ULONG StructureVersion,
IN ULONG StructureSize,
IN ULONG StructureCount
)
/*++
Routine Description
Called by the ip router manager to add an interface when it finds our
information block within the interface's configuration. We verify the
information and create an entry for the interface in our interface
table. Then we see all the configured addresses for the interface and
create a binding structure for each address The interface comes up as
UNBOUND-DISABLED (INACTIVE).
Arguments
InterfaceName The name of the interface, used for logging.
InterfaceIndex The positive integer used to refer to this interface.
AccessType Access type of the interface
InterfaceInfo Our config for this interface
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE4(ENTER, "Entering AddInterface: %S %u %u 0x%08x",
InterfaceName, InterfaceIndex, AccessType, InterfaceInfo);
// interface properties unused for now
UNREFERENCED_PARAMETER(InterfaceType);
UNREFERENCED_PARAMETER(MediaType);
UNREFERENCED_PARAMETER(ConnectionType);
if (AccessType != IF_ACCESS_POINTTOPOINT)
AccessType = IF_ACCESS_BROADCAST;
do // breakout loop
{
// validate parameters
if ((wcslen(InterfaceName) is 0) or
!((AccessType is IF_ACCESS_BROADCAST) or
(AccessType is IF_ACCESS_POINTTOPOINT)) or
!InterfaceInfo)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = NM_AddInterface(InterfaceName,
InterfaceIndex,
AccessType,
InterfaceInfo);
} while(FALSE);
TRACE1(LEAVE, "Leaving AddInterface: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
DeleteInterface (
IN ULONG InterfaceIndex
)
/*++
Routine Description
Called by the ip router manager to delete an interface and free its
resources. If the interface is ACTIVE we shut it down.
Arguments
InterfaceIndex The index of the interface to be deleted
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE1(ENTER, "Entering DeleteInterface: %u", InterfaceIndex);
dwErr = NM_DeleteInterface(InterfaceIndex);
TRACE1(LEAVE, "Leaving DeleteInterface: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
InterfaceStatus (
IN ULONG InterfaceIndex,
IN BOOL InterfaceActive,
IN DWORD StatusType,
IN PVOID StatusInfo
)
/*++
Routine Description
Called by ip router manager to bind/unbind/activate/deactivate interfaces.
BIND (
(StatusType is RIS_INTERFACE_ADDRESS_CHANGE) and
(((PIP_ADAPTER_BINDING_INFO) StatusInfo)->AddressCount > 0)
)
Called by the ip router manager once it learns the address(es) on an
interface. This may happen as soon as the router starts (after the
interface is added, of course) when the interface has a static address
or may happen when an interface acquires a DHCP address or may happen
when IPCP acquires the address for a dial up link. The binding may
consist of one or more addresses.
UNBIND (
(StatusType is RIS_INTERFACE_ADDRESS_CHANGE) and
(((PIP_ADAPTER_BINDING_INFO) StatusInfo)->AddressCount is 0)
)
Called when the interface loses its ip Address(es). This may happen
when the interface is shutting down. It may be because an admin
disabled IP on the interface (as opposed to just disabling the protocol
on the interface). It can happen when the admin releases a DHCP
acquired interface or when a dial up link disconnects.
ENABLED (RIS_INTERFACE_ENABLED)
Called to enable the interface after it has been added or when the
interface is being reenabled after being disabled by the admin. The
bindings on an interface are kept across Enable-Disable.
DISABLED (RIS_INTERFACE_DISABLED)
Called to disable an interface. This is usually in response to an
admin setting the AdminStatus in IP to DOWN. This is different from an
admin trying to disable an interface by setting a flag in our interface
config because that is opaque to IP. That is a routing protocol
specific disable and is conveyed to us via SetInterfaceConfig() calls.
THIS IS AN IMPORTANT DISTINCTION. A ROUTING PROTOCOL NEEDS TO MANTAIN
TWO STATES - AN NT STATE AND A PROTOCOL SPECIFIC STATE.
INTERFACE ACTIVE
This flag is used to activate the protocol over the interface
independent of whether the interface has been bound or enabled.
An unnumbered interface will not have a binding even when activated.
Arguments
InterfaceIndex The index of the interface in question
InterfaceActive Whether the interface can send and receive data
StatusType RIS_INTERFACE_[ADDRESS_CHANGED|ENABLED|DISABLED]
SattusInfo Pointer to IP_ADAPTER_BINDING_INFO containing info
about the addresses on the interface
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE4(ENTER, "Entering InterfaceStatus: %u %u %u 0x%08x",
InterfaceIndex, InterfaceActive, StatusType, StatusInfo);
do // breakout loop
{
dwErr = NM_InterfaceStatus(InterfaceIndex,
InterfaceActive,
StatusType,
StatusInfo);
} while(FALSE);
TRACE1(LEAVE, "Leaving InterfaceStatus: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
GetInterfaceConfigInfo (
IN ULONG InterfaceIndex,
IN PVOID InterfaceInfo,
IN OUT PULONG BufferSize,
OUT PULONG StructureVersion,
OUT PULONG StructureSize,
OUT PULONG StructureCount
)
/*++
Routine Description
Called by the IP Router Manager to retrieve an interface's
configuration. Usually this is because an admin utility is displaying
this information. The Router Manager calls us with a NULL config and
ZERO size. We return the required size to it. It then allocates the
needed memory and calls us a second time with a valid buffer. We
validate parameters each time and copy out our config if we can.
Arguments
InterfaceIndex Index of the interface being queried
InterfaceInfo Pointer to buffer to store the config
BufferSize Size of the buffer
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE3(ENTER, "Entering GetInterfaceConfigInfo: %u 0x%08x 0x%08x",
InterfaceIndex, InterfaceInfo, BufferSize);
do // breakout loop
{
// validate parameters
if(BufferSize is NULL)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = NM_GetInterfaceInfo(InterfaceIndex,
InterfaceInfo,
BufferSize,
StructureVersion,
StructureSize,
StructureCount);
} while(FALSE);
TRACE1(LEAVE, "Leaving GetInterfaceConfigInfo: %u",
dwErr);
return dwErr;
}
DWORD
WINAPI
SetInterfaceConfigInfo (
IN ULONG InterfaceIndex,
IN PVOID InterfaceInfo,
IN ULONG StructureVersion,
IN ULONG StructureSize,
IN ULONG StructureCount
)
/*++
Routine Description
Called by the IP Router Manager to set an interface's configuration.
Usually this is because an admin utility modified this information.
After validating parameters we update our config if we can.
Arguments
InterfaceIndex Index of the interface being updated
InterfaceInfo Buffer with our updated configuration
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE2(ENTER, "Entering SetInterfaceConfigInfo: %u 0x%08x",
InterfaceIndex, InterfaceInfo);
do // breakout loop
{
// validate parameters
if(InterfaceInfo is NULL)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = NM_SetInterfaceInfo(InterfaceIndex, InterfaceInfo);
} while(FALSE);
TRACE1(LEAVE, "Leaving SetInterfaceConfigInfo: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
GetEventMessage (
OUT ROUTING_PROTOCOL_EVENTS *Event,
OUT MESSAGE *Result
)
/*++
Routine Description
This is called by the IP Router Manager if we indicate that we have a
message in our queue to be delivered to it (by setting the
g_ce.hMgrNotificationEvent)
Arguments
Event Routing Protocol Event Type
Result Message associated with the event
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE2(ENTER, "Entering GetEventMessage: 0x%08x 0x%08x",
Event, Result);
do // breakout loop
{
// validate parameters
if (!Event or !Result)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = CM_GetEventMessage(Event, Result);
} while(FALSE);
TRACE1(LEAVE, "Leaving GetEventMessage: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
DoUpdateRoutes (
IN ULONG InterfaceIndex
)
/*++
Routine Description
This function is called by the IP Router Manger to ask us to update
routes over a Demand Dial link. The link has already been brought up
so should be in ENABLED-BOUND state. After we are done we need to set
the g_ce.hMgrNotificationEvent to inform the Router Manager that we
have a message in our queue to be delivered to it. The Router Manager
will call our GetEventMessage() function in which we will inform it
that we are done with update routes (and the routes have been stored in
RTMv2). The Router Manager will "freeze" these routes by converting
them to AUTOSTATIC.
Arguments
InterfaceIndex Interface index on which to do the update
Return Value
NO_ERROR Success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE1(ENTER, "Entering DoUpdateRoutes: %u", InterfaceIndex);
dwErr = NM_DoUpdateRoutes(InterfaceIndex);
TRACE1(LEAVE, "Leaving DoUpdateRoutes: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibCreate (
IN ULONG InputDataSize,
IN PVOID InputData
)
/*++
Routine Description
This function does nothing, since IPSAMPLE does not support creation of
interface objects via SNMP. However, this could be implemented as a
sequence of calls to NM_AddInterface(), IE_BindInterface() and
IE_EnableInterface. The input data would then have to contain the
interface's index, configuration, and binding.
Arguments
InputData Relevant input, some struct defined in ipsamplerm.h
InputDataSize Size of the input
Return Value
ERROR_CAN_NOT_COMPLETE for now
--*/
{
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
TRACE2(ENTER, "Entering MibCreate: %u 0x%08x",
InputDataSize, InputData);
TRACE1(LEAVE, "Leaving MibCreate: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibDelete (
IN ULONG InputDataSize,
IN PVOID InputData
)
/*++
Routine Description
This function does nothing, since IPSAMPLE does not support deletion of
interface objects via SNMP. However, this could be implemented as a
call to NM_DeleteInterface(). The input data would then have to
contain the interface's index.
Arguments
InputData Relevant input, some struct defined in ipsamplerm.h
InputDataSize Size of the input
Return Value
ERROR_CAN_NOT_COMPLETE for now
--*/
{
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
TRACE2(ENTER, "Entering MibDelete: %u 0x%08x",
InputDataSize, InputData);
TRACE1(LEAVE, "Leaving MibDelete: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibSet (
IN ULONG InputDataSize,
IN PVOID InputData
)
/*++
Routine Description
This function sets IPSAMPLE's global or interface configuration.
Arguments
InputData Relevant input, struct IPSAMPLE_MIB_SET_INPUT_DATA
InputDataSize Size of the input
Return Value
NO_ERROR success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE2(ENTER, "Entering MibSet: %u 0x%08x",
InputDataSize, InputData);
do // breakout loop
{
// validate parameters
if ((!InputData) or
(InputDataSize < sizeof(IPSAMPLE_MIB_SET_INPUT_DATA)))
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = MM_MibSet((PIPSAMPLE_MIB_SET_INPUT_DATA) InputData);
} while(FALSE);
TRACE1(LEAVE, "Leaving MibSet: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibGet (
IN ULONG InputDataSize,
IN PVOID InputData,
IN OUT PULONG OutputDataSize,
OUT PVOID OutputData
)
/*++
Routine Description
This function retrieves one of...
. global configuration
. interface configuration
. global stats
. interface stats
. interface binding
Called by an admin (SNMP) utility. It actually passes through the IP
Router Manager, but all that does is demux the call to the desired
routing protocol.
Arguments
InputData Relevant input, struct IPSAMPLE_MIB_GET_INPUT_DATA
InputDataSize Size of the input
OutputData Buffer for struct IPSAMPLE_MIB_GET_OUTPUT_DATA
OutputDataSize IN size of output buffer received
OUT size of output buffer required
Return Value
NO_ERROR success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE4(ENTER, "Entering MibGet: %u 0x%08x 0x%08x 0x%08x",
InputDataSize, InputData, OutputDataSize, OutputData);
do // breakout loop
{
// validate parameters
if ((!InputData) or
(InputDataSize < sizeof(IPSAMPLE_MIB_GET_INPUT_DATA)) or
(!OutputDataSize))
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = MM_MibGet((PIPSAMPLE_MIB_GET_INPUT_DATA) InputData,
(PIPSAMPLE_MIB_GET_OUTPUT_DATA) OutputData,
OutputDataSize,
GET_EXACT);
} while(FALSE);
TRACE1(LEAVE, "Leaving MibGet: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibGetFirst (
IN ULONG InputDataSize,
IN PVOID InputData,
IN OUT PULONG OutputDataSize,
OUT PVOID OutputData
)
/*++
Routine Description
This function retrieves one of...
. global configuration
. interface configuration
. global stats
. interface stats
. interface binding
It differs from MibGet() in that it always returns the FIRST entry in
whichever table is being queried. There is only one entry in the
global configuration and global stats tables, but the interface
configuration, interface stats, and interface binding tables are sorted
by IP address; this function returns the first entry from these.
Arguments
InputData Relevant input, struct IPSAMPLE_MIB_GET_INPUT_DATA
InputDataSize Size of the input
OutputData Buffer for struct IPSAMPLE_MIB_GET_OUTPUT_DATA
OutputDataSize IN size of output buffer received
OUT size of output buffer required
Return Value
NO_ERROR success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE4(ENTER, "Entering MibGetFirst: %u 0x%08x 0x%08x 0x%08x",
InputDataSize, InputData, OutputDataSize, OutputData);
do // breakout loop
{
// validate parameters
if ((!InputData) or
(InputDataSize < sizeof(IPSAMPLE_MIB_GET_INPUT_DATA)) or
(!OutputDataSize))
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = MM_MibGet((PIPSAMPLE_MIB_GET_INPUT_DATA) InputData,
(PIPSAMPLE_MIB_GET_OUTPUT_DATA) OutputData,
OutputDataSize,
GET_FIRST);
} while(FALSE);
TRACE1(LEAVE, "Leaving MibGetFirst: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibGetNext (
IN ULONG InputDataSize,
IN PVOID InputData,
IN OUT PULONG OutputDataSize,
OUT PVOID OutputData
)
/*++
Routine Description
This function retrieves one of...
. global configuration
. interface configuration
. global stats
. interface stats
. interface binding
It differs from both MibGet() and MibGetFirst() in that it returns the
entry AFTER the one specified in the indicated table. Thus, in the
interface configuration, interface stats, and interface binding tables,
this function supplies the entry after the one with the input address.
If there are no more entries in the table being queried we return
ERROR_NO_MORE_ITEMS. Unlike SNMP we don't walk to the next table.
This does not take away any functionality since the NT SNMP agent
will try the next variable (having ID one greater than the ID passed
in) automatically on getting this error.
Arguments
InputData Relevant input, struct IPSAMPLE_MIB_GET_INPUT_DATA
InputDataSize Size of the input
OutputData Buffer for struct IPSAMPLE_MIB_GET_OUTPUT_DATA
OutputDataSize IN size of output buffer received
OUT size of output buffer required
Return Value
NO_ERROR success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE4(ENTER, "Entering MibGetFirst: %u 0x%08x 0x%08x 0x%08x",
InputDataSize, InputData, OutputDataSize, OutputData);
do // breakout loop
{
// validate parameters
if ((!InputData) or
(InputDataSize < sizeof(IPSAMPLE_MIB_GET_INPUT_DATA)) or
(!OutputDataSize))
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = MM_MibGet((PIPSAMPLE_MIB_GET_INPUT_DATA) InputData,
(PIPSAMPLE_MIB_GET_OUTPUT_DATA) OutputData,
OutputDataSize,
GET_NEXT);
} while(FALSE);
TRACE1(LEAVE, "Leaving MibGetNext: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibSetTrapInfo (
IN HANDLE Event,
IN ULONG InputDataSize,
IN PVOID InputData,
OUT PULONG OutputDataSize,
OUT PVOID OutputData
)
/*++
Routine Description
This function does nothing at the moment...
Return Value
ERROR_CAN_NOT_COMPLETE for now
--*/
{
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
TRACE0(ENTER, "Entering MibSetTrapInfo");
TRACE1(LEAVE, "Leaving MibSetTrapInfo: %u", dwErr);
return dwErr;
}
DWORD
WINAPI
MibGetTrapInfo (
IN ULONG InputDataSize,
IN PVOID InputData,
OUT PULONG OutputDataSize,
OUT PVOID OutputData
)
/*++
Routine Description
This function does nothing at the moment...
Return Value
ERROR_CAN_NOT_COMPLETE for now
--*/
{
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
TRACE0(ENTER, "Entering MibGetTrapInfo");
TRACE1(LEAVE, "Leaving MibGetTrapInfo: %u", dwErr);
return dwErr;
}
//----------------------------------------------------------------------------
// Function: RegisterProtocol
//
// Returns protocol ID and functionality for IPRIP
//----------------------------------------------------------------------------
DWORD
APIENTRY
RegisterProtocol(
IN OUT PMPR_ROUTING_CHARACTERISTICS pRoutingChar,
IN OUT PMPR_SERVICE_CHARACTERISTICS pServiceChar
)
/*++
Routine Description
This is the first function called by the IP Router Manager. The Router
Manager tells the routing protocol its version and capabilities. It
also tells our DLL, the ID of the protocol it expects us to register.
This allows one DLL to support multiple routing protocols. We return
the functionality we support and a pointer to our functions.
Arguments
pRoutingChar The routing characteristics
pServiceChar The service characteristics (IPX 'thingy')
Return Value
NO_ERROR success
ERROR_NOT_SUPPORTED o/w
--*/
{
DWORD dwErr = NO_ERROR;
TRACE0(ENTER, "Entering RegisterProtocol");
do // breakout loop
{
if(pRoutingChar->dwProtocolId != MS_IP_SAMPLE)
{
dwErr = ERROR_NOT_SUPPORTED;
break;
}
if ((pRoutingChar->fSupportedFunctionality
& (RF_ROUTING|RF_DEMAND_UPDATE_ROUTES)) !=
(RF_ROUTING|RF_DEMAND_UPDATE_ROUTES))
{
dwErr = ERROR_NOT_SUPPORTED;
break;
}
pRoutingChar->fSupportedFunctionality =
(RF_ROUTING | RF_DEMAND_UPDATE_ROUTES);
// Since we are not a service advertiser (and IPX thing)
pServiceChar->fSupportedFunctionality = 0;
pRoutingChar->pfnStartProtocol = StartProtocol;
pRoutingChar->pfnStartComplete = StartComplete;
pRoutingChar->pfnStopProtocol = StopProtocol;
pRoutingChar->pfnGetGlobalInfo = GetGlobalInfo;
pRoutingChar->pfnSetGlobalInfo = SetGlobalInfo;
pRoutingChar->pfnQueryPower = NULL;
pRoutingChar->pfnSetPower = NULL;
pRoutingChar->pfnAddInterface = AddInterface;
pRoutingChar->pfnDeleteInterface = DeleteInterface;
pRoutingChar->pfnInterfaceStatus = InterfaceStatus;
pRoutingChar->pfnGetInterfaceInfo = GetInterfaceConfigInfo;
pRoutingChar->pfnSetInterfaceInfo = SetInterfaceConfigInfo;
pRoutingChar->pfnGetEventMessage = GetEventMessage;
pRoutingChar->pfnUpdateRoutes = DoUpdateRoutes;
pRoutingChar->pfnConnectClient = NULL;
pRoutingChar->pfnDisconnectClient = NULL;
pRoutingChar->pfnGetNeighbors = NULL;
pRoutingChar->pfnGetMfeStatus = NULL;
pRoutingChar->pfnMibCreateEntry = MibCreate;
pRoutingChar->pfnMibDeleteEntry = MibDelete;
pRoutingChar->pfnMibGetEntry = MibGet;
pRoutingChar->pfnMibSetEntry = MibSet;
pRoutingChar->pfnMibGetFirstEntry = MibGetFirst;
pRoutingChar->pfnMibGetNextEntry = MibGetNext;
pRoutingChar->pfnMibSetTrapInfo = MibSetTrapInfo;
pRoutingChar->pfnMibGetTrapInfo = MibGetTrapInfo;
} while (FALSE);
TRACE1(LEAVE, "Leaving RegisterProtocol: %u", dwErr);
return dwErr;
}