309 lines
6.3 KiB
C
309 lines
6.3 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
select.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implements the partial selection of configuration from the
|
||
|
full MM configuration data structures.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <precomp.h>
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|