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.

2796 lines
111 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: most of the rpc apis are here and some miscellaneous functions too
  5. // all the functions here go to the DS directly.
  6. //================================================================================
  7. #include <hdrmacro.h>
  8. #include <store.h>
  9. #include <dhcpmsg.h>
  10. #include <wchar.h>
  11. #include <dhcpbas.h>
  12. #include <mm\opt.h>
  13. #include <mm\optl.h>
  14. #include <mm\optdefl.h>
  15. #include <mm\optclass.h>
  16. #include <mm\classdefl.h>
  17. #include <mm\bitmask.h>
  18. #include <mm\reserve.h>
  19. #include <mm\range.h>
  20. #include <mm\subnet.h>
  21. #include <mm\sscope.h>
  22. #include <mm\oclassdl.h>
  23. #include <mm\server.h>
  24. #include <mm\address.h>
  25. #include <mm\server2.h>
  26. #include <mm\memfree.h>
  27. #include <mmreg\regutil.h>
  28. #include <mmreg\regread.h>
  29. #include <mmreg\regsave.h>
  30. #include <dhcpapi.h>
  31. //================================================================================
  32. // THE FOLLOWING FUNCTIONS HAVE BEEN COPIED OVER FROM RPCAPI1.C (IN THE
  33. // DHCP\SERVER\SERVER DIRECTORY).
  34. //================================================================================
  35. #undef DhcpPrint
  36. #define DhcpPrint(X)
  37. #define DhcpAssert(X)
  38. typedef struct _OPTION_BIN {
  39. DWORD DataSize;
  40. DHCP_OPTION_DATA_TYPE OptionType;
  41. DWORD NumElements;
  42. BYTE Data[0];
  43. } OPTION_BIN, *LPOPTION_BIN;
  44. #define IS_SPACE_AVAILABLE(FilledSize, AvailableSize, RequiredSpace ) ((FilledSize) + (RequiredSpace) <= (AvailableSize) )
  45. BOOL _inline
  46. CheckForVendor(
  47. IN DWORD OptId,
  48. IN BOOL IsVendor
  49. )
  50. {
  51. if( IsVendor ) return (256 <= OptId);
  52. return 256 > OptId;
  53. }
  54. DWORD _inline
  55. ConvertOptIdToRPCValue(
  56. IN DWORD OptId,
  57. IN BOOL IsVendorUnused
  58. )
  59. {
  60. return OptId % 256;
  61. }
  62. DWORD _inline
  63. ConvertOptIdToMemValue(
  64. IN DWORD OptId,
  65. IN BOOL IsVendor
  66. )
  67. {
  68. if( IsVendor ) return OptId + 256;
  69. return OptId;
  70. }
  71. DWORD
  72. DhcpConvertOptionRPCToRegFormat(
  73. IN LPDHCP_OPTION_DATA Option,
  74. IN OUT LPBYTE RegBuffer, // OPTIONAL
  75. IN OUT DWORD *BufferSize // input: buffer size, output: filled buffer size
  76. )
  77. {
  78. OPTION_BIN Dummy;
  79. DWORD AvailableSize;
  80. DWORD FilledSize;
  81. DWORD nElements;
  82. DWORD i;
  83. DWORD DataLength;
  84. DWORD Length;
  85. DHCP_OPTION_DATA_TYPE OptType;
  86. LPBYTE BufStart;
  87. AvailableSize = *BufferSize;
  88. FilledSize = 0;
  89. BufStart = RegBuffer;
  90. Dummy.DataSize = sizeof(Dummy);
  91. Dummy.OptionType = DhcpByteOption;
  92. Dummy.NumElements = 0;
  93. FilledSize = ROUND_UP_COUNT(sizeof(Dummy), ALIGN_WORST);
  94. RegBuffer += FilledSize; // will do this actual filling at the very end
  95. if( NULL == Option || 0 == Option->NumElements ) {
  96. OptType = DhcpByteOption;
  97. nElements =0;
  98. } else {
  99. OptType = Option->Elements[0].OptionType;
  100. nElements = Option->NumElements;
  101. }
  102. for( i = 0; i < nElements ; i ++ ) { // marshal each argument in
  103. if( OptType != Option->Elements[i].OptionType ) {
  104. return ERROR_INVALID_PARAMETER; // do not allow random option types, all got to be same
  105. }
  106. switch(OptType) {
  107. case DhcpByteOption:
  108. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD)) ) {
  109. *((LPDWORD)RegBuffer) = Option->Elements[i].Element.ByteOption;
  110. RegBuffer += sizeof(DWORD);
  111. }
  112. FilledSize += sizeof(DWORD);
  113. break;
  114. case DhcpWordOption:
  115. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD)) ) {
  116. *((LPDWORD)RegBuffer) = Option->Elements[i].Element.WordOption;
  117. RegBuffer += sizeof(DWORD);
  118. }
  119. FilledSize += sizeof(DWORD);
  120. break;
  121. case DhcpDWordOption:
  122. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD) )) {
  123. *((LPDWORD)RegBuffer) = Option->Elements[i].Element.DWordOption;
  124. RegBuffer += sizeof(DWORD);
  125. }
  126. FilledSize += sizeof(DWORD);
  127. break;
  128. case DhcpDWordDWordOption:
  129. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DWORD_DWORD)) ) {
  130. *((LPDWORD_DWORD)RegBuffer) = Option->Elements[i].Element.DWordDWordOption;
  131. RegBuffer += sizeof(DWORD);
  132. }
  133. FilledSize += sizeof(DWORD_DWORD);
  134. break;
  135. case DhcpIpAddressOption:
  136. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, sizeof(DHCP_IP_ADDRESS)) ) {
  137. *((LPDHCP_IP_ADDRESS)RegBuffer) = Option->Elements[i].Element.IpAddressOption;
  138. RegBuffer += sizeof(DHCP_IP_ADDRESS);
  139. }
  140. FilledSize += sizeof(DHCP_IP_ADDRESS);
  141. break;
  142. case DhcpStringDataOption:
  143. if( NULL == Option->Elements[i].Element.StringDataOption ) {
  144. DataLength = ROUND_UP_COUNT((FilledSize + sizeof(DWORD) + sizeof(WCHAR)), ALIGN_DWORD);
  145. DataLength -= FilledSize;
  146. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength ) ) {
  147. *(LPDWORD)RegBuffer = (DWORD) sizeof(WCHAR);
  148. RegBuffer += sizeof(DWORD);
  149. *(LPWSTR)RegBuffer = L'\0';
  150. RegBuffer += ROUND_UP_COUNT(sizeof(WCHAR), ALIGN_DWORD);
  151. DhcpAssert(sizeof(DWORD) + ROUND_UP_COUNT(sizeof(WCHAR),ALIGN_DWORD) == DataLength);
  152. }
  153. FilledSize += DataLength;
  154. break;
  155. }
  156. Length = (1+wcslen(Option->Elements[i].Element.StringDataOption))*sizeof(WCHAR);
  157. DataLength = ROUND_UP_COUNT((Length + FilledSize + sizeof(DWORD)), ALIGN_DWORD);
  158. DataLength -= FilledSize;
  159. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength) ) {
  160. *((LPDWORD)RegBuffer) = Length;
  161. RegBuffer += sizeof(DWORD);
  162. memcpy(RegBuffer, Option->Elements[i].Element.StringDataOption, Length );
  163. RegBuffer += ROUND_UP_COUNT(Length, ALIGN_DWORD);
  164. DhcpAssert(ROUND_UP_COUNT(Length,ALIGN_DWORD) + sizeof(DWORD) == DataLength);
  165. }
  166. FilledSize += DataLength;
  167. break;
  168. case DhcpBinaryDataOption:
  169. case DhcpEncapsulatedDataOption:
  170. Length = Option->Elements[i].Element.BinaryDataOption.DataLength;
  171. DataLength = ROUND_UP_COUNT((FilledSize+Length+sizeof(DWORD)), ALIGN_DWORD);
  172. DataLength -= FilledSize;
  173. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength) ) {
  174. *((LPDWORD)RegBuffer) = Length;
  175. RegBuffer += sizeof(DWORD);
  176. memcpy(RegBuffer, Option->Elements[i].Element.BinaryDataOption.Data, Length);
  177. Length = ROUND_UP_COUNT(Length, ALIGN_DWORD);
  178. DhcpAssert(Length + sizeof(DWORD) == DataLength);
  179. RegBuffer += Length;
  180. }
  181. FilledSize += DataLength;
  182. break;
  183. default:
  184. return ERROR_INVALID_PARAMETER; // Dont support any other kind of options
  185. }
  186. }
  187. // Length = ROUND_UP_COUNT(FilledSize, ALIGN_WORST);
  188. *BufferSize = FilledSize;
  189. if( AvailableSize < FilledSize ) return ERROR_MORE_DATA;
  190. Dummy.NumElements = nElements;
  191. Dummy.DataSize = *BufferSize;
  192. Dummy.OptionType = OptType;
  193. memcpy(BufStart, (LPBYTE)&Dummy, sizeof(Dummy));
  194. return ERROR_SUCCESS;
  195. }
  196. //================================================================================
  197. // helper routines for ds..
  198. //================================================================================
  199. VOID static
  200. MemFreeFunc(
  201. IN OUT LPVOID Memory
  202. )
  203. {
  204. MemFree(Memory);
  205. }
  206. //DOC DhcpConvertOptionRegToRPCFormat2 converts from the registry format option
  207. //DOC to the RPC format. Additionally, it packs the whole stuff in one buffer.
  208. //DOC If the Option buffer size (in bytes) as specified for input, is insufficient
  209. //DOC to hold all the data, then, the function returns ERROR_MORE_DATA and sets
  210. //DOC the same Size parameter to hold the actual # of bytes space required.
  211. //DOC On a successful conversion, Size holds the total # of bytes copied.
  212. //DOC Most of the code is same as for DhcpConvertOptionRegToRPCFormat
  213. //DOC
  214. DWORD
  215. DhcpConvertOptionRegToRPCFormat2( // convert from Reg fmt to RPC..
  216. IN LPBYTE Buffer, // reg fmt option buffer
  217. IN DWORD BufferSize, // size of above in bytes
  218. IN OUT LPDHCP_OPTION_DATA Option, // where to fill the option data
  219. IN OUT LPBYTE OptBuf, // buffer for internal option data..
  220. IN OUT DWORD *Size // i/p: sizeof(Option) o/p: reqd size
  221. )
  222. {
  223. LPOPTION_BIN OptBin;
  224. LPBYTE OptData;
  225. LPBYTE DataBuffer;
  226. DWORD OptSize;
  227. DWORD OptType;
  228. DWORD nElements;
  229. DWORD i;
  230. DWORD NetworkULong;
  231. DWORD DataLength;
  232. DWORD FilledSize;
  233. DWORD AvailableSize;
  234. WORD NetworkUShort;
  235. LPDHCP_OPTION_DATA_ELEMENT Elements;
  236. if( !Buffer || !BufferSize || !Size ) return ERROR_INVALID_PARAMETER;
  237. AvailableSize = *Size;
  238. FilledSize = *Size = 0;
  239. OptBin = (LPOPTION_BIN)Buffer;
  240. if(OptBin->DataSize != BufferSize) { // internal error!
  241. DhcpPrint((DEBUG_ERRORS, "Internal error while parsing options\n"));
  242. DhcpAssert(FALSE);
  243. return ERROR_INVALID_PARAMETER;
  244. }
  245. OptType = OptBin->OptionType; // copy highly used stuff
  246. nElements = OptBin->NumElements;
  247. OptData = OptBin->Data;
  248. OptData = ROUND_UP_COUNT(sizeof(OPTION_BIN), ALIGN_WORST) + (LPBYTE)OptBin;
  249. if( Option ) {
  250. Option->NumElements = 0;
  251. Option->Elements = NULL;
  252. }
  253. if( 0 == nElements ) {
  254. return ERROR_SUCCESS;
  255. }
  256. Elements = (LPVOID)OptBuf;
  257. FilledSize += nElements * ROUND_UP_COUNT(sizeof(DHCP_OPTION_DATA_ELEMENT), ALIGN_WORST);
  258. if( !IS_SPACE_AVAILABLE(FilledSize, AvailableSize, 0 ) ) {
  259. Elements = NULL; // not enough space is really available..
  260. }
  261. for(i = 0; i < nElements ; i ++ ) { // marshal the elements in the data buffer
  262. if( Elements ) { // copy only when space is there
  263. Elements[i].OptionType = OptType;
  264. }
  265. switch( OptType ) { // each type has diff fields to look at
  266. case DhcpByteOption:
  267. if( Elements ) {
  268. Elements[i].Element.ByteOption = *((LPBYTE)OptData);
  269. }
  270. OptData += sizeof(DWORD);
  271. break;
  272. case DhcpWordOption:
  273. if( Elements ) {
  274. Elements[i].Element.WordOption = (WORD)(*((LPDWORD)OptData));
  275. }
  276. OptData += sizeof(DWORD);
  277. break;
  278. case DhcpDWordOption:
  279. if( Elements ) {
  280. Elements[i].Element.DWordOption = *((LPDWORD)OptData);
  281. }
  282. OptData += sizeof(DWORD);
  283. break;
  284. case DhcpDWordDWordOption:
  285. if( Elements ) {
  286. Elements[i].Element.DWordDWordOption = *((LPDWORD_DWORD)OptData);
  287. }
  288. OptData += sizeof(DWORD_DWORD);
  289. break;
  290. case DhcpIpAddressOption:
  291. if( Elements ) {
  292. Elements[i].Element.IpAddressOption = *((LPDHCP_IP_ADDRESS)OptData);
  293. }
  294. OptData += sizeof(DHCP_IP_ADDRESS);
  295. break;
  296. case DhcpStringDataOption:
  297. case DhcpBinaryDataOption:
  298. case DhcpEncapsulatedDataOption:
  299. DataLength = *((LPWORD)OptData);
  300. OptData += sizeof(DWORD);
  301. if( IS_SPACE_AVAILABLE(FilledSize, AvailableSize, DataLength) ) {
  302. DataBuffer = (LPVOID)(FilledSize + OptBuf);
  303. } else {
  304. DataBuffer = NULL;
  305. }
  306. FilledSize += DataLength;
  307. if( DataBuffer ) {
  308. RtlCopyMemory( DataBuffer, OptData, DataLength );
  309. }
  310. OptData += ROUND_UP_COUNT(DataLength, ALIGN_DWORD);
  311. if( Elements ) {
  312. if( OptType == DhcpStringDataOption ) {
  313. Elements[i].Element.StringDataOption = (LPWSTR)DataBuffer;
  314. } else {
  315. Elements[i].Element.BinaryDataOption.DataLength = DataLength;
  316. Elements[i].Element.BinaryDataOption.Data = DataBuffer;
  317. }
  318. }
  319. DhcpAssert( i == 0 ); // should not be more than one binary element specified
  320. if( i > 0 ) {
  321. DhcpPrint(( DEBUG_OPTIONS, "Multiple Binary option packed\n"));
  322. }
  323. break;
  324. default:
  325. DhcpPrint(( DEBUG_OPTIONS, "Unknown option found\n"));
  326. break;
  327. }
  328. }
  329. if( Option ) {
  330. Option->NumElements = i; // nElements maybe?
  331. Option->Elements = Elements;
  332. }
  333. *Size = FilledSize;
  334. if( FilledSize <= AvailableSize ) return ERROR_SUCCESS;
  335. return ERROR_MORE_DATA; // did not copy everything actually.
  336. }
  337. //================================================================================
  338. // DS Access Routines
  339. //================================================================================
  340. //BeginExport(function)
  341. //DOC DhcpDsCreateOptionDef tries to create an option definition in the DS with the
  342. //DOC given attributes. The option must not exist in the DS prior to this call.
  343. //DOC There are requirements on the fmt used in the DS.
  344. DWORD
  345. DhcpDsCreateOptionDef( // create option definition
  346. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  347. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  348. IN DWORD Reserved, // must be zero, future use
  349. IN LPWSTR Name, // option name
  350. IN LPWSTR Comment, // OPTIONAL option comment
  351. IN LPWSTR ClassName, // OPTIONAL unused, opt class
  352. IN DWORD OptId, // # between 0-255 per DHCP draft
  353. IN DWORD OptType, // some option flags
  354. IN LPBYTE OptVal, // default option value
  355. IN DWORD OptLen // # of bytes of above
  356. ) //EndExport(function)
  357. {
  358. DWORD Result, unused;
  359. ARRAY OptDefAttribs;
  360. PEATTRIB ThisAttrib;
  361. EATTRIB DummyAttrib;
  362. ARRAY_LOCATION Loc;
  363. MemArrayInit(&OptDefAttribs);
  364. Result = DhcpDsGetLists( // get list of opt defs frm DS
  365. /* Reserved */ DDS_RESERVED_DWORD,
  366. /* hStore */ hServer,
  367. /* RecursionDepth */ 0xFFFFFFFF,
  368. /* Servers */ NULL,
  369. /* Subnets */ NULL,
  370. /* IpAddress */ NULL,
  371. /* Mask */ NULL,
  372. /* Ranges */ NULL,
  373. /* Sites */ NULL,
  374. /* Reservations */ NULL,
  375. /* SuperScopes */ NULL,
  376. /* OptionDescription */ &OptDefAttribs,
  377. /* OptionsLocation */ NULL,
  378. /* Options */ NULL,
  379. /* Classes */ NULL
  380. );
  381. if( ERROR_SUCCESS != Result ) return Result;
  382. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  383. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  384. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  385. ) {
  386. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  387. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  388. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  389. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  390. continue; // mismatch
  391. }
  392. if( ClassName ) { // need to check class name
  393. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  394. if( 0 != wcscmp(ThisAttrib->String3, ClassName) ) continue;
  395. }
  396. Result = ERROR_DDS_OPTION_ALREADY_EXISTS;
  397. goto Cleanup;
  398. }
  399. }
  400. NothingPresent(&DummyAttrib); // prepare an elt to add to list
  401. STRING1_PRESENT(&DummyAttrib);
  402. if( Comment ) STRING2_PRESENT(&DummyAttrib);
  403. if( ClassName ) STRING3_PRESENT(&DummyAttrib);
  404. DWORD1_PRESENT(&DummyAttrib);
  405. BINARY1_PRESENT(&DummyAttrib);
  406. FLAGS1_PRESENT(&DummyAttrib);
  407. DummyAttrib.String1 = Name; // fill in reqd fields only
  408. if( Comment ) DummyAttrib.String2 = Comment;
  409. if( ClassName ) DummyAttrib.String3 = ClassName;
  410. DummyAttrib.Dword1 = OptId;
  411. DummyAttrib.Flags1 = OptType;
  412. DummyAttrib.Binary1 = OptVal;
  413. DummyAttrib.BinLen1 = OptLen;
  414. Result = MemArrayAddElement(&OptDefAttribs, &DummyAttrib);
  415. if( ERROR_SUCCESS != Result ) goto Cleanup; // Add dummy element to list
  416. Result = DhcpDsSetLists( // set the new list in DS
  417. /* Reserved */ DDS_RESERVED_DWORD,
  418. /* hStore */ hServer,
  419. /* SetParams */ &unused,
  420. /* Servers */ NULL,
  421. /* Subnets */ NULL,
  422. /* IpAddress */ NULL,
  423. /* Mask */ NULL,
  424. /* Ranges */ NULL,
  425. /* Sites */ NULL,
  426. /* Reservations */ NULL,
  427. /* SuperScopes */ NULL,
  428. /* OptionDescripti.. */ &OptDefAttribs,
  429. /* OptionsLocation */ NULL,
  430. /* Options */ NULL,
  431. /* ClassDescriptio.. */ NULL,
  432. /* Classes */ NULL
  433. );
  434. (void)MemArrayLastLoc(&OptDefAttribs, &Loc); // clear up list to way it was
  435. //- ERROR_SUCCESS == Result
  436. (void)MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib);
  437. //- ERROR_SUCCESS == Result && ThisAttrib == &DummyAttrib
  438. Cleanup: // free up any memory used
  439. (void)MemArrayFree(&OptDefAttribs, MemFreeFunc);
  440. return Result;
  441. }
  442. //BeginExport(function)
  443. //DOC DhcpDsModifyOptionDef tries to modify an existing optdef in the DS with the
  444. //DOC given attributes. The option must exist in the DS prior to this call.
  445. //DOC There are requirements on the fmt used in the DS.
  446. DWORD
  447. DhcpDsModifyOptionDef( // modify option definition
  448. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  449. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  450. IN DWORD Reserved, // must be zero, future use
  451. IN LPWSTR Name, // option name
  452. IN LPWSTR Comment, // OPTIONAL option comment
  453. IN LPWSTR ClassName, // OPTIONAL unused, opt class
  454. IN DWORD OptId, // # between 0-255 per DHCP draft
  455. IN DWORD OptType, // some option flags
  456. IN LPBYTE OptVal, // default option value
  457. IN DWORD OptLen // # of bytes of above
  458. ) //EndExport(function)
  459. {
  460. DWORD Result, unused;
  461. ARRAY OptDefAttribs;
  462. PEATTRIB ThisAttrib;
  463. EATTRIB DummyAttrib;
  464. ARRAY_LOCATION Loc;
  465. MemArrayInit(&OptDefAttribs);
  466. Result = DhcpDsGetLists( // get list of opt defs frm DS
  467. /* Reserved */ DDS_RESERVED_DWORD,
  468. /* hStore */ hServer,
  469. /* RecursionDepth */ 0xFFFFFFFF,
  470. /* Servers */ NULL,
  471. /* Subnets */ NULL,
  472. /* IpAddress */ NULL,
  473. /* Mask */ NULL,
  474. /* Ranges */ NULL,
  475. /* Sites */ NULL,
  476. /* Reservations */ NULL,
  477. /* SuperScopes */ NULL,
  478. /* OptionDescription */ &OptDefAttribs,
  479. /* OptionsLocation */ NULL,
  480. /* Options */ NULL,
  481. /* Classes */ NULL
  482. );
  483. if( ERROR_SUCCESS != Result ) return Result;
  484. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  485. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  486. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  487. ) {
  488. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  489. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  490. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  491. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  492. continue; // mismatch
  493. }
  494. if( ClassName ) { // need to check class name
  495. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  496. if( 0 != wcscmp(ThisAttrib->String3, ClassName) ) continue;
  497. }
  498. Result = MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib);
  499. //- ERROR_SUCCESS == Result
  500. MemFreeFunc(ThisAttrib);
  501. Result = ERROR_SUCCESS;
  502. break;
  503. }
  504. }
  505. if( ERROR_SUCCESS != Result ) { // option def was not found
  506. Result = ERROR_DDS_OPTION_DOES_NOT_EXIST;
  507. }
  508. NothingPresent(&DummyAttrib); // prepare an elt to add to list
  509. STRING1_PRESENT(&DummyAttrib);
  510. if( Comment ) STRING2_PRESENT(&DummyAttrib);
  511. if( ClassName ) STRING3_PRESENT(&DummyAttrib);
  512. DWORD1_PRESENT(&DummyAttrib);
  513. BINARY1_PRESENT(&DummyAttrib);
  514. FLAGS1_PRESENT(&DummyAttrib);
  515. DummyAttrib.String1 = Name; // fill in reqd fields only
  516. if( Comment ) DummyAttrib.String2 = Comment;
  517. if( ClassName )DummyAttrib.String3 = ClassName;
  518. DummyAttrib.Dword1 = OptId;
  519. DummyAttrib.Flags1 = OptType;
  520. DummyAttrib.Binary1 = OptVal;
  521. DummyAttrib.BinLen1 = OptLen;
  522. Result = MemArrayAddElement(&OptDefAttribs, &DummyAttrib);
  523. if( ERROR_SUCCESS != Result ) goto Cleanup; // Add dummy element to list
  524. Result = DhcpDsSetLists( // set the new list in DS
  525. /* Reserved */ DDS_RESERVED_DWORD,
  526. /* hStore */ hServer,
  527. /* SetParams */ &unused,
  528. /* Servers */ NULL,
  529. /* Subnets */ NULL,
  530. /* IpAddress */ NULL,
  531. /* Mask */ NULL,
  532. /* Ranges */ NULL,
  533. /* Sites */ NULL,
  534. /* Reservations */ NULL,
  535. /* SuperScopes */ NULL,
  536. /* OptionDescripti.. */ &OptDefAttribs,
  537. /* OptionsLocation */ NULL,
  538. /* Options */ NULL,
  539. /* ClassDescriptio.. */ NULL,
  540. /* Classes */ NULL
  541. );
  542. (void)MemArrayLastLoc(&OptDefAttribs, &Loc); // clear up list to way it was
  543. //- ERROR_SUCCESS == Result
  544. (void)MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib);
  545. //- ERROR_SUCCESS == Result && ThisAttrib == &DummyAttrib
  546. Cleanup: // free up any memory used
  547. (void)MemArrayFree(&OptDefAttribs, MemFreeFunc);
  548. return Result;
  549. }
  550. //BeginExport(function)
  551. //DOC DhcpDsEnumOptionDefs gets the list of options defined for the given class.
  552. //DOC Currently, class is ignored as option defs dont have classes associated.
  553. //DOC There are requirements on the fmt used in the DS.
  554. DWORD
  555. DhcpDsEnumOptionDefs( // enum list of opt defs in DS
  556. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  557. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  558. IN DWORD Reserved, // must be zero, future use
  559. IN LPWSTR ClassName, // OPTIONAL, unused.
  560. IN BOOL IsVendor, // vendor only? non-vendor only?
  561. OUT LPDHCP_OPTION_ARRAY *RetOptArray // allocated and fill this.
  562. ) //EndExport(function)
  563. {
  564. DWORD Result, Result2, unused, Size, Size2, i, AllocSize;
  565. ARRAY OptDefAttribs;
  566. PEATTRIB ThisAttrib;
  567. EATTRIB DummyAttrib;
  568. ARRAY_LOCATION Loc;
  569. LPDHCP_OPTION_ARRAY OptArray;
  570. LPBYTE Ptr;
  571. *RetOptArray = NULL;
  572. MemArrayInit(&OptDefAttribs);
  573. Result = DhcpDsGetLists( // get list of opt defs frm DS
  574. /* Reserved */ DDS_RESERVED_DWORD,
  575. /* hStore */ hServer,
  576. /* RecursionDepth */ 0xFFFFFFFF,
  577. /* Servers */ NULL,
  578. /* Subnets */ NULL,
  579. /* IpAddress */ NULL,
  580. /* Mask */ NULL,
  581. /* Ranges */ NULL,
  582. /* Sites */ NULL,
  583. /* Reservations */ NULL,
  584. /* SuperScopes */ NULL,
  585. /* OptionDescription */ &OptDefAttribs,
  586. /* OptionsLocation */ NULL,
  587. /* Options */ NULL,
  588. /* Classes */ NULL
  589. );
  590. if( ERROR_SUCCESS != Result ) return Result;
  591. Size = i = 0; // calculate size
  592. Size += ROUND_UP_COUNT(sizeof(DHCP_OPTION_ARRAY), ALIGN_WORST);
  593. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  594. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  595. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  596. ) {
  597. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  598. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  599. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib)
  600. || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
  601. continue; // skip it
  602. }
  603. if( !CheckForVendor(ThisAttrib->Dword1, IsVendor) ) {
  604. continue; // separate vendor and non-vendor
  605. }
  606. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  607. continue; // classname mismatch
  608. }
  609. if( ClassName ) { // need to have matching class
  610. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  611. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  612. }
  613. Size2 = 0;
  614. Result2 = DhcpConvertOptionRegToRPCFormat2(
  615. /* Buffer */ ThisAttrib->Binary1,
  616. /* BufferSize */ ThisAttrib->BinLen1,
  617. /* Option */ NULL, // will allocate this later
  618. /* OptBuf */ NULL,
  619. /* Size */ &Size2
  620. );
  621. if( ERROR_MORE_DATA == Result2 ) Result2 = ERROR_SUCCESS;
  622. if( ERROR_SUCCESS != Result2 ) continue; // errors? skip this attrib
  623. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  624. Size2 = sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1));
  625. if( IS_STRING2_PRESENT(ThisAttrib) ) { // if comment is present..
  626. Size2 += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String2));
  627. }
  628. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  629. i ++;
  630. }
  631. Size += ROUND_UP_COUNT(i* sizeof(DHCP_OPTION), ALIGN_WORST);
  632. Ptr = MemAlloc(AllocSize = Size);
  633. OptArray = (LPVOID)Ptr;
  634. if( NULL == OptArray ) return ERROR_NOT_ENOUGH_MEMORY;
  635. Size = 0; // this time, fill in the values
  636. Size += ROUND_UP_COUNT(sizeof(DHCP_OPTION_ARRAY), ALIGN_WORST);
  637. Ptr += Size;
  638. OptArray->NumElements = i;
  639. OptArray->Options = (LPVOID)Ptr;
  640. Size += ROUND_UP_COUNT(i* sizeof(DHCP_OPTION), ALIGN_WORST);
  641. Ptr += ROUND_UP_COUNT(i* sizeof(DHCP_OPTION), ALIGN_WORST);
  642. i = 0;
  643. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  644. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  645. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  646. ) {
  647. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  648. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  649. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib)
  650. || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
  651. continue; // skip it
  652. }
  653. if( !CheckForVendor(ThisAttrib->Dword1, IsVendor) ) {
  654. continue; // separate vendor and non-vendor
  655. }
  656. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  657. continue; // classname mismatch
  658. }
  659. if( ClassName ) { // need to have matching class
  660. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  661. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  662. }
  663. Size2 = AllocSize - Size;
  664. Result2 = DhcpConvertOptionRegToRPCFormat2(
  665. /* Buffer */ ThisAttrib->Binary1,
  666. /* BufferSize */ ThisAttrib->BinLen1,
  667. /* Option */ &OptArray->Options[i].DefaultValue,
  668. /* OptBuf */ Ptr,
  669. /* Size */ &Size2
  670. );
  671. //- ERROR_MORE_DATA != Result2
  672. if( ERROR_SUCCESS != Result2 ) continue; // errors? skip this attrib
  673. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  674. Ptr += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  675. OptArray->Options[i].OptionID = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE);
  676. if( IS_FLAGS1_PRESENT(ThisAttrib) ) { // if some flags present
  677. OptArray->Options[i].OptionType = ThisAttrib->Flags1;
  678. } else { // if no flags present, assume 0 type
  679. OptArray->Options[i].OptionType = 0;
  680. }
  681. OptArray->Options[i].OptionName = (LPVOID)Ptr;
  682. wcscpy((LPWSTR)Ptr, ThisAttrib->String1);
  683. Ptr += sizeof(WCHAR)*(1+wcslen((LPWSTR)Ptr));
  684. Size2 = sizeof(WCHAR)*(1+wcslen(ThisAttrib->String1));
  685. if( IS_STRING2_PRESENT(ThisAttrib) ) { // if comment is present..
  686. Size2 += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String2));
  687. OptArray->Options[i].OptionComment = (LPVOID)Ptr;
  688. wcscpy((LPWSTR)Ptr, ThisAttrib->String2);
  689. } else {
  690. OptArray->Options[i].OptionComment = NULL;
  691. }
  692. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  693. Ptr = ROUND_UP_COUNT(Size2, ALIGN_WORST) + (LPBYTE)(OptArray->Options[i].OptionName);
  694. i ++;
  695. }
  696. //- OptArray->NumElements == i
  697. *RetOptArray = OptArray;
  698. return ERROR_SUCCESS;
  699. }
  700. //BeginExport(function)
  701. //DOC DhcpDsDeleteOptionDef deletes an option definition in the DS based on the option id.
  702. //DOC Note that the ClassName field is currently ignored.
  703. //DOC No error is reported if the option is not present in the DS.
  704. //DOC
  705. DWORD
  706. DhcpDsDeleteOptionDef( // enum list of opt defs in DS
  707. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  708. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  709. IN DWORD Reserved, // must be zero, future use
  710. IN LPWSTR ClassName, // OPTIONAL, unused.
  711. IN DWORD OptId
  712. ) //EndExport(function)
  713. {
  714. DWORD Result, Result2, unused;
  715. ARRAY OptDefAttribs;
  716. PEATTRIB ThisAttrib;
  717. EATTRIB DummyAttrib;
  718. ARRAY_LOCATION Loc;
  719. MemArrayInit(&OptDefAttribs);
  720. Result = DhcpDsGetLists( // get list of opt defs frm DS
  721. /* Reserved */ DDS_RESERVED_DWORD,
  722. /* hStore */ hServer,
  723. /* RecursionDepth */ 0xFFFFFFFF,
  724. /* Servers */ NULL,
  725. /* Subnets */ NULL,
  726. /* IpAddress */ NULL,
  727. /* Mask */ NULL,
  728. /* Ranges */ NULL,
  729. /* Sites */ NULL,
  730. /* Reservations */ NULL,
  731. /* SuperScopes */ NULL,
  732. /* OptionDescription */ &OptDefAttribs,
  733. /* OptionsLocation */ NULL,
  734. /* Options */ NULL,
  735. /* Classes */ NULL
  736. );
  737. if( ERROR_SUCCESS != Result ) return Result;
  738. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  739. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  740. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  741. ) {
  742. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  743. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  744. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  745. continue; // classname mismatch
  746. }
  747. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  748. if( ClassName ) { // need to have matching class
  749. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  750. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  751. }
  752. Result = MemArrayDelElement(&OptDefAttribs, &Loc, &ThisAttrib);
  753. //- ERROR_SUCCESS == Result
  754. MemFreeFunc(ThisAttrib);
  755. Result = ERROR_SUCCESS;
  756. break;
  757. }
  758. }
  759. if( ERROR_SUCCESS != Result ) { // could not find the option in DS
  760. Result = ERROR_SUCCESS; // pretend everything was fine
  761. } else {
  762. Result = DhcpDsSetLists( // set the new list in DS
  763. /* Reserved */ DDS_RESERVED_DWORD,
  764. /* hStore */ hServer,
  765. /* SetParams */ &unused,
  766. /* Servers */ NULL,
  767. /* Subnets */ NULL,
  768. /* IpAddress */ NULL,
  769. /* Mask */ NULL,
  770. /* Ranges */ NULL,
  771. /* Sites */ NULL,
  772. /* Reservations */ NULL,
  773. /* SuperScopes */ NULL,
  774. /* OptionDescripti.. */ &OptDefAttribs,
  775. /* OptionsLocation */ NULL,
  776. /* Options */ NULL,
  777. /* ClassDescriptio.. */ NULL,
  778. /* Classes */ NULL
  779. );
  780. }
  781. (void) MemArrayFree(&OptDefAttribs, MemFreeFunc);
  782. return Result;
  783. }
  784. //BeginExport(function)
  785. //DOC DhcpDsDeleteOptionDef deletes an option definition in the DS based on the option id.
  786. //DOC Note that the ClassName field is currently ignored.
  787. //DOC No error is reported if the option is not present in the DS.
  788. //DOC
  789. DWORD
  790. DhcpDsGetOptionDef( // enum list of opt defs in DS
  791. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  792. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  793. IN DWORD Reserved, // must be zero, future use
  794. IN LPWSTR ClassName, // OPTIONAL, unused.
  795. IN DWORD OptId,
  796. OUT LPDHCP_OPTION *OptInfo
  797. ) //EndExport(function)
  798. {
  799. DWORD Result, Result2, unused;
  800. ARRAY OptDefAttribs;
  801. PEATTRIB ThisAttrib;
  802. EATTRIB DummyAttrib;
  803. ARRAY_LOCATION Loc;
  804. MemArrayInit(&OptDefAttribs);
  805. Result = DhcpDsGetLists( // get list of opt defs frm DS
  806. /* Reserved */ DDS_RESERVED_DWORD,
  807. /* hStore */ hServer,
  808. /* RecursionDepth */ 0xFFFFFFFF,
  809. /* Servers */ NULL,
  810. /* Subnets */ NULL,
  811. /* IpAddress */ NULL,
  812. /* Mask */ NULL,
  813. /* Ranges */ NULL,
  814. /* Sites */ NULL,
  815. /* Reservations */ NULL,
  816. /* SuperScopes */ NULL,
  817. /* OptionDescription */ &OptDefAttribs,
  818. /* OptionsLocation */ NULL,
  819. /* Options */ NULL,
  820. /* Classes */ NULL
  821. );
  822. if( ERROR_SUCCESS != Result ) return Result;
  823. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  824. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  825. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  826. ) {
  827. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  828. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  829. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  830. // invalid attributes?
  831. continue;
  832. }
  833. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  834. continue; // classname mismatch
  835. }
  836. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  837. if( ClassName ) { // need to have matching class
  838. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  839. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  840. }
  841. Result = ERROR_SUCCESS;
  842. break;
  843. }
  844. }
  845. if( ERROR_SUCCESS == Result ) do {
  846. ULONG Size, Size2;
  847. LPBYTE Ptr;
  848. Size2 = Size = 0;
  849. Result = DhcpConvertOptionRegToRPCFormat2(
  850. /* Buffer */ ThisAttrib->Binary1,
  851. /* BufferSize */ ThisAttrib->BinLen1,
  852. /* Option */ NULL, // will allocate this later
  853. /* OptBuf */ NULL,
  854. /* Size */ &Size2
  855. );
  856. if( ERROR_MORE_DATA == Result ) Result = ERROR_SUCCESS;
  857. if( ERROR_SUCCESS != Result ) break; // errors? skip this attrib
  858. Size = ROUND_UP_COUNT(sizeof(DHCP_OPTION), ALIGN_WORST);
  859. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  860. Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1));
  861. if( IS_STRING2_PRESENT(ThisAttrib) ) {
  862. Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String2));
  863. }
  864. (*OptInfo) = (LPVOID)Ptr = MemAlloc(Size);
  865. if( NULL == *OptInfo ) { Result = ERROR_NOT_ENOUGH_MEMORY ; break; }
  866. Ptr += ROUND_UP_COUNT(sizeof(DHCP_OPTION), ALIGN_WORST);
  867. (*OptInfo)->OptionID = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE);
  868. if( IS_FLAGS1_PRESENT(ThisAttrib) ) (*OptInfo)->OptionType = ThisAttrib->Flags1;
  869. else (*OptInfo)->OptionType = 0;
  870. Size2 = Size - ROUND_UP_COUNT(sizeof(DHCP_OPTION), ALIGN_WORST);
  871. Result = DhcpConvertOptionRegToRPCFormat2(
  872. /* Buffer */ ThisAttrib->Binary1,
  873. /* BufferSize */ ThisAttrib->BinLen1,
  874. /* Option */ &((*OptInfo)->DefaultValue),
  875. /* OptBuf */ Ptr,
  876. /* Size */ &Size2
  877. );
  878. Ptr += Size2;
  879. (*OptInfo)->OptionName = (LPVOID)Ptr; wcscpy((LPWSTR)Ptr, ThisAttrib->String1);
  880. if( !IS_STRING2_PRESENT(ThisAttrib) ) (*OptInfo)->OptionComment = NULL;
  881. else {
  882. Ptr += sizeof(WCHAR)*(1+ wcslen(ThisAttrib->String1));
  883. (*OptInfo)->OptionComment = (LPVOID)Ptr;
  884. wcscpy((LPWSTR)Ptr, ThisAttrib->String2);
  885. }
  886. Result = ERROR_SUCCESS;
  887. } while(0);
  888. (void) MemArrayFree(&OptDefAttribs, MemFreeFunc);
  889. return Result;
  890. }
  891. //BeginExport(function)
  892. //DOC DhcpDsSetOptionValue sets the required option value in the DS.
  893. //DOC Note that if the option existed earlier, it is overwritten. Also, the
  894. //DOC option definition is not checked against -- so there need not be an
  895. //DOC option type specified.
  896. //DOC Also, this function works assuming that the option has to be written
  897. //DOC to the current object in DS as given by hObject ptr.
  898. //DOC There are requirements on the fmt used in the DS.
  899. DWORD
  900. DhcpDsSetOptionValue( // set option value
  901. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  902. IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
  903. IN DWORD Reserved, // must be zero, future use
  904. IN LPWSTR ClassName, // name of class for this opt
  905. IN LPWSTR UserClass, // name of user class for this opt
  906. IN DWORD OptId, // option id
  907. IN LPDHCP_OPTION_DATA OptData // what is the option
  908. ) //EndExport(function)
  909. {
  910. DWORD Result, Result2, unused, ValueSize;
  911. ARRAY OptAttribs;
  912. PEATTRIB ThisAttrib;
  913. EATTRIB DummyAttrib;
  914. ARRAY_LOCATION Loc;
  915. LPBYTE Value;
  916. MemArrayInit(&OptAttribs);
  917. Result = DhcpDsGetLists( // get list of options frm DS
  918. /* Reserved */ DDS_RESERVED_DWORD,
  919. /* hStore */ hObject,
  920. /* RecursionDepth */ 0xFFFFFFFF,
  921. /* Servers */ NULL,
  922. /* Subnets */ NULL,
  923. /* IpAddress */ NULL,
  924. /* Mask */ NULL,
  925. /* Ranges */ NULL,
  926. /* Sites */ NULL,
  927. /* Reservations */ NULL,
  928. /* SuperScopes */ NULL,
  929. /* OptionDescription */ NULL,
  930. /* OptionsLocation */ NULL,
  931. /* Options */ &OptAttribs,
  932. /* Classes */ NULL
  933. );
  934. // if( ERROR_SUCCESS != Result ) return Result;
  935. for( Result = MemArrayInitLoc(&OptAttribs, &Loc)
  936. ; ERROR_FILE_NOT_FOUND != Result ; // search for option w/ <OptId>
  937. Result = MemArrayNextLoc(&OptAttribs, &Loc)
  938. ) {
  939. Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib);
  940. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  941. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  942. continue; // classname mismatch
  943. }
  944. if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) {
  945. continue; // user class mismatch
  946. }
  947. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  948. if( ClassName ) { // need to have matching class
  949. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  950. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  951. }
  952. if( UserClass ) { // need to 've matchin user class
  953. if( !IS_STRING4_PRESENT(ThisAttrib) ) continue;
  954. if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue;
  955. }
  956. Result = MemArrayDelElement(&OptAttribs, &Loc, &ThisAttrib);
  957. //- ERROR_SUCCESS == Result
  958. MemFreeFunc(ThisAttrib);
  959. break;
  960. }
  961. }
  962. NothingPresent(&DummyAttrib); // prepare an elt to add to list
  963. // STRING1_PRESENT(&DummyAttrib); // No name or comment
  964. // if( Comment ) STRING2_PRESENT(&DummyAttrib);
  965. if( ClassName ) STRING3_PRESENT(&DummyAttrib);// class name?
  966. if( UserClass ) STRING4_PRESENT(&DummyAttrib);// user class?
  967. DWORD1_PRESENT(&DummyAttrib); // this is option id
  968. BINARY1_PRESENT(&DummyAttrib); // value is this
  969. // FLAGS1_PRESENT(&DummyAttrib); // flags are not currently used
  970. Value = NULL;
  971. ValueSize = 0; // dont know the size, find out
  972. Result = DhcpConvertOptionRPCToRegFormat( // first convert to Reg fmt
  973. OptData,
  974. NULL,
  975. &ValueSize
  976. );
  977. if( ERROR_MORE_DATA != Result ) { // oops unexpected turn of evts
  978. Result = ERROR_DDS_UNEXPECTED_ERROR;
  979. goto Cleanup;
  980. }
  981. Value = MemAlloc(ValueSize); // got the size, allocate the mem
  982. if( NULL == Value ) { // this shouldnt happen actually
  983. Result = ERROR_NOT_ENOUGH_MEMORY;
  984. goto Cleanup;
  985. }
  986. Result = DhcpConvertOptionRPCToRegFormat( // now convert to Reg fmt
  987. OptData,
  988. Value,
  989. &ValueSize
  990. );
  991. if( ERROR_SUCCESS != Result ) { // this should not happen either
  992. return ERROR_DDS_UNEXPECTED_ERROR;
  993. }
  994. DummyAttrib.Dword1 = OptId; // option Id
  995. DummyAttrib.String3 = ClassName; // class Name
  996. DummyAttrib.String4 = UserClass; // user class
  997. DummyAttrib.Binary1 = Value;
  998. DummyAttrib.BinLen1 = ValueSize;
  999. Result = MemArrayAddElement(&OptAttribs, &DummyAttrib);
  1000. if( ERROR_SUCCESS != Result ) goto Cleanup; // Add dummy element to list
  1001. Result = DhcpDsSetLists( // set the new list in DS
  1002. /* Reserved */ DDS_RESERVED_DWORD,
  1003. /* hStore */ hObject,
  1004. /* SetParams */ &unused,
  1005. /* Servers */ NULL,
  1006. /* Subnets */ NULL,
  1007. /* IpAddress */ NULL,
  1008. /* Mask */ NULL,
  1009. /* Ranges */ NULL,
  1010. /* Sites */ NULL,
  1011. /* Reservations */ NULL,
  1012. /* SuperScopes */ NULL,
  1013. /* OptionDescripti.. */ NULL,
  1014. /* OptionsLocation */ NULL,
  1015. /* Options */ &OptAttribs,
  1016. /* ClassDescriptio.. */ NULL,
  1017. /* Classes */ NULL
  1018. );
  1019. (void)MemArrayLastLoc(&OptAttribs, &Loc); // clear up list to way it was
  1020. //- ERROR_SUCCESS == Result
  1021. (void)MemArrayDelElement(&OptAttribs, &Loc, &ThisAttrib);
  1022. //- ERROR_SUCCESS == Result && ThisAttrib == &DummyAttrib
  1023. Cleanup: // free up any memory used
  1024. (void)MemArrayFree(&OptAttribs, MemFreeFunc);
  1025. if( Value ) MemFree(Value);
  1026. return Result;
  1027. }
  1028. //BeginExport(function)
  1029. //DOC DhcpDsRemoveOptionValue deletes the required option value from DS
  1030. //DOC the specific option value should exist in DS, else error.
  1031. //DOC Also, this function works assuming that the option has been written
  1032. //DOC to the current object in DS as given by hObject ptr.
  1033. //DOC There are requirements on the fmt used in the DS.
  1034. DWORD
  1035. DhcpDsRemoveOptionValue( // remove option value
  1036. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1037. IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
  1038. IN DWORD Reserved, // must be zero, future use
  1039. IN LPWSTR ClassName, // name of class for this opt
  1040. IN LPWSTR UserClass, // user class for opt
  1041. IN DWORD OptId // option id
  1042. ) //EndExport(function)
  1043. {
  1044. DWORD Result, Result2, unused, ValueSize;
  1045. ARRAY OptAttribs;
  1046. PEATTRIB ThisAttrib;
  1047. ARRAY_LOCATION Loc;
  1048. MemArrayInit(&OptAttribs);
  1049. Result = DhcpDsGetLists( // get list of options frm DS
  1050. /* Reserved */ DDS_RESERVED_DWORD,
  1051. /* hStore */ hObject,
  1052. /* RecursionDepth */ 0xFFFFFFFF,
  1053. /* Servers */ NULL,
  1054. /* Subnets */ NULL,
  1055. /* IpAddress */ NULL,
  1056. /* Mask */ NULL,
  1057. /* Ranges */ NULL,
  1058. /* Sites */ NULL,
  1059. /* Reservations */ NULL,
  1060. /* SuperScopes */ NULL,
  1061. /* OptionDescription */ NULL,
  1062. /* OptionsLocation */ NULL,
  1063. /* Options */ &OptAttribs,
  1064. /* Classes */ NULL
  1065. );
  1066. // if( ERROR_SUCCESS != Result ) return Result;
  1067. for( Result = MemArrayInitLoc(&OptAttribs, &Loc)
  1068. ; ERROR_FILE_NOT_FOUND != Result ; // search for option w/ <OptId>
  1069. Result = MemArrayNextLoc(&OptAttribs, &Loc)
  1070. ) {
  1071. Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib);
  1072. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1073. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  1074. continue; // classname mismatch
  1075. }
  1076. if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) {
  1077. continue; // user class mismatch
  1078. }
  1079. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  1080. if( ClassName ) { // need to have matching class
  1081. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  1082. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  1083. }
  1084. if( UserClass ) { // need to 've matchin user class
  1085. if( !IS_STRING4_PRESENT(ThisAttrib) ) continue;
  1086. if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue;
  1087. }
  1088. Result = ERROR_SUCCESS;
  1089. break;
  1090. }
  1091. }
  1092. if( ERROR_SUCCESS != Result ) { // option was not present in DS
  1093. return ERROR_DDS_OPTION_DOES_NOT_EXIST;
  1094. }
  1095. Result = MemArrayDelElement(&OptAttribs, &Loc, &ThisAttrib);
  1096. //- ERROR_SUCCESS == Result
  1097. MemFreeFunc(ThisAttrib);
  1098. Result = DhcpDsSetLists( // set the new list in DS
  1099. /* Reserved */ DDS_RESERVED_DWORD,
  1100. /* hStore */ hObject,
  1101. /* SetParams */ &unused,
  1102. /* Servers */ NULL,
  1103. /* Subnets */ NULL,
  1104. /* IpAddress */ NULL,
  1105. /* Mask */ NULL,
  1106. /* Ranges */ NULL,
  1107. /* Sites */ NULL,
  1108. /* Reservations */ NULL,
  1109. /* SuperScopes */ NULL,
  1110. /* OptionDescripti.. */ NULL,
  1111. /* OptionsLocation */ NULL,
  1112. /* Options */ &OptAttribs,
  1113. /* ClassDescriptio.. */ NULL,
  1114. /* Classes */ NULL
  1115. );
  1116. (void)MemArrayFree(&OptAttribs, MemFreeFunc);
  1117. return Result;
  1118. }
  1119. //BeginExport(function)
  1120. //DOC DhcpDsGetOptionValue retrieves the particular option value in question.
  1121. //DOC This function returns ERROR_DDS_OPTION_DOES_NOT_EXIST if the option was
  1122. //DOC not found.
  1123. DWORD
  1124. DhcpDsGetOptionValue( // get option value frm DS
  1125. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1126. IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
  1127. IN DWORD Reserved, // must be zero, future use
  1128. IN LPWSTR ClassName, // name of class for this opt
  1129. IN LPWSTR UserClass, // user class this opt belongs 2
  1130. IN DWORD OptId, // option id
  1131. OUT LPDHCP_OPTION_VALUE *OptionValue // allocate and fill this ptr
  1132. ) //EndExport(function)
  1133. {
  1134. DWORD Result, Result2, unused, Size, Size2;
  1135. ARRAY OptAttribs;
  1136. PEATTRIB ThisAttrib;
  1137. ARRAY_LOCATION Loc;
  1138. LPDHCP_OPTION_VALUE LocalOptionValue;
  1139. *OptionValue = NULL;
  1140. LocalOptionValue = NULL;
  1141. MemArrayInit(&OptAttribs);
  1142. Result = DhcpDsGetLists( // get list of options frm DS
  1143. /* Reserved */ DDS_RESERVED_DWORD,
  1144. /* hStore */ hObject,
  1145. /* RecursionDepth */ 0xFFFFFFFF,
  1146. /* Servers */ NULL,
  1147. /* Subnets */ NULL,
  1148. /* IpAddress */ NULL,
  1149. /* Mask */ NULL,
  1150. /* Ranges */ NULL,
  1151. /* Sites */ NULL,
  1152. /* Reservations */ NULL,
  1153. /* SuperScopes */ NULL,
  1154. /* OptionDescription */ NULL,
  1155. /* OptionsLocation */ NULL,
  1156. /* Options */ &OptAttribs,
  1157. /* Classes */ NULL
  1158. );
  1159. // if( ERROR_SUCCESS != Result ) return Result;
  1160. for( Result = MemArrayInitLoc(&OptAttribs, &Loc)
  1161. ; ERROR_FILE_NOT_FOUND != Result ; // search for option w/ <OptId>
  1162. Result = MemArrayNextLoc(&OptAttribs, &Loc)
  1163. ) {
  1164. Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib);
  1165. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1166. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  1167. continue; // classname mismatch
  1168. }
  1169. if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) {
  1170. continue; // user class mismatch
  1171. }
  1172. if( IS_DWORD1_PRESENT(ThisAttrib) && OptId == ThisAttrib->Dword1 ) {
  1173. if( ClassName ) { // need to have matching class
  1174. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  1175. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  1176. }
  1177. if( UserClass ) { // need to 've matchin user class
  1178. if( !IS_STRING4_PRESENT(ThisAttrib) ) continue;
  1179. if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue;
  1180. }
  1181. Result = ERROR_SUCCESS;
  1182. break;
  1183. }
  1184. Result = ERROR_SUCCESS; // perfect match
  1185. break;
  1186. }
  1187. if( ERROR_SUCCESS != Result ) { // option was not present in DS
  1188. return ERROR_DDS_OPTION_DOES_NOT_EXIST;
  1189. }
  1190. Size2 = 0; // calculate the size reqd for mem
  1191. Size = ROUND_UP_COUNT(sizeof(*LocalOptionValue), ALIGN_WORST);
  1192. Result = DhcpConvertOptionRegToRPCFormat2( // convert from RPC to registry fmt
  1193. /* Buffer */ ThisAttrib->Binary1,
  1194. /* BufferSize */ ThisAttrib->BinLen1,
  1195. /* Option */ NULL,
  1196. /* OptBuf */ NULL,
  1197. /* Size */ &Size2 // just calculate the size..
  1198. );
  1199. if( ERROR_MORE_DATA != Result ) { // cant really go wrong
  1200. Result = ERROR_DDS_UNEXPECTED_ERROR;
  1201. goto Cleanup;
  1202. }
  1203. LocalOptionValue = MemAlloc(Size);
  1204. if( NULL == LocalOptionValue ) {
  1205. Result = ERROR_NOT_ENOUGH_MEMORY;
  1206. goto Cleanup;
  1207. }
  1208. LocalOptionValue->OptionID = ConvertOptIdToRPCValue(OptId, TRUE);
  1209. Size2 = Size - ROUND_UP_COUNT(sizeof(*LocalOptionValue), ALIGN_WORST);
  1210. Result = DhcpConvertOptionRegToRPCFormat2( // convert from RPC to registry fmt
  1211. /* Buffer */ ThisAttrib->Binary1,
  1212. /* BufferSize */ ThisAttrib->BinLen1,
  1213. /* Option */ &LocalOptionValue->Value,
  1214. /* OptBuf */ ROUND_UP_COUNT(sizeof(*LocalOptionValue), ALIGN_WORST) + (LPBYTE)LocalOptionValue,
  1215. /* Size */ &Size2 // just calculate the size..
  1216. );
  1217. if( ERROR_SUCCESS != Result ) { // cant really go wrong
  1218. if( ERROR_MORE_DATA == Result ) { // this can cause confusion..
  1219. Result = ERROR_DDS_UNEXPECTED_ERROR;
  1220. }
  1221. goto Cleanup;
  1222. }
  1223. *OptionValue = LocalOptionValue;
  1224. Cleanup:
  1225. if( ERROR_SUCCESS != Result ) {
  1226. if( LocalOptionValue ) MemFreeFunc(LocalOptionValue);
  1227. *OptionValue = NULL;
  1228. }
  1229. (void)MemArrayFree(&OptAttribs, MemFreeFunc);
  1230. return Result;
  1231. }
  1232. //BeginExport(function)
  1233. //DOC DhcpDsEnumOptionValues enumerates the list of options for a given class
  1234. //DOC Also, depending on whether IsVendor is TRUE or false, this function enumerates
  1235. //DOC only vendor specific or only non-vendor-specific options respectively.
  1236. //DOC This function gets the whole bunch in one shot.
  1237. DWORD
  1238. DhcpDsEnumOptionValues( // get option values from DS
  1239. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1240. IN OUT LPSTORE_HANDLE hObject, // handle to object in DS
  1241. IN DWORD Reserved, // must be zero, future use
  1242. IN LPWSTR ClassName, // name of class for this opt
  1243. IN LPWSTR UserClass, // for which user class?
  1244. IN DWORD IsVendor, // enum only vendor/non-vendor?
  1245. OUT LPDHCP_OPTION_VALUE_ARRAY *OptionValues // allocate option values..
  1246. ) //EndExport(function)
  1247. {
  1248. DWORD Result, Result2, unused, Size, Size2, i;
  1249. DWORD AllocSize;
  1250. ARRAY OptAttribs;
  1251. PEATTRIB ThisAttrib;
  1252. ARRAY_LOCATION Loc;
  1253. LPDHCP_OPTION_VALUE_ARRAY LocalOptionValueArray;
  1254. LPBYTE Ptr;
  1255. *OptionValues = NULL;
  1256. LocalOptionValueArray = NULL;
  1257. MemArrayInit(&OptAttribs);
  1258. Result = DhcpDsGetLists( // get list of options frm DS
  1259. /* Reserved */ DDS_RESERVED_DWORD,
  1260. /* hStore */ hObject,
  1261. /* RecursionDepth */ 0xFFFFFFFF,
  1262. /* Servers */ NULL,
  1263. /* Subnets */ NULL,
  1264. /* IpAddress */ NULL,
  1265. /* Mask */ NULL,
  1266. /* Ranges */ NULL,
  1267. /* Sites */ NULL,
  1268. /* Reservations */ NULL,
  1269. /* SuperScopes */ NULL,
  1270. /* OptionDescription */ NULL,
  1271. /* OptionsLocation */ NULL,
  1272. /* Options */ &OptAttribs,
  1273. /* Classes */ NULL
  1274. );
  1275. // if( ERROR_SUCCESS != Result ) return Result;
  1276. Size = i = 0;
  1277. for( Result = MemArrayInitLoc(&OptAttribs, &Loc)
  1278. ; ERROR_FILE_NOT_FOUND != Result ; // go thru each option, calc size
  1279. Result = MemArrayNextLoc(&OptAttribs, &Loc)
  1280. ) {
  1281. Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib);
  1282. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1283. if( !IS_DWORD1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1284. continue; // illegal attrib, or not this opt
  1285. }
  1286. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  1287. continue; // classname mismatch
  1288. }
  1289. if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) {
  1290. continue; // user class mismatch
  1291. }
  1292. if( ClassName ) { // need to have matching class
  1293. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  1294. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  1295. }
  1296. if( UserClass ) { // need to 've matchin user class
  1297. if( !IS_STRING4_PRESENT(ThisAttrib) ) continue;
  1298. if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue;
  1299. }
  1300. Size2 = 0; // calculate the size reqd for mem
  1301. Result2= DhcpConvertOptionRegToRPCFormat2(// convert from RPC to registry fmt
  1302. /* Buffer */ ThisAttrib->Binary1,
  1303. /* BufferSize */ ThisAttrib->BinLen1,
  1304. /* Option */ NULL,
  1305. /* OptBuf */ NULL,
  1306. /* Size */ &Size2 // just calculate the size..
  1307. );
  1308. if( ERROR_MORE_DATA != Result2 ) { // cant really go wrong
  1309. continue; // skip this attrib in this case
  1310. }
  1311. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  1312. i ++;
  1313. }
  1314. Size += ROUND_UP_COUNT( i * sizeof(DHCP_OPTION_VALUE), ALIGN_WORST);
  1315. Size += ROUND_UP_COUNT( sizeof(DHCP_OPTION_VALUE_ARRAY ), ALIGN_WORST);
  1316. Ptr = MemAlloc(AllocSize = Size); LocalOptionValueArray = (LPVOID)Ptr;
  1317. if( NULL == LocalOptionValueArray ) {
  1318. Result = ERROR_NOT_ENOUGH_MEMORY;
  1319. goto Cleanup;
  1320. }
  1321. Ptr += ROUND_UP_COUNT( sizeof(DHCP_OPTION_VALUE_ARRAY ), ALIGN_WORST);
  1322. LocalOptionValueArray->Values = (LPVOID)Ptr;
  1323. Ptr += ROUND_UP_COUNT( i * sizeof(DHCP_OPTION_VALUE), ALIGN_WORST);
  1324. Size = i = 0;
  1325. for( Result = MemArrayInitLoc(&OptAttribs, &Loc)
  1326. ; ERROR_FILE_NOT_FOUND != Result ; // go thru each opt, fill data
  1327. Result = MemArrayNextLoc(&OptAttribs, &Loc)
  1328. ) {
  1329. Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib);
  1330. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1331. if( !IS_DWORD1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1332. continue; // illegal attrib, or not this opt
  1333. }
  1334. if( NULL == ClassName && IS_STRING3_PRESENT(ThisAttrib) ) {
  1335. continue; // classname mismatch
  1336. }
  1337. if( NULL == UserClass && IS_STRING4_PRESENT(ThisAttrib) ) {
  1338. continue; // user class mismatch
  1339. }
  1340. if( ClassName ) { // need to have matching class
  1341. if( !IS_STRING3_PRESENT(ThisAttrib) ) continue;
  1342. if( 0 != wcscmp(ClassName, ThisAttrib->String3) ) continue;
  1343. }
  1344. if( UserClass ) { // need to 've matchin user class
  1345. if( !IS_STRING4_PRESENT(ThisAttrib) ) continue;
  1346. if( 0 != wcscmp(UserClass, ThisAttrib->String4) ) continue;
  1347. }
  1348. Size2 = AllocSize - Size;
  1349. Result2= DhcpConvertOptionRegToRPCFormat2(// convert from RPC to registry fmt
  1350. /* Buffer */ ThisAttrib->Binary1,
  1351. /* BufferSize */ ThisAttrib->BinLen1,
  1352. /* Option */ &LocalOptionValueArray->Values[i].Value,
  1353. /* OptBuf */ Ptr,
  1354. /* Size */ &Size2 // just calculate the size..
  1355. );
  1356. if( ERROR_SUCCESS != Result2 ) { // cant really go wrong
  1357. continue; // skip this attrib in this case
  1358. }
  1359. LocalOptionValueArray->Values[i].OptionID = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE);
  1360. Size += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  1361. Ptr += ROUND_UP_COUNT(Size2, ALIGN_WORST);
  1362. i ++;
  1363. }
  1364. LocalOptionValueArray->NumElements = i;
  1365. *OptionValues = LocalOptionValueArray;
  1366. Cleanup:
  1367. if( ERROR_SUCCESS != Result ) {
  1368. if( LocalOptionValueArray ) MemFreeFunc(LocalOptionValueArray);
  1369. *OptionValues = NULL;
  1370. }
  1371. (void)MemArrayFree(&OptAttribs, MemFreeFunc);
  1372. return Result;
  1373. }
  1374. //BeginExport(function)
  1375. //DOC DhcpDsCreateClass creates a given class in the DS. The class should not
  1376. //DOC exist prior to this in the DS (if it does, this fn returns error
  1377. //DOC ERROR_DDS_CLASS_EXISTS).
  1378. DWORD
  1379. DhcpDsCreateClass( // create this class in the ds
  1380. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1381. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  1382. IN DWORD Reserved, // must be zero, future use
  1383. IN LPWSTR ClassName, // name of class..
  1384. IN LPWSTR ClassComment, // comment for this class
  1385. IN LPBYTE ClassData, // the bytes that form the class data
  1386. IN DWORD ClassDataLen, // # of bytes of above
  1387. IN BOOL IsVendor // is this a vendor class?
  1388. ) //EndExport(function)
  1389. {
  1390. DWORD Result, Result2, unused;
  1391. ARRAY ClassAttribs;
  1392. ARRAY_LOCATION Loc;
  1393. PEATTRIB ThisAttrib;
  1394. EATTRIB DummyAttrib;
  1395. if( NULL == ClassName || NULL == ClassData || 0 == ClassDataLen )
  1396. return ERROR_INVALID_PARAMETER;
  1397. MemArrayInit(&ClassAttribs);
  1398. Result = DhcpDsGetLists( // get list of options frm DS
  1399. /* Reserved */ DDS_RESERVED_DWORD,
  1400. /* hStore */ hServer,
  1401. /* RecursionDepth */ 0xFFFFFFFF,
  1402. /* Servers */ NULL,
  1403. /* Subnets */ NULL,
  1404. /* IpAddress */ NULL,
  1405. /* Mask */ NULL,
  1406. /* Ranges */ NULL,
  1407. /* Sites */ NULL,
  1408. /* Reservations */ NULL,
  1409. /* SuperScopes */ NULL,
  1410. /* OptionDescription */ NULL,
  1411. /* OptionsLocation */ NULL,
  1412. /* Options */ NULL,
  1413. /* Classes */ &ClassAttribs
  1414. );
  1415. // if( ERROR_SUCCESS != Result ) return Result;
  1416. Result = MemArrayInitLoc(&ClassAttribs, &Loc);
  1417. while( ERROR_FILE_NOT_FOUND != Result ) { // search for existing class
  1418. Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib);
  1419. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1420. Result = MemArrayNextLoc(&ClassAttribs, &Loc);
  1421. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1422. continue; // invalid attrib for a class
  1423. }
  1424. if( 0 == wcscmp(ClassName, ThisAttrib->String1) ) {
  1425. Result = ERROR_DDS_CLASS_EXISTS; // gotcha! same name
  1426. goto Cleanup;
  1427. }
  1428. }
  1429. NothingPresent(&DummyAttrib); // create an attrib for the class
  1430. STRING1_PRESENT(&DummyAttrib); // class name
  1431. if( ClassComment ) {
  1432. STRING2_PRESENT(&DummyAttrib); // class comment
  1433. }
  1434. BINARY1_PRESENT(&DummyAttrib); // class data
  1435. FLAGS1_PRESENT(&DummyAttrib); // vendorclass etc information
  1436. DummyAttrib.String1 = ClassName; // now fill in the actual values
  1437. DummyAttrib.String2 = ClassComment;
  1438. DummyAttrib.Binary1 = ClassData;
  1439. DummyAttrib.BinLen1 = ClassDataLen;
  1440. DummyAttrib.Flags1 = IsVendor;
  1441. Result = MemArrayAddElement(&ClassAttribs, &DummyAttrib);
  1442. if( ERROR_SUCCESS != Result ) { // could not add an elt? uh uh.
  1443. goto Cleanup;
  1444. }
  1445. Result = DhcpDsSetLists( // write back the modified list
  1446. /* Reserved */ DDS_RESERVED_DWORD,
  1447. /* hStore */ hServer,
  1448. /* SetParams */ &unused,
  1449. /* Servers */ NULL,
  1450. /* Subnets */ NULL,
  1451. /* IpAddress */ NULL,
  1452. /* Mask */ NULL,
  1453. /* Ranges */ NULL,
  1454. /* Sites */ NULL,
  1455. /* Reservations */ NULL,
  1456. /* SuperScopes */ NULL,
  1457. /* OptionDescripti.. */ NULL,
  1458. /* OptionsLocation */ NULL,
  1459. /* Options */ NULL,
  1460. /* ClassDescriptio.. */ NULL,
  1461. /* Classes */ &ClassAttribs
  1462. );
  1463. // now try to remove the dummy element that was added..
  1464. Result2 = MemArrayLastLoc(&ClassAttribs, &Loc);
  1465. //- ERROR_SUCCESS == Result2
  1466. Result2 = MemArrayDelElement(&ClassAttribs, &Loc, &ThisAttrib);
  1467. //- ERROR_SUCCESS == Result2 && ThisAttrib == &DummyAttrib
  1468. Cleanup:
  1469. (void) MemArrayFree(&ClassAttribs, MemFreeFunc);
  1470. return Result;
  1471. }
  1472. //BeginExport(function)
  1473. //DOC DhcpDsDeleteClass deletes the class from off the DS, and returns an error
  1474. //DOC if the class did not exist in the DS for hte given server object.
  1475. DWORD
  1476. DhcpDsDeleteClass( // delete the class from the ds
  1477. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1478. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  1479. IN DWORD Reserved, // must be zero, future use
  1480. IN LPWSTR ClassName // name of class..
  1481. ) //EndExport(function)
  1482. {
  1483. DWORD Result, Result2, unused;
  1484. ARRAY ClassAttribs;
  1485. ARRAY_LOCATION Loc;
  1486. PEATTRIB ThisAttrib;
  1487. EATTRIB DummyAttrib;
  1488. if( NULL == ClassName ) return ERROR_INVALID_PARAMETER;
  1489. MemArrayInit(&ClassAttribs);
  1490. Result = DhcpDsGetLists( // get list of options frm DS
  1491. /* Reserved */ DDS_RESERVED_DWORD,
  1492. /* hStore */ hServer,
  1493. /* RecursionDepth */ 0xFFFFFFFF,
  1494. /* Servers */ NULL,
  1495. /* Subnets */ NULL,
  1496. /* IpAddress */ NULL,
  1497. /* Mask */ NULL,
  1498. /* Ranges */ NULL,
  1499. /* Sites */ NULL,
  1500. /* Reservations */ NULL,
  1501. /* SuperScopes */ NULL,
  1502. /* OptionDescription */ NULL,
  1503. /* OptionsLocation */ NULL,
  1504. /* Options */ NULL,
  1505. /* Classes */ &ClassAttribs
  1506. );
  1507. // if( ERROR_SUCCESS != Result ) return Result;
  1508. for( Result = MemArrayInitLoc(&ClassAttribs, &Loc)
  1509. ; ERROR_FILE_NOT_FOUND != Result ; // search for existing class
  1510. Result = MemArrayNextLoc(&ClassAttribs, &Loc)
  1511. ) {
  1512. Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib);
  1513. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1514. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1515. continue; // invalid attrib for a class
  1516. }
  1517. if( 0 == wcscmp(ClassName, ThisAttrib->String1) ) {
  1518. Result = ERROR_SUCCESS; // gotcha! same name
  1519. break;
  1520. }
  1521. }
  1522. if( ERROR_SUCCESS != Result ) {
  1523. Result = ERROR_DDS_CLASS_DOES_NOT_EXIST;
  1524. goto Cleanup;
  1525. }
  1526. Result = MemArrayDelElement(&ClassAttribs, &Loc, &ThisAttrib);
  1527. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1528. MemFreeFunc(ThisAttrib);
  1529. Result = DhcpDsSetLists( // write back the modified list
  1530. /* Reserved */ DDS_RESERVED_DWORD,
  1531. /* hStore */ hServer,
  1532. /* SetParams */ &unused,
  1533. /* Servers */ NULL,
  1534. /* Subnets */ NULL,
  1535. /* IpAddress */ NULL,
  1536. /* Mask */ NULL,
  1537. /* Ranges */ NULL,
  1538. /* Sites */ NULL,
  1539. /* Reservations */ NULL,
  1540. /* SuperScopes */ NULL,
  1541. /* OptionDescripti.. */ NULL,
  1542. /* OptionsLocation */ NULL,
  1543. /* Options */ NULL,
  1544. /* ClassDescriptio.. */ NULL,
  1545. /* Classes */ &ClassAttribs
  1546. );
  1547. Cleanup:
  1548. (void) MemArrayFree(&ClassAttribs, MemFreeFunc);
  1549. return Result;
  1550. }
  1551. //BeginExport(function)
  1552. //DOC this is not yet implemented.
  1553. DWORD
  1554. DhcpDsModifyClass( // modify a class in the DS
  1555. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1556. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  1557. IN DWORD Reserved, // must be zero, future use
  1558. IN LPWSTR ClassName, // name of class -- this is the key
  1559. IN LPWSTR ClassComment, // comment for this class
  1560. IN LPBYTE ClassData, // the bytes that form the class data
  1561. IN DWORD ClassDataLen // # of bytes of above
  1562. ) //EndExport(function)
  1563. {
  1564. return ERROR_CALL_NOT_IMPLEMENTED;
  1565. }
  1566. //BeginExport(function)
  1567. //DOC DhcpDsGetClassInfo get information on a class by doing a search based
  1568. //DOC on either the class name or the class data fields. ClassName is guaranteed
  1569. //DOC to be unique. ClassData may/maynot be unique. The search is done in the DS,
  1570. //DOC so things are likely to be a lot slower than they should be.
  1571. //DOC This should be fixed by doing some intelligent searches.
  1572. //DOC Note that the hServer and the hDhcpC handles should point to the right objects.
  1573. //DOC
  1574. DWORD
  1575. DhcpDsGetClassInfo( // get class details for given class
  1576. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1577. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  1578. IN DWORD Reserved, // must be zero, future use
  1579. IN LPWSTR ClassName, // OPTIONAL search on class name
  1580. IN LPBYTE ClassData, // OPTIONAL srch on class data
  1581. IN DWORD ClassDataLen, // # of bytes of ClassData
  1582. OUT LPDHCP_CLASS_INFO *ClassInfo // allocate and copy ptr
  1583. ) //EndExport(function)
  1584. {
  1585. DWORD Result, Result2, Size;
  1586. DWORD IsVendor, Flags;
  1587. ARRAY ClassAttribs;
  1588. ARRAY_LOCATION Loc;
  1589. PEATTRIB ThisAttrib;
  1590. EATTRIB DummyAttrib;
  1591. LPDHCP_CLASS_INFO LocalClassInfo;
  1592. LPBYTE Ptr;
  1593. LPWSTR ClassComment;
  1594. if( NULL == ClassName || NULL == ClassData || 0 == ClassDataLen )
  1595. return ERROR_INVALID_PARAMETER;
  1596. LocalClassInfo = *ClassInfo = NULL;
  1597. MemArrayInit(&ClassAttribs);
  1598. Result = DhcpDsGetLists( // get list of options frm DS
  1599. /* Reserved */ DDS_RESERVED_DWORD,
  1600. /* hStore */ hServer,
  1601. /* RecursionDepth */ 0xFFFFFFFF,
  1602. /* Servers */ NULL,
  1603. /* Subnets */ NULL,
  1604. /* IpAddress */ NULL,
  1605. /* Mask */ NULL,
  1606. /* Ranges */ NULL,
  1607. /* Sites */ NULL,
  1608. /* Reservations */ NULL,
  1609. /* SuperScopes */ NULL,
  1610. /* OptionDescription */ NULL,
  1611. /* OptionsLocation */ NULL,
  1612. /* Options */ NULL,
  1613. /* Classes */ &ClassAttribs
  1614. );
  1615. // if( ERROR_SUCCESS != Result ) return Result;
  1616. Result = MemArrayInitLoc(&ClassAttribs, &Loc);
  1617. while( ERROR_FILE_NOT_FOUND != Result ) { // search for existing class
  1618. Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib);
  1619. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1620. Result = MemArrayNextLoc(&ClassAttribs, &Loc);
  1621. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1622. continue; // invalid attrib for a class
  1623. }
  1624. if( 0 == ThisAttrib->BinLen1 ) { // invalid attrib for this class
  1625. continue;
  1626. }
  1627. if( ClassName ) { // if srching on ClassName field
  1628. if( 0 == wcscmp(ClassName, ThisAttrib->String1) ) {
  1629. Result = ERROR_SUCCESS; // gotcha! same name
  1630. break;
  1631. }
  1632. } else { // srching on ClassData field
  1633. if( ClassDataLen != ThisAttrib->BinLen1 )
  1634. continue; // nope mismatch
  1635. if( 0 == memcpy(ClassData, ThisAttrib->Binary1, ClassDataLen) ) {
  1636. Result = ERROR_SUCCESS; // gotcha! matching bits
  1637. break;
  1638. }
  1639. }
  1640. }
  1641. if( ERROR_SUCCESS != Result ) { // did not find the class
  1642. Result = ERROR_DDS_CLASS_DOES_NOT_EXIST;
  1643. goto Cleanup;
  1644. }
  1645. ClassName = ThisAttrib->String1;
  1646. if( IS_STRING2_PRESENT(ThisAttrib) ) {
  1647. ClassComment = ThisAttrib->String2;
  1648. } else {
  1649. ClassComment = NULL;
  1650. }
  1651. ClassData = ThisAttrib->Binary1;
  1652. ClassDataLen = ThisAttrib->BinLen1;
  1653. if( IS_FLAGS1_PRESENT(ThisAttrib) ) {
  1654. IsVendor = ThisAttrib->Flags1;
  1655. } else IsVendor = 0;
  1656. if( IS_FLAGS2_PRESENT(ThisAttrib) ) {
  1657. Flags = ThisAttrib->Flags2;
  1658. } else Flags = 0;
  1659. Size = 0; // calculate size reqd
  1660. Size = ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO),ALIGN_WORST);
  1661. Size += sizeof(WCHAR)*(wcslen(ClassName)+1); // alloc space for name
  1662. if( ClassComment ) { // alloc space for comment
  1663. Size += sizeof(WCHAR)*(wcslen(ClassComment) +1);
  1664. }
  1665. Size += ThisAttrib->BinLen1; // alloc space for data
  1666. Ptr = MemAlloc(Size); // allocate memory
  1667. LocalClassInfo = (LPVOID)Ptr;
  1668. if( NULL == LocalClassInfo ) {
  1669. Result = ERROR_NOT_ENOUGH_MEMORY;
  1670. goto Cleanup;
  1671. }
  1672. Size = 0; // copy the stuff in
  1673. Size = ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO),ALIGN_WORST);
  1674. LocalClassInfo->ClassName = (LPVOID)(Size + Ptr);
  1675. wcscpy(LocalClassInfo->ClassName, ClassName);
  1676. Size += sizeof(WCHAR)*(wcslen(ClassName)+1);
  1677. if( NULL == ClassComment ) {
  1678. LocalClassInfo->ClassComment = NULL;
  1679. } else {
  1680. LocalClassInfo->ClassComment = (LPVOID)(Size + Ptr);
  1681. wcscpy(LocalClassInfo->ClassComment, ThisAttrib->String2 );
  1682. Size += sizeof(WCHAR)*(wcslen(ThisAttrib->String2) +1);
  1683. }
  1684. LocalClassInfo->ClassDataLength = ThisAttrib->BinLen1;
  1685. LocalClassInfo->ClassData = Size+Ptr;
  1686. memcpy(LocalClassInfo->ClassData, ThisAttrib->Binary1, ThisAttrib->BinLen1);
  1687. LocalClassInfo->IsVendor = IsVendor;
  1688. LocalClassInfo->Flags = Flags;
  1689. *ClassInfo = LocalClassInfo;
  1690. Result = ERROR_SUCCESS;
  1691. Cleanup:
  1692. (void) MemArrayFree(&ClassAttribs, MemFreeFunc);
  1693. return Result;
  1694. }
  1695. //BeginExport(function)
  1696. //DOC DhcpDsEnumClasses enumerates the classes for a given server (as specified
  1697. //DOC via the hServer object.)
  1698. //DOC The memory for Classes is allocated by this function.
  1699. DWORD
  1700. DhcpDsEnumClasses( // get the list of classes frm ds
  1701. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1702. IN OUT LPSTORE_HANDLE hServer, // handle to server object in DS
  1703. IN DWORD Reserved, // must be zero, future use
  1704. OUT LPDHCP_CLASS_INFO_ARRAY *Classes // allocate memory for this
  1705. ) //EndExport(function)
  1706. {
  1707. DWORD Result, Result2, Size, Size2, i;
  1708. DWORD ClassDataLen, IsVendor, Flags;
  1709. ARRAY ClassAttribs;
  1710. ARRAY_LOCATION Loc;
  1711. PEATTRIB ThisAttrib;
  1712. EATTRIB DummyAttrib;
  1713. LPDHCP_CLASS_INFO_ARRAY LocalClassInfoArray;
  1714. LPBYTE Ptr, ClassData;
  1715. LPWSTR ClassName, ClassComment;
  1716. LocalClassInfoArray = *Classes = NULL;
  1717. MemArrayInit(&ClassAttribs);
  1718. Result = DhcpDsGetLists( // get list of options frm DS
  1719. /* Reserved */ DDS_RESERVED_DWORD,
  1720. /* hStore */ hServer,
  1721. /* RecursionDepth */ 0xFFFFFFFF,
  1722. /* Servers */ NULL,
  1723. /* Subnets */ NULL,
  1724. /* IpAddress */ NULL,
  1725. /* Mask */ NULL,
  1726. /* Ranges */ NULL,
  1727. /* Sites */ NULL,
  1728. /* Reservations */ NULL,
  1729. /* SuperScopes */ NULL,
  1730. /* OptionDescription */ NULL,
  1731. /* OptionsLocation */ NULL,
  1732. /* Options */ NULL,
  1733. /* Classes */ &ClassAttribs
  1734. );
  1735. // if( ERROR_SUCCESS != Result ) return Result;
  1736. Result = MemArrayInitLoc(&ClassAttribs, &Loc);
  1737. for(Size = i = 0 // search for existing classes
  1738. ; ERROR_FILE_NOT_FOUND != Result;
  1739. Result = MemArrayNextLoc(&ClassAttribs, &Loc)
  1740. ) {
  1741. Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib);
  1742. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1743. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1744. continue; // invalid attrib for a class
  1745. }
  1746. if( 0 == ThisAttrib->BinLen1 ) { // invalid attrib for this class
  1747. continue;
  1748. }
  1749. ClassName = ThisAttrib->String1;
  1750. if( IS_STRING2_PRESENT(ThisAttrib) ) {
  1751. ClassComment = ThisAttrib->String2;
  1752. } else {
  1753. ClassComment = NULL;
  1754. }
  1755. ClassData = ThisAttrib->Binary1;
  1756. ClassDataLen = ThisAttrib->BinLen1;
  1757. Size += sizeof(WCHAR)*(wcslen(ClassName)+1);
  1758. if( ClassComment ) { // alloc space for comment
  1759. Size += sizeof(WCHAR)*(wcslen(ClassComment) +1);
  1760. }
  1761. Size += ROUND_UP_COUNT(ClassDataLen,ALIGN_WORST);
  1762. i ++;
  1763. }
  1764. Size += ROUND_UP_COUNT(i*sizeof(DHCP_CLASS_INFO), ALIGN_WORST);
  1765. Size += ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO_ARRAY), ALIGN_WORST);
  1766. Ptr = MemAlloc(Size); // allocate memory
  1767. LocalClassInfoArray = (LPVOID)Ptr;
  1768. if( NULL == LocalClassInfoArray ) {
  1769. Result = ERROR_NOT_ENOUGH_MEMORY;
  1770. goto Cleanup;
  1771. }
  1772. Size = 0; // copy the stuff in
  1773. LocalClassInfoArray->NumElements = i;
  1774. Size += ROUND_UP_COUNT(sizeof(DHCP_CLASS_INFO_ARRAY), ALIGN_WORST);
  1775. LocalClassInfoArray->Classes = (LPVOID) (Size + Ptr);
  1776. Size += ROUND_UP_COUNT(i*sizeof(DHCP_CLASS_INFO), ALIGN_WORST);
  1777. Result = MemArrayInitLoc(&ClassAttribs, &Loc);
  1778. for(i = 0 // fill in the array with details
  1779. ; ERROR_FILE_NOT_FOUND != Result;
  1780. Result = MemArrayNextLoc(&ClassAttribs, &Loc)
  1781. ) {
  1782. Result = MemArrayGetElement(&ClassAttribs, &Loc, &ThisAttrib);
  1783. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  1784. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  1785. continue; // invalid attrib for a class
  1786. }
  1787. if( 0 == ThisAttrib->BinLen1 ) { // invalid attrib for this class
  1788. continue;
  1789. }
  1790. ClassName = ThisAttrib->String1;
  1791. if( IS_STRING2_PRESENT(ThisAttrib) ) {
  1792. ClassComment = ThisAttrib->String2;
  1793. } else {
  1794. ClassComment = NULL;
  1795. }
  1796. ClassData = ThisAttrib->Binary1;
  1797. ClassDataLen = ThisAttrib->BinLen1;
  1798. LocalClassInfoArray->Classes[i].ClassName = (LPVOID)(Size + Ptr);
  1799. wcscpy(LocalClassInfoArray->Classes[i].ClassName, ClassName);
  1800. Size += sizeof(WCHAR)*(wcslen(ClassName)+1);
  1801. if( NULL == ClassComment ) {
  1802. LocalClassInfoArray->Classes[i].ClassComment = NULL;
  1803. } else {
  1804. LocalClassInfoArray->Classes[i].ClassComment = (LPVOID)(Size + Ptr);
  1805. wcscpy(LocalClassInfoArray->Classes[i].ClassComment, ThisAttrib->String2 );
  1806. Size += sizeof(WCHAR)*(wcslen(ClassComment) +1);
  1807. }
  1808. LocalClassInfoArray->Classes[i].ClassDataLength = ClassDataLen;
  1809. LocalClassInfoArray->Classes[i].ClassData = Size+Ptr;
  1810. memcpy(LocalClassInfoArray->Classes[i].ClassData, ClassData,ClassDataLen);
  1811. Size += ROUND_UP_COUNT(ClassDataLen,ALIGN_WORST);
  1812. if( IS_FLAGS1_PRESENT(ThisAttrib) ) {
  1813. IsVendor = ThisAttrib->Flags1;
  1814. } else IsVendor = 0;
  1815. if( IS_FLAGS2_PRESENT(ThisAttrib) ) {
  1816. Flags = ThisAttrib->Flags2;
  1817. } else Flags = 0;
  1818. LocalClassInfoArray->Classes[i].IsVendor = IsVendor;
  1819. LocalClassInfoArray->Classes[i].Flags = Flags;
  1820. i ++;
  1821. }
  1822. *Classes = LocalClassInfoArray;
  1823. Result = ERROR_SUCCESS;
  1824. Cleanup:
  1825. (void) MemArrayFree(&ClassAttribs, MemFreeFunc);
  1826. return Result;
  1827. }
  1828. //================================================================================
  1829. // get all optinos and get all option values code
  1830. //================================================================================
  1831. BOOL
  1832. TripletNewlyAdded( // check to see if triplet is old or new
  1833. IN PARRAY UClasses, // array of strings
  1834. IN PARRAY VClasses, // array of strings again
  1835. IN PARRAY IsVendorVals, // this is an array of booleans..
  1836. IN LPWSTR UClass, // user class
  1837. IN LPWSTR VClass, // venodr class
  1838. IN ULONG IsVendor // is this vendor or not?
  1839. )
  1840. {
  1841. ARRAY_LOCATION Loc1, Loc2, Loc3;
  1842. DWORD Result, Size, ThisIsVendor;
  1843. LPWSTR ThisUClass, ThisVClass;
  1844. Result = MemArrayInitLoc(UClasses, &Loc1);
  1845. Result = MemArrayInitLoc(VClasses, &Loc2);
  1846. Result = MemArrayInitLoc(IsVendorVals, &Loc3);
  1847. for(
  1848. ; ERROR_FILE_NOT_FOUND != Result ;
  1849. Result = MemArrayNextLoc(UClasses, &Loc1),
  1850. Result = MemArrayNextLoc(VClasses, &Loc2),
  1851. Result = MemArrayNextLoc(IsVendorVals, &Loc3)
  1852. ) {
  1853. MemArrayGetElement(UClasses, &Loc1, &ThisUClass);
  1854. MemArrayGetElement(VClasses, &Loc2, &ThisVClass);
  1855. MemArrayGetElement(IsVendorVals, &Loc3, (LPVOID *)&ThisIsVendor);
  1856. if( ThisIsVendor != IsVendor ) continue;
  1857. if( NULL == ThisUClass && NULL != UClass ||
  1858. NULL == UClass && NULL != ThisUClass ) continue;
  1859. if( NULL != ThisUClass && 0 != wcscmp(ThisUClass, UClass) ) continue;
  1860. if( NULL == ThisVClass && NULL != VClass ||
  1861. NULL == VClass && NULL != ThisVClass ) continue;
  1862. if( NULL != ThisVClass && 0 != wcscmp(ThisVClass, VClass) ) continue;
  1863. return FALSE; // triplet already found!
  1864. }
  1865. // New triplet try to add..
  1866. Result = MemArrayAddElement(IsVendorVals, ULongToPtr(IsVendor));
  1867. if( ERROR_SUCCESS != Result ) return FALSE;
  1868. Result = MemArrayAddElement(VClasses, VClass);
  1869. if( ERROR_SUCCESS != Result ) return FALSE;
  1870. Result = MemArrayAddElement(UClasses, UClass);
  1871. if ( ERROR_SUCCESS != Result ) return FALSE;
  1872. return TRUE;
  1873. }
  1874. DWORD
  1875. ClassifyAndAddOptionValues( // find if this combo is alreayd there?
  1876. IN PEATTRIB ThisAttrib, // attribute to process
  1877. IN PARRAY UClasses, // array of user class strings +
  1878. IN PARRAY VClasses, // array of vernor class strings +
  1879. IN PARRAY IsVendorVals, // array of isvendor values
  1880. IN OUT PULONG StringSpace, // amout of space reqd to store strings
  1881. IN OUT PULONG BinSpace, // amount of space required to store bins..
  1882. IN OUT PULONG OptionCount // # of option values in all.
  1883. )
  1884. {
  1885. ULONG Err, Size;
  1886. LPWSTR UClass, VClass;
  1887. ULONG IsVendor;
  1888. UClass = IS_STRING4_PRESENT(ThisAttrib)? ThisAttrib->String4 : NULL;
  1889. VClass = IS_STRING3_PRESENT(ThisAttrib)? ThisAttrib->String3 : NULL;
  1890. IsVendor = CheckForVendor(ThisAttrib->Dword1, TRUE);
  1891. if( TripletNewlyAdded(UClasses, VClasses, IsVendorVals, UClass, VClass, IsVendor) ) {
  1892. // this triplet was not present before but was just added... need to make space..
  1893. if( UClass ) (*StringSpace) += 1 + wcslen(UClass);
  1894. if( VClass ) (*StringSpace) += 1 + wcslen(VClass);
  1895. }
  1896. Size = 0;
  1897. Err = DhcpConvertOptionRegToRPCFormat2(
  1898. /* Buffer */ ThisAttrib->Binary1,
  1899. /* BufferSize */ ThisAttrib->BinLen1,
  1900. /* Option */ NULL,
  1901. /* OptBuf */ NULL,
  1902. /* Size */ &Size // just calculate the size..
  1903. );
  1904. if( ERROR_MORE_DATA != Err && ERROR_SUCCESS != Err ) {
  1905. return Err; // oops strange error..
  1906. }
  1907. (*BinSpace) += Size; // ok additional binary space is this..
  1908. (*OptionCount) ++; // one more option..
  1909. return ERROR_SUCCESS;
  1910. }
  1911. DWORD
  1912. CalculateOptionValuesSize( // amount of space required for storing...
  1913. IN ULONG nElements, // # of triples of <classid/vendorid/isvendor>
  1914. IN ULONG StringSpace, // # of WCHARs of strings requried
  1915. IN ULONG BinSpace, // # of bytes of space requried for storage of bin..
  1916. IN ULONG OptCount // total # of options values
  1917. )
  1918. {
  1919. ULONG Size; // return value.
  1920. DHCP_ALL_OPTION_VALUES AllValues;
  1921. // basic strucutre
  1922. Size = ROUND_UP_COUNT(sizeof(AllValues), ALIGN_WORST);
  1923. // array of triplets
  1924. Size += nElements * ( sizeof(*(AllValues.Options)) );
  1925. Size = ROUND_UP_COUNT( Size, ALIGN_WORST);
  1926. // each triplet also has an array in it.. the basic struc..
  1927. Size += nElements * ( sizeof(*(AllValues.Options->OptionsArray)) );
  1928. Size = ROUND_UP_COUNT( Size, ALIGN_WORST);
  1929. // now comes the arrays of options actually
  1930. Size += OptCount * sizeof(DHCP_OPTION_VALUE);
  1931. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  1932. // now the space to store the strings..
  1933. Size += sizeof(WCHAR)*StringSpace;
  1934. // now to store the binaries..
  1935. Size += BinSpace;
  1936. return Size;
  1937. }
  1938. DWORD
  1939. AddSpecificOptionValues( // for this triple, add all options to array
  1940. IN OUT LPDHCP_OPTION_VALUE_ARRAY Values, // array to fill
  1941. IN LPWSTR UClass, // the user class of this set of values
  1942. IN LPWSTR VClass, // the vendor class of this set of values
  1943. IN ULONG IsVendor, // is it vendor or not?
  1944. IN PARRAY InputValues, // array of PEATTRIB types from DS
  1945. IN OUT LPDHCP_OPTION_VALUE *OptionValues, // use this for space and update it..
  1946. IN OUT LPBYTE *Ptr // use this for binary space and update it..
  1947. )
  1948. {
  1949. ARRAY_LOCATION Loc;
  1950. PEATTRIB ThisAttrib;
  1951. DWORD Result, Size, ThisIsVendor;
  1952. LPWSTR ThisUClass, ThisVClass;
  1953. Values->NumElements = 0;
  1954. Values->Values = (*OptionValues);
  1955. for( Result = MemArrayInitLoc(InputValues, &Loc)
  1956. ; ERROR_FILE_NOT_FOUND != Result ;
  1957. Result = MemArrayNextLoc(InputValues, &Loc)
  1958. ) {
  1959. MemArrayGetElement(InputValues, &Loc, &ThisAttrib);
  1960. ThisUClass = IS_STRING4_PRESENT(ThisAttrib)? ThisAttrib->String4 : NULL;
  1961. ThisVClass = IS_STRING3_PRESENT(ThisAttrib)? ThisAttrib->String3 : NULL;
  1962. ThisIsVendor = CheckForVendor(ThisAttrib->Dword1, TRUE);
  1963. if( ThisIsVendor != IsVendor ) continue;
  1964. if( NULL == ThisUClass && NULL != UClass ||
  1965. NULL == UClass && NULL != ThisUClass ) continue;
  1966. if( NULL != ThisUClass && 0 != wcscmp(ThisUClass, UClass) ) continue;
  1967. if( NULL == ThisVClass && NULL != VClass ||
  1968. NULL == VClass && NULL != ThisVClass ) continue;
  1969. if( NULL != ThisVClass && 0 != wcscmp(ThisVClass, VClass) ) continue;
  1970. // matched.. increase count.. convert option.. move pointers..
  1971. Values->NumElements ++;
  1972. (*OptionValues)->OptionID = ThisAttrib->Dword1;
  1973. Size = 0xFFFFFFFF; // dont know size but definitely enough
  1974. Result = DhcpConvertOptionRegToRPCFormat2(
  1975. /* Buffer */ ThisAttrib->Binary1,
  1976. /* BufferSize */ ThisAttrib->BinLen1,
  1977. /* Option */ &(*OptionValues)->Value,
  1978. /* OptBuf */ (*Ptr),
  1979. /* Size */ &Size // just calculate the size..
  1980. );
  1981. if( ERROR_MORE_DATA != Result && ERROR_SUCCESS != Result ) {
  1982. return Result; // oops strange error..
  1983. }
  1984. (*OptionValues) ++;
  1985. (*Ptr) += Size;
  1986. }
  1987. return ERROR_SUCCESS;
  1988. }
  1989. DWORD
  1990. FillOptionValues( // fill optiosn according to pattern laid out above..
  1991. IN PARRAY Options, // teh options to fill
  1992. IN PARRAY UClasses, // the user classes
  1993. IN PARRAY VClasses, // the vendor classes
  1994. IN PARRAY IsVendorVals, // Isvenodr values
  1995. IN ULONG StringSpace, // how much space for strings?
  1996. IN ULONG BinSpace, // how much space for bins?
  1997. IN ULONG OptCount, // total # of options
  1998. OUT LPDHCP_ALL_OPTION_VALUES Values // fill this out and returns
  1999. )
  2000. {
  2001. DHCP_ALL_OPTION_VALUES AllValues;
  2002. ULONG Result, nElements, Size;
  2003. LPBYTE Ptr = (LPBYTE)Values;
  2004. LPWSTR Strings;
  2005. LPDHCP_OPTION_VALUE OptionValuesArray;
  2006. int i;
  2007. ARRAY_LOCATION Loc1, Loc2, Loc3;
  2008. LPVOID ThisElt;
  2009. // basic strucutre
  2010. Size = ROUND_UP_COUNT(sizeof(AllValues), ALIGN_WORST);
  2011. Ptr = Size + (LPBYTE)Values;
  2012. Values->NumElements = nElements = MemArraySize(UClasses);
  2013. Values->Flags = 0;
  2014. Values->Options = (LPVOID)Ptr;
  2015. // array of triplets
  2016. Size += nElements * ( sizeof(*(AllValues.Options)) );
  2017. Size = ROUND_UP_COUNT( Size, ALIGN_WORST);
  2018. Ptr = Size + (LPBYTE)Values;
  2019. // each triplet also has an array in it.. the basic struc..
  2020. for( i = 0; i < (int)nElements; i ++ ) {
  2021. Values->Options[i].OptionsArray = (LPVOID)Ptr;
  2022. Ptr += sizeof(*(AllValues.Options->OptionsArray));
  2023. }
  2024. Size += nElements * ( sizeof(*(AllValues.Options->OptionsArray)) );
  2025. Size = ROUND_UP_COUNT( Size, ALIGN_WORST);
  2026. Ptr = Size + (LPBYTE)Values;
  2027. // now comes the arrays of options actually
  2028. OptionValuesArray = (LPVOID) Ptr;
  2029. Size += OptCount * sizeof(DHCP_OPTION_VALUE);
  2030. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2031. Ptr = Size + (LPBYTE)Values;
  2032. // now the space to store the strings..
  2033. Strings = (LPWSTR)Ptr;
  2034. Size += sizeof(WCHAR)*StringSpace;
  2035. // now to store the binaries..
  2036. Ptr = Size + (LPBYTE)Values;
  2037. Size += BinSpace;
  2038. // now do the filling in earnestly.
  2039. MemArrayInitLoc(UClasses, &Loc1);
  2040. MemArrayInitLoc(VClasses, &Loc2);
  2041. MemArrayInitLoc(IsVendorVals, &Loc3);
  2042. for( i = 0; i < (int)nElements ; i ++ ) {
  2043. LPWSTR UClass, VClass;
  2044. ULONG IsVendor;
  2045. MemArrayGetElement(UClasses, &Loc1, &UClass);
  2046. MemArrayGetElement(VClasses, &Loc2, &VClass);
  2047. MemArrayGetElement(IsVendorVals, &Loc3, (LPVOID *)&IsVendor);
  2048. MemArrayNextLoc(UClasses, &Loc1);
  2049. MemArrayNextLoc(VClasses, &Loc2);
  2050. MemArrayNextLoc(IsVendorVals, &Loc3);
  2051. if( NULL == UClass ) {
  2052. Values->Options[i].ClassName = NULL;
  2053. } else {
  2054. Values->Options[i].ClassName = Strings;
  2055. wcscpy(Strings, UClass);
  2056. Strings += 1 + wcslen(UClass);
  2057. }
  2058. if( NULL == VClass ) {
  2059. Values->Options[i].VendorName = NULL;
  2060. } else {
  2061. Values->Options[i].VendorName = Strings;
  2062. wcscpy(Strings, VClass);
  2063. Strings += 1 + wcslen(VClass);
  2064. }
  2065. Values->Options[i].IsVendor = IsVendor;
  2066. Result = AddSpecificOptionValues(
  2067. Values->Options[i].OptionsArray,
  2068. UClass, VClass, IsVendor,
  2069. Options,
  2070. &OptionValuesArray,
  2071. &Ptr
  2072. );
  2073. if( ERROR_SUCCESS != Result ) return Result;
  2074. }
  2075. return ERROR_SUCCESS;
  2076. }
  2077. //BeginExport(function)
  2078. //DOC This function retrieves all the option valuesdefined for this object frm th dS
  2079. DWORD
  2080. DhcpDsGetAllOptionValues(
  2081. IN LPSTORE_HANDLE hDhcpC,
  2082. IN LPSTORE_HANDLE hObject,
  2083. IN DWORD Reserved,
  2084. OUT LPDHCP_ALL_OPTION_VALUES *OptionValues
  2085. ) //EndExport(function)
  2086. {
  2087. DWORD Result, Result2, unused, Size, Size2, i;
  2088. DWORD AllocSize;
  2089. ARRAY OptAttribs;
  2090. PEATTRIB ThisAttrib;
  2091. ARRAY_LOCATION Loc;
  2092. LPDHCP_OPTION_VALUE_ARRAY LocalOptionValueArray;
  2093. LPBYTE Ptr;
  2094. ARRAY UserClassNames;
  2095. ARRAY VendorClassNames;
  2096. ARRAY IsVendorValues;
  2097. ULONG StringSpace, BinSpace;
  2098. ULONG OptionCount, ElementCount;
  2099. *OptionValues = NULL;
  2100. LocalOptionValueArray = NULL;
  2101. MemArrayInit(&OptAttribs);
  2102. Result = DhcpDsGetLists( // get list of options frm DS
  2103. /* Reserved */ DDS_RESERVED_DWORD,
  2104. /* hStore */ hObject,
  2105. /* RecursionDepth */ 0xFFFFFFFF,
  2106. /* Servers */ NULL,
  2107. /* Subnets */ NULL,
  2108. /* IpAddress */ NULL,
  2109. /* Mask */ NULL,
  2110. /* Ranges */ NULL,
  2111. /* Sites */ NULL,
  2112. /* Reservations */ NULL,
  2113. /* SuperScopes */ NULL,
  2114. /* OptionDescription */ NULL,
  2115. /* OptionsLocation */ NULL,
  2116. /* Options */ &OptAttribs,
  2117. /* Classes */ NULL
  2118. );
  2119. // if( ERROR_SUCCESS != Result ) return Result;
  2120. StringSpace = 0; BinSpace = 0; OptionCount = 0;
  2121. MemArrayInit(&UserClassNames);
  2122. MemArrayInit(&VendorClassNames);
  2123. MemArrayInit(&IsVendorValues);
  2124. for( Result = MemArrayInitLoc(&OptAttribs, &Loc)
  2125. ; ERROR_FILE_NOT_FOUND != Result ; // go thru each option, calc size
  2126. Result = MemArrayNextLoc(&OptAttribs, &Loc)
  2127. ) {
  2128. Result = MemArrayGetElement(&OptAttribs, &Loc, &ThisAttrib);
  2129. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  2130. if( !IS_DWORD1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib) ) {
  2131. continue; // illegal attrib, or not this opt
  2132. }
  2133. Result = ClassifyAndAddOptionValues(
  2134. ThisAttrib, &UserClassNames, &VendorClassNames, &IsVendorValues,
  2135. &StringSpace, &BinSpace, &OptionCount
  2136. );
  2137. if( ERROR_SUCCESS != Result ) goto Cleanup;
  2138. }
  2139. // total space required calculation...
  2140. ElementCount = MemArraySize(&UserClassNames); // same as vendor class etc..
  2141. Size = CalculateOptionValuesSize(ElementCount, StringSpace, BinSpace, OptionCount);
  2142. (*OptionValues) = MemAlloc(Size);
  2143. if( NULL == (*OptionValues) ) {
  2144. Result = ERROR_NOT_ENOUGH_MEMORY;
  2145. goto Cleanup;
  2146. }
  2147. Result = FillOptionValues(
  2148. &OptAttribs, &UserClassNames, &VendorClassNames, &IsVendorValues,
  2149. StringSpace, BinSpace, OptionCount,
  2150. (*OptionValues)
  2151. );
  2152. if( ERROR_SUCCESS != Result ) {
  2153. MemFree(*OptionValues);
  2154. *OptionValues = NULL;
  2155. }
  2156. Cleanup:
  2157. MemArrayFree(&OptAttribs, MemFreeFunc);
  2158. MemArrayFree(&UserClassNames, MemFreeFunc);
  2159. MemArrayFree(&VendorClassNames, MemFreeFunc);
  2160. MemArrayFree(&IsVendorValues, MemFreeFunc);
  2161. return Result;
  2162. }
  2163. DWORD
  2164. ClassifyAndAddOption( // classify as vendor/non-vendor etc
  2165. IN PEATTRIB ThisAttrib, // attrib to classify
  2166. IN PULONG StringSpace, // add to this the space reqd for strings
  2167. IN PULONG BinSpace, // add to this the space reqd for bin.
  2168. IN PULONG VendorCount, // increment if vendor
  2169. IN PULONG NonVendorCount // increment if non-vendor
  2170. )
  2171. {
  2172. BOOL IsVendor;
  2173. ULONG Result, Size;
  2174. if( CheckForVendor(ThisAttrib->Dword1, TRUE) ) {
  2175. (*VendorCount) ++; // vendor specific option..
  2176. IsVendor = TRUE;
  2177. if( IS_STRING3_PRESENT(ThisAttrib) ) { // got a class name
  2178. (*StringSpace) += 1+wcslen(ThisAttrib->String3);
  2179. }
  2180. } else {
  2181. (*NonVendorCount) ++; // not a vendor option
  2182. IsVendor = FALSE;
  2183. }
  2184. (*StringSpace) += 1+wcslen(ThisAttrib->String1);
  2185. if( IS_STRING2_PRESENT(ThisAttrib) ) { // string1 is name, string2 is comment
  2186. (*StringSpace) += 1+wcslen(ThisAttrib->String2);
  2187. }
  2188. Size = 0;
  2189. Result = DhcpConvertOptionRegToRPCFormat2(
  2190. /* Buffer */ ThisAttrib->Binary1,
  2191. /* BufferSize */ ThisAttrib->BinLen1,
  2192. /* Option */ NULL,
  2193. /* OptBuf */ NULL,
  2194. /* Size */ &Size
  2195. );
  2196. if( ERROR_MORE_DATA != Result && ERROR_SUCCESS != Result ) {
  2197. return Result;
  2198. }
  2199. (*BinSpace) += Size;
  2200. return ERROR_SUCCESS;
  2201. }
  2202. DWORD
  2203. CalculateOptionsSize( // calc amt storage reqd for this..
  2204. IN ULONG VendorCount, // # of vendor options
  2205. IN ULONG NonVendorCount,// # of non-vendor options
  2206. IN ULONG StringSpace, // # of WCHAR string chars
  2207. IN ULONG BinSpace // # of bytes for binary data..
  2208. )
  2209. {
  2210. ULONG Size;
  2211. LPDHCP_ALL_OPTIONS AllOptions; // dummy structure..
  2212. // First comes the structure itself
  2213. Size = ROUND_UP_COUNT(sizeof(*AllOptions), ALIGN_WORST);
  2214. // Next comes the space for a NonVendorOptions array
  2215. Size += sizeof(*(AllOptions->NonVendorOptions));
  2216. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2217. // Next comes the non-vendor optiosn themselves
  2218. Size += NonVendorCount * sizeof(DHCP_OPTION);
  2219. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2220. // Next comes the vendor options structure..
  2221. Size += VendorCount * sizeof(*(AllOptions->VendorOptions));
  2222. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2223. // Next store the strings..
  2224. Size += sizeof(WCHAR)*StringSpace;
  2225. // Next store the binary information..
  2226. Size += BinSpace;
  2227. return Size;
  2228. }
  2229. DWORD
  2230. AddSpecificOptions( // fill in the structure of optiosn..
  2231. IN OUT LPDHCP_ALL_OPTIONS AllOptions, // this is the structure to fill in
  2232. IN LPWSTR Strings, // Buffer to use to fill in all strings
  2233. IN LPBYTE BinarySpace, // this is the space to use for bin..
  2234. IN PARRAY OptDefs // the array to pick off hte options from
  2235. )
  2236. {
  2237. ULONG Err, Size;
  2238. ARRAY_LOCATION Loc;
  2239. PEATTRIB ThisAttrib;
  2240. ULONG nVendorOpts, nNonVendorOpts;
  2241. BOOL IsVendor;
  2242. ULONG OptId, OptType;
  2243. LPWSTR OptionName;
  2244. LPWSTR OptionComment;
  2245. LPWSTR VendorName;
  2246. LPDHCP_OPTION ThisOption;
  2247. AllOptions->Flags = 0;
  2248. nVendorOpts = nNonVendorOpts = 0;
  2249. for( Err = MemArrayInitLoc(OptDefs, &Loc)
  2250. ; ERROR_SUCCESS == Err ;
  2251. Err = MemArrayNextLoc(OptDefs, &Loc)
  2252. ) { // process each option
  2253. Err = MemArrayGetElement(OptDefs, &Loc, &ThisAttrib);
  2254. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib)
  2255. || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
  2256. continue; // skip it
  2257. }
  2258. IsVendor = CheckForVendor(ThisAttrib->Dword1, TRUE );
  2259. OptId = ConvertOptIdToRPCValue(ThisAttrib->Dword1, TRUE);
  2260. OptType = IS_FLAGS1_PRESENT(ThisAttrib) ? ThisAttrib->Flags1 : 0;
  2261. OptionName = ThisAttrib->String1;
  2262. OptionComment = IS_STRING2_PRESENT(ThisAttrib) ? ThisAttrib->String2 : NULL;
  2263. VendorName = IS_STRING3_PRESENT(ThisAttrib) ? ThisAttrib->String3 : NULL;
  2264. if( !IsVendor ) { // fill in the non-vendor part..
  2265. ThisOption = &AllOptions->NonVendorOptions->Options[nNonVendorOpts++];
  2266. } else {
  2267. ThisOption = &AllOptions->VendorOptions[nVendorOpts].Option;
  2268. if( !VendorName ) {
  2269. AllOptions->VendorOptions[nVendorOpts].VendorName = NULL;
  2270. } else {
  2271. wcscpy(Strings, VendorName);
  2272. AllOptions->VendorOptions[nVendorOpts].VendorName = Strings;
  2273. Strings += 1+wcslen(Strings);
  2274. }
  2275. AllOptions->VendorOptions[nVendorOpts++].ClassName = NULL;
  2276. }
  2277. Size = 0xFFFFFFFF; // databuffer size is sufficient.. but unkonwn..
  2278. Err = DhcpConvertOptionRegToRPCFormat2(
  2279. /* Buffer */ ThisAttrib->Binary1,
  2280. /* BufferSize */ ThisAttrib->BinLen1,
  2281. /* Option */ &ThisOption->DefaultValue,
  2282. /* OptBuf */ BinarySpace,
  2283. /* Size */ &Size
  2284. );
  2285. if( ERROR_SUCCESS != Err ) return Err; // barf
  2286. BinarySpace += Size; // update sapce ..
  2287. ThisOption->OptionID = OptId;
  2288. ThisOption->OptionType = OptType;
  2289. ThisOption->OptionName = Strings;
  2290. wcscpy(Strings, OptionName); Strings += 1+wcslen(Strings);
  2291. if( NULL == OptionComment ) {
  2292. ThisOption->OptionComment = NULL;
  2293. } else {
  2294. ThisOption->OptionComment = Strings;
  2295. wcscpy(Strings, OptionComment);
  2296. Strings += 1 + wcslen(Strings);
  2297. }
  2298. }
  2299. if( AllOptions->NumVendorOptions != nVendorOpts ||
  2300. AllOptions->NonVendorOptions->NumElements != nNonVendorOpts ) {
  2301. return ERROR_INVALID_DATA;
  2302. }
  2303. return ERROR_SUCCESS;
  2304. }
  2305. DWORD
  2306. FillOptions( // fill in the optinos..
  2307. IN PARRAY OptDefs, // each attrib isz an option to fill in
  2308. IN ULONG VendorCount, // # of vendor options
  2309. IN ULONG NonVendorCount,// # of non-vendor options
  2310. IN ULONG StringSpace, // sapce for strings
  2311. IN ULONG BinSpace, // space for binary..
  2312. OUT LPDHCP_ALL_OPTIONS AllOptions // fill this in..
  2313. )
  2314. {
  2315. LPBYTE Ptr;
  2316. ULONG Size,Result;
  2317. LPWSTR Strings;
  2318. LPBYTE Binary;
  2319. // first comes the structure itself..
  2320. AllOptions->Flags = 0;
  2321. AllOptions->NumVendorOptions = VendorCount;
  2322. Size = ROUND_UP_COUNT(sizeof(*AllOptions), ALIGN_WORST);
  2323. Ptr = Size + (LPBYTE)AllOptions;
  2324. // next comes NonVendorOptions array
  2325. AllOptions->NonVendorOptions = (LPVOID)Ptr;
  2326. AllOptions->NonVendorOptions->NumElements = NonVendorCount;
  2327. Size += sizeof(*(AllOptions->NonVendorOptions));
  2328. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2329. Ptr = Size + (LPBYTE)AllOptions;
  2330. if( 0 == NonVendorCount ) {
  2331. AllOptions->NonVendorOptions->Options = NULL;
  2332. } else {
  2333. AllOptions->NonVendorOptions->Options = (LPVOID)Ptr;
  2334. }
  2335. // Next comes the non-vendor optiosn themselves
  2336. Size += NonVendorCount * sizeof(DHCP_OPTION);
  2337. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2338. Ptr = Size + (LPBYTE)AllOptions;
  2339. // Next comes the vendor options structure..
  2340. AllOptions->VendorOptions = (LPVOID)Ptr;
  2341. Size += VendorCount * sizeof(*(AllOptions->VendorOptions));
  2342. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  2343. Ptr = Size + (LPBYTE)AllOptions;
  2344. // Next store the strings..
  2345. Strings = (LPWSTR)Ptr;
  2346. Size += sizeof(WCHAR)*StringSpace;
  2347. Ptr = Size + (LPBYTE)AllOptions;
  2348. // Next store the binary information..
  2349. Binary = Ptr;
  2350. return AddSpecificOptions(
  2351. AllOptions,
  2352. Strings,
  2353. Binary,
  2354. OptDefs
  2355. );
  2356. }
  2357. //BeginExport(function)
  2358. //DOC This function retrieves all the optiosn defined for this server.. frm the DS
  2359. DWORD
  2360. DhcpDsGetAllOptions(
  2361. IN LPSTORE_HANDLE hDhcpC,
  2362. IN LPSTORE_HANDLE hServer,
  2363. IN DWORD Reserved,
  2364. OUT LPDHCP_ALL_OPTIONS *Options
  2365. ) //EndExport(function)
  2366. {
  2367. DWORD Result, Result2, unused, Size, Size2, i, AllocSize;
  2368. ARRAY OptDefAttribs;
  2369. PEATTRIB ThisAttrib;
  2370. EATTRIB DummyAttrib;
  2371. ARRAY_LOCATION Loc;
  2372. LPDHCP_OPTION_ARRAY OptArray;
  2373. ULONG StringSpace, BinSpace;
  2374. ULONG VendorCount, NonVendorCount;
  2375. *Options = NULL;
  2376. MemArrayInit(&OptDefAttribs);
  2377. Result = DhcpDsGetLists( // get list of opt defs frm DS
  2378. /* Reserved */ DDS_RESERVED_DWORD,
  2379. /* hStore */ hServer,
  2380. /* RecursionDepth */ 0xFFFFFFFF,
  2381. /* Servers */ NULL,
  2382. /* Subnets */ NULL,
  2383. /* IpAddress */ NULL,
  2384. /* Mask */ NULL,
  2385. /* Ranges */ NULL,
  2386. /* Sites */ NULL,
  2387. /* Reservations */ NULL,
  2388. /* SuperScopes */ NULL,
  2389. /* OptionDescription */ &OptDefAttribs,
  2390. /* OptionsLocation */ NULL,
  2391. /* Options */ NULL,
  2392. /* Classes */ NULL
  2393. );
  2394. if( ERROR_SUCCESS != Result ) return Result;
  2395. StringSpace = 0; BinSpace = 0;
  2396. VendorCount = NonVendorCount = 0;
  2397. for( Result = MemArrayInitLoc(&OptDefAttribs, &Loc)
  2398. ; ERROR_FILE_NOT_FOUND != Result ; // search for optdef w/ <OptId>
  2399. Result = MemArrayNextLoc(&OptDefAttribs, &Loc)
  2400. ) {
  2401. Result = MemArrayGetElement(&OptDefAttribs, &Loc, &ThisAttrib);
  2402. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  2403. if( !IS_STRING1_PRESENT(ThisAttrib) || !IS_BINARY1_PRESENT(ThisAttrib)
  2404. || !IS_DWORD1_PRESENT(ThisAttrib) ) { // invalid attrib
  2405. continue; // skip it
  2406. }
  2407. Result = ClassifyAndAddOption(
  2408. ThisAttrib, &StringSpace, &BinSpace, &VendorCount, &NonVendorCount
  2409. );
  2410. if( ERROR_SUCCESS != Result ) goto Cleanup;
  2411. }
  2412. Size = CalculateOptionsSize(
  2413. VendorCount, NonVendorCount, StringSpace, BinSpace
  2414. );
  2415. (*Options) = MemAlloc(Size);
  2416. if( NULL == (*Options) ) {
  2417. Result = ERROR_NOT_ENOUGH_MEMORY;
  2418. goto Cleanup;
  2419. }
  2420. Result = FillOptions(
  2421. &OptDefAttribs, VendorCount, NonVendorCount, StringSpace, BinSpace,
  2422. (*Options)
  2423. );
  2424. if( ERROR_SUCCESS == Result ) return ERROR_SUCCESS;
  2425. MemFree(*Options);
  2426. *Options = NULL;
  2427. Cleanup:
  2428. MemArrayFree(&OptDefAttribs, MemFreeFunc);
  2429. return Result;
  2430. }
  2431. //================================================================================
  2432. // End of file
  2433. //================================================================================