/*++ Copyright (c) 2000 Microsoft corporation Module Name: select.c Abstract: Implements the partial selection of configuration from the full MM configuration data structures. --*/ #include typedef struct _SELECT_CTXT { ULONG *Subnets; ULONG nSubnets; } SELECT_CTXT, *PSELECT_CTXT; DWORD DeleteScopesCallback( IN OUT PMM_ITERATE_CTXT Ctxt ) { PSELECT_CTXT SelectCtxt = Ctxt->ExtraCtxt; ULONG *Subnets, nSubnets, i; Subnets = SelectCtxt->Subnets; nSubnets = SelectCtxt->nSubnets; for( i = 0; i < nSubnets; i ++ ) { if( Subnets[i] == Ctxt->Scope->Address ) break; } if( i == nSubnets ) { // // Returning KEY_DELETED will cause the IterateScopes // routine to delete this scope out. // return ERROR_KEY_DELETED; } return NO_ERROR; } DWORD OptionCheckForClass( IN OUT PMM_ITERATE_CTXT Ctxt ) { PM_CLASSDEF ClassDef = Ctxt->ExtraCtxt; // // If the class specified in ExtraCtxt matches the current // option's user or vendor class, then bummer -- fail // immediately with error code ERROR_DEVICE_IN_USE to // indicate that this class is needed and can't be deleted // if( Ctxt->UserClass == ClassDef || Ctxt->VendorClass == ClassDef ) { return ERROR_DEVICE_IN_USE; } return NO_ERROR; } DWORD OptionCheckForOptDef( IN OUT PMM_ITERATE_CTXT Ctxt ) { PMM_ITERATE_CTXT OtherCtxt = Ctxt->ExtraCtxt; // // If the current option matches the optdef parameters, then // we need to save the optdef .. // if( Ctxt->VendorClass == OtherCtxt->VendorClass && Ctxt->Option->OptId == OtherCtxt->OptDef->OptId ) { return ERROR_DEVICE_IN_USE; } return NO_ERROR; } DWORD ScopeReservationsCheckForClass( IN OUT PMM_ITERATE_CTXT Ctxt ) { return IterateReservationOptions( Ctxt->Server, Ctxt->Res, Ctxt->ExtraCtxt, OptionCheckForClass ); } DWORD ScopeReservationsCheckForOptDef( IN OUT PMM_ITERATE_CTXT Ctxt ) { return IterateReservationOptions( Ctxt->Server, Ctxt->Res, Ctxt->ExtraCtxt, OptionCheckForOptDef ); } DWORD ScopeCheckForClass( IN OUT PMM_ITERATE_CTXT Ctxt ) { DWORD Error; // // Iterate over each option in the current scope to see if // any of them use the same class // Error = IterateScopeOptions( Ctxt->Scope, Ctxt->ExtraCtxt, OptionCheckForClass ); if( NO_ERROR != Error ) return Error; // // Otherwise iterate for each reservation to see if this is a // problem. // return IterateScopeReservations( Ctxt->Scope, Ctxt->ExtraCtxt, ScopeReservationsCheckForClass ); } DWORD ScopeCheckForOptDef( IN OUT PMM_ITERATE_CTXT Ctxt ) { DWORD Error; // // Iterate over each option in the current scope to see if // any of them use the same class // Error = IterateScopeOptions( Ctxt->Scope, Ctxt->ExtraCtxt, OptionCheckForOptDef ); if( NO_ERROR != Error ) return Error; // // Otherwise iterate for each reservation to see if this is a // problem. // return IterateScopeReservations( Ctxt->Scope, Ctxt->ExtraCtxt, ScopeReservationsCheckForOptDef ); } DWORD DeleteClassesCallback( IN OUT PMM_ITERATE_CTXT Ctxt ) { DWORD Error; // // Go through each subnet to see if there is any option // configured to use this class // Error = IterateScopes( Ctxt->Server, Ctxt->ClassDef, ScopeCheckForClass ); // // If the specified class is in use, then don't // delete. Otherwise delete. // if( ERROR_DEVICE_IN_USE == Error ) return NO_ERROR; if (NO_ERROR == Error ) return ERROR_KEY_DELETED; return Error; } DWORD DeleteOptDefsCallback( IN OUT PMM_ITERATE_CTXT Ctxt ) { DWORD Error; // // Go through each subnet to see if there is any option // configured to use this optdef // Error = IterateScopes( Ctxt->Server, Ctxt, ScopeCheckForOptDef ); // // If the specified class is in use, then don't // delete. Otherwise delete. // if( ERROR_DEVICE_IN_USE == Error ) return NO_ERROR; if (NO_ERROR == Error ) return ERROR_KEY_DELETED; return Error; } DWORD SelectConfiguration( IN OUT PM_SERVER Server, IN ULONG *Subnets, IN ULONG nSubnets ) { SELECT_CTXT Ctxt = { Subnets, nSubnets }; DWORD Error; ULONG i; WCHAR SubnetAddress[30]; // // No selection needed if nSubnets == 0, as this indicates // that the whole configuration is to be used // Tr("SelectConfiguration entered\n"); if( nSubnets == 0 ) return NO_ERROR; // // First go through all scopes and check if all the required // scopes are present // for( i = 0; i < nSubnets ; i ++ ) { PM_SUBNET Subnet; Error = MemServerGetUAddressInfo( Server, Subnets[i], &Subnet, NULL, NULL, NULL ); if( NO_ERROR != Error ) { Tr("Cant find subnet 0x%lx: %ld\n", Subnets[i], Error ); if( ERROR_FILE_NOT_FOUND == Error ) { IpAddressToStringW(Subnets[i], (LPWSTR)SubnetAddress); DhcpEximErrorSubnetNotFound( (LPWSTR)SubnetAddress ); Error = ERROR_CAN_NOT_COMPLETE; } return Error; } } // // Global options are never needed.. so we can delete them. // MemOptClassFree( &Server->Options ); // // Go through all the subnets and delete ones that are // not selected // Error = IterateScopes( Server, &Ctxt, DeleteScopesCallback ); if( NO_ERROR != Error ) { Tr("IterateScopes: %ld\n", Error ); return Error; } // // Now check if all the option-defs are needed // Error = IterateOptDefs( Server, NULL, DeleteOptDefsCallback ); if( NO_ERROR != Error ) { Tr("IterateOptDefs: %ld\n", Error ); return Error; } // // Now check if all the user classes are needed // Error = IterateClasses( Server, NULL, DeleteClassesCallback ); if( NO_ERROR != Error ) { Tr("IterateClasses: %ld\n", Error ); return Error; } return NO_ERROR; }