|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ifmgr.c
Abstract:
RIP Interface Manager
Author:
Stefan Solomon 07/06/1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define IsInterfaceBound(icbp)\
((icbp)->AdapterBindingInfo.AdapterIndex != INVALID_ADAPTER_INDEX)
#define IsInterfaceEnabled(icbp)\
(((icbp)->IfConfigInfo.AdminState == ADMIN_STATE_ENABLED) &&\ ((icbp)->IpxIfAdminState == ADMIN_STATE_ENABLED))
VOID StartInterface(PICB icbp);
VOID StopInterface(PICB icbp);
PICB CreateInterfaceCB(LPWSTR InterfaceName, ULONG InterfaceIndex, PRIP_IF_INFO IfConfigInfop, NET_INTERFACE_TYPE NetInterfaceType, PRIP_IF_STATS IfStatsp OPTIONAL);
VOID DiscardInterfaceCB(PICB icbp);
DWORD CreateNewFiltersBlock(PRIP_IF_FILTERS_I *fcbpp, PRIP_IF_FILTERS RipIfFiltersp);
DWORD CreateOldFiltersBlockCopy(PRIP_IF_FILTERS_I *fcbpp, PRIP_IF_FILTERS_I RipIfFiltersp);
DWORD WINAPI AddInterface( IN LPWSTR InterfaceName, IN ULONG InterfaceIndex, IN NET_INTERFACE_TYPE NetInterfaceType, IN PVOID InterfaceInfo) { PICB icbp; PRIP_IF_FILTERS_I fcbp;
Trace(IFMGR_TRACE, "AddInterface: Entered for if # %d\n", InterfaceIndex);
ACQUIRE_DATABASE_LOCK;
if(RipOperState != OPER_STATE_UP) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
if(GetInterfaceByIndex(InterfaceIndex) != NULL) {
RELEASE_DATABASE_LOCK; return ERROR_INVALID_PARAMETER; }
// create the filters block for this interface
if(CreateNewFiltersBlock(&fcbp, &((PRIP_IF_CONFIG)InterfaceInfo)->RipIfFilters) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
if((icbp = CreateInterfaceCB( InterfaceName, InterfaceIndex, (PRIP_IF_INFO)InterfaceInfo, NetInterfaceType, NULL)) == NULL) {
if(fcbp) {
GlobalFree(fcbp); }
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
// bind the filters block with the interface control block
icbp->RipIfFiltersIp = fcbp;
RELEASE_DATABASE_LOCK;
return NO_ERROR; }
DWORD WINAPI DeleteInterface( IN ULONG InterfaceIndex) { PICB icbp; DWORD rc;
Trace(IFMGR_TRACE,"DeleteInterface: Entered for if # %d\n", InterfaceIndex);
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
ACQUIRE_IF_LOCK(icbp);
if(!DeleteRipInterface(icbp)) {
// interface CB still exists but has been discarded
RELEASE_IF_LOCK(icbp); }
RELEASE_DATABASE_LOCK;
return NO_ERROR; }
DWORD WINAPI GetInterfaceConfigInfo( IN ULONG InterfaceIndex, IN PVOID InterfaceInfo, IN OUT PULONG InterfaceInfoSize) { PICB icbp; DWORD rc, i; ULONG ifconfigsize; PRIP_IF_FILTERS_I fcbp; PRIP_IF_FILTERS RipIfFiltersp; PRIP_ROUTE_FILTER_INFO rfp; PRIP_ROUTE_FILTER_INFO_I rfip;
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
ACQUIRE_IF_LOCK(icbp);
ifconfigsize = sizeof(RIP_IF_CONFIG);
if((fcbp = icbp->RipIfFiltersIp) != NULL) {
ifconfigsize += (fcbp->SupplyFilterCount + fcbp->ListenFilterCount - 1) * sizeof(RIP_ROUTE_FILTER_INFO); }
if((InterfaceInfo == NULL) || (*InterfaceInfoSize < ifconfigsize)) {
*InterfaceInfoSize = ifconfigsize;
RELEASE_IF_LOCK(icbp); RELEASE_DATABASE_LOCK; return ERROR_INSUFFICIENT_BUFFER; }
((PRIP_IF_CONFIG)InterfaceInfo)->RipIfInfo = icbp->IfConfigInfo; RipIfFiltersp = &(((PRIP_IF_CONFIG)InterfaceInfo)->RipIfFilters);
if(fcbp == NULL) {
// no filters
memset(RipIfFiltersp, 0, sizeof(RIP_IF_FILTERS)); } else { // convert all filters from internal to external format
if(fcbp->SupplyFilterAction) {
RipIfFiltersp->SupplyFilterAction = IPX_ROUTE_FILTER_PERMIT; } else { RipIfFiltersp->SupplyFilterAction = IPX_ROUTE_FILTER_DENY; }
RipIfFiltersp->SupplyFilterCount = fcbp->SupplyFilterCount;
if(fcbp->ListenFilterAction) {
RipIfFiltersp->ListenFilterAction = IPX_ROUTE_FILTER_PERMIT; } else { RipIfFiltersp->ListenFilterAction = IPX_ROUTE_FILTER_DENY; }
RipIfFiltersp->ListenFilterCount = fcbp->ListenFilterCount;
rfp = RipIfFiltersp->RouteFilter; rfip = fcbp->RouteFilterI;
for(i=0; i<fcbp->SupplyFilterCount + fcbp->ListenFilterCount; i++, rfp++, rfip++) { PUTULONG2LONG(rfp->Network, rfip->Network); PUTULONG2LONG(rfp->Mask, rfip->Mask); } }
*InterfaceInfoSize = ifconfigsize;
RELEASE_IF_LOCK(icbp);
RELEASE_DATABASE_LOCK;
return NO_ERROR; }
DWORD WINAPI SetInterfaceConfigInfo( IN ULONG InterfaceIndex, IN PVOID InterfaceInfo) { DWORD rc; PICB icbp; PRIP_IF_FILTERS_I fcbp;
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
// create the filters block for this interface
if(CreateNewFiltersBlock(&fcbp, &((PRIP_IF_CONFIG)InterfaceInfo)->RipIfFilters) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
rc = SetRipInterface(InterfaceIndex, (PRIP_IF_INFO)InterfaceInfo, fcbp, 0);
RELEASE_DATABASE_LOCK;
return rc; }
DWORD WINAPI BindInterface( IN ULONG InterfaceIndex, IN PVOID BindingInfo) { PICB icbp, newicbp; DWORD rc; PWORK_ITEM wip; PRIP_IF_FILTERS_I fcbp = NULL;
Trace(IFMGR_TRACE, "BindInterface: Entered for if # %d\n", InterfaceIndex);
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
ACQUIRE_IF_LOCK(icbp);
if(IsInterfaceBound(icbp)) {
SS_ASSERT(FALSE);
RELEASE_IF_LOCK(icbp); RELEASE_DATABASE_LOCK;
return ERROR_INVALID_PARAMETER; }
SS_ASSERT(icbp->IfStats.RipIfOperState != OPER_STATE_UP);
if(icbp->RefCount) {
// The interface is UNBOUND but is still referenced.
// make a copy of the old if filters if any
if(icbp->RipIfFiltersIp != NULL) {
if(CreateOldFiltersBlockCopy(&fcbp, icbp->RipIfFiltersIp) != NO_ERROR) {
// cannot allocate memory for the copy of the filters block
RELEASE_IF_LOCK(icbp); RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; } }
// remove the old if Cb from the if list and hash
RemoveIfFromDb(icbp);
if((newicbp = CreateInterfaceCB( icbp->InterfaceName, InterfaceIndex, &icbp->IfConfigInfo, icbp->InterfaceType, &icbp->IfStats)) == NULL) {
// restore the old if and get out
AddIfToDb(icbp);
if(fcbp != NULL) {
GlobalFree(fcbp); }
RELEASE_IF_LOCK(icbp); RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
// bind the old filters copy to the new interface
if(icbp->RipIfFiltersIp != NULL) {
newicbp->RipIfFiltersIp = fcbp; }
newicbp->IfConfigInfo = icbp->IfConfigInfo; newicbp->IpxIfAdminState = icbp->IpxIfAdminState;
DiscardInterfaceCB(icbp);
RELEASE_IF_LOCK(icbp);
ACQUIRE_IF_LOCK(newicbp);
icbp = newicbp; }
// bind the if to adapter and add it to adapter hash table
BindIf(icbp, (PIPX_ADAPTER_BINDING_INFO)BindingInfo);
// start work on this interface if the admin state is enabled
if(IsInterfaceEnabled(icbp) && (InterfaceIndex!=0)) {
StartInterface(icbp); }
RELEASE_IF_LOCK(icbp); RELEASE_DATABASE_LOCK;
return NO_ERROR; }
DWORD WINAPI UnbindInterface( IN ULONG InterfaceIndex) { PICB icbp; DWORD rc;
Trace(IFMGR_TRACE, "UnbindInterface: Entered for if # %d\n", InterfaceIndex);
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
ACQUIRE_IF_LOCK(icbp);
if(!IsInterfaceBound(icbp)) {
// already unbound
RELEASE_IF_LOCK(icbp); RELEASE_DATABASE_LOCK; return ERROR_INVALID_PARAMETER; }
UnbindIf(icbp);
if(icbp->IfStats.RipIfOperState == OPER_STATE_UP) {
// remove RIP routes added by this interface and discard the send queue
StopInterface(icbp); }
RELEASE_IF_LOCK(icbp);
RELEASE_DATABASE_LOCK;
return NO_ERROR; }
DWORD WINAPI EnableInterface(IN ULONG InterfaceIndex) { DWORD rc; PICB icbp;
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
rc = SetRipInterface(InterfaceIndex, NULL, NULL, ADMIN_STATE_ENABLED);
RELEASE_DATABASE_LOCK;
return rc; }
DWORD WINAPI DisableInterface(IN ULONG InterfaceIndex) { DWORD rc; PICB icbp;
ACQUIRE_DATABASE_LOCK;
if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
RELEASE_DATABASE_LOCK; return rc; }
rc = SetRipInterface(InterfaceIndex, NULL, NULL, ADMIN_STATE_DISABLED);
RELEASE_DATABASE_LOCK;
return rc; }
/*++
Function: SetRipInterface
Descr: set the new interface parameters. If the interface was actively doing something, all operations are implicitly aborted on this interface.
Remark: Called with the database lock held
--*/
DWORD SetRipInterface(ULONG InterfaceIndex, PRIP_IF_INFO RipIfInfop, // if this parameter NULL -> Enable/Disable if
PRIP_IF_FILTERS_I RipIfFiltersIp, ULONG IpxIfAdminState) { PICB icbp, newicbp; IPX_ADAPTER_BINDING_INFO AdapterBindingInfo; PWORK_ITEM wip; PRIP_IF_FILTERS_I fcbp = NULL;
if((icbp = GetInterfaceByIndex(InterfaceIndex)) == NULL) {
return ERROR_INVALID_PARAMETER; }
ACQUIRE_IF_LOCK(icbp);
if(icbp->RefCount) {
// The interface is still referenced.
// if this is an enable/disable interface call, we need to make a copy of the old
// interface filter block
if((RipIfInfop == NULL) && (icbp->RipIfFiltersIp != NULL)) {
if(CreateOldFiltersBlockCopy(&fcbp, icbp->RipIfFiltersIp) != NO_ERROR) {
// cannot allocate memory for the copy of the filters block
RELEASE_IF_LOCK(icbp); return ERROR_CAN_NOT_COMPLETE; } }
// remove the old if CB from the if list and hash
RemoveIfFromDb(icbp);
// Create a new if CB and add it to the list
if((newicbp = CreateInterfaceCB( icbp->InterfaceName, InterfaceIndex, &icbp->IfConfigInfo, icbp->InterfaceType, &icbp->IfStats)) == NULL) {
// restore the old if and get out
AddIfToDb(icbp);
if(fcbp != NULL) {
GlobalFree(fcbp); }
RELEASE_IF_LOCK(icbp); return ERROR_CAN_NOT_COMPLETE; }
// bind the new interface cb with a copy of the old filter block if this is just an
// enable/disable
if((RipIfInfop == NULL) && (icbp->RipIfFiltersIp != NULL)) {
newicbp->RipIfFiltersIp = fcbp; }
if(IsInterfaceBound(icbp)) {
// copy the binding info and insert the new one in adapters hash table
// if bound.
AdapterBindingInfo = icbp->AdapterBindingInfo;
// remove the old if from the adapters hash and insert the new one
UnbindIf(icbp); BindIf(newicbp, &AdapterBindingInfo); }
// copy the old config info and the old binding info
newicbp->IfConfigInfo = icbp->IfConfigInfo; newicbp->IpxIfAdminState = icbp->IpxIfAdminState;
DiscardInterfaceCB(icbp);
ACQUIRE_IF_LOCK(newicbp);
RELEASE_IF_LOCK(icbp);
icbp = newicbp; } //
// *** Set the new config info OR Set the new Ipx If Admin State ***
//
// if this is a SetInterface call, modify the configuration
if(RipIfInfop != NULL) {
// config info has changed
icbp->IfConfigInfo = *RipIfInfop;
// dispose of the old filters block if any and bind to the new one
if((icbp->RipIfFiltersIp != NULL) && (icbp->RipIfFiltersIp!=RipIfFiltersIp)) {
GlobalFree(icbp->RipIfFiltersIp); }
icbp->RipIfFiltersIp = RipIfFiltersIp; } else { // Ipx interface admin state has changed
icbp->IpxIfAdminState = IpxIfAdminState; }
if (InterfaceIndex!=0) { if(IsInterfaceBound(icbp)) {
if(IsInterfaceEnabled(icbp)) {
StartInterface(icbp); } else { // interface has been disabled
if(icbp->IfStats.RipIfOperState == OPER_STATE_UP) {
// remove the routes and discard the changes bcast queue
StopInterface(icbp); } else icbp->IfStats.RipIfOperState = OPER_STATE_DOWN; } } else { if (IsInterfaceEnabled(icbp) && (icbp->InterfaceType!=PERMANENT)) icbp->IfStats.RipIfOperState = OPER_STATE_SLEEPING; else icbp->IfStats.RipIfOperState = OPER_STATE_DOWN; } }
RELEASE_IF_LOCK(icbp);
return NO_ERROR; }
/*++
Function: StartInterface
Descr: Start work on this interface
Remark: Called with interface lock held
--*/
VOID StartInterface(PICB icbp) { PWORK_ITEM bcwip, grwip;
Trace(IFMGR_TRACE, "StartInterface: Entered for if index %d\n", icbp->InterfaceIndex);
icbp->IfStats.RipIfOperState = OPER_STATE_UP; // check that this is not the internal interface and
// check the update type and make a periodic update work item if necessary
if(((icbp->IfConfigInfo.UpdateMode == IPX_STANDARD_UPDATE) && (icbp->IfConfigInfo.Supply == ADMIN_STATE_ENABLED)) || (icbp->InterfaceType == LOCAL_WORKSTATION_DIAL)) {
if((bcwip = AllocateWorkItem(PERIODIC_BCAST_PACKET_TYPE)) == NULL) {
goto ErrorExit; }
// init the periodic bcast work item
bcwip->icbp = icbp; bcwip->AdapterIndex = icbp->AdapterBindingInfo.AdapterIndex;
// mark the work item state as "start of bcast"
bcwip->WorkItemSpecific.WIS_EnumRoutes.RtmEnumerationHandle = NULL;
// start bcast on this interface
IfPeriodicBcast(bcwip);
// send a general request packet on this interface
SendRipGenRequest(icbp); }
if(((icbp->InterfaceType == REMOTE_WORKSTATION_DIAL) || (icbp->InterfaceType == LOCAL_WORKSTATION_DIAL)) && SendGenReqOnWkstaDialLinks) {
if((grwip = AllocateWorkItem(PERIODIC_GEN_REQUEST_TYPE)) == NULL) {
goto ErrorExit; }
grwip->icbp = icbp; grwip->AdapterIndex = icbp->AdapterBindingInfo.AdapterIndex;
IfPeriodicGenRequest(grwip); }
return;
ErrorExit:
icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
return; }
/*++
Function: StopInterface
Descr: Stop work on this interface: remove rip routes added by this interface set oper state to sleeping
Remark: Called with database AND interface locks held
--*/
VOID StopInterface(PICB icbp) { PLIST_ENTRY lep; PWORK_ITEM wip;
Trace(IFMGR_TRACE, "StopInterface: Entered for if index %d\n", icbp->InterfaceIndex);
DeleteAllRipRoutes(icbp->InterfaceIndex);
if (IsInterfaceEnabled (icbp)) icbp->IfStats.RipIfOperState = OPER_STATE_SLEEPING; else icbp->IfStats.RipIfOperState = OPER_STATE_DOWN; }
/*++
Function: CreateInterfaceCB
Descr: allocate interface CB init if lock init if index init if config info init if stats add if to db mark it unbound
--*/
PICB CreateInterfaceCB( LPWSTR InterfaceName, ULONG InterfaceIndex, PRIP_IF_INFO IfConfigInfop, NET_INTERFACE_TYPE InterfaceType, PRIP_IF_STATS IfStatsp OPTIONAL) { PICB icbp;
if((icbp = GlobalAlloc(GPTR, FIELD_OFFSET(ICB,InterfaceName[wcslen(InterfaceName)+1]))) == NULL) {
return NULL; }
// create the interface lock
try {
InitializeCriticalSection(&icbp->InterfaceLock); } except(EXCEPTION_EXECUTE_HANDLER) {
GlobalFree(icbp); return NULL; }
// initialize the ICB
wcscpy (icbp->InterfaceName, InterfaceName); icbp->InterfaceIndex = InterfaceIndex;
icbp->IfConfigInfo = *IfConfigInfop; icbp->InterfaceType = InterfaceType;
if(IfStatsp != NULL) {
icbp->IfStats = *IfStatsp; } else { icbp->IfStats.RipIfOperState = OPER_STATE_DOWN; icbp->IfStats.RipIfInputPackets = 0; icbp->IfStats.RipIfOutputPackets = 0; }
icbp->RefCount = 0;
// link the ICB in the ordered if list and the if hash table
AddIfToDb(icbp);
icbp->Discarded = FALSE;
// init the changes bcast queue
InitializeListHead(&icbp->ChangesBcastQueue);
// mark the interface as unbound to any adapter
icbp->AdapterBindingInfo.AdapterIndex = INVALID_ADAPTER_INDEX;
// set the ipx if admin state to disabled until we find out what it is
icbp->IpxIfAdminState = ADMIN_STATE_DISABLED;
// set the filters block ptr to null initially
icbp->RipIfFiltersIp = NULL;
return icbp; }
/*++
Function: DiscardInterfaceCB
Descr: insert the if in the discarded list mark it discarded set its oper state to down so the referencing work items will know to --*/
VOID DiscardInterfaceCB(PICB icbp) { icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
InsertTailList(&DiscardedIfList, &icbp->IfListLinkage);
icbp->Discarded = TRUE;
Trace(IFMGR_TRACE, "DiscardInterface: interface CB for if # %d moved on DISCARDED list\n", icbp->InterfaceIndex); }
/*++
Function: DeleteRipInterface
Descr: remove the if from the database unbinds and stops the if if active if not referenced frees the if CB and destroys the lock, else discards it
Returns: TRUE - interface CB has been freed and if lock deleted FALSE - interface CB has been discarded and if lock is valid
Remark: called with if lock held AND database lock held
--*/
BOOL DeleteRipInterface(PICB icbp) { // remove the interface from the database
RemoveIfFromDb(icbp);
// check if the interface is still bound to an adapter.
if(IsInterfaceBound(icbp)) {
UnbindIf(icbp); }
// set if state to sleeping and remove changes bcast queued at the if cb
if(icbp->IfStats.RipIfOperState == OPER_STATE_UP) {
StopInterface(icbp); }
// check if the interface is still referenced
if(icbp->RefCount == 0) {
Trace(IFMGR_TRACE, "DeleteRipInterface: free interface CB for if # %d\n", icbp->InterfaceIndex);
// no more references to this interface CB, free it
//
DestroyInterfaceCB(icbp);
return TRUE; } else { // the interface CB is still referenced. It will be freed by the
// worker when the RefCount becomes 0.
DiscardInterfaceCB(icbp);
return FALSE; } }
DWORD ValidStateAndIfIndex(ULONG InterfaceIndex, PICB *icbpp) { if(RipOperState != OPER_STATE_UP) {
return ERROR_CAN_NOT_COMPLETE; }
if((*icbpp = GetInterfaceByIndex(InterfaceIndex)) == NULL) {
return ERROR_INVALID_PARAMETER; }
return NO_ERROR; }
/*++
Function: CreateFiltersBlock
Descr: Allocates and initializes a filters block from the Add/Set Interface Config filter parameter
--*/
DWORD CreateNewFiltersBlock(PRIP_IF_FILTERS_I *fcbpp, PRIP_IF_FILTERS RipIfFiltersp) { ULONG FcbSize, i; PRIP_ROUTE_FILTER_INFO rfp; PRIP_ROUTE_FILTER_INFO_I rfip;
if((RipIfFiltersp->SupplyFilterCount == 0) && (RipIfFiltersp->ListenFilterCount == 0)) {
*fcbpp = NULL; return NO_ERROR; }
FcbSize = sizeof(RIP_IF_FILTERS_I) + (RipIfFiltersp->SupplyFilterCount + RipIfFiltersp->ListenFilterCount - 1) * sizeof(RIP_ROUTE_FILTER_INFO_I);
if((*fcbpp = GlobalAlloc(GPTR, FcbSize)) == NULL) {
return ERROR_CAN_NOT_COMPLETE; }
if(RipIfFiltersp->SupplyFilterAction == IPX_ROUTE_FILTER_PERMIT) {
(*fcbpp)->SupplyFilterAction = TRUE; } else { (*fcbpp)->SupplyFilterAction = FALSE; }
if(RipIfFiltersp->ListenFilterAction == IPX_ROUTE_FILTER_PERMIT) {
(*fcbpp)->ListenFilterAction = TRUE; } else { (*fcbpp)->ListenFilterAction = FALSE; }
(*fcbpp)->SupplyFilterCount = RipIfFiltersp->SupplyFilterCount; (*fcbpp)->ListenFilterCount = RipIfFiltersp->ListenFilterCount;
// convert route_filters into route_filters_i
rfp = RipIfFiltersp->RouteFilter; rfip = (*fcbpp)->RouteFilterI;
for(i=0; i<RipIfFiltersp->SupplyFilterCount + RipIfFiltersp->ListenFilterCount; i++, rfp++, rfip++) { GETLONG2ULONG(&rfip->Network, rfp->Network); GETLONG2ULONG(&rfip->Mask, rfp->Mask); }
return NO_ERROR; }
/*++
Function: CreateOldFiltersBlockCopy
Descr: Allocates and initializes a filters block from an existing filters block
--*/
DWORD CreateOldFiltersBlockCopy(PRIP_IF_FILTERS_I *fcbpp, PRIP_IF_FILTERS_I RipIfFiltersp) { ULONG FcbSize;
FcbSize = sizeof(RIP_IF_FILTERS_I) + (RipIfFiltersp->SupplyFilterCount + RipIfFiltersp->ListenFilterCount - 1) * sizeof(RIP_ROUTE_FILTER_INFO_I);
if((*fcbpp = GlobalAlloc(GPTR, FcbSize)) == NULL) {
return ERROR_CAN_NOT_COMPLETE; }
memcpy(*fcbpp, RipIfFiltersp, FcbSize);
return NO_ERROR; }
VOID DestroyInterfaceCB(PICB icbp) { DeleteCriticalSection(&icbp->InterfaceLock);
if(icbp->RipIfFiltersIp) {
GlobalFree(icbp->RipIfFiltersIp); }
GlobalFree(icbp); }
|