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.

1615 lines
47 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: This implements the init time reading in of the registry
  5. // (this may/may work even when used to read at any other time.. but is not efficient)
  6. //================================================================================
  7. #include <mmregpch.h>
  8. #include <regutil.h>
  9. #include <regsave.h>
  10. #include "server\uniqid.h"
  11. #define InitArray(X) do{DWORD Error = MemArrayInit((X)); Require(ERROR_SUCCESS == Error); }while(0)
  12. #define ERRCHK do{if( ERROR_SUCCESS != Error ) goto Cleanup; }while(0)
  13. #define FreeArray1(X) Error = LoopThruArray((X), DestroyString, NULL, NULL);Require(ERROR_SUCCESS == Error);
  14. #define FreeArray2(X) Error = MemArrayCleanup((X)); Require(ERROR_SUCCESS == Error);
  15. #define FreeArray(X) do{ DWORD Error; FreeArray1(X); FreeArray2(X); }while(0)
  16. #if DBG
  17. #define Report(Who) if(Error) DbgPrint("[DHCPServer] %s: %ld [0x%lx]\n", Who, Error, Error)
  18. #define INVALID_REG DbgPrint
  19. #else
  20. #define Report(Who)
  21. #define INVALID_REG (void)
  22. #endif
  23. typedef DWORD (*ARRAY_FN)(PREG_HANDLE, LPWSTR ArrayString, LPVOID MemObject);
  24. DWORD
  25. LoopThruArray(
  26. IN PARRAY Array,
  27. IN ARRAY_FN ArrayFn,
  28. IN PREG_HANDLE Hdl,
  29. IN LPVOID MemObject
  30. )
  31. {
  32. DWORD Error;
  33. ARRAY_LOCATION Loc;
  34. LPWSTR ArrayString;
  35. Error = MemArrayInitLoc(Array, &Loc);
  36. while(ERROR_FILE_NOT_FOUND != Error) {
  37. Require(ERROR_SUCCESS == Error);
  38. Error = MemArrayGetElement(Array, &Loc, (LPVOID *)&ArrayString);
  39. Require(ERROR_SUCCESS == Error && ArrayString);
  40. Error = ArrayFn(Hdl, ArrayString, MemObject);
  41. if( ERROR_SUCCESS != Error ) {
  42. //
  43. // Operation failed -- but ignore it.
  44. //
  45. // return Error;
  46. }
  47. Error = MemArrayNextLoc(Array, &Loc);
  48. }
  49. return ERROR_SUCCESS;
  50. }
  51. DWORD
  52. DestroyString(
  53. IN PREG_HANDLE Unused,
  54. IN LPWSTR StringToFree,
  55. IN LPVOID Unused2
  56. )
  57. {
  58. MemFree(StringToFree);
  59. return ERROR_SUCCESS;
  60. }
  61. DWORD
  62. WStringToAddress(
  63. IN LPWSTR Str
  64. )
  65. {
  66. CHAR IpString[100];
  67. DWORD Count;
  68. Count = wcstombs(IpString, Str, sizeof(IpString)-1);
  69. if( -1 == Count ) return 0;
  70. return htonl(inet_addr(IpString));
  71. }
  72. DWORD
  73. ConvertWStringToDWORD(
  74. IN LPWSTR Str
  75. )
  76. {
  77. return _wtoi(Str);
  78. }
  79. DWORD
  80. DhcpRegpSubnetAddServer(
  81. IN PREG_HANDLE Hdl,
  82. IN LPWSTR ServerName,
  83. IN PM_SUBNET Subnet
  84. )
  85. {
  86. return ERROR_SUCCESS;
  87. }
  88. DWORD
  89. SetBitForRange(
  90. IN PM_RANGE Range,
  91. IN DWORD Address
  92. )
  93. {
  94. BOOL WasSet;
  95. if( Address > Range->End || Address < Range->Start )
  96. return ERROR_INVALID_PARAMETER;
  97. return MemBitSetOrClear(
  98. Range->BitMask,
  99. Address - Range->Start,
  100. TRUE,
  101. &WasSet
  102. );
  103. }
  104. DWORD GlobalWorkingOnOldStyleSubnet = 0;
  105. DWORD GlobalWorkingOnPreWin2kMScope = 0;
  106. const DWORD One = 0x1;
  107. DWORD
  108. DhcpRegFillClusterAddresses(
  109. IN OUT PM_RANGE Range,
  110. IN LPBYTE InUseClusters,
  111. IN DWORD InUseClustersSize,
  112. IN LPBYTE UsedClusters,
  113. IN DWORD UsedClustersSize
  114. ) {
  115. DWORD Error;
  116. DWORD i;
  117. DWORD Address;
  118. DWORD UNALIGNED* InUseBits;
  119. DWORD UNALIGNED* UsedBits;
  120. DWORD nInUseBits;
  121. DWORD nUsedBits;
  122. if( InUseClusters && InUseClustersSize ) {
  123. nInUseBits = InUseClustersSize/sizeof(DWORD);
  124. InUseBits = (DWORD UNALIGNED*)InUseClusters;
  125. Require(nInUseBits == 2*InUseBits[0] + 1 );
  126. nInUseBits --; InUseBits ++;
  127. while(nInUseBits) {
  128. for(i = 0; i < sizeof(DWORD)*8; i ++ )
  129. if( InUseBits[1] & ( One << i ) )
  130. SetBitForRange(Range, InUseBits[0] + i );
  131. nInUseBits -= 2;
  132. InUseBits += 2;
  133. }
  134. }
  135. if( UsedClusters && UsedClustersSize ) {
  136. nUsedBits = UsedClustersSize/sizeof(DWORD);
  137. UsedBits = (DWORD UNALIGNED*)UsedClusters;
  138. Require(nUsedBits == UsedBits[0] + 1);
  139. nUsedBits --; UsedBits ++;
  140. while(nUsedBits) {
  141. for( i = 0; i < sizeof(DWORD)*8; i ++ )
  142. SetBitForRange(Range, UsedBits[0] + i);
  143. UsedBits ++;
  144. nUsedBits --;
  145. }
  146. }
  147. return ERROR_SUCCESS;
  148. }
  149. static DWORD Masks[] = {
  150. 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
  151. };
  152. DWORD
  153. DhcpRegpFillBitsForRange(
  154. IN LPBYTE Buffer,
  155. IN ULONG BufSize,
  156. IN OUT PM_RANGE Range,
  157. IN PM_SUBNET Subnet
  158. )
  159. {
  160. ULONG Size, AllocSize, nSet, Offset;
  161. ULONG nBitsSet, Index;
  162. ULONG Error;
  163. Size = ntohl(((UNALIGNED DWORD *)Buffer)[0]);
  164. AllocSize = ntohl(((UNALIGNED DWORD *)Buffer)[1]);
  165. nSet = ntohl(((UNALIGNED DWORD *)Buffer)[2]);
  166. Offset = ntohl(((UNALIGNED DWORD *)Buffer)[3]);
  167. //
  168. // do not check for validity of the offset sizes.
  169. // SetBitForRange does this check anyway.
  170. //
  171. // if( Range->Start + Offset + Size > 1+Range->End )
  172. // return ERROR_INVALID_DATA;
  173. Require(nSet != 0);
  174. if( nSet == 0 ) return ERROR_SUCCESS;
  175. if( nSet == Size ) {
  176. Require( AllocSize == 0 );
  177. for( Index = 0; Index < nSet ; Index ++ ) {
  178. Error = SetBitForRange(Range, Range->Start + Index);
  179. Require( ERROR_SUCCESS == Error );
  180. }
  181. return ERROR_SUCCESS;
  182. }
  183. if( AllocSize + sizeof(DWORD)*4 != BufSize ) return ERROR_INVALID_DATA;
  184. nBitsSet = 0;
  185. Require( Size/8 <= AllocSize );
  186. for( Index = 0; Index < Size ; Index ++ ) {
  187. if( Buffer[ 4*sizeof(DWORD) + (Index/8) ] & Masks[Index%8] ) {
  188. nBitsSet ++;
  189. //
  190. // whistler bug 283457, offset not taken into account
  191. //
  192. Error = SetBitForRange( Range, Range->Start + Index + Offset );
  193. Require( ERROR_SUCCESS == Error );
  194. }
  195. }
  196. Require(nBitsSet == nSet);
  197. return ERROR_SUCCESS;
  198. }
  199. static
  200. BYTE TempBuffer[MAX_BIT1SIZE + sizeof(DWORD)*4];
  201. DWORD
  202. DhcpRegpFillBitmasks(
  203. IN HKEY Key,
  204. IN PM_RANGE Range,
  205. IN PM_SUBNET Subnet
  206. )
  207. {
  208. ULONG Error, nValues, Index;
  209. WCHAR ValueNameBuf[100];
  210. DWORD ValueNameSize, ValueType;
  211. DWORD ValueSize;
  212. WCHAR RangeStartStr[30];
  213. BOOL fPostNt5 = FALSE;
  214. REG_HANDLE Hdl;
  215. if( NULL == Key ) {
  216. ConvertAddressToLPWSTR( Range->Start, RangeStartStr);
  217. fPostNt5 = TRUE;
  218. Error = DhcpRegGetThisServer( &Hdl );
  219. if( NO_ERROR != Error ) return Error;
  220. Key = Hdl.Key;
  221. }
  222. Error = RegQueryInfoKey(
  223. Key, NULL, NULL, NULL, NULL, NULL, NULL, &nValues, NULL, NULL, NULL, NULL
  224. );
  225. if( ERROR_SUCCESS != Error ) goto Cleanup;
  226. Index = nValues -1;
  227. while( nValues ) {
  228. ValueNameSize = sizeof(ValueNameBuf)/sizeof(WCHAR);
  229. ValueSize = sizeof(TempBuffer)/sizeof(WCHAR);
  230. Error = RegEnumValue(
  231. Key,
  232. Index,
  233. ValueNameBuf,
  234. &ValueNameSize,
  235. NULL,
  236. &ValueType,
  237. TempBuffer,
  238. &ValueSize
  239. );
  240. if( ERROR_SUCCESS != Error ) goto Cleanup;
  241. if( fPostNt5 && 0 != wcsncmp(
  242. ValueNameBuf, RangeStartStr, wcslen(RangeStartStr)) ) {
  243. //
  244. // Skip irrelevant bitmaps
  245. //
  246. Index --;
  247. nValues --;
  248. continue;
  249. }
  250. if( REG_BINARY == ValueType && ValueSize >= sizeof(DWORD)*4 ) {
  251. Error = DhcpRegpFillBitsForRange(
  252. TempBuffer,
  253. ValueSize,
  254. Range,
  255. Subnet
  256. );
  257. if( ERROR_SUCCESS != Error ) {
  258. Require(FALSE);
  259. goto Cleanup;
  260. }
  261. }
  262. Index --;
  263. nValues --;
  264. }
  265. Cleanup:
  266. if( fPostNt5 ) {
  267. DhcpRegCloseHdl( &Hdl );
  268. }
  269. return Error;
  270. }
  271. DWORD
  272. DhcpRegpSubnetAddRange(
  273. IN PREG_HANDLE Hdl,
  274. IN LPWSTR RangeName,
  275. IN PM_SUBNET Subnet
  276. )
  277. {
  278. DWORD LocalError;
  279. DWORD Error;
  280. REG_HANDLE Hdl2;
  281. LPWSTR Name = NULL;
  282. LPWSTR Comment = NULL;
  283. DWORD Flags;
  284. DWORD StartAddress;
  285. DWORD EndAddress;
  286. LPBYTE InUseClusters = NULL;
  287. DWORD InUseClustersSize;
  288. LPBYTE UsedClusters = NULL;
  289. DWORD UsedClustersSize;
  290. ULONG Alloc, MaxAlloc;
  291. PM_RANGE OverlappingRange;
  292. PM_RANGE ThisRange = NULL;
  293. BOOL fRangeAdded = FALSE;
  294. Error = DhcpRegSubnetGetRangeHdl(Hdl, RangeName, &Hdl2);
  295. if( ERROR_SUCCESS != Error ) return Error;
  296. Error = DhcpRegRangeGetAttributes(
  297. &Hdl2,
  298. &Name,
  299. &Comment,
  300. &Flags,
  301. &Alloc,
  302. &MaxAlloc,
  303. &StartAddress,
  304. &EndAddress,
  305. &InUseClusters,
  306. &InUseClustersSize,
  307. &UsedClusters,
  308. &UsedClustersSize
  309. );
  310. ERRCHK;
  311. if( 0 == StartAddress || 0 == EndAddress ) {
  312. INVALID_REG("[DHCPServer] Noticed undefined range: %ws (ignored)\n", RangeName);
  313. Error = ERROR_SUCCESS;
  314. goto Cleanup;
  315. }
  316. if( FALSE == Subnet->fSubnet && GlobalWorkingOnPreWin2kMScope ) {
  317. Subnet->MScopeId = StartAddress;
  318. GlobalWorkingOnPreWin2kMScope = FALSE;
  319. }
  320. Error = MemSubnetAddRange(
  321. Subnet,
  322. StartAddress,
  323. EndAddress,
  324. Flags,
  325. Alloc,
  326. MaxAlloc,
  327. &OverlappingRange,
  328. INVALID_UNIQ_ID
  329. );
  330. ERRCHK;
  331. fRangeAdded = TRUE;
  332. Error = MemSubnetGetAddressInfo(
  333. Subnet,
  334. StartAddress,
  335. &ThisRange,
  336. NULL,
  337. NULL
  338. );
  339. ERRCHK;
  340. if( InUseClustersSize || UsedClustersSize ) {
  341. //
  342. // Old style information? Save it as new style
  343. //
  344. GlobalWorkingOnOldStyleSubnet ++;
  345. DhcpRegFillClusterAddresses(
  346. ThisRange,
  347. InUseClusters,
  348. InUseClustersSize,
  349. UsedClusters,
  350. UsedClustersSize
  351. ); // this is always returning ERROR_SUCCESS.
  352. //
  353. // Error = FlushRanges(ThisRange, FLUSH_ANYWAY, Subnet);
  354. // Require( ERROR_SUCCESS == Error );
  355. //
  356. // Do not actually write back the stuff to the registry..
  357. // This read code path is used in dhcpexim at which time
  358. // the registry should not be munged..
  359. //
  360. } else {
  361. //
  362. // Need to read new style bitmasks..
  363. //
  364. Error = DhcpRegpFillBitmasks(
  365. Hdl2.Key,
  366. ThisRange,
  367. Subnet
  368. );
  369. Require( ERROR_SUCCESS == Error );
  370. }
  371. Cleanup:
  372. Report("SubnetAddRange");
  373. if( ERROR_SUCCESS != Error && ThisRange ) {
  374. if( !fRangeAdded ) {
  375. LocalError = MemRangeCleanup(ThisRange);
  376. Require( ERROR_SUCCESS == LocalError );
  377. } else {
  378. LocalError = MemSubnetDelRange(
  379. Subnet, StartAddress );
  380. Require( ERROR_SUCCESS == LocalError );
  381. }
  382. }
  383. if( Name ) MemFree(Name);
  384. if( Comment ) MemFree(Comment);
  385. if( InUseClusters ) MemFree(InUseClusters);
  386. if( UsedClusters ) MemFree(UsedClusters);
  387. LocalError = DhcpRegCloseHdl(&Hdl2);
  388. Require(ERROR_SUCCESS == LocalError);
  389. return Error;
  390. }
  391. DWORD
  392. DhcpRegpReservationAddOption(
  393. IN PREG_HANDLE Hdl,
  394. IN LPWSTR OptionName,
  395. IN PM_RESERVATION Reservation
  396. )
  397. {
  398. DWORD Error;
  399. DWORD LocalError;
  400. REG_HANDLE Hdl2;
  401. DWORD OptionId;
  402. LPWSTR ClassName = NULL;
  403. LPWSTR VendorName = NULL;
  404. DWORD Flags;
  405. LPBYTE Value = NULL;
  406. DWORD ValueSize;
  407. DWORD ClassId;
  408. DWORD VendorId;
  409. PM_OPTION Option = NULL;
  410. PM_OPTION DeletedOption = NULL;
  411. PM_CLASSDEF ThisClasDef;
  412. Error = DhcpRegReservationGetOptHdl(Hdl, OptionName, &Hdl2);
  413. if(ERROR_SUCCESS != Error) return Error;
  414. Error = DhcpRegOptGetAttributes(
  415. &Hdl2,
  416. &OptionId,
  417. &ClassName,
  418. &VendorName,
  419. &Flags,
  420. &Value,
  421. &ValueSize
  422. );
  423. ERRCHK;
  424. if( OptionId == 0 ) // old registry format does not contain "OptionId" value => it can be taken from the key name.
  425. OptionId = _wtol(OptionName);
  426. if( OptionId == 0 || NULL == Value || 0 == ValueSize ) {
  427. INVALID_REG("[DHCPServer] Found invalid option %ws (ignored)\n", OptionName);
  428. Error = ERROR_SUCCESS;
  429. goto Cleanup;
  430. }
  431. if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0;
  432. else {
  433. PM_SUBNET Subnet = Reservation->SubnetPtr;
  434. PM_SERVER Server = Subnet->ServerPtr;
  435. Error = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClasDef);
  436. if( ERROR_SUCCESS != Error ) {
  437. if (*(DWORD *)ClassName != OptionId) // some registry entries were corrupted due to an old bug. Load these entries too (see bug #192933)
  438. {
  439. INVALID_REG("ReservationAddOption(%ws): unknown class (ignored)\n", OptionName);
  440. Error = ERROR_SUCCESS;
  441. goto Cleanup;
  442. }
  443. else
  444. {
  445. ClassId = 0;
  446. }
  447. } else {
  448. ClassId = ThisClasDef->ClassId;
  449. Require(ThisClasDef->IsVendor == FALSE);
  450. }
  451. }
  452. if( NULL == VendorName || wcslen(VendorName) == 0 ) VendorId = 0;
  453. else {
  454. PM_SUBNET Subnet = Reservation->SubnetPtr;
  455. PM_SERVER Server = Subnet->ServerPtr;
  456. Error = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClasDef);
  457. if( ERROR_SUCCESS != Error ) {
  458. INVALID_REG("ReservationAddOption(%ws): unknown vendor (ignored)\n", OptionName);
  459. Error = ERROR_SUCCESS;
  460. goto Cleanup;
  461. } else {
  462. VendorId = ThisClasDef->ClassId;
  463. Require(ThisClasDef->IsVendor == TRUE);
  464. }
  465. }
  466. if( 0 == OptionId ) OptionId = ConvertWStringToDWORD(OptionName);
  467. Error = MemOptInit(&Option, OptionId, ValueSize, Value);
  468. ERRCHK;
  469. Error = MemOptClassAddOption( &(Reservation->Options), Option, ClassId,
  470. VendorId, &DeletedOption, INVALID_UNIQ_ID );
  471. ERRCHK;
  472. Cleanup:
  473. Report("ReservationAddOption");
  474. LocalError = DhcpRegCloseHdl(&Hdl2);
  475. Require(ERROR_SUCCESS == LocalError);
  476. if( ClassName ) MemFree(ClassName);
  477. if( VendorName ) MemFree(VendorName);
  478. if( Value ) MemFree(Value);
  479. if( DeletedOption ) {
  480. LocalError = MemOptCleanup(DeletedOption);
  481. Require(ERROR_SUCCESS == LocalError);
  482. }
  483. if( ERROR_SUCCESS != Error && Option ) {
  484. LocalError = MemOptCleanup(Option);
  485. Require(ERROR_SUCCESS == LocalError);
  486. }
  487. return Error;
  488. }
  489. DWORD
  490. DhcpRegpSubnetAddReservation(
  491. IN PREG_HANDLE Hdl,
  492. IN LPWSTR ReservationName,
  493. IN PM_SUBNET Subnet
  494. )
  495. {
  496. DWORD LocalError;
  497. DWORD Error;
  498. REG_HANDLE Hdl2;
  499. LPWSTR Name = NULL;
  500. LPWSTR Comment = NULL;
  501. DWORD Flags;
  502. DWORD Address;
  503. LPBYTE ClientUID = NULL;
  504. DWORD ClientUIDSize;
  505. PM_RESERVATION ThisReservation;
  506. ARRAY Options;
  507. Error = DhcpRegSubnetGetReservationHdl(Hdl, ReservationName, &Hdl2);
  508. if( ERROR_SUCCESS != Error ) return Error;
  509. Error = DhcpRegReservationGetAttributes(
  510. &Hdl2,
  511. &Name,
  512. &Comment,
  513. &Flags,
  514. &Address,
  515. &ClientUID,
  516. &ClientUIDSize
  517. );
  518. ERRCHK;
  519. if( 0 == Address || NULL == ClientUID || 0 == ClientUIDSize ) {
  520. INVALID_REG("[DHCPServer] Found invalid reservation %ws (ignored)\n", ReservationName);
  521. Error = ERROR_SUCCESS;
  522. goto Cleanup;
  523. }
  524. Error = MemReserveAdd(
  525. &(Subnet->Reservations),
  526. Address,
  527. Flags,
  528. ClientUID,
  529. ClientUIDSize,
  530. INVALID_UNIQ_ID
  531. );
  532. // if the reservation is a duplicate ignore the error and do no further processing as the
  533. // reservation structure was already initialized. The duplicate reservation will simply be
  534. // ignored.
  535. if (ERROR_SUCCESS == Error)
  536. {
  537. Error = MemReserveFindByAddress(
  538. &(Subnet->Reservations),
  539. Address,
  540. &ThisReservation
  541. );
  542. ERRCHK;
  543. ThisReservation->SubnetPtr = Subnet;
  544. Error = MemArrayInit(&Options);
  545. ERRCHK;
  546. Error = DhcpRegReservationGetList(
  547. &Hdl2,
  548. &Options
  549. );
  550. ERRCHK;
  551. Error = LoopThruArray(&Options, DhcpRegpReservationAddOption, &Hdl2, ThisReservation);
  552. } else if ( ERROR_OBJECT_ALREADY_EXISTS == Error )
  553. Error = ERROR_SUCCESS;
  554. Cleanup:
  555. Report("SubnetAddReservation");
  556. if( Name ) MemFree(Name);
  557. if( Comment ) MemFree(Comment);
  558. if( ClientUID ) MemFree(ClientUID);
  559. LocalError = DhcpRegCloseHdl(&Hdl2);
  560. Require(ERROR_SUCCESS == LocalError);
  561. FreeArray(&Options);
  562. return Error;
  563. }
  564. DWORD
  565. DhcpRegpSubnetAddOption(
  566. IN PREG_HANDLE Hdl,
  567. IN LPWSTR OptionName,
  568. IN PM_SUBNET Subnet
  569. )
  570. {
  571. DWORD Error;
  572. DWORD LocalError;
  573. REG_HANDLE Hdl2;
  574. DWORD OptionId;
  575. LPWSTR ClassName = NULL;
  576. LPWSTR VendorName = NULL;
  577. DWORD Flags;
  578. LPBYTE Value = NULL;
  579. DWORD ValueSize;
  580. DWORD ClassId;
  581. DWORD VendorId;
  582. PM_OPTION Option = NULL;
  583. PM_OPTION DeletedOption = NULL;
  584. PM_CLASSDEF ThisClasDef;
  585. Error = DhcpRegSubnetGetOptHdl(Hdl, OptionName, &Hdl2);
  586. if(ERROR_SUCCESS != Error) return Error;
  587. Error = DhcpRegOptGetAttributes(
  588. &Hdl2,
  589. &OptionId,
  590. &ClassName,
  591. &VendorName,
  592. &Flags,
  593. &Value,
  594. &ValueSize
  595. );
  596. ERRCHK;
  597. if( OptionId == 0 ) // old registry format does not contain "OptionId" value => it can be taken from the key name.
  598. OptionId = _wtol(OptionName);
  599. if( OptionId == 0 || NULL == Value || 0 == ValueSize ) {
  600. INVALID_REG("[DHCPServer] Found invalid option %ws (ignored)\n", OptionName);
  601. Error = ERROR_SUCCESS;
  602. goto Cleanup;
  603. }
  604. if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0;
  605. else {
  606. Error = MemServerGetClassDef((PM_SERVER)(Subnet->ServerPtr),0, ClassName,0,NULL,&ThisClasDef);
  607. if( ERROR_SUCCESS != Error ) {
  608. if (*(DWORD *)ClassName != OptionId) // some registry entries were corrupted due to an old bug. Load these entries too (see bug #192933)
  609. {
  610. INVALID_REG("SubnetAddOption(%ws): unknown class (ignored)\n", OptionName);
  611. Error = ERROR_SUCCESS;
  612. goto Cleanup;
  613. }
  614. else
  615. {
  616. ClassId = 0;
  617. }
  618. } else {
  619. ClassId = ThisClasDef->ClassId;
  620. Require(ThisClasDef->IsVendor == FALSE);
  621. }
  622. }
  623. if( NULL == VendorName || wcslen(VendorName) == 0 ) VendorId = 0;
  624. else {
  625. Error = MemServerGetClassDef((PM_SERVER)(Subnet->ServerPtr),0, VendorName,0,NULL,&ThisClasDef);
  626. if( ERROR_SUCCESS != Error ) {
  627. INVALID_REG("SubnetAddOption(%ws): unknown class (ignored)\n", OptionName);
  628. Error = ERROR_SUCCESS;
  629. goto Cleanup;
  630. } else {
  631. VendorId = ThisClasDef->ClassId;
  632. Require(ThisClasDef->IsVendor == TRUE);
  633. }
  634. }
  635. if( 0 == OptionId ) OptionId = ConvertWStringToDWORD(OptionName);
  636. Error = MemOptInit(&Option, OptionId, ValueSize, Value);
  637. ERRCHK;
  638. Error = MemOptClassAddOption( &(Subnet->Options), Option, ClassId,
  639. VendorId, &DeletedOption, INVALID_UNIQ_ID );
  640. ERRCHK;
  641. Cleanup:
  642. Report("Subnet Add Option");
  643. LocalError = DhcpRegCloseHdl(&Hdl2);
  644. Require(ERROR_SUCCESS == LocalError);
  645. if( ClassName ) MemFree(ClassName);
  646. if( VendorName ) MemFree(VendorName);
  647. if( Value ) MemFree(Value);
  648. if( DeletedOption ) {
  649. LocalError = MemOptCleanup(DeletedOption);
  650. Require(ERROR_SUCCESS == LocalError);
  651. }
  652. if( ERROR_SUCCESS != Error && Option ) {
  653. LocalError = MemOptCleanup(Option);
  654. Require(ERROR_SUCCESS == LocalError);
  655. }
  656. return Error;
  657. }
  658. DWORD
  659. DhcpRegSubnetAddExclusions(
  660. IN PM_SUBNET Subnet,
  661. IN LPBYTE Excl,
  662. IN DWORD ExclSize
  663. )
  664. {
  665. DWORD UNALIGNED* Addr;
  666. DWORD Count, i, j;
  667. DWORD Error;
  668. PM_EXCL OverlappingExcl;
  669. Count = ExclSize / sizeof(DWORD);
  670. Addr = (DWORD UNALIGNED*)Excl;
  671. if( 0 == Count || 0 == Addr[0] || 0 == Addr[1] ) {
  672. INVALID_REG("[DHCPServer] invalid exclusion ignored\n");
  673. return ERROR_SUCCESS;
  674. }
  675. Require(Count == 2*Addr[0] + 1);
  676. Count --; Addr ++;
  677. while(Count) {
  678. Error = MemSubnetAddExcl(
  679. Subnet,
  680. Addr[0],
  681. Addr[1],
  682. &OverlappingExcl,
  683. INVALID_UNIQ_ID
  684. );
  685. if( ERROR_SUCCESS != Error ) {
  686. INVALID_REG("[DHCPServer] DhcpRegSubnetAddExclusions:MemSubnetAddExcl;0x%lx\n", Error);
  687. } else {
  688. if( Subnet->fSubnet && GlobalWorkingOnOldStyleSubnet ) {
  689. //
  690. // For subnets alone (not mscopes), check if
  691. // we are upgrading from pre-win2k -- then make sure
  692. // all address from the excluded range are removed
  693. // from the bitmask
  694. //
  695. for( i = Addr[0]; i <= Addr[1]; i ++ ) {
  696. MemSubnetReleaseAddress(
  697. Subnet, i, FALSE
  698. );
  699. }
  700. }
  701. }
  702. Addr += 2;
  703. Count -= 2;
  704. }
  705. return ERROR_SUCCESS;
  706. }
  707. DWORD
  708. DhcpRegServerAddSubnet(
  709. IN PREG_HANDLE Hdl,
  710. IN PM_SERVER Server,
  711. IN PM_SUBNET Subnet
  712. )
  713. {
  714. DWORD Error;
  715. DWORD Index;
  716. ARRAY Servers;
  717. ARRAY IpRanges;
  718. ARRAY Reservations;
  719. ARRAY Options;
  720. LPBYTE Excl = NULL;
  721. DWORD ExclSize;
  722. struct {
  723. PARRAY Array;
  724. ARRAY_FN Fn;
  725. } Lists[] = {
  726. &Servers, DhcpRegpSubnetAddServer,
  727. &IpRanges, DhcpRegpSubnetAddRange,
  728. &Reservations, DhcpRegpSubnetAddReservation,
  729. &Options, DhcpRegpSubnetAddOption
  730. };
  731. Subnet->ServerPtr = Server;
  732. for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) {
  733. InitArray(Lists[Index].Array);
  734. }
  735. Error = DhcpRegSubnetGetList(
  736. Hdl, &Servers, &IpRanges, &Reservations, &Options, &Excl, &ExclSize
  737. );
  738. GlobalWorkingOnOldStyleSubnet = 0;
  739. for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) {
  740. Error = LoopThruArray(Lists[Index].Array, Lists[Index].Fn, Hdl, Subnet);
  741. ERRCHK;
  742. }
  743. if( GlobalWorkingOnOldStyleSubnet ) {
  744. Report("Old style subnet found, careful with exclusions\n");
  745. }
  746. if( Excl ) Error = DhcpRegSubnetAddExclusions(Subnet, Excl, ExclSize);
  747. ERRCHK;
  748. Error = Subnet->fSubnet ? MemServerAddSubnet(Server, Subnet, INVALID_UNIQ_ID )
  749. : MemServerAddMScope(Server, Subnet, INVALID_UNIQ_ID );
  750. Cleanup:
  751. GlobalWorkingOnOldStyleSubnet = 0;
  752. GlobalWorkingOnPreWin2kMScope = 0;
  753. Report("ServerAddSubnet");
  754. for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) {
  755. FreeArray(Lists[Index].Array);
  756. }
  757. return Error;
  758. }
  759. DWORD
  760. DhcpRegServerAddMScope(
  761. IN PREG_HANDLE Hdl,
  762. IN PM_SERVER Server,
  763. IN PM_MSCOPE MScope
  764. )
  765. {
  766. return DhcpRegServerAddSubnet(Hdl, Server, MScope);
  767. }
  768. DWORD
  769. DhcpRegServerAddSScope(
  770. IN PREG_HANDLE Hdl,
  771. IN PM_SERVER Server,
  772. IN PM_SSCOPE SScope
  773. )
  774. {
  775. DWORD Error;
  776. ARRAY Subnets;
  777. ARRAY_LOCATION Loc;
  778. LPWSTR SubnetWString;
  779. DWORD SubnetAddress;
  780. PM_SUBNET Subnet;
  781. InitArray(&Subnets);
  782. Error = DhcpRegSScopeGetList(Hdl, &Subnets);
  783. ERRCHK;
  784. Error = MemArrayInitLoc(&Subnets, &Loc);
  785. while(ERROR_FILE_NOT_FOUND != Error) {
  786. Require(ERROR_SUCCESS == Error);
  787. Error = MemArrayGetElement(&Subnets, &Loc, &SubnetWString);
  788. Require(ERROR_SUCCESS == Error && SubnetWString);
  789. SubnetAddress = WStringToAddress(SubnetWString);
  790. Error = MemServerGetAddressInfo(
  791. Server,
  792. SubnetAddress,
  793. &Subnet,
  794. NULL,
  795. NULL,
  796. NULL
  797. );
  798. if( ERROR_SUCCESS == Error && Subnet ) {
  799. Error = MemSubnetSetSuperScope(Subnet,SScope);
  800. Require(ERROR_SUCCESS == Error);
  801. }
  802. Error = MemArrayNextLoc(&Subnets, &Loc);
  803. }
  804. Error = MemServerAddSScope( Server, SScope );
  805. Cleanup:
  806. Report("ServerAddSScope");
  807. FreeArray(&Subnets);
  808. return Error;
  809. } // DhcpRegpServerAddSScope()
  810. DWORD
  811. DhcpRegpServerAddSubnet(
  812. IN PREG_HANDLE Hdl,
  813. IN LPWSTR SubnetName,
  814. IN PM_SERVER Server
  815. )
  816. {
  817. DWORD Error;
  818. DWORD LocalError;
  819. REG_HANDLE Hdl2;
  820. LPWSTR Name = NULL;
  821. LPWSTR Comment = NULL;
  822. DWORD Address;
  823. DWORD Flags;
  824. DWORD Mask;
  825. PM_SUBNET Subnet = NULL;
  826. Error = DhcpRegServerGetSubnetHdl(Hdl, SubnetName, &Hdl2);
  827. if(ERROR_SUCCESS != Error) return Error;
  828. Error = DhcpRegSubnetGetAttributes(
  829. &Hdl2,
  830. &Name,
  831. &Comment,
  832. &Flags,
  833. &Address,
  834. &Mask
  835. );
  836. ERRCHK;
  837. if( NULL == Name || 0 == Address || 0 == Mask ) {
  838. INVALID_REG("[DHCPServer] invalid subnet %ws ignored\n", SubnetName);
  839. Error = ERROR_SUCCESS;
  840. goto Cleanup;
  841. }
  842. Error = MemSubnetInit(
  843. &Subnet,
  844. Address,
  845. Mask,
  846. Flags,
  847. 0,
  848. Name,
  849. Comment
  850. );
  851. ERRCHK;
  852. Error = DhcpRegServerAddSubnet(&Hdl2, Server, Subnet);
  853. Cleanup:
  854. Report("ServerAddSubnet");
  855. LocalError = DhcpRegCloseHdl(&Hdl2);
  856. Require( ERROR_SUCCESS == LocalError);
  857. if( Name ) MemFree(Name);
  858. if( Comment ) MemFree(Comment);
  859. if( ERROR_SUCCESS != Error ) {
  860. if( Subnet ) {
  861. LocalError = MemSubnetCleanup(Subnet);
  862. Require(ERROR_SUCCESS == LocalError);
  863. }
  864. }
  865. return Error;
  866. }
  867. DWORD
  868. DhcpRegpServerAddMScope(
  869. IN PREG_HANDLE Hdl,
  870. IN LPWSTR MScopeName,
  871. IN PM_SERVER Server
  872. ) {
  873. DWORD Error;
  874. DWORD LocalError;
  875. REG_HANDLE Hdl2;
  876. LPWSTR Comment = NULL;
  877. DWORD State;
  878. DWORD ScopeId;
  879. DWORD Policy;
  880. PM_MSCOPE MScope = NULL;
  881. LPWSTR LangTag = NULL;
  882. DWORD TTL = 32;
  883. PDATE_TIME ExpiryTime = NULL;
  884. GlobalWorkingOnPreWin2kMScope = 0;
  885. Error = DhcpRegServerGetMScopeHdl(Hdl, MScopeName, &Hdl2);
  886. if(ERROR_SUCCESS != Error) return Error;
  887. Error = DhcpRegMScopeGetAttributes(
  888. &Hdl2,
  889. &Comment,
  890. &State,
  891. &ScopeId,
  892. &Policy,
  893. &TTL,
  894. &LangTag,
  895. &ExpiryTime
  896. );
  897. if( ERROR_INVALID_DATA == Error ) {
  898. GlobalWorkingOnPreWin2kMScope = TRUE;
  899. //
  900. // hackorama isn't it?
  901. //
  902. Error = NO_ERROR;
  903. }
  904. ERRCHK;
  905. if( 0 == ScopeId || GlobalWorkingOnPreWin2kMScope ) {
  906. INVALID_REG("[DHCPServer] invalid m-scope %ws, id %ld ignored\n", MScopeName, ScopeId);
  907. Error = ERROR_SUCCESS;
  908. //goto Cleanup;
  909. }
  910. Error = MemMScopeInit(
  911. &MScope,
  912. ScopeId,
  913. State,
  914. Policy,
  915. (BYTE)TTL,
  916. MScopeName,
  917. Comment,
  918. LangTag,
  919. *ExpiryTime
  920. );
  921. ERRCHK;
  922. Error = DhcpRegServerAddMScope(&Hdl2, Server, MScope);
  923. Cleanup:
  924. GlobalWorkingOnPreWin2kMScope = 0;
  925. Report("Server Add MScope");
  926. LocalError = DhcpRegCloseHdl(&Hdl2);
  927. Require(ERROR_SUCCESS == LocalError);
  928. if( Comment ) MemFree(Comment);
  929. if( LangTag ) MemFree(LangTag);
  930. if( ExpiryTime ) MemFree(ExpiryTime);
  931. if( ERROR_SUCCESS != Error ) {
  932. if( MScope ) {
  933. LocalError = MemMScopeCleanup(MScope);
  934. Require(ERROR_SUCCESS == Error);
  935. }
  936. }
  937. return Error;
  938. }
  939. DWORD
  940. DhcpRegpServerAddSScope(
  941. IN PREG_HANDLE Hdl,
  942. IN LPWSTR SScopeName,
  943. IN PM_SERVER Server
  944. ) {
  945. DWORD Error;
  946. DWORD LocalError;
  947. REG_HANDLE Hdl2;
  948. LPWSTR Name = NULL;
  949. LPWSTR Comment = NULL;
  950. DWORD Flags;
  951. PM_SSCOPE SScope = NULL;
  952. Error = DhcpRegServerGetSScopeHdl(Hdl, SScopeName, &Hdl2);
  953. if(ERROR_SUCCESS != Error) return Error;
  954. #if 0 // superscope name is given above -- nothing else to be done
  955. Error = DhcpRegSScopeGetAttributes(
  956. &Hdl2,
  957. &Name,
  958. &Description,
  959. &Flags
  960. );
  961. ERRCHK;
  962. #endif
  963. Error = MemSScopeInit(
  964. &SScope,
  965. 0,
  966. SScopeName
  967. );
  968. ERRCHK;
  969. Error = DhcpRegServerAddSScope(&Hdl2, Server, SScope);
  970. Cleanup:
  971. Report("Server Add Scope");
  972. LocalError = DhcpRegCloseHdl(&Hdl2);
  973. Require(ERROR_SUCCESS == LocalError);
  974. if( ERROR_SUCCESS != Error ) {
  975. if( SScope ) {
  976. LocalError = MemSScopeCleanup(SScope);
  977. Require(ERROR_SUCCESS == Error);
  978. }
  979. }
  980. return Error;
  981. }
  982. DWORD
  983. DhcpRegpServerAddOption(
  984. IN PREG_HANDLE Hdl,
  985. IN LPWSTR OptionName,
  986. IN PM_SERVER Server
  987. ) {
  988. DWORD Error;
  989. DWORD LocalError;
  990. REG_HANDLE Hdl2;
  991. DWORD OptionId;
  992. LPWSTR ClassName = NULL;
  993. LPWSTR VendorName = NULL;
  994. DWORD Flags;
  995. LPBYTE Value = NULL;
  996. DWORD ValueSize;
  997. DWORD ClassId;
  998. DWORD VendorId;
  999. PM_OPTION Option = NULL;
  1000. PM_OPTION DeletedOption = NULL;
  1001. PM_CLASSDEF ThisClasDef;
  1002. Error = DhcpRegServerGetOptHdl(Hdl, OptionName, &Hdl2);
  1003. if(ERROR_SUCCESS != Error) return Error;
  1004. Error = DhcpRegOptGetAttributes(
  1005. &Hdl2,
  1006. &OptionId,
  1007. &ClassName,
  1008. &VendorName,
  1009. &Flags,
  1010. &Value,
  1011. &ValueSize
  1012. );
  1013. ERRCHK;
  1014. if( OptionId == 0 ) // old registry format does not contain "OptionId" value => it can be taken from the key name.
  1015. OptionId = _wtol(OptionName);
  1016. if( 0 == OptionId || NULL == Value || 0 == ValueSize ) {
  1017. INVALID_REG("[DHCPServer] found invalid option %ws (ignored)\n", OptionName );
  1018. Error = ERROR_SUCCESS;
  1019. goto Cleanup;
  1020. }
  1021. if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0;
  1022. else {
  1023. Error = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClasDef);
  1024. if( ERROR_SUCCESS != Error ) {
  1025. if (*(DWORD *)ClassName != OptionId) // some registry entries were corrupted due to an old bug. Load these entries too (see bug #192933)
  1026. {
  1027. INVALID_REG("ServerAddOption(%ws): unknown class (ignored)\n", OptionName);
  1028. Error = ERROR_SUCCESS;
  1029. goto Cleanup;
  1030. }
  1031. else
  1032. {
  1033. ClassId = 0;
  1034. }
  1035. } else {
  1036. ClassId = ThisClasDef->ClassId;
  1037. Require(ThisClasDef->IsVendor == FALSE);
  1038. }
  1039. }
  1040. if( NULL == VendorName || wcslen(VendorName) == 0) VendorId = 0;
  1041. else {
  1042. Error = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClasDef);
  1043. if( ERROR_SUCCESS != Error ) {
  1044. INVALID_REG("ServerAddOption(%ws): unknown class (ignored)\n", OptionName);
  1045. Error = ERROR_SUCCESS;
  1046. goto Cleanup;
  1047. } else {
  1048. VendorId = ThisClasDef->ClassId;
  1049. Require(ThisClasDef->IsVendor == TRUE);
  1050. }
  1051. }
  1052. Error = MemOptInit(&Option, OptionId, ValueSize, Value);
  1053. ERRCHK;
  1054. Error = MemOptClassAddOption( &(Server->Options), Option, ClassId,
  1055. VendorId, &DeletedOption, INVALID_UNIQ_ID );
  1056. ERRCHK;
  1057. Cleanup:
  1058. Report("Server Add Option");
  1059. LocalError = DhcpRegCloseHdl(&Hdl2);
  1060. Require(ERROR_SUCCESS == LocalError);
  1061. if( ClassName ) MemFree(ClassName);
  1062. if( VendorName ) MemFree(VendorName);
  1063. if( Value ) MemFree(Value);
  1064. if( DeletedOption ) {
  1065. LocalError = MemOptCleanup(DeletedOption);
  1066. Require(ERROR_SUCCESS == LocalError);
  1067. }
  1068. if( ERROR_SUCCESS != Error && Option ) {
  1069. LocalError = MemOptCleanup(Option);
  1070. Require(ERROR_SUCCESS == LocalError);
  1071. }
  1072. return Error;
  1073. }
  1074. DWORD
  1075. DhcpRegpServerAddDefList(
  1076. IN PREG_HANDLE Hdl,
  1077. IN LPWSTR DefName,
  1078. IN PM_SERVER Server
  1079. ) {
  1080. DWORD Error;
  1081. DWORD LocalError;
  1082. REG_HANDLE Hdl2;
  1083. LPWSTR Name = NULL;
  1084. LPWSTR Comments = NULL;
  1085. DWORD Flags;
  1086. DWORD OptionId;
  1087. LPWSTR ClassName = NULL;
  1088. LPWSTR VendorName = NULL;
  1089. DWORD ClassId;
  1090. DWORD VendorId;
  1091. LPBYTE Value = NULL;
  1092. DWORD ValueSize;
  1093. PM_CLASSDEF ThisClassDef;
  1094. Error = DhcpRegServerGetOptDefHdl(Hdl, DefName, &Hdl2);
  1095. if(ERROR_SUCCESS != Error) return Error;
  1096. Error = DhcpRegOptDefGetAttributes(
  1097. &Hdl2,
  1098. &Name,
  1099. &Comments,
  1100. &Flags,
  1101. &OptionId,
  1102. &ClassName,
  1103. &VendorName,
  1104. &Value,
  1105. &ValueSize
  1106. );
  1107. ERRCHK;
  1108. if( OptionId == 0)
  1109. OptionId = _wtol(DefName);
  1110. if( NULL == Name || 0 == OptionId ) {
  1111. INVALID_REG("[DHCPServer] invalid option def %ws ignored\n", DefName );
  1112. Error = ERROR_SUCCESS;
  1113. goto Cleanup;
  1114. }
  1115. if( NULL == ClassName || wcslen(ClassName) == 0) ClassId = 0;
  1116. else {
  1117. Error = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClassDef);
  1118. if( ERROR_SUCCESS != Error ) ClassId = 0;
  1119. else {
  1120. ClassId = ThisClassDef->ClassId;
  1121. Require(ThisClassDef->IsVendor == FALSE);
  1122. }
  1123. }
  1124. if( NULL == VendorName || wcslen(VendorName) == 0 ) VendorId = 0;
  1125. else {
  1126. Error = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClassDef);
  1127. if( ERROR_SUCCESS != Error ) VendorId = 0;
  1128. else {
  1129. VendorId = ThisClassDef->ClassId;
  1130. Require(ThisClassDef->IsVendor == TRUE);
  1131. }
  1132. }
  1133. Error = MemOptClassDefListAddOptDef(
  1134. &(Server->OptDefs),
  1135. ClassId,
  1136. VendorId,
  1137. OptionId,
  1138. Flags,
  1139. Name,
  1140. Comments,
  1141. Value,
  1142. ValueSize,
  1143. INVALID_UNIQ_ID
  1144. );
  1145. Cleanup:
  1146. Report("Server Add DefList");
  1147. LocalError = DhcpRegCloseHdl(&Hdl2);
  1148. Require(ERROR_SUCCESS == LocalError);
  1149. if( Name ) MemFree(Name);
  1150. if( Comments ) MemFree(Comments);
  1151. if( ClassName ) MemFree(ClassName);
  1152. if( VendorName ) MemFree(VendorName);
  1153. if( Value ) MemFree(Value);
  1154. return Error;
  1155. }
  1156. DWORD
  1157. DhcpRegpServerAddClassDef(
  1158. IN PREG_HANDLE Hdl,
  1159. IN LPWSTR ClassDefName,
  1160. IN PM_SERVER Server
  1161. ) {
  1162. DWORD Error;
  1163. DWORD LocalError;
  1164. REG_HANDLE Hdl2;
  1165. LPWSTR Name = NULL;
  1166. LPWSTR Comment = NULL;
  1167. DWORD Flags;
  1168. LPBYTE Value = NULL;
  1169. DWORD ValueSize;
  1170. Error = DhcpRegServerGetClassDefHdl(Hdl, ClassDefName, &Hdl2);
  1171. if(ERROR_SUCCESS != Error) return Error;
  1172. Error = DhcpRegClassDefGetAttributes(
  1173. &Hdl2,
  1174. &Name,
  1175. &Comment,
  1176. &Flags,
  1177. &Value,
  1178. &ValueSize
  1179. );
  1180. ERRCHK;
  1181. if( NULL == Name || 0 == ValueSize || NULL == Value ) {
  1182. INVALID_REG("[DHCPServer] invalid class def %ws ignored\n", ClassDefName);
  1183. Error = ERROR_SUCCESS;
  1184. goto Cleanup;
  1185. }
  1186. Error = MemClassDefListAddClassDef(
  1187. &(Server->ClassDefs),
  1188. MemNewClassId(),
  1189. Flags,
  1190. 0, /* no Type... */
  1191. Name,
  1192. Comment,
  1193. Value,
  1194. ValueSize,
  1195. INVALID_UNIQ_ID
  1196. );
  1197. ERRCHK;
  1198. Cleanup:
  1199. Report("Server Add ClassDef");
  1200. LocalError = DhcpRegCloseHdl(&Hdl2);
  1201. Require(ERROR_SUCCESS == LocalError);
  1202. if( Name ) MemFree(Name);
  1203. if( Comment ) MemFree(Comment);
  1204. if( Value ) MemFree(Value);
  1205. return Error;
  1206. }
  1207. //BeginExport(function)
  1208. DWORD
  1209. DhcpRegReadSubServer( // read all the sub objects of a server and add 'em
  1210. IN PREG_HANDLE Hdl,
  1211. IN OUT PM_SERVER Server
  1212. ) //EndExport(function)
  1213. {
  1214. DWORD Error;
  1215. DWORD Index;
  1216. ARRAY OptList;
  1217. ARRAY DefList;
  1218. ARRAY ClassDefs;
  1219. ARRAY Subnets;
  1220. ARRAY MScopes;
  1221. ARRAY SScopes;
  1222. struct {
  1223. PARRAY Array;
  1224. ARRAY_FN Fn;
  1225. } Lists[] = {
  1226. &ClassDefs, DhcpRegpServerAddClassDef,
  1227. &DefList, DhcpRegpServerAddDefList,
  1228. &OptList, DhcpRegpServerAddOption,
  1229. &Subnets, DhcpRegpServerAddSubnet,
  1230. &MScopes, DhcpRegpServerAddMScope,
  1231. &SScopes, DhcpRegpServerAddSScope
  1232. };
  1233. for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) {
  1234. InitArray(Lists[Index].Array);
  1235. }
  1236. Error = DhcpRegServerGetList(
  1237. Hdl, &OptList, &DefList, &Subnets, &SScopes, &ClassDefs, &MScopes
  1238. );
  1239. ERRCHK;
  1240. for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) {
  1241. Error = LoopThruArray(Lists[Index].Array, Lists[Index].Fn, Hdl, Server);
  1242. ERRCHK;
  1243. }
  1244. Cleanup:
  1245. for( Index = 0; Index < sizeof(Lists)/sizeof(Lists[0]); Index ++ ) {
  1246. FreeArray(Lists[Index].Array);
  1247. }
  1248. Report("ServerAddSubServer");
  1249. return Error;
  1250. }
  1251. //BeginExport(function)
  1252. DWORD
  1253. DhcpRegReadServer( // read the server and all its sub objects
  1254. IN PREG_HANDLE Hdl,
  1255. OUT PM_SERVER *Server // return the created object
  1256. ) //EndExport(function)
  1257. {
  1258. DWORD Error;
  1259. LPWSTR Name;
  1260. LPWSTR Comments;
  1261. DWORD Flags;
  1262. PM_SERVER ThisServer;
  1263. Name = NULL; Comments = NULL; Flags = 0; ThisServer = NULL;
  1264. Error = DhcpRegServerGetAttributes(
  1265. Hdl,
  1266. &Name,
  1267. &Comments,
  1268. &Flags
  1269. );
  1270. if( ERROR_SUCCESS != Error ) goto Cleanup;
  1271. Error = MemServerInit(
  1272. &ThisServer,
  1273. 0xFFFFFFFF,
  1274. Flags,
  1275. 0,
  1276. Name,
  1277. Comments
  1278. );
  1279. if( ERROR_SUCCESS != Error ) goto Cleanup;
  1280. Error = DhcpRegReadSubServer(Hdl, ThisServer);
  1281. if( ERROR_SUCCESS != Error ) goto Cleanup;
  1282. *Server = ThisServer;
  1283. Cleanup:
  1284. if( NULL != Name ) MemFree(Name);
  1285. if( NULL != Comments) MemFree(Comments);
  1286. if( ERROR_SUCCESS != Error && NULL != ThisServer) {
  1287. MemServerCleanup(ThisServer);
  1288. }
  1289. return Error;
  1290. }
  1291. //BeginExport(function)
  1292. DWORD
  1293. DhcpRegReadThisServer( // recursively read for the current server
  1294. OUT PM_SERVER *Server
  1295. ) //EndExport(function)
  1296. {
  1297. DWORD Error;
  1298. REG_HANDLE ThisServer;
  1299. LPWSTR Name;
  1300. LPWSTR Comment;
  1301. Error = DhcpRegGetThisServer(&ThisServer);
  1302. if( ERROR_SUCCESS != Error ) return Error;
  1303. Error = DhcpRegReadServer(&ThisServer, Server);
  1304. DhcpRegCloseHdl(&ThisServer);
  1305. return Error;
  1306. }
  1307. DWORD
  1308. DhcpRegReadScopeBitmasks(
  1309. IN OUT PM_SUBNET Scope
  1310. )
  1311. {
  1312. PM_RANGE Range;
  1313. ARRAY_LOCATION Loc;
  1314. DWORD Error;
  1315. WCHAR SubnetStr[sizeof("000.000.000.000")];
  1316. REG_HANDLE Hdl, Hdl1;
  1317. Error = MemArrayInitLoc( &Scope->Ranges, &Loc);
  1318. while( NO_ERROR == Error ) {
  1319. Error = MemArrayGetElement( &Scope->Ranges, &Loc, &Range );
  1320. Require( NO_ERROR == Error && NULL != Range );
  1321. //
  1322. // Fill in the range
  1323. //
  1324. Error = DhcpRegpFillBitmasks(
  1325. NULL, Range, Scope );
  1326. ASSERT( NO_ERROR == Error );
  1327. Error = MemArrayNextLoc( &Scope->Ranges, &Loc );
  1328. }
  1329. if( ERROR_FILE_NOT_FOUND != Error ) return Error;
  1330. return NO_ERROR;
  1331. }
  1332. //BeginExport(function)
  1333. DWORD
  1334. DhcpRegReadServerBitmasks(
  1335. IN OUT PM_SERVER Server
  1336. ) // EndExport(function)
  1337. {
  1338. PM_SUBNET Scope, MScope;
  1339. ARRAY_LOCATION Loc;
  1340. DWORD Error;
  1341. Error = MemArrayInitLoc(&Server->Subnets, &Loc);
  1342. while( NO_ERROR == Error ) {
  1343. Error = MemArrayGetElement( &Server->Subnets, &Loc, &Scope);
  1344. Require( NO_ERROR == Error && NULL != Scope );
  1345. //
  1346. // get the keys to the scope in question
  1347. //
  1348. Error = DhcpRegReadScopeBitmasks(Scope);
  1349. if( NO_ERROR != Error ) return Error;
  1350. Error = MemArrayNextLoc( &Server->Subnets, &Loc );
  1351. }
  1352. if( ERROR_FILE_NOT_FOUND != Error ) return Error;
  1353. Error = MemArrayInitLoc(&Server->MScopes, &Loc);
  1354. while( NO_ERROR == Error ) {
  1355. Require( ERROR_SUCCESS == Error );
  1356. Error = MemArrayGetElement( &Server->MScopes, &Loc, &MScope);
  1357. Require( NO_ERROR == Error && NULL != MScope );
  1358. //
  1359. // get the keys to the scope in question
  1360. //
  1361. Error = DhcpRegReadScopeBitmasks(MScope);
  1362. if( NO_ERROR != Error ) return Error;
  1363. Error = MemArrayNextLoc( &Server->MScopes, &Loc );
  1364. }
  1365. if( ERROR_FILE_NOT_FOUND != Error ) return Error;
  1366. return NO_ERROR;
  1367. }
  1368. //================================================================================
  1369. // end of file
  1370. //================================================================================