/*++ Copyright (c) 1997 - 98, Microsoft Corporation Module Name: rtmlist.c Abstract: Contains routines for managing entity-specific list of routes in RTM. Author: Chaitanya Kodeboyina (chaitk) 10-Sep-1998 Revision History: --*/ #include "pchrtm.h" #pragma hdrstop DWORD WINAPI RtmCreateRouteList ( IN RTM_ENTITY_HANDLE RtmRegHandle, OUT PRTM_ROUTE_LIST_HANDLE RouteListHandle ) /*++ Routine Description: Creates a list in which the caller can keep routes owned by it. Arguments: RtmRegHandle - RTM registration handle for calling entity RouteListHandle - Handle to the new route list is returned Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PROUTE_LIST RouteList; VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); // // Create and initialize a new route list // RouteList = (PROUTE_LIST) AllocNZeroObject(sizeof(ROUTE_LIST)); if (RouteList == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } #if DBG_HDL RouteList->ListHeader.ObjectHeader.TypeSign = ROUTE_LIST_ALLOC; RouteList->ListHeader.HandleType = ROUTE_LIST_TYPE; #endif InitializeListHead(&RouteList->ListHead); #if DBG_HDL // // Insert into list of handles opened by entity // ACQUIRE_OPEN_HANDLES_LOCK(Entity); InsertTailList(&Entity->OpenHandles, &RouteList->ListHeader.HandlesLE); RELEASE_OPEN_HANDLES_LOCK(Entity); #endif REFERENCE_ENTITY(Entity, LIST_REF); // // Make a handle to the route list and return // *RouteListHandle = MAKE_HANDLE_FROM_POINTER(RouteList); return NO_ERROR; } DWORD WINAPI RtmInsertInRouteList ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ROUTE_LIST_HANDLE RouteListHandle OPTIONAL, IN UINT NumRoutes, IN PRTM_ROUTE_HANDLE RouteHandles ) /*++ Routine Description: Inserts a set of routes into the route list. If any route is already in another route list, it is removed from this old list in the process. Arguments: RtmRegHandle - RTM registration handle for calling entity RouteListHandle - Handle to the route list into which we are moving the routes to; if this argument is NULL then we are just removing the routes from the route lists to which they belonged NumRoutes - Num. of route handles in the input buffer RouteHandles - Array of handles to insert into the new list Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PROUTE_LIST RouteList; PROUTE_INFO Route; UINT i; VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); RouteList = NULL; if (ARGUMENT_PRESENT(RouteListHandle)) { VALIDATE_ROUTE_LIST_HANDLE(RouteListHandle, &RouteList); } ACQUIRE_ROUTE_LISTS_WRITE_LOCK(Entity); for (i = 0; i < NumRoutes; i++) { Route = ROUTE_FROM_HANDLE(RouteHandles[i]); ASSERT(Route->RouteInfo.RouteOwner == RtmRegHandle); // // Remove from old list if it was present in one // if (!IsListEmpty(&Route->RouteListLE)) { RemoveEntryList(&Route->RouteListLE); DEREFERENCE_ROUTE(Route, LIST_REF); } // // Insert in the new list if a new list is specified // if (RouteList) { InsertTailList(&RouteList->ListHead, &Route->RouteListLE); REFERENCE_ROUTE(Route, LIST_REF); } } RELEASE_ROUTE_LISTS_WRITE_LOCK(Entity); return NO_ERROR; } DWORD WINAPI RtmCreateRouteListEnum ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ROUTE_LIST_HANDLE RouteListHandle, OUT PRTM_ENUM_HANDLE RtmEnumHandle ) /*++ Routine Description: Creates a enumeration on routes in the specified route list. Arguments: RtmRegHandle - RTM registration handle for calling entity, RouteListHandle - Handle to route list whose routes we want, RtmEnumHandle - Handle to this enumeration, which is used in calls to get routes in the route list Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PROUTE_LIST RouteList; PLIST_ENUM Enum; VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); VALIDATE_ROUTE_LIST_HANDLE(RouteListHandle, &RouteList); // // Create and initialize an list enumeration block // Enum = (PLIST_ENUM) AllocNZeroObject(sizeof(LIST_ENUM)); if (Enum == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } #if DBG_HDL Enum->EnumHeader.ObjectHeader.TypeSign = LIST_ENUM_ALLOC; #endif Enum->EnumHeader.HandleType = LIST_ENUM_TYPE; Enum->RouteList = RouteList; // // Insert marker into the route list // ACQUIRE_ROUTE_LISTS_WRITE_LOCK(Entity); InsertHeadList(&RouteList->ListHead, &Enum->MarkerRoute.RouteListLE); RELEASE_ROUTE_LISTS_WRITE_LOCK(Entity); #if DBG_HDL // // Insert into the list of handles opened by entity // ACQUIRE_OPEN_HANDLES_LOCK(Entity); InsertTailList(&Entity->OpenHandles,&Enum->EnumHeader.HandlesLE); RELEASE_OPEN_HANDLES_LOCK(Entity); #endif REFERENCE_ENTITY(Entity, ENUM_REF); // // Make a handle to the enum block and return // *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum); return NO_ERROR; } DWORD WINAPI RtmGetListEnumRoutes ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ENUM_HANDLE EnumHandle, IN OUT PUINT NumRoutes, OUT PRTM_ROUTE_HANDLE RouteHandles ) /*++ Routine Description: Enumerates a set of routes in the route list starting from a specific route (if given) or the start of the route list. Arguments: RtmRegHandle - RTM registration handle for calling entity, EnumHandle - Handle to enumeration on the route list, NumRoutes - Max. number of routes to fill is passed in, Num. of routes actually copied is returned. RouteHandles - Output buffer where route handles are retd. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PLIST_ENUM ListEnum; PROUTE_INFO Route; UINT RoutesInput; PLIST_ENTRY p; RoutesInput = *NumRoutes; *NumRoutes = 0; // // Do some validation checks on the input params // VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); VALIDATE_LIST_ENUM_HANDLE(EnumHandle, &ListEnum); if (RoutesInput > Entity->OwningAddrFamily->MaxHandlesInEnum) { return ERROR_INVALID_PARAMETER; } // // List routes starting from the enum's marker route // ACQUIRE_ROUTE_LISTS_WRITE_LOCK(Entity); for (p = ListEnum->MarkerRoute.RouteListLE.Flink; p != &ListEnum->RouteList->ListHead; p = p->Flink) { if (*NumRoutes >= RoutesInput) { break; } Route = CONTAINING_RECORD(p, ROUTE_INFO, RouteListLE); // // If this route is not a marker route, copy handle // if (Route->RouteInfo.DestHandle) { RouteHandles[(*NumRoutes)++] = MAKE_HANDLE_FROM_POINTER(Route); REFERENCE_ROUTE(Route, HANDLE_REF); } } // // Re-adjust the marker to reflect its new posn // RemoveEntryList(&ListEnum->MarkerRoute.RouteListLE); InsertTailList(p, &ListEnum->MarkerRoute.RouteListLE); RELEASE_ROUTE_LISTS_WRITE_LOCK(Entity); return NO_ERROR; } DWORD WINAPI RtmDeleteRouteList ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ROUTE_LIST_HANDLE RouteListHandle ) /*++ Routine Description: Removes all routes on an entity specific list and frees resources allocated to it. Arguments: RtmRegHandle - RTM registration handle for calling entity, RouteListHandle - Handle to the route list to delete. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PROUTE_LIST RouteList; PLIST_ENUM Enum; PROUTE_INFO Route; PLIST_ENTRY p; VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); VALIDATE_ROUTE_LIST_HANDLE(RouteListHandle, &RouteList); ACQUIRE_ROUTE_LISTS_WRITE_LOCK(Entity); // // Remove each route from the route list // while (!IsListEmpty(&RouteList->ListHead)) { p = RemoveHeadList(&RouteList->ListHead); Route = CONTAINING_RECORD(p, ROUTE_INFO, RouteListLE); if (Route->RouteInfo.DestHandle) { // This is an actual route in the list DEREFERENCE_ROUTE(Route, LIST_REF); } else { // This is a marker route for an enum Enum = CONTAINING_RECORD(Route, LIST_ENUM, MarkerRoute); #if DBG_HDL // // Remove from the list of handles opened by entity // ACQUIRE_OPEN_HANDLES_LOCK(Entity); RemoveEntryList(&Enum->EnumHeader.HandlesLE); RELEASE_OPEN_HANDLES_LOCK(Entity); #endif DEREFERENCE_ENTITY(Entity, ENUM_REF); // Free the memory allocated for the enum and continue #if DBG_HDL Enum->EnumHeader.ObjectHeader.TypeSign = LIST_ENUM_FREED; #endif FreeObject(Enum); } } RELEASE_ROUTE_LISTS_WRITE_LOCK(Entity); #if DBG_HDL // // Remove from the list of handles opened by entity // ACQUIRE_OPEN_HANDLES_LOCK(Entity); RemoveEntryList(&RouteList->ListHeader.HandlesLE); RELEASE_OPEN_HANDLES_LOCK(Entity); #endif DEREFERENCE_ENTITY(Entity, LIST_REF); // Free the memory allocated for the list and return #if DBG_HDL RouteList->ListHeader.ObjectHeader.TypeSign = ROUTE_LIST_FREED; #endif FreeObject(RouteList); return NO_ERROR; }