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.

1871 lines
44 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. rtmenum.c
  5. Abstract:
  6. Contains routines for managing any enumerations
  7. over destinations, routes and next hops in RTM.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 23-Aug-1998
  10. Revision History:
  11. --*/
  12. #include "pchrtm.h"
  13. #pragma hdrstop
  14. DWORD
  15. WINAPI
  16. RtmCreateDestEnum (
  17. IN RTM_ENTITY_HANDLE RtmRegHandle,
  18. IN RTM_VIEW_SET TargetViews,
  19. IN RTM_ENUM_FLAGS EnumFlags,
  20. IN PRTM_NET_ADDRESS NetAddress,
  21. IN ULONG ProtocolId,
  22. OUT PRTM_ENUM_HANDLE RtmEnumHandle
  23. )
  24. /*++
  25. Routine Description:
  26. Creates a enumeration over the destinations in the route table.
  27. Arguments:
  28. RtmRegHandle - RTM registration handle for calling entity,
  29. TargetViews - Set of views in which the enumeration is done,
  30. EnumFlags - Flags that control the dests returned in enum,
  31. NetAddress - Start and/or stop address of the enumeration,
  32. [ See a description of RTM_ENUM_FLAGS ...]
  33. Protocol Id - Protocol Id that determines the best route
  34. information returned in 'GetEnumDests' call,
  35. RtmEnumHandle - Handle to this enumeration, which is used
  36. in subsequent calls to get dests, and so on.
  37. Return Value:
  38. Status of the operation
  39. --*/
  40. {
  41. PADDRFAM_INFO AddrFamInfo;
  42. PENTITY_INFO Entity;
  43. PDEST_ENUM Enum;
  44. PUCHAR AddrBits;
  45. UINT AddrSize;
  46. UINT i, j;
  47. DWORD Status;
  48. BOOL LockInited;
  49. //
  50. // Do some validation checks on the input params
  51. //
  52. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  53. if ((EnumFlags & RTM_ENUM_NEXT) && (EnumFlags & RTM_ENUM_RANGE))
  54. {
  55. return ERROR_INVALID_PARAMETER;
  56. }
  57. if (EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  58. {
  59. if (!NetAddress)
  60. {
  61. return ERROR_INVALID_PARAMETER;
  62. }
  63. }
  64. AddrFamInfo = Entity->OwningAddrFamily;
  65. //
  66. // Is he interested in any non-supported views ?
  67. //
  68. if (TargetViews & ~AddrFamInfo->ViewsSupported)
  69. {
  70. return ERROR_NOT_SUPPORTED;
  71. }
  72. //
  73. // Create and initialize an dest enumeration block
  74. //
  75. Enum = (PDEST_ENUM) AllocNZeroObject(sizeof(DEST_ENUM));
  76. if (Enum == NULL)
  77. {
  78. return ERROR_NOT_ENOUGH_MEMORY;
  79. }
  80. do
  81. {
  82. #if DBG_HDL
  83. Enum->EnumHeader.ObjectHeader.TypeSign = DEST_ENUM_ALLOC;
  84. #endif
  85. Enum->EnumHeader.HandleType = DEST_ENUM_TYPE;
  86. Enum->TargetViews = TargetViews;
  87. Enum->NumberOfViews = NUMBER_OF_BITS(TargetViews);
  88. Enum->ProtocolId = ProtocolId;
  89. Enum->EnumFlags = EnumFlags;
  90. #if DBG
  91. // Initialize the first address in the enum
  92. if (Enum->EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  93. {
  94. CopyMemory(&Enum->StartAddress,
  95. NetAddress,
  96. sizeof(RTM_NET_ADDRESS));
  97. }
  98. #endif
  99. AddrSize = AddrFamInfo->AddressSize;
  100. //
  101. // Initialize the last address in the enum
  102. //
  103. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  104. {
  105. //
  106. // Convert the NetAddress a.b/n -> a.b.FF.FF/N where N = ADDRSIZE
  107. //
  108. Enum->StopAddress.AddressFamily = NetAddress->AddressFamily;
  109. Enum->StopAddress.NumBits = (USHORT) (AddrSize * BITS_IN_BYTE);
  110. AddrBits = Enum->StopAddress.AddrBits;
  111. for (i = 0; i < (NetAddress->NumBits / BITS_IN_BYTE); i++)
  112. {
  113. AddrBits[i] = NetAddress->AddrBits[i];
  114. }
  115. j = i;
  116. for (; i < AddrSize; i++)
  117. {
  118. AddrBits[i] = 0xFF;
  119. }
  120. if (j < AddrSize)
  121. {
  122. AddrBits[j] >>= (NetAddress->NumBits % BITS_IN_BYTE);
  123. AddrBits[j] |= NetAddress->AddrBits[j];
  124. }
  125. }
  126. LockInited = FALSE;
  127. try
  128. {
  129. InitializeCriticalSection(&Enum->EnumLock);
  130. LockInited = TRUE;
  131. }
  132. except(EXCEPTION_EXECUTE_HANDLER)
  133. {
  134. Status = ERROR_NOT_ENOUGH_MEMORY;
  135. break;
  136. }
  137. // Initialize the next destination context
  138. if (EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  139. {
  140. CopyMemory(&Enum->NextDest,
  141. NetAddress,
  142. sizeof(RTM_NET_ADDRESS));
  143. }
  144. #if DBG_HDL
  145. //
  146. // Insert into list of handles opened by entity
  147. //
  148. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  149. InsertTailList(&Entity->OpenHandles, &Enum->EnumHeader.HandlesLE);
  150. RELEASE_OPEN_HANDLES_LOCK(Entity);
  151. #endif
  152. REFERENCE_ENTITY(Entity, ENUM_REF);
  153. //
  154. // Make a handle to the enum block and return
  155. //
  156. *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum);
  157. return NO_ERROR;
  158. }
  159. while (FALSE);
  160. //
  161. // Something failed - undo work done and return status
  162. //
  163. #if DBG_HDL
  164. Enum->EnumHeader.ObjectHeader.TypeSign = DEST_ENUM_FREED;
  165. #endif
  166. if (LockInited)
  167. {
  168. DeleteCriticalSection(&Enum->EnumLock);
  169. }
  170. FreeObject(Enum);
  171. *RtmEnumHandle = NULL;
  172. return Status;
  173. }
  174. DWORD
  175. WINAPI
  176. RtmGetEnumDests (
  177. IN RTM_ENTITY_HANDLE RtmRegHandle,
  178. IN RTM_ENUM_HANDLE EnumHandle,
  179. IN OUT PUINT NumDests,
  180. OUT PRTM_DEST_INFO DestInfos
  181. )
  182. /*++
  183. Routine Description:
  184. Gets the next set of destinations in the given enumeration
  185. on the route table.
  186. Arguments:
  187. RtmRegHandle - RTM registration handle for calling entity,
  188. EnumHandle - Handle to the destination enumeration,
  189. NumDests - Num. of DestInfo's in output is passed in,
  190. Num. of DestInfo's copied out is returned.
  191. DestInfos - Output buffer where destination info is retd.
  192. Return Value:
  193. Status of the operation
  194. --*/
  195. {
  196. PADDRFAM_INFO AddrFamInfo;
  197. PENTITY_INFO Entity;
  198. PDEST_ENUM Enum;
  199. LOOKUP_CONTEXT Context;
  200. PUCHAR EndofBuffer;
  201. UINT DestInfoSize;
  202. UINT DestsInput;
  203. UINT DestsCopied;
  204. UINT DestsLeft;
  205. PDEST_INFO Dest;
  206. PLOOKUP_LINKAGE*DestData;
  207. PROUTE_INFO Route;
  208. USHORT StopNumBits;
  209. PUCHAR StopKeyBits;
  210. UINT i, j;
  211. DWORD Status;
  212. //
  213. // Init the output params in case we fail validation
  214. //
  215. DestsInput = *NumDests;
  216. *NumDests = 0;
  217. //
  218. // Do some validation checks on the input params
  219. //
  220. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  221. VALIDATE_DEST_ENUM_HANDLE(EnumHandle, &Enum);
  222. AddrFamInfo = Entity->OwningAddrFamily;
  223. if ((DestsInput > AddrFamInfo->MaxHandlesInEnum) ||
  224. (DestsInput < 1))
  225. {
  226. return ERROR_INVALID_PARAMETER;
  227. }
  228. // Acquire lock to block other RtmGetEnumDests
  229. ACQUIRE_DEST_ENUM_LOCK(Enum);
  230. // Make sure enum is active at this point
  231. if (Enum->EnumDone)
  232. {
  233. RELEASE_DEST_ENUM_LOCK(Enum);
  234. return ERROR_NO_MORE_ITEMS;
  235. }
  236. //
  237. // Get the next set of destinations from table
  238. //
  239. // Initialize the lookup context before Enum
  240. ZeroMemory(&Context, sizeof(LOOKUP_CONTEXT));
  241. DestInfoSize = RTM_SIZE_OF_DEST_INFO(Enum->NumberOfViews);
  242. EndofBuffer = (PUCHAR) DestInfos + DestsInput * DestInfoSize;
  243. DestsLeft = DestsInput;
  244. DestsCopied = 0;
  245. ACQUIRE_ROUTE_TABLE_READ_LOCK(AddrFamInfo);
  246. do
  247. {
  248. // Use the end of the caller's buffer as temp space
  249. DestData = (PLOOKUP_LINKAGE *) (EndofBuffer -
  250. DestsLeft * sizeof(PLOOKUP_LINKAGE));
  251. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  252. {
  253. StopNumBits = Enum->StopAddress.NumBits;
  254. StopKeyBits = Enum->StopAddress.AddrBits;
  255. }
  256. else
  257. {
  258. StopNumBits = 0;
  259. StopKeyBits = NULL;
  260. }
  261. Status = EnumOverTable(AddrFamInfo->RouteTable,
  262. &Enum->NextDest.NumBits,
  263. Enum->NextDest.AddrBits,
  264. &Context,
  265. StopNumBits,
  266. StopKeyBits,
  267. &DestsLeft,
  268. DestData);
  269. for (i = 0; i < DestsLeft; i++)
  270. {
  271. Dest = CONTAINING_RECORD(DestData[i], DEST_INFO, LookupLinkage);
  272. if ((Enum->TargetViews == RTM_VIEW_MASK_ANY) ||
  273. (Dest->BelongsToViews & Enum->TargetViews))
  274. {
  275. if (Enum->EnumFlags & RTM_ENUM_OWN_DESTS)
  276. {
  277. // Check if this dest is owned in any view by caller
  278. for (j = 0; j < AddrFamInfo->NumberOfViews; j++)
  279. {
  280. Route = Dest->ViewInfo[j].BestRoute;
  281. if (Route)
  282. {
  283. if (Route->RouteInfo.RouteOwner == RtmRegHandle)
  284. {
  285. break;
  286. }
  287. }
  288. }
  289. if (j == AddrFamInfo->NumberOfViews)
  290. {
  291. continue;
  292. }
  293. }
  294. //
  295. // Get the destination info from the dest
  296. //
  297. GetDestInfo(Entity,
  298. Dest,
  299. Enum->ProtocolId,
  300. Enum->TargetViews,
  301. DestInfos);
  302. DestsCopied++;
  303. DestInfos = (PRTM_DEST_INFO)(DestInfoSize + (PUCHAR)DestInfos);
  304. }
  305. }
  306. DestsLeft = DestsInput - DestsCopied;
  307. }
  308. while (SUCCESS(Status) && (DestsLeft > 0));
  309. //
  310. // We have no more dests, or we have filled output
  311. //
  312. ASSERT(!SUCCESS(Status) || ((PUCHAR) DestInfos == (PUCHAR) EndofBuffer));
  313. RELEASE_ROUTE_TABLE_READ_LOCK(AddrFamInfo);
  314. // If we are at end of the enum, make enum as done
  315. if (Status == ERROR_NO_MORE_ITEMS)
  316. {
  317. Enum->EnumDone = TRUE;
  318. }
  319. RELEASE_DEST_ENUM_LOCK(Enum);
  320. *NumDests = DestsCopied;
  321. return *NumDests ? NO_ERROR : ERROR_NO_MORE_ITEMS;
  322. }
  323. DWORD
  324. WINAPI
  325. RtmReleaseDests (
  326. IN RTM_ENTITY_HANDLE RtmRegHandle,
  327. IN UINT NumDests,
  328. IN PRTM_DEST_INFO DestInfos
  329. )
  330. /*++
  331. Routine Description:
  332. Release destination information obtained in other calls -
  333. like dest enumerations.
  334. Arguments:
  335. RtmRegHandle - RTM registration handle for calling entity,
  336. NumDests - Number of dest infos that are being released,
  337. DestInfos - Array of dest infos that are being released.
  338. Return Value:
  339. Status of the operation
  340. --*/
  341. {
  342. PENTITY_INFO Entity;
  343. UINT NumViews;
  344. UINT DestInfoSize;
  345. UINT i;
  346. DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  347. //
  348. // Get the size of each info in dest info array
  349. //
  350. NumViews = ((PRTM_DEST_INFO) DestInfos)->NumberOfViews;
  351. DestInfoSize = RTM_SIZE_OF_DEST_INFO(NumViews);
  352. //
  353. // Dereference each dest info in array
  354. //
  355. for (i = 0; i < NumDests; i++)
  356. {
  357. RtmReleaseDestInfo(RtmRegHandle, DestInfos);
  358. DestInfos = (PRTM_DEST_INFO)(DestInfoSize + (PUCHAR)DestInfos);
  359. }
  360. return NO_ERROR;
  361. }
  362. DWORD
  363. WINAPI
  364. RtmCreateRouteEnum (
  365. IN RTM_ENTITY_HANDLE RtmRegHandle,
  366. IN RTM_DEST_HANDLE DestHandle OPTIONAL,
  367. IN RTM_VIEW_SET TargetViews,
  368. IN RTM_ENUM_FLAGS EnumFlags,
  369. IN PRTM_NET_ADDRESS StartDest OPTIONAL,
  370. IN RTM_MATCH_FLAGS MatchingFlags,
  371. IN PRTM_ROUTE_INFO CriteriaRoute OPTIONAL,
  372. IN ULONG CriteriaInterface OPTIONAL,
  373. OUT PRTM_ENUM_HANDLE RtmEnumHandle
  374. )
  375. /*++
  376. Routine Description:
  377. Creates a enumeration over the routes on a particular dest
  378. in the route table. If the dest is NULL, an enumeration is
  379. created over the whole route table.
  380. If matching flags are specified, only routes that match the
  381. criteria are returned.
  382. Arguments:
  383. RtmRegHandle - RTM registration handle for calling entity,
  384. DestHandle - The destination whose routes we are enum'ing,
  385. Or NULL if we are enum'ing over all dests.
  386. TargetViews - Set of views in which the enumeration is done,
  387. EnumFlags - Flags that control the routes retd in enum,
  388. MatchingFlags - Indicates the elements of the route to match,
  389. CriteriaRoute - Values to match each route in the enum,
  390. CritInterface - Interface on which routes should fall on,
  391. RtmEnumHandle - Handle to this enumeration, which is used
  392. in subsequent calls to get routes, and so on.
  393. Return Value:
  394. Status of the operation
  395. --*/
  396. {
  397. PADDRFAM_INFO AddrFamInfo;
  398. PENTITY_INFO Entity;
  399. PROUTE_ENUM Enum;
  400. PDEST_INFO Dest;
  401. BOOL LockInited;
  402. ULONG NumBytes;
  403. DWORD Status;
  404. //
  405. // Do some validation checks on the input params
  406. //
  407. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  408. AddrFamInfo = Entity->OwningAddrFamily;
  409. #if WRN
  410. Dest = NULL;
  411. #endif
  412. if (ARGUMENT_PRESENT(DestHandle))
  413. {
  414. // StartDest doesnt apply if enum'ing a dest
  415. if (ARGUMENT_PRESENT(StartDest))
  416. {
  417. return ERROR_INVALID_PARAMETER;
  418. }
  419. VALIDATE_DEST_HANDLE(DestHandle, &Dest);
  420. }
  421. // If we have matching flags, we need corr. route
  422. if (MatchingFlags & ~RTM_MATCH_INTERFACE)
  423. {
  424. if (!ARGUMENT_PRESENT(CriteriaRoute))
  425. {
  426. return ERROR_INVALID_PARAMETER;
  427. }
  428. }
  429. //
  430. // Is he interested in any non-supported views ?
  431. //
  432. if (TargetViews & ~AddrFamInfo->ViewsSupported)
  433. {
  434. return ERROR_NOT_SUPPORTED;
  435. }
  436. //
  437. // Create and initialize a route enumeration block
  438. //
  439. Enum = (PROUTE_ENUM) AllocNZeroObject(sizeof(ROUTE_ENUM));
  440. if (Enum == NULL)
  441. {
  442. return ERROR_NOT_ENOUGH_MEMORY;
  443. }
  444. LockInited = FALSE;
  445. #if WRN
  446. Status = ERROR_GEN_FAILURE;
  447. #endif
  448. do
  449. {
  450. #if DBG_HDL
  451. Enum->EnumHeader.ObjectHeader.TypeSign = ROUTE_ENUM_ALLOC;
  452. #endif
  453. Enum->EnumHeader.HandleType = ROUTE_ENUM_TYPE;
  454. Enum->TargetViews = TargetViews;
  455. Enum->EnumFlags = EnumFlags;
  456. if (MatchingFlags)
  457. {
  458. Enum->MatchFlags = MatchingFlags;
  459. if (MatchingFlags & ~RTM_MATCH_INTERFACE)
  460. {
  461. NumBytes = sizeof(RTM_ROUTE_INFO) +
  462. (AddrFamInfo->MaxNextHopsInRoute - 1) *
  463. sizeof(RTM_NEXTHOP_HANDLE);
  464. Enum->CriteriaRoute = AllocMemory(NumBytes);
  465. if (Enum->CriteriaRoute == NULL)
  466. {
  467. break;
  468. }
  469. CopyMemory(Enum->CriteriaRoute, CriteriaRoute, NumBytes);
  470. }
  471. Enum->CriteriaInterface = CriteriaInterface;
  472. }
  473. //
  474. // Initialize the lock to serialize enum requests
  475. //
  476. try
  477. {
  478. InitializeCriticalSection(&Enum->EnumLock);
  479. LockInited = TRUE;
  480. }
  481. except(EXCEPTION_EXECUTE_HANDLER)
  482. {
  483. Status = ERROR_NOT_ENOUGH_MEMORY;
  484. break;
  485. }
  486. //
  487. // Are we enumerating routes on all destinations ?
  488. //
  489. if (!ARGUMENT_PRESENT(DestHandle))
  490. {
  491. //
  492. // Create a temp dest info structure for enum
  493. //
  494. Enum->DestInfo = AllocDestInfo(AddrFamInfo->NumberOfViews);
  495. if (Enum->DestInfo == NULL)
  496. {
  497. Status = ERROR_NOT_ENOUGH_MEMORY;
  498. break;
  499. }
  500. //
  501. // Open a dest enumeration to get all dests
  502. //
  503. Status = RtmCreateDestEnum(RtmRegHandle,
  504. TargetViews,
  505. EnumFlags,
  506. StartDest,
  507. RTM_BEST_PROTOCOL,
  508. &Enum->DestEnum);
  509. if (!SUCCESS(Status))
  510. {
  511. break;
  512. }
  513. }
  514. else
  515. {
  516. //
  517. // Ref dest whose routes we are enum'ing
  518. //
  519. Enum->Destination = Dest;
  520. REFERENCE_DEST(Dest, ENUM_REF);
  521. }
  522. #if DBG_HDL
  523. //
  524. // Insert into list of handles opened by entity
  525. //
  526. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  527. InsertTailList(&Entity->OpenHandles, &Enum->EnumHeader.HandlesLE);
  528. RELEASE_OPEN_HANDLES_LOCK(Entity);
  529. #endif
  530. REFERENCE_ENTITY(Entity, ENUM_REF);
  531. //
  532. // Make a handle to the enum block and return
  533. //
  534. *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum);
  535. return NO_ERROR;
  536. }
  537. while (FALSE);
  538. //
  539. // Something failed - undo work done and return status
  540. //
  541. if (Enum->DestInfo)
  542. {
  543. FreeMemory(Enum->DestInfo);
  544. }
  545. if (LockInited)
  546. {
  547. DeleteCriticalSection(&Enum->EnumLock);
  548. }
  549. if (Enum->CriteriaRoute)
  550. {
  551. FreeMemory(Enum->CriteriaRoute);
  552. }
  553. FreeObject(Enum);
  554. *RtmEnumHandle = NULL;
  555. return Status;
  556. }
  557. DWORD
  558. WINAPI
  559. RtmGetEnumRoutes (
  560. IN RTM_ENTITY_HANDLE RtmRegHandle,
  561. IN RTM_ENUM_HANDLE EnumHandle,
  562. IN OUT PUINT NumRoutes,
  563. OUT PRTM_ROUTE_HANDLE RouteHandles
  564. )
  565. /*++
  566. Routine Description:
  567. Gets the next set of routes in the given enumeration on the
  568. route table.
  569. Arguments:
  570. RtmRegHandle - RTM registration handle for calling entity,
  571. EnumHandle - Handle to the route enumeration,
  572. NumRoutes - Max. number of routes to fill is passed in,
  573. Num. of routes actually copied is returned.
  574. RouteHandles - Output buffer where route handles are retd.
  575. Return Value:
  576. Status of the operation
  577. --*/
  578. {
  579. PADDRFAM_INFO AddrFamInfo;
  580. PENTITY_INFO Entity;
  581. PROUTE_ENUM Enum;
  582. PDEST_INFO Dest;
  583. PROUTE_INFO Route;
  584. PROUTE_INFO *NextRoute;
  585. UINT NumDests;
  586. UINT RoutesInput;
  587. UINT RoutesCopied;
  588. UINT RoutesOnDest;
  589. UINT RoutesToCopy;
  590. PLIST_ENTRY p;
  591. UINT i;
  592. DWORD Status;
  593. //
  594. // Init the output params in case we fail validation
  595. //
  596. RoutesInput = *NumRoutes;
  597. *NumRoutes = 0;
  598. //
  599. // Do some validation checks on the input params
  600. //
  601. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  602. VALIDATE_ROUTE_ENUM_HANDLE(EnumHandle, &Enum);
  603. AddrFamInfo = Entity->OwningAddrFamily;
  604. if ((RoutesInput > AddrFamInfo->MaxHandlesInEnum) ||
  605. (RoutesInput < 1))
  606. {
  607. return ERROR_INVALID_PARAMETER;
  608. }
  609. // Acquire lock to block other RtmGetEnumRoutes
  610. ACQUIRE_ROUTE_ENUM_LOCK(Enum);
  611. // Make sure enum is active at this point
  612. if (Enum->EnumDone)
  613. {
  614. RELEASE_ROUTE_ENUM_LOCK(Enum);
  615. return ERROR_NO_MORE_ITEMS;
  616. }
  617. //
  618. // Get more routes until you satisfy the request
  619. //
  620. Status = NO_ERROR;
  621. RoutesCopied = 0;
  622. do
  623. {
  624. //
  625. // Do we have any routes in current snapshot ?
  626. //
  627. RoutesOnDest = Enum->NumRoutes - Enum->NextRoute;
  628. if (RoutesOnDest == 0)
  629. {
  630. //
  631. // Destination value in the enum is not set if
  632. //
  633. // 1. we are doing an enum over the whole
  634. // table, and
  635. //
  636. // 2. we did not run out of memory in the
  637. // previous attempt to take a snapshot
  638. // ( if we did make an attempt before )
  639. //
  640. if (Enum->Destination == NULL)
  641. {
  642. ASSERT(Enum->DestEnum);
  643. //
  644. // Get the next destination in the table
  645. //
  646. NumDests = 1;
  647. Status = RtmGetEnumDests(RtmRegHandle,
  648. Enum->DestEnum,
  649. &NumDests,
  650. Enum->DestInfo);
  651. if (NumDests < 1)
  652. {
  653. break;
  654. }
  655. Dest = DEST_FROM_HANDLE(Enum->DestInfo->DestHandle);
  656. Enum->Destination = Dest;
  657. REFERENCE_DEST(Dest, ENUM_REF);
  658. RtmReleaseDestInfo(RtmRegHandle,
  659. Enum->DestInfo);
  660. }
  661. else
  662. {
  663. Dest = Enum->Destination;
  664. }
  665. ASSERT(Enum->Destination != NULL);
  666. //
  667. // Allocate memory to hold snapshot of routes
  668. //
  669. ACQUIRE_DEST_READ_LOCK(Dest);
  670. if (Enum->MaxRoutes < Dest->NumRoutes)
  671. {
  672. //
  673. // Re-adjust the size of snapshot buffer
  674. //
  675. if (Enum->RoutesOnDest)
  676. {
  677. FreeMemory(Enum->RoutesOnDest);
  678. }
  679. Enum->RoutesOnDest = (PROUTE_INFO *)
  680. AllocNZeroMemory(Dest->NumRoutes *
  681. sizeof(PROUTE_INFO));
  682. if (Enum->RoutesOnDest == NULL)
  683. {
  684. RELEASE_DEST_READ_LOCK(Dest);
  685. Enum->MaxRoutes = 0;
  686. Enum->NumRoutes = 0;
  687. Enum->NextRoute = 0;
  688. Status = ERROR_NOT_ENOUGH_MEMORY;
  689. break;
  690. }
  691. Enum->MaxRoutes = Dest->NumRoutes;
  692. }
  693. //
  694. // Get snapshot of all routes on this dest
  695. //
  696. Enum->NumRoutes = Enum->NextRoute = 0;
  697. for (p = Dest->RouteList.Flink; p != &Dest->RouteList; p= p->Flink)
  698. {
  699. Route = CONTAINING_RECORD(p, ROUTE_INFO, DestLE);
  700. //
  701. // Does this route belong one of interesting views ?
  702. //
  703. if ((Enum->TargetViews == RTM_VIEW_MASK_ANY) ||
  704. (Route->RouteInfo.BelongsToViews & Enum->TargetViews))
  705. {
  706. if (Enum->EnumFlags & RTM_ENUM_OWN_ROUTES)
  707. {
  708. // Check if this route is owned by the caller
  709. if (Route->RouteInfo.RouteOwner != RtmRegHandle)
  710. {
  711. continue;
  712. }
  713. }
  714. // Does this route match the enumeration criteria ?
  715. if (Enum->MatchFlags &&
  716. !MatchRouteWithCriteria(Route,
  717. Enum->MatchFlags,
  718. Enum->CriteriaRoute,
  719. Enum->CriteriaInterface))
  720. {
  721. continue;
  722. }
  723. REFERENCE_ROUTE(Route, ENUM_REF);
  724. //
  725. // Reference the route and copy the handle to output
  726. //
  727. Enum->RoutesOnDest[Enum->NumRoutes++] = Route;
  728. }
  729. }
  730. ASSERT(Enum->NumRoutes <= Dest->NumRoutes);
  731. RELEASE_DEST_READ_LOCK(Dest);
  732. //
  733. // If we are enum'ing the whole table, we do
  734. // not need the dest whose snapshot is taken
  735. //
  736. if (Enum->DestEnum)
  737. {
  738. Enum->Destination = NULL;
  739. DEREFERENCE_DEST(Dest, ENUM_REF);
  740. }
  741. // Adjust the number of routes on the dest
  742. RoutesOnDest = Enum->NumRoutes - Enum->NextRoute;
  743. }
  744. //
  745. // Copy routes to output from the current snapshot
  746. //
  747. if (RoutesOnDest)
  748. {
  749. RoutesToCopy = RoutesInput - RoutesCopied;
  750. if (RoutesToCopy > RoutesOnDest)
  751. {
  752. RoutesToCopy = RoutesOnDest;
  753. }
  754. NextRoute = &Enum->RoutesOnDest[Enum->NextRoute];
  755. for (i = 0; i < RoutesToCopy; i++)
  756. {
  757. #if DBG_REF
  758. REFERENCE_ROUTE(*NextRoute, HANDLE_REF);
  759. DEREFERENCE_ROUTE(*NextRoute, ENUM_REF);
  760. #endif
  761. RouteHandles[RoutesCopied++] =
  762. MAKE_HANDLE_FROM_POINTER(*NextRoute++);
  763. }
  764. Enum->NextRoute += RoutesToCopy;
  765. RoutesOnDest -= RoutesToCopy;
  766. }
  767. //
  768. // Are we done with all the routes in snapshot ?
  769. //
  770. if (RoutesOnDest == 0)
  771. {
  772. //
  773. // If we are enum'ing a single dest, we are done
  774. //
  775. if (Enum->DestEnum == NULL)
  776. {
  777. Status = ERROR_NO_MORE_ITEMS;
  778. break;
  779. }
  780. }
  781. }
  782. while (SUCCESS(Status) && (RoutesCopied < RoutesInput));
  783. // If we are at end of the enum, make enum as done
  784. if ((Status == ERROR_NO_MORE_ITEMS) && (RoutesOnDest == 0))
  785. {
  786. Enum->EnumDone = TRUE;
  787. }
  788. RELEASE_ROUTE_ENUM_LOCK(Enum);
  789. //
  790. // Update output to reflect number of routes copied
  791. //
  792. *NumRoutes = RoutesCopied;
  793. return *NumRoutes ? NO_ERROR : ERROR_NO_MORE_ITEMS;
  794. }
  795. BOOL
  796. MatchRouteWithCriteria (
  797. IN PROUTE_INFO Route,
  798. IN RTM_MATCH_FLAGS MatchingFlags,
  799. IN PRTM_ROUTE_INFO CriteriaRouteInfo,
  800. IN ULONG CriteriaInterface
  801. )
  802. /*++
  803. Routine Description:
  804. Matches a route with the input criteria given by input flags
  805. and the route to match.
  806. Arguments:
  807. Route - Route that we are matching criteria with,
  808. MatchingFlags - Flags that indicate which fields to match,
  809. CriteriaRouteInfo - Route info that specifies match criteria,
  810. CriteriaInterface - Interface to match if MATCH_INTERFACE is set.
  811. Return Value:
  812. TRUE if route matches criteria, FALSE if not
  813. --*/
  814. {
  815. PRTM_NEXTHOP_HANDLE NextHops;
  816. PNEXTHOP_INFO NextHop;
  817. UINT NumNHops;
  818. UINT i;
  819. //
  820. // Try matching the route owner if flags say so
  821. //
  822. if (MatchingFlags & RTM_MATCH_OWNER)
  823. {
  824. if (Route->RouteInfo.RouteOwner != CriteriaRouteInfo->RouteOwner)
  825. {
  826. return FALSE;
  827. }
  828. }
  829. //
  830. // Try matching the neighbour if flags say so
  831. //
  832. if (MatchingFlags & RTM_MATCH_NEIGHBOUR)
  833. {
  834. if (Route->RouteInfo.Neighbour != CriteriaRouteInfo->Neighbour)
  835. {
  836. return FALSE;
  837. }
  838. }
  839. //
  840. // Try matching the preference if flags say so
  841. //
  842. if (MatchingFlags & RTM_MATCH_PREF)
  843. {
  844. if (!IsPrefEqual(&Route->RouteInfo, CriteriaRouteInfo))
  845. {
  846. return FALSE;
  847. }
  848. }
  849. //
  850. // Try matching the interface if flags say so
  851. //
  852. if (MatchingFlags & RTM_MATCH_INTERFACE)
  853. {
  854. NumNHops = Route->RouteInfo.NextHopsList.NumNextHops;
  855. NextHops = Route->RouteInfo.NextHopsList.NextHops;
  856. for (i = 0; i < NumNHops; i++)
  857. {
  858. NextHop = NEXTHOP_FROM_HANDLE(NextHops[i]);
  859. if (NextHop->NextHopInfo.InterfaceIndex == CriteriaInterface)
  860. {
  861. break;
  862. }
  863. }
  864. if (i == NumNHops)
  865. {
  866. return FALSE;
  867. }
  868. }
  869. //
  870. // Try matching the nexthop if flags say so
  871. //
  872. if (MatchingFlags & RTM_MATCH_NEXTHOP)
  873. {
  874. NumNHops = Route->RouteInfo.NextHopsList.NumNextHops;
  875. NextHops = Route->RouteInfo.NextHopsList.NextHops;
  876. ASSERT(CriteriaRouteInfo->NextHopsList.NumNextHops == 1);
  877. for (i = 0; i < NumNHops; i++)
  878. {
  879. if (NextHops[i] == CriteriaRouteInfo->NextHopsList.NextHops[0])
  880. {
  881. break;
  882. }
  883. }
  884. if (i == NumNHops)
  885. {
  886. return FALSE;
  887. }
  888. }
  889. return TRUE;
  890. }
  891. DWORD
  892. WINAPI
  893. RtmReleaseRoutes (
  894. IN RTM_ENTITY_HANDLE RtmRegHandle,
  895. IN UINT NumRoutes,
  896. IN PRTM_ROUTE_HANDLE RouteHandles
  897. )
  898. /*++
  899. Routine Description:
  900. Release (also called de-reference) handles to routes
  901. obtained in other RTM calls like route enumerations.
  902. Arguments:
  903. RtmRegHandle - RTM registration handle for calling entity,
  904. NumRoutes - Number of handles that are being released,
  905. RouteHandles - An array of handles that are being released.
  906. Return Value:
  907. Status of the operation
  908. --*/
  909. {
  910. PENTITY_INFO Entity;
  911. PROUTE_INFO Route;
  912. UINT i;
  913. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  914. //
  915. // Dereference each route handle in array
  916. //
  917. for (i = 0; i < NumRoutes; i++)
  918. {
  919. Route = ROUTE_FROM_HANDLE(RouteHandles[i]);
  920. DEREFERENCE_ROUTE(Route, HANDLE_REF);
  921. }
  922. return NO_ERROR;
  923. }
  924. DWORD
  925. WINAPI
  926. RtmCreateNextHopEnum (
  927. IN RTM_ENTITY_HANDLE RtmRegHandle,
  928. IN RTM_ENUM_FLAGS EnumFlags,
  929. IN PRTM_NET_ADDRESS NetAddress,
  930. OUT PRTM_ENUM_HANDLE RtmEnumHandle
  931. )
  932. /*++
  933. Routine Description:
  934. Creates a enumeration over all the next-hops in table.
  935. Arguments:
  936. RtmRegHandle - RTM registration handle for calling entity,
  937. EnumFlags - Flags that control the nexthops retd in enum,
  938. NetAddress - Start and/or stop address of the enumeration,
  939. [ See a description of RTM_ENUM_FLAGS ...]
  940. RtmEnumHandle - Handle to this enumeration, which is used in
  941. subsequent calls to get next-hops, and so on.
  942. Return Value:
  943. Status of the operation
  944. --*/
  945. {
  946. PENTITY_INFO Entity;
  947. PNEXTHOP_ENUM Enum;
  948. PUCHAR AddrBits;
  949. UINT AddrSize;
  950. UINT i, j;
  951. DWORD Status;
  952. BOOL LockInited;
  953. //
  954. // Do some validation checks on the input params
  955. //
  956. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  957. if ((EnumFlags & RTM_ENUM_NEXT) && (EnumFlags & RTM_ENUM_RANGE))
  958. {
  959. return ERROR_INVALID_PARAMETER;
  960. }
  961. if (EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  962. {
  963. if (!NetAddress)
  964. {
  965. return ERROR_INVALID_PARAMETER;
  966. }
  967. }
  968. //
  969. // Create and initialize an nexthop enumeration block
  970. //
  971. Enum = (PNEXTHOP_ENUM) AllocNZeroObject(sizeof(NEXTHOP_ENUM));
  972. if (Enum == NULL)
  973. {
  974. return ERROR_NOT_ENOUGH_MEMORY;
  975. }
  976. do
  977. {
  978. #if DBG_HDL
  979. Enum->EnumHeader.ObjectHeader.TypeSign = NEXTHOP_ENUM_ALLOC;
  980. #endif
  981. Enum->EnumHeader.HandleType = NEXTHOP_ENUM_TYPE;
  982. Enum->EnumFlags = EnumFlags;
  983. #if DBG
  984. // Initialize the first address in the enum
  985. if (Enum->EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  986. {
  987. CopyMemory(&Enum->StartAddress,
  988. NetAddress,
  989. sizeof(RTM_NET_ADDRESS));
  990. }
  991. #endif
  992. AddrSize = Entity->OwningAddrFamily->AddressSize;
  993. //
  994. // Initialize the last address in the enum
  995. //
  996. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  997. {
  998. //
  999. // Convert the NetAddress a.b/n -> a.b.FF.FF/N where N = ADDRSIZE
  1000. //
  1001. Enum->StopAddress.AddressFamily = NetAddress->AddressFamily;
  1002. Enum->StopAddress.NumBits = (USHORT) (AddrSize * BITS_IN_BYTE);
  1003. AddrBits = Enum->StopAddress.AddrBits;
  1004. for (i = 0; i < (NetAddress->NumBits / BITS_IN_BYTE); i++)
  1005. {
  1006. AddrBits[i] = NetAddress->AddrBits[i];
  1007. }
  1008. j = i;
  1009. for (; i < AddrSize; i++)
  1010. {
  1011. AddrBits[i] = 0xFF;
  1012. }
  1013. if (j < AddrSize)
  1014. {
  1015. AddrBits[j] >>= (NetAddress->NumBits % BITS_IN_BYTE);
  1016. AddrBits[j] |= NetAddress->AddrBits[j];
  1017. }
  1018. }
  1019. LockInited = FALSE;
  1020. try
  1021. {
  1022. InitializeCriticalSection(&Enum->EnumLock);
  1023. LockInited = TRUE;
  1024. }
  1025. except(EXCEPTION_EXECUTE_HANDLER)
  1026. {
  1027. Status = ERROR_NOT_ENOUGH_MEMORY;
  1028. break;
  1029. }
  1030. // Initialize the next 'nexthop' context
  1031. if (NetAddress)
  1032. {
  1033. CopyMemory(&Enum->NextAddress,
  1034. NetAddress,
  1035. sizeof(RTM_NET_ADDRESS));
  1036. }
  1037. Enum->NextIfIndex = START_IF_INDEX;
  1038. #if DBG_HDL
  1039. //
  1040. // Insert into list of handles opened by entity
  1041. //
  1042. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  1043. InsertTailList(&Entity->OpenHandles, &Enum->EnumHeader.HandlesLE);
  1044. RELEASE_OPEN_HANDLES_LOCK(Entity);
  1045. #endif
  1046. REFERENCE_ENTITY(Entity, ENUM_REF);
  1047. //
  1048. // Make a handle to the enum block and return
  1049. //
  1050. *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum);
  1051. return NO_ERROR;
  1052. }
  1053. while (FALSE);
  1054. //
  1055. // Something failed - undo work done and return status
  1056. //
  1057. #if DBG_HDL
  1058. Enum->EnumHeader.ObjectHeader.TypeSign = NEXTHOP_ENUM_FREED;
  1059. #endif
  1060. if (LockInited)
  1061. {
  1062. DeleteCriticalSection(&Enum->EnumLock);
  1063. }
  1064. FreeObject(Enum);
  1065. *RtmEnumHandle = NULL;
  1066. return Status;
  1067. }
  1068. DWORD
  1069. WINAPI
  1070. RtmGetEnumNextHops (
  1071. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1072. IN RTM_ENUM_HANDLE EnumHandle,
  1073. IN OUT PUINT NumNextHops,
  1074. OUT PRTM_NEXTHOP_HANDLE NextHopHandles
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. Gets the next set of next-hops in the given enumeration
  1079. on the next-hop table.
  1080. Arguments:
  1081. RtmRegHandle - RTM registration handle for calling entity,
  1082. EnumHandle - Handle to the next-hop enumeration,
  1083. NumNextHops - Num. of next-hops in output is passed in,
  1084. Num. of next-hops copied out is returned.
  1085. NextHopHandles - Output buffer where next-hop handles are retd.
  1086. Return Value:
  1087. Status of the operation
  1088. --*/
  1089. {
  1090. PADDRFAM_INFO AddrFamInfo;
  1091. PENTITY_INFO Entity;
  1092. PNEXTHOP_ENUM Enum;
  1093. LOOKUP_CONTEXT Context;
  1094. PNEXTHOP_LIST HopList;
  1095. PNEXTHOP_INFO NextHop;
  1096. PLOOKUP_LINKAGE NextHopData;
  1097. PLIST_ENTRY NextHops, p;
  1098. UINT NextHopsInput;
  1099. UINT NextHopsCopied;
  1100. UINT NumHopLists;
  1101. USHORT StopNumBits;
  1102. PUCHAR StopKeyBits;
  1103. DWORD Status;
  1104. //
  1105. // Init the output params in case we fail validation
  1106. //
  1107. NextHopsInput = *NumNextHops;
  1108. *NumNextHops = 0;
  1109. //
  1110. // Do some validation checks on the input params
  1111. //
  1112. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  1113. VALIDATE_NEXTHOP_ENUM_HANDLE(EnumHandle, &Enum);
  1114. AddrFamInfo = Entity->OwningAddrFamily;
  1115. if ((NextHopsInput > AddrFamInfo->MaxHandlesInEnum) ||
  1116. (NextHopsInput < 1))
  1117. {
  1118. return ERROR_INVALID_PARAMETER;
  1119. }
  1120. // Acquire lock to block other RtmGetEnumNextHops
  1121. ACQUIRE_NEXTHOP_ENUM_LOCK(Enum);
  1122. // Make sure enum is active at this point
  1123. if (Enum->EnumDone)
  1124. {
  1125. RELEASE_NEXTHOP_ENUM_LOCK(Enum);
  1126. return ERROR_NO_MORE_ITEMS;
  1127. }
  1128. // Initialize the lookup context before Enum
  1129. ZeroMemory(&Context, sizeof(LOOKUP_CONTEXT));
  1130. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  1131. {
  1132. StopNumBits = Enum->StopAddress.NumBits;
  1133. StopKeyBits = Enum->StopAddress.AddrBits;
  1134. }
  1135. else
  1136. {
  1137. StopNumBits = 0;
  1138. StopKeyBits = NULL;
  1139. }
  1140. NextHopsCopied = 0;
  1141. ACQUIRE_NHOP_TABLE_READ_LOCK(Entity);
  1142. do
  1143. {
  1144. //
  1145. // Get the next list of next-hops from table
  1146. //
  1147. NumHopLists = 1;
  1148. Status = EnumOverTable(Entity->NextHopTable,
  1149. &Enum->NextAddress.NumBits,
  1150. Enum->NextAddress.AddrBits,
  1151. &Context,
  1152. StopNumBits,
  1153. StopKeyBits,
  1154. &NumHopLists,
  1155. &NextHopData);
  1156. if (NumHopLists < 1)
  1157. {
  1158. break;
  1159. }
  1160. HopList = CONTAINING_RECORD(NextHopData, NEXTHOP_LIST, LookupLinkage);
  1161. NextHops = &HopList->NextHopsList;
  1162. // Skip all the interface indices we have seen
  1163. for (p = NextHops->Flink; p != NextHops; p = p->Flink)
  1164. {
  1165. NextHop = CONTAINING_RECORD(p, NEXTHOP_INFO, NextHopsLE);
  1166. if (NextHop->NextHopInfo.InterfaceIndex <= Enum->NextIfIndex)
  1167. {
  1168. break;
  1169. }
  1170. }
  1171. #if WRN
  1172. NextHop = NULL;
  1173. #endif
  1174. // Copy the rest of the next-hops in the list
  1175. for ( ; p != NextHops; p = p->Flink)
  1176. {
  1177. NextHop = CONTAINING_RECORD(p, NEXTHOP_INFO, NextHopsLE);
  1178. if (NextHopsCopied == NextHopsInput)
  1179. {
  1180. break;
  1181. }
  1182. REFERENCE_NEXTHOP(NextHop, HANDLE_REF);
  1183. NextHopHandles[NextHopsCopied++]=MAKE_HANDLE_FROM_POINTER(NextHop);
  1184. }
  1185. // If we are going to the next list, reset if index
  1186. if (p == NextHops)
  1187. {
  1188. Enum->NextIfIndex = START_IF_INDEX;
  1189. }
  1190. else
  1191. {
  1192. // We have copied enough for this call
  1193. ASSERT(NextHopsCopied == NextHopsInput);
  1194. //
  1195. // We still have next-hops on the list,
  1196. // set back the next 'nexthop address'
  1197. //
  1198. Enum->NextAddress = NextHop->NextHopInfo.NextHopAddress;
  1199. Enum->NextIfIndex = NextHop->NextHopInfo.InterfaceIndex;
  1200. Status = NO_ERROR;
  1201. }
  1202. }
  1203. while (SUCCESS(Status) && (NextHopsCopied < NextHopsInput));
  1204. RELEASE_NHOP_TABLE_READ_LOCK(Entity);
  1205. // If we are at end of the enum, make enum as done
  1206. if (Status == ERROR_NO_MORE_ITEMS)
  1207. {
  1208. Enum->EnumDone = TRUE;
  1209. }
  1210. RELEASE_NEXTHOP_ENUM_LOCK(Enum);
  1211. *NumNextHops = NextHopsCopied;
  1212. return *NumNextHops ? NO_ERROR : ERROR_NO_MORE_ITEMS;
  1213. }
  1214. DWORD
  1215. WINAPI
  1216. RtmReleaseNextHops (
  1217. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1218. IN UINT NumNextHops,
  1219. IN PRTM_NEXTHOP_HANDLE NextHopHandles
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. Release (also called de-reference) handles to next-hops
  1224. obtained in other RTM calls like next hop enumerations.
  1225. Arguments:
  1226. RtmRegHandle - RTM registration handle for calling entity,
  1227. NumNextHops - Number of handles that are being released,
  1228. NextHopHandles - An array of handles that are being released.
  1229. Return Value:
  1230. Status of the operation
  1231. --*/
  1232. {
  1233. PENTITY_INFO Entity;
  1234. PNEXTHOP_INFO NextHop;
  1235. UINT i;
  1236. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  1237. //
  1238. // Dereference each nexthop handle in array
  1239. //
  1240. for (i = 0; i < NumNextHops; i++)
  1241. {
  1242. NextHop = NEXTHOP_FROM_HANDLE(NextHopHandles[i]);
  1243. DEREFERENCE_NEXTHOP(NextHop, HANDLE_REF);
  1244. }
  1245. return NO_ERROR;
  1246. }
  1247. DWORD
  1248. WINAPI
  1249. RtmDeleteEnumHandle (
  1250. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1251. IN RTM_ENUM_HANDLE EnumHandle
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. Deletes the enumeration handle and frees all resources
  1256. allocated to the enumeration.
  1257. Arguments:
  1258. RtmRegHandle - RTM registration handle for calling entity,
  1259. EnumHandle - Handle to the enumeration.
  1260. Return Value:
  1261. Status of the operation
  1262. --*/
  1263. {
  1264. PENTITY_INFO Entity;
  1265. POPEN_HEADER Enum;
  1266. PROUTE_ENUM RouteEnum;
  1267. UCHAR HandleType;
  1268. UINT i;
  1269. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  1270. //
  1271. // Figure out the enum type and act accordingly
  1272. //
  1273. HandleType = GET_ENUM_TYPE(EnumHandle, &Enum);
  1274. #if DBG
  1275. VALIDATE_OBJECT_HANDLE(EnumHandle, HandleType, &Enum);
  1276. #endif
  1277. switch (HandleType)
  1278. {
  1279. case DEST_ENUM_TYPE:
  1280. DeleteCriticalSection(&((PDEST_ENUM)Enum)->EnumLock);
  1281. break;
  1282. case ROUTE_ENUM_TYPE:
  1283. RouteEnum = (PROUTE_ENUM) Enum;
  1284. // Dereference the destination that we are enum'ing
  1285. if (RouteEnum->Destination)
  1286. {
  1287. DEREFERENCE_DEST(RouteEnum->Destination, ENUM_REF);
  1288. }
  1289. //
  1290. // Close the associated destination enum & resources
  1291. //
  1292. if (RouteEnum->DestInfo)
  1293. {
  1294. FreeMemory(RouteEnum->DestInfo);
  1295. }
  1296. if (RouteEnum->DestEnum)
  1297. {
  1298. RtmDeleteEnumHandle(RtmRegHandle, RouteEnum->DestEnum);
  1299. }
  1300. // Dereference all routes in the enum's snapshot
  1301. for (i = RouteEnum->NextRoute; i < RouteEnum->NumRoutes; i++)
  1302. {
  1303. DEREFERENCE_ROUTE(RouteEnum->RoutesOnDest[i], ENUM_REF);
  1304. }
  1305. // Free memory associated with criteria matching
  1306. if (RouteEnum->CriteriaRoute)
  1307. {
  1308. FreeMemory(RouteEnum->CriteriaRoute);
  1309. }
  1310. // Free memory allocated for the enum's snapshot
  1311. FreeMemory(RouteEnum->RoutesOnDest);
  1312. DeleteCriticalSection(&RouteEnum->EnumLock);
  1313. break;
  1314. case NEXTHOP_ENUM_TYPE:
  1315. DeleteCriticalSection(&((PNEXTHOP_ENUM)Enum)->EnumLock);
  1316. break;
  1317. case LIST_ENUM_TYPE:
  1318. //
  1319. // Remove the enum's marker route from route list
  1320. //
  1321. ACQUIRE_ROUTE_LISTS_WRITE_LOCK(Entity);
  1322. RemoveEntryList(&((PLIST_ENUM)Enum)->MarkerRoute.RouteListLE);
  1323. RELEASE_ROUTE_LISTS_WRITE_LOCK(Entity);
  1324. break;
  1325. default:
  1326. return ERROR_INVALID_HANDLE;
  1327. }
  1328. #if DBG_HDL
  1329. //
  1330. // Remove from the list of handles opened by entity
  1331. //
  1332. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  1333. RemoveEntryList(&Enum->HandlesLE);
  1334. RELEASE_OPEN_HANDLES_LOCK(Entity);
  1335. #endif
  1336. DEREFERENCE_ENTITY(Entity, ENUM_REF);
  1337. // Free the memory allocated for the enum and return
  1338. #if DBG_HDL
  1339. Enum->ObjectHeader.Alloc = FREED;
  1340. #endif
  1341. FreeObject(Enum);
  1342. return NO_ERROR;
  1343. }