//================================================================================ // Copyright (C) 1997 Microsoft Corporation // Author: RameshV // Description: This module implements most of the reading part of the ds access //================================================================================ //================================================================================ // headers //================================================================================ #include #include #include #include #include #include // need all the MM stuff... #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // need all the registry stuff #include #include #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 //================================================================================