|
|
//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RameshV
// Description: This implements the init time reading in of the registry
// (this may/may work even when used to read at any other time.. but is not efficient)
//================================================================================
#include <mmregpch.h>
#include <regutil.h>
#include <regsave.h>
#include "server\uniqid.h"
#define InitArray(X) do{DWORD Error = MemArrayInit((X)); Require(ERROR_SUCCESS == Error); }while(0)
#define ERRCHK do{if( ERROR_SUCCESS != Error ) goto Cleanup; }while(0)
#define FreeArray1(X) Error = LoopThruArray((X), DestroyString, NULL, NULL);Require(ERROR_SUCCESS == Error);
#define FreeArray2(X) Error = MemArrayCleanup((X)); Require(ERROR_SUCCESS == Error);
#define FreeArray(X) do{ DWORD Error; FreeArray1(X); FreeArray2(X); }while(0)
#if DBG
#define Report(Who) if(Error) DbgPrint("[DHCPServer] %s: %ld [0x%lx]\n", Who, Error, Error)
#define INVALID_REG DbgPrint
#else
#define Report(Who)
#define INVALID_REG (void)
#endif
typedef DWORD (*ARRAY_FN)(PREG_HANDLE, LPWSTR ArrayString, LPVOID MemObject);
DWORD LoopThruArray( IN PARRAY Array, IN ARRAY_FN ArrayFn, IN PREG_HANDLE Hdl, IN LPVOID MemObject ) { DWORD Error; ARRAY_LOCATION Loc; LPWSTR ArrayString;
Error = MemArrayInitLoc(Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error);
Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&ArrayString); Require(ERROR_SUCCESS == Error && ArrayString);
Error = ArrayFn(Hdl, ArrayString, MemObject); if( ERROR_SUCCESS != Error ) { //
// Operation failed -- but ignore it.
//
// return Error;
}
Error = MemArrayNextLoc(Array, &Loc); }
return ERROR_SUCCESS; }
DWORD DestroyString( IN PREG_HANDLE Unused, IN LPWSTR StringToFree, IN LPVOID Unused2 ) { MemFree(StringToFree); return ERROR_SUCCESS; }
DWORD WStringToAddress( IN LPWSTR Str ) { CHAR IpString[100]; DWORD Count;
Count = wcstombs(IpString, Str, sizeof(IpString)-1); if( -1 == Count ) return 0;
return htonl(inet_addr(IpString)); }
DWORD ConvertWStringToDWORD( IN LPWSTR Str ) { return _wtoi(Str); }
DWORD DhcpRegpSubnetAddServer( IN PREG_HANDLE Hdl, IN LPWSTR ServerName, IN PM_SUBNET Subnet ) { return ERROR_SUCCESS; }
DWORD SetBitForRange( IN PM_RANGE Range, IN DWORD Address ) { BOOL WasSet; if( Address > Range->End || Address < Range->Start ) return ERROR_INVALID_PARAMETER;
return MemBitSetOrClear( Range->BitMask, Address - Range->Start, TRUE, &WasSet ); }
DWORD GlobalWorkingOnOldStyleSubnet = 0; DWORD GlobalWorkingOnPreWin2kMScope = 0; const DWORD One = 0x1;
DWORD DhcpRegFillClusterAddresses( IN OUT PM_RANGE Range, IN LPBYTE InUseClusters, IN DWORD InUseClustersSize, IN LPBYTE UsedClusters, IN DWORD UsedClustersSize ) { DWORD Error; DWORD i; DWORD Address; DWORD UNALIGNED* InUseBits; DWORD UNALIGNED* UsedBits; DWORD nInUseBits; DWORD nUsedBits;
if( InUseClusters && InUseClustersSize ) { nInUseBits = InUseClustersSize/sizeof(DWORD); InUseBits = (DWORD UNALIGNED*)InUseClusters;
Require(nInUseBits == 2*InUseBits[0] + 1 ); nInUseBits --; InUseBits ++;
while(nInUseBits) { for(i = 0; i < sizeof(DWORD)*8; i ++ ) if( InUseBits[1] & ( One << i ) ) SetBitForRange(Range, InUseBits[0] + i ); nInUseBits -= 2; InUseBits += 2; } }
if( UsedClusters && UsedClustersSize ) { nUsedBits = UsedClustersSize/sizeof(DWORD); UsedBits = (DWORD UNALIGNED*)UsedClusters;
Require(nUsedBits == UsedBits[0] + 1); nUsedBits --; UsedBits ++;
while(nUsedBits) { for( i = 0; i < sizeof(DWORD)*8; i ++ ) SetBitForRange(Range, UsedBits[0] + i); UsedBits ++; nUsedBits --; } }
return ERROR_SUCCESS; }
static DWORD Masks[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
DWORD DhcpRegpFillBitsForRange( IN LPBYTE Buffer, IN ULONG BufSize, IN OUT PM_RANGE Range, IN PM_SUBNET Subnet ) { ULONG Size, AllocSize, nSet, Offset; ULONG nBitsSet, Index; ULONG Error;
Size = ntohl(((UNALIGNED DWORD *)Buffer)[0]); AllocSize = ntohl(((UNALIGNED DWORD *)Buffer)[1]); nSet = ntohl(((UNALIGNED DWORD *)Buffer)[2]); Offset = ntohl(((UNALIGNED DWORD *)Buffer)[3]);
//
// do not check for validity of the offset sizes.
// SetBitForRange does this check anyway.
//
// if( Range->Start + Offset + Size > 1+Range->End )
// return ERROR_INVALID_DATA;
Require(nSet != 0); if( nSet == 0 ) return ERROR_SUCCESS; if( nSet == Size ) { Require( AllocSize == 0 ); for( Index = 0; Index < nSet ; Index ++ ) { Error = SetBitForRange(Range, Range->Start + Index); Require( ERROR_SUCCESS == Error ); } return ERROR_SUCCESS; }
if( AllocSize + sizeof(DWORD)*4 != BufSize ) return ERROR_INVALID_DATA;
nBitsSet = 0; Require( Size/8 <= AllocSize ); for( Index = 0; Index < Size ; Index ++ ) { if( Buffer[ 4*sizeof(DWORD) + (Index/8) ] & Masks[Index%8] ) { nBitsSet ++; //
// whistler bug 283457, offset not taken into account
//
Error = SetBitForRange( Range, Range->Start + Index + Offset ); Require( ERROR_SUCCESS == Error ); } }
Require(nBitsSet == nSet); return ERROR_SUCCESS; }
static BYTE TempBuffer[MAX_BIT1SIZE + sizeof(DWORD)*4];
DWORD DhcpRegpFillBitmasks( IN HKEY Key, IN PM_RANGE Range, IN PM_SUBNET Subnet ) { ULONG Error, nValues, Index; WCHAR ValueNameBuf[100]; DWORD ValueNameSize, ValueType; DWORD ValueSize; WCHAR RangeStartStr[30]; BOOL fPostNt5 = FALSE; REG_HANDLE Hdl; if( NULL == Key ) { ConvertAddressToLPWSTR( Range->Start, RangeStartStr); fPostNt5 = TRUE; Error = DhcpRegGetThisServer( &Hdl ); if( NO_ERROR != Error ) return Error; Key = Hdl.Key; } Error = RegQueryInfoKey( Key, NULL, NULL, NULL, NULL, NULL, NULL, &nValues, NULL, NULL, NULL, NULL ); if( ERROR_SUCCESS != Error ) goto Cleanup;
Index = nValues -1; while( nValues ) {
ValueNameSize = sizeof(ValueNameBuf)/sizeof(WCHAR); ValueSize = sizeof(TempBuffer)/sizeof(WCHAR); Error = RegEnumValue( Key, Index, ValueNameBuf, &ValueNameSize, NULL, &ValueType, TempBuffer, &ValueSize ); if( ERROR_SUCCESS != Error ) goto Cleanup;
if( fPostNt5 && 0 != wcsncmp( ValueNameBuf, RangeStartStr, wcslen(RangeStartStr)) ) { //
// Skip irrelevant bitmaps
//
Index --; nValues --; continue; } if( REG_BINARY == ValueType && ValueSize >= sizeof(DWORD)*4 ) { Error = DhcpRegpFillBitsForRange( TempBuffer, ValueSize, Range, Subnet ); if( ERROR_SUCCESS != Error ) { Require(FALSE); goto Cleanup; } }
Index --; nValues --; }
Cleanup:
if( fPostNt5 ) { DhcpRegCloseHdl( &Hdl ); }
return Error; }
DWORD DhcpRegpSubnetAddRange( IN PREG_HANDLE Hdl, IN LPWSTR RangeName, IN PM_SUBNET Subnet ) { DWORD LocalError; DWORD Error; REG_HANDLE Hdl2; LPWSTR Name = NULL; LPWSTR Comment = NULL; DWORD Flags; DWORD StartAddress; DWORD EndAddress; LPBYTE InUseClusters = NULL; DWORD InUseClustersSize; LPBYTE UsedClusters = NULL; DWORD UsedClustersSize; ULONG Alloc, MaxAlloc; PM_RANGE OverlappingRange; PM_RANGE ThisRange = NULL; BOOL fRangeAdded = FALSE; Error = DhcpRegSubnetGetRangeHdl(Hdl, RangeName, &Hdl2); if( ERROR_SUCCESS != Error ) return Error;
Error = DhcpRegRangeGetAttributes( &Hdl2, &Name, &Comment, &Flags, &Alloc, &MaxAlloc, &StartAddress, &EndAddress, &InUseClusters, &InUseClustersSize, &UsedClusters, &UsedClustersSize ); ERRCHK;
if( 0 == StartAddress || 0 == EndAddress ) { INVALID_REG("[DHCPServer] Noticed undefined range: %ws (ignored)\n", RangeName); Error = ERROR_SUCCESS; goto Cleanup; }
if( FALSE == Subnet->fSubnet && GlobalWorkingOnPreWin2kMScope ) { Subnet->MScopeId = StartAddress; GlobalWorkingOnPreWin2kMScope = FALSE; }
Error = MemSubnetAddRange( Subnet, StartAddress, EndAddress, Flags, Alloc, MaxAlloc, &OverlappingRange, INVALID_UNIQ_ID ); ERRCHK;
fRangeAdded = TRUE; Error = MemSubnetGetAddressInfo( Subnet, StartAddress, &ThisRange, NULL, NULL ); ERRCHK;
if( InUseClustersSize || UsedClustersSize ) {
//
// Old style information? Save it as new style
//
GlobalWorkingOnOldStyleSubnet ++; DhcpRegFillClusterAddresses( ThisRange, InUseClusters, InUseClustersSize, UsedClusters, UsedClustersSize ); // this is always returning ERROR_SUCCESS.
//
// Error = FlushRanges(ThisRange, FLUSH_ANYWAY, Subnet);
// Require( ERROR_SUCCESS == Error );
//
// Do not actually write back the stuff to the registry..
// This read code path is used in dhcpexim at which time
// the registry should not be munged..
//
} else {
//
// Need to read new style bitmasks..
//
Error = DhcpRegpFillBitmasks( Hdl2.Key, ThisRange, Subnet ); Require( ERROR_SUCCESS == Error ); }
Cleanup: Report("SubnetAddRange");
if( ERROR_SUCCESS != Error && ThisRange ) { if( !fRangeAdded ) { LocalError = MemRangeCleanup(ThisRange); Require( ERROR_SUCCESS == LocalError ); } else { LocalError = MemSubnetDelRange( Subnet, StartAddress ); Require( ERROR_SUCCESS == LocalError ); } } if( Name ) MemFree(Name); if( Comment ) MemFree(Comment); if( InUseClusters ) MemFree(InUseClusters); if( UsedClusters ) MemFree(UsedClusters);
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError);
return Error; }
DWORD DhcpRegpReservationAddOption( IN PREG_HANDLE Hdl, IN LPWSTR OptionName, IN PM_RESERVATION Reservation ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; DWORD OptionId; LPWSTR ClassName = NULL; LPWSTR VendorName = NULL; DWORD Flags; LPBYTE Value = NULL; DWORD ValueSize; DWORD ClassId; DWORD VendorId; PM_OPTION Option = NULL; PM_OPTION DeletedOption = NULL; PM_CLASSDEF ThisClasDef;
Error = DhcpRegReservationGetOptHdl(Hdl, OptionName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegOptGetAttributes( &Hdl2, &OptionId, &ClassName, &VendorName, &Flags, &Value, &ValueSize ); ERRCHK;
if( OptionId == 0 ) // old registry format does not contain "OptionId" value => it can be taken from the key name.
OptionId = _wtol(OptionName);
if( OptionId == 0 || NULL == Value || 0 == ValueSize ) { INVALID_REG("[DHCPServer] Found invalid option %ws (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; }
if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0; else { PM_SUBNET Subnet = Reservation->SubnetPtr; PM_SERVER Server = Subnet->ServerPtr; Error = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClasDef); if( ERROR_SUCCESS != Error ) { if (*(DWORD *)ClassName != OptionId) // some registry entries were corrupted due to an old bug. Load these entries too (see bug #192933)
{ INVALID_REG("ReservationAddOption(%ws): unknown class (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; } else { ClassId = 0; }
} else { ClassId = ThisClasDef->ClassId; Require(ThisClasDef->IsVendor == FALSE); } }
if( NULL == VendorName || wcslen(VendorName) == 0 ) VendorId = 0; else { PM_SUBNET Subnet = Reservation->SubnetPtr; PM_SERVER Server = Subnet->ServerPtr; Error = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClasDef); if( ERROR_SUCCESS != Error ) { INVALID_REG("ReservationAddOption(%ws): unknown vendor (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; } else { VendorId = ThisClasDef->ClassId; Require(ThisClasDef->IsVendor == TRUE); } }
if( 0 == OptionId ) OptionId = ConvertWStringToDWORD(OptionName);
Error = MemOptInit(&Option, OptionId, ValueSize, Value); ERRCHK;
Error = MemOptClassAddOption( &(Reservation->Options), Option, ClassId, VendorId, &DeletedOption, INVALID_UNIQ_ID ); ERRCHK;
Cleanup: Report("ReservationAddOption");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ClassName ) MemFree(ClassName); if( VendorName ) MemFree(VendorName); if( Value ) MemFree(Value); if( DeletedOption ) { LocalError = MemOptCleanup(DeletedOption); Require(ERROR_SUCCESS == LocalError); } if( ERROR_SUCCESS != Error && Option ) { LocalError = MemOptCleanup(Option); Require(ERROR_SUCCESS == LocalError); } return Error;
}
DWORD DhcpRegpSubnetAddReservation( IN PREG_HANDLE Hdl, IN LPWSTR ReservationName, IN PM_SUBNET Subnet ) { DWORD LocalError; DWORD Error; REG_HANDLE Hdl2; LPWSTR Name = NULL; LPWSTR Comment = NULL; DWORD Flags; DWORD Address; LPBYTE ClientUID = NULL; DWORD ClientUIDSize; PM_RESERVATION ThisReservation; ARRAY Options;
Error = DhcpRegSubnetGetReservationHdl(Hdl, ReservationName, &Hdl2); if( ERROR_SUCCESS != Error ) return Error;
Error = DhcpRegReservationGetAttributes( &Hdl2, &Name, &Comment, &Flags, &Address, &ClientUID, &ClientUIDSize ); ERRCHK;
if( 0 == Address || NULL == ClientUID || 0 == ClientUIDSize ) { INVALID_REG("[DHCPServer] Found invalid reservation %ws (ignored)\n", ReservationName); Error = ERROR_SUCCESS; goto Cleanup; }
Error = MemReserveAdd( &(Subnet->Reservations), Address, Flags, ClientUID, ClientUIDSize, INVALID_UNIQ_ID ); // if the reservation is a duplicate ignore the error and do no further processing as the
// reservation structure was already initialized. The duplicate reservation will simply be
// ignored.
if (ERROR_SUCCESS == Error) { Error = MemReserveFindByAddress( &(Subnet->Reservations), Address, &ThisReservation ); ERRCHK;
ThisReservation->SubnetPtr = Subnet;
Error = MemArrayInit(&Options); ERRCHK;
Error = DhcpRegReservationGetList( &Hdl2, &Options ); ERRCHK;
Error = LoopThruArray(&Options, DhcpRegpReservationAddOption, &Hdl2, ThisReservation);
} else if ( ERROR_OBJECT_ALREADY_EXISTS == Error ) Error = ERROR_SUCCESS;
Cleanup: Report("SubnetAddReservation");
if( Name ) MemFree(Name); if( Comment ) MemFree(Comment); if( ClientUID ) MemFree(ClientUID);
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError);
FreeArray(&Options); return Error; }
DWORD DhcpRegpSubnetAddOption( IN PREG_HANDLE Hdl, IN LPWSTR OptionName, IN PM_SUBNET Subnet ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; DWORD OptionId; LPWSTR ClassName = NULL; LPWSTR VendorName = NULL; DWORD Flags; LPBYTE Value = NULL; DWORD ValueSize; DWORD ClassId; DWORD VendorId; PM_OPTION Option = NULL; PM_OPTION DeletedOption = NULL; PM_CLASSDEF ThisClasDef;
Error = DhcpRegSubnetGetOptHdl(Hdl, OptionName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegOptGetAttributes( &Hdl2, &OptionId, &ClassName, &VendorName, &Flags, &Value, &ValueSize ); ERRCHK;
if( OptionId == 0 ) // old registry format does not contain "OptionId" value => it can be taken from the key name.
OptionId = _wtol(OptionName);
if( OptionId == 0 || NULL == Value || 0 == ValueSize ) { INVALID_REG("[DHCPServer] Found invalid option %ws (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; }
if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0; else { Error = MemServerGetClassDef((PM_SERVER)(Subnet->ServerPtr),0, ClassName,0,NULL,&ThisClasDef); if( ERROR_SUCCESS != Error ) { if (*(DWORD *)ClassName != OptionId) // some registry entries were corrupted due to an old bug. Load these entries too (see bug #192933)
{ INVALID_REG("SubnetAddOption(%ws): unknown class (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; } else { ClassId = 0; } } else { ClassId = ThisClasDef->ClassId; Require(ThisClasDef->IsVendor == FALSE); } } if( NULL == VendorName || wcslen(VendorName) == 0 ) VendorId = 0; else { Error = MemServerGetClassDef((PM_SERVER)(Subnet->ServerPtr),0, VendorName,0,NULL,&ThisClasDef); if( ERROR_SUCCESS != Error ) { INVALID_REG("SubnetAddOption(%ws): unknown class (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; } else { VendorId = ThisClasDef->ClassId; Require(ThisClasDef->IsVendor == TRUE); } } if( 0 == OptionId ) OptionId = ConvertWStringToDWORD(OptionName);
Error = MemOptInit(&Option, OptionId, ValueSize, Value); ERRCHK;
Error = MemOptClassAddOption( &(Subnet->Options), Option, ClassId, VendorId, &DeletedOption, INVALID_UNIQ_ID ); ERRCHK;
Cleanup: Report("Subnet Add Option");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ClassName ) MemFree(ClassName); if( VendorName ) MemFree(VendorName); if( Value ) MemFree(Value); if( DeletedOption ) { LocalError = MemOptCleanup(DeletedOption); Require(ERROR_SUCCESS == LocalError); } if( ERROR_SUCCESS != Error && Option ) { LocalError = MemOptCleanup(Option); Require(ERROR_SUCCESS == LocalError); } return Error;
}
DWORD DhcpRegSubnetAddExclusions( IN PM_SUBNET Subnet, IN LPBYTE Excl, IN DWORD ExclSize ) { DWORD UNALIGNED* Addr; DWORD Count, i, j; DWORD Error; PM_EXCL OverlappingExcl;
Count = ExclSize / sizeof(DWORD); Addr = (DWORD UNALIGNED*)Excl;
if( 0 == Count || 0 == Addr[0] || 0 == Addr[1] ) { INVALID_REG("[DHCPServer] invalid exclusion ignored\n"); return ERROR_SUCCESS; }
Require(Count == 2*Addr[0] + 1); Count --; Addr ++;
while(Count) { Error = MemSubnetAddExcl( Subnet, Addr[0], Addr[1], &OverlappingExcl, INVALID_UNIQ_ID ); if( ERROR_SUCCESS != Error ) { INVALID_REG("[DHCPServer] DhcpRegSubnetAddExclusions:MemSubnetAddExcl;0x%lx\n", Error); } else { if( Subnet->fSubnet && GlobalWorkingOnOldStyleSubnet ) { //
// For subnets alone (not mscopes), check if
// we are upgrading from pre-win2k -- then make sure
// all address from the excluded range are removed
// from the bitmask
//
for( i = Addr[0]; i <= Addr[1]; i ++ ) { MemSubnetReleaseAddress( Subnet, i, FALSE ); } } }
Addr += 2; Count -= 2; } return ERROR_SUCCESS; }
DWORD DhcpRegServerAddSubnet( IN PREG_HANDLE Hdl, IN PM_SERVER Server, IN PM_SUBNET Subnet ) { DWORD Error; DWORD Index; ARRAY Servers; ARRAY IpRanges; ARRAY Reservations; ARRAY Options; LPBYTE Excl = NULL; DWORD ExclSize; struct { PARRAY Array; ARRAY_FN Fn; } Lists[] = { &Servers, DhcpRegpSubnetAddServer, &IpRanges, DhcpRegpSubnetAddRange, &Reservations, DhcpRegpSubnetAddReservation, &Options, DhcpRegpSubnetAddOption };
Subnet->ServerPtr = Server; for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) { InitArray(Lists[Index].Array); }
Error = DhcpRegSubnetGetList( Hdl, &Servers, &IpRanges, &Reservations, &Options, &Excl, &ExclSize );
GlobalWorkingOnOldStyleSubnet = 0; for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) { Error = LoopThruArray(Lists[Index].Array, Lists[Index].Fn, Hdl, Subnet); ERRCHK; }
if( GlobalWorkingOnOldStyleSubnet ) { Report("Old style subnet found, careful with exclusions\n"); } if( Excl ) Error = DhcpRegSubnetAddExclusions(Subnet, Excl, ExclSize); ERRCHK;
Error = Subnet->fSubnet ? MemServerAddSubnet(Server, Subnet, INVALID_UNIQ_ID ) : MemServerAddMScope(Server, Subnet, INVALID_UNIQ_ID );
Cleanup: GlobalWorkingOnOldStyleSubnet = 0; GlobalWorkingOnPreWin2kMScope = 0; Report("ServerAddSubnet");
for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) { FreeArray(Lists[Index].Array); }
return Error; }
DWORD DhcpRegServerAddMScope( IN PREG_HANDLE Hdl, IN PM_SERVER Server, IN PM_MSCOPE MScope ) { return DhcpRegServerAddSubnet(Hdl, Server, MScope); }
DWORD DhcpRegServerAddSScope( IN PREG_HANDLE Hdl, IN PM_SERVER Server, IN PM_SSCOPE SScope ) { DWORD Error; ARRAY Subnets; ARRAY_LOCATION Loc; LPWSTR SubnetWString; DWORD SubnetAddress; PM_SUBNET Subnet;
InitArray(&Subnets);
Error = DhcpRegSScopeGetList(Hdl, &Subnets); ERRCHK;
Error = MemArrayInitLoc(&Subnets, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error);
Error = MemArrayGetElement(&Subnets, &Loc, &SubnetWString); Require(ERROR_SUCCESS == Error && SubnetWString);
SubnetAddress = WStringToAddress(SubnetWString);
Error = MemServerGetAddressInfo( Server, SubnetAddress, &Subnet, NULL, NULL, NULL ); if( ERROR_SUCCESS == Error && Subnet ) { Error = MemSubnetSetSuperScope(Subnet,SScope); Require(ERROR_SUCCESS == Error); }
Error = MemArrayNextLoc(&Subnets, &Loc); } Error = MemServerAddSScope( Server, SScope );
Cleanup: Report("ServerAddSScope");
FreeArray(&Subnets);
return Error; } // DhcpRegpServerAddSScope()
DWORD DhcpRegpServerAddSubnet( IN PREG_HANDLE Hdl, IN LPWSTR SubnetName, IN PM_SERVER Server ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; LPWSTR Name = NULL; LPWSTR Comment = NULL; DWORD Address; DWORD Flags; DWORD Mask; PM_SUBNET Subnet = NULL;
Error = DhcpRegServerGetSubnetHdl(Hdl, SubnetName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegSubnetGetAttributes( &Hdl2, &Name, &Comment, &Flags, &Address, &Mask ); ERRCHK;
if( NULL == Name || 0 == Address || 0 == Mask ) { INVALID_REG("[DHCPServer] invalid subnet %ws ignored\n", SubnetName); Error = ERROR_SUCCESS; goto Cleanup; }
Error = MemSubnetInit( &Subnet, Address, Mask, Flags, 0, Name, Comment ); ERRCHK;
Error = DhcpRegServerAddSubnet(&Hdl2, Server, Subnet);
Cleanup: Report("ServerAddSubnet");
LocalError = DhcpRegCloseHdl(&Hdl2); Require( ERROR_SUCCESS == LocalError); if( Name ) MemFree(Name); if( Comment ) MemFree(Comment);
if( ERROR_SUCCESS != Error ) { if( Subnet ) { LocalError = MemSubnetCleanup(Subnet); Require(ERROR_SUCCESS == LocalError); } } return Error; }
DWORD DhcpRegpServerAddMScope( IN PREG_HANDLE Hdl, IN LPWSTR MScopeName, IN PM_SERVER Server ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; LPWSTR Comment = NULL; DWORD State; DWORD ScopeId; DWORD Policy; PM_MSCOPE MScope = NULL; LPWSTR LangTag = NULL; DWORD TTL = 32; PDATE_TIME ExpiryTime = NULL;
GlobalWorkingOnPreWin2kMScope = 0; Error = DhcpRegServerGetMScopeHdl(Hdl, MScopeName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegMScopeGetAttributes( &Hdl2, &Comment, &State, &ScopeId, &Policy, &TTL, &LangTag, &ExpiryTime ); if( ERROR_INVALID_DATA == Error ) { GlobalWorkingOnPreWin2kMScope = TRUE; //
// hackorama isn't it?
//
Error = NO_ERROR; } ERRCHK;
if( 0 == ScopeId || GlobalWorkingOnPreWin2kMScope ) { INVALID_REG("[DHCPServer] invalid m-scope %ws, id %ld ignored\n", MScopeName, ScopeId); Error = ERROR_SUCCESS; //goto Cleanup;
}
Error = MemMScopeInit( &MScope, ScopeId, State, Policy, (BYTE)TTL, MScopeName, Comment, LangTag, *ExpiryTime ); ERRCHK;
Error = DhcpRegServerAddMScope(&Hdl2, Server, MScope);
Cleanup:
GlobalWorkingOnPreWin2kMScope = 0; Report("Server Add MScope");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( Comment ) MemFree(Comment); if( LangTag ) MemFree(LangTag); if( ExpiryTime ) MemFree(ExpiryTime);
if( ERROR_SUCCESS != Error ) { if( MScope ) { LocalError = MemMScopeCleanup(MScope); Require(ERROR_SUCCESS == Error); } } return Error; }
DWORD DhcpRegpServerAddSScope( IN PREG_HANDLE Hdl, IN LPWSTR SScopeName, IN PM_SERVER Server ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; LPWSTR Name = NULL; LPWSTR Comment = NULL; DWORD Flags; PM_SSCOPE SScope = NULL;
Error = DhcpRegServerGetSScopeHdl(Hdl, SScopeName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
#if 0 // superscope name is given above -- nothing else to be done
Error = DhcpRegSScopeGetAttributes( &Hdl2, &Name, &Description, &Flags ); ERRCHK; #endif
Error = MemSScopeInit( &SScope, 0, SScopeName ); ERRCHK;
Error = DhcpRegServerAddSScope(&Hdl2, Server, SScope);
Cleanup: Report("Server Add Scope");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError);
if( ERROR_SUCCESS != Error ) { if( SScope ) { LocalError = MemSScopeCleanup(SScope); Require(ERROR_SUCCESS == Error); } } return Error; }
DWORD DhcpRegpServerAddOption( IN PREG_HANDLE Hdl, IN LPWSTR OptionName, IN PM_SERVER Server ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; DWORD OptionId; LPWSTR ClassName = NULL; LPWSTR VendorName = NULL; DWORD Flags; LPBYTE Value = NULL; DWORD ValueSize; DWORD ClassId; DWORD VendorId; PM_OPTION Option = NULL; PM_OPTION DeletedOption = NULL; PM_CLASSDEF ThisClasDef;
Error = DhcpRegServerGetOptHdl(Hdl, OptionName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegOptGetAttributes( &Hdl2, &OptionId, &ClassName, &VendorName, &Flags, &Value, &ValueSize ); ERRCHK;
if( OptionId == 0 ) // old registry format does not contain "OptionId" value => it can be taken from the key name.
OptionId = _wtol(OptionName);
if( 0 == OptionId || NULL == Value || 0 == ValueSize ) { INVALID_REG("[DHCPServer] found invalid option %ws (ignored)\n", OptionName ); Error = ERROR_SUCCESS; goto Cleanup; }
if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0; else { Error = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClasDef); if( ERROR_SUCCESS != Error ) { if (*(DWORD *)ClassName != OptionId) // some registry entries were corrupted due to an old bug. Load these entries too (see bug #192933)
{ INVALID_REG("ServerAddOption(%ws): unknown class (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; } else { ClassId = 0; } } else { ClassId = ThisClasDef->ClassId; Require(ThisClasDef->IsVendor == FALSE); } } if( NULL == VendorName || wcslen(VendorName) == 0) VendorId = 0; else { Error = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClasDef); if( ERROR_SUCCESS != Error ) { INVALID_REG("ServerAddOption(%ws): unknown class (ignored)\n", OptionName); Error = ERROR_SUCCESS; goto Cleanup; } else { VendorId = ThisClasDef->ClassId; Require(ThisClasDef->IsVendor == TRUE); } }
Error = MemOptInit(&Option, OptionId, ValueSize, Value); ERRCHK;
Error = MemOptClassAddOption( &(Server->Options), Option, ClassId, VendorId, &DeletedOption, INVALID_UNIQ_ID ); ERRCHK;
Cleanup: Report("Server Add Option");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( ClassName ) MemFree(ClassName); if( VendorName ) MemFree(VendorName); if( Value ) MemFree(Value); if( DeletedOption ) { LocalError = MemOptCleanup(DeletedOption); Require(ERROR_SUCCESS == LocalError); } if( ERROR_SUCCESS != Error && Option ) { LocalError = MemOptCleanup(Option); Require(ERROR_SUCCESS == LocalError); } return Error; }
DWORD DhcpRegpServerAddDefList( IN PREG_HANDLE Hdl, IN LPWSTR DefName, IN PM_SERVER Server ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; LPWSTR Name = NULL; LPWSTR Comments = NULL; DWORD Flags; DWORD OptionId; LPWSTR ClassName = NULL; LPWSTR VendorName = NULL; DWORD ClassId; DWORD VendorId; LPBYTE Value = NULL; DWORD ValueSize; PM_CLASSDEF ThisClassDef;
Error = DhcpRegServerGetOptDefHdl(Hdl, DefName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegOptDefGetAttributes( &Hdl2, &Name, &Comments, &Flags, &OptionId, &ClassName, &VendorName, &Value, &ValueSize ); ERRCHK;
if( OptionId == 0) OptionId = _wtol(DefName);
if( NULL == Name || 0 == OptionId ) { INVALID_REG("[DHCPServer] invalid option def %ws ignored\n", DefName ); Error = ERROR_SUCCESS; goto Cleanup; }
if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0; else { Error = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClassDef); if( ERROR_SUCCESS != Error ) ClassId = 0; else { ClassId = ThisClassDef->ClassId; Require(ThisClassDef->IsVendor == FALSE); } } if( NULL == VendorName || wcslen(VendorName) == 0 ) VendorId = 0; else { Error = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClassDef); if( ERROR_SUCCESS != Error ) VendorId = 0; else { VendorId = ThisClassDef->ClassId; Require(ThisClassDef->IsVendor == TRUE); } }
Error = MemOptClassDefListAddOptDef( &(Server->OptDefs), ClassId, VendorId, OptionId, Flags, Name, Comments, Value, ValueSize, INVALID_UNIQ_ID );
Cleanup: Report("Server Add DefList");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( Name ) MemFree(Name); if( Comments ) MemFree(Comments); if( ClassName ) MemFree(ClassName); if( VendorName ) MemFree(VendorName); if( Value ) MemFree(Value);
return Error; }
DWORD DhcpRegpServerAddClassDef( IN PREG_HANDLE Hdl, IN LPWSTR ClassDefName, IN PM_SERVER Server ) { DWORD Error; DWORD LocalError; REG_HANDLE Hdl2; LPWSTR Name = NULL; LPWSTR Comment = NULL; DWORD Flags; LPBYTE Value = NULL; DWORD ValueSize;
Error = DhcpRegServerGetClassDefHdl(Hdl, ClassDefName, &Hdl2); if(ERROR_SUCCESS != Error) return Error;
Error = DhcpRegClassDefGetAttributes( &Hdl2, &Name, &Comment, &Flags, &Value, &ValueSize ); ERRCHK;
if( NULL == Name || 0 == ValueSize || NULL == Value ) { INVALID_REG("[DHCPServer] invalid class def %ws ignored\n", ClassDefName); Error = ERROR_SUCCESS; goto Cleanup; }
Error = MemClassDefListAddClassDef( &(Server->ClassDefs), MemNewClassId(), Flags, 0, /* no Type... */ Name, Comment, Value, ValueSize, INVALID_UNIQ_ID ); ERRCHK;
Cleanup: Report("Server Add ClassDef");
LocalError = DhcpRegCloseHdl(&Hdl2); Require(ERROR_SUCCESS == LocalError); if( Name ) MemFree(Name); if( Comment ) MemFree(Comment); if( Value ) MemFree(Value); return Error; }
//BeginExport(function)
DWORD DhcpRegReadSubServer( // read all the sub objects of a server and add 'em
IN PREG_HANDLE Hdl, IN OUT PM_SERVER Server ) //EndExport(function)
{ DWORD Error; DWORD Index; ARRAY OptList; ARRAY DefList; ARRAY ClassDefs; ARRAY Subnets; ARRAY MScopes; ARRAY SScopes; struct { PARRAY Array; ARRAY_FN Fn; } Lists[] = { &ClassDefs, DhcpRegpServerAddClassDef, &DefList, DhcpRegpServerAddDefList, &OptList, DhcpRegpServerAddOption, &Subnets, DhcpRegpServerAddSubnet, &MScopes, DhcpRegpServerAddMScope, &SScopes, DhcpRegpServerAddSScope };
for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) { InitArray(Lists[Index].Array); }
Error = DhcpRegServerGetList( Hdl, &OptList, &DefList, &Subnets, &SScopes, &ClassDefs, &MScopes ); ERRCHK;
for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) { Error = LoopThruArray(Lists[Index].Array, Lists[Index].Fn, Hdl, Server); ERRCHK; }
Cleanup:
for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) { FreeArray(Lists[Index].Array); }
Report("ServerAddSubServer");
return Error; }
//BeginExport(function)
DWORD DhcpRegReadServer( // read the server and all its sub objects
IN PREG_HANDLE Hdl, OUT PM_SERVER *Server // return the created object
) //EndExport(function)
{ DWORD Error; LPWSTR Name; LPWSTR Comments; DWORD Flags; PM_SERVER ThisServer;
Name = NULL; Comments = NULL; Flags = 0; ThisServer = NULL;
Error = DhcpRegServerGetAttributes( Hdl, &Name, &Comments, &Flags ); if( ERROR_SUCCESS != Error ) goto Cleanup;
Error = MemServerInit( &ThisServer, 0xFFFFFFFF, Flags, 0, Name, Comments ); if( ERROR_SUCCESS != Error ) goto Cleanup;
Error = DhcpRegReadSubServer(Hdl, ThisServer); if( ERROR_SUCCESS != Error ) goto Cleanup;
*Server = ThisServer;
Cleanup: if( NULL != Name ) MemFree(Name); if( NULL != Comments) MemFree(Comments); if( ERROR_SUCCESS != Error && NULL != ThisServer) { MemServerCleanup(ThisServer); }
return Error; } //BeginExport(function)
DWORD DhcpRegReadThisServer( // recursively read for the current server
OUT PM_SERVER *Server ) //EndExport(function)
{ DWORD Error; REG_HANDLE ThisServer; LPWSTR Name; LPWSTR Comment;
Error = DhcpRegGetThisServer(&ThisServer); if( ERROR_SUCCESS != Error ) return Error;
Error = DhcpRegReadServer(&ThisServer, Server); DhcpRegCloseHdl(&ThisServer);
return Error; }
DWORD DhcpRegReadScopeBitmasks( IN OUT PM_SUBNET Scope ) { PM_RANGE Range; ARRAY_LOCATION Loc; DWORD Error; WCHAR SubnetStr[sizeof("000.000.000.000")]; REG_HANDLE Hdl, Hdl1;
Error = MemArrayInitLoc( &Scope->Ranges, &Loc); while( NO_ERROR == Error ) { Error = MemArrayGetElement( &Scope->Ranges, &Loc, &Range ); Require( NO_ERROR == Error && NULL != Range );
//
// Fill in the range
//
Error = DhcpRegpFillBitmasks( NULL, Range, Scope ); ASSERT( NO_ERROR == Error ); Error = MemArrayNextLoc( &Scope->Ranges, &Loc ); }
if( ERROR_FILE_NOT_FOUND != Error ) return Error; return NO_ERROR; }
//BeginExport(function)
DWORD DhcpRegReadServerBitmasks( IN OUT PM_SERVER Server ) // EndExport(function)
{ PM_SUBNET Scope, MScope; ARRAY_LOCATION Loc; DWORD Error; Error = MemArrayInitLoc(&Server->Subnets, &Loc); while( NO_ERROR == Error ) { Error = MemArrayGetElement( &Server->Subnets, &Loc, &Scope); Require( NO_ERROR == Error && NULL != Scope );
//
// get the keys to the scope in question
//
Error = DhcpRegReadScopeBitmasks(Scope); if( NO_ERROR != Error ) return Error; Error = MemArrayNextLoc( &Server->Subnets, &Loc ); }
if( ERROR_FILE_NOT_FOUND != Error ) return Error;
Error = MemArrayInitLoc(&Server->MScopes, &Loc); while( NO_ERROR == Error ) { Require( ERROR_SUCCESS == Error );
Error = MemArrayGetElement( &Server->MScopes, &Loc, &MScope); Require( NO_ERROR == Error && NULL != MScope );
//
// get the keys to the scope in question
//
Error = DhcpRegReadScopeBitmasks(MScope); if( NO_ERROR != Error ) return Error;
Error = MemArrayNextLoc( &Server->MScopes, &Loc ); }
if( ERROR_FILE_NOT_FOUND != Error ) return Error; return NO_ERROR; }
//================================================================================
// end of file
//================================================================================
|