|
|
//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RameshV
// Description: This module implements most of the reading part of the ds access
//================================================================================
//================================================================================
// headers
//================================================================================
#include <hdrmacro.h>
#include <store.h>
#include <dhcpmsg.h>
#include <wchar.h>
#include <dhcpbas.h>
#include <mm\opt.h> // need all the MM stuff...
#include <mm\optl.h>
#include <mm\optdefl.h>
#include <mm\optclass.h>
#include <mm\classdefl.h>
#include <mm\bitmask.h>
#include <mm\reserve.h>
#include <mm\range.h>
#include <mm\subnet.h>
#include <mm\sscope.h>
#include <mm\oclassdl.h>
#include <mm\server.h>
#include <mm\address.h>
#include <mm\server2.h>
#include <mm\memfree.h>
#include <mmreg\regutil.h> // need all the registry stuff
#include <mmreg\regread.h>
#include <mmreg\regsave.h>
#define DONT_USE_PARENT (0)
//================================================================================
// misc helper functions
//================================================================================
VOID ArrayMemFree( // free each ptr of the array using MemFree
IN OUT PARRAY Array ) { DWORD Result; ARRAY_LOCATION Loc; LPVOID Ptr;
Result = MemArrayInitLoc(Array, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(Array, &Loc, &Ptr); //- ERROR_SUCCESS == Result
if( Ptr ) MemFree(Ptr); Result = MemArrayNextLoc(Array, &Loc); }
MemArrayCleanup(Array); }
//================================================================================
// exported functions and helpers
//================================================================================
DWORD CheckoutAlternateOptions( IN OUT LPSTORE_HANDLE hContainer, IN PARRAY AltAttribs, IN OUT PARRAY OptDefAttribs, IN OUT PARRAY OptAttribs );
DWORD CheckoutAlternateOptions1( IN OUT LPSTORE_HANDLE hContainer, IN PEATTRIB ThisAttrib, IN OUT PARRAY OptDefAttribs, IN OUT PARRAY OptAttribs ) { DWORD Result; STORE_HANDLE hStore; ARRAY AlternateOptAttribs;
if( !IS_ADSPATH_PRESENT(ThisAttrib) ) return ERROR_SUCCESS;
Result = StoreGetHandle( /* hStore */ hContainer, /* Reserved */ DDS_RESERVED_DWORD, /* StoreGetType */ ThisAttrib->StoreGetType, /* Path */ ThisAttrib->ADsPath, /* hStoreOut */ &hStore ); if( ERROR_DS_NO_SUCH_OBJECT == Result ) return ERROR_SUCCESS; if( ERROR_SUCCESS != Result ) return Result;
MemArrayInit(&AlternateOptAttribs); Result = DhcpDsGetLists( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ &hStore, /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
/* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti */ OptDefAttribs, /* OptionsLocation */ &AlternateOptAttribs, /* Options */ OptAttribs, /* Classes */ NULL );
CheckoutAlternateOptions(hContainer, &AlternateOptAttribs, OptDefAttribs, OptAttribs);
StoreCleanupHandle(&hStore, DDS_RESERVED_DWORD ); ArrayMemFree(&AlternateOptAttribs);
return ERROR_SUCCESS; }
DWORD CheckoutAlternateOptions( IN OUT LPSTORE_HANDLE hContainer, IN PARRAY AltAttribs, IN OUT PARRAY OptDefAttribs, IN OUT PARRAY OptAttribs ) { DWORD Result; DWORD LastError; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(AltAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(AltAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
Result = CheckoutAlternateOptions1(hContainer,ThisAttrib, OptDefAttribs, OptAttribs); if( ERROR_SUCCESS != Result ) LastError = Result; Result = MemArrayNextLoc(AltAttribs, &Loc); }
return LastError; }
DWORD DhcpOptClassAddOption( IN OUT PM_SERVER Server, IN OUT PM_OPTCLASS OptClass, IN PEATTRIB Option ) { DWORD Result; LPWSTR ClassName; LPWSTR VendorName; DWORD OptionId, Flags; DWORD ValueSize; DWORD ClassId; DWORD VendorId; LPBYTE Value; PM_OPTION NewOption, DeletedOption; PM_CLASSDEF ThisClassDef;
if( !IS_BINARY1_PRESENT(Option) || !IS_DWORD1_PRESENT(Option) ) return ERROR_INVALID_DATA;
if( IS_STRING4_PRESENT(Option) ) ClassName = Option->String4; else ClassName = NULL;
if( IS_STRING3_PRESENT(Option) ) VendorName = Option->String3; else VendorName = NULL;
OptionId = Option->Dword1; if( IS_FLAGS1_PRESENT(Option) ) Flags = Option->Flags1; else Flags = 0; Value = Option->Binary1; ValueSize = Option->BinLen1;
if( NULL == ClassName ) ClassId = 0; else { Result = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClassDef); if( ERROR_SUCCESS != Result ) { // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", ClassName);
ClassId =0; } else { ClassId = ThisClassDef->ClassId; //- ThisClassDef->IsVendor == FALSE
} }
if( NULL == VendorName ) VendorId = 0; else { Result = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClassDef); if( ERROR_SUCCESS != Result ) { // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", VendorName);
VendorId =0; } else { VendorId = ThisClassDef->ClassId; //- ThisClassDef->IsVendor == TRUE
} }
Result = MemOptInit(&NewOption, OptionId, ValueSize, Value); if( ERROR_SUCCESS != Result ) return Result;
DeletedOption = NULL; Result = MemOptClassAddOption(OptClass, NewOption, ClassId , VendorId, &DeletedOption);
if( ERROR_SUCCESS != Result ) { MemOptCleanup(NewOption); } if( DeletedOption ) { MemOptCleanup(DeletedOption); }
return Result; }
DWORD DhcpOptClassAddOptions( IN OUT PM_SERVER Server, IN OUT PM_OPTCLASS OptClass, IN PARRAY OptAttribs ) { DWORD Result, LastError; ARRAY_LOCATION Loc; PEATTRIB ThisOpt;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(OptAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(OptAttribs, &Loc, &ThisOpt); //- ERROR_SUCCESS == Result && ThisOpt
Result = DhcpOptClassAddOption(Server, OptClass,ThisOpt); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = MemArrayNextLoc(OptAttribs, &Loc); } return LastError; }
DWORD FirstAddress( IN PARRAY Attribs ) { ARRAY_LOCATION Loc; DWORD Result; PEATTRIB ThisAttrib;
Result = MemArrayInitLoc(Attribs, &Loc); if( ERROR_SUCCESS != Result ) return 0; Result = MemArrayGetElement(Attribs, &Loc, &ThisAttrib); if( ERROR_SUCCESS != Result ) return 0;
if( IS_ADDRESS1_PRESENT(ThisAttrib) ) return ThisAttrib->Address1; return 0; }
//================================================================================
// operations on the server or global object ONLY
//================================================================================
DWORD DhcpServerAddClass( IN OUT PM_SERVER Server, IN PEATTRIB Class ) { DWORD Result; DWORD Flags; DWORD ValueSize; LPBYTE Value; LPWSTR Name; LPWSTR Comment;
if( !IS_STRING1_PRESENT(Class) || !IS_BINARY1_PRESENT(Class) ) return ERROR_INVALID_PARAMETER;
Name = Class->String1; if( IS_STRING2_PRESENT(Class) ) Comment = Class->String2; else Comment = NULL;
if( IS_FLAGS1_PRESENT(Class) ) Flags = Class->Flags1; else Flags = 0;
Value = Class->Binary1; ValueSize = Class->BinLen1;
Result = MemClassDefListAddClassDef( &(Server->ClassDefs), MemNewClassId(), Flags, 0, /* dont care about type */ Name, Comment, Value, ValueSize );
return Result; }
DWORD DhcpServerAddClasses( IN OUT PM_SERVER Server, IN PARRAY ClassAttribs ) { DWORD Result; DWORD LastError; ARRAY_LOCATION Loc; PEATTRIB ThisClass;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(ClassAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(ClassAttribs, &Loc, &ThisClass); //- ERROR_SUCCESS == Result && NULL != ThisC;as
Result = DhcpServerAddClass(Server, ThisClass ); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = MemArrayNextLoc(ClassAttribs, &Loc); } return LastError; }
DWORD DhcpServerAddOptDef( IN OUT PM_SERVER Server, IN PEATTRIB OptDef ) { DWORD Result; LPWSTR Name,Comment,ClassName, VendorName; DWORD OptionId, Flags; DWORD ValueSize; DWORD ClassId, VendorId; LPBYTE Value; PM_CLASSDEF ThisClassDef;
if( !IS_STRING1_PRESENT(OptDef) || !IS_BINARY1_PRESENT(OptDef) || !IS_DWORD1_PRESENT(OptDef) ) return ERROR_INVALID_DATA;
Name = OptDef->String1; if( IS_STRING2_PRESENT(OptDef) ) Comment = OptDef->String2; else Comment = NULL;
if( IS_STRING4_PRESENT(OptDef) ) ClassName = OptDef->String4; else ClassName = NULL;
if( IS_STRING3_PRESENT(OptDef) ) VendorName = OptDef->String3; else VendorName = NULL;
OptionId = OptDef->Dword1;
if( IS_FLAGS1_PRESENT(OptDef) ) Flags = OptDef->Flags1; else Flags = 0;
Value = OptDef->Binary1; ValueSize = OptDef->BinLen1;
if( NULL == ClassName ) ClassId = 0; else { Result = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClassDef); if( ERROR_SUCCESS != Result ) { // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", ClassName);
ClassId =0; } else { ClassId = ThisClassDef->ClassId; //- ThisClassDef->IsVendor == FALSE
} }
if( NULL == VendorName ) VendorId = 0; else { Result = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClassDef); if( ERROR_SUCCESS != Result ) { // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", VendorName);
VendorId =0; } else { VendorId = ThisClassDef->ClassId; //- ThisClassDef->IsVendor == TRUE
} }
return MemOptClassDefListAddOptDef( &(Server->OptDefs), ClassId, VendorId, OptionId, Flags, Name, Comment, Value, ValueSize ); }
DWORD DhcpServerAddOptionDefs( IN OUT PM_SERVER Server, IN PARRAY OptDefAttribs ) { DWORD Result; DWORD LastError; ARRAY_LOCATION Loc; PEATTRIB ThisOptDef;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(OptDefAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(OptDefAttribs, &Loc, &ThisOptDef); //- ERROR_SUCCESS == Result && NULL != ThisOptDef
Result = DhcpServerAddOptDef(Server, ThisOptDef ); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = MemArrayNextLoc(OptDefAttribs, &Loc); } return LastError; }
DWORD DhcpServerAddOptions( IN OUT PM_SERVER Server, IN PARRAY OptAttribs ) { return DhcpOptClassAddOptions( Server, &Server->Options, OptAttribs ); }
DWORD DhcpSubnetAddOptions( IN OUT PM_SERVER Server, IN OUT PM_SUBNET Subnet, IN PARRAY OptAttribs ) { return DhcpOptClassAddOptions( Server, &Subnet->Options, OptAttribs ); }
DWORD DhcpSubnetAddRanges( IN OUT PM_SUBNET Subnet, IN PARRAY RangeAttribs ) { DWORD Result, LastError; DWORD Type; ARRAY_LOCATION Loc; PEATTRIB ThisRange; PM_RANGE OverlappingRange; PM_EXCL OverlappingExcl; ULONG State, BootpAllocated, MaxBootpAllocated;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(RangeAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(RangeAttribs, &Loc, &ThisRange); //- ERROR_SUCCESS == Result && NULL != ThisRange
if( !IS_ADDRESS1_PRESENT(ThisRange) || !IS_ADDRESS2_PRESENT(ThisRange) || !IS_FLAGS1_PRESENT(ThisRange) ) LastError = ERROR_INVALID_DATA; else { OverlappingRange = NULL; OverlappingExcl = NULL; if( IS_FLAGS2_PRESENT(ThisRange) ) Type = ThisRange->Flags2; else Type = RANGE_TYPE_RANGE; BootpAllocated = IS_DWORD1_PRESENT(ThisRange)? ThisRange->Dword1 : 0; MaxBootpAllocated = IS_DWORD2_PRESENT(ThisRange) ? ThisRange->Dword2 : ~0;
if( (Type & RANGE_TYPE_MASK) == RANGE_TYPE_RANGE ) { Result = MemSubnetAddRange( Subnet, ThisRange->Address1, ThisRange->Address2, ThisRange->Flags1, BootpAllocated, MaxBootpAllocated, &OverlappingRange ); if( ERROR_SUCCESS != Result || OverlappingRange ) LastError = Result; } else { Result = MemSubnetAddExcl( Subnet, ThisRange->Address1, ThisRange->Address2, &OverlappingExcl ); if( ERROR_SUCCESS != Result || OverlappingExcl ) LastError = Result; } } Result = MemArrayNextLoc(RangeAttribs, &Loc); }
return LastError; }
DWORD DhcpSubnetAddSuperScopes( IN OUT PM_SERVER Server, IN OUT PM_SUBNET Subnet, IN PARRAY SuperScopeAttribs ) { DWORD Result; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib; PM_SSCOPE SScope;
Result = MemArrayInitLoc(SuperScopeAttribs, &Loc); if( ERROR_SUCCESS != Result ) return ERROR_SUCCESS;
Result = MemArrayGetElement(SuperScopeAttribs, &Loc, &ThisAttrib); if( ERROR_SUCCESS != Result ) return Result;
if( !IS_STRING1_PRESENT(ThisAttrib) ) return ERROR_INVALID_DATA;
Result = MemServerFindSScope( Server, 0xFFFFFFFF, // invalid scope id ==> use scope name for search
ThisAttrib->String1, &SScope ); if( ERROR_FILE_NOT_FOUND != Result ) { if( ERROR_SUCCESS != Result ) return Result; Result = MemSubnetSetSuperScope(Subnet, SScope); return Result; }
Result = MemSScopeInit( &SScope, IS_FLAGS2_PRESENT(ThisAttrib)?ThisAttrib->Flags2:0, ThisAttrib->String1 ); if( ERROR_SUCCESS != Result ) return Result;
Result = MemServerAddSScope( Server, SScope ); if( ERROR_SUCCESS != Result ) { MemSScopeCleanup(SScope); }
return Result; }
DWORD DhcpSubnetAddReservation( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hSubnet, IN OUT PM_SERVER Server, IN OUT PM_SUBNET Subnet, IN PEATTRIB ReservationAttrib ) { DWORD Result; DWORD Address, State; DWORD nBytes; LPBYTE ClientUID; ARRAY Options; PM_RESERVATION Res1;
if( !IS_ADDRESS1_PRESENT(ReservationAttrib) || !IS_FLAGS1_PRESENT(ReservationAttrib) || !IS_BINARY1_PRESENT(ReservationAttrib) ) return ERROR_SUCCESS;
Address = ReservationAttrib->Address1; State = ReservationAttrib->Flags1; ClientUID = ReservationAttrib->Binary1; nBytes = ReservationAttrib->BinLen1;
Result = MemReserveAdd( &Subnet->Reservations, Address, State, ClientUID, nBytes ); if( ERROR_SUCCESS != Result ) return Result;
if( !IS_ADSPATH_PRESENT(ReservationAttrib) ) return ERROR_SUCCESS;
Result = MemReserveFindByAddress( &Subnet->Reservations, Address, &Res1 ); if( ERROR_SUCCESS != Result ) return ERROR_DDS_UNEXPECTED_ERROR;
MemArrayInit(&Options); Result = CheckoutAlternateOptions1( hContainer, ReservationAttrib, NULL, &Options ); //Ignore Result
if( 0 == MemArraySize(&Options) ) Result = ERROR_SUCCESS; else Result = DhcpOptClassAddOptions( Server, &Res1->Options, &Options ); ArrayMemFree(&Options);
return Result; }
DWORD DhcpSubnetAddReservations( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hSubnet, IN OUT PM_SERVER Server, IN OUT PM_SUBNET Subnet, IN PARRAY ReservationAttribs ) { DWORD Result, LastError; ARRAY_LOCATION Loc; PEATTRIB ThisReservation;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(ReservationAttribs, &Loc); while(ERROR_FILE_NOT_FOUND != Result ) { //= ERROR_SUCCESS == Result
Result = MemArrayGetElement(ReservationAttribs, &Loc, &ThisReservation); //- ERROR_SUCCESS == Result && NULL != ThisReservation
Result = DhcpSubnetAddReservation(hContainer, hDhcpRoot, hSubnet, Server, Subnet, ThisReservation); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = MemArrayNextLoc(ReservationAttribs, &Loc); } return LastError; }
DWORD DhcpServerFillSubnet( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hSubnet, IN OUT PM_SERVER Server, IN OUT PM_SUBNET Subnet ) { DWORD Result, LastError; ARRAY RangeAttribs; ARRAY ReservationAttribs; ARRAY AddressAttribs; ARRAY SuperScopeAttribs; ARRAY OptDefAttribs; ARRAY AlternateOptAttribs; ARRAY OptAttribs; ARRAY ClassAttribs;
MemArrayInit(&RangeAttribs); MemArrayInit(&ReservationAttribs); MemArrayInit(&SuperScopeAttribs); MemArrayInit(&AlternateOptAttribs); MemArrayInit(&OptAttribs); Result = DhcpDsGetLists( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hSubnet, /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
/* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ &RangeAttribs, /* Sites */ NULL, /* Reservations */ &ReservationAttribs, /* SuperScopes */ &SuperScopeAttribs, /* OptionDescripti */ NULL, /* OptionsLocation */ &AlternateOptAttribs, /* Options */ &OptAttribs, /* Classes */ NULL ); // Ignore Result
Result = CheckoutAlternateOptions( hContainer, &AlternateOptAttribs, NULL, &OptAttribs ); // Ignore Result
ArrayMemFree(&AlternateOptAttribs); LastError = ERROR_SUCCESS; Result = DhcpSubnetAddOptions( Server, Subnet, &OptAttribs ); ArrayMemFree(&OptAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = DhcpSubnetAddRanges( Subnet, &RangeAttribs ); ArrayMemFree(&RangeAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
if( DONT_USE_PARENT ) { // we are not peeking at SubnetAttrib, so do this..
Result = DhcpSubnetAddSuperScopes( Server, Subnet, &SuperScopeAttribs ); ArrayMemFree(&SuperScopeAttribs); if( ERROR_SUCCESS != Result ) LastError = Result; } else { ArrayMemFree(&SuperScopeAttribs); }
Result = DhcpSubnetAddReservations( hContainer, hDhcpRoot, hSubnet, Server, Subnet, &ReservationAttribs ); ArrayMemFree(&ReservationAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
return LastError; }
DWORD DhcpServerGetSubnet( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hSubnet, IN OUT PM_SERVER Server, IN PEATTRIB SubnetAttrib, IN PM_SUBNET *Subnet ) { DWORD Result; DWORD FoundParams; DWORD Type; DWORD Address, Mask, State, Policy, SScopeId; LPWSTR Name, Comment; LARGE_INTEGER Flags; ARRAY AddressAttribs, MaskAttribs; PM_SSCOPE SScope;
if( DONT_USE_PARENT ) { // get state frm server obj or root obj?
FoundParams = 0; Type = 0; Name = NULL; Comment = NULL; Result = DhcpDsGetAttribs( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hSubnet, /* FoundParams */ &FoundParams, /* UniqueKey */ NULL, /* Type */ &Type, /* Flags */ &Flags, /* Name */ &Name, /* Description */ &Comment, /* Location */ NULL, /* MScopeId */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
if( !DhcpCheckParams(FoundParams, 3) ) { State = Policy = 0; } else { State = Flags.LowPart; Policy = Flags.HighPart; } } else { if( IS_FLAGS1_PRESENT(SubnetAttrib) ) { State = SubnetAttrib->Flags1; } else State = 0; if( IS_FLAGS2_PRESENT(SubnetAttrib) ) { Policy = SubnetAttrib->Flags2; } else Policy = 0; Name = SubnetAttrib->String1; if( IS_STRING2_PRESENT(SubnetAttrib) ) { Comment = SubnetAttrib->String2; } else Comment = NULL; }
if( DONT_USE_PARENT ) { // get info from subnet obj, not server
MemArrayInit(&AddressAttribs); MemArrayInit(&MaskAttribs); Result = DhcpDsGetLists( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hSubnet, /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
/* Servers */ NULL, /* Subnets */ NULL, /* IpAddress */ &AddressAttribs, /* Mask */ &MaskAttribs, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti */ NULL, /* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL );
Address = FirstAddress(&AddressAttribs); Mask = FirstAddress(&MaskAttribs); ArrayMemFree(&AddressAttribs); ArrayMemFree(&MaskAttribs); } else { // get info frm the subnet attrib
Address = SubnetAttrib->Address1; Mask = SubnetAttrib->Address2; }
SScope = NULL; if( !DONT_USE_PARENT ) do { // if we can peek into SubnetAttrib
if( !IS_STRING3_PRESENT(SubnetAttrib) ) { // does this have a superscope name?
SScopeId = 0; // nope, so SScopeId is zero
break; // also, quit from here..
} Result = MemServerFindSScope( // first see if the superscope already exists
Server, 0xFFFFFFFF, SubnetAttrib->String3, &SScope ); if( ERROR_SUCCESS== Result ) { // got it.
SScopeId = SScope->SScopeId; break; // superscope set.. dont need to worry
} if( ERROR_FILE_NOT_FOUND != Result ) { // something seriously wrong?
return Result; // cant go on
}
//= NULL == SScope
Result = MemSScopeInit( // try to create a new super scope
&SScope, 0, SubnetAttrib->String3 ); if( ERROR_SUCCESS != Result ) { // hmm.. should not go wrong at all?
return Result; }
Result = MemServerAddSScope( // now add it to the server
Server, SScope ); if( ERROR_SUCCESS != Result ) { // oh boy, not again
MemSScopeCleanup(SScope); return Result; }
SScopeId = SScope->SScopeId; // finally got the superscope
} while(0); // not really a loop.. just a programming trick
Result = MemSubnetInit( /* pSubnet */ Subnet, /* Address */ Address, /* Mask */ Mask, /* State */ State, /* SuperScopeId */ DONT_USE_PARENT ? 0 : SScopeId, /* Name */ Name, /* Description */ Comment );
if( DONT_USE_PARENT ) { // need to free Name and Comment
if( Name ) MemFree(Name); if( Comment ) MemFree(Comment); }
if( ERROR_SUCCESS != Result ) return Result;
Result = DhcpServerFillSubnet( hContainer, hDhcpRoot, hSubnet, Server, *Subnet );
if( ERROR_SUCCESS != Result ) { MemSubnetFree(*Subnet); *Subnet = NULL; }
return Result; }
DWORD DhcpServerAddSubnet( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hServer, IN OUT PM_SERVER Server, IN PEATTRIB SubnetAttrib ) { DWORD Result; STORE_HANDLE hStore; PM_SUBNET NewSubnet;
if( !IS_STRING1_PRESENT(SubnetAttrib) || // no subnet name
!IS_ADDRESS1_PRESENT(SubnetAttrib) || // no subnet address
!IS_ADDRESS2_PRESENT(SubnetAttrib) ) { // no subnet mask
return ERROR_SUCCESS; //= ds inconsistent
}
if( !IS_STOREGETTYPE_PRESENT(SubnetAttrib) ) { return ERROR_SUCCESS; // this is just a dummy here for no reason at all
}
Result = StoreGetHandle( /* hStore */ hContainer, /* Reserved */ DDS_RESERVED_DWORD, /* StoreGetType */ SubnetAttrib->StoreGetType, /* Path */ SubnetAttrib->ADsPath, /* hStoreOut */ &hStore ); if( ERROR_DS_NO_SUCH_OBJECT == Result ) return ERROR_SUCCESS; if( ERROR_SUCCESS != Result ) return Result;
NewSubnet = NULL; Result = DhcpServerGetSubnet( hContainer, hDhcpRoot, &hStore, Server, SubnetAttrib, &NewSubnet ); StoreCleanupHandle(&hStore, DDS_RESERVED_DWORD);
if( ERROR_SUCCESS != Result ) return Result; Result = MemServerAddSubnet(Server, NewSubnet); if( ERROR_SUCCESS != Result ) MemSubnetFree(NewSubnet); return Result; }
DWORD DhcpServerAddSubnets( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hServer, IN OUT PM_SERVER Server, IN PARRAY SubnetAttribs ) { DWORD Result, LastError; ARRAY_LOCATION Loc; PEATTRIB ThisAttrib;
LastError = ERROR_SUCCESS; Result = MemArrayInitLoc(SubnetAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(SubnetAttribs, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result
Result = DhcpServerAddSubnet( hContainer, hDhcpRoot, hServer, Server, ThisAttrib ); if( ERROR_SUCCESS != Result ) LastError = Result; Result = MemArrayNextLoc(SubnetAttribs, &Loc); } return LastError; }
DWORD DhcpFillServer( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hServer, IN OUT PM_SERVER Server ) { DWORD Result, LastError; DWORD Address; ARRAY SubnetAttribs; ARRAY AddressAttribs; ARRAY SuperScopeAttribs; ARRAY OptDefAttribs; ARRAY AlternateOptAttribs; ARRAY OptAttribs; ARRAY ClassAttribs;
MemArrayInit(&SubnetAttribs); MemArrayInit(&AddressAttribs); MemArrayInit(&SuperScopeAttribs); MemArrayInit(&OptDefAttribs); MemArrayInit(&AlternateOptAttribs); MemArrayInit(&OptAttribs); MemArrayInit(&ClassAttribs); Result = DhcpDsGetLists( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
/* Servers */ NULL, /* Subnets */ &SubnetAttribs, /* IpAddress */ &AddressAttribs, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, // &SuperScopeAttribs,
/* OptionDescripti */ &OptDefAttribs, /* OptionsLocation */ &AlternateOptAttribs, /* Options */ &OptAttribs, /* Classes */ &ClassAttribs ); // Ignore Result
Result = CheckoutAlternateOptions( hContainer, &AlternateOptAttribs, &OptDefAttribs, &OptAttribs ); // Ignore Result
ArrayMemFree(&AlternateOptAttribs); LastError = ERROR_SUCCESS; Result = DhcpServerAddClasses( Server, &ClassAttribs ); ArrayMemFree(&ClassAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = DhcpServerAddOptionDefs( Server, &OptDefAttribs ); ArrayMemFree(&OptDefAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = DhcpServerAddOptions( Server, &OptAttribs ); ArrayMemFree(&OptAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
Result = DhcpServerAddSubnets( hContainer, hDhcpRoot, hServer, Server, &SubnetAttribs ); ArrayMemFree(&SubnetAttribs); if( ERROR_SUCCESS != Result ) LastError = Result;
ArrayMemFree(&SuperScopeAttribs);
Server->Address = FirstAddress(&AddressAttribs); ArrayMemFree(&AddressAttribs);
return LastError; }
DWORD DhcpGetServer( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT LPSTORE_HANDLE hServer, IN PEATTRIB ServerAttrib, OUT PM_SERVER *Server ) { DWORD Result; DWORD FoundParams; DWORD Type; DWORD State, Policy; LPWSTR Name, Comment; LARGE_INTEGER Flags;
if( DONT_USE_PARENT ) { // get state frm server obj or root obj?
FoundParams = 0; Type = 0; Name = NULL; Comment = NULL; Result = DhcpDsGetAttribs( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hServer, /* FoundParams */ &FoundParams, /* UniqueKey */ NULL, /* Type */ &Type, /* Flags */ &Flags, /* Name */ &Name, /* Description */ &Comment, /* Location */ NULL, /* MScopeId */ NULL ); if( ERROR_SUCCESS != Result ) return Result;
if( !DhcpCheckParams(FoundParams, 3) ) { State = Policy = 0; } else { State = Flags.LowPart; Policy = Flags.HighPart; } } else { if( IS_FLAGS1_PRESENT(ServerAttrib) ) { State = ServerAttrib->Flags1; } else State = 0; if( IS_FLAGS2_PRESENT(ServerAttrib) ) { Policy = ServerAttrib->Flags2; } else Policy = 0; Name = ServerAttrib->String1; if( IS_STRING2_PRESENT(ServerAttrib) ) { Comment = ServerAttrib->String2; } else Comment = NULL; }
Result = MemServerInit( /* Server */ Server, /* Address */ 0, // Address gets filled in DhcpFillServer
/* State */ State, /* Policy */ Policy, /* Name */ Name, /* Comment */ Comment );
if( DONT_USE_PARENT ) { // Name and Comment were allocated..
if( Name ) MemFree(Name); if( Comment ) MemFree(Comment); }
if( ERROR_SUCCESS != Result ) return Result;
Result = DhcpFillServer( hContainer, hDhcpRoot, hServer, *Server ); if( ERROR_SUCCESS != Result ) { MemServerFree(*Server); *Server = NULL; }
return Result; }
BOOL _inline AddressFoundInHostent( IN DHCP_IP_ADDRESS AddrToSearch, // Host-Order addr
IN HOSTENT *ServerEntry // entry to search for..
) { ULONG nAddresses, ThisAddress;
if( NULL == ServerEntry ) return FALSE; // no address to search in
nAddresses = 0; // have a host entry to compare for addresses
while( ServerEntry->h_addr_list[nAddresses] ) { ThisAddress = ntohl(*(DHCP_IP_ADDRESS*)ServerEntry->h_addr_list[nAddresses++] ); if( ThisAddress == AddrToSearch ) { return TRUE; // yeah address matched.
} }
return FALSE; }
DWORD static DhcpAddServer( IN OUT LPSTORE_HANDLE hContainer, IN OUT LPSTORE_HANDLE hDhcpRoot, IN OUT PARRAY Servers, IN PEATTRIB ServerAttrib, IN HOSTENT *ServerEntry ) { DWORD Result, ServerAddress, State, Policy; STORE_HANDLE hStore; PM_SERVER NewServer; ARRAY_LOCATION Loc;
if( !IS_STOREGETTYPE_PRESENT(ServerAttrib) ) return ERROR_SUCCESS; // empty server... just there for other reasons
if( !IS_ADDRESS1_PRESENT(ServerAttrib) ) { return ERROR_SUCCESS; // invalid attribute?
}
for( Result = MemArrayInitLoc(Servers, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // search if we've added this before!
Result = MemArrayNextLoc(Servers, &Loc) ) { //- ERROR_SUCCESS == Result
Result = MemArrayGetElement(Servers, &Loc, (LPVOID*)&NewServer); //- ERROR_SUCCESS == Result
if( 0 == wcscmp(NewServer->Name, ServerAttrib->String1) ) { return ERROR_SUCCESS; // server already added
}
if( AddressFoundInHostent(NewServer->Address, ServerEntry) ) { return ERROR_SUCCESS; // server already added
}
//
// A better check would be to see if the server object was loaded before..
// by looking at the location... welll.. This should be done soon.
//
}
ServerAddress = ServerAttrib->Address1; if( !IS_FLAGS1_PRESENT(ServerAttrib)) State = 0; else State = ServerAttrib->Flags1;
if( !IS_FLAGS2_PRESENT(ServerAttrib)) Policy = 0; else State = ServerAttrib->Flags2;
Result = StoreGetHandle( /* hStore */ hContainer, /* Reserved */ DDS_RESERVED_DWORD, /* StoreGetType */ ServerAttrib->StoreGetType, /* Path */ ServerAttrib->ADsPath, /* hStoreOut */ &hStore ); if( ERROR_DS_NO_SUCH_OBJECT == Result ) return ERROR_DDS_DHCP_SERVER_NOT_FOUND; if( ERROR_SUCCESS != Result ) return Result;
NewServer = NULL; Result = DhcpGetServer( hContainer, hDhcpRoot, &hStore, ServerAttrib, &NewServer ); StoreCleanupHandle(&hStore, DDS_RESERVED_DWORD);
if( ERROR_SUCCESS != Result ) return Result;
NewServer->Address = ServerAddress; NewServer->State = State; NewServer->Policy = Policy;
Result = MemArrayAddElement(Servers, NewServer);
if( ERROR_SUCCESS != Result ) MemServerFree(NewServer); return Result; }
BOOL _inline FoundServer( // does this attrib belong to given server?
IN PEATTRIB ServerAttrib, IN LPWSTR ServerName, IN HOSTENT *ServerEntry ) { ULONG nAddresses; DHCP_IP_ADDRESS ThisAddress;
if( NULL == ServerName ) return TRUE;
do { // not a loop
if( !IS_STRING1_PRESENT(ServerAttrib) ) break ; // could not even find any name!
if( NULL != ServerAttrib->String1 && 0 == wcscmp(ServerName, ServerAttrib->String1) ) return TRUE; // ok, the names match
} while(0);
if( IS_ADDRESS1_PRESENT(ServerAttrib) ) { // this MUST be TRUEEEE
if( AddressFoundInHostent(ServerAttrib->Address1, ServerEntry) ) { return TRUE; // yes, there was a match
} }
return FALSE; // nope, this server is not what we're lookin for
}
//BeginExport(function)
DWORD DhcpDsGetServers( IN OUT LPSTORE_HANDLE hContainer, // the container handle
IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object
IN DWORD Reserved, IN LPWSTR ServerName, // OPTIONAL, NULL ==> All servers
IN OUT PARRAY Servers // fill in this array with PM_SERVER types
) //EndExport(function)
{ ARRAY ServerAttribs; ARRAY_LOCATION Loc; DWORD Result; DWORD LastError; PEATTRIB ThisAttrib; BOOL GotOneServerAtleast; HOSTENT *ServerEntry;
if( NULL == hContainer || NULL == hContainer->ADSIHandle ) return ERROR_INVALID_PARAMETER; if( NULL == hDhcpRoot || NULL == hDhcpRoot->ADSIHandle ) return ERROR_INVALID_PARAMETER; if( 0 != Reserved || NULL == Servers ) return ERROR_INVALID_PARAMETER;
MemArrayInit(&ServerAttribs); Result = DhcpDsGetLists( /* Reserved */ DDS_RESERVED_DWORD, /* hStore */ hDhcpRoot, /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
/* Servers */ &ServerAttribs, /* Subnets */ NULL, /* IpAddress */ NULL, /* Mask */ NULL, /* Ranges */ NULL, /* Sites */ NULL, /* Reservations */ NULL, /* SuperScopes */ NULL, /* OptionDescripti */ NULL, // need to do global options, classes etc
/* OptionsLocation */ NULL, /* Options */ NULL, /* Classes */ NULL ); if( 0 == MemArraySize(&ServerAttribs) ) { if( ERROR_SUCCESS != Result ) return Result; return ERROR_DDS_DHCP_SERVER_NOT_FOUND; }
GotOneServerAtleast = FALSE; LastError = ERROR_DDS_DHCP_SERVER_NOT_FOUND; if( NULL == ServerName ) { ServerEntry = NULL; } else { CHAR TmpBuf[300]; wcstombs(TmpBuf, ServerName, sizeof(TmpBuf)-1); TmpBuf[sizeof(TmpBuf)-1] = '\0'; ServerEntry = gethostbyname(TmpBuf); }
Result = MemArrayInitLoc(&ServerAttribs, &Loc); while( ERROR_FILE_NOT_FOUND != Result ) { //- (ERROR_SUCCESS == Result )
Result = MemArrayGetElement(&ServerAttribs, &Loc, (LPVOID*)&ThisAttrib); if( ERROR_SUCCESS != Result ) { //- FALSE
break; }
if( FoundServer(ThisAttrib, ServerName, ServerEntry) ) { Result = DhcpAddServer(hContainer, hDhcpRoot, Servers, ThisAttrib, ServerEntry); if( ERROR_SUCCESS != Result ) LastError = Result; else GotOneServerAtleast = TRUE; }
MemFree(ThisAttrib); Result = MemArrayNextLoc(&ServerAttribs, &Loc); }
if( GotOneServerAtleast ) return ERROR_SUCCESS; return LastError; }
//BeginExport(function)
DWORD DhcpDsGetEnterpriseServers( // get the dhcp servers for the current enterprise
IN DWORD Reserved, IN LPWSTR ServerName, IN OUT PARRAY Servers ) //EndExport(function)
{ DWORD Result; STORE_HANDLE hRoot; STORE_HANDLE hDhcpRoot; STORE_HANDLE hContainer;
Result = StoreInitHandle( /* hStore */ &hRoot, /* Reserved */ DDS_RESERVED_DWORD, /* ThisDomain */ NULL, /* UserName */ NULL, /* Password */ NULL, /* AuthFlags */ ADS_SECURE_AUTHENTICATION ); if( ERROR_SUCCESS != Result ) return ERROR_DDS_NO_DS_AVAILABLE;
Result = DhcpDsGetRoot( /* Flags */ DDS_FLAGS_CREATE, /* hStoreCC */ &hRoot, /* hStoreDhcpRoot */ &hDhcpRoot ); if( ERROR_SUCCESS != Result ) { StoreCleanupHandle(&hRoot, DDS_RESERVED_DWORD); return Result; }
Result = StoreGetHandle( /* hStore */ &hRoot, /* Reserved */ DDS_RESERVED_DWORD, /* StoreGetType */ StoreGetChildType, /* Path */ DHCP_ROOT_OBJECT_PARENT_LOC, /* hStoreOut */ &hContainer ); StoreCleanupHandle(&hRoot, DDS_RESERVED_DWORD);
if( ERROR_SUCCESS != Result ) { StoreCleanupHandle(&hRoot, DDS_RESERVED_DWORD); return ERROR_DDS_UNEXPECTED_ERROR; }
Result = DhcpDsGetServers( /* hContainer */ &hContainer, /* hDhcpRoot */ &hDhcpRoot, /* Reserved */ DDS_RESERVED_DWORD, /* ServerName */ ServerName, /* Servers */ Servers );
StoreCleanupHandle(&hContainer, DDS_RESERVED_DWORD); StoreCleanupHandle(&hDhcpRoot, DDS_RESERVED_DWORD);
return Result; }
//================================================================================
// end of file
//================================================================================
|