Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

936 lines
26 KiB

//================================================================================
// 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
//================================================================================