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.

1443 lines
46 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: This module implements most of the reading part of the ds access
  5. //================================================================================
  6. //================================================================================
  7. // headers
  8. //================================================================================
  9. #include <hdrmacro.h>
  10. #include <store.h>
  11. #include <dhcpmsg.h>
  12. #include <wchar.h>
  13. #include <dhcpbas.h>
  14. #include <mm\opt.h> // need all the MM stuff...
  15. #include <mm\optl.h>
  16. #include <mm\optdefl.h>
  17. #include <mm\optclass.h>
  18. #include <mm\classdefl.h>
  19. #include <mm\bitmask.h>
  20. #include <mm\reserve.h>
  21. #include <mm\range.h>
  22. #include <mm\subnet.h>
  23. #include <mm\sscope.h>
  24. #include <mm\oclassdl.h>
  25. #include <mm\server.h>
  26. #include <mm\address.h>
  27. #include <mm\server2.h>
  28. #include <mm\memfree.h>
  29. #include <mmreg\regutil.h> // need all the registry stuff
  30. #include <mmreg\regread.h>
  31. #include <mmreg\regsave.h>
  32. #define DONT_USE_PARENT (0)
  33. //================================================================================
  34. // misc helper functions
  35. //================================================================================
  36. VOID
  37. ArrayMemFree( // free each ptr of the array using MemFree
  38. IN OUT PARRAY Array
  39. )
  40. {
  41. DWORD Result;
  42. ARRAY_LOCATION Loc;
  43. LPVOID Ptr;
  44. Result = MemArrayInitLoc(Array, &Loc);
  45. while( ERROR_FILE_NOT_FOUND != Result ) {
  46. //- ERROR_SUCCESS == Result
  47. Result = MemArrayGetElement(Array, &Loc, &Ptr);
  48. //- ERROR_SUCCESS == Result
  49. if( Ptr ) MemFree(Ptr);
  50. Result = MemArrayNextLoc(Array, &Loc);
  51. }
  52. MemArrayCleanup(Array);
  53. }
  54. //================================================================================
  55. // exported functions and helpers
  56. //================================================================================
  57. DWORD
  58. CheckoutAlternateOptions(
  59. IN OUT LPSTORE_HANDLE hContainer,
  60. IN PARRAY AltAttribs,
  61. IN OUT PARRAY OptDefAttribs,
  62. IN OUT PARRAY OptAttribs
  63. );
  64. DWORD
  65. CheckoutAlternateOptions1(
  66. IN OUT LPSTORE_HANDLE hContainer,
  67. IN PEATTRIB ThisAttrib,
  68. IN OUT PARRAY OptDefAttribs,
  69. IN OUT PARRAY OptAttribs
  70. )
  71. {
  72. DWORD Result;
  73. STORE_HANDLE hStore;
  74. ARRAY AlternateOptAttribs;
  75. if( !IS_ADSPATH_PRESENT(ThisAttrib) ) return ERROR_SUCCESS;
  76. Result = StoreGetHandle(
  77. /* hStore */ hContainer,
  78. /* Reserved */ DDS_RESERVED_DWORD,
  79. /* StoreGetType */ ThisAttrib->StoreGetType,
  80. /* Path */ ThisAttrib->ADsPath,
  81. /* hStoreOut */ &hStore
  82. );
  83. if( ERROR_DS_NO_SUCH_OBJECT == Result ) return ERROR_SUCCESS;
  84. if( ERROR_SUCCESS != Result ) return Result;
  85. MemArrayInit(&AlternateOptAttribs);
  86. Result = DhcpDsGetLists(
  87. /* Reserved */ DDS_RESERVED_DWORD,
  88. /* hStore */ &hStore,
  89. /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
  90. /* Servers */ NULL,
  91. /* Subnets */ NULL,
  92. /* IpAddress */ NULL,
  93. /* Mask */ NULL,
  94. /* Ranges */ NULL,
  95. /* Sites */ NULL,
  96. /* Reservations */ NULL,
  97. /* SuperScopes */ NULL,
  98. /* OptionDescripti */ OptDefAttribs,
  99. /* OptionsLocation */ &AlternateOptAttribs,
  100. /* Options */ OptAttribs,
  101. /* Classes */ NULL
  102. );
  103. CheckoutAlternateOptions(hContainer, &AlternateOptAttribs, OptDefAttribs, OptAttribs);
  104. StoreCleanupHandle(&hStore, DDS_RESERVED_DWORD );
  105. ArrayMemFree(&AlternateOptAttribs);
  106. return ERROR_SUCCESS;
  107. }
  108. DWORD
  109. CheckoutAlternateOptions(
  110. IN OUT LPSTORE_HANDLE hContainer,
  111. IN PARRAY AltAttribs,
  112. IN OUT PARRAY OptDefAttribs,
  113. IN OUT PARRAY OptAttribs
  114. )
  115. {
  116. DWORD Result;
  117. DWORD LastError;
  118. ARRAY_LOCATION Loc;
  119. PEATTRIB ThisAttrib;
  120. LastError = ERROR_SUCCESS;
  121. Result = MemArrayInitLoc(AltAttribs, &Loc);
  122. while( ERROR_FILE_NOT_FOUND != Result ) {
  123. //- ERROR_SUCCESS == Result
  124. Result = MemArrayGetElement(AltAttribs, &Loc, &ThisAttrib);
  125. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  126. Result = CheckoutAlternateOptions1(hContainer,ThisAttrib, OptDefAttribs, OptAttribs);
  127. if( ERROR_SUCCESS != Result ) LastError = Result;
  128. Result = MemArrayNextLoc(AltAttribs, &Loc);
  129. }
  130. return LastError;
  131. }
  132. DWORD
  133. DhcpOptClassAddOption(
  134. IN OUT PM_SERVER Server,
  135. IN OUT PM_OPTCLASS OptClass,
  136. IN PEATTRIB Option
  137. )
  138. {
  139. DWORD Result;
  140. LPWSTR ClassName;
  141. LPWSTR VendorName;
  142. DWORD OptionId, Flags;
  143. DWORD ValueSize;
  144. DWORD ClassId;
  145. DWORD VendorId;
  146. LPBYTE Value;
  147. PM_OPTION NewOption, DeletedOption;
  148. PM_CLASSDEF ThisClassDef;
  149. if( !IS_BINARY1_PRESENT(Option) || !IS_DWORD1_PRESENT(Option) )
  150. return ERROR_INVALID_DATA;
  151. if( IS_STRING4_PRESENT(Option) ) ClassName = Option->String4;
  152. else ClassName = NULL;
  153. if( IS_STRING3_PRESENT(Option) ) VendorName = Option->String3;
  154. else VendorName = NULL;
  155. OptionId = Option->Dword1;
  156. if( IS_FLAGS1_PRESENT(Option) ) Flags = Option->Flags1; else Flags = 0;
  157. Value = Option->Binary1;
  158. ValueSize = Option->BinLen1;
  159. if( NULL == ClassName ) ClassId = 0;
  160. else {
  161. Result = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClassDef);
  162. if( ERROR_SUCCESS != Result ) {
  163. // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", ClassName);
  164. ClassId =0;
  165. } else {
  166. ClassId = ThisClassDef->ClassId;
  167. //- ThisClassDef->IsVendor == FALSE
  168. }
  169. }
  170. if( NULL == VendorName ) VendorId = 0;
  171. else {
  172. Result = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClassDef);
  173. if( ERROR_SUCCESS != Result ) {
  174. // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", VendorName);
  175. VendorId =0;
  176. } else {
  177. VendorId = ThisClassDef->ClassId;
  178. //- ThisClassDef->IsVendor == TRUE
  179. }
  180. }
  181. Result = MemOptInit(&NewOption, OptionId, ValueSize, Value);
  182. if( ERROR_SUCCESS != Result ) return Result;
  183. DeletedOption = NULL;
  184. Result = MemOptClassAddOption(OptClass, NewOption, ClassId , VendorId, &DeletedOption);
  185. if( ERROR_SUCCESS != Result ) {
  186. MemOptCleanup(NewOption);
  187. }
  188. if( DeletedOption ) {
  189. MemOptCleanup(DeletedOption);
  190. }
  191. return Result;
  192. }
  193. DWORD
  194. DhcpOptClassAddOptions(
  195. IN OUT PM_SERVER Server,
  196. IN OUT PM_OPTCLASS OptClass,
  197. IN PARRAY OptAttribs
  198. )
  199. {
  200. DWORD Result, LastError;
  201. ARRAY_LOCATION Loc;
  202. PEATTRIB ThisOpt;
  203. LastError = ERROR_SUCCESS;
  204. Result = MemArrayInitLoc(OptAttribs, &Loc);
  205. while( ERROR_FILE_NOT_FOUND != Result ) {
  206. //- ERROR_SUCCESS == Result
  207. Result = MemArrayGetElement(OptAttribs, &Loc, &ThisOpt);
  208. //- ERROR_SUCCESS == Result && ThisOpt
  209. Result = DhcpOptClassAddOption(Server, OptClass,ThisOpt);
  210. if( ERROR_SUCCESS != Result ) LastError = Result;
  211. Result = MemArrayNextLoc(OptAttribs, &Loc);
  212. }
  213. return LastError;
  214. }
  215. DWORD
  216. FirstAddress(
  217. IN PARRAY Attribs
  218. )
  219. {
  220. ARRAY_LOCATION Loc;
  221. DWORD Result;
  222. PEATTRIB ThisAttrib;
  223. Result = MemArrayInitLoc(Attribs, &Loc);
  224. if( ERROR_SUCCESS != Result ) return 0;
  225. Result = MemArrayGetElement(Attribs, &Loc, &ThisAttrib);
  226. if( ERROR_SUCCESS != Result ) return 0;
  227. if( IS_ADDRESS1_PRESENT(ThisAttrib) ) return ThisAttrib->Address1;
  228. return 0;
  229. }
  230. //================================================================================
  231. // operations on the server or global object ONLY
  232. //================================================================================
  233. DWORD
  234. DhcpServerAddClass(
  235. IN OUT PM_SERVER Server,
  236. IN PEATTRIB Class
  237. )
  238. {
  239. DWORD Result;
  240. DWORD Flags;
  241. DWORD ValueSize;
  242. LPBYTE Value;
  243. LPWSTR Name;
  244. LPWSTR Comment;
  245. if( !IS_STRING1_PRESENT(Class) ||
  246. !IS_BINARY1_PRESENT(Class) )
  247. return ERROR_INVALID_PARAMETER;
  248. Name = Class->String1;
  249. if( IS_STRING2_PRESENT(Class) ) Comment = Class->String2;
  250. else Comment = NULL;
  251. if( IS_FLAGS1_PRESENT(Class) ) Flags = Class->Flags1;
  252. else Flags = 0;
  253. Value = Class->Binary1;
  254. ValueSize = Class->BinLen1;
  255. Result = MemClassDefListAddClassDef(
  256. &(Server->ClassDefs),
  257. MemNewClassId(),
  258. Flags,
  259. 0, /* dont care about type */
  260. Name,
  261. Comment,
  262. Value,
  263. ValueSize
  264. );
  265. return Result;
  266. }
  267. DWORD
  268. DhcpServerAddClasses(
  269. IN OUT PM_SERVER Server,
  270. IN PARRAY ClassAttribs
  271. )
  272. {
  273. DWORD Result;
  274. DWORD LastError;
  275. ARRAY_LOCATION Loc;
  276. PEATTRIB ThisClass;
  277. LastError = ERROR_SUCCESS;
  278. Result = MemArrayInitLoc(ClassAttribs, &Loc);
  279. while( ERROR_FILE_NOT_FOUND != Result ) {
  280. //- ERROR_SUCCESS == Result
  281. Result = MemArrayGetElement(ClassAttribs, &Loc, &ThisClass);
  282. //- ERROR_SUCCESS == Result && NULL != ThisC;as
  283. Result = DhcpServerAddClass(Server, ThisClass );
  284. if( ERROR_SUCCESS != Result ) LastError = Result;
  285. Result = MemArrayNextLoc(ClassAttribs, &Loc);
  286. }
  287. return LastError;
  288. }
  289. DWORD
  290. DhcpServerAddOptDef(
  291. IN OUT PM_SERVER Server,
  292. IN PEATTRIB OptDef
  293. )
  294. {
  295. DWORD Result;
  296. LPWSTR Name,Comment,ClassName, VendorName;
  297. DWORD OptionId, Flags;
  298. DWORD ValueSize;
  299. DWORD ClassId, VendorId;
  300. LPBYTE Value;
  301. PM_CLASSDEF ThisClassDef;
  302. if( !IS_STRING1_PRESENT(OptDef) || !IS_BINARY1_PRESENT(OptDef) ||
  303. !IS_DWORD1_PRESENT(OptDef) ) return ERROR_INVALID_DATA;
  304. Name = OptDef->String1;
  305. if( IS_STRING2_PRESENT(OptDef) ) Comment = OptDef->String2;
  306. else Comment = NULL;
  307. if( IS_STRING4_PRESENT(OptDef) ) ClassName = OptDef->String4;
  308. else ClassName = NULL;
  309. if( IS_STRING3_PRESENT(OptDef) ) VendorName = OptDef->String3;
  310. else VendorName = NULL;
  311. OptionId = OptDef->Dword1;
  312. if( IS_FLAGS1_PRESENT(OptDef) ) Flags = OptDef->Flags1; else Flags = 0;
  313. Value = OptDef->Binary1;
  314. ValueSize = OptDef->BinLen1;
  315. if( NULL == ClassName ) ClassId = 0;
  316. else {
  317. Result = MemServerGetClassDef(Server,0, ClassName,0,NULL,&ThisClassDef);
  318. if( ERROR_SUCCESS != Result ) {
  319. // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", ClassName);
  320. ClassId =0;
  321. } else {
  322. ClassId = ThisClassDef->ClassId;
  323. //- ThisClassDef->IsVendor == FALSE
  324. }
  325. }
  326. if( NULL == VendorName ) VendorId = 0;
  327. else {
  328. Result = MemServerGetClassDef(Server,0, VendorName,0,NULL,&ThisClassDef);
  329. if( ERROR_SUCCESS != Result ) {
  330. // INVALID_REG("OptDef %ld unknown class %ws, option ignored\n", VendorName);
  331. VendorId =0;
  332. } else {
  333. VendorId = ThisClassDef->ClassId;
  334. //- ThisClassDef->IsVendor == TRUE
  335. }
  336. }
  337. return MemOptClassDefListAddOptDef(
  338. &(Server->OptDefs),
  339. ClassId,
  340. VendorId,
  341. OptionId,
  342. Flags,
  343. Name,
  344. Comment,
  345. Value,
  346. ValueSize
  347. );
  348. }
  349. DWORD
  350. DhcpServerAddOptionDefs(
  351. IN OUT PM_SERVER Server,
  352. IN PARRAY OptDefAttribs
  353. )
  354. {
  355. DWORD Result;
  356. DWORD LastError;
  357. ARRAY_LOCATION Loc;
  358. PEATTRIB ThisOptDef;
  359. LastError = ERROR_SUCCESS;
  360. Result = MemArrayInitLoc(OptDefAttribs, &Loc);
  361. while( ERROR_FILE_NOT_FOUND != Result ) {
  362. //- ERROR_SUCCESS == Result
  363. Result = MemArrayGetElement(OptDefAttribs, &Loc, &ThisOptDef);
  364. //- ERROR_SUCCESS == Result && NULL != ThisOptDef
  365. Result = DhcpServerAddOptDef(Server, ThisOptDef );
  366. if( ERROR_SUCCESS != Result ) LastError = Result;
  367. Result = MemArrayNextLoc(OptDefAttribs, &Loc);
  368. }
  369. return LastError;
  370. }
  371. DWORD
  372. DhcpServerAddOptions(
  373. IN OUT PM_SERVER Server,
  374. IN PARRAY OptAttribs
  375. )
  376. {
  377. return DhcpOptClassAddOptions(
  378. Server,
  379. &Server->Options,
  380. OptAttribs
  381. );
  382. }
  383. DWORD
  384. DhcpSubnetAddOptions(
  385. IN OUT PM_SERVER Server,
  386. IN OUT PM_SUBNET Subnet,
  387. IN PARRAY OptAttribs
  388. )
  389. {
  390. return DhcpOptClassAddOptions(
  391. Server,
  392. &Subnet->Options,
  393. OptAttribs
  394. );
  395. }
  396. DWORD
  397. DhcpSubnetAddRanges(
  398. IN OUT PM_SUBNET Subnet,
  399. IN PARRAY RangeAttribs
  400. )
  401. {
  402. DWORD Result, LastError;
  403. DWORD Type;
  404. ARRAY_LOCATION Loc;
  405. PEATTRIB ThisRange;
  406. PM_RANGE OverlappingRange;
  407. PM_EXCL OverlappingExcl;
  408. ULONG State, BootpAllocated, MaxBootpAllocated;
  409. LastError = ERROR_SUCCESS;
  410. Result = MemArrayInitLoc(RangeAttribs, &Loc);
  411. while( ERROR_FILE_NOT_FOUND != Result ) {
  412. //- ERROR_SUCCESS == Result
  413. Result = MemArrayGetElement(RangeAttribs, &Loc, &ThisRange);
  414. //- ERROR_SUCCESS == Result && NULL != ThisRange
  415. if( !IS_ADDRESS1_PRESENT(ThisRange) ||
  416. !IS_ADDRESS2_PRESENT(ThisRange) ||
  417. !IS_FLAGS1_PRESENT(ThisRange) )
  418. LastError = ERROR_INVALID_DATA;
  419. else {
  420. OverlappingRange = NULL;
  421. OverlappingExcl = NULL;
  422. if( IS_FLAGS2_PRESENT(ThisRange) ) Type = ThisRange->Flags2;
  423. else Type = RANGE_TYPE_RANGE;
  424. BootpAllocated = IS_DWORD1_PRESENT(ThisRange)? ThisRange->Dword1 : 0;
  425. MaxBootpAllocated = IS_DWORD2_PRESENT(ThisRange) ? ThisRange->Dword2 : ~0;
  426. if( (Type & RANGE_TYPE_MASK) == RANGE_TYPE_RANGE ) {
  427. Result = MemSubnetAddRange(
  428. Subnet,
  429. ThisRange->Address1,
  430. ThisRange->Address2,
  431. ThisRange->Flags1,
  432. BootpAllocated,
  433. MaxBootpAllocated,
  434. &OverlappingRange
  435. );
  436. if( ERROR_SUCCESS != Result || OverlappingRange )
  437. LastError = Result;
  438. } else {
  439. Result = MemSubnetAddExcl(
  440. Subnet,
  441. ThisRange->Address1,
  442. ThisRange->Address2,
  443. &OverlappingExcl
  444. );
  445. if( ERROR_SUCCESS != Result || OverlappingExcl )
  446. LastError = Result;
  447. }
  448. }
  449. Result = MemArrayNextLoc(RangeAttribs, &Loc);
  450. }
  451. return LastError;
  452. }
  453. DWORD
  454. DhcpSubnetAddSuperScopes(
  455. IN OUT PM_SERVER Server,
  456. IN OUT PM_SUBNET Subnet,
  457. IN PARRAY SuperScopeAttribs
  458. )
  459. {
  460. DWORD Result;
  461. ARRAY_LOCATION Loc;
  462. PEATTRIB ThisAttrib;
  463. PM_SSCOPE SScope;
  464. Result = MemArrayInitLoc(SuperScopeAttribs, &Loc);
  465. if( ERROR_SUCCESS != Result ) return ERROR_SUCCESS;
  466. Result = MemArrayGetElement(SuperScopeAttribs, &Loc, &ThisAttrib);
  467. if( ERROR_SUCCESS != Result ) return Result;
  468. if( !IS_STRING1_PRESENT(ThisAttrib) ) return ERROR_INVALID_DATA;
  469. Result = MemServerFindSScope(
  470. Server,
  471. 0xFFFFFFFF, // invalid scope id ==> use scope name for search
  472. ThisAttrib->String1,
  473. &SScope
  474. );
  475. if( ERROR_FILE_NOT_FOUND != Result ) {
  476. if( ERROR_SUCCESS != Result ) return Result;
  477. Result = MemSubnetSetSuperScope(Subnet, SScope);
  478. return Result;
  479. }
  480. Result = MemSScopeInit(
  481. &SScope,
  482. IS_FLAGS2_PRESENT(ThisAttrib)?ThisAttrib->Flags2:0,
  483. ThisAttrib->String1
  484. );
  485. if( ERROR_SUCCESS != Result ) return Result;
  486. Result = MemServerAddSScope( Server, SScope );
  487. if( ERROR_SUCCESS != Result ) {
  488. MemSScopeCleanup(SScope);
  489. }
  490. return Result;
  491. }
  492. DWORD
  493. DhcpSubnetAddReservation(
  494. IN OUT LPSTORE_HANDLE hContainer,
  495. IN OUT LPSTORE_HANDLE hDhcpRoot,
  496. IN OUT LPSTORE_HANDLE hSubnet,
  497. IN OUT PM_SERVER Server,
  498. IN OUT PM_SUBNET Subnet,
  499. IN PEATTRIB ReservationAttrib
  500. )
  501. {
  502. DWORD Result;
  503. DWORD Address, State;
  504. DWORD nBytes;
  505. LPBYTE ClientUID;
  506. ARRAY Options;
  507. PM_RESERVATION Res1;
  508. if( !IS_ADDRESS1_PRESENT(ReservationAttrib) ||
  509. !IS_FLAGS1_PRESENT(ReservationAttrib) ||
  510. !IS_BINARY1_PRESENT(ReservationAttrib) )
  511. return ERROR_SUCCESS;
  512. Address = ReservationAttrib->Address1;
  513. State = ReservationAttrib->Flags1;
  514. ClientUID = ReservationAttrib->Binary1;
  515. nBytes = ReservationAttrib->BinLen1;
  516. Result = MemReserveAdd(
  517. &Subnet->Reservations,
  518. Address,
  519. State,
  520. ClientUID,
  521. nBytes
  522. );
  523. if( ERROR_SUCCESS != Result ) return Result;
  524. if( !IS_ADSPATH_PRESENT(ReservationAttrib) )
  525. return ERROR_SUCCESS;
  526. Result = MemReserveFindByAddress(
  527. &Subnet->Reservations,
  528. Address,
  529. &Res1
  530. );
  531. if( ERROR_SUCCESS != Result ) return ERROR_DDS_UNEXPECTED_ERROR;
  532. MemArrayInit(&Options);
  533. Result = CheckoutAlternateOptions1(
  534. hContainer,
  535. ReservationAttrib,
  536. NULL,
  537. &Options
  538. );
  539. //Ignore Result
  540. if( 0 == MemArraySize(&Options) ) Result = ERROR_SUCCESS;
  541. else Result = DhcpOptClassAddOptions(
  542. Server,
  543. &Res1->Options,
  544. &Options
  545. );
  546. ArrayMemFree(&Options);
  547. return Result;
  548. }
  549. DWORD
  550. DhcpSubnetAddReservations(
  551. IN OUT LPSTORE_HANDLE hContainer,
  552. IN OUT LPSTORE_HANDLE hDhcpRoot,
  553. IN OUT LPSTORE_HANDLE hSubnet,
  554. IN OUT PM_SERVER Server,
  555. IN OUT PM_SUBNET Subnet,
  556. IN PARRAY ReservationAttribs
  557. )
  558. {
  559. DWORD Result, LastError;
  560. ARRAY_LOCATION Loc;
  561. PEATTRIB ThisReservation;
  562. LastError = ERROR_SUCCESS;
  563. Result = MemArrayInitLoc(ReservationAttribs, &Loc);
  564. while(ERROR_FILE_NOT_FOUND != Result ) {
  565. //= ERROR_SUCCESS == Result
  566. Result = MemArrayGetElement(ReservationAttribs, &Loc, &ThisReservation);
  567. //- ERROR_SUCCESS == Result && NULL != ThisReservation
  568. Result = DhcpSubnetAddReservation(hContainer, hDhcpRoot, hSubnet, Server, Subnet, ThisReservation);
  569. if( ERROR_SUCCESS != Result ) LastError = Result;
  570. Result = MemArrayNextLoc(ReservationAttribs, &Loc);
  571. }
  572. return LastError;
  573. }
  574. DWORD
  575. DhcpServerFillSubnet(
  576. IN OUT LPSTORE_HANDLE hContainer,
  577. IN OUT LPSTORE_HANDLE hDhcpRoot,
  578. IN OUT LPSTORE_HANDLE hSubnet,
  579. IN OUT PM_SERVER Server,
  580. IN OUT PM_SUBNET Subnet
  581. )
  582. {
  583. DWORD Result, LastError;
  584. ARRAY RangeAttribs;
  585. ARRAY ReservationAttribs;
  586. ARRAY AddressAttribs;
  587. ARRAY SuperScopeAttribs;
  588. ARRAY OptDefAttribs;
  589. ARRAY AlternateOptAttribs;
  590. ARRAY OptAttribs;
  591. ARRAY ClassAttribs;
  592. MemArrayInit(&RangeAttribs);
  593. MemArrayInit(&ReservationAttribs);
  594. MemArrayInit(&SuperScopeAttribs);
  595. MemArrayInit(&AlternateOptAttribs);
  596. MemArrayInit(&OptAttribs);
  597. Result = DhcpDsGetLists(
  598. /* Reserved */ DDS_RESERVED_DWORD,
  599. /* hStore */ hSubnet,
  600. /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
  601. /* Servers */ NULL,
  602. /* Subnets */ NULL,
  603. /* IpAddress */ NULL,
  604. /* Mask */ NULL,
  605. /* Ranges */ &RangeAttribs,
  606. /* Sites */ NULL,
  607. /* Reservations */ &ReservationAttribs,
  608. /* SuperScopes */ &SuperScopeAttribs,
  609. /* OptionDescripti */ NULL,
  610. /* OptionsLocation */ &AlternateOptAttribs,
  611. /* Options */ &OptAttribs,
  612. /* Classes */ NULL
  613. );
  614. // Ignore Result
  615. Result = CheckoutAlternateOptions(
  616. hContainer,
  617. &AlternateOptAttribs,
  618. NULL,
  619. &OptAttribs
  620. );
  621. // Ignore Result
  622. ArrayMemFree(&AlternateOptAttribs);
  623. LastError = ERROR_SUCCESS;
  624. Result = DhcpSubnetAddOptions(
  625. Server,
  626. Subnet,
  627. &OptAttribs
  628. );
  629. ArrayMemFree(&OptAttribs);
  630. if( ERROR_SUCCESS != Result ) LastError = Result;
  631. Result = DhcpSubnetAddRanges(
  632. Subnet,
  633. &RangeAttribs
  634. );
  635. ArrayMemFree(&RangeAttribs);
  636. if( ERROR_SUCCESS != Result ) LastError = Result;
  637. if( DONT_USE_PARENT ) { // we are not peeking at SubnetAttrib, so do this..
  638. Result = DhcpSubnetAddSuperScopes(
  639. Server,
  640. Subnet,
  641. &SuperScopeAttribs
  642. );
  643. ArrayMemFree(&SuperScopeAttribs);
  644. if( ERROR_SUCCESS != Result ) LastError = Result;
  645. } else {
  646. ArrayMemFree(&SuperScopeAttribs);
  647. }
  648. Result = DhcpSubnetAddReservations(
  649. hContainer,
  650. hDhcpRoot,
  651. hSubnet,
  652. Server,
  653. Subnet,
  654. &ReservationAttribs
  655. );
  656. ArrayMemFree(&ReservationAttribs);
  657. if( ERROR_SUCCESS != Result ) LastError = Result;
  658. return LastError;
  659. }
  660. DWORD
  661. DhcpServerGetSubnet(
  662. IN OUT LPSTORE_HANDLE hContainer,
  663. IN OUT LPSTORE_HANDLE hDhcpRoot,
  664. IN OUT LPSTORE_HANDLE hSubnet,
  665. IN OUT PM_SERVER Server,
  666. IN PEATTRIB SubnetAttrib,
  667. IN PM_SUBNET *Subnet
  668. )
  669. {
  670. DWORD Result;
  671. DWORD FoundParams;
  672. DWORD Type;
  673. DWORD Address, Mask, State, Policy, SScopeId;
  674. LPWSTR Name, Comment;
  675. LARGE_INTEGER Flags;
  676. ARRAY AddressAttribs, MaskAttribs;
  677. PM_SSCOPE SScope;
  678. if( DONT_USE_PARENT ) { // get state frm server obj or root obj?
  679. FoundParams = 0; Type = 0; Name = NULL; Comment = NULL;
  680. Result = DhcpDsGetAttribs(
  681. /* Reserved */ DDS_RESERVED_DWORD,
  682. /* hStore */ hSubnet,
  683. /* FoundParams */ &FoundParams,
  684. /* UniqueKey */ NULL,
  685. /* Type */ &Type,
  686. /* Flags */ &Flags,
  687. /* Name */ &Name,
  688. /* Description */ &Comment,
  689. /* Location */ NULL,
  690. /* MScopeId */ NULL
  691. );
  692. if( ERROR_SUCCESS != Result ) return Result;
  693. if( !DhcpCheckParams(FoundParams, 3) ) {
  694. State = Policy = 0;
  695. } else {
  696. State = Flags.LowPart; Policy = Flags.HighPart;
  697. }
  698. } else {
  699. if( IS_FLAGS1_PRESENT(SubnetAttrib) ) {
  700. State = SubnetAttrib->Flags1;
  701. } else State = 0;
  702. if( IS_FLAGS2_PRESENT(SubnetAttrib) ) {
  703. Policy = SubnetAttrib->Flags2;
  704. } else Policy = 0;
  705. Name = SubnetAttrib->String1;
  706. if( IS_STRING2_PRESENT(SubnetAttrib) ) {
  707. Comment = SubnetAttrib->String2;
  708. } else Comment = NULL;
  709. }
  710. if( DONT_USE_PARENT ) { // get info from subnet obj, not server
  711. MemArrayInit(&AddressAttribs); MemArrayInit(&MaskAttribs);
  712. Result = DhcpDsGetLists(
  713. /* Reserved */ DDS_RESERVED_DWORD,
  714. /* hStore */ hSubnet,
  715. /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
  716. /* Servers */ NULL,
  717. /* Subnets */ NULL,
  718. /* IpAddress */ &AddressAttribs,
  719. /* Mask */ &MaskAttribs,
  720. /* Ranges */ NULL,
  721. /* Sites */ NULL,
  722. /* Reservations */ NULL,
  723. /* SuperScopes */ NULL,
  724. /* OptionDescripti */ NULL,
  725. /* OptionsLocation */ NULL,
  726. /* Options */ NULL,
  727. /* Classes */ NULL
  728. );
  729. Address = FirstAddress(&AddressAttribs);
  730. Mask = FirstAddress(&MaskAttribs);
  731. ArrayMemFree(&AddressAttribs);
  732. ArrayMemFree(&MaskAttribs);
  733. } else { // get info frm the subnet attrib
  734. Address = SubnetAttrib->Address1;
  735. Mask = SubnetAttrib->Address2;
  736. }
  737. SScope = NULL;
  738. if( !DONT_USE_PARENT ) do { // if we can peek into SubnetAttrib
  739. if( !IS_STRING3_PRESENT(SubnetAttrib) ) { // does this have a superscope name?
  740. SScopeId = 0; // nope, so SScopeId is zero
  741. break; // also, quit from here..
  742. }
  743. Result = MemServerFindSScope( // first see if the superscope already exists
  744. Server,
  745. 0xFFFFFFFF,
  746. SubnetAttrib->String3,
  747. &SScope
  748. );
  749. if( ERROR_SUCCESS== Result ) { // got it.
  750. SScopeId = SScope->SScopeId;
  751. break; // superscope set.. dont need to worry
  752. }
  753. if( ERROR_FILE_NOT_FOUND != Result ) { // something seriously wrong?
  754. return Result; // cant go on
  755. }
  756. //= NULL == SScope
  757. Result = MemSScopeInit( // try to create a new super scope
  758. &SScope,
  759. 0,
  760. SubnetAttrib->String3
  761. );
  762. if( ERROR_SUCCESS != Result ) { // hmm.. should not go wrong at all?
  763. return Result;
  764. }
  765. Result = MemServerAddSScope( // now add it to the server
  766. Server,
  767. SScope
  768. );
  769. if( ERROR_SUCCESS != Result ) { // oh boy, not again
  770. MemSScopeCleanup(SScope);
  771. return Result;
  772. }
  773. SScopeId = SScope->SScopeId; // finally got the superscope
  774. } while(0); // not really a loop.. just a programming trick
  775. Result = MemSubnetInit(
  776. /* pSubnet */ Subnet,
  777. /* Address */ Address,
  778. /* Mask */ Mask,
  779. /* State */ State,
  780. /* SuperScopeId */ DONT_USE_PARENT ? 0 : SScopeId,
  781. /* Name */ Name,
  782. /* Description */ Comment
  783. );
  784. if( DONT_USE_PARENT ) { // need to free Name and Comment
  785. if( Name ) MemFree(Name);
  786. if( Comment ) MemFree(Comment);
  787. }
  788. if( ERROR_SUCCESS != Result ) return Result;
  789. Result = DhcpServerFillSubnet(
  790. hContainer,
  791. hDhcpRoot,
  792. hSubnet,
  793. Server,
  794. *Subnet
  795. );
  796. if( ERROR_SUCCESS != Result ) {
  797. MemSubnetFree(*Subnet);
  798. *Subnet = NULL;
  799. }
  800. return Result;
  801. }
  802. DWORD
  803. DhcpServerAddSubnet(
  804. IN OUT LPSTORE_HANDLE hContainer,
  805. IN OUT LPSTORE_HANDLE hDhcpRoot,
  806. IN OUT LPSTORE_HANDLE hServer,
  807. IN OUT PM_SERVER Server,
  808. IN PEATTRIB SubnetAttrib
  809. )
  810. {
  811. DWORD Result;
  812. STORE_HANDLE hStore;
  813. PM_SUBNET NewSubnet;
  814. if( !IS_STRING1_PRESENT(SubnetAttrib) || // no subnet name
  815. !IS_ADDRESS1_PRESENT(SubnetAttrib) || // no subnet address
  816. !IS_ADDRESS2_PRESENT(SubnetAttrib) ) { // no subnet mask
  817. return ERROR_SUCCESS; //= ds inconsistent
  818. }
  819. if( !IS_STOREGETTYPE_PRESENT(SubnetAttrib) ) {
  820. return ERROR_SUCCESS; // this is just a dummy here for no reason at all
  821. }
  822. Result = StoreGetHandle(
  823. /* hStore */ hContainer,
  824. /* Reserved */ DDS_RESERVED_DWORD,
  825. /* StoreGetType */ SubnetAttrib->StoreGetType,
  826. /* Path */ SubnetAttrib->ADsPath,
  827. /* hStoreOut */ &hStore
  828. );
  829. if( ERROR_DS_NO_SUCH_OBJECT == Result ) return ERROR_SUCCESS;
  830. if( ERROR_SUCCESS != Result ) return Result;
  831. NewSubnet = NULL;
  832. Result = DhcpServerGetSubnet(
  833. hContainer,
  834. hDhcpRoot,
  835. &hStore,
  836. Server,
  837. SubnetAttrib,
  838. &NewSubnet
  839. );
  840. StoreCleanupHandle(&hStore, DDS_RESERVED_DWORD);
  841. if( ERROR_SUCCESS != Result ) return Result;
  842. Result = MemServerAddSubnet(Server, NewSubnet);
  843. if( ERROR_SUCCESS != Result ) MemSubnetFree(NewSubnet);
  844. return Result;
  845. }
  846. DWORD
  847. DhcpServerAddSubnets(
  848. IN OUT LPSTORE_HANDLE hContainer,
  849. IN OUT LPSTORE_HANDLE hDhcpRoot,
  850. IN OUT LPSTORE_HANDLE hServer,
  851. IN OUT PM_SERVER Server,
  852. IN PARRAY SubnetAttribs
  853. )
  854. {
  855. DWORD Result, LastError;
  856. ARRAY_LOCATION Loc;
  857. PEATTRIB ThisAttrib;
  858. LastError = ERROR_SUCCESS;
  859. Result = MemArrayInitLoc(SubnetAttribs, &Loc);
  860. while( ERROR_FILE_NOT_FOUND != Result ) {
  861. //- ERROR_SUCCESS == Result
  862. Result = MemArrayGetElement(SubnetAttribs, &Loc, &ThisAttrib);
  863. //- ERROR_SUCCESS == Result
  864. Result = DhcpServerAddSubnet(
  865. hContainer,
  866. hDhcpRoot,
  867. hServer,
  868. Server,
  869. ThisAttrib
  870. );
  871. if( ERROR_SUCCESS != Result ) LastError = Result;
  872. Result = MemArrayNextLoc(SubnetAttribs, &Loc);
  873. }
  874. return LastError;
  875. }
  876. DWORD
  877. DhcpFillServer(
  878. IN OUT LPSTORE_HANDLE hContainer,
  879. IN OUT LPSTORE_HANDLE hDhcpRoot,
  880. IN OUT LPSTORE_HANDLE hServer,
  881. IN OUT PM_SERVER Server
  882. )
  883. {
  884. DWORD Result, LastError;
  885. DWORD Address;
  886. ARRAY SubnetAttribs;
  887. ARRAY AddressAttribs;
  888. ARRAY SuperScopeAttribs;
  889. ARRAY OptDefAttribs;
  890. ARRAY AlternateOptAttribs;
  891. ARRAY OptAttribs;
  892. ARRAY ClassAttribs;
  893. MemArrayInit(&SubnetAttribs);
  894. MemArrayInit(&AddressAttribs);
  895. MemArrayInit(&SuperScopeAttribs);
  896. MemArrayInit(&OptDefAttribs);
  897. MemArrayInit(&AlternateOptAttribs);
  898. MemArrayInit(&OptAttribs);
  899. MemArrayInit(&ClassAttribs);
  900. Result = DhcpDsGetLists(
  901. /* Reserved */ DDS_RESERVED_DWORD,
  902. /* hStore */ hServer,
  903. /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
  904. /* Servers */ NULL,
  905. /* Subnets */ &SubnetAttribs,
  906. /* IpAddress */ &AddressAttribs,
  907. /* Mask */ NULL,
  908. /* Ranges */ NULL,
  909. /* Sites */ NULL,
  910. /* Reservations */ NULL,
  911. /* SuperScopes */ NULL, // &SuperScopeAttribs,
  912. /* OptionDescripti */ &OptDefAttribs,
  913. /* OptionsLocation */ &AlternateOptAttribs,
  914. /* Options */ &OptAttribs,
  915. /* Classes */ &ClassAttribs
  916. );
  917. // Ignore Result
  918. Result = CheckoutAlternateOptions(
  919. hContainer,
  920. &AlternateOptAttribs,
  921. &OptDefAttribs,
  922. &OptAttribs
  923. );
  924. // Ignore Result
  925. ArrayMemFree(&AlternateOptAttribs);
  926. LastError = ERROR_SUCCESS;
  927. Result = DhcpServerAddClasses(
  928. Server,
  929. &ClassAttribs
  930. );
  931. ArrayMemFree(&ClassAttribs);
  932. if( ERROR_SUCCESS != Result ) LastError = Result;
  933. Result = DhcpServerAddOptionDefs(
  934. Server,
  935. &OptDefAttribs
  936. );
  937. ArrayMemFree(&OptDefAttribs);
  938. if( ERROR_SUCCESS != Result ) LastError = Result;
  939. Result = DhcpServerAddOptions(
  940. Server,
  941. &OptAttribs
  942. );
  943. ArrayMemFree(&OptAttribs);
  944. if( ERROR_SUCCESS != Result ) LastError = Result;
  945. Result = DhcpServerAddSubnets(
  946. hContainer,
  947. hDhcpRoot,
  948. hServer,
  949. Server,
  950. &SubnetAttribs
  951. );
  952. ArrayMemFree(&SubnetAttribs);
  953. if( ERROR_SUCCESS != Result ) LastError = Result;
  954. ArrayMemFree(&SuperScopeAttribs);
  955. Server->Address = FirstAddress(&AddressAttribs);
  956. ArrayMemFree(&AddressAttribs);
  957. return LastError;
  958. }
  959. DWORD
  960. DhcpGetServer(
  961. IN OUT LPSTORE_HANDLE hContainer,
  962. IN OUT LPSTORE_HANDLE hDhcpRoot,
  963. IN OUT LPSTORE_HANDLE hServer,
  964. IN PEATTRIB ServerAttrib,
  965. OUT PM_SERVER *Server
  966. )
  967. {
  968. DWORD Result;
  969. DWORD FoundParams;
  970. DWORD Type;
  971. DWORD State, Policy;
  972. LPWSTR Name, Comment;
  973. LARGE_INTEGER Flags;
  974. if( DONT_USE_PARENT ) { // get state frm server obj or root obj?
  975. FoundParams = 0; Type = 0; Name = NULL; Comment = NULL;
  976. Result = DhcpDsGetAttribs(
  977. /* Reserved */ DDS_RESERVED_DWORD,
  978. /* hStore */ hServer,
  979. /* FoundParams */ &FoundParams,
  980. /* UniqueKey */ NULL,
  981. /* Type */ &Type,
  982. /* Flags */ &Flags,
  983. /* Name */ &Name,
  984. /* Description */ &Comment,
  985. /* Location */ NULL,
  986. /* MScopeId */ NULL
  987. );
  988. if( ERROR_SUCCESS != Result ) return Result;
  989. if( !DhcpCheckParams(FoundParams, 3) ) {
  990. State = Policy = 0;
  991. } else {
  992. State = Flags.LowPart; Policy = Flags.HighPart;
  993. }
  994. } else {
  995. if( IS_FLAGS1_PRESENT(ServerAttrib) ) {
  996. State = ServerAttrib->Flags1;
  997. } else State = 0;
  998. if( IS_FLAGS2_PRESENT(ServerAttrib) ) {
  999. Policy = ServerAttrib->Flags2;
  1000. } else Policy = 0;
  1001. Name = ServerAttrib->String1;
  1002. if( IS_STRING2_PRESENT(ServerAttrib) ) {
  1003. Comment = ServerAttrib->String2;
  1004. } else Comment = NULL;
  1005. }
  1006. Result = MemServerInit(
  1007. /* Server */ Server,
  1008. /* Address */ 0, // Address gets filled in DhcpFillServer
  1009. /* State */ State,
  1010. /* Policy */ Policy,
  1011. /* Name */ Name,
  1012. /* Comment */ Comment
  1013. );
  1014. if( DONT_USE_PARENT ) { // Name and Comment were allocated..
  1015. if( Name ) MemFree(Name);
  1016. if( Comment ) MemFree(Comment);
  1017. }
  1018. if( ERROR_SUCCESS != Result ) return Result;
  1019. Result = DhcpFillServer(
  1020. hContainer,
  1021. hDhcpRoot,
  1022. hServer,
  1023. *Server
  1024. );
  1025. if( ERROR_SUCCESS != Result ) {
  1026. MemServerFree(*Server);
  1027. *Server = NULL;
  1028. }
  1029. return Result;
  1030. }
  1031. BOOL _inline
  1032. AddressFoundInHostent(
  1033. IN DHCP_IP_ADDRESS AddrToSearch, // Host-Order addr
  1034. IN HOSTENT *ServerEntry // entry to search for..
  1035. )
  1036. {
  1037. ULONG nAddresses, ThisAddress;
  1038. if( NULL == ServerEntry ) return FALSE; // no address to search in
  1039. nAddresses = 0; // have a host entry to compare for addresses
  1040. while( ServerEntry->h_addr_list[nAddresses] ) {
  1041. ThisAddress = ntohl(*(DHCP_IP_ADDRESS*)ServerEntry->h_addr_list[nAddresses++] );
  1042. if( ThisAddress == AddrToSearch ) {
  1043. return TRUE; // yeah address matched.
  1044. }
  1045. }
  1046. return FALSE;
  1047. }
  1048. DWORD static
  1049. DhcpAddServer(
  1050. IN OUT LPSTORE_HANDLE hContainer,
  1051. IN OUT LPSTORE_HANDLE hDhcpRoot,
  1052. IN OUT PARRAY Servers,
  1053. IN PEATTRIB ServerAttrib,
  1054. IN HOSTENT *ServerEntry
  1055. )
  1056. {
  1057. DWORD Result, ServerAddress, State, Policy;
  1058. STORE_HANDLE hStore;
  1059. PM_SERVER NewServer;
  1060. ARRAY_LOCATION Loc;
  1061. if( !IS_STOREGETTYPE_PRESENT(ServerAttrib) )
  1062. return ERROR_SUCCESS; // empty server... just there for other reasons
  1063. if( !IS_ADDRESS1_PRESENT(ServerAttrib) ) {
  1064. return ERROR_SUCCESS; // invalid attribute?
  1065. }
  1066. for( Result = MemArrayInitLoc(Servers, &Loc)
  1067. ; ERROR_FILE_NOT_FOUND != Result ; // search if we've added this before!
  1068. Result = MemArrayNextLoc(Servers, &Loc)
  1069. ) {
  1070. //- ERROR_SUCCESS == Result
  1071. Result = MemArrayGetElement(Servers, &Loc, (LPVOID*)&NewServer);
  1072. //- ERROR_SUCCESS == Result
  1073. if( 0 == wcscmp(NewServer->Name, ServerAttrib->String1) ) {
  1074. return ERROR_SUCCESS; // server already added
  1075. }
  1076. if( AddressFoundInHostent(NewServer->Address, ServerEntry) ) {
  1077. return ERROR_SUCCESS; // server already added
  1078. }
  1079. //
  1080. // A better check would be to see if the server object was loaded before..
  1081. // by looking at the location... welll.. This should be done soon.
  1082. //
  1083. }
  1084. ServerAddress = ServerAttrib->Address1;
  1085. if( !IS_FLAGS1_PRESENT(ServerAttrib)) State = 0;
  1086. else State = ServerAttrib->Flags1;
  1087. if( !IS_FLAGS2_PRESENT(ServerAttrib)) Policy = 0;
  1088. else State = ServerAttrib->Flags2;
  1089. Result = StoreGetHandle(
  1090. /* hStore */ hContainer,
  1091. /* Reserved */ DDS_RESERVED_DWORD,
  1092. /* StoreGetType */ ServerAttrib->StoreGetType,
  1093. /* Path */ ServerAttrib->ADsPath,
  1094. /* hStoreOut */ &hStore
  1095. );
  1096. if( ERROR_DS_NO_SUCH_OBJECT == Result ) return ERROR_DDS_DHCP_SERVER_NOT_FOUND;
  1097. if( ERROR_SUCCESS != Result ) return Result;
  1098. NewServer = NULL;
  1099. Result = DhcpGetServer(
  1100. hContainer,
  1101. hDhcpRoot,
  1102. &hStore,
  1103. ServerAttrib,
  1104. &NewServer
  1105. );
  1106. StoreCleanupHandle(&hStore, DDS_RESERVED_DWORD);
  1107. if( ERROR_SUCCESS != Result ) return Result;
  1108. NewServer->Address = ServerAddress;
  1109. NewServer->State = State;
  1110. NewServer->Policy = Policy;
  1111. Result = MemArrayAddElement(Servers, NewServer);
  1112. if( ERROR_SUCCESS != Result ) MemServerFree(NewServer);
  1113. return Result;
  1114. }
  1115. BOOL _inline
  1116. FoundServer( // does this attrib belong to given server?
  1117. IN PEATTRIB ServerAttrib,
  1118. IN LPWSTR ServerName,
  1119. IN HOSTENT *ServerEntry
  1120. )
  1121. {
  1122. ULONG nAddresses;
  1123. DHCP_IP_ADDRESS ThisAddress;
  1124. if( NULL == ServerName ) return TRUE;
  1125. do { // not a loop
  1126. if( !IS_STRING1_PRESENT(ServerAttrib) )
  1127. break ; // could not even find any name!
  1128. if( NULL != ServerAttrib->String1 && 0 == wcscmp(ServerName, ServerAttrib->String1) )
  1129. return TRUE; // ok, the names match
  1130. } while(0);
  1131. if( IS_ADDRESS1_PRESENT(ServerAttrib) ) { // this MUST be TRUEEEE
  1132. if( AddressFoundInHostent(ServerAttrib->Address1, ServerEntry) ) {
  1133. return TRUE; // yes, there was a match
  1134. }
  1135. }
  1136. return FALSE; // nope, this server is not what we're lookin for
  1137. }
  1138. //BeginExport(function)
  1139. DWORD
  1140. DhcpDsGetServers(
  1141. IN OUT LPSTORE_HANDLE hContainer, // the container handle
  1142. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object
  1143. IN DWORD Reserved,
  1144. IN LPWSTR ServerName, // OPTIONAL, NULL ==> All servers
  1145. IN OUT PARRAY Servers // fill in this array with PM_SERVER types
  1146. ) //EndExport(function)
  1147. {
  1148. ARRAY ServerAttribs;
  1149. ARRAY_LOCATION Loc;
  1150. DWORD Result;
  1151. DWORD LastError;
  1152. PEATTRIB ThisAttrib;
  1153. BOOL GotOneServerAtleast;
  1154. HOSTENT *ServerEntry;
  1155. if( NULL == hContainer || NULL == hContainer->ADSIHandle )
  1156. return ERROR_INVALID_PARAMETER;
  1157. if( NULL == hDhcpRoot || NULL == hDhcpRoot->ADSIHandle )
  1158. return ERROR_INVALID_PARAMETER;
  1159. if( 0 != Reserved || NULL == Servers )
  1160. return ERROR_INVALID_PARAMETER;
  1161. MemArrayInit(&ServerAttribs);
  1162. Result = DhcpDsGetLists(
  1163. /* Reserved */ DDS_RESERVED_DWORD,
  1164. /* hStore */ hDhcpRoot,
  1165. /* RecursionDepth */ 0x7FFFFFFF, // max out recursion
  1166. /* Servers */ &ServerAttribs,
  1167. /* Subnets */ NULL,
  1168. /* IpAddress */ NULL,
  1169. /* Mask */ NULL,
  1170. /* Ranges */ NULL,
  1171. /* Sites */ NULL,
  1172. /* Reservations */ NULL,
  1173. /* SuperScopes */ NULL,
  1174. /* OptionDescripti */ NULL, // need to do global options, classes etc
  1175. /* OptionsLocation */ NULL,
  1176. /* Options */ NULL,
  1177. /* Classes */ NULL
  1178. );
  1179. if( 0 == MemArraySize(&ServerAttribs) ) {
  1180. if( ERROR_SUCCESS != Result ) return Result;
  1181. return ERROR_DDS_DHCP_SERVER_NOT_FOUND;
  1182. }
  1183. GotOneServerAtleast = FALSE;
  1184. LastError = ERROR_DDS_DHCP_SERVER_NOT_FOUND;
  1185. if( NULL == ServerName ) {
  1186. ServerEntry = NULL;
  1187. } else {
  1188. CHAR TmpBuf[300];
  1189. wcstombs(TmpBuf, ServerName, sizeof(TmpBuf)-1);
  1190. TmpBuf[sizeof(TmpBuf)-1] = '\0';
  1191. ServerEntry = gethostbyname(TmpBuf);
  1192. }
  1193. Result = MemArrayInitLoc(&ServerAttribs, &Loc);
  1194. while( ERROR_FILE_NOT_FOUND != Result ) {
  1195. //- (ERROR_SUCCESS == Result )
  1196. Result = MemArrayGetElement(&ServerAttribs, &Loc, (LPVOID*)&ThisAttrib);
  1197. if( ERROR_SUCCESS != Result ) {
  1198. //- FALSE
  1199. break;
  1200. }
  1201. if( FoundServer(ThisAttrib, ServerName, ServerEntry) ) {
  1202. Result = DhcpAddServer(hContainer, hDhcpRoot, Servers, ThisAttrib, ServerEntry);
  1203. if( ERROR_SUCCESS != Result ) LastError = Result;
  1204. else GotOneServerAtleast = TRUE;
  1205. }
  1206. MemFree(ThisAttrib);
  1207. Result = MemArrayNextLoc(&ServerAttribs, &Loc);
  1208. }
  1209. if( GotOneServerAtleast ) return ERROR_SUCCESS;
  1210. return LastError;
  1211. }
  1212. //BeginExport(function)
  1213. DWORD
  1214. DhcpDsGetEnterpriseServers( // get the dhcp servers for the current enterprise
  1215. IN DWORD Reserved,
  1216. IN LPWSTR ServerName,
  1217. IN OUT PARRAY Servers
  1218. ) //EndExport(function)
  1219. {
  1220. DWORD Result;
  1221. STORE_HANDLE hRoot;
  1222. STORE_HANDLE hDhcpRoot;
  1223. STORE_HANDLE hContainer;
  1224. Result = StoreInitHandle(
  1225. /* hStore */ &hRoot,
  1226. /* Reserved */ DDS_RESERVED_DWORD,
  1227. /* ThisDomain */ NULL,
  1228. /* UserName */ NULL,
  1229. /* Password */ NULL,
  1230. /* AuthFlags */ ADS_SECURE_AUTHENTICATION
  1231. );
  1232. if( ERROR_SUCCESS != Result ) return ERROR_DDS_NO_DS_AVAILABLE;
  1233. Result = DhcpDsGetRoot(
  1234. /* Flags */ DDS_FLAGS_CREATE,
  1235. /* hStoreCC */ &hRoot,
  1236. /* hStoreDhcpRoot */ &hDhcpRoot
  1237. );
  1238. if( ERROR_SUCCESS != Result ) {
  1239. StoreCleanupHandle(&hRoot, DDS_RESERVED_DWORD);
  1240. return Result;
  1241. }
  1242. Result = StoreGetHandle(
  1243. /* hStore */ &hRoot,
  1244. /* Reserved */ DDS_RESERVED_DWORD,
  1245. /* StoreGetType */ StoreGetChildType,
  1246. /* Path */ DHCP_ROOT_OBJECT_PARENT_LOC,
  1247. /* hStoreOut */ &hContainer
  1248. );
  1249. StoreCleanupHandle(&hRoot, DDS_RESERVED_DWORD);
  1250. if( ERROR_SUCCESS != Result ) {
  1251. StoreCleanupHandle(&hRoot, DDS_RESERVED_DWORD);
  1252. return ERROR_DDS_UNEXPECTED_ERROR;
  1253. }
  1254. Result = DhcpDsGetServers(
  1255. /* hContainer */ &hContainer,
  1256. /* hDhcpRoot */ &hDhcpRoot,
  1257. /* Reserved */ DDS_RESERVED_DWORD,
  1258. /* ServerName */ ServerName,
  1259. /* Servers */ Servers
  1260. );
  1261. StoreCleanupHandle(&hContainer, DDS_RESERVED_DWORD);
  1262. StoreCleanupHandle(&hDhcpRoot, DDS_RESERVED_DWORD);
  1263. return Result;
  1264. }
  1265. //================================================================================
  1266. // end of file
  1267. //================================================================================