756 lines
16 KiB
C
756 lines
16 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1997 - 98, Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
rtminfo.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Contains routines for getting information
|
||
|
on various objects pointed to by handles.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Chaitanya Kodeboyina (chaitk) 22-Aug-1998
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pchrtm.h"
|
||
|
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmGetEntityInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN RTM_ENTITY_HANDLE EntityHandle,
|
||
|
OUT PRTM_ENTITY_INFO EntityInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Retrieves information pertaining to a registered entity.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
EntityHandle - RTM handle for entity whose info we want,
|
||
|
|
||
|
EntityInfo - Block in which the entity info is returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PADDRFAM_INFO AddrFamilyInfo;
|
||
|
PENTITY_INFO Entity;
|
||
|
|
||
|
DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
VALIDATE_ENTITY_HANDLE(EntityHandle, &Entity);
|
||
|
|
||
|
//
|
||
|
// Copy the entity information to output buffer
|
||
|
//
|
||
|
|
||
|
AddrFamilyInfo = Entity->OwningAddrFamily;
|
||
|
|
||
|
EntityInfo->RtmInstanceId = AddrFamilyInfo->Instance->RtmInstanceId;
|
||
|
|
||
|
EntityInfo->AddressFamily = AddrFamilyInfo->AddressFamily;
|
||
|
|
||
|
EntityInfo->EntityId = Entity->EntityId;
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmGetDestInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN RTM_DEST_HANDLE DestHandle,
|
||
|
IN ULONG ProtocolId,
|
||
|
IN RTM_VIEW_SET TargetViews,
|
||
|
OUT PRTM_DEST_INFO DestInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Retrieves information for a destination in the route table
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
DestHandle - RTM handle for dest whose info we want,
|
||
|
|
||
|
ProtocolId - Protocol whose best route info is retd,
|
||
|
|
||
|
TargetViews - Views in which best route info is retd,
|
||
|
|
||
|
DestInfo - Block in which the dest info is returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PDEST_INFO Dest;
|
||
|
|
||
|
VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
// VALIDATE_DEST_HANDLE(DestHandle, &Dest);
|
||
|
Dest = DEST_FROM_HANDLE(DestHandle);
|
||
|
if (!Dest)
|
||
|
{
|
||
|
return ERROR_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
ACQUIRE_DEST_READ_LOCK(Dest);
|
||
|
|
||
|
GetDestInfo(Entity,
|
||
|
Dest,
|
||
|
ProtocolId,
|
||
|
TargetViews,
|
||
|
DestInfo);
|
||
|
|
||
|
RELEASE_DEST_READ_LOCK(Dest);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
GetDestInfo (
|
||
|
IN PENTITY_INFO Entity,
|
||
|
IN PDEST_INFO Dest,
|
||
|
IN ULONG ProtocolId,
|
||
|
IN RTM_VIEW_SET TargetViews,
|
||
|
OUT PRTM_DEST_INFO DestInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Retrieves information for a destination in the route table
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Entity - RTM registration info for calling entity,
|
||
|
|
||
|
Dest - Pointer to the dest whose info we want,
|
||
|
|
||
|
ProtocolId - Protocol whose best route info is retd,
|
||
|
|
||
|
TargetViews - Views in which best route info is retd,
|
||
|
|
||
|
DestInfo - Block in which the dest info is returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Owner;
|
||
|
PROUTE_INFO Route;
|
||
|
RTM_VIEW_SET ViewsSeen;
|
||
|
RTM_VIEW_SET ViewSet;
|
||
|
RTM_VIEW_SET BelongsToViews;
|
||
|
PLIST_ENTRY p;
|
||
|
UINT i, j, k;
|
||
|
|
||
|
// Limit caller's interest to set of views supported
|
||
|
TargetViews &= Entity->OwningAddrFamily->ViewsSupported;
|
||
|
|
||
|
//
|
||
|
// Copy dest info to output and ref handles given out
|
||
|
//
|
||
|
|
||
|
DestInfo->DestHandle = MAKE_HANDLE_FROM_POINTER(Dest);
|
||
|
|
||
|
REFERENCE_DEST(Dest, HANDLE_REF);
|
||
|
|
||
|
CopyMemory(&DestInfo->DestAddress,
|
||
|
&Dest->DestAddress,
|
||
|
sizeof(RTM_NET_ADDRESS));
|
||
|
|
||
|
DestInfo->LastChanged = Dest->LastChanged;
|
||
|
|
||
|
DestInfo->BelongsToViews = Dest->BelongsToViews;
|
||
|
|
||
|
//
|
||
|
// Copy the holddown route out in all requested views
|
||
|
//
|
||
|
|
||
|
ViewSet = TargetViews;
|
||
|
|
||
|
for (i = j = 0; ViewSet && (i < RTM_VIEW_MASK_SIZE); i++)
|
||
|
{
|
||
|
if (ViewSet & 0x01)
|
||
|
{
|
||
|
k = Entity->OwningAddrFamily->ViewIndexFromId[i];
|
||
|
|
||
|
Route = Dest->ViewInfo[k].HoldRoute;
|
||
|
|
||
|
//
|
||
|
// Init view info and fill the holddown route
|
||
|
//
|
||
|
|
||
|
ZeroMemory(&DestInfo->ViewInfo[j], sizeof(DestInfo->ViewInfo[0]));
|
||
|
|
||
|
DestInfo->ViewInfo[j].ViewId = i;
|
||
|
|
||
|
if (Route)
|
||
|
{
|
||
|
DestInfo->ViewInfo[j].HoldRoute =
|
||
|
MAKE_HANDLE_FROM_POINTER(Route);
|
||
|
|
||
|
REFERENCE_ROUTE(Route, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
j++;
|
||
|
}
|
||
|
|
||
|
ViewSet >>= 1;
|
||
|
}
|
||
|
|
||
|
// Keep track of total number of view info slots filled in
|
||
|
DestInfo->NumberOfViews = j;
|
||
|
|
||
|
//
|
||
|
// Fill up information in all the views he is interested in
|
||
|
//
|
||
|
|
||
|
if (TargetViews & Dest->BelongsToViews)
|
||
|
{
|
||
|
// Resolve the protocol id if it is RTM_THIS_PROTOCOL
|
||
|
|
||
|
if (ProtocolId == RTM_THIS_PROTOCOL)
|
||
|
{
|
||
|
ProtocolId = Entity->EntityId.EntityProtocolId;
|
||
|
}
|
||
|
|
||
|
ViewsSeen = 0;
|
||
|
|
||
|
//
|
||
|
// Copy best route in each view & ref handles given out
|
||
|
//
|
||
|
|
||
|
for (p = Dest->RouteList.Flink; p != &Dest->RouteList; p = p->Flink)
|
||
|
{
|
||
|
Route = CONTAINING_RECORD(p, ROUTE_INFO, DestLE);
|
||
|
|
||
|
//
|
||
|
// Make sure that this agrees with our protocol id
|
||
|
//
|
||
|
|
||
|
Owner = ENTITY_FROM_HANDLE(Route->RouteInfo.RouteOwner);
|
||
|
|
||
|
if (ProtocolId != RTM_BEST_PROTOCOL)
|
||
|
{
|
||
|
if (Owner->EntityId.EntityProtocolId != ProtocolId)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Does this route belong to any interested views
|
||
|
//
|
||
|
|
||
|
if ((TargetViews & Route->RouteInfo.BelongsToViews) == 0)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update dest info in each view that route belongs to
|
||
|
//
|
||
|
|
||
|
BelongsToViews = Route->RouteInfo.BelongsToViews;
|
||
|
|
||
|
ViewSet = TargetViews;
|
||
|
|
||
|
for (i = j = 0; ViewSet && (i < RTM_VIEW_MASK_SIZE); i++)
|
||
|
{
|
||
|
if (ViewSet & 0x01)
|
||
|
{
|
||
|
if (BelongsToViews & 0x01)
|
||
|
{
|
||
|
//
|
||
|
// Increment number of routes in this view
|
||
|
//
|
||
|
|
||
|
DestInfo->ViewInfo[j].NumRoutes++;
|
||
|
|
||
|
//
|
||
|
// If you not already seen this view (in
|
||
|
// other words got the best route in it)
|
||
|
// update the DestInfo for this view now
|
||
|
//
|
||
|
|
||
|
if (!(ViewsSeen & VIEW_MASK(i)))
|
||
|
{
|
||
|
DestInfo->ViewInfo[j].Route =
|
||
|
MAKE_HANDLE_FROM_POINTER(Route);
|
||
|
|
||
|
REFERENCE_ROUTE(Route, HANDLE_REF);
|
||
|
|
||
|
|
||
|
DestInfo->ViewInfo[j].Owner =
|
||
|
MAKE_HANDLE_FROM_POINTER(Owner);
|
||
|
|
||
|
REFERENCE_ENTITY(Owner, HANDLE_REF);
|
||
|
|
||
|
|
||
|
DestInfo->ViewInfo[j].DestFlags =
|
||
|
Route->RouteInfo.Flags;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
j++;
|
||
|
}
|
||
|
|
||
|
ViewSet >>= 1;
|
||
|
|
||
|
BelongsToViews >>= 1;
|
||
|
}
|
||
|
|
||
|
ViewsSeen |= Route->RouteInfo.BelongsToViews;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmGetRouteInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN RTM_ROUTE_HANDLE RouteHandle,
|
||
|
OUT PRTM_ROUTE_INFO RouteInfo OPTIONAL,
|
||
|
OUT PRTM_NET_ADDRESS DestAddress OPTIONAL
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Retrieves information for a route in the route table
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
RouteHandle - RTM handle for route whose info we want,
|
||
|
|
||
|
RouteInfo - Block in which the route info is returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PROUTE_INFO Route;
|
||
|
PDEST_INFO Dest;
|
||
|
|
||
|
DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
#if 1
|
||
|
Route = ROUTE_FROM_HANDLE(RouteHandle);
|
||
|
|
||
|
if (!Route)
|
||
|
{
|
||
|
return ERROR_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
VALIDATE_ROUTE_HANDLE(RouteHandle, &Route);
|
||
|
#endif
|
||
|
|
||
|
Dest = DEST_FROM_HANDLE(Route->RouteInfo.DestHandle);
|
||
|
|
||
|
// Get a consitent picture of the route
|
||
|
|
||
|
ACQUIRE_DEST_READ_LOCK(Dest);
|
||
|
|
||
|
if (ARGUMENT_PRESENT(RouteInfo))
|
||
|
{
|
||
|
GetRouteInfo(Dest, Route, RouteInfo);
|
||
|
}
|
||
|
|
||
|
RELEASE_DEST_READ_LOCK(Dest);
|
||
|
|
||
|
// No lock reqd - dest addr is constant
|
||
|
|
||
|
if (ARGUMENT_PRESENT(DestAddress))
|
||
|
{
|
||
|
CopyMemory(DestAddress, &Dest->DestAddress, sizeof(RTM_NET_ADDRESS));
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
WINAPI
|
||
|
GetRouteInfo (
|
||
|
IN PDEST_INFO Dest,
|
||
|
IN PROUTE_INFO Route,
|
||
|
OUT PRTM_ROUTE_INFO RouteInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Retrieves information for a route in the route table
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Dest - Pointer to the destination of the route,
|
||
|
|
||
|
Route - Pointer to the route whose info we want,
|
||
|
|
||
|
RouteInfo - Block in which the route info is returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PNEXTHOP_INFO Neighbour;
|
||
|
PNEXTHOP_INFO NextHop;
|
||
|
UINT NumBytes;
|
||
|
UINT i;
|
||
|
|
||
|
//
|
||
|
// Copy the route information to output buffer
|
||
|
//
|
||
|
|
||
|
NumBytes = sizeof(RTM_ROUTE_INFO) +
|
||
|
sizeof(RTM_NEXTHOP_HANDLE) *
|
||
|
(Route->RouteInfo.NextHopsList.NumNextHops - 1);
|
||
|
|
||
|
CopyMemory(RouteInfo, &Route->RouteInfo, NumBytes);
|
||
|
|
||
|
//
|
||
|
// Reference handles that are given out in info
|
||
|
//
|
||
|
|
||
|
Entity = ENTITY_FROM_HANDLE(RouteInfo->RouteOwner);
|
||
|
REFERENCE_ENTITY(Entity, HANDLE_REF);
|
||
|
|
||
|
if (RouteInfo->Neighbour)
|
||
|
{
|
||
|
Neighbour = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour);
|
||
|
REFERENCE_NEXTHOP(Neighbour, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < RouteInfo->NextHopsList.NumNextHops; i++)
|
||
|
{
|
||
|
NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->NextHopsList.NextHops[i]);
|
||
|
REFERENCE_NEXTHOP(NextHop, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
REFERENCE_DEST(Dest, HANDLE_REF);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmGetNextHopInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN RTM_NEXTHOP_HANDLE NextHopHandle,
|
||
|
OUT PRTM_NEXTHOP_INFO NextHopInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Retrieves information for a next-hop in the route table
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
NextHopHandle - RTM handle for next-hop whose info we want,
|
||
|
|
||
|
NextHopInfo - Block in which the next-hop info is returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PNEXTHOP_INFO NextHop;
|
||
|
PDEST_INFO Dest;
|
||
|
|
||
|
DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
VALIDATE_NEXTHOP_HANDLE(NextHopHandle, &NextHop);
|
||
|
|
||
|
Entity = ENTITY_FROM_HANDLE(NextHop->NextHopInfo.NextHopOwner);
|
||
|
|
||
|
ACQUIRE_NHOP_TABLE_READ_LOCK(Entity);
|
||
|
|
||
|
//
|
||
|
// Copy the next-hop information to output buffer
|
||
|
//
|
||
|
|
||
|
CopyMemory(NextHopInfo, &NextHop->NextHopInfo, sizeof(RTM_NEXTHOP_INFO));
|
||
|
|
||
|
//
|
||
|
// Reference handles that are given out in info
|
||
|
//
|
||
|
|
||
|
if (NextHop->NextHopInfo.RemoteNextHop)
|
||
|
{
|
||
|
Dest = DEST_FROM_HANDLE(NextHop->NextHopInfo.RemoteNextHop);
|
||
|
REFERENCE_DEST(Dest, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
REFERENCE_ENTITY(Entity, HANDLE_REF);
|
||
|
|
||
|
RELEASE_NHOP_TABLE_READ_LOCK(Entity);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmReleaseEntityInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN PRTM_ENTITY_INFO EntityInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Releases all handles present in the input info structure
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
EntityInfo - All handles in this info are de-referenced.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(RtmRegHandle);
|
||
|
UNREFERENCED_PARAMETER(EntityInfo);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmReleaseDestInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN PRTM_DEST_INFO DestInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Releases all handles present in the input info structure
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
DestInfo - All handles in this info are de-referenced.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PENTITY_INFO Owner;
|
||
|
PDEST_INFO Dest;
|
||
|
PROUTE_INFO Route;
|
||
|
UINT i;
|
||
|
|
||
|
DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
for (i = 0; i < DestInfo->NumberOfViews; i++)
|
||
|
{
|
||
|
//
|
||
|
// If a best route, dereference it and its owner
|
||
|
//
|
||
|
|
||
|
if (DestInfo->ViewInfo[i].Route)
|
||
|
{
|
||
|
Route = ROUTE_FROM_HANDLE(DestInfo->ViewInfo[i].Route);
|
||
|
DEREFERENCE_ROUTE(Route, HANDLE_REF);
|
||
|
|
||
|
Owner = ENTITY_FROM_HANDLE(DestInfo->ViewInfo[i].Owner);
|
||
|
DEREFERENCE_ENTITY(Owner, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we have a holddown route, dereference it
|
||
|
//
|
||
|
|
||
|
if (DestInfo->ViewInfo[i].HoldRoute)
|
||
|
{
|
||
|
Route = ROUTE_FROM_HANDLE(DestInfo->ViewInfo[i].HoldRoute);
|
||
|
DEREFERENCE_ROUTE(Route, HANDLE_REF);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Dest = DEST_FROM_HANDLE(DestInfo->DestHandle);
|
||
|
DEREFERENCE_DEST(Dest, HANDLE_REF);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmReleaseRouteInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN PRTM_ROUTE_INFO RouteInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Releases all handles present in the input info structure
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
RouteInfo - All handles in this info are de-referenced.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PDEST_INFO Dest;
|
||
|
PNEXTHOP_INFO Neighbour;
|
||
|
PNEXTHOP_INFO NextHop;
|
||
|
UINT i;
|
||
|
|
||
|
DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
for (i = 0; i < RouteInfo->NextHopsList.NumNextHops; i++)
|
||
|
{
|
||
|
NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->NextHopsList.NextHops[i]);
|
||
|
DEREFERENCE_NEXTHOP(NextHop, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
if (RouteInfo->Neighbour)
|
||
|
{
|
||
|
Neighbour = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour);
|
||
|
DEREFERENCE_NEXTHOP(Neighbour, HANDLE_REF);
|
||
|
}
|
||
|
|
||
|
Entity = ENTITY_FROM_HANDLE(RouteInfo->RouteOwner);
|
||
|
DEREFERENCE_ENTITY(Entity, HANDLE_REF);
|
||
|
|
||
|
Dest = DEST_FROM_HANDLE(RouteInfo->DestHandle);
|
||
|
DEREFERENCE_DEST(Dest, HANDLE_REF);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
RtmReleaseNextHopInfo (
|
||
|
IN RTM_ENTITY_HANDLE RtmRegHandle,
|
||
|
IN PRTM_NEXTHOP_INFO NextHopInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Releases all handles present in the input info structure
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RtmRegHandle - RTM registration handle for calling entity,
|
||
|
|
||
|
NextHopInfo - All handles in this info are de-referenced.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status of the operation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PENTITY_INFO Entity;
|
||
|
PDEST_INFO Dest;
|
||
|
|
||
|
DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
|
||
|
|
||
|
if (NextHopInfo->RemoteNextHop)
|
||
|
{
|
||
|
Dest = DEST_FROM_HANDLE(NextHopInfo->RemoteNextHop);
|
||
|
|
||
|
if (Dest)
|
||
|
{
|
||
|
DEREFERENCE_DEST(Dest, HANDLE_REF);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Entity = ENTITY_FROM_HANDLE(NextHopInfo->NextHopOwner);
|
||
|
DEREFERENCE_ENTITY(Entity, HANDLE_REF);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|