Source code of Windows XP (NT5)
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

  1. //================================================================================
  2. // Copyright (c) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: this file deals with the part that keeps the registry bitmask in
  5. // sync. the way, this is done is by keeping a count in each RANGE object to
  6. // count the # of operations that have been performed on it.. if it crosses
  7. // a threshold, it is saved to registry..
  8. //================================================================================
  9. //#include <dhcpsrv.h>
  10. #include <mmregpch.h>
  11. #include <regutil.h>
  12. #include <regsave.h>
  13. extern CRITICAL_SECTION DhcpGlobalInProgressCritSect;
  14. extern CRITICAL_SECTION DhcpGlobalMemoryCritSect;
  15. #define LOCK_MEMORY() EnterCriticalSection(&DhcpGlobalMemoryCritSect)
  16. #define UNLOCK_MEMORY() LeaveCriticalSection(&DhcpGlobalMemoryCritSect)
  17. #define LOCK_INPROGRESS_LIST() EnterCriticalSection(&DhcpGlobalInProgressCritSect)
  18. #define UNLOCK_INPROGRESS_LIST() LeaveCriticalSection(&DhcpGlobalInProgressCritSect)
  19. #define DIRT_THRESHOLD 10 // flush every 10 addresses
  20. //BeginExport(defines)
  21. #define FLUSH_MODIFIED_DIRTY 0
  22. #define FLUSH_MODIFIED 1
  23. #define FLUSH_ANYWAY 2
  24. //EndExport(defines)
  25. DWORD
  26. FlushCheckLoop(
  27. IN PARRAY ArrayToLoopThru,
  28. IN DWORD (*Iterator)(LPVOID Element, DWORD FlushNow, LPVOID Context),
  29. IN DWORD FlushNow,
  30. IN LPVOID Context
  31. )
  32. {
  33. DWORD LastFailure;
  34. DWORD Error;
  35. ARRAY_LOCATION Loc;
  36. LPVOID Element;
  37. LastFailure = ERROR_SUCCESS;
  38. Error = MemArrayInitLoc(ArrayToLoopThru, &Loc);
  39. while(ERROR_FILE_NOT_FOUND != Error ) {
  40. Require(ERROR_SUCCESS == Error);
  41. Error = MemArrayGetElement(ArrayToLoopThru, &Loc, &Element);
  42. Require(ERROR_SUCCESS == Error && NULL != Element);
  43. Error = Iterator(Element, FlushNow, Context);
  44. Require(ERROR_SUCCESS == Error);
  45. if( ERROR_SUCCESS != Error ) LastFailure = Error;
  46. Error = MemArrayNextLoc(ArrayToLoopThru, &Loc);
  47. }
  48. return LastFailure;
  49. }
  50. BOOL _inline
  51. SpecialValues(
  52. IN LPWSTR ValueName
  53. )
  54. {
  55. return (0 == wcscmp(ValueName, REG_RANGE_START_ADDRESS) ||
  56. 0 == wcscmp(ValueName, REG_RANGE_END_ADDRESS) ||
  57. 0 == wcscmp(ValueName, REG_FLAGS) ||
  58. 0 == wcscmp(ValueName, REG_SUBNET_EXCL) ||
  59. 0 == wcscmp(ValueName, REG_SUBNET_SWITCHED_FLAG) ||
  60. 0 == wcscmp(ValueName, REG_MSCOPE_NAME) ||
  61. 0 == wcscmp(ValueName, REG_MSCOPE_COMMENT) ||
  62. 0 == wcscmp(ValueName, REG_MSCOPE_SCOPEID) ||
  63. 0 == wcscmp(ValueName, REG_MSCOPE_STATE) ||
  64. 0 == wcscmp(ValueName, REG_MSCOPE_ADDR_POLICY) ||
  65. 0 == wcscmp(ValueName, REG_MSCOPE_TTL) ||
  66. 0 == wcscmp(ValueName, REG_MSCOPE_LANG_TAG) ||
  67. 0 == wcscmp(ValueName, REG_MSCOPE_EXPIRY_TIME)
  68. );
  69. }
  70. typedef struct _FLSH_BITS_CTXT {
  71. REG_HANDLE *Hdl;
  72. PM_SUBNET Subnet;
  73. PM_RANGE Range;
  74. LONG Index;
  75. } FLSH_BITS_CTXT, *LPFLSH_BITS_CTXT;
  76. static
  77. BYTE TempBuffer[MAX_BIT1SIZE + sizeof(DWORD)*4];
  78. DWORD
  79. FlushBitmask(
  80. IN PM_BITMASK1 Bits1,
  81. IN DWORD FlushNow,
  82. IN LPVOID FlushCtxt
  83. )
  84. {
  85. LPFLSH_BITS_CTXT Ctxt = FlushCtxt;
  86. HKEY Key = Ctxt->Hdl->Key;
  87. WCHAR BitsValueName[REG_RANGE_BITS_PREFIX_WCHAR_COUNT+57];
  88. LONG Count, Index = (Ctxt->Index++);
  89. ULONG WriteSize = 4*sizeof(DWORD), Tmp;
  90. DWORD Error;
  91. LPWSTR TmpStr;
  92. if( FLUSH_ANYWAY != FlushNow && 0 == Bits1->nDirtyOps ) {
  93. return ERROR_SUCCESS;
  94. }
  95. Bits1->nDirtyOps = 0;
  96. ZeroMemory( BitsValueName, sizeof(BitsValueName));
  97. ConvertAddressToLPWSTR(Ctxt->Range->Start, BitsValueName);
  98. wcscat(BitsValueName, L" ");
  99. wcscat(BitsValueName, REG_RANGE_BITS_PREFIX);
  100. TmpStr = &BitsValueName[wcslen(BitsValueName)];
  101. for( Count = 5; Count >= 0; Count -- ) {
  102. TmpStr[Count] = (WCHAR)(L'0' + (Index%10)); Index/= 10;
  103. }
  104. TmpStr[6] = L'\0';
  105. if( 0 == Bits1->nSet ) {
  106. //
  107. // If no bit is set, we don't have to write this to registry -- just need to REMOVE value..
  108. //
  109. Error = RegDeleteValue(Key, (LPWSTR)BitsValueName);
  110. if( ERROR_FILE_NOT_FOUND == Error || ERROR_PATH_NOT_FOUND == Error ) {
  111. return ERROR_SUCCESS;
  112. }
  113. return Error;
  114. }
  115. //
  116. // compose TempBuffer -- note that this whole func is serialized, so we can use
  117. // TempBuffer safely..
  118. //
  119. Tmp = htonl(Bits1->Size); memcpy(&TempBuffer[0*sizeof(DWORD)], &Tmp, sizeof(DWORD));
  120. if( Bits1->Size == Bits1->nSet ) {
  121. Require(Bits1->Mask == NULL);
  122. Tmp = 0;
  123. } else Tmp = htonl(Bits1->AllocSize);
  124. memcpy(&TempBuffer[1*sizeof(DWORD)], &Tmp, sizeof(DWORD));
  125. Tmp = htonl(Bits1->nSet); memcpy(&TempBuffer[2*sizeof(DWORD)], &Tmp, sizeof(DWORD));
  126. Tmp = htonl(Bits1->Offset); memcpy(&TempBuffer[3*sizeof(DWORD)], &Tmp, sizeof(DWORD));
  127. if( Bits1->Mask ) {
  128. memcpy(&TempBuffer[4*sizeof(DWORD)], Bits1->Mask, Bits1->AllocSize);
  129. WriteSize += Bits1->AllocSize;
  130. }
  131. return RegSetValueEx(
  132. Key,
  133. (LPWSTR)BitsValueName,
  134. 0,
  135. REG_BINARY,
  136. TempBuffer,
  137. WriteSize
  138. );
  139. }
  140. DWORD
  141. DhcpRegClearupRangeValues(
  142. IN PM_SUBNET Subnet,
  143. IN PM_RANGE Range
  144. )
  145. /*++
  146. Routine Description:
  147. This routine clears up all values for a given Range (this can be
  148. specified via a single Key for the range, or via the Range/Subnet
  149. object pair) excepting "StartAddress", "EndAddress" and "Flags".
  150. Arguments:
  151. Key INVALID_HANDLE_VALUE if range is specified
  152. via Range, Subnet pair. Else Range key in registry.
  153. Subnet Subnet object if Key is not speificed.
  154. Range Range object if key is not specified.
  155. Returns:
  156. Win32 errors (registry) or ERROR_SUCCESS on success.
  157. --*/
  158. {
  159. ULONG Error, nValues, Index;
  160. REG_HANDLE Hdl;
  161. HKEY UseKey;
  162. WCHAR ValueNameBuf[100], RangeStr[50];
  163. DWORD ValueNameSize, ValueType;
  164. Error = DhcpRegGetThisServer( &Hdl );
  165. if( NO_ERROR != Error ) return Error;
  166. ZeroMemory( RangeStr, sizeof(RangeStr));
  167. ConvertAddressToLPWSTR( Range->Start, RangeStr );
  168. UseKey = Hdl.Key;
  169. do {
  170. Error = RegQueryInfoKey(
  171. UseKey, NULL, NULL, NULL, NULL, NULL, NULL, &nValues, NULL, NULL, NULL, NULL
  172. );
  173. if( ERROR_SUCCESS != Error ) break;
  174. Index = nValues -1;
  175. while( nValues ) {
  176. ValueNameSize = sizeof(ValueNameBuf)/sizeof(WCHAR);
  177. Error = RegEnumValue(
  178. UseKey,
  179. Index,
  180. (LPWSTR)ValueNameBuf,
  181. &ValueNameSize,
  182. NULL,
  183. &ValueType,
  184. NULL,
  185. NULL
  186. );
  187. if( ERROR_SUCCESS != Error ) break;
  188. if( 0 == wcsncmp( ValueNameBuf, RangeStr,
  189. wcslen(RangeStr) ) ) {
  190. RegDeleteValue(UseKey, (LPWSTR)ValueNameBuf);
  191. }
  192. Index --;
  193. nValues --;
  194. }
  195. } while ( 0 );
  196. DhcpRegCloseHdl(&Hdl);
  197. return Error;
  198. }
  199. // This function is ALSO CALLED FROM REGREAD.C while reading in a subnet info..
  200. //BeginExport(function)
  201. DWORD
  202. FlushRanges(
  203. IN PM_RANGE Range,
  204. IN DWORD FlushNow,
  205. IN PM_SUBNET Subnet
  206. ) //EndExport(function)
  207. {
  208. DWORD Error;
  209. REG_HANDLE Hdl;
  210. PM_BITMASK BitMask;
  211. FLSH_BITS_CTXT Ctxt = { &Hdl, Subnet, Range, 0};
  212. if( (FLUSH_ANYWAY != FlushNow && 0 == Range->DirtyOps) ||
  213. (FLUSH_MODIFIED_DIRTY == FlushNow && Range->DirtyOps < DIRT_THRESHOLD ) ) {
  214. return ERROR_SUCCESS;
  215. }
  216. Error = DhcpRegGetThisServer( &Hdl );
  217. if( NO_ERROR != Error ) return Error;
  218. //
  219. // Lock is needed to serialize access to memory -- shouldn't be allocating addresses
  220. // while we're planning to save it to registry..
  221. //
  222. LOCK_INPROGRESS_LIST();
  223. LOCK_MEMORY();
  224. Range->DirtyOps = 0;
  225. BitMask = Range->BitMask;
  226. if( FLUSH_ANYWAY == FlushNow ) {
  227. DhcpRegClearupRangeValues(Subnet, Range);
  228. }
  229. Error = FlushCheckLoop(&BitMask->Array, FlushBitmask, FlushNow, &Ctxt );
  230. DhcpRegCloseHdl( &Hdl );
  231. UNLOCK_MEMORY();
  232. UNLOCK_INPROGRESS_LIST();
  233. return Error;
  234. }
  235. DWORD
  236. FlushSubnets(
  237. IN PM_SUBNET Subnet,
  238. IN DWORD FlushNow,
  239. IN LPVOID Context_UNUSED
  240. )
  241. {
  242. ULONG Error;
  243. Error = FlushCheckLoop(&Subnet->Ranges, FlushRanges, FlushNow, Subnet);
  244. Require( ERROR_SUCCESS == Error );
  245. return Error;
  246. }
  247. //BeginExport(function)
  248. DWORD
  249. DhcpRegServerFlush(
  250. IN PM_SERVER Server,
  251. IN DWORD FlushNow
  252. ) //EndExport(function)
  253. {
  254. DWORD Error;
  255. Error = FlushCheckLoop(&Server->Subnets, FlushSubnets, FlushNow, NULL);
  256. Require(ERROR_SUCCESS == Error);
  257. Error = FlushCheckLoop(&Server->MScopes, FlushSubnets, FlushNow, NULL);
  258. Require(ERROR_SUCCESS == Error);
  259. return Error;
  260. }
  261. //BeginExport(function)
  262. DWORD
  263. DhcpRegFlushServer(
  264. IN DWORD FlushNow
  265. ) //EndExport(function)
  266. {
  267. PM_SERVER Server;
  268. DWORD Error;
  269. PM_SERVER DhcpGetCurrentServer(VOID);
  270. Server = DhcpGetCurrentServer();
  271. Error = FlushCheckLoop(&Server->Subnets, FlushSubnets, FlushNow, NULL);
  272. Require(ERROR_SUCCESS == Error);
  273. Error = FlushCheckLoop(&Server->MScopes, FlushSubnets, FlushNow, NULL);
  274. Require(ERROR_SUCCESS == Error);
  275. return Error;
  276. }
  277. //================================================================================
  278. // ds support routines -- flush a full server to disk
  279. //================================================================================
  280. DWORD
  281. SaveArray(
  282. IN PARRAY Array,
  283. IN DWORD (*Func)(LPVOID, LPVOID, LPVOID),
  284. IN LPVOID Arg2,
  285. IN LPVOID Arg3
  286. )
  287. {
  288. ARRAY_LOCATION Loc;
  289. DWORD Result;
  290. LPVOID ThisPtr;
  291. Result = MemArrayInitLoc(Array, &Loc);
  292. while(ERROR_FILE_NOT_FOUND != Result ) {
  293. Result = MemArrayGetElement(Array, &Loc, &ThisPtr);
  294. Require(ERROR_SUCCESS == Result && NULL != ThisPtr );
  295. Result = Func(ThisPtr, Arg2, Arg3);
  296. if( ERROR_SUCCESS != Result ) return Result;
  297. Result = MemArrayNextLoc(Array, &Loc);
  298. }
  299. return ERROR_SUCCESS;
  300. }
  301. DWORD
  302. DhcpRegSaveOptList(
  303. IN PM_ONECLASS_OPTLIST OptClassOptList,
  304. IN LPVOID Arg1,
  305. IN LPVOID Arg2
  306. )
  307. {
  308. DWORD Result;
  309. DWORD ClassId;
  310. DWORD VendorId;
  311. LPWSTR ClassName;
  312. LPWSTR VendorName;
  313. PM_OPTLIST OptList;
  314. PM_SERVER Server;
  315. PM_SUBNET Subnet;
  316. PM_RESERVATION Reservation;
  317. PM_SSCOPE SScope;
  318. PM_OPTION Option;
  319. PM_CLASSDEF ClassDef;
  320. ARRAY_LOCATION Loc;
  321. ClassId = OptClassOptList->ClassId;
  322. VendorId = OptClassOptList->VendorId;
  323. OptList = &OptClassOptList->OptList;
  324. if( NULL != Arg1 && NULL != Arg2 ) { // reservations
  325. Reservation = Arg1; Subnet = Arg2;
  326. Server = Subnet->ServerPtr;
  327. } else if( NULL == Arg2 ) { // subnet options
  328. Reservation = NULL; Subnet = Arg1;
  329. Server = Subnet->ServerPtr;
  330. } else if( NULL == Arg1 ) { // global options
  331. Reservation = NULL; Subnet = NULL;
  332. Server = Arg2;
  333. } else { // enterprise options?
  334. return ERROR_NOT_SUPPORTED;
  335. }
  336. Result = MemServerGetClassDef( // get the vendor name first
  337. Server,
  338. VendorId,
  339. NULL,
  340. 0,
  341. NULL,
  342. &ClassDef
  343. );
  344. if( ERROR_SUCCESS != Result ) {
  345. VendorName = NULL;
  346. } else {
  347. VendorName = ClassDef->Name;
  348. Require(ClassDef->IsVendor == TRUE);
  349. }
  350. Result = MemServerGetClassDef( // get the class name for this class
  351. Server,
  352. ClassId,
  353. NULL,
  354. 0,
  355. NULL,
  356. &ClassDef
  357. );
  358. if( ERROR_SUCCESS != Result ) {
  359. ClassName = NULL;
  360. } else {
  361. ClassName = ClassDef->Name;
  362. Require(ClassDef->IsVendor == FALSE);
  363. }
  364. Result = MemArrayInitLoc(OptList, &Loc);
  365. while( ERROR_FILE_NOT_FOUND != Result ) {
  366. //- ERROR_SUCCESS == Result
  367. Result = MemArrayGetElement(OptList, &Loc, &Option);
  368. //- ERROR_SUCCESS == Result && NULL != Option
  369. if( NULL != Reservation ) { // save reservation options
  370. Result = DhcpRegSaveReservedOption(
  371. Subnet->Address,
  372. Reservation->Address,
  373. Option->OptId,
  374. ClassName,
  375. VendorName,
  376. Option->Val,
  377. Option->Len
  378. );
  379. } else if( NULL != Subnet ) { // save subnet optinos
  380. Result = DhcpRegSaveSubnetOption(
  381. Subnet,
  382. Option->OptId,
  383. ClassName,
  384. VendorName,
  385. Option->Val,
  386. Option->Len
  387. );
  388. } else if( NULL != Server ) { // save global options
  389. Result = DhcpRegSaveGlobalOption(
  390. Option->OptId,
  391. ClassName,
  392. VendorName,
  393. Option->Val,
  394. Option->Len
  395. );
  396. } else { // save enterprise wide optinos
  397. return ERROR_CALL_NOT_IMPLEMENTED;
  398. }
  399. if( ERROR_SUCCESS != Result ) return Result;
  400. Result = MemArrayNextLoc(OptList, &Loc);
  401. }
  402. return ERROR_SUCCESS;
  403. }
  404. DWORD
  405. DhcpRegSaveReservationOptions(
  406. IN PM_OPTCLASS OptClass,
  407. IN PM_RESERVATION Reservation,
  408. IN PM_SUBNET Subnet
  409. )
  410. {
  411. DWORD Result;
  412. ARRAY_LOCATION Loc;
  413. return SaveArray(&OptClass->Array, DhcpRegSaveOptList, Reservation, Subnet);
  414. }
  415. DWORD
  416. DhcpRegSaveSubnetOptions(
  417. IN PM_OPTCLASS OptClass,
  418. IN PM_SUBNET Subnet,
  419. IN LPVOID Unused
  420. )
  421. {
  422. return SaveArray(&OptClass->Array, DhcpRegSaveOptList, Subnet, NULL);
  423. }
  424. DWORD
  425. DhcpRegSaveGlobalOptions(
  426. IN PM_OPTCLASS OptClass,
  427. IN PM_SERVER Server,
  428. IN LPVOID Unused
  429. )
  430. {
  431. return SaveArray(&OptClass->Array, DhcpRegSaveOptList, NULL, Server);
  432. }
  433. DWORD
  434. DhcpRegSaveOptDefList(
  435. IN PM_OPTCLASSDEFL_ONE OClassDefL,
  436. IN PM_SERVER Server,
  437. IN LPVOID Unused
  438. )
  439. {
  440. DWORD Result;
  441. DWORD ClassId;
  442. DWORD VendorId;
  443. LPWSTR ClassName;
  444. LPWSTR VendorName;
  445. PM_OPTDEFLIST OptDefList;
  446. PM_OPTDEF OptDef;
  447. PM_CLASSDEF ClassDef;
  448. ARRAY_LOCATION Loc;
  449. ClassId = OClassDefL->ClassId;
  450. VendorId = OClassDefL->VendorId;
  451. OptDefList = &OClassDefL->OptDefList;
  452. Result = MemServerGetClassDef( // first find the vendor name
  453. Server,
  454. VendorId,
  455. NULL,
  456. 0,
  457. NULL,
  458. &ClassDef
  459. );
  460. if( ERROR_SUCCESS != Result ) {
  461. VendorName = NULL;
  462. } else {
  463. VendorName = ClassDef->Name;
  464. Require(ClassDef->IsVendor == TRUE);
  465. }
  466. Result = MemServerGetClassDef( // now find the class name
  467. Server,
  468. ClassId,
  469. NULL,
  470. 0,
  471. NULL,
  472. &ClassDef
  473. );
  474. if( ERROR_SUCCESS != Result ) {
  475. ClassName = NULL;
  476. } else {
  477. ClassName = ClassDef->Name;
  478. Require(ClassDef->IsVendor == FALSE);
  479. }
  480. Result = MemArrayInitLoc(&OptDefList->OptDefArray, &Loc);
  481. while( ERROR_FILE_NOT_FOUND != Result ) {
  482. //- ERROR_SUCCESS == Result
  483. Result = MemArrayGetElement(&OptDefList->OptDefArray, &Loc, &OptDef);
  484. //- ERROR_SUCCESS == Result && NULL != OptDef
  485. Result = DhcpRegSaveOptDef(
  486. OptDef->OptId,
  487. ClassName,
  488. VendorName,
  489. OptDef->OptName,
  490. OptDef->OptComment,
  491. OptDef->Type,
  492. OptDef->OptVal,
  493. OptDef->OptValLen
  494. );
  495. if( ERROR_SUCCESS != Result ) return Result;
  496. Result = MemArrayNextLoc(&OptDefList->OptDefArray, &Loc);
  497. }
  498. return ERROR_SUCCESS;
  499. }
  500. DWORD
  501. DhcpRegSaveOptDefs(
  502. IN PM_OPTCLASSDEFLIST OptDefs,
  503. IN PM_SERVER Server,
  504. IN LPVOID Unused
  505. )
  506. {
  507. return SaveArray(&OptDefs->Array, DhcpRegSaveOptDefList, Server, NULL);
  508. }
  509. DWORD
  510. DhcpRegSaveClass(
  511. IN PM_CLASSDEF Class,
  512. IN PM_SERVER Server,
  513. IN LPVOID Unused
  514. )
  515. {
  516. return DhcpRegSaveClassDef(
  517. Class->Name,
  518. Class->Comment,
  519. (DWORD)Class->IsVendor,
  520. Class->ActualBytes,
  521. Class->nBytes
  522. );
  523. }
  524. DWORD
  525. DhcpRegSaveClassDefs(
  526. IN PM_CLASSDEFLIST ClassDefs,
  527. IN PM_SERVER Server,
  528. IN LPVOID Unused
  529. )
  530. {
  531. return SaveArray(&ClassDefs->ClassDefArray, DhcpRegSaveClass, Server, NULL);
  532. }
  533. DWORD
  534. DhcpRegSaveRanges(
  535. IN PM_RANGE Range,
  536. IN PM_SUBNET Subnet,
  537. IN LPVOID Unused
  538. )
  539. {
  540. DWORD Result;
  541. DWORD Zero = 0;
  542. return DhcpRegAddRangeEx(
  543. Subnet,
  544. Range->Start,
  545. Range->End,
  546. Range->BootpAllocated,
  547. Range->MaxBootpAllowed,
  548. Range->State,
  549. (LPBYTE)&Zero,
  550. sizeof(Zero),
  551. (LPBYTE)&Zero,
  552. sizeof(Zero)
  553. );
  554. }
  555. DWORD
  556. DhcpRegSaveExcls(
  557. IN PM_SUBNET Subnet,
  558. IN PARRAY Excl
  559. )
  560. {
  561. DWORD Result;
  562. DWORD nElems;
  563. DWORD *ExclArray;
  564. DWORD i;
  565. ARRAY_LOCATION Loc;
  566. PM_RANGE ThisRange;
  567. nElems = MemArraySize(Excl);
  568. ExclArray = MemAlloc(( nElems*2+1) *sizeof(DWORD));
  569. if( NULL == ExclArray ) return ERROR_NOT_ENOUGH_MEMORY;
  570. ExclArray[0] = nElems;
  571. MemArrayInitLoc(Excl, &Loc);
  572. for( i = 0 ; i < nElems ; i ++ ) {
  573. MemArrayGetElement(Excl, &Loc, &ThisRange);
  574. Require(ThisRange != NULL);
  575. ExclArray[2*i+1] = ThisRange->Start;
  576. ExclArray[2*i+2] = ThisRange->End;
  577. MemArrayNextLoc(Excl, &Loc);
  578. }
  579. Result = DhcpRegSaveExcl(Subnet, (LPBYTE)ExclArray, sizeof(DWORD)*(nElems*2+1));
  580. MemFree(ExclArray);
  581. return Result;
  582. }
  583. DWORD
  584. DhcpRegSaveReservation1(
  585. IN PM_RESERVATION Reservation,
  586. IN PM_SUBNET Subnet,
  587. IN LPVOID Unused
  588. )
  589. {
  590. DWORD Result;
  591. Result = DhcpRegSaveReservation(
  592. Subnet->Address,
  593. Reservation->Address,
  594. Reservation->Flags,
  595. Reservation->ClientUID,
  596. Reservation->nBytes
  597. );
  598. if( ERROR_SUCCESS != Result ) return Result;
  599. return DhcpRegSaveReservationOptions(
  600. &Reservation->Options, Reservation, Subnet
  601. );
  602. }
  603. DWORD
  604. DhcpRegSaveReservations(
  605. IN PM_RESERVATIONS Reservations,
  606. IN PM_SUBNET Subnet,
  607. IN LPVOID Unused
  608. )
  609. {
  610. return SaveArray(Reservations, DhcpRegSaveReservation1, Subnet, NULL);
  611. }
  612. DWORD
  613. DhcpRegSaveSubnets(
  614. IN PM_SUBNET Subnet,
  615. IN PM_SERVER Server,
  616. IN LPVOID Unused2
  617. )
  618. {
  619. DWORD Result;
  620. PM_SSCOPE SScope;
  621. if( Subnet->fSubnet ) {
  622. Result = DhcpRegSaveSubnet(
  623. Subnet->Address,
  624. Subnet->Mask,
  625. Subnet->State,
  626. Subnet->Name,
  627. Subnet->Description
  628. );
  629. } else {
  630. Result = DhcpRegSaveMScope(
  631. Subnet->MScopeId,
  632. Subnet->State,
  633. Subnet->Policy,
  634. Subnet->TTL,
  635. Subnet->Name,
  636. Subnet->Description,
  637. Subnet->LangTag,
  638. &Subnet->ExpiryTime
  639. );
  640. }
  641. if( ERROR_SUCCESS != Result ) return Result;
  642. Result = SaveArray(&Subnet->Ranges, DhcpRegSaveRanges, Subnet, NULL);
  643. if( ERROR_SUCCESS != Result ) return Result;
  644. Result = DhcpRegSaveExcls(
  645. Subnet,
  646. &Subnet->Exclusions
  647. );
  648. if( ERROR_SUCCESS != Result ) return Result;
  649. Result = DhcpRegSaveSubnetOptions(&Subnet->Options, Subnet, NULL);
  650. if( ERROR_SUCCESS != Result ) return Result;
  651. Result = DhcpRegSaveReservations(&Subnet->Reservations, Subnet, NULL);
  652. if( ERROR_SUCCESS != Result ) return Result;
  653. if( 0 == Subnet->SuperScopeId ) return ERROR_SUCCESS;
  654. Result = MemServerFindSScope(
  655. Server,
  656. Subnet->SuperScopeId,
  657. NULL,
  658. &SScope
  659. );
  660. if( ERROR_FILE_NOT_FOUND == Result ) return ERROR_SUCCESS;
  661. if( ERROR_SUCCESS != Result ) return Result;
  662. Result = DhcpRegSScopeSaveSubnet(SScope->Name, Subnet->Address);
  663. if( ERROR_SUCCESS != Result ) return Result;
  664. return ERROR_SUCCESS;
  665. }
  666. DWORD
  667. DhcpRegSaveMScopes(
  668. IN PM_MSCOPE MScope,
  669. IN PM_SERVER Server,
  670. IN LPVOID Unused
  671. )
  672. {
  673. return DhcpRegSaveSubnets(MScope, Server, NULL);
  674. }
  675. //BeginExport(function)
  676. DWORD
  677. DhcpRegServerSave(
  678. IN PM_SERVER Server
  679. ) //EndExport(function)
  680. {
  681. DWORD Result;
  682. #if 0
  683. Result = DhcpRegServerSetAttributes(
  684. Hdl,
  685. &Server->Name,
  686. &Server->Comment,
  687. &Server->State
  688. );
  689. if( ERROR_SUCCESS != Result ) return Result;
  690. #endif
  691. Result = SaveArray(&Server->Subnets, DhcpRegSaveSubnets, Server, NULL);
  692. if( ERROR_SUCCESS != Result ) return Result;
  693. Result = SaveArray(&Server->MScopes, DhcpRegSaveMScopes, Server, NULL);
  694. if( ERROR_SUCCESS != Result ) return Result;
  695. #if 0
  696. Result = SaveArray(&Server->SuperScopes, DhcpRegSaveSuperScopes, Server, NULL);
  697. if( ERROR_SUCCESS != Result ) return Result;
  698. #endif
  699. Result = DhcpRegSaveGlobalOptions(&Server->Options, Server, NULL);
  700. if( ERROR_SUCCESS != Result ) return Result;
  701. Result = DhcpRegSaveOptDefs(&Server->OptDefs, Server, NULL);
  702. if( ERROR_SUCCESS != Result ) return Result;
  703. Result = DhcpRegSaveClassDefs(&Server->ClassDefs, Server, NULL);
  704. if( ERROR_SUCCESS != Result ) return Result;
  705. return ERROR_SUCCESS;
  706. }
  707. #if 0
  708. // ---BeginExport(function)
  709. DWORD
  710. DhcpRegSaveThisServer(
  711. IN LPWSTR Location,
  712. IN PM_SERVER Server
  713. ) // ---EndExport(function)
  714. {
  715. DWORD Result, Result2;
  716. REG_HANDLE Hdl;
  717. REG_HANDLE SaveHdl;
  718. Result = DhcpRegGetThisServer(&Hdl);
  719. if( ERROR_SUCCESS != Result ) return Result;
  720. Result = DhcpRegGetNextHdl(&Hdl, Location, &SaveHdl);
  721. Result2 = DhcpRegCloseHdl(&Hdl);
  722. Require( ERROR_SUCCESS == Result2 );
  723. if( ERROR_SUCCESS != Result ) return Result;
  724. DhcpRegSetCurrentServer(&SaveHdl);
  725. Result = DhcpRegServerSave(Server);
  726. DhcpRegSetCurrentServer(NULL);
  727. Result2 = DhcpRegCloseHdl(&SaveHdl);
  728. Require( ERROR_SUCCESS == Result2 );
  729. return Result;
  730. }
  731. #endif
  732. //BeginExport(function)
  733. DWORD
  734. DhcpMigrateMScopes(
  735. IN LPCWSTR OldMscopeName,
  736. IN LPCWSTR NewMscopeName,
  737. IN DWORD (*SaveOrRestoreRoutine)(
  738. IN HKEY Key, IN LPWSTR ConfigName, IN BOOL fRestore
  739. )
  740. ) //EndExport(function)
  741. /*++
  742. Routine Description:
  743. This routine attempts to migrate the key stored under
  744. OldMscopeName to NewMscopeName name.
  745. N.B. It does not delete the old key.
  746. Return Values:
  747. Win32 error codes
  748. --*/
  749. {
  750. REG_HANDLE Hdl1, Hdl2, Hdl3;
  751. ULONG Error, Error2;
  752. Error = DhcpRegGetThisServer(&Hdl1);
  753. if( NO_ERROR != Error ) return Error;
  754. Error = DhcpRegServerGetMScopeHdl(
  755. &Hdl1, (LPWSTR)OldMscopeName, &Hdl2
  756. );
  757. if( NO_ERROR == Error ) {
  758. Error2 = DhcpRegServerGetMScopeHdl(
  759. &Hdl1, (LPWSTR)NewMscopeName, &Hdl3
  760. );
  761. }
  762. DhcpRegCloseHdl(&Hdl1);
  763. if( NO_ERROR != Error ) return Error;
  764. if( NO_ERROR != Error2 ) {
  765. DhcpRegCloseHdl(&Hdl2);
  766. return Error2;
  767. }
  768. Error = SaveOrRestoreRoutine(
  769. Hdl2.Key, L"DHCPMSCOPE.CFG", FALSE
  770. );
  771. if( NO_ERROR == Error ) {
  772. Error = SaveOrRestoreRoutine(
  773. Hdl3.Key, L"DHCPMSCOPE.CFG", TRUE
  774. );
  775. }
  776. DhcpRegCloseHdl(&Hdl2);
  777. DhcpRegCloseHdl(&Hdl3);
  778. return Error;
  779. }
  780. //================================================================================
  781. // end of file
  782. //================================================================================