937 lines
26 KiB
C
937 lines
26 KiB
C
|
//================================================================================
|
||
|
// Copyright (c) 1997 Microsoft Corporation
|
||
|
// Author: RameshV
|
||
|
// Description: this file deals with the part that keeps the registry bitmask in
|
||
|
// sync. the way, this is done is by keeping a count in each RANGE object to
|
||
|
// count the # of operations that have been performed on it.. if it crosses
|
||
|
// a threshold, it is saved to registry..
|
||
|
//================================================================================
|
||
|
|
||
|
//#include <dhcpsrv.h>
|
||
|
#include <mmregpch.h>
|
||
|
#include <regutil.h>
|
||
|
#include <regsave.h>
|
||
|
|
||
|
extern CRITICAL_SECTION DhcpGlobalInProgressCritSect;
|
||
|
extern CRITICAL_SECTION DhcpGlobalMemoryCritSect;
|
||
|
|
||
|
#define LOCK_MEMORY() EnterCriticalSection(&DhcpGlobalMemoryCritSect)
|
||
|
#define UNLOCK_MEMORY() LeaveCriticalSection(&DhcpGlobalMemoryCritSect)
|
||
|
#define LOCK_INPROGRESS_LIST() EnterCriticalSection(&DhcpGlobalInProgressCritSect)
|
||
|
#define UNLOCK_INPROGRESS_LIST() LeaveCriticalSection(&DhcpGlobalInProgressCritSect)
|
||
|
|
||
|
#define DIRT_THRESHOLD 10 // flush every 10 addresses
|
||
|
|
||
|
//BeginExport(defines)
|
||
|
#define FLUSH_MODIFIED_DIRTY 0
|
||
|
#define FLUSH_MODIFIED 1
|
||
|
#define FLUSH_ANYWAY 2
|
||
|
//EndExport(defines)
|
||
|
|
||
|
DWORD
|
||
|
FlushCheckLoop(
|
||
|
IN PARRAY ArrayToLoopThru,
|
||
|
IN DWORD (*Iterator)(LPVOID Element, DWORD FlushNow, LPVOID Context),
|
||
|
IN DWORD FlushNow,
|
||
|
IN LPVOID Context
|
||
|
)
|
||
|
{
|
||
|
DWORD LastFailure;
|
||
|
DWORD Error;
|
||
|
ARRAY_LOCATION Loc;
|
||
|
LPVOID Element;
|
||
|
|
||
|
LastFailure = ERROR_SUCCESS;
|
||
|
Error = MemArrayInitLoc(ArrayToLoopThru, &Loc);
|
||
|
while(ERROR_FILE_NOT_FOUND != Error ) {
|
||
|
Require(ERROR_SUCCESS == Error);
|
||
|
|
||
|
Error = MemArrayGetElement(ArrayToLoopThru, &Loc, &Element);
|
||
|
Require(ERROR_SUCCESS == Error && NULL != Element);
|
||
|
|
||
|
Error = Iterator(Element, FlushNow, Context);
|
||
|
Require(ERROR_SUCCESS == Error);
|
||
|
if( ERROR_SUCCESS != Error ) LastFailure = Error;
|
||
|
|
||
|
Error = MemArrayNextLoc(ArrayToLoopThru, &Loc);
|
||
|
}
|
||
|
|
||
|
return LastFailure;
|
||
|
}
|
||
|
|
||
|
BOOL _inline
|
||
|
SpecialValues(
|
||
|
IN LPWSTR ValueName
|
||
|
)
|
||
|
{
|
||
|
return (0 == wcscmp(ValueName, REG_RANGE_START_ADDRESS) ||
|
||
|
0 == wcscmp(ValueName, REG_RANGE_END_ADDRESS) ||
|
||
|
0 == wcscmp(ValueName, REG_FLAGS) ||
|
||
|
0 == wcscmp(ValueName, REG_SUBNET_EXCL) ||
|
||
|
0 == wcscmp(ValueName, REG_SUBNET_SWITCHED_FLAG) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_NAME) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_COMMENT) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_SCOPEID) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_STATE) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_ADDR_POLICY) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_TTL) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_LANG_TAG) ||
|
||
|
0 == wcscmp(ValueName, REG_MSCOPE_EXPIRY_TIME)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
typedef struct _FLSH_BITS_CTXT {
|
||
|
REG_HANDLE *Hdl;
|
||
|
PM_SUBNET Subnet;
|
||
|
PM_RANGE Range;
|
||
|
LONG Index;
|
||
|
} FLSH_BITS_CTXT, *LPFLSH_BITS_CTXT;
|
||
|
|
||
|
static
|
||
|
BYTE TempBuffer[MAX_BIT1SIZE + sizeof(DWORD)*4];
|
||
|
|
||
|
DWORD
|
||
|
FlushBitmask(
|
||
|
IN PM_BITMASK1 Bits1,
|
||
|
IN DWORD FlushNow,
|
||
|
IN LPVOID FlushCtxt
|
||
|
)
|
||
|
{
|
||
|
LPFLSH_BITS_CTXT Ctxt = FlushCtxt;
|
||
|
HKEY Key = Ctxt->Hdl->Key;
|
||
|
WCHAR BitsValueName[REG_RANGE_BITS_PREFIX_WCHAR_COUNT+57];
|
||
|
LONG Count, Index = (Ctxt->Index++);
|
||
|
ULONG WriteSize = 4*sizeof(DWORD), Tmp;
|
||
|
DWORD Error;
|
||
|
LPWSTR TmpStr;
|
||
|
|
||
|
if( FLUSH_ANYWAY != FlushNow && 0 == Bits1->nDirtyOps ) {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
Bits1->nDirtyOps = 0;
|
||
|
|
||
|
ZeroMemory( BitsValueName, sizeof(BitsValueName));
|
||
|
ConvertAddressToLPWSTR(Ctxt->Range->Start, BitsValueName);
|
||
|
wcscat(BitsValueName, L" ");
|
||
|
wcscat(BitsValueName, REG_RANGE_BITS_PREFIX);
|
||
|
TmpStr = &BitsValueName[wcslen(BitsValueName)];
|
||
|
for( Count = 5; Count >= 0; Count -- ) {
|
||
|
TmpStr[Count] = (WCHAR)(L'0' + (Index%10)); Index/= 10;
|
||
|
}
|
||
|
TmpStr[6] = L'\0';
|
||
|
|
||
|
if( 0 == Bits1->nSet ) {
|
||
|
|
||
|
//
|
||
|
// If no bit is set, we don't have to write this to registry -- just need to REMOVE value..
|
||
|
//
|
||
|
|
||
|
Error = RegDeleteValue(Key, (LPWSTR)BitsValueName);
|
||
|
if( ERROR_FILE_NOT_FOUND == Error || ERROR_PATH_NOT_FOUND == Error ) {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// compose TempBuffer -- note that this whole func is serialized, so we can use
|
||
|
// TempBuffer safely..
|
||
|
//
|
||
|
|
||
|
Tmp = htonl(Bits1->Size); memcpy(&TempBuffer[0*sizeof(DWORD)], &Tmp, sizeof(DWORD));
|
||
|
if( Bits1->Size == Bits1->nSet ) {
|
||
|
Require(Bits1->Mask == NULL);
|
||
|
Tmp = 0;
|
||
|
} else Tmp = htonl(Bits1->AllocSize);
|
||
|
memcpy(&TempBuffer[1*sizeof(DWORD)], &Tmp, sizeof(DWORD));
|
||
|
Tmp = htonl(Bits1->nSet); memcpy(&TempBuffer[2*sizeof(DWORD)], &Tmp, sizeof(DWORD));
|
||
|
Tmp = htonl(Bits1->Offset); memcpy(&TempBuffer[3*sizeof(DWORD)], &Tmp, sizeof(DWORD));
|
||
|
if( Bits1->Mask ) {
|
||
|
memcpy(&TempBuffer[4*sizeof(DWORD)], Bits1->Mask, Bits1->AllocSize);
|
||
|
WriteSize += Bits1->AllocSize;
|
||
|
}
|
||
|
|
||
|
return RegSetValueEx(
|
||
|
Key,
|
||
|
(LPWSTR)BitsValueName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
TempBuffer,
|
||
|
WriteSize
|
||
|
);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegClearupRangeValues(
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN PM_RANGE Range
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine clears up all values for a given Range (this can be
|
||
|
specified via a single Key for the range, or via the Range/Subnet
|
||
|
object pair) excepting "StartAddress", "EndAddress" and "Flags".
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Key INVALID_HANDLE_VALUE if range is specified
|
||
|
via Range, Subnet pair. Else Range key in registry.
|
||
|
|
||
|
Subnet Subnet object if Key is not speificed.
|
||
|
|
||
|
Range Range object if key is not specified.
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
Win32 errors (registry) or ERROR_SUCCESS on success.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG Error, nValues, Index;
|
||
|
REG_HANDLE Hdl;
|
||
|
HKEY UseKey;
|
||
|
WCHAR ValueNameBuf[100], RangeStr[50];
|
||
|
DWORD ValueNameSize, ValueType;
|
||
|
|
||
|
Error = DhcpRegGetThisServer( &Hdl );
|
||
|
if( NO_ERROR != Error ) return Error;
|
||
|
|
||
|
ZeroMemory( RangeStr, sizeof(RangeStr));
|
||
|
ConvertAddressToLPWSTR( Range->Start, RangeStr );
|
||
|
|
||
|
UseKey = Hdl.Key;
|
||
|
|
||
|
do {
|
||
|
Error = RegQueryInfoKey(
|
||
|
UseKey, NULL, NULL, NULL, NULL, NULL, NULL, &nValues, NULL, NULL, NULL, NULL
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Error ) break;
|
||
|
|
||
|
Index = nValues -1;
|
||
|
while( nValues ) {
|
||
|
|
||
|
ValueNameSize = sizeof(ValueNameBuf)/sizeof(WCHAR);
|
||
|
Error = RegEnumValue(
|
||
|
UseKey,
|
||
|
Index,
|
||
|
(LPWSTR)ValueNameBuf,
|
||
|
&ValueNameSize,
|
||
|
NULL,
|
||
|
&ValueType,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Error ) break;
|
||
|
|
||
|
if( 0 == wcsncmp( ValueNameBuf, RangeStr,
|
||
|
wcslen(RangeStr) ) ) {
|
||
|
RegDeleteValue(UseKey, (LPWSTR)ValueNameBuf);
|
||
|
}
|
||
|
|
||
|
Index --;
|
||
|
nValues --;
|
||
|
}
|
||
|
|
||
|
} while ( 0 );
|
||
|
|
||
|
DhcpRegCloseHdl(&Hdl);
|
||
|
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
|
||
|
// This function is ALSO CALLED FROM REGREAD.C while reading in a subnet info..
|
||
|
|
||
|
//BeginExport(function)
|
||
|
DWORD
|
||
|
FlushRanges(
|
||
|
IN PM_RANGE Range,
|
||
|
IN DWORD FlushNow,
|
||
|
IN PM_SUBNET Subnet
|
||
|
) //EndExport(function)
|
||
|
{
|
||
|
DWORD Error;
|
||
|
REG_HANDLE Hdl;
|
||
|
PM_BITMASK BitMask;
|
||
|
FLSH_BITS_CTXT Ctxt = { &Hdl, Subnet, Range, 0};
|
||
|
|
||
|
if( (FLUSH_ANYWAY != FlushNow && 0 == Range->DirtyOps) ||
|
||
|
(FLUSH_MODIFIED_DIRTY == FlushNow && Range->DirtyOps < DIRT_THRESHOLD ) ) {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
Error = DhcpRegGetThisServer( &Hdl );
|
||
|
if( NO_ERROR != Error ) return Error;
|
||
|
|
||
|
//
|
||
|
// Lock is needed to serialize access to memory -- shouldn't be allocating addresses
|
||
|
// while we're planning to save it to registry..
|
||
|
//
|
||
|
|
||
|
LOCK_INPROGRESS_LIST();
|
||
|
LOCK_MEMORY();
|
||
|
|
||
|
Range->DirtyOps = 0;
|
||
|
BitMask = Range->BitMask;
|
||
|
|
||
|
if( FLUSH_ANYWAY == FlushNow ) {
|
||
|
DhcpRegClearupRangeValues(Subnet, Range);
|
||
|
}
|
||
|
|
||
|
Error = FlushCheckLoop(&BitMask->Array, FlushBitmask, FlushNow, &Ctxt );
|
||
|
|
||
|
DhcpRegCloseHdl( &Hdl );
|
||
|
|
||
|
UNLOCK_MEMORY();
|
||
|
UNLOCK_INPROGRESS_LIST();
|
||
|
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
FlushSubnets(
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN DWORD FlushNow,
|
||
|
IN LPVOID Context_UNUSED
|
||
|
)
|
||
|
{
|
||
|
ULONG Error;
|
||
|
|
||
|
Error = FlushCheckLoop(&Subnet->Ranges, FlushRanges, FlushNow, Subnet);
|
||
|
Require( ERROR_SUCCESS == Error );
|
||
|
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
//BeginExport(function)
|
||
|
DWORD
|
||
|
DhcpRegServerFlush(
|
||
|
IN PM_SERVER Server,
|
||
|
IN DWORD FlushNow
|
||
|
) //EndExport(function)
|
||
|
{
|
||
|
DWORD Error;
|
||
|
|
||
|
Error = FlushCheckLoop(&Server->Subnets, FlushSubnets, FlushNow, NULL);
|
||
|
Require(ERROR_SUCCESS == Error);
|
||
|
Error = FlushCheckLoop(&Server->MScopes, FlushSubnets, FlushNow, NULL);
|
||
|
Require(ERROR_SUCCESS == Error);
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
//BeginExport(function)
|
||
|
DWORD
|
||
|
DhcpRegFlushServer(
|
||
|
IN DWORD FlushNow
|
||
|
) //EndExport(function)
|
||
|
{
|
||
|
PM_SERVER Server;
|
||
|
DWORD Error;
|
||
|
PM_SERVER DhcpGetCurrentServer(VOID);
|
||
|
|
||
|
Server = DhcpGetCurrentServer();
|
||
|
|
||
|
Error = FlushCheckLoop(&Server->Subnets, FlushSubnets, FlushNow, NULL);
|
||
|
Require(ERROR_SUCCESS == Error);
|
||
|
Error = FlushCheckLoop(&Server->MScopes, FlushSubnets, FlushNow, NULL);
|
||
|
Require(ERROR_SUCCESS == Error);
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
//================================================================================
|
||
|
// ds support routines -- flush a full server to disk
|
||
|
//================================================================================
|
||
|
|
||
|
DWORD
|
||
|
SaveArray(
|
||
|
IN PARRAY Array,
|
||
|
IN DWORD (*Func)(LPVOID, LPVOID, LPVOID),
|
||
|
IN LPVOID Arg2,
|
||
|
IN LPVOID Arg3
|
||
|
)
|
||
|
{
|
||
|
ARRAY_LOCATION Loc;
|
||
|
DWORD Result;
|
||
|
LPVOID ThisPtr;
|
||
|
|
||
|
Result = MemArrayInitLoc(Array, &Loc);
|
||
|
while(ERROR_FILE_NOT_FOUND != Result ) {
|
||
|
Result = MemArrayGetElement(Array, &Loc, &ThisPtr);
|
||
|
Require(ERROR_SUCCESS == Result && NULL != ThisPtr );
|
||
|
|
||
|
Result = Func(ThisPtr, Arg2, Arg3);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = MemArrayNextLoc(Array, &Loc);
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveOptList(
|
||
|
IN PM_ONECLASS_OPTLIST OptClassOptList,
|
||
|
IN LPVOID Arg1,
|
||
|
IN LPVOID Arg2
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
DWORD ClassId;
|
||
|
DWORD VendorId;
|
||
|
LPWSTR ClassName;
|
||
|
LPWSTR VendorName;
|
||
|
PM_OPTLIST OptList;
|
||
|
PM_SERVER Server;
|
||
|
PM_SUBNET Subnet;
|
||
|
PM_RESERVATION Reservation;
|
||
|
PM_SSCOPE SScope;
|
||
|
PM_OPTION Option;
|
||
|
PM_CLASSDEF ClassDef;
|
||
|
ARRAY_LOCATION Loc;
|
||
|
|
||
|
ClassId = OptClassOptList->ClassId;
|
||
|
VendorId = OptClassOptList->VendorId;
|
||
|
OptList = &OptClassOptList->OptList;
|
||
|
|
||
|
if( NULL != Arg1 && NULL != Arg2 ) { // reservations
|
||
|
Reservation = Arg1; Subnet = Arg2;
|
||
|
Server = Subnet->ServerPtr;
|
||
|
} else if( NULL == Arg2 ) { // subnet options
|
||
|
Reservation = NULL; Subnet = Arg1;
|
||
|
Server = Subnet->ServerPtr;
|
||
|
} else if( NULL == Arg1 ) { // global options
|
||
|
Reservation = NULL; Subnet = NULL;
|
||
|
Server = Arg2;
|
||
|
} else { // enterprise options?
|
||
|
return ERROR_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
Result = MemServerGetClassDef( // get the vendor name first
|
||
|
Server,
|
||
|
VendorId,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
&ClassDef
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) {
|
||
|
VendorName = NULL;
|
||
|
} else {
|
||
|
VendorName = ClassDef->Name;
|
||
|
Require(ClassDef->IsVendor == TRUE);
|
||
|
}
|
||
|
|
||
|
Result = MemServerGetClassDef( // get the class name for this class
|
||
|
Server,
|
||
|
ClassId,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
&ClassDef
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) {
|
||
|
ClassName = NULL;
|
||
|
} else {
|
||
|
ClassName = ClassDef->Name;
|
||
|
Require(ClassDef->IsVendor == FALSE);
|
||
|
}
|
||
|
|
||
|
Result = MemArrayInitLoc(OptList, &Loc);
|
||
|
while( ERROR_FILE_NOT_FOUND != Result ) {
|
||
|
//- ERROR_SUCCESS == Result
|
||
|
Result = MemArrayGetElement(OptList, &Loc, &Option);
|
||
|
//- ERROR_SUCCESS == Result && NULL != Option
|
||
|
if( NULL != Reservation ) { // save reservation options
|
||
|
Result = DhcpRegSaveReservedOption(
|
||
|
Subnet->Address,
|
||
|
Reservation->Address,
|
||
|
Option->OptId,
|
||
|
ClassName,
|
||
|
VendorName,
|
||
|
Option->Val,
|
||
|
Option->Len
|
||
|
);
|
||
|
} else if( NULL != Subnet ) { // save subnet optinos
|
||
|
Result = DhcpRegSaveSubnetOption(
|
||
|
Subnet,
|
||
|
Option->OptId,
|
||
|
ClassName,
|
||
|
VendorName,
|
||
|
Option->Val,
|
||
|
Option->Len
|
||
|
);
|
||
|
} else if( NULL != Server ) { // save global options
|
||
|
Result = DhcpRegSaveGlobalOption(
|
||
|
Option->OptId,
|
||
|
ClassName,
|
||
|
VendorName,
|
||
|
Option->Val,
|
||
|
Option->Len
|
||
|
);
|
||
|
} else { // save enterprise wide optinos
|
||
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||
|
}
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = MemArrayNextLoc(OptList, &Loc);
|
||
|
}
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveReservationOptions(
|
||
|
IN PM_OPTCLASS OptClass,
|
||
|
IN PM_RESERVATION Reservation,
|
||
|
IN PM_SUBNET Subnet
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
ARRAY_LOCATION Loc;
|
||
|
|
||
|
return SaveArray(&OptClass->Array, DhcpRegSaveOptList, Reservation, Subnet);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveSubnetOptions(
|
||
|
IN PM_OPTCLASS OptClass,
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return SaveArray(&OptClass->Array, DhcpRegSaveOptList, Subnet, NULL);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveGlobalOptions(
|
||
|
IN PM_OPTCLASS OptClass,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return SaveArray(&OptClass->Array, DhcpRegSaveOptList, NULL, Server);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveOptDefList(
|
||
|
IN PM_OPTCLASSDEFL_ONE OClassDefL,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
DWORD ClassId;
|
||
|
DWORD VendorId;
|
||
|
LPWSTR ClassName;
|
||
|
LPWSTR VendorName;
|
||
|
PM_OPTDEFLIST OptDefList;
|
||
|
PM_OPTDEF OptDef;
|
||
|
PM_CLASSDEF ClassDef;
|
||
|
ARRAY_LOCATION Loc;
|
||
|
|
||
|
ClassId = OClassDefL->ClassId;
|
||
|
VendorId = OClassDefL->VendorId;
|
||
|
OptDefList = &OClassDefL->OptDefList;
|
||
|
|
||
|
Result = MemServerGetClassDef( // first find the vendor name
|
||
|
Server,
|
||
|
VendorId,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
&ClassDef
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) {
|
||
|
VendorName = NULL;
|
||
|
} else {
|
||
|
VendorName = ClassDef->Name;
|
||
|
Require(ClassDef->IsVendor == TRUE);
|
||
|
}
|
||
|
|
||
|
Result = MemServerGetClassDef( // now find the class name
|
||
|
Server,
|
||
|
ClassId,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
&ClassDef
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) {
|
||
|
ClassName = NULL;
|
||
|
} else {
|
||
|
ClassName = ClassDef->Name;
|
||
|
Require(ClassDef->IsVendor == FALSE);
|
||
|
}
|
||
|
|
||
|
Result = MemArrayInitLoc(&OptDefList->OptDefArray, &Loc);
|
||
|
while( ERROR_FILE_NOT_FOUND != Result ) {
|
||
|
//- ERROR_SUCCESS == Result
|
||
|
Result = MemArrayGetElement(&OptDefList->OptDefArray, &Loc, &OptDef);
|
||
|
//- ERROR_SUCCESS == Result && NULL != OptDef
|
||
|
Result = DhcpRegSaveOptDef(
|
||
|
OptDef->OptId,
|
||
|
ClassName,
|
||
|
VendorName,
|
||
|
OptDef->OptName,
|
||
|
OptDef->OptComment,
|
||
|
OptDef->Type,
|
||
|
OptDef->OptVal,
|
||
|
OptDef->OptValLen
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = MemArrayNextLoc(&OptDefList->OptDefArray, &Loc);
|
||
|
}
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveOptDefs(
|
||
|
IN PM_OPTCLASSDEFLIST OptDefs,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return SaveArray(&OptDefs->Array, DhcpRegSaveOptDefList, Server, NULL);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveClass(
|
||
|
IN PM_CLASSDEF Class,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return DhcpRegSaveClassDef(
|
||
|
Class->Name,
|
||
|
Class->Comment,
|
||
|
(DWORD)Class->IsVendor,
|
||
|
Class->ActualBytes,
|
||
|
Class->nBytes
|
||
|
);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveClassDefs(
|
||
|
IN PM_CLASSDEFLIST ClassDefs,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return SaveArray(&ClassDefs->ClassDefArray, DhcpRegSaveClass, Server, NULL);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveRanges(
|
||
|
IN PM_RANGE Range,
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
DWORD Zero = 0;
|
||
|
|
||
|
return DhcpRegAddRangeEx(
|
||
|
Subnet,
|
||
|
Range->Start,
|
||
|
Range->End,
|
||
|
Range->BootpAllocated,
|
||
|
Range->MaxBootpAllowed,
|
||
|
Range->State,
|
||
|
(LPBYTE)&Zero,
|
||
|
sizeof(Zero),
|
||
|
(LPBYTE)&Zero,
|
||
|
sizeof(Zero)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveExcls(
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN PARRAY Excl
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
DWORD nElems;
|
||
|
DWORD *ExclArray;
|
||
|
DWORD i;
|
||
|
ARRAY_LOCATION Loc;
|
||
|
PM_RANGE ThisRange;
|
||
|
|
||
|
nElems = MemArraySize(Excl);
|
||
|
ExclArray = MemAlloc(( nElems*2+1) *sizeof(DWORD));
|
||
|
if( NULL == ExclArray ) return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
|
||
|
ExclArray[0] = nElems;
|
||
|
|
||
|
MemArrayInitLoc(Excl, &Loc);
|
||
|
for( i = 0 ; i < nElems ; i ++ ) {
|
||
|
MemArrayGetElement(Excl, &Loc, &ThisRange);
|
||
|
Require(ThisRange != NULL);
|
||
|
|
||
|
ExclArray[2*i+1] = ThisRange->Start;
|
||
|
ExclArray[2*i+2] = ThisRange->End;
|
||
|
MemArrayNextLoc(Excl, &Loc);
|
||
|
}
|
||
|
|
||
|
Result = DhcpRegSaveExcl(Subnet, (LPBYTE)ExclArray, sizeof(DWORD)*(nElems*2+1));
|
||
|
MemFree(ExclArray);
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveReservation1(
|
||
|
IN PM_RESERVATION Reservation,
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
|
||
|
Result = DhcpRegSaveReservation(
|
||
|
Subnet->Address,
|
||
|
Reservation->Address,
|
||
|
Reservation->Flags,
|
||
|
Reservation->ClientUID,
|
||
|
Reservation->nBytes
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
return DhcpRegSaveReservationOptions(
|
||
|
&Reservation->Options, Reservation, Subnet
|
||
|
);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveReservations(
|
||
|
IN PM_RESERVATIONS Reservations,
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return SaveArray(Reservations, DhcpRegSaveReservation1, Subnet, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveSubnets(
|
||
|
IN PM_SUBNET Subnet,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused2
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
PM_SSCOPE SScope;
|
||
|
|
||
|
if( Subnet->fSubnet ) {
|
||
|
Result = DhcpRegSaveSubnet(
|
||
|
Subnet->Address,
|
||
|
Subnet->Mask,
|
||
|
Subnet->State,
|
||
|
Subnet->Name,
|
||
|
Subnet->Description
|
||
|
);
|
||
|
} else {
|
||
|
Result = DhcpRegSaveMScope(
|
||
|
Subnet->MScopeId,
|
||
|
Subnet->State,
|
||
|
Subnet->Policy,
|
||
|
Subnet->TTL,
|
||
|
Subnet->Name,
|
||
|
Subnet->Description,
|
||
|
Subnet->LangTag,
|
||
|
&Subnet->ExpiryTime
|
||
|
);
|
||
|
}
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = SaveArray(&Subnet->Ranges, DhcpRegSaveRanges, Subnet, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegSaveExcls(
|
||
|
Subnet,
|
||
|
&Subnet->Exclusions
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegSaveSubnetOptions(&Subnet->Options, Subnet, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegSaveReservations(&Subnet->Reservations, Subnet, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
if( 0 == Subnet->SuperScopeId ) return ERROR_SUCCESS;
|
||
|
Result = MemServerFindSScope(
|
||
|
Server,
|
||
|
Subnet->SuperScopeId,
|
||
|
NULL,
|
||
|
&SScope
|
||
|
);
|
||
|
if( ERROR_FILE_NOT_FOUND == Result ) return ERROR_SUCCESS;
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegSScopeSaveSubnet(SScope->Name, Subnet->Address);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DhcpRegSaveMScopes(
|
||
|
IN PM_MSCOPE MScope,
|
||
|
IN PM_SERVER Server,
|
||
|
IN LPVOID Unused
|
||
|
)
|
||
|
{
|
||
|
return DhcpRegSaveSubnets(MScope, Server, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
//BeginExport(function)
|
||
|
DWORD
|
||
|
DhcpRegServerSave(
|
||
|
IN PM_SERVER Server
|
||
|
) //EndExport(function)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
|
||
|
#if 0
|
||
|
Result = DhcpRegServerSetAttributes(
|
||
|
Hdl,
|
||
|
&Server->Name,
|
||
|
&Server->Comment,
|
||
|
&Server->State
|
||
|
);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
#endif
|
||
|
|
||
|
Result = SaveArray(&Server->Subnets, DhcpRegSaveSubnets, Server, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = SaveArray(&Server->MScopes, DhcpRegSaveMScopes, Server, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
#if 0
|
||
|
Result = SaveArray(&Server->SuperScopes, DhcpRegSaveSuperScopes, Server, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
#endif
|
||
|
|
||
|
Result = DhcpRegSaveGlobalOptions(&Server->Options, Server, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegSaveOptDefs(&Server->OptDefs, Server, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegSaveClassDefs(&Server->ClassDefs, Server, NULL);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
// ---BeginExport(function)
|
||
|
DWORD
|
||
|
DhcpRegSaveThisServer(
|
||
|
IN LPWSTR Location,
|
||
|
IN PM_SERVER Server
|
||
|
) // ---EndExport(function)
|
||
|
{
|
||
|
DWORD Result, Result2;
|
||
|
REG_HANDLE Hdl;
|
||
|
REG_HANDLE SaveHdl;
|
||
|
|
||
|
Result = DhcpRegGetThisServer(&Hdl);
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
Result = DhcpRegGetNextHdl(&Hdl, Location, &SaveHdl);
|
||
|
Result2 = DhcpRegCloseHdl(&Hdl);
|
||
|
Require( ERROR_SUCCESS == Result2 );
|
||
|
|
||
|
if( ERROR_SUCCESS != Result ) return Result;
|
||
|
|
||
|
DhcpRegSetCurrentServer(&SaveHdl);
|
||
|
|
||
|
Result = DhcpRegServerSave(Server);
|
||
|
|
||
|
DhcpRegSetCurrentServer(NULL);
|
||
|
Result2 = DhcpRegCloseHdl(&SaveHdl);
|
||
|
Require( ERROR_SUCCESS == Result2 );
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//BeginExport(function)
|
||
|
DWORD
|
||
|
DhcpMigrateMScopes(
|
||
|
IN LPCWSTR OldMscopeName,
|
||
|
IN LPCWSTR NewMscopeName,
|
||
|
IN DWORD (*SaveOrRestoreRoutine)(
|
||
|
IN HKEY Key, IN LPWSTR ConfigName, IN BOOL fRestore
|
||
|
)
|
||
|
) //EndExport(function)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine attempts to migrate the key stored under
|
||
|
OldMscopeName to NewMscopeName name.
|
||
|
|
||
|
N.B. It does not delete the old key.
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
Win32 error codes
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
REG_HANDLE Hdl1, Hdl2, Hdl3;
|
||
|
ULONG Error, Error2;
|
||
|
|
||
|
Error = DhcpRegGetThisServer(&Hdl1);
|
||
|
if( NO_ERROR != Error ) return Error;
|
||
|
|
||
|
Error = DhcpRegServerGetMScopeHdl(
|
||
|
&Hdl1, (LPWSTR)OldMscopeName, &Hdl2
|
||
|
);
|
||
|
if( NO_ERROR == Error ) {
|
||
|
Error2 = DhcpRegServerGetMScopeHdl(
|
||
|
&Hdl1, (LPWSTR)NewMscopeName, &Hdl3
|
||
|
);
|
||
|
}
|
||
|
|
||
|
DhcpRegCloseHdl(&Hdl1);
|
||
|
if( NO_ERROR != Error ) return Error;
|
||
|
if( NO_ERROR != Error2 ) {
|
||
|
DhcpRegCloseHdl(&Hdl2);
|
||
|
return Error2;
|
||
|
}
|
||
|
|
||
|
Error = SaveOrRestoreRoutine(
|
||
|
Hdl2.Key, L"DHCPMSCOPE.CFG", FALSE
|
||
|
);
|
||
|
|
||
|
if( NO_ERROR == Error ) {
|
||
|
Error = SaveOrRestoreRoutine(
|
||
|
Hdl3.Key, L"DHCPMSCOPE.CFG", TRUE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
DhcpRegCloseHdl(&Hdl2);
|
||
|
DhcpRegCloseHdl(&Hdl3);
|
||
|
|
||
|
return Error;
|
||
|
}
|
||
|
|
||
|
//================================================================================
|
||
|
// end of file
|
||
|
//================================================================================
|
||
|
|
||
|
|
||
|
|