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.

3359 lines
129 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. #include <delete.h>
  32. #include <st_srvr.h>
  33. #include <upndown.h>
  34. #include <dnsapi.h>
  35. //================================================================================
  36. // helper functions
  37. //================================================================================
  38. #include <rpcapi2.h>
  39. //
  40. // Allow Debug prints to ntsd or kd
  41. //
  42. // #ifdef DBG
  43. // #define DsAuthPrint(_x_) DsAuthDebugPrintRoutine _x_
  44. // #else
  45. // #define DebugPrint(_x_)
  46. // #endif
  47. extern LPWSTR
  48. CloneString( IN LPWSTR String );
  49. typedef enum {
  50. LDAP_OPERATOR_EQUAL_TO,
  51. LDAP_OPERATOR_APPROX_EQUAL_TO,
  52. LDAP_OPERATOR_LESS_OR_EQUAL_TO,
  53. LDAP_OPERATOR_GREATER_OR_EQUAL_TO,
  54. LDAP_OPERATOR_AND,
  55. LDAP_OPERATOR_OR,
  56. LDAP_OPERATOR_NOT,
  57. LDAP_OPERATOR_TOTAL
  58. } LDAP_OPERATOR_ENUM;
  59. LPWSTR LdapOperators[ LDAP_OPERATOR_TOTAL ] =
  60. { L"=", L"~=", L"<=", L">=", L"&", L"|", L"!" };
  61. VOID DsAuthPrintRoutine(
  62. LPWSTR Format,
  63. ...
  64. )
  65. {
  66. WCHAR buf[2 * 256];
  67. va_list arg;
  68. DWORD len;
  69. va_start( arg, Format );
  70. len = wsprintf(buf, L"DSAUTH: ");
  71. wvsprintf( &buf[ len ], Format, arg );
  72. va_end( arg );
  73. OutputDebugString( buf );
  74. } // DsAuthPrint()
  75. //
  76. // This function creates an LDAP query filter string
  77. // with the option type, value and operator.
  78. //
  79. // Syntax:
  80. // primitive : <filter>=(<attribute><operator><value>)
  81. // complex : (<operator><filter1><filter2>)
  82. //
  83. LPWSTR
  84. MakeLdapFilter(
  85. IN LPWSTR Operand1,
  86. IN LDAP_OPERATOR_ENUM Operator,
  87. IN LPWSTR Operand2,
  88. IN BOOL Primitive
  89. )
  90. {
  91. LPWSTR Result;
  92. DWORD Size;
  93. DWORD Len;
  94. CHAR buffer[100];
  95. Result = NULL;
  96. AssertRet((( NULL != Operand1 ) &&
  97. ( NULL != Operand2 ) &&
  98. (( Operator >= 0 ) && ( Operator < LDAP_OPERATOR_TOTAL ))),
  99. NULL );
  100. // calculate the amount of memory needed
  101. Size = 0;
  102. Size += ROUND_UP_COUNT( sizeof( L"(" ), ALIGN_WORST );
  103. Size += ROUND_UP_COUNT( sizeof( L")" ), ALIGN_WORST );
  104. Size += ROUND_UP_COUNT( wcslen( Operand1 ), ALIGN_WORST );
  105. Size += ROUND_UP_COUNT( wcslen( Operand2 ), ALIGN_WORST );
  106. Size += ROUND_UP_COUNT( wcslen( LdapOperators[ Operator ] ), ALIGN_WORST );
  107. Size += 16; // padding
  108. Result = MemAlloc( Size * sizeof( WCHAR ));
  109. if ( NULL == Result ) {
  110. return NULL;
  111. }
  112. if ( Primitive ) {
  113. Len = wsprintf( Result,
  114. L"(%ws%ws%ws)",
  115. Operand1, LdapOperators[ Operator ], Operand2
  116. );
  117. }
  118. else {
  119. Len = wsprintf( Result,
  120. L"(%ws%ws%ws)",
  121. LdapOperators[ Operator ], Operand1, Operand2
  122. );
  123. } // else
  124. AssertRet( Len <= Size, NULL );
  125. return Result;
  126. } // MakeLdapFilter()
  127. //
  128. // Make a LDAP query filter like this:
  129. // (&(objectCategory=dHCPClass)(|(dhcpServer="i<ip>*")(dhcpServer="*s<hostname>*")))
  130. //
  131. LPWSTR
  132. MakeFilter(
  133. LPWSTR LookupServerIP, // Printable IP addr
  134. LPWSTR HostName
  135. )
  136. {
  137. LPWSTR Filter1, Filter2, Filter3, Filter4, SearchFilter;
  138. LPWSTR Buf;
  139. DWORD Len, CopiedLen;
  140. AssertRet((( NULL != LookupServerIP ) &&
  141. ( NULL != HostName )), NULL );
  142. Filter1 = NULL;
  143. Filter2 = NULL;
  144. Filter3 = NULL;
  145. Filter4 = NULL;
  146. SearchFilter = NULL;
  147. do {
  148. Len = wcslen( HostName ) + 10 ;
  149. Buf = MemAlloc( Len * sizeof( WCHAR ));
  150. if ( NULL == Buf ) {
  151. break;
  152. }
  153. // make (objectCategory=dHCPClass)
  154. Filter1 = MakeLdapFilter( ATTRIB_OBJECT_CATEGORY,
  155. LDAP_OPERATOR_EQUAL_TO,
  156. DEFAULT_DHCP_CLASS_ATTRIB_VALUE,
  157. TRUE );
  158. if ( NULL == Filter1 ) {
  159. break;
  160. }
  161. // The IP needs to be sent as i<ip>* to match the query
  162. // make (dhcpServers="i<ip>*")
  163. CopiedLen = _snwprintf( Buf, Len, L"i%ws*", LookupServerIP );
  164. Require( CopiedLen > 0 );
  165. Filter2 = MakeLdapFilter( DHCP_ATTRIB_SERVERS,
  166. LDAP_OPERATOR_EQUAL_TO, Buf, TRUE );
  167. if ( NULL == Filter2 ) {
  168. break;
  169. }
  170. // make (dhcpServers="*s<hostname>*")
  171. CopiedLen = _snwprintf( Buf, Len, L"*s%ws*", HostName );
  172. Require( CopiedLen > 0 );
  173. Filter3 = MakeLdapFilter( DHCP_ATTRIB_SERVERS,
  174. LDAP_OPERATOR_EQUAL_TO, Buf, TRUE );
  175. if ( NULL == Filter3 ) {
  176. break;
  177. }
  178. // make (|(<ipfilter>)(<hostfilter))
  179. Filter4 = MakeLdapFilter( Filter2, LDAP_OPERATOR_OR,
  180. Filter3, FALSE );
  181. if ( NULL == Filter4 ) {
  182. break;
  183. }
  184. // Finally make the filter to be returned
  185. SearchFilter = MakeLdapFilter( Filter1, LDAP_OPERATOR_AND,
  186. Filter4, FALSE );
  187. } while ( FALSE );
  188. if ( NULL != Buf ) {
  189. MemFree( Buf );
  190. }
  191. if ( NULL != Filter1 ) {
  192. MemFree( Filter1 );
  193. }
  194. if ( NULL != Filter2 ) {
  195. MemFree( Filter2 );
  196. }
  197. if ( NULL != Filter3 ) {
  198. MemFree( Filter3 );
  199. }
  200. if ( NULL != Filter4 ) {
  201. MemFree( Filter4 );
  202. }
  203. return SearchFilter;
  204. } // MakeFilter()
  205. //================================================================================
  206. // This function computes the unique identifier for a client; this is just
  207. // client subnet + client hw address type + client hw address. note that client
  208. // hardware address type is hardcoded as HARDWARE_TYPE_10MB_EITHERNET as there
  209. // is no way in the ui to specify type of reservations..
  210. // Also, DhcpValidateClient (cltapi.c?) uses the subnet address for validation.
  211. // Dont remove that.
  212. //================================================================================
  213. DWORD
  214. DhcpMakeClientUID( // compute unique identifier for the client
  215. IN LPBYTE ClientHardwareAddress,
  216. IN DWORD ClientHardwareAddressLength,
  217. IN BYTE ClientHardwareAddressType,
  218. IN DHCP_IP_ADDRESS ClientSubnetAddress,
  219. OUT LPBYTE *ClientUID, // will be allocated by function
  220. OUT DWORD *ClientUIDLength
  221. )
  222. {
  223. LPBYTE Buffer;
  224. LPBYTE ClientUIDBuffer;
  225. BYTE ClientUIDBufferLength;
  226. if( NULL == ClientUID || NULL == ClientUIDLength || 0 == ClientHardwareAddressLength )
  227. return ERROR_INVALID_PARAMETER;
  228. // see comment about on hardcoded hardware address type
  229. ClientHardwareAddressType = HARDWARE_TYPE_10MB_EITHERNET;
  230. ClientUIDBufferLength = sizeof(ClientSubnetAddress);
  231. ClientUIDBufferLength += sizeof(ClientHardwareAddressType);
  232. ClientUIDBufferLength += (BYTE)ClientHardwareAddressLength;
  233. ClientUIDBuffer = MemAlloc( ClientUIDBufferLength );
  234. if( ClientUIDBuffer == NULL ) {
  235. *ClientUIDLength = 0;
  236. return ERROR_NOT_ENOUGH_MEMORY;
  237. }
  238. Buffer = ClientUIDBuffer;
  239. RtlCopyMemory(Buffer,&ClientSubnetAddress,sizeof(ClientSubnetAddress));
  240. Buffer += sizeof(ClientSubnetAddress);
  241. RtlCopyMemory(Buffer,&ClientHardwareAddressType,sizeof(ClientHardwareAddressType) );
  242. Buffer += sizeof(ClientHardwareAddressType);
  243. RtlCopyMemory(Buffer,ClientHardwareAddress,ClientHardwareAddressLength );
  244. *ClientUID = ClientUIDBuffer;
  245. *ClientUIDLength = ClientUIDBufferLength;
  246. return ERROR_SUCCESS;
  247. }
  248. VOID static
  249. MemFreeFunc( // free memory
  250. IN OUT LPVOID Memory
  251. )
  252. {
  253. MemFree(Memory);
  254. }
  255. //DOC ServerAddAddress should add the new address to the server's attribs
  256. //DOC it should take this opportunity to reconcile the server.
  257. //DOC Currently it does nothing. (at the least it should probably try to
  258. //DOC check if the object exists, and if not create it.)
  259. //DOC
  260. DWORD
  261. ServerAddAddress( // add server and do misc work
  262. IN OUT LPSTORE_HANDLE hDhcpC, // container for server obj
  263. IN LPWSTR ServerName, // [DNS?] name of server
  264. IN LPWSTR ADsPath, // ADS path of the server
  265. IN DWORD IpAddress, // IpAddress to add to server
  266. IN DWORD State // state of server
  267. )
  268. {
  269. return AddServer(hDhcpC, ServerName, ADsPath, IpAddress, State);
  270. }
  271. //DOC CreateServerObject creates the server object in the DS. It takes the
  272. //DOC ServerName parameter and names the object using this.
  273. //DOC The server is created with default values for most attribs.
  274. //DOC Several attribs are just not set.
  275. //DOC This returns ERROR_DDS_UNEXPECTED_ERROR if any DS operation fails.
  276. DWORD
  277. CreateServerObject( // create dhcp srvr obj in ds
  278. IN OUT LPSTORE_HANDLE hDhcpC, // container to creat obj in
  279. IN LPWSTR ServerName // [DNS?] name of server
  280. )
  281. {
  282. DWORD Err;
  283. LPWSTR ServerCNName; // container name
  284. ServerCNName = MakeColumnName(ServerName); // convert from "name" to "CN=name"
  285. if( NULL == ServerCNName ) return ERROR_NOT_ENOUGH_MEMORY;
  286. Err = StoreCreateObject // now create the object
  287. (
  288. /* hStore */ hDhcpC,
  289. /* Reserved */ DDS_RESERVED_DWORD,
  290. /* NewObjName */ ServerCNName,
  291. /* ... */
  292. /* Identification */
  293. ADSTYPE_DN_STRING, ATTRIB_DN_NAME, ServerName,
  294. ADSTYPE_DN_STRING, ATTRIB_OBJECT_CLASS, DEFAULT_DHCP_CLASS_ATTRIB_VALUE,
  295. /* systemMustContain */
  296. ADSTYPE_INTEGER, ATTRIB_DHCP_UNIQUE_KEY, 0,
  297. ADSTYPE_INTEGER, ATTRIB_DHCP_TYPE, DHCP_OBJ_TYPE_SERVER,
  298. ADSTYPE_DN_STRING, ATTRIB_DHCP_IDENTIFICATION, DHCP_OBJ_TYPE_SERVER_DESC,
  299. ADSTYPE_INTEGER, ATTRIB_DHCP_FLAGS, 0,
  300. ADSTYPE_INTEGER, ATTRIB_INSTANCE_TYPE, DEFAULT_INSTANCE_TYPE_ATTRIB_VALUE,
  301. /* terminator */
  302. ADSTYPE_INVALID
  303. );
  304. if( ERROR_ALREADY_EXISTS == Err ) { // if object exists, ignore this..
  305. Err = ERROR_SUCCESS;
  306. }
  307. MemFree(ServerCNName);
  308. return Err;
  309. }
  310. //DOC CreateSubnetObject creates the subnet object in the DS by cooking up a
  311. //DOC name that is just a concatenation of the server name and the subnet address.
  312. //DOC The object is set with some default values for most attribs.
  313. //DOC This fn returns ERROR_DDS_UNEXPECTED_ERROR if any DS operation fails.
  314. DWORD
  315. CreateSubnetObject( // create dhcp subnet obj in ds
  316. IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container obj
  317. IN LPWSTR SubnetCNName // subnet name in "CN=xx" fmt
  318. )
  319. {
  320. DWORD Err;
  321. LPWSTR SubnetName;
  322. SubnetName = SubnetCNName + 3; // skip the "CN=" part
  323. Err = StoreCreateObject // now create the object
  324. (
  325. /* hStore */ hDhcpC,
  326. /* Reserved */ DDS_RESERVED_DWORD,
  327. /* NewObjName */ SubnetCNName,
  328. /* ... */
  329. /* Identification */
  330. ADSTYPE_DN_STRING, ATTRIB_DN_NAME, SubnetName,
  331. ADSTYPE_DN_STRING, ATTRIB_OBJECT_CLASS, DEFAULT_DHCP_CLASS_ATTRIB_VALUE,
  332. /* systemMustContain */
  333. ADSTYPE_INTEGER, ATTRIB_DHCP_UNIQUE_KEY, 0,
  334. ADSTYPE_INTEGER, ATTRIB_DHCP_TYPE, DHCP_OBJ_TYPE_SUBNET,
  335. ADSTYPE_DN_STRING, ATTRIB_DHCP_IDENTIFICATION, DHCP_OBJ_TYPE_SUBNET_DESC,
  336. ADSTYPE_INTEGER, ATTRIB_DHCP_FLAGS, 0,
  337. ADSTYPE_INTEGER, ATTRIB_INSTANCE_TYPE, DEFAULT_INSTANCE_TYPE_ATTRIB_VALUE,
  338. /* terminator */
  339. ADSTYPE_INVALID
  340. );
  341. if( ERROR_ALREADY_EXISTS == Err ) { // if object exists, ignore this..
  342. Err = ERROR_SUCCESS;
  343. }
  344. return Err;
  345. }
  346. //DOC CreateReservationObject creates a reservation object in the DS.
  347. //DOC It just fills in some reasonable information for all the required fields.
  348. //DOC If fails if the object already exists
  349. //DOC
  350. DWORD
  351. CreateReservationObject( // create reservation object in DS
  352. IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container obj
  353. IN LPWSTR ReserveCNName // reservation name in "CN=X" fmt
  354. )
  355. {
  356. DWORD Err;
  357. LPWSTR ReserveName;
  358. ReserveName = ReserveCNName+ 3;
  359. Err = StoreCreateObject // now create the object
  360. (
  361. /* hStore */ hDhcpC,
  362. /* Reserved */ DDS_RESERVED_DWORD,
  363. /* NewObjName */ ReserveCNName,
  364. /* ... */
  365. /* Identification */
  366. ADSTYPE_DN_STRING, ATTRIB_DN_NAME, ReserveName,
  367. ADSTYPE_DN_STRING, ATTRIB_OBJECT_CLASS, DEFAULT_DHCP_CLASS_ATTRIB_VALUE,
  368. /* systemMustContain */
  369. ADSTYPE_INTEGER, ATTRIB_DHCP_UNIQUE_KEY, 0,
  370. ADSTYPE_INTEGER, ATTRIB_DHCP_TYPE, DHCP_OBJ_TYPE_RESERVATION,
  371. ADSTYPE_DN_STRING, ATTRIB_DHCP_IDENTIFICATION, DHCP_OBJ_TYPE_RESERVATION_DESC,
  372. ADSTYPE_INTEGER, ATTRIB_DHCP_FLAGS, 0,
  373. ADSTYPE_INTEGER, ATTRIB_INSTANCE_TYPE, DEFAULT_INSTANCE_TYPE_ATTRIB_VALUE,
  374. /* terminator */
  375. ADSTYPE_INVALID
  376. );
  377. if( ERROR_ALREADY_EXISTS == Err ) { // if object exists, ignore this..
  378. Err = ERROR_SUCCESS;
  379. }
  380. return Err;
  381. }
  382. //DOC FindCollisions walks through an array of attribs and compares each
  383. //DOC against the parameters to see if there is a collision.. If the parameters
  384. //DOC passed have type RANGE, then an extension of a range is allowed.
  385. //DOC If not, anything is allowed. In case there is an extension, the Extender
  386. //DOC parameter is filled with the attrib that gets extended..
  387. //DOC This function returns TRUE if there is a collision and FALSE if ok.
  388. BOOL
  389. FindCollisions( // find range vs range collisions
  390. IN PARRAY Attribs, // array of PEATTRIB's
  391. IN DWORD RangeStart,
  392. IN DWORD RangeEnd,
  393. IN DWORD RangeType, // RANGE_TYPE_RANGE || RANGE_TYPE_EXCL
  394. OUT PEATTRIB *Extender // this attrib needs to be extended
  395. )
  396. {
  397. DWORD Err, Cond;
  398. ARRAY_LOCATION Loc;
  399. PEATTRIB ThisAttrib;
  400. *Extender = NULL;
  401. if( (RangeType & RANGE_TYPE_MASK) == RANGE_TYPE_EXCL ) {
  402. return ERROR_SUCCESS; // anything is ok for excl
  403. }
  404. for( // walk thru the array
  405. Err = MemArrayInitLoc(Attribs, &Loc)
  406. ; ERROR_FILE_NOT_FOUND != Err ;
  407. Err = MemArrayNextLoc(Attribs, &Loc)
  408. ) {
  409. Err = MemArrayGetElement(Attribs, &Loc, &ThisAttrib);
  410. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  411. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no range start
  412. !IS_ADDRESS2_PRESENT(ThisAttrib) || // no range end
  413. !IS_FLAGS1_PRESENT(ThisAttrib) ) { // range state?
  414. continue; //= ds inconsistent
  415. }
  416. if( IS_FLAGS2_PRESENT(ThisAttrib) &&
  417. (RANGE_TYPE_MASK & ThisAttrib->Flags2) == RANGE_TYPE_EXCL ) {
  418. continue; // skip exclusions
  419. }
  420. if( ThisAttrib->Address2 < ThisAttrib->Address1 ) {
  421. continue; //= ds inconsistent
  422. }
  423. Cond = MemRangeCompare(
  424. RangeStart,RangeEnd, // range X and below is range Y
  425. ThisAttrib->Address1, ThisAttrib->Address2
  426. );
  427. switch(Cond) { // make comparisons on 2 ranges
  428. case X_LESSTHAN_Y_OVERLAP:
  429. case Y_LESSTHAN_X_OVERLAP:
  430. if( NULL != *Extender ) return TRUE; // double extensions not allowed
  431. *Extender = ThisAttrib;
  432. break;
  433. case X_IN_Y:
  434. case Y_IN_X:
  435. return TRUE; // head on collision is fatal
  436. }
  437. }
  438. return FALSE;
  439. }
  440. BOOL
  441. ServerMatched(
  442. IN PEATTRIB ThisAttrib,
  443. IN LPWSTR ServerName,
  444. IN ULONG IpAddress,
  445. OUT BOOL *fExactMatch
  446. )
  447. {
  448. BOOL fIpMatch, fNameMatch, fWildcardIp;
  449. (*fExactMatch) = FALSE;
  450. fIpMatch = (ThisAttrib->Address1 == IpAddress);
  451. if( INADDR_BROADCAST == ThisAttrib->Address1 ||
  452. INADDR_BROADCAST == IpAddress ) {
  453. fWildcardIp = TRUE;
  454. } else {
  455. fWildcardIp = FALSE;
  456. }
  457. if( FALSE == fIpMatch ) {
  458. //
  459. // If IP Addresses don't match, then check to see if
  460. // one of the IP addresses is a broadcast address..
  461. //
  462. if( !fWildcardIp ) return FALSE;
  463. }
  464. fNameMatch = DnsNameCompare_W(ThisAttrib->String1, ServerName);
  465. if( FALSE == fNameMatch ) {
  466. //
  467. // If names don't match _and_ IP's don't match, no match.
  468. //
  469. if( FALSE == fIpMatch || fWildcardIp ) return FALSE;
  470. } else {
  471. if( FALSE == fIpMatch ) return TRUE;
  472. (*fExactMatch) = TRUE;
  473. }
  474. return TRUE;
  475. }
  476. DWORD
  477. GetListOfAllServersMatchingFilter(
  478. IN OUT LPSTORE_HANDLE hDhcpC,
  479. IN OUT PARRAY Servers,
  480. IN LPWSTR SearchFilter OPTIONAL
  481. )
  482. {
  483. DWORD Err, LastErr;
  484. STORE_HANDLE hContainer;
  485. LPWSTR Filter;
  486. AssertRet( ( NULL != hDhcpC ) && ( NULL != Servers ),
  487. ERROR_INVALID_PARAMETER );
  488. Err = StoreSetSearchOneLevel(
  489. hDhcpC, DDS_RESERVED_DWORD );
  490. AssertRet( Err == NO_ERROR, Err );
  491. if ( NULL == SearchFilter ) {
  492. Filter = DHCP_SEARCH_FILTER;
  493. }
  494. else {
  495. Filter = SearchFilter;
  496. }
  497. AssertRet( NULL != Filter, ERROR_INVALID_PARAMETER );
  498. Err = StoreBeginSearch(
  499. hDhcpC, DDS_RESERVED_DWORD, Filter );
  500. AssertRet( Err == NO_ERROR, Err );
  501. while( TRUE ) {
  502. Err = StoreSearchGetNext(
  503. hDhcpC, DDS_RESERVED_DWORD, &hContainer );
  504. if( ERROR_DS_INVALID_DN_SYNTAX == Err ) {
  505. //
  506. // This nasty problem is because of an upgrade issue
  507. // in DS where some bad-named objects may exist..
  508. //
  509. Err = NO_ERROR;
  510. continue;
  511. }
  512. if( NO_ERROR != Err ) break;
  513. Err = DhcpDsGetLists
  514. (
  515. /* Reserved */ DDS_RESERVED_DWORD,
  516. /* hStore */ &hContainer,
  517. /* RecursionDepth */ 0xFFFFFFFF,
  518. /* Servers */ Servers, // array of PEATTRIB 's
  519. /* Subnets */ NULL,
  520. /* IpAddress */ NULL,
  521. /* Mask */ NULL,
  522. /* Ranges */ NULL,
  523. /* Sites */ NULL,
  524. /* Reservations */ NULL,
  525. /* SuperScopes */ NULL,
  526. /* OptionDescription */ NULL,
  527. /* OptionsLocation */ NULL,
  528. /* Options */ NULL,
  529. /* Classes */ NULL
  530. );
  531. StoreCleanupHandle( &hContainer, DDS_RESERVED_DWORD );
  532. if( NO_ERROR != Err ) break;
  533. }
  534. if( Err == ERROR_NO_MORE_ITEMS ) Err = NO_ERROR;
  535. LastErr = StoreEndSearch( hDhcpC, DDS_RESERVED_DWORD );
  536. //Require( LastErr == NO_ERROR );
  537. return Err;
  538. }
  539. DWORD
  540. DhcpDsAddServerInternal( // add a server in DS
  541. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  542. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  543. IN DWORD Reserved, // must be zero, future use
  544. IN LPWSTR ServerName, // [DNS?] name of server
  545. IN LPWSTR ReservedPtr, // Server location? future use
  546. IN DWORD IpAddress, // ip address of server
  547. IN DWORD State // currently un-interpreted
  548. )
  549. {
  550. DWORD Err, Err2, unused;
  551. ARRAY Servers;
  552. ARRAY_LOCATION Loc;
  553. PEATTRIB ThisAttrib;
  554. EATTRIB DummyAttrib;
  555. BOOL fServerExists;
  556. LPWSTR ServerLocation, Tmp;
  557. DWORD ServerLocType;
  558. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  559. return ERROR_INVALID_PARAMETER;
  560. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  561. return ERROR_INVALID_PARAMETER;
  562. if( NULL == ServerName || 0 != Reserved )
  563. return ERROR_INVALID_PARAMETER;
  564. Err = MemArrayInit(&Servers); // cant fail
  565. //= require ERROR_SUCCESS == Err
  566. Err = DhcpDsGetLists // get list of servers
  567. (
  568. /* Reserved */ DDS_RESERVED_DWORD,
  569. /* hStore */ hDhcpRoot,
  570. /* RecursionDepth */ 0xFFFFFFFF,
  571. /* Servers */ &Servers, // array of PEATTRIB 's
  572. /* Subnets */ NULL,
  573. /* IpAddress */ NULL,
  574. /* Mask */ NULL,
  575. /* Ranges */ NULL,
  576. /* Sites */ NULL,
  577. /* Reservations */ NULL,
  578. /* SuperScopes */ NULL,
  579. /* OptionDescription */ NULL,
  580. /* OptionsLocation */ NULL,
  581. /* Options */ NULL,
  582. /* Classes */ NULL
  583. );
  584. if( ERROR_SUCCESS != Err ) return Err;
  585. Tmp = NULL; ServerLocation = NULL;
  586. fServerExists = FALSE; // did we find the same servername?
  587. for( // search list of servers
  588. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  589. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  590. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  591. ) {
  592. BOOL fExactMatch = FALSE;
  593. //= require ERROR_SUCCESS == Err
  594. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  595. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  596. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  597. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  598. continue; //= ds inconsistent
  599. }
  600. if( ServerMatched(ThisAttrib, ServerName, IpAddress, &fExactMatch ) ) {
  601. //
  602. // Server found in the list of servers. Exact match not allowed.
  603. //
  604. if( fExactMatch ) {
  605. MemArrayFree(&Servers,MemFreeFunc);// free allocated memory
  606. return ERROR_DDS_SERVER_ALREADY_EXISTS;
  607. }
  608. fServerExists = TRUE;
  609. if( IS_ADDRESS1_PRESENT(ThisAttrib) &&
  610. NULL == ServerLocation ) { // remember location in DS.
  611. ServerLocation = ThisAttrib->ADsPath;
  612. ServerLocType = ThisAttrib->StoreGetType;
  613. }
  614. }
  615. }
  616. if( !fServerExists ) { // if freshly adding a server, create obj
  617. WCHAR Buf[sizeof("000.000.000.000")];
  618. LPWSTR SName;
  619. if( L'\0' != ServerName[0] ) {
  620. SName = ServerName;
  621. } else {
  622. ULONG IpAddr;
  623. LPSTR IpAddrString;
  624. IpAddr = htonl(IpAddress);
  625. IpAddrString = inet_ntoa(*(struct in_addr *)&IpAddr);
  626. Err = mbstowcs(Buf, IpAddrString, sizeof(Buf)/sizeof(WCHAR));
  627. if( -1 == Err ) {
  628. MemArrayFree(&Servers, MemFreeFunc);
  629. return ERROR_CAN_NOT_COMPLETE;
  630. }
  631. SName = Buf;
  632. }
  633. ServerLocation = Tmp = MakeColumnName(SName);
  634. ServerLocType = StoreGetChildType;
  635. }
  636. NothingPresent(&DummyAttrib); // fill in attrib w/ srvr info
  637. STRING1_PRESENT(&DummyAttrib); // name
  638. ADDRESS1_PRESENT(&DummyAttrib); // ip addr
  639. FLAGS1_PRESENT(&DummyAttrib); // state
  640. DummyAttrib.String1 = ServerName;
  641. DummyAttrib.Address1 = IpAddress;
  642. DummyAttrib.Flags1 = State;
  643. if( ServerLocation ) {
  644. ADSPATH_PRESENT(&DummyAttrib); // ADsPath of location of server object
  645. STOREGETTYPE_PRESENT(&DummyAttrib);
  646. DummyAttrib.ADsPath = ServerLocation;
  647. DummyAttrib.StoreGetType = ServerLocType;
  648. }
  649. Err = MemArrayAddElement(&Servers, &DummyAttrib);
  650. if( ERROR_SUCCESS != Err ) { // could not add this to attrib array
  651. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  652. if( Tmp ) MemFree(Tmp); // if allocate mem for ServerLocation..
  653. return Err;
  654. }
  655. Err = DhcpDsSetLists // now set the new attrib list
  656. (
  657. /* Reserved */ DDS_RESERVED_DWORD,
  658. /* hStore */ hDhcpRoot,
  659. /* SetParams */ &unused,
  660. /* Servers */ &Servers,
  661. /* Subnets */ NULL,
  662. /* IpAddress */ NULL,
  663. /* Mask */ NULL,
  664. /* Ranges */ NULL,
  665. /* Sites */ NULL,
  666. /* Reservations */ NULL,
  667. /* SuperScopes */ NULL,
  668. /* OptionDescription.. */ NULL,
  669. /* OptionsLocation */ NULL,
  670. /* Options */ NULL,
  671. /* ClassDescription */ NULL,
  672. /* Classes */ NULL
  673. );
  674. Err2 = MemArrayLastLoc(&Servers, &Loc); // theres atleast 1 elt in array
  675. //= require ERROR_SUCCESS == Err2
  676. Err2 = MemArrayDelElement(&Servers, &Loc, &ThisAttrib);
  677. //= require ERROR_SUCCESS == Err2 && ThisAttrib == &DummyAttrib
  678. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  679. if( ERROR_SUCCESS != Err || fServerExists ) {
  680. if( Tmp ) MemFree(Tmp); // if allocated memory for ServerLocation..
  681. if( ERROR_SUCCESS != Err) return Err; // check err for DhcpDsSetLists
  682. //: This wont do if there is a problem...
  683. if( fServerExists ) return ERROR_SUCCESS; // if server already existed.. not much work needed?
  684. }
  685. if( Tmp ) MemFree(Tmp);
  686. return Err;
  687. }
  688. //================================================================================
  689. // exported functions
  690. //================================================================================
  691. //BeginExport(function)
  692. //DOC DhcpDsAddServer adds a server's entry in the DS. Note that only the name
  693. //DOC uniquely determines the server. There can be one server with many ip addresses.
  694. //DOC If the server is created first time, a separate object is created for the
  695. //DOC server. : TO DO: The newly added server should also have its data
  696. //DOC updated in the DS uploaded from the server itself if it is still up.
  697. //DOC Note that it takes as parameter the Dhcp root container.
  698. //DOC If the requested address already exists in the DS (maybe to some other
  699. //DOC server), then the function returns ERROR_DDS_SERVER_ALREADY_EXISTS
  700. DWORD
  701. DhcpDsAddServer( // add a server in DS
  702. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  703. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  704. IN DWORD Reserved, // must be zero, future use
  705. IN LPWSTR ServerName, // [DNS?] name of server
  706. IN LPWSTR ReservedPtr, // Server location? future use
  707. IN DWORD IpAddress, // ip address of server
  708. IN DWORD State // currently un-interpreted
  709. ) //EndExport(function)
  710. {
  711. DWORD Err, Err2, unused;
  712. ARRAY Servers;
  713. ARRAY_LOCATION Loc;
  714. PEATTRIB ThisAttrib;
  715. BOOL fServerExists;
  716. LPWSTR ServerLocation, Tmp;
  717. DWORD ServerLocType;
  718. STORE_HANDLE hDhcpServer;
  719. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  720. return ERROR_INVALID_PARAMETER;
  721. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  722. return ERROR_INVALID_PARAMETER;
  723. if( NULL == ServerName || 0 != Reserved )
  724. return ERROR_INVALID_PARAMETER;
  725. Err = MemArrayInit(&Servers); // cant fail
  726. //= require ERROR_SUCCESS == Err
  727. DsAuthPrint(( L"DhcpAddServer() \n" ));
  728. Err = GetListOfAllServersMatchingFilter( hDhcpC, &Servers,
  729. DHCP_SEARCH_FILTER );
  730. if( ERROR_SUCCESS != Err ) return Err;
  731. Tmp = NULL; ServerLocation = NULL;
  732. fServerExists = FALSE; // did we find the same servername?
  733. for( // search list of servers
  734. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  735. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  736. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  737. ) {
  738. BOOL fExactMatch = FALSE;
  739. //= require ERROR_SUCCESS == Err
  740. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  741. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  742. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  743. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  744. continue; //= ds inconsistent
  745. }
  746. if( ServerMatched(ThisAttrib, ServerName, IpAddress, &fExactMatch ) ) {
  747. //
  748. // Server found in the list of servers. Exact match not allowed.
  749. //
  750. if( fExactMatch ) {
  751. MemArrayFree(&Servers,MemFreeFunc);// free allocated memory
  752. return ERROR_DDS_SERVER_ALREADY_EXISTS;
  753. }
  754. fServerExists = TRUE;
  755. if( IS_ADDRESS1_PRESENT(ThisAttrib) &&
  756. NULL == ServerLocation ) { // remember location in DS.
  757. ServerLocation = ThisAttrib->ADsPath;
  758. ServerLocType = ThisAttrib->StoreGetType;
  759. }
  760. }
  761. } // for
  762. if( !fServerExists ) { // if freshly adding a server, create obj
  763. WCHAR Buf[sizeof("000.000.000.000")];
  764. LPWSTR SName;
  765. if( L'\0' != ServerName[0] ) {
  766. // do not use the name. Use the printable IP addr instead
  767. SName = ServerName;
  768. } else {
  769. ULONG IpAddr;
  770. LPSTR IpAddrString;
  771. IpAddr = htonl(IpAddress);
  772. IpAddrString = inet_ntoa(*(struct in_addr *)&IpAddr);
  773. Err = mbstowcs(Buf, IpAddrString, sizeof(Buf)/sizeof(WCHAR));
  774. if( -1 == Err ) {
  775. MemArrayFree(&Servers, MemFreeFunc);
  776. return ERROR_CAN_NOT_COMPLETE;
  777. }
  778. SName = Buf;
  779. }
  780. Err = CreateServerObject(
  781. /* hDhcpC */ hDhcpC,
  782. /* ServerName */ SName
  783. );
  784. if( ERROR_SUCCESS != Err ) { // dont add server if obj cant be created
  785. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  786. return Err;
  787. }
  788. ServerLocation = Tmp = MakeColumnName(SName);
  789. ServerLocType = StoreGetChildType;
  790. }
  791. Err = StoreGetHandle(
  792. hDhcpC, 0, ServerLocType, ServerLocation, &hDhcpServer );
  793. if( NO_ERROR == Err ) {
  794. Err = DhcpDsAddServerInternal(
  795. hDhcpC, &hDhcpServer, Reserved, ServerName, ReservedPtr,
  796. IpAddress, State );
  797. StoreCleanupHandle( &hDhcpServer, 0 );
  798. }
  799. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  800. if( ERROR_SUCCESS != Err || fServerExists ) {
  801. if( Tmp ) MemFree(Tmp); // if allocated memory for ServerLocation..
  802. if( ERROR_SUCCESS != Err) return Err; // check err for DhcpDsSetLists
  803. //: This wont do if there is a problem...
  804. if( fServerExists ) return ERROR_SUCCESS; // if server already existed.. not much work needed?
  805. }
  806. Err = ServerAddAddress // add the info into the server
  807. (
  808. /* hDhcpC */ hDhcpC,
  809. /* ServerName */ ServerName,
  810. /* ADsPath */ ServerLocation,
  811. /* IpAddress */ IpAddress,
  812. /* State */ State
  813. );
  814. if( Tmp ) MemFree(Tmp);
  815. return Err;
  816. }
  817. DWORD
  818. DhcpDsDelServerInternal( // Delete a server from memory
  819. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  820. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  821. IN DWORD Reserved, // must be zero, for future use
  822. IN LPWSTR ServerName, // which server to delete for
  823. IN LPWSTR ReservedPtr, // server location ? future use
  824. IN DWORD IpAddress // the IpAddress to delete..
  825. )
  826. {
  827. DWORD Err, Err2, unused;
  828. ARRAY Servers;
  829. ARRAY_LOCATION Loc;
  830. PEATTRIB ThisAttrib, SavedAttrib;
  831. BOOL fServerExists;
  832. BOOL fServerDeleted;
  833. LPWSTR SName;
  834. LPWSTR ServerLoc = NULL;
  835. DWORD ServerLocType;
  836. WCHAR Buf[sizeof("000.000.000.000")];
  837. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  838. return ERROR_INVALID_PARAMETER;
  839. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  840. return ERROR_INVALID_PARAMETER;
  841. if( NULL == ServerName || 0 != Reserved )
  842. return ERROR_INVALID_PARAMETER;
  843. Err = MemArrayInit(&Servers); // cant fail
  844. //= require ERROR_SUCCESS == Err
  845. Err = DhcpDsGetLists // get list of servers
  846. (
  847. /* Reserved */ DDS_RESERVED_DWORD,
  848. /* hStore */ hDhcpRoot,
  849. /* RecursionDepth */ 0xFFFFFFFF,
  850. /* Servers */ &Servers, // array of PEATTRIB 's
  851. /* Subnets */ NULL,
  852. /* IpAddress */ NULL,
  853. /* Mask */ NULL,
  854. /* Ranges */ NULL,
  855. /* Sites */ NULL,
  856. /* Reservations */ NULL,
  857. /* SuperScopes */ NULL,
  858. /* OptionDescription */ NULL,
  859. /* OptionsLocation */ NULL,
  860. /* Options */ NULL,
  861. /* Classes */ NULL
  862. );
  863. if( ERROR_SUCCESS != Err ) return Err;
  864. SavedAttrib = NULL;
  865. fServerExists = fServerDeleted = FALSE;
  866. for( // search list of servers
  867. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  868. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  869. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  870. ) {
  871. BOOL fExactMatch = FALSE;
  872. //= require ERROR_SUCCESS == Err
  873. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  874. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  875. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  876. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  877. continue; //= ds inconsistent
  878. }
  879. if( ServerMatched(ThisAttrib, ServerName, IpAddress, &fExactMatch ) ) {
  880. //
  881. // Server found. If exact match, remove the element from list.
  882. //
  883. if( fExactMatch ) {
  884. Err2 = MemArrayDelElement(&Servers, &Loc, &ThisAttrib);
  885. //= ERROR_SUCCESS == Err2 && NULL != ThisAttrib
  886. }
  887. if( (NULL == ServerLoc || fExactMatch)
  888. && IS_ADSPATH_PRESENT(ThisAttrib) ) {
  889. ServerLocType = ThisAttrib->StoreGetType;
  890. ServerLoc = ThisAttrib->ADsPath; // remember this path..
  891. SavedAttrib = ThisAttrib; // remember this attrib.. to del later
  892. } else { // this attrib is useless, free it
  893. if( fExactMatch ) MemFree(ThisAttrib);
  894. }
  895. if( fExactMatch ) fServerDeleted = TRUE;
  896. else fServerExists = TRUE;
  897. }
  898. }
  899. if( !fServerDeleted ) { // never found the requested entry..
  900. MemArrayFree(&Servers, MemFreeFunc); // free up memory
  901. return ERROR_DDS_SERVER_DOES_NOT_EXIST;
  902. }
  903. Err = DhcpDsSetLists // now set the new attrib list
  904. (
  905. /* Reserved */ DDS_RESERVED_DWORD,
  906. /* hStore */ hDhcpRoot,
  907. /* SetParams */ &unused,
  908. /* Servers */ &Servers,
  909. /* Subnets */ NULL,
  910. /* IpAddress */ NULL,
  911. /* Mask */ NULL,
  912. /* Ranges */ NULL,
  913. /* Sites */ NULL,
  914. /* Reservations */ NULL,
  915. /* SuperScopes */ NULL,
  916. /* OptionDescription.. */ NULL,
  917. /* OptionsLocation */ NULL,
  918. /* Options */ NULL,
  919. /* ClassDescription */ NULL,
  920. /* Classes */ NULL
  921. );
  922. MemArrayFree(&Servers, MemFreeFunc); // free allocated memory
  923. if( ERROR_SUCCESS != Err) { // check err for DhcpDsSetLists
  924. if(SavedAttrib) MemFree(SavedAttrib);
  925. return Err;
  926. }
  927. if( fServerExists ) { // still some addr left for this srvr
  928. if( SavedAttrib ) MemFree(SavedAttrib);
  929. return ERROR_SUCCESS;
  930. }
  931. if( SavedAttrib ) MemFree(SavedAttrib);
  932. return Err;
  933. }
  934. //BeginExport(function)
  935. //DOC DhcpDsDelServer removes the requested servername-ipaddress pair from the ds.
  936. //DOC If this is the last ip address for the given servername, then the server
  937. //DOC is also removed from memory. But objects referred by the Server are left in
  938. //DOC the DS as they may also be referred to from else where. This needs to be
  939. //DOC fixed via references being tagged as direct and symbolic -- one causing deletion
  940. //DOC and other not causing any deletion. THIS NEEDS TO BE FIXED.
  941. DWORD
  942. DhcpDsDelServer( // Delete a server from memory
  943. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  944. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  945. IN DWORD Reserved, // must be zero, for future use
  946. IN LPWSTR ServerName, // which server to delete for
  947. IN LPWSTR ReservedPtr, // server location ? future use
  948. IN DWORD IpAddress // the IpAddress to delete..
  949. ) //EndExport(function)
  950. {
  951. DWORD Err, LastErr, ReturnError;
  952. STORE_HANDLE hDhcpServer;
  953. ARRAY Servers;
  954. BOOL fEmpty;
  955. LPWSTR Location;
  956. LPWSTR IsDhcpRoot = NULL;
  957. MemArrayInit(&Servers);
  958. Err = StoreSetSearchOneLevel(
  959. hDhcpC, DDS_RESERVED_DWORD );
  960. AssertRet( Err == NO_ERROR, Err );
  961. Err = StoreBeginSearch(
  962. hDhcpC, DDS_RESERVED_DWORD, DHCP_SEARCH_FILTER );
  963. AssertRet( Err == NO_ERROR, Err );
  964. //
  965. // Look at each dhcp object in container
  966. //
  967. ReturnError = ERROR_DDS_SERVER_DOES_NOT_EXIST;
  968. while( TRUE ) {
  969. Err = StoreSearchGetNext(
  970. hDhcpC, DDS_RESERVED_DWORD, &hDhcpServer );
  971. if( ERROR_DS_INVALID_DN_SYNTAX == Err ) {
  972. //
  973. // This nasty problem is because of an upgrade issue
  974. // in DS where some bad-named objects may exist..
  975. //
  976. Err = NO_ERROR;
  977. continue;
  978. }
  979. if( NO_ERROR != Err ) break;
  980. //
  981. // Attempt to delete reqd server
  982. //
  983. Err = DhcpDsDelServerInternal(
  984. hDhcpC, &hDhcpServer, Reserved, ServerName,
  985. ReservedPtr, IpAddress );
  986. if( ERROR_DDS_SERVER_DOES_NOT_EXIST == Err ) {
  987. StoreCleanupHandle( &hDhcpServer, DDS_RESERVED_DWORD );
  988. continue;
  989. }
  990. if( NO_ERROR != Err ) {
  991. StoreCleanupHandle( &hDhcpServer, DDS_RESERVED_DWORD );
  992. break;
  993. }
  994. ReturnError = NO_ERROR;
  995. //
  996. // If the above succeeded, then check if the container
  997. // has no servers defined -- in this case we can delete
  998. // the container itself
  999. //
  1000. Err = DhcpDsGetLists
  1001. (
  1002. /* Reserved */ DDS_RESERVED_DWORD,
  1003. /* hStore */ &hDhcpServer,
  1004. /* RecursionDepth */ 0xFFFFFFFF,
  1005. /* Servers */ &Servers, // array of PEATTRIB 's
  1006. /* Subnets */ NULL,
  1007. /* IpAddress */ NULL,
  1008. /* Mask */ NULL,
  1009. /* Ranges */ NULL,
  1010. /* Sites */ NULL,
  1011. /* Reservations */ NULL,
  1012. /* SuperScopes */ NULL,
  1013. /* OptionDescription */ NULL,
  1014. /* OptionsLocation */ NULL,
  1015. /* Options */ NULL,
  1016. /* Classes */ NULL
  1017. );
  1018. if( NO_ERROR != Err ) {
  1019. StoreCleanupHandle( &hDhcpServer, DDS_RESERVED_DWORD );
  1020. break;
  1021. }
  1022. fEmpty = (0 == MemArraySize(&Servers));
  1023. MemArrayFree(&Servers, MemFreeFunc);
  1024. Location = CloneString(hDhcpServer.Location);
  1025. StoreCleanupHandle( &hDhcpServer, DDS_RESERVED_DWORD );
  1026. if( NULL == Location ) {
  1027. Err = ERROR_NOT_ENOUGH_MEMORY;
  1028. break;
  1029. }
  1030. IsDhcpRoot = wcsstr( Location, DHCP_ROOT_OBJECT_NAME );
  1031. if( fEmpty && ( IsDhcpRoot == NULL ) )
  1032. Err = StoreDeleteThisObject(
  1033. hDhcpC,
  1034. DDS_RESERVED_DWORD,
  1035. StoreGetAbsoluteOtherServerType,
  1036. Location );
  1037. MemFree( Location );
  1038. if( NO_ERROR != Err ) break;
  1039. }
  1040. if( Err == ERROR_NO_MORE_ITEMS ) Err = NO_ERROR;
  1041. LastErr = StoreEndSearch( hDhcpC, DDS_RESERVED_DWORD );
  1042. //Require( LastErr == NO_ERROR );
  1043. if( NO_ERROR == Err ) Err = ReturnError;
  1044. return Err;
  1045. } // DhcpDsDelServer()
  1046. //BeginExport(function)
  1047. BOOL
  1048. DhcpDsLookupServer( // get info about a server
  1049. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1050. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  1051. IN DWORD Reserved, // must be zero, for future use
  1052. IN LPWSTR LookupServerIP,// Server to lookup IP
  1053. IN LPWSTR HostName // Hostname to lookup
  1054. ) //EndExport(function)
  1055. {
  1056. DWORD Err, Err2, Size, Size2, i, N;
  1057. ARRAY Servers;
  1058. ARRAY_LOCATION Loc;
  1059. PEATTRIB ThisAttrib;
  1060. LPDHCPDS_SERVERS LocalServers;
  1061. LPBYTE Ptr;
  1062. LPWSTR SearchFilter;
  1063. STORE_HANDLE hContainer;
  1064. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  1065. return FALSE;
  1066. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  1067. return FALSE;
  1068. if (( NULL == HostName ) ||
  1069. ( NULL == LookupServerIP )) {
  1070. return FALSE;
  1071. }
  1072. SearchFilter = MakeFilter( LookupServerIP, HostName );
  1073. if ( NULL == SearchFilter ) {
  1074. return FALSE;
  1075. }
  1076. DsAuthPrint(( L"hostname = %ws, IP = %ws, Filter = %ws\n",
  1077. HostName, LookupServerIP, SearchFilter ));
  1078. Err = StoreSetSearchOneLevel( hDhcpC, DDS_RESERVED_DWORD );
  1079. AssertRet( Err == NO_ERROR, Err );
  1080. Err = StoreBeginSearch( hDhcpC, DDS_RESERVED_DWORD, SearchFilter );
  1081. MemFree( SearchFilter );
  1082. AssertRet( Err == NO_ERROR, Err );
  1083. Err = StoreSearchGetNext( hDhcpC, DDS_RESERVED_DWORD, &hContainer );
  1084. StoreEndSearch( hDhcpC, DDS_RESERVED_DWORD );
  1085. return ( NO_ERROR == Err );
  1086. } // DhcpDsLookupServer()
  1087. //BeginExport(function)
  1088. //DOC DhcpDsEnumServers retrieves a bunch of information about each server that
  1089. //DOC has an entry in the Servers attribute of the root object. There are no guarantees
  1090. //DOC on the order..
  1091. //DOC The memory for this is allocated in ONE shot -- so the output can be freed in
  1092. //DOC one shot too.
  1093. //DOC
  1094. DWORD
  1095. DhcpDsEnumServers( // get info abt all existing servers
  1096. IN OUT LPSTORE_HANDLE hDhcpC, // container for dhcp objects
  1097. IN OUT LPSTORE_HANDLE hDhcpRoot, // dhcp root object handle
  1098. IN DWORD Reserved, // must be zero, for future use
  1099. OUT LPDHCPDS_SERVERS *ServersInfo // array of servers
  1100. ) //EndExport(function)
  1101. {
  1102. DWORD Err, Err2, Size, Size2, i, N;
  1103. ARRAY Servers;
  1104. ARRAY_LOCATION Loc;
  1105. PEATTRIB ThisAttrib;
  1106. LPDHCPDS_SERVERS LocalServers;
  1107. LPBYTE Ptr;
  1108. LPWSTR Filter1, Filter2, Filter3;
  1109. if( NULL == hDhcpRoot || NULL == hDhcpC ) // check params
  1110. return ERROR_INVALID_PARAMETER;
  1111. if( NULL == hDhcpRoot->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  1112. return ERROR_INVALID_PARAMETER;
  1113. if( 0 != Reserved || NULL == ServersInfo )
  1114. return ERROR_INVALID_PARAMETER;
  1115. *ServersInfo = NULL; i = N = Size = Size2 = 0;
  1116. Err = MemArrayInit(&Servers); // cant fail
  1117. //= require ERROR_SUCCESS == Err
  1118. DsAuthPrint(( L"DhcpDsEnumServers \n" ));
  1119. Err = GetListOfAllServersMatchingFilter( hDhcpC, &Servers,
  1120. DHCP_SEARCH_FILTER );
  1121. if( ERROR_SUCCESS != Err ) return Err;
  1122. Size = Size2 = 0;
  1123. for( // walk thru list of servers
  1124. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  1125. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  1126. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  1127. ) {
  1128. //= require ERROR_SUCCESS == Err
  1129. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  1130. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1131. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  1132. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  1133. continue; //= ds inconsistent
  1134. }
  1135. Size2 = sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1));
  1136. if( IS_ADSPATH_PRESENT(ThisAttrib) ) { // if ADsPath there, account for it
  1137. Size2 += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->ADsPath));
  1138. }
  1139. Size += Size2; // keep track of total mem reqd
  1140. i ++;
  1141. }
  1142. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVERS), ALIGN_WORST);
  1143. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVER)*i, ALIGN_WORST);
  1144. Ptr = MemAlloc(Size); // allocate memory
  1145. if( NULL == Ptr ) {
  1146. MemArrayFree(&Servers, MemFreeFunc ); // free allocated memory
  1147. return ERROR_NOT_ENOUGH_MEMORY;
  1148. }
  1149. LocalServers = (LPDHCPDS_SERVERS)Ptr;
  1150. LocalServers->NumElements = i;
  1151. LocalServers->Flags = 0;
  1152. Size = 0; // start from offset 0
  1153. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVERS), ALIGN_WORST);
  1154. LocalServers->Servers = (LPDHCPDS_SERVER)(Size + Ptr);
  1155. Size += ROUND_UP_COUNT(sizeof(DHCPDS_SERVER)*i, ALIGN_WORST);
  1156. i = Size2 = 0;
  1157. for( // copy list of servers
  1158. Err = MemArrayInitLoc(&Servers, &Loc) // initialize
  1159. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  1160. Err = MemArrayNextLoc(&Servers, &Loc) // skip to next element
  1161. ) {
  1162. //= require ERROR_SUCCESS == Err
  1163. Err = MemArrayGetElement(&Servers, &Loc, &ThisAttrib);
  1164. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1165. if( !IS_STRING1_PRESENT(ThisAttrib) || // no name for this server
  1166. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no address for this server
  1167. continue; //= ds inconsistent
  1168. }
  1169. LocalServers->Servers[i].Version =0; // version is always zero in this build
  1170. LocalServers->Servers[i].State=0;
  1171. LocalServers->Servers[i].ServerName = (LPWSTR)(Size + Ptr);
  1172. wcscpy((LPWSTR)(Size+Ptr), ThisAttrib->String1);
  1173. Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->String1));
  1174. LocalServers->Servers[i].ServerAddress = ThisAttrib->Address1;
  1175. if( IS_FLAGS1_PRESENT(ThisAttrib) ) { // State present
  1176. LocalServers->Servers[i].Flags = ThisAttrib->Flags1;
  1177. } else {
  1178. LocalServers->Servers[i].Flags = 0; // if no flags present, use zero
  1179. }
  1180. if( IS_ADSPATH_PRESENT(ThisAttrib) ) { // if ADsPath there, copy it too
  1181. LocalServers->Servers[i].DsLocType = ThisAttrib->StoreGetType;
  1182. LocalServers->Servers[i].DsLocation = (LPWSTR)(Size + Ptr);
  1183. wcscpy((LPWSTR)(Size + Ptr), ThisAttrib->ADsPath);
  1184. Size += sizeof(WCHAR)*(1 + wcslen(ThisAttrib->ADsPath));
  1185. } else { // no ADsPath present
  1186. LocalServers->Servers[i].DsLocType = 0;
  1187. LocalServers->Servers[i].DsLocation = NULL;
  1188. }
  1189. i ++;
  1190. }
  1191. *ServersInfo = LocalServers;
  1192. MemArrayFree(&Servers, MemFreeFunc ); // free allocated memory
  1193. return ERROR_SUCCESS;
  1194. } // DhcpDsEnumServers()
  1195. //BeginExport(function)
  1196. //DOC DhcpDsSetSScope modifies the superscope that a subnet belongs to.
  1197. //DOC The function tries to set the superscope of the subnet referred by
  1198. //DOC address IpAddress to SScopeName. It does not matter if the superscope
  1199. //DOC by that name does not exist, it is automatically created.
  1200. //DOC If the subnet already had a superscope, then the behaviour depends on
  1201. //DOC the flag ChangeSScope. If this is TRUE, it sets the new superscopes.
  1202. //DOC If the flag is FALSE, it returns ERROR_DDS_SUBNET_HAS_DIFF_SSCOPE.
  1203. //DOC This flag is ignored if the subnet does not have a superscope already.
  1204. //DOC If SScopeName is NULL, the function removes the subnet from any superscope
  1205. //DOC if it belonged to one before.
  1206. //DOC If the specified subnet does not exist, it returns ERROR_DDS_SUBNET_NOT_PRESENT.
  1207. DWORD
  1208. DhcpDsSetSScope( // change superscope of subnet
  1209. IN OUT LPSTORE_HANDLE hDhcpC, // container where dhcp objects are stored
  1210. IN OUT LPSTORE_HANDLE hServer, // the server object referred
  1211. IN DWORD Reserved, // must be zero, for future use
  1212. IN DWORD IpAddress, // subnet address to use
  1213. IN LPWSTR SScopeName, // sscope it must now be in
  1214. IN BOOL ChangeSScope // if it already has a SScope, change it?
  1215. ) //EndExport(function)
  1216. {
  1217. DWORD Err, unused;
  1218. ARRAY Subnets;
  1219. ARRAY_LOCATION Loc;
  1220. PEATTRIB ThisAttrib;
  1221. BOOL SubnetPresent;
  1222. if( 0 != Reserved ) // check params
  1223. return ERROR_INVALID_PARAMETER;
  1224. if( NULL == hDhcpC || NULL == hDhcpC->ADSIHandle )
  1225. return ERROR_INVALID_PARAMETER;
  1226. if( NULL == hServer || NULL == hServer->ADSIHandle )
  1227. return ERROR_INVALID_PARAMETER;
  1228. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1229. Err = DhcpDsGetLists // fetch subnet array
  1230. (
  1231. /* Reserved */ DDS_RESERVED_DWORD,
  1232. /* hStore */ hServer,
  1233. /* RecursionDepth */ 0xFFFFFFFF,
  1234. /* Servers */ NULL,
  1235. /* Subnets */ &Subnets,
  1236. /* IpAddress */ NULL,
  1237. /* Mask */ NULL,
  1238. /* Ranges */ NULL,
  1239. /* Sites */ NULL,
  1240. /* Reservations */ NULL,
  1241. /* SuperScopes */ NULL,
  1242. /* OptionDescription */ NULL,
  1243. /* OptionsLocation */ NULL,
  1244. /* Options */ NULL,
  1245. /* Classes */ NULL
  1246. );
  1247. if( ERROR_SUCCESS != Err ) return Err; // shouldn't really fail
  1248. SubnetPresent = FALSE;
  1249. for( // search for specified subnet
  1250. Err = MemArrayInitLoc(&Subnets, &Loc) // init
  1251. ; ERROR_FILE_NOT_FOUND != Err ; // 'til v run out of elts
  1252. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next elt
  1253. ) {
  1254. //= require ERROR_SUCCESS == Err
  1255. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1256. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1257. if( !IS_STRING1_PRESENT(ThisAttrib) || // no subnet name
  1258. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no subnet address
  1259. continue; //= ds inconsistent
  1260. }
  1261. if( ThisAttrib->Address1 != IpAddress ) { // not this subnet we're looking for
  1262. continue;
  1263. }
  1264. SubnetPresent = TRUE; // found the subnet we're intersted in
  1265. break;
  1266. }
  1267. if( !SubnetPresent ) { // did not even find the subnet?
  1268. MemArrayFree(&Subnets, MemFreeFunc); // free up memory taken
  1269. return ERROR_DDS_SUBNET_NOT_PRESENT;
  1270. }
  1271. if( NULL == SScopeName ) { // we're trying to remove from sscope
  1272. if( !IS_STRING3_PRESENT(ThisAttrib) ) { // does not belong to any sscope ?
  1273. MemArrayFree(&Subnets, MemFreeFunc);
  1274. return ERROR_SUCCESS; // return as no change reqd
  1275. }
  1276. STRING3_ABSENT(ThisAttrib); // remove SScope..
  1277. } else {
  1278. if( IS_STRING3_PRESENT(ThisAttrib) ) { // sscope present.. trying to change it
  1279. if( FALSE == ChangeSScope ) { // we were not asked to do this
  1280. MemArrayFree(&Subnets, MemFreeFunc);
  1281. return ERROR_DDS_SUBNET_HAS_DIFF_SSCOPE;
  1282. }
  1283. }
  1284. STRING3_PRESENT(ThisAttrib);
  1285. ThisAttrib->String3 = SScopeName; // set the new SScope for this
  1286. }
  1287. Err = DhcpDsSetLists // now write back the new info onto the DS
  1288. (
  1289. /* Reserved */ DDS_RESERVED_DWORD,
  1290. /* hStore */ hServer,
  1291. /* SetParams */ &unused,
  1292. /* Servers */ NULL,
  1293. /* Subnets */ &Subnets,
  1294. /* IpAddress */ NULL,
  1295. /* Mask */ NULL,
  1296. /* Ranges */ NULL,
  1297. /* Sites */ NULL,
  1298. /* Reservations */ NULL,
  1299. /* SuperScopes */ NULL,
  1300. /* OptionDescripti.. */ NULL,
  1301. /* OptionsLocation */ NULL,
  1302. /* Options */ NULL,
  1303. /* ClassDescriptio.. */ NULL,
  1304. /* Classes */ NULL
  1305. );
  1306. MemArrayFree(&Subnets, MemFreeFunc);
  1307. return Err;
  1308. }
  1309. //BeginExport(function)
  1310. //DOC DhcpDsDelSScope deletes the superscope and removes all elements
  1311. //DOC that belong to that superscope in one shot. There is no error if the
  1312. //DOC superscope does not exist.
  1313. DWORD
  1314. DhcpDsDelSScope( // delete superscope off DS
  1315. IN OUT LPSTORE_HANDLE hDhcpC, // container where dhcp objects are stored
  1316. IN OUT LPSTORE_HANDLE hServer, // the server object referred
  1317. IN DWORD Reserved, // must be zero, for future use
  1318. IN LPWSTR SScopeName // sscope to delete
  1319. ) //EndExport(function)
  1320. {
  1321. DWORD Err, unused;
  1322. ARRAY Subnets;
  1323. ARRAY_LOCATION Loc;
  1324. PEATTRIB ThisAttrib;
  1325. BOOL AnythingChanged;
  1326. if( 0 != Reserved || NULL == SScopeName ) // check params
  1327. return ERROR_INVALID_PARAMETER;
  1328. if( NULL == hDhcpC || NULL == hDhcpC->ADSIHandle )
  1329. return ERROR_INVALID_PARAMETER;
  1330. if( NULL == hServer || NULL == hServer->ADSIHandle )
  1331. return ERROR_INVALID_PARAMETER;
  1332. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1333. Err = DhcpDsGetLists // fetch subnet array
  1334. (
  1335. /* Reserved */ DDS_RESERVED_DWORD,
  1336. /* hStore */ hServer,
  1337. /* RecursionDepth */ 0xFFFFFFFF,
  1338. /* Servers */ NULL,
  1339. /* Subnets */ &Subnets,
  1340. /* IpAddress */ NULL,
  1341. /* Mask */ NULL,
  1342. /* Ranges */ NULL,
  1343. /* Sites */ NULL,
  1344. /* Reservations */ NULL,
  1345. /* SuperScopes */ NULL,
  1346. /* OptionDescription */ NULL,
  1347. /* OptionsLocation */ NULL,
  1348. /* Options */ NULL,
  1349. /* Classes */ NULL
  1350. );
  1351. if( ERROR_SUCCESS != Err ) return Err; // shouldn't really fail
  1352. AnythingChanged = FALSE;
  1353. for( // search for specified SScope
  1354. Err = MemArrayInitLoc(&Subnets, &Loc) // init
  1355. ; ERROR_FILE_NOT_FOUND != Err ; // 'til v run out of elts
  1356. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next elt
  1357. ) {
  1358. //= require ERROR_SUCCESS == Err
  1359. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1360. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1361. if( !IS_STRING1_PRESENT(ThisAttrib) || // no subnet name
  1362. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no subnet address
  1363. continue; //= ds inconsistent
  1364. }
  1365. if( !IS_STRING3_PRESENT(ThisAttrib) ) { // this subnet does not have a sscope anyways
  1366. continue;
  1367. }
  1368. if( 0 != wcscmp(ThisAttrib->String3, SScopeName) ) {
  1369. continue; // not the same superscope
  1370. }
  1371. STRING3_ABSENT(ThisAttrib); // kill the superscope
  1372. AnythingChanged = TRUE;
  1373. }
  1374. if( !AnythingChanged ) {
  1375. Err = ERROR_SUCCESS; // nothing more to do now..
  1376. } else {
  1377. Err = DhcpDsSetLists // now write back the new info onto the DS
  1378. (
  1379. /* Reserved */ DDS_RESERVED_DWORD,
  1380. /* hStore */ hServer,
  1381. /* SetParams */ &unused,
  1382. /* Servers */ NULL,
  1383. /* Subnets */ &Subnets,
  1384. /* IpAddress */ NULL,
  1385. /* Mask */ NULL,
  1386. /* Ranges */ NULL,
  1387. /* Sites */ NULL,
  1388. /* Reservations */ NULL,
  1389. /* SuperScopes */ NULL,
  1390. /* OptionDescripti..*/ NULL,
  1391. /* OptionsLocation */ NULL,
  1392. /* Options */ NULL,
  1393. /* ClassDescriptio..*/ NULL,
  1394. /* Classes */ NULL
  1395. );
  1396. }
  1397. MemArrayFree(&Subnets, MemFreeFunc);
  1398. return Err;
  1399. }
  1400. //BeginExport(function)
  1401. //DOC DhcpDsGetSScopeInfo retrieves the SuperScope table for the server of interest.
  1402. //DOC The table itself is allocated in one blob, so it can be freed lateron.
  1403. //DOC The SuperScopeNumber is garbage (always zero) and the NextInSuperScope reflects
  1404. //DOC the order in the DS which may/maynot be the same in the DHCP server.
  1405. //DOC SuperScopeName is NULL in for subnets that done have a sscope.
  1406. DWORD
  1407. DhcpDsGetSScopeInfo( // get superscope table from ds
  1408. IN OUT LPSTORE_HANDLE hDhcpC, // container where dhcp objects are stored
  1409. IN OUT LPSTORE_HANDLE hServer, // the server object referred
  1410. IN DWORD Reserved, // must be zero, for future use
  1411. OUT LPDHCP_SUPER_SCOPE_TABLE *SScopeTbl // allocated by this func in one blob
  1412. ) //EndExport(function)
  1413. {
  1414. DWORD Err, unused, Size, Size2, i;
  1415. DWORD Index, nSubnets;
  1416. ARRAY Subnets;
  1417. ARRAY_LOCATION Loc;
  1418. PEATTRIB ThisAttrib;
  1419. LPDHCP_SUPER_SCOPE_TABLE LocalTbl;
  1420. LPBYTE Ptr;
  1421. if( 0 != Reserved ) // check params
  1422. return ERROR_INVALID_PARAMETER;
  1423. if( NULL == hDhcpC || NULL == hDhcpC->ADSIHandle )
  1424. return ERROR_INVALID_PARAMETER;
  1425. if( NULL == hServer || NULL == hServer->ADSIHandle )
  1426. return ERROR_INVALID_PARAMETER;
  1427. if( NULL == SScopeTbl ) return ERROR_INVALID_PARAMETER;
  1428. *SScopeTbl = NULL;
  1429. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1430. Err = DhcpDsGetLists // fetch subnet array
  1431. (
  1432. /* Reserved */ DDS_RESERVED_DWORD,
  1433. /* hStore */ hServer,
  1434. /* RecursionDepth */ 0xFFFFFFFF,
  1435. /* Servers */ NULL,
  1436. /* Subnets */ &Subnets,
  1437. /* IpAddress */ NULL,
  1438. /* Mask */ NULL,
  1439. /* Ranges */ NULL,
  1440. /* Sites */ NULL,
  1441. /* Reservations */ NULL,
  1442. /* SuperScopes */ NULL,
  1443. /* OptionDescription */ NULL,
  1444. /* OptionsLocation */ NULL,
  1445. /* Options */ NULL,
  1446. /* Classes */ NULL
  1447. );
  1448. if( ERROR_SUCCESS != Err ) return Err; // shouldn't really fail
  1449. Size = Size2 = i = 0;
  1450. for( // search for specified SScope
  1451. Err = MemArrayInitLoc(&Subnets, &Loc) // init
  1452. ; ERROR_FILE_NOT_FOUND != Err ; // 'til v run out of elts
  1453. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next elt
  1454. ) {
  1455. //= require ERROR_SUCCESS == Err
  1456. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1457. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1458. if( !IS_STRING1_PRESENT(ThisAttrib) || // no subnet name
  1459. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no subnet address
  1460. continue; //= ds inconsistent
  1461. }
  1462. if( IS_STRING3_PRESENT(ThisAttrib) ) { // make space for sscope name
  1463. Size += sizeof(WCHAR)*(1+wcslen(ThisAttrib->String3));
  1464. }
  1465. i ++; // keep right count of # of subnets
  1466. }
  1467. Size += ROUND_UP_COUNT(sizeof(DHCP_SUPER_SCOPE_TABLE),ALIGN_WORST);
  1468. Size += ROUND_UP_COUNT(i*sizeof(DHCP_SUPER_SCOPE_TABLE_ENTRY), ALIGN_WORST);
  1469. Ptr = MemAlloc(Size); // allocate the blob
  1470. if( NULL == Ptr ) {
  1471. MemArrayFree(&Subnets, MemFreeFunc);
  1472. return ERROR_NOT_ENOUGH_MEMORY;
  1473. }
  1474. LocalTbl = (LPDHCP_SUPER_SCOPE_TABLE)Ptr;
  1475. Size = ROUND_UP_COUNT(sizeof(DHCP_SUPER_SCOPE_TABLE),ALIGN_WORST);
  1476. LocalTbl->cEntries = i;
  1477. if( i ) LocalTbl->pEntries = (LPDHCP_SUPER_SCOPE_TABLE_ENTRY)(Size+Ptr);
  1478. else LocalTbl->pEntries = NULL;
  1479. Size += ROUND_UP_COUNT(i*sizeof(DHCP_SUPER_SCOPE_TABLE_ENTRY), ALIGN_WORST);
  1480. i = 0;
  1481. for( // search for specified SScope
  1482. Err = MemArrayInitLoc(&Subnets, &Loc) // init
  1483. ; ERROR_FILE_NOT_FOUND != Err ; // 'til v run out of elts
  1484. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next elt
  1485. ) {
  1486. //= require ERROR_SUCCESS == Err
  1487. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1488. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1489. if( !IS_STRING1_PRESENT(ThisAttrib) || // no subnet name
  1490. !IS_ADDRESS1_PRESENT(ThisAttrib) ) { // no subnet address
  1491. continue; //= ds inconsistent
  1492. }
  1493. LocalTbl->pEntries[i].SubnetAddress = ThisAttrib->Address1;
  1494. LocalTbl->pEntries[i].SuperScopeNumber = 0;
  1495. LocalTbl->pEntries[i].NextInSuperScope = 0;
  1496. LocalTbl->pEntries[i].SuperScopeName = NULL;
  1497. if( !IS_STRING3_PRESENT(ThisAttrib) ) { // no sscope, nothin to do
  1498. i ++;
  1499. continue;
  1500. }
  1501. LocalTbl->pEntries[i].SuperScopeName = (LPWSTR)(Size + Ptr);
  1502. wcscpy((LPWSTR)(Size+Ptr), ThisAttrib->String3);
  1503. Size += sizeof(WCHAR)*(1+wcslen(ThisAttrib->String3));
  1504. i ++; // keep right count of # of subnets
  1505. }
  1506. MemArrayFree(&Subnets, MemFreeFunc);
  1507. nSubnets = i;
  1508. for( Index = 0; Index < nSubnets ; Index ++){ // calculate for each Index, next value
  1509. if( NULL == LocalTbl->pEntries[Index].SuperScopeName)
  1510. continue; // skip subnets that dont have sscope
  1511. LocalTbl->pEntries[Index].NextInSuperScope = Index;
  1512. for( i = 0; i < Index ; i ++ ) { // first set it to just prev subnet
  1513. if( NULL == LocalTbl->pEntries[i].SuperScopeName)
  1514. continue;
  1515. if( 0 == wcscmp(
  1516. LocalTbl->pEntries[Index].SuperScopeName,
  1517. LocalTbl->pEntries[i].SuperScopeName)
  1518. ) { // both subnets have same superscope
  1519. LocalTbl->pEntries[Index].NextInSuperScope = i;
  1520. // set next as last match in array before position Index
  1521. }
  1522. }
  1523. for( i = Index + 1; i < nSubnets; i ++ ) {// check to see if any real next exists
  1524. if( NULL == LocalTbl->pEntries[i].SuperScopeName)
  1525. continue;
  1526. if( 0 == wcscmp(
  1527. LocalTbl->pEntries[Index].SuperScopeName,
  1528. LocalTbl->pEntries[i].SuperScopeName)
  1529. ) { // both subnets have same superscope
  1530. LocalTbl->pEntries[Index].NextInSuperScope = i;
  1531. break;
  1532. }
  1533. }
  1534. }
  1535. *SScopeTbl = LocalTbl; // done.
  1536. return ERROR_SUCCESS;
  1537. }
  1538. //BeginExport(function)
  1539. //DOC DhcpDsServerAddSubnet tries to add a subnet to a given server. Each subnet
  1540. //DOC address has to be unique, but the other parameters dont have to.
  1541. //DOC The subnet address being added should not belong to any other subnet.
  1542. //DOC In this case it returns error ERROR_DDS_SUBNET_EXISTS
  1543. DWORD
  1544. DhcpDsServerAddSubnet( // create a new subnet
  1545. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  1546. IN OUT LPSTORE_HANDLE hServer, // server object
  1547. IN DWORD Reserved, // for future use, reserved
  1548. IN LPWSTR ServerName, // name of server we're using
  1549. IN LPDHCP_SUBNET_INFO Info // info on new subnet to create
  1550. ) //EndExport(function)
  1551. {
  1552. DWORD Err, Err2, unused, i;
  1553. DWORD Index, nSubnets;
  1554. ARRAY Subnets;
  1555. ARRAY_LOCATION Loc;
  1556. PEATTRIB ThisAttrib;
  1557. EATTRIB Dummy;
  1558. LPWSTR SubnetObjName;
  1559. if( 0 != Reserved ) // check params
  1560. return ERROR_INVALID_PARAMETER;
  1561. if( NULL == hDhcpC || NULL == hDhcpC->ADSIHandle )
  1562. return ERROR_INVALID_PARAMETER;
  1563. if( NULL == hServer || NULL == hServer->ADSIHandle )
  1564. return ERROR_INVALID_PARAMETER;
  1565. if( NULL == Info || NULL == ServerName )
  1566. return ERROR_INVALID_PARAMETER;
  1567. if( Info->SubnetAddress != (Info->SubnetAddress & Info->SubnetMask ) )
  1568. return ERROR_INVALID_PARAMETER;
  1569. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1570. Err = DhcpDsGetLists // fetch subnet array
  1571. (
  1572. /* Reserved */ DDS_RESERVED_DWORD,
  1573. /* hStore */ hServer,
  1574. /* RecursionDepth */ 0xFFFFFFFF,
  1575. /* Servers */ NULL,
  1576. /* Subnets */ &Subnets,
  1577. /* IpAddress */ NULL,
  1578. /* Mask */ NULL,
  1579. /* Ranges */ NULL,
  1580. /* Sites */ NULL,
  1581. /* Reservations */ NULL,
  1582. /* SuperScopes */ NULL,
  1583. /* OptionDescription */ NULL,
  1584. /* OptionsLocation */ NULL,
  1585. /* Options */ NULL,
  1586. /* Classes */ NULL
  1587. );
  1588. if( ERROR_SUCCESS != Err ) return Err; // shouldn't really fail
  1589. for( // search for specified SScope
  1590. Err = MemArrayInitLoc(&Subnets, &Loc) // init
  1591. ; ERROR_FILE_NOT_FOUND != Err ; // 'til v run out of elts
  1592. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next elt
  1593. ) {
  1594. //= require ERROR_SUCCESS == Err
  1595. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1596. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1597. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  1598. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  1599. continue; //= ds inconsistent
  1600. }
  1601. if( (Info->SubnetAddress & ThisAttrib->Address2 ) == ThisAttrib->Address1 ) {
  1602. return ERROR_DDS_SUBNET_EXISTS; // Info belongs to this subnet
  1603. }
  1604. if( Info->SubnetAddress == (ThisAttrib->Address1 & Info->SubnetMask) ) {
  1605. return ERROR_DDS_SUBNET_EXISTS; // Info subsumes some other subnet
  1606. }
  1607. }
  1608. SubnetObjName = MakeSubnetLocation(ServerName, Info->SubnetAddress);
  1609. if( NULL == SubnetObjName ) { // not enough memory?
  1610. MemArrayFree(&Subnets, MemFreeFunc);
  1611. return ERROR_NOT_ENOUGH_MEMORY;
  1612. }
  1613. Err = CreateSubnetObject // try creating the subnet obj 1st
  1614. (
  1615. /* hDhcpC */ hDhcpC, // create obj here..
  1616. /* SubnetName */ SubnetObjName
  1617. );
  1618. if( ERROR_SUCCESS != Err ) { // could not create obj, dont proceed
  1619. MemArrayFree(&Subnets, MemFreeFunc);
  1620. MemFree(SubnetObjName);
  1621. return Err;
  1622. }
  1623. NothingPresent(&Dummy); // prepare info for new subnet
  1624. ADDRESS1_PRESENT(&Dummy); // subnet address
  1625. Dummy.Address1 = Info->SubnetAddress;
  1626. ADDRESS2_PRESENT(&Dummy); // subnet mask
  1627. Dummy.Address2 = Info->SubnetMask;
  1628. FLAGS1_PRESENT(&Dummy); // subnet state
  1629. Dummy.Flags1 = Info->SubnetState;
  1630. if( Info->SubnetName ) { // subnet name
  1631. STRING1_PRESENT(&Dummy);
  1632. Dummy.String1 = Info->SubnetName;
  1633. }
  1634. if( Info->SubnetComment ) { // subnet comment
  1635. STRING2_PRESENT(&Dummy);
  1636. Dummy.String2 = Info->SubnetComment;
  1637. }
  1638. ADSPATH_PRESENT(&Dummy); // subnet obj location
  1639. STOREGETTYPE_PRESENT(&Dummy);
  1640. Dummy.ADsPath = SubnetObjName;
  1641. Dummy.StoreGetType = StoreGetChildType;
  1642. Err = MemArrayAddElement(&Subnets, &Dummy); // add new attrib at end
  1643. if( ERROR_SUCCESS != Err ) { // add failed for some reason
  1644. MemFree(SubnetObjName);
  1645. MemArrayFree(&Subnets, MemFreeFunc); // cleanup any mem used
  1646. return Err;
  1647. }
  1648. Err = DhcpDsSetLists // write back new info onto DS
  1649. (
  1650. /* Reserved */ DDS_RESERVED_DWORD,
  1651. /* hStore */ hServer,
  1652. /* SetParams */ &unused,
  1653. /* Servers */ NULL,
  1654. /* Subnets */ &Subnets,
  1655. /* IpAddress */ NULL,
  1656. /* Mask */ NULL,
  1657. /* Ranges */ NULL,
  1658. /* Sites */ NULL,
  1659. /* Reservations */ NULL,
  1660. /* SuperScopes */ NULL,
  1661. /* OptionDescripti.. */ NULL,
  1662. /* OptionsLocation */ NULL,
  1663. /* Options */ NULL,
  1664. /* ClassDescriptio.. */ NULL,
  1665. /* Classes */ NULL
  1666. );
  1667. MemFree(SubnetObjName);
  1668. Err2 = MemArrayLastLoc(&Subnets, &Loc); //= require ERROR_SUCCESS == Err
  1669. Err2 = MemArrayDelElement(&Subnets, &Loc, &ThisAttrib);
  1670. MemArrayFree(&Subnets, MemFreeFunc);
  1671. return Err;
  1672. }
  1673. //BeginExport(function)
  1674. //DOC DhcpDsServerDelSubnet removes a subnet from a given server. It removes not
  1675. //DOC just the subnet, but also all dependent objects like reservations etc.
  1676. //DOC This fn returns ERROR_DDS_SUBNET_NOT_PRESENT if the subnet is not found.
  1677. DWORD
  1678. DhcpDsServerDelSubnet( // Delete the subnet
  1679. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create obj
  1680. IN LPSTORE_HANDLE hServer, // server obj
  1681. IN DWORD Reserved, // for future use, must be zero
  1682. IN LPWSTR ServerName, // name of dhcp server 2 del off
  1683. IN DWORD IpAddress // ip address of subnet to del
  1684. ) //EndExport(function)
  1685. {
  1686. DWORD Err, Err2, unused;
  1687. ARRAY Subnets;
  1688. ARRAY_LOCATION Loc;
  1689. PEATTRIB ThisAttrib;
  1690. BOOL fSubnetExists;
  1691. BOOL fSubnetDeleted;
  1692. LPWSTR SubnetCNName;
  1693. LPWSTR SubnetLoc;
  1694. DWORD SubnetLocType;
  1695. if( NULL == hServer || NULL == hDhcpC ) // check params
  1696. return ERROR_INVALID_PARAMETER;
  1697. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  1698. return ERROR_INVALID_PARAMETER;
  1699. if( NULL == ServerName || 0 != Reserved )
  1700. return ERROR_INVALID_PARAMETER;
  1701. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1702. Err = DhcpDsGetLists // get list of subnets
  1703. (
  1704. /* Reserved */ DDS_RESERVED_DWORD,
  1705. /* hStore */ hServer,
  1706. /* RecursionDepth */ 0xFFFFFFFF,
  1707. /* Servers */ NULL,
  1708. /* Subnets */ &Subnets, // array of PEATTRIB 's
  1709. /* IpAddress */ NULL,
  1710. /* Mask */ NULL,
  1711. /* Ranges */ NULL,
  1712. /* Sites */ NULL,
  1713. /* Reservations */ NULL,
  1714. /* SuperScopes */ NULL,
  1715. /* OptionDescription */ NULL,
  1716. /* OptionsLocation */ NULL,
  1717. /* Options */ NULL,
  1718. /* Classes */ NULL
  1719. );
  1720. if( ERROR_SUCCESS != Err ) return Err;
  1721. fSubnetExists = fSubnetDeleted = FALSE;
  1722. for( // search list of subnets
  1723. Err = MemArrayInitLoc(&Subnets, &Loc) // initialize
  1724. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  1725. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next element
  1726. ) {
  1727. //= require ERROR_SUCCESS == Err
  1728. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1729. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1730. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  1731. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  1732. continue; //= ds inconsistent
  1733. }
  1734. if( ThisAttrib->Address1 == IpAddress ) { // matching address?
  1735. fSubnetExists = TRUE;
  1736. Err2 = MemArrayDelElement(&Subnets, &Loc, &ThisAttrib);
  1737. //= ERROR_SUCCESS == Err2 && NULL != ThisAttrib
  1738. break;
  1739. }
  1740. }
  1741. if( !fSubnetExists ) { // no matching subnet found
  1742. MemArrayFree(&Subnets, MemFreeFunc);
  1743. return ERROR_DDS_SUBNET_NOT_PRESENT;
  1744. }
  1745. Err = DhcpDsSetLists // now set the new attrib list
  1746. (
  1747. /* Reserved */ DDS_RESERVED_DWORD,
  1748. /* hStore */ hServer,
  1749. /* SetParams */ &unused,
  1750. /* Servers */ NULL,
  1751. /* Subnets */ &Subnets,
  1752. /* IpAddress */ NULL,
  1753. /* Mask */ NULL,
  1754. /* Ranges */ NULL,
  1755. /* Sites */ NULL,
  1756. /* Reservations */ NULL,
  1757. /* SuperScopes */ NULL,
  1758. /* OptionDescription.. */ NULL,
  1759. /* OptionsLocation */ NULL,
  1760. /* Options */ NULL,
  1761. /* ClassDescription */ NULL,
  1762. /* Classes */ NULL
  1763. );
  1764. MemArrayFree(&Subnets, MemFreeFunc); // free allocated memory
  1765. if( ERROR_SUCCESS != Err) { // check err for DhcpDsSetLists
  1766. MemFree(ThisAttrib);
  1767. return Err;
  1768. }
  1769. if( IS_ADSPATH_PRESENT(ThisAttrib) ) { // remember the location to delete
  1770. SubnetLocType = ThisAttrib->StoreGetType;
  1771. SubnetLoc = ThisAttrib->ADsPath;
  1772. } else {
  1773. SubnetLoc = NULL;
  1774. }
  1775. if( NULL == SubnetLoc ) { // Dont know location
  1776. SubnetCNName = MakeSubnetLocation(ServerName,IpAddress);
  1777. SubnetLoc = SubnetCNName; // set name for subnet obj
  1778. SubnetLocType = StoreGetChildType; // assume located in DhcpC container
  1779. } else {
  1780. SubnetCNName = NULL; // Did not allocate subnet name
  1781. }
  1782. if( NULL == SubnetLoc ) { // MakeSubnetLocation failed
  1783. Err = ERROR_NOT_ENOUGH_MEMORY;
  1784. } else { // lets try to delete the subnet
  1785. Err = ServerDeleteSubnet // delete the dhcp subnet object
  1786. (
  1787. /* hDhcpC */ hDhcpC,
  1788. /* ServerName */ ServerName,
  1789. /* hServer */ hServer,
  1790. /* ADsPath */ SubnetLoc,
  1791. /* StoreGetType */ SubnetLocType
  1792. );
  1793. }
  1794. if( SubnetCNName ) MemFree(SubnetCNName); // if we allocated mem, free it
  1795. MemFree(ThisAttrib); // lonely attrib needs to be freed
  1796. return Err;
  1797. }
  1798. //BeginExport(function)
  1799. //DOC DhcpDsServerModifySubnet changes the subnet name, comment, state, mask
  1800. //DOC fields of the subnet. Actually, currently, the mask should probably not
  1801. //DOC be changed, as no checks are performed in this case. The address cannot
  1802. //DOC be changed.. If the subnet is not present, the error returned is
  1803. //DOC ERROR_DDS_SUBNET_NOT_PRESENT
  1804. DWORD
  1805. DhcpDsServerModifySubnet( // modify subnet info
  1806. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  1807. IN OUT LPSTORE_HANDLE hServer, // server object
  1808. IN DWORD Reserved, // for future use, reserved
  1809. IN LPWSTR ServerName, // name of server we're using
  1810. IN LPDHCP_SUBNET_INFO Info // info on new subnet to create
  1811. ) //EndExport(function)
  1812. {
  1813. DWORD Err, Err2, unused;
  1814. ARRAY Subnets;
  1815. ARRAY_LOCATION Loc;
  1816. PEATTRIB ThisAttrib;
  1817. BOOL fSubnetExists, fSubnetDeleted;
  1818. if( NULL == hDhcpC ) // check params
  1819. return ERROR_INVALID_PARAMETER;
  1820. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  1821. return ERROR_INVALID_PARAMETER;
  1822. if( NULL == ServerName || 0 != Reserved )
  1823. return ERROR_INVALID_PARAMETER;
  1824. if( NULL == Info )
  1825. return ERROR_INVALID_PARAMETER;
  1826. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1827. Err = DhcpDsGetLists // get list of subnets
  1828. (
  1829. /* Reserved */ DDS_RESERVED_DWORD,
  1830. /* hStore */ hServer,
  1831. /* RecursionDepth */ 0xFFFFFFFF,
  1832. /* Servers */ NULL,
  1833. /* Subnets */ &Subnets, // array of PEATTRIB 's
  1834. /* IpAddress */ NULL,
  1835. /* Mask */ NULL,
  1836. /* Ranges */ NULL,
  1837. /* Sites */ NULL,
  1838. /* Reservations */ NULL,
  1839. /* SuperScopes */ NULL,
  1840. /* OptionDescription */ NULL,
  1841. /* OptionsLocation */ NULL,
  1842. /* Options */ NULL,
  1843. /* Classes */ NULL
  1844. );
  1845. if( ERROR_SUCCESS != Err ) return Err;
  1846. fSubnetExists = fSubnetDeleted = FALSE;
  1847. for( // search list of subnets
  1848. Err = MemArrayInitLoc(&Subnets, &Loc) // initialize
  1849. ; ERROR_FILE_NOT_FOUND != Err ; // until we run out of elts
  1850. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next element
  1851. ) {
  1852. //= require ERROR_SUCCESS == Err
  1853. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1854. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  1855. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  1856. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  1857. continue; //= ds inconsistent
  1858. }
  1859. if( ThisAttrib->Address1 == Info->SubnetAddress ) {
  1860. fSubnetExists = TRUE; // matching address?
  1861. break;
  1862. }
  1863. }
  1864. if( !fSubnetExists ) { // no matching subnet found
  1865. MemArrayFree(&Subnets, MemFreeFunc);
  1866. return ERROR_DDS_SUBNET_NOT_PRESENT;
  1867. }
  1868. ThisAttrib->Address2 = Info->SubnetMask; // alter information
  1869. FLAGS1_PRESENT(ThisAttrib);
  1870. ThisAttrib->Flags1 = Info->SubnetState;
  1871. if( NULL == Info->SubnetName ) {
  1872. STRING1_ABSENT(ThisAttrib);
  1873. } else {
  1874. STRING1_PRESENT(ThisAttrib);
  1875. ThisAttrib->String1 = Info->SubnetName;
  1876. }
  1877. if( NULL == Info->SubnetComment ) {
  1878. STRING2_ABSENT(ThisAttrib);
  1879. } else {
  1880. STRING2_PRESENT(ThisAttrib);
  1881. ThisAttrib->String2 = Info->SubnetComment;
  1882. }
  1883. Err = DhcpDsSetLists // now set the new attrib list
  1884. (
  1885. /* Reserved */ DDS_RESERVED_DWORD,
  1886. /* hStore */ hServer,
  1887. /* SetParams */ &unused,
  1888. /* Servers */ NULL,
  1889. /* Subnets */ &Subnets,
  1890. /* IpAddress */ NULL,
  1891. /* Mask */ NULL,
  1892. /* Ranges */ NULL,
  1893. /* Sites */ NULL,
  1894. /* Reservations */ NULL,
  1895. /* SuperScopes */ NULL,
  1896. /* OptionDescription.. */ NULL,
  1897. /* OptionsLocation */ NULL,
  1898. /* Options */ NULL,
  1899. /* ClassDescription */ NULL,
  1900. /* Classes */ NULL
  1901. );
  1902. MemArrayFree(&Subnets, MemFreeFunc); // free allocated memory
  1903. return Err;
  1904. }
  1905. //BeginExport(function)
  1906. //DOC DhcpDsServerEnumSubnets is not yet implemented.
  1907. DWORD
  1908. DhcpDsServerEnumSubnets( // get subnet list
  1909. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  1910. IN OUT LPSTORE_HANDLE hServer, // server object
  1911. IN DWORD Reserved, // for future use, reserved
  1912. IN LPWSTR ServerName, // name of server we're using
  1913. OUT LPDHCP_IP_ARRAY *SubnetsArray // give array of subnets
  1914. ) //EndExport(function)
  1915. {
  1916. LPDHCP_IP_ARRAY LocalSubnetArray;
  1917. DWORD Err, Err2, unused, Size;
  1918. ARRAY Subnets;
  1919. ARRAY_LOCATION Loc;
  1920. PEATTRIB ThisAttrib;
  1921. if( NULL == hDhcpC ) // check params
  1922. return ERROR_INVALID_PARAMETER;
  1923. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  1924. return ERROR_INVALID_PARAMETER;
  1925. if( NULL == ServerName || 0 != Reserved )
  1926. return ERROR_INVALID_PARAMETER;
  1927. if( NULL == SubnetsArray )
  1928. return ERROR_INVALID_PARAMETER;
  1929. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  1930. Err = DhcpDsGetLists // get list of subnets
  1931. (
  1932. /* Reserved */ DDS_RESERVED_DWORD,
  1933. /* hStore */ hServer,
  1934. /* RecursionDepth */ 0xFFFFFFFF,
  1935. /* Servers */ NULL,
  1936. /* Subnets */ &Subnets, // array of PEATTRIB 's
  1937. /* IpAddress */ NULL,
  1938. /* Mask */ NULL,
  1939. /* Ranges */ NULL,
  1940. /* Sites */ NULL,
  1941. /* Reservations */ NULL,
  1942. /* SuperScopes */ NULL,
  1943. /* OptionDescription */ NULL,
  1944. /* OptionsLocation */ NULL,
  1945. /* Options */ NULL,
  1946. /* Classes */ NULL
  1947. );
  1948. if( ERROR_SUCCESS != Err ) return Err;
  1949. LocalSubnetArray = MemAlloc(sizeof(DHCP_IP_ARRAY));
  1950. if( NULL == LocalSubnetArray ) {
  1951. MemArrayFree(&Subnets, MemFreeFunc);
  1952. return ERROR_NOT_ENOUGH_MEMORY;
  1953. }
  1954. LocalSubnetArray->NumElements = 0;
  1955. LocalSubnetArray->Elements = NULL;
  1956. Size = sizeof(DHCP_IP_ADDRESS)*MemArraySize(&Subnets);
  1957. if( Size ) LocalSubnetArray->Elements = MemAlloc(Size);
  1958. for( // accumulate the subnets
  1959. Err = MemArrayInitLoc(&Subnets, &Loc) // for each subnet
  1960. ; ERROR_FILE_NOT_FOUND != Err ; // until there are no more
  1961. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next
  1962. ) {
  1963. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  1964. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  1965. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  1966. continue; //= ds inconsistent
  1967. }
  1968. LocalSubnetArray->Elements[LocalSubnetArray->NumElements++] = ThisAttrib->Address1;
  1969. }
  1970. MemArrayFree(&Subnets, MemFreeFunc);
  1971. *SubnetsArray = LocalSubnetArray;
  1972. return ERROR_SUCCESS;
  1973. }
  1974. //BeginExport(function)
  1975. //DOC DhcpDsServerGetSubnetInfo is not yet implemented.
  1976. DWORD
  1977. DhcpDsServerGetSubnetInfo( // get info on subnet
  1978. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  1979. IN OUT LPSTORE_HANDLE hServer, // server object
  1980. IN DWORD Reserved, // for future use, reserved
  1981. IN LPWSTR ServerName, // name of server we're using
  1982. IN DHCP_IP_ADDRESS SubnetAddress, // address of subnet to get info for
  1983. OUT LPDHCP_SUBNET_INFO *SubnetInfo // o/p: allocated info
  1984. ) //EndExport(function)
  1985. {
  1986. DWORD Err, Err2, unused;
  1987. ARRAY Subnets;
  1988. ARRAY_LOCATION Loc;
  1989. PEATTRIB ThisAttrib;
  1990. LPDHCP_SUBNET_INFO Info;
  1991. BOOL fSubnetExists;
  1992. if( NULL == hDhcpC ) // check params
  1993. return ERROR_INVALID_PARAMETER;
  1994. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  1995. return ERROR_INVALID_PARAMETER;
  1996. if( NULL == ServerName || 0 != Reserved )
  1997. return ERROR_INVALID_PARAMETER;
  1998. if( NULL == SubnetInfo )
  1999. return ERROR_INVALID_PARAMETER;
  2000. Err = MemArrayInit(&Subnets); //= require ERROR_SUCCESS == Err
  2001. Err = DhcpDsGetLists // get list of subnets
  2002. (
  2003. /* Reserved */ DDS_RESERVED_DWORD,
  2004. /* hStore */ hServer,
  2005. /* RecursionDepth */ 0xFFFFFFFF,
  2006. /* Servers */ NULL,
  2007. /* Subnets */ &Subnets, // array of PEATTRIB 's
  2008. /* IpAddress */ NULL,
  2009. /* Mask */ NULL,
  2010. /* Ranges */ NULL,
  2011. /* Sites */ NULL,
  2012. /* Reservations */ NULL,
  2013. /* SuperScopes */ NULL,
  2014. /* OptionDescription */ NULL,
  2015. /* OptionsLocation */ NULL,
  2016. /* Options */ NULL,
  2017. /* Classes */ NULL
  2018. );
  2019. if( ERROR_SUCCESS != Err ) return Err;
  2020. fSubnetExists = FALSE;
  2021. for( // accumulate the subnets
  2022. Err = MemArrayInitLoc(&Subnets, &Loc) // for each subnet
  2023. ; ERROR_FILE_NOT_FOUND != Err ; // until there are no more
  2024. Err = MemArrayNextLoc(&Subnets, &Loc) // skip to next
  2025. ) {
  2026. Err = MemArrayGetElement(&Subnets, &Loc, &ThisAttrib);
  2027. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  2028. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  2029. continue; //= ds inconsistent
  2030. }
  2031. if( ThisAttrib->Address1 == SubnetAddress ) {
  2032. fSubnetExists = TRUE; // found the required subnet
  2033. break;
  2034. }
  2035. }
  2036. if( !fSubnetExists ) { // no subnet matching address
  2037. MemArrayFree(&Subnets, MemFreeFunc);
  2038. return ERROR_DDS_SUBNET_NOT_PRESENT;
  2039. }
  2040. Info = MemAlloc(sizeof(LPDHCP_SUBNET_INFO));
  2041. if( NULL == Info) {
  2042. MemArrayFree(&Subnets, MemFreeFunc);
  2043. return ERROR_NOT_ENOUGH_MEMORY;
  2044. }
  2045. Info->SubnetAddress = ThisAttrib->Address1; // subnet address
  2046. Info->SubnetMask = ThisAttrib->Address2; // subnet mask
  2047. if( !IS_STRING1_PRESENT(ThisAttrib) ) { // subnet name?
  2048. Info->SubnetName = NULL;
  2049. } else {
  2050. Info->SubnetName = MemAlloc(sizeof(WCHAR) * (1+wcslen(ThisAttrib->String1)));
  2051. if( NULL != Info->SubnetName ) {
  2052. wcscpy(Info->SubnetName, ThisAttrib->String1);
  2053. }
  2054. }
  2055. if( !IS_STRING2_PRESENT(ThisAttrib) ) { // subnet comment?
  2056. Info->SubnetComment = NULL; // no subnet comment
  2057. } else {
  2058. Info->SubnetComment = MemAlloc(sizeof(WCHAR) * (1+wcslen(ThisAttrib->String2)));
  2059. if( NULL != Info->SubnetComment ) {
  2060. wcscpy(Info->SubnetComment, ThisAttrib->String2);
  2061. }
  2062. }
  2063. if( !IS_FLAGS1_PRESENT(ThisAttrib) ) { // subnet state information
  2064. Info->SubnetState = DhcpSubnetEnabled;
  2065. } else {
  2066. Info->SubnetState = ThisAttrib->Flags1;
  2067. }
  2068. MemArrayFree(&Subnets, MemFreeFunc); // clear up memory
  2069. *SubnetInfo = Info;
  2070. Info->PrimaryHost.IpAddress = 0; // : unsupported fields..
  2071. Info->PrimaryHost.NetBiosName = NULL;
  2072. Info->PrimaryHost.HostName = NULL;
  2073. return ERROR_SUCCESS;
  2074. }
  2075. //BeginExport(function)
  2076. //DOC DhcpDsSubnetAddRangeOrExcl adds a range/excl to an existing subnet.
  2077. //DOC If there is a collision with between ranges, then the error code returned
  2078. //DOC is ERROR_DDS_POSSIBLE_RANGE_CONFLICT. Note that no checks are made for
  2079. //DOC exclusions though. Also, if a RANGE is extended via this routine, then
  2080. //DOC there is no error returned, but a limitation currently is that multiple
  2081. //DOC ranges (two only right) cannot be simultaneously extended.
  2082. //DOC BUBGUG: The basic check of whether the range belongs in the subnet is
  2083. //DOC not done..
  2084. DWORD
  2085. DhcpDsSubnetAddRangeOrExcl( // add a range or exclusion
  2086. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2087. IN OUT LPSTORE_HANDLE hServer, // server object
  2088. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2089. IN DWORD Reserved, // for future use, reserved
  2090. IN LPWSTR ServerName, // name of server we're using
  2091. IN DWORD Start, // start addr in range
  2092. IN DWORD End, // end addr in range
  2093. IN BOOL RangeOrExcl // TRUE ==> Range,FALSE ==> Excl
  2094. ) //EndExport(function)
  2095. {
  2096. DWORD Err, Err2, Type, unused;
  2097. ARRAY_LOCATION Loc;
  2098. PEATTRIB ThisAttrib;
  2099. EATTRIB Dummy;
  2100. ARRAY Ranges;
  2101. if( NULL == hDhcpC || NULL == hServer ) // check params
  2102. return ERROR_INVALID_PARAMETER;
  2103. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  2104. return ERROR_INVALID_PARAMETER;
  2105. if( NULL == hSubnet || NULL == hSubnet->ADSIHandle )
  2106. return ERROR_INVALID_PARAMETER;
  2107. if( NULL == ServerName || 0 != Reserved )
  2108. return ERROR_INVALID_PARAMETER;
  2109. if( Start > End ) return ERROR_INVALID_PARAMETER;
  2110. Err = MemArrayInit(&Ranges); //= require ERROR_SUCCESS == Err
  2111. Err = DhcpDsGetLists // get list of ranges frm ds
  2112. (
  2113. /* Reserved */ DDS_RESERVED_DWORD,
  2114. /* hStore */ hSubnet,
  2115. /* RecursionDepth */ 0xFFFFFFFF,
  2116. /* Servers */ NULL,
  2117. /* Subnets */ NULL,
  2118. /* IpAddress */ NULL,
  2119. /* Mask */ NULL,
  2120. /* Ranges */ &Ranges, // array of PEATTRIB 's
  2121. /* Sites */ NULL,
  2122. /* Reservations */ NULL,
  2123. /* SuperScopes */ NULL,
  2124. /* OptionDescription */ NULL,
  2125. /* OptionsLocation */ NULL,
  2126. /* Options */ NULL,
  2127. /* Classes */ NULL
  2128. );
  2129. if( ERROR_SUCCESS != Err ) return Err;
  2130. Type = (RangeOrExcl? RANGE_TYPE_RANGE: RANGE_TYPE_EXCL);
  2131. ThisAttrib = NULL;
  2132. if( FindCollisions(&Ranges,Start,End,Type, &ThisAttrib) ) {
  2133. MemArrayFree(&Ranges, MemFreeFunc);
  2134. return ERROR_DDS_POSSIBLE_RANGE_CONFLICT; // hit a range conflict!
  2135. }
  2136. if( NULL != ThisAttrib ) { // this is a collision case
  2137. if( Start == ThisAttrib->Address2 ) { // this is the collapse point
  2138. ThisAttrib->Address2 = End;
  2139. } else {
  2140. ThisAttrib->Address1 = Start;
  2141. }
  2142. } else { // not a collision
  2143. NothingPresent(&Dummy); // create a new range
  2144. ADDRESS1_PRESENT(&Dummy); // range start
  2145. Dummy.Address1 = Start;
  2146. ADDRESS2_PRESENT(&Dummy); // range end
  2147. Dummy.Address2 = End;
  2148. FLAGS1_PRESENT(&Dummy);
  2149. Dummy.Flags1 = 0;
  2150. FLAGS2_PRESENT(&Dummy); // range type or excl type?
  2151. Dummy.Flags2 = Type;
  2152. Err = MemArrayAddElement(&Ranges, &Dummy);
  2153. if( ERROR_SUCCESS != Err ) { // could not create new lists
  2154. MemArrayFree(&Ranges, MemFreeFunc);
  2155. return Err;
  2156. }
  2157. }
  2158. Err = DhcpDsSetLists // write back new list to ds
  2159. (
  2160. /* Reserved */ DDS_RESERVED_DWORD,
  2161. /* hStore */ hSubnet,
  2162. /* SetParams */ &unused,
  2163. /* Servers */ NULL,
  2164. /* Subnets */ NULL,
  2165. /* IpAddress */ NULL,
  2166. /* Mask */ NULL,
  2167. /* Ranges */ &Ranges,
  2168. /* Sites */ NULL,
  2169. /* Reservations */ NULL,
  2170. /* SuperScopes */ NULL,
  2171. /* OptionDescription.. */ NULL,
  2172. /* OptionsLocation */ NULL,
  2173. /* Options */ NULL,
  2174. /* ClassDescription */ NULL,
  2175. /* Classes */ NULL
  2176. );
  2177. if( NULL == ThisAttrib ) { // in case we added the new range
  2178. Err2 = MemArrayLastLoc(&Ranges, &Loc); // try to delete frm mem the new elt
  2179. Err2 = MemArrayDelElement(&Ranges, &Loc, &ThisAttrib);
  2180. //= require ERROR_SUCCESS == Err && ThisAttrib == &Dummy
  2181. }
  2182. MemArrayFree(&Ranges, MemFreeFunc);
  2183. return Err; // DhcpDsSetLists's ret code
  2184. }
  2185. //BeginExport(function)
  2186. //DOC DhcpDsSubnetDelRangeOrExcl deletes a range or exclusion from off the ds.
  2187. //DOC To specify range, set the RangeOrExcl parameter to TRUE.
  2188. DWORD
  2189. DhcpDsSubnetDelRangeOrExcl( // del a range or exclusion
  2190. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2191. IN OUT LPSTORE_HANDLE hServer, // server object
  2192. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2193. IN DWORD Reserved, // for future use, reserved
  2194. IN LPWSTR ServerName, // name of server we're using
  2195. IN DWORD Start, // start addr in range
  2196. IN DWORD End, // end addr in range
  2197. IN BOOL RangeOrExcl // TRUE ==> Range,FALSE ==> Excl
  2198. ) //EndExport(function)
  2199. {
  2200. DWORD Err, Err2, Type, ThisType, unused;
  2201. ARRAY_LOCATION Loc;
  2202. PEATTRIB ThisAttrib;
  2203. ARRAY Ranges;
  2204. BOOL Changed;
  2205. if( NULL == hDhcpC || NULL == hServer ) // check params
  2206. return ERROR_INVALID_PARAMETER;
  2207. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  2208. return ERROR_INVALID_PARAMETER;
  2209. if( NULL == hSubnet || NULL == hSubnet->ADSIHandle )
  2210. return ERROR_INVALID_PARAMETER;
  2211. if( NULL == ServerName || 0 != Reserved )
  2212. return ERROR_INVALID_PARAMETER;
  2213. if( Start > End ) return ERROR_INVALID_PARAMETER;
  2214. Err = MemArrayInit(&Ranges); //= require ERROR_SUCCESS == Err
  2215. Err = DhcpDsGetLists // get list of ranges frm ds
  2216. (
  2217. /* Reserved */ DDS_RESERVED_DWORD,
  2218. /* hStore */ hSubnet,
  2219. /* RecursionDepth */ 0xFFFFFFFF,
  2220. /* Servers */ NULL,
  2221. /* Subnets */ NULL,
  2222. /* IpAddress */ NULL,
  2223. /* Mask */ NULL,
  2224. /* Ranges */ &Ranges, // array of PEATTRIB 's
  2225. /* Sites */ NULL,
  2226. /* Reservations */ NULL,
  2227. /* SuperScopes */ NULL,
  2228. /* OptionDescription */ NULL,
  2229. /* OptionsLocation */ NULL,
  2230. /* Options */ NULL,
  2231. /* Classes */ NULL
  2232. );
  2233. if( ERROR_SUCCESS != Err ) return Err;
  2234. Type = (RangeOrExcl? RANGE_TYPE_RANGE: RANGE_TYPE_EXCL);
  2235. Changed = FALSE;
  2236. for( // look for matching range/excl
  2237. Err = MemArrayInitLoc(&Ranges, &Loc)
  2238. ; ERROR_FILE_NOT_FOUND != Err ;
  2239. Err = MemArrayNextLoc(&Ranges, &Loc)
  2240. ) {
  2241. Err = MemArrayGetElement(&Ranges, &Loc, &ThisAttrib);
  2242. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2243. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  2244. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  2245. continue; //= ds inconsistent
  2246. }
  2247. if( !IS_FLAGS2_PRESENT(ThisAttrib) ) { // this is a RANGE_TYPE_RANGE
  2248. ThisType = RANGE_TYPE_RANGE;
  2249. } else ThisType = ThisAttrib->Flags2;
  2250. if( Start != ThisAttrib->Address1 ||
  2251. End != ThisAttrib->Address2 ) { // range mismatch
  2252. continue;
  2253. }
  2254. if(Type != ThisType ) { // looking for x, bug this is !x.
  2255. continue;
  2256. }
  2257. Err2 = MemArrayDelElement(&Ranges, &Loc, &ThisAttrib);
  2258. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2259. MemFreeFunc(ThisAttrib);
  2260. Changed = TRUE;
  2261. }
  2262. if( !Changed ) { // nothing found ni registry
  2263. Err = ERROR_DDS_RANGE_DOES_NOT_EXIST;
  2264. } else {
  2265. Err = DhcpDsSetLists // write back new list to ds
  2266. (
  2267. /* Reserved */ DDS_RESERVED_DWORD,
  2268. /* hStore */ hSubnet,
  2269. /* SetParams */ &unused,
  2270. /* Servers */ NULL,
  2271. /* Subnets */ NULL,
  2272. /* IpAddress */ NULL,
  2273. /* Mask */ NULL,
  2274. /* Ranges */ &Ranges,
  2275. /* Sites */ NULL,
  2276. /* Reservations */ NULL,
  2277. /* SuperScopes */ NULL,
  2278. /* OptionDescription.. */ NULL,
  2279. /* OptionsLocation */ NULL,
  2280. /* Options */ NULL,
  2281. /* ClassDescription */ NULL,
  2282. /* Classes */ NULL
  2283. );
  2284. }
  2285. MemArrayFree(&Ranges, MemFreeFunc);
  2286. return Err; // DhcpDsSetLists's ret code
  2287. }
  2288. DWORD
  2289. ConvertAttribToRanges( // convert from array of attribs ..
  2290. IN DWORD nRanges, // # of ranges,
  2291. IN PARRAY Ranges, // input array of attribs
  2292. IN ULONG Type, // TYPE_RANGE_TYPE or TYPE_EXCLUSION_TYPE?
  2293. OUT LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *pRanges //output array..
  2294. )
  2295. {
  2296. DWORD Err;
  2297. ULONG Count, ThisType;
  2298. PEATTRIB ThisAttrib;
  2299. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 localRanges;
  2300. ARRAY_LOCATION Loc;
  2301. DHCP_IP_RANGE *ThisRange;
  2302. localRanges = MemAlloc(sizeof(DHCP_SUBNET_ELEMENT_INFO_ARRAY_V4));
  2303. *pRanges = localRanges;
  2304. if( NULL == localRanges ) return ERROR_NOT_ENOUGH_MEMORY;
  2305. if( 0 == nRanges ) {
  2306. localRanges->NumElements = 0;
  2307. localRanges->Elements = NULL;
  2308. return ERROR_SUCCESS;
  2309. }
  2310. localRanges->Elements = MemAlloc(nRanges*sizeof(DHCP_SUBNET_ELEMENT_DATA_V4));
  2311. if( NULL == localRanges->Elements ) {
  2312. MemFree(localRanges);
  2313. *pRanges = NULL;
  2314. return ERROR_NOT_ENOUGH_MEMORY;
  2315. }
  2316. localRanges->NumElements = nRanges;
  2317. for( Count = 0 ; Count < nRanges ; Count ++ ) {
  2318. localRanges->Elements[Count].Element.IpRange =
  2319. localRanges->Elements[Count].Element.ExcludeIpRange =
  2320. ThisRange = MemAlloc(sizeof(DHCP_IP_RANGE));
  2321. if( NULL == ThisRange ) { // oops could not allocate ? free everything and bail!
  2322. while( Count != 0 ) { // remember Count is unsigned ..
  2323. Count --;
  2324. MemFree(localRanges->Elements[Count].Element.IpRange);
  2325. }
  2326. MemFree(localRanges->Elements);
  2327. MemFree(localRanges);
  2328. *pRanges = NULL;
  2329. return ERROR_NOT_ENOUGH_MEMORY;
  2330. }
  2331. }
  2332. Count = 0;
  2333. for( // look for matching range/excl
  2334. Err = MemArrayInitLoc(Ranges, &Loc)
  2335. ; ERROR_FILE_NOT_FOUND != Err ;
  2336. Err = MemArrayNextLoc(Ranges, &Loc)
  2337. ) {
  2338. Err = MemArrayGetElement(Ranges, &Loc, &ThisAttrib);
  2339. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2340. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  2341. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  2342. continue; //= ds inconsistent
  2343. }
  2344. if( !IS_FLAGS2_PRESENT(ThisAttrib) ) { // this is a RANGE_TYPE_RANGE
  2345. ThisType = RANGE_TYPE_RANGE;
  2346. } else ThisType = ThisAttrib->Flags2;
  2347. if(Type != ThisType ) { // looking for x, bug this is !x.
  2348. continue;
  2349. }
  2350. //= require ThisAttrib->Address1 < ThisAttrib->Address2
  2351. if( RANGE_TYPE_RANGE == Type ) {
  2352. localRanges->Elements[Count].ElementType = DhcpIpRanges ;
  2353. localRanges->Elements[Count].Element.IpRange->StartAddress = ThisAttrib->Address1;
  2354. localRanges->Elements[Count].Element.IpRange->EndAddress = ThisAttrib->Address2;
  2355. } else {
  2356. localRanges->Elements[Count].ElementType = DhcpExcludedIpRanges;
  2357. localRanges->Elements[Count].Element.ExcludeIpRange->StartAddress = ThisAttrib->Address1;
  2358. localRanges->Elements[Count].Element.ExcludeIpRange->EndAddress = ThisAttrib->Address2;
  2359. }
  2360. Count ++;
  2361. }
  2362. return ERROR_SUCCESS;
  2363. }
  2364. //BeginExport(function)
  2365. //DOC DhcpDsEnumRangesOrExcl is not yet implemented.
  2366. DWORD
  2367. DhcpDsEnumRangesOrExcl( // enum list of ranges 'n excl
  2368. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2369. IN OUT LPSTORE_HANDLE hServer, // server object
  2370. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2371. IN DWORD Reserved, // for future use, reserved
  2372. IN LPWSTR ServerName, // name of server we're using
  2373. IN BOOL RangeOrExcl, // TRUE ==> Range, FALSE ==> Excl
  2374. OUT LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *pRanges
  2375. ) //EndExport(function)
  2376. {
  2377. DWORD Err, Err2, Type, ThisType, unused;
  2378. DWORD Count;
  2379. ARRAY_LOCATION Loc;
  2380. PEATTRIB ThisAttrib;
  2381. ARRAY Ranges;
  2382. if( NULL == hDhcpC || NULL == hServer ) // check params
  2383. return ERROR_INVALID_PARAMETER;
  2384. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  2385. return ERROR_INVALID_PARAMETER;
  2386. if( NULL == hSubnet || NULL == hSubnet->ADSIHandle )
  2387. return ERROR_INVALID_PARAMETER;
  2388. if( NULL == ServerName || 0 != Reserved )
  2389. return ERROR_INVALID_PARAMETER;
  2390. Err = MemArrayInit(&Ranges); //= require ERROR_SUCCESS == Err
  2391. Err = DhcpDsGetLists // get list of ranges frm ds
  2392. (
  2393. /* Reserved */ DDS_RESERVED_DWORD,
  2394. /* hStore */ hSubnet,
  2395. /* RecursionDepth */ 0xFFFFFFFF,
  2396. /* Servers */ NULL,
  2397. /* Subnets */ NULL,
  2398. /* IpAddress */ NULL,
  2399. /* Mask */ NULL,
  2400. /* Ranges */ &Ranges, // array of PEATTRIB 's
  2401. /* Sites */ NULL,
  2402. /* Reservations */ NULL,
  2403. /* SuperScopes */ NULL,
  2404. /* OptionDescription */ NULL,
  2405. /* OptionsLocation */ NULL,
  2406. /* Options */ NULL,
  2407. /* Classes */ NULL
  2408. );
  2409. if( ERROR_SUCCESS != Err ) return Err;
  2410. Type = (RangeOrExcl? RANGE_TYPE_RANGE: RANGE_TYPE_EXCL);
  2411. Count = 0;
  2412. for( // look for matching range/excl
  2413. Err = MemArrayInitLoc(&Ranges, &Loc)
  2414. ; ERROR_FILE_NOT_FOUND != Err ;
  2415. Err = MemArrayNextLoc(&Ranges, &Loc)
  2416. ) {
  2417. Err = MemArrayGetElement(&Ranges, &Loc, &ThisAttrib);
  2418. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2419. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no subnet address
  2420. !IS_ADDRESS2_PRESENT(ThisAttrib) ) { // no subnet mask
  2421. continue; //= ds inconsistent
  2422. }
  2423. if( !IS_FLAGS2_PRESENT(ThisAttrib) ) { // this is a RANGE_TYPE_RANGE
  2424. ThisType = RANGE_TYPE_RANGE;
  2425. } else ThisType = ThisAttrib->Flags2;
  2426. if(Type != ThisType ) { // looking for x, bug this is !x.
  2427. continue;
  2428. }
  2429. Count ++;
  2430. }
  2431. Err = ConvertAttribToRanges(Count, &Ranges, Type, pRanges);
  2432. MemArrayFree(&Ranges, MemFreeFunc);
  2433. return Err;
  2434. }
  2435. //BeginExport(function)
  2436. //DOC DhcpDsSubnetAddReservation tries to add a reservation object in the DS.
  2437. //DOC Neither the ip address not hte hw-address must exist in the DS prior to this.
  2438. //DOC If they do exist, the error returned is ERROR_DDS_RESERVATION_CONFLICT.
  2439. //DOC No checks are made on the sanity of the address in this subnet..
  2440. DWORD
  2441. DhcpDsSubnetAddReservation( // add a reservation
  2442. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2443. IN OUT LPSTORE_HANDLE hServer, // server object
  2444. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2445. IN DWORD Reserved, // for future use, reserved
  2446. IN LPWSTR ServerName, // name of server we're using
  2447. IN DWORD ReservedAddr, // reservation ip address to add
  2448. IN LPBYTE HwAddr, // RAW [ethernet?] hw addr of the client
  2449. IN DWORD HwAddrLen, // length in # of bytes of hw addr
  2450. IN DWORD ClientType // client is BOOTP, DHCP, or both?
  2451. ) //EndExport(function)
  2452. {
  2453. DWORD Err, Err2, Type, ClientUIDSize, unused;
  2454. ARRAY_LOCATION Loc;
  2455. PEATTRIB ThisAttrib;
  2456. EATTRIB Dummy;
  2457. ARRAY Reservations;
  2458. LPBYTE ClientUID;
  2459. LPWSTR ReservationCNName;
  2460. if( NULL == hDhcpC || NULL == hServer ) // check params
  2461. return ERROR_INVALID_PARAMETER;
  2462. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  2463. return ERROR_INVALID_PARAMETER;
  2464. if( NULL == ServerName || 0 != Reserved )
  2465. return ERROR_INVALID_PARAMETER;
  2466. if( NULL == HwAddr || 0 == HwAddrLen )
  2467. return ERROR_INVALID_PARAMETER;
  2468. ClientUID = NULL;
  2469. Err = DhcpMakeClientUID(
  2470. HwAddr,
  2471. HwAddrLen,
  2472. HARDWARE_TYPE_10MB_EITHERNET,
  2473. ReservedAddr,
  2474. &ClientUID,
  2475. &ClientUIDSize
  2476. );
  2477. if( ERROR_SUCCESS != Err ) { // should not happen
  2478. return Err;
  2479. }
  2480. Err = MemArrayInit(&Reservations); //= require ERROR_SUCCESS == Err
  2481. Err = DhcpDsGetLists // get list of ranges frm ds
  2482. (
  2483. /* Reserved */ DDS_RESERVED_DWORD,
  2484. /* hStore */ hSubnet,
  2485. /* RecursionDepth */ 0xFFFFFFFF,
  2486. /* Servers */ NULL,
  2487. /* Subnets */ NULL,
  2488. /* IpAddress */ NULL,
  2489. /* Mask */ NULL,
  2490. /* Ranges */ NULL,
  2491. /* Sites */ NULL,
  2492. /* Reservations */ &Reservations,
  2493. /* SuperScopes */ NULL,
  2494. /* OptionDescription */ NULL,
  2495. /* OptionsLocation */ NULL,
  2496. /* Options */ NULL,
  2497. /* Classes */ NULL
  2498. );
  2499. if( ERROR_SUCCESS != Err ) {
  2500. MemFree(ClientUID);
  2501. return Err;
  2502. }
  2503. for( // search for existing reservation
  2504. Err = MemArrayInitLoc(&Reservations, &Loc)
  2505. ; ERROR_FILE_NOT_FOUND != Err ;
  2506. Err = MemArrayNextLoc(&Reservations, &Loc)
  2507. ) {
  2508. BOOL Mismatch;
  2509. //= require ERROR_SUCCESS == Err
  2510. Err = MemArrayGetElement(&Reservations, &Loc, &ThisAttrib);
  2511. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2512. if( !IS_ADDRESS1_PRESENT(ThisAttrib) // no address for reservations
  2513. || !IS_BINARY1_PRESENT(ThisAttrib) // no hw len specified
  2514. || !IS_FLAGS1_PRESENT(ThisAttrib) ) { // no client type present
  2515. continue; //= ds inconsistent
  2516. }
  2517. Mismatch = FALSE;
  2518. if( ThisAttrib->Address1 == ReservedAddr ) {
  2519. Mismatch = TRUE; // address already reserved
  2520. }
  2521. if( ThisAttrib->BinLen1 == ClientUIDSize // see if hw address matches
  2522. && 0 == memcmp(ThisAttrib->Binary1, ClientUID, ClientUIDSize)
  2523. ) {
  2524. Mismatch = TRUE;
  2525. }
  2526. if( Mismatch ) { // ip addr or hw-addr in use
  2527. MemArrayFree(&Reservations, MemFreeFunc);
  2528. MemFree(ClientUID);
  2529. return ERROR_DDS_RESERVATION_CONFLICT;
  2530. }
  2531. }
  2532. ReservationCNName = MakeReservationLocation(ServerName, ReservedAddr);
  2533. if( NULL == ReservationCNName ) { // not enough mem to create string
  2534. Err = ERROR_NOT_ENOUGH_MEMORY;
  2535. } else {
  2536. Err = CreateReservationObject // create the new reservation object
  2537. (
  2538. /* hDhcpC */ hDhcpC, // container to create obj in
  2539. /* ReserveCNName */ ReservationCNName
  2540. );
  2541. }
  2542. if( ERROR_SUCCESS != Err ) { // could not create reservation object
  2543. MemArrayFree(&Reservations, MemFreeFunc);
  2544. MemFree(ClientUID);
  2545. return Err;
  2546. }
  2547. NothingPresent(&Dummy); // create a new reservation
  2548. ADDRESS1_PRESENT(&Dummy); // ip address
  2549. Dummy.Address1 = ReservedAddr;
  2550. FLAGS1_PRESENT(&Dummy); // client type
  2551. Dummy.Flags1 = ClientType;
  2552. BINARY1_PRESENT(&Dummy); // client uid
  2553. Dummy.BinLen1 = ClientUIDSize;
  2554. Dummy.Binary1 = ClientUID;
  2555. STOREGETTYPE_PRESENT(&Dummy); // relative location for reservation obj
  2556. ADSPATH_PRESENT(&Dummy);
  2557. Dummy.StoreGetType = StoreGetChildType;
  2558. Dummy.ADsPath = ReservationCNName;
  2559. Err = MemArrayAddElement(&Reservations,&Dummy);
  2560. if( ERROR_SUCCESS != Err ) { // oops, cannot add reservation
  2561. MemArrayFree(&Reservations, MemFreeFunc);
  2562. MemFree(ClientUID);
  2563. MemFree(ReservationCNName);
  2564. return Err;
  2565. }
  2566. Err = DhcpDsSetLists // write back new list to ds
  2567. (
  2568. /* Reserved */ DDS_RESERVED_DWORD,
  2569. /* hStore */ hSubnet,
  2570. /* SetParams */ &unused,
  2571. /* Servers */ NULL,
  2572. /* Subnets */ NULL,
  2573. /* IpAddress */ NULL,
  2574. /* Mask */ NULL,
  2575. /* Ranges */ NULL,
  2576. /* Sites */ NULL,
  2577. /* Reservations */ &Reservations,
  2578. /* SuperScopes */ NULL,
  2579. /* OptionDescription.. */ NULL,
  2580. /* OptionsLocation */ NULL,
  2581. /* Options */ NULL,
  2582. /* ClassDescription */ NULL,
  2583. /* Classes */ NULL
  2584. );
  2585. Err2 = MemArrayLastLoc(&Reservations, &Loc); // try to delete frm mem the new elt
  2586. Err2 = MemArrayDelElement(&Reservations, &Loc, &ThisAttrib);
  2587. //= require ERROR_SUCCESS == Err && ThisAttrib == &Dummy
  2588. MemArrayFree(&Reservations, MemFreeFunc);
  2589. MemFree(ClientUID);
  2590. MemFree(ReservationCNName);
  2591. return Err; // DhcpDsSetLists's ret code
  2592. }
  2593. //BeginExport(function)
  2594. //DOC DhcpDsSubnetDelReservation deletes a reservation from the DS.
  2595. //DOC If the reservation does not exist, it returns ERROR_DDS_RESERVATION_NOT_PRESENT.
  2596. //DOC Reservations cannot be deleted by anything but ip address for now.
  2597. DWORD
  2598. DhcpDsSubnetDelReservation( // delete a reservation
  2599. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2600. IN OUT LPSTORE_HANDLE hServer, // server object
  2601. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2602. IN DWORD Reserved, // for future use, reserved
  2603. IN LPWSTR ServerName, // name of server we're using
  2604. IN DWORD ReservedAddr // ip address to delete reserv. by
  2605. ) //EndExport(function)
  2606. {
  2607. DWORD Err, Err2, Type, ThisType, unused;
  2608. ARRAY_LOCATION Loc;
  2609. PEATTRIB ThisAttrib;
  2610. ARRAY Reservations;
  2611. BOOL ReservationExists;
  2612. LPWSTR ReservationLocPath, ReservationCNName;
  2613. DWORD ReservationLocType;
  2614. if( NULL == hDhcpC || NULL == hServer ) // check params
  2615. return ERROR_INVALID_PARAMETER;
  2616. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  2617. return ERROR_INVALID_PARAMETER;
  2618. if( NULL == ServerName || 0 != Reserved )
  2619. return ERROR_INVALID_PARAMETER;
  2620. Err = MemArrayInit(&Reservations); //= require ERROR_SUCCESS == Err
  2621. Err = DhcpDsGetLists // get list of ranges frm ds
  2622. (
  2623. /* Reserved */ DDS_RESERVED_DWORD,
  2624. /* hStore */ hSubnet,
  2625. /* RecursionDepth */ 0xFFFFFFFF,
  2626. /* Servers */ NULL,
  2627. /* Subnets */ NULL,
  2628. /* IpAddress */ NULL,
  2629. /* Mask */ NULL,
  2630. /* Ranges */ NULL,
  2631. /* Sites */ NULL,
  2632. /* Reservations */ &Reservations,
  2633. /* SuperScopes */ NULL,
  2634. /* OptionDescription */ NULL,
  2635. /* OptionsLocation */ NULL,
  2636. /* Options */ NULL,
  2637. /* Classes */ NULL
  2638. );
  2639. if( ERROR_SUCCESS != Err ) return Err;
  2640. ReservationExists = FALSE;
  2641. for( // look for matching range/excl
  2642. Err = MemArrayInitLoc(&Reservations, &Loc)
  2643. ; ERROR_FILE_NOT_FOUND != Err ;
  2644. Err = MemArrayNextLoc(&Reservations, &Loc)
  2645. ) {
  2646. Err = MemArrayGetElement(&Reservations, &Loc, &ThisAttrib);
  2647. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2648. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no reservation address
  2649. !IS_BINARY1_PRESENT(ThisAttrib) ) { // no hw addr specified
  2650. continue; //= ds inconsistent
  2651. }
  2652. if( ThisAttrib->Address1 != ReservedAddr ) {
  2653. continue; // not this reservation
  2654. }
  2655. ReservationExists = TRUE;
  2656. Err2 = MemArrayDelElement(&Reservations, &Loc, &ThisAttrib);
  2657. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2658. break;
  2659. }
  2660. if( !ReservationExists ) { // no matching reservation found
  2661. MemArrayFree(&Reservations, MemFreeFunc);
  2662. return ERROR_DDS_RESERVATION_NOT_PRESENT;
  2663. }
  2664. Err = DhcpDsSetLists // write back new list to ds
  2665. (
  2666. /* Reserved */ DDS_RESERVED_DWORD,
  2667. /* hStore */ hSubnet,
  2668. /* SetParams */ &unused,
  2669. /* Servers */ NULL,
  2670. /* Subnets */ NULL,
  2671. /* IpAddress */ NULL,
  2672. /* Mask */ NULL,
  2673. /* Ranges */ NULL,
  2674. /* Sites */ NULL,
  2675. /* Reservations */ &Reservations,
  2676. /* SuperScopes */ NULL,
  2677. /* OptionDescription.. */ NULL,
  2678. /* OptionsLocation */ NULL,
  2679. /* Options */ NULL,
  2680. /* ClassDescription */ NULL,
  2681. /* Classes */ NULL
  2682. );
  2683. MemArrayFree(&Reservations, MemFreeFunc);
  2684. if( ERROR_SUCCESS != Err ) {
  2685. MemFree(ThisAttrib);
  2686. return Err;
  2687. }
  2688. if( IS_ADSPATH_PRESENT(ThisAttrib) ) { // deleted reservation's location in ds
  2689. ReservationLocType = ThisAttrib->StoreGetType;
  2690. ReservationLocPath = ThisAttrib->ADsPath;
  2691. } else {
  2692. ReservationLocPath = NULL;
  2693. }
  2694. if( NULL == ReservationLocPath ) { // no path present, but guess it anyways
  2695. ReservationCNName = MakeReservationLocation(ServerName,ReservedAddr);
  2696. ReservationLocPath = ReservationCNName; // same name that is used generally
  2697. ReservationLocType = StoreGetChildType; // child object
  2698. } else {
  2699. ReservationCNName = NULL; // NULL indicating no alloc
  2700. }
  2701. if( NULL == ReservationLocPath ) { // dont know what to delete..
  2702. Err = ERROR_NOT_ENOUGH_MEMORY; // MakeReservationLocation failed
  2703. } else { // try to delete subnet object
  2704. Err = SubnetDeleteReservation // actual delete in ds
  2705. (
  2706. /* hDhcpC */ hDhcpC,
  2707. /* ServerName */ ServerName,
  2708. /* hServer */ hServer,
  2709. /* hSubnet */ hSubnet,
  2710. /* ADsPath */ ReservationLocPath,
  2711. /* StoreGetType */ ReservationLocType
  2712. );
  2713. }
  2714. if( ReservationCNName ) MemFree(ReservationCNName);
  2715. MemFree(ThisAttrib); // free all ptrs left..
  2716. return Err;
  2717. }
  2718. LPBYTE _inline
  2719. DupeBytes( // allocate mem and copy bytes
  2720. IN LPBYTE Data,
  2721. IN ULONG DataLen
  2722. )
  2723. {
  2724. LPBYTE NewData;
  2725. if( 0 == DataLen ) return NULL;
  2726. NewData = MemAlloc(DataLen);
  2727. if( NULL != NewData ) {
  2728. memcpy(NewData, Data, DataLen);
  2729. }
  2730. return NewData;
  2731. }
  2732. DWORD
  2733. ConvertAttribToReservations( // convert from arry of attribs ..
  2734. IN DWORD nRes, // # of reservatiosn to convert
  2735. IN PARRAY Res, // the actual array of reservations
  2736. OUT LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *pResInfo
  2737. )
  2738. {
  2739. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 localRes;
  2740. DWORD Err, Count;
  2741. LPWSTR ReservationLocPath, ReservationCNName;
  2742. DWORD ReservationLocType;
  2743. ARRAY_LOCATION Loc;
  2744. PEATTRIB ThisAttrib;
  2745. ARRAY Reservations;
  2746. LPDHCP_IP_RESERVATION_V4 ThisRes;
  2747. LPVOID Data;
  2748. localRes = MemAlloc(sizeof(DHCP_SUBNET_ELEMENT_INFO_ARRAY_V4));
  2749. *pResInfo = localRes;
  2750. if( NULL == localRes ) return ERROR_NOT_ENOUGH_MEMORY;
  2751. if( 0 == nRes ) {
  2752. localRes->NumElements = 0;
  2753. localRes->Elements = NULL;
  2754. return ERROR_SUCCESS;
  2755. }
  2756. localRes->Elements = MemAlloc(nRes*sizeof(DHCP_SUBNET_ELEMENT_DATA_V4));
  2757. if( NULL == localRes->Elements ) {
  2758. MemFree(localRes);
  2759. *pResInfo = NULL;
  2760. return ERROR_NOT_ENOUGH_MEMORY;
  2761. }
  2762. localRes->NumElements = nRes;
  2763. for( Count = 0 ; Count < nRes ; Count ++ ) {
  2764. localRes->Elements[Count].Element.ReservedIp =
  2765. ThisRes = MemAlloc(sizeof(DHCP_IP_RESERVATION_V4));
  2766. if( NULL != ThisRes ) { // successfull allocation..
  2767. ThisRes->ReservedForClient = MemAlloc(sizeof(DHCP_CLIENT_UID));
  2768. if( NULL == ThisRes->ReservedForClient) {
  2769. MemFree(ThisRes); // duh it failed here..
  2770. ThisRes = NULL; // fake an upper level fail
  2771. }
  2772. }
  2773. if( NULL == ThisRes ) { // oops could not allocate ? free everything and bail!
  2774. while( Count != 0 ) { // remember Count is unsigned ..
  2775. Count --;
  2776. MemFree(localRes->Elements[Count].Element.ReservedIp->ReservedForClient);
  2777. MemFree(localRes->Elements[Count].Element.ReservedIp);
  2778. }
  2779. MemFree(localRes->Elements);
  2780. MemFree(localRes);
  2781. *pResInfo = NULL;
  2782. return ERROR_NOT_ENOUGH_MEMORY;
  2783. }
  2784. }
  2785. Count = 0;
  2786. for( // look for matching range/excl
  2787. Err = MemArrayInitLoc(Res, &Loc)
  2788. ; ERROR_FILE_NOT_FOUND != Err ;
  2789. Err = MemArrayNextLoc(Res, &Loc)
  2790. ) {
  2791. Err = MemArrayGetElement(Res, &Loc, &ThisAttrib);
  2792. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2793. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no reservation address
  2794. !IS_BINARY1_PRESENT(ThisAttrib) ) { // no hw addr specified
  2795. continue; //= ds inconsistent
  2796. }
  2797. localRes->Elements[Count].ElementType = DhcpReservedIps;
  2798. if( IS_FLAGS1_PRESENT(ThisAttrib) ) {
  2799. localRes->Elements[Count].Element.ReservedIp->bAllowedClientTypes = (BYTE)ThisAttrib->Flags1;
  2800. } else {
  2801. localRes->Elements[Count].Element.ReservedIp->bAllowedClientTypes = 0;
  2802. }
  2803. localRes->Elements[Count].Element.ReservedIp->ReservedIpAddress = ThisAttrib->Address1;
  2804. localRes->Elements[Count].Element.ReservedIp->ReservedForClient->Data =
  2805. Data = DupeBytes(ThisAttrib->Binary1, ThisAttrib->BinLen1);
  2806. if( NULL == Data ) { // could not allocate memory..
  2807. localRes->Elements[Count].Element.ReservedIp->ReservedForClient->DataLength = 0;
  2808. } else {
  2809. localRes->Elements[Count].Element.ReservedIp->ReservedForClient->DataLength = ThisAttrib->BinLen1;
  2810. }
  2811. Count++;
  2812. }
  2813. return ERROR_SUCCESS;
  2814. }
  2815. //BeginExport(function)
  2816. //DOC DhcpDsEnumReservations enumerates the reservations..
  2817. DWORD
  2818. DhcpDsEnumReservations( // enumerate reservations frm DS
  2819. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2820. IN OUT LPSTORE_HANDLE hServer, // server object
  2821. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2822. IN DWORD Reserved, // for future use, reserved
  2823. IN LPWSTR ServerName, // name of server we're using
  2824. OUT LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *pReservations
  2825. ) //EndExport(function)
  2826. {
  2827. DWORD Err, Err2, Type, ThisType, unused;
  2828. DWORD Count;
  2829. ARRAY_LOCATION Loc;
  2830. PEATTRIB ThisAttrib;
  2831. ARRAY Reservations;
  2832. if( NULL == hDhcpC || NULL == hServer ) // check params
  2833. return ERROR_INVALID_PARAMETER;
  2834. if( NULL == hServer->ADSIHandle || NULL == hDhcpC->ADSIHandle )
  2835. return ERROR_INVALID_PARAMETER;
  2836. if( NULL == ServerName || 0 != Reserved )
  2837. return ERROR_INVALID_PARAMETER;
  2838. Err = MemArrayInit(&Reservations); //= require ERROR_SUCCESS == Err
  2839. Err = DhcpDsGetLists // get list of ranges frm ds
  2840. (
  2841. /* Reserved */ DDS_RESERVED_DWORD,
  2842. /* hStore */ hSubnet,
  2843. /* RecursionDepth */ 0xFFFFFFFF,
  2844. /* Servers */ NULL,
  2845. /* Subnets */ NULL,
  2846. /* IpAddress */ NULL,
  2847. /* Mask */ NULL,
  2848. /* Ranges */ NULL,
  2849. /* Sites */ NULL,
  2850. /* Reservations */ &Reservations,
  2851. /* SuperScopes */ NULL,
  2852. /* OptionDescription */ NULL,
  2853. /* OptionsLocation */ NULL,
  2854. /* Options */ NULL,
  2855. /* Classes */ NULL
  2856. );
  2857. if( ERROR_SUCCESS != Err ) return Err;
  2858. Count = 0;
  2859. for( // look for matching range/excl
  2860. Err = MemArrayInitLoc(&Reservations, &Loc)
  2861. ; ERROR_FILE_NOT_FOUND != Err ;
  2862. Err = MemArrayNextLoc(&Reservations, &Loc)
  2863. ) {
  2864. Err = MemArrayGetElement(&Reservations, &Loc, &ThisAttrib);
  2865. //= require ERROR_SUCCESS == Err && NULL != ThisAttrib
  2866. if( !IS_ADDRESS1_PRESENT(ThisAttrib) || // no reservation address
  2867. !IS_BINARY1_PRESENT(ThisAttrib) ) { // no hw addr specified
  2868. continue; //= ds inconsistent
  2869. }
  2870. }
  2871. Err = ConvertAttribToReservations(Count, &Reservations, pReservations);
  2872. MemArrayFree(&Reservations, MemFreeFunc);
  2873. return Err;
  2874. }
  2875. //BeginExport(function)
  2876. //DOC DhcpDsEnumSubnetElements enumerates the list of subnet elements in a
  2877. //DOC subnet... such as IpRanges, Exclusions, Reservations..
  2878. //DOC
  2879. DWORD
  2880. DhcpDsEnumSubnetElements(
  2881. IN OUT LPSTORE_HANDLE hDhcpC, // root container to create objects
  2882. IN OUT LPSTORE_HANDLE hServer, // server object
  2883. IN OUT LPSTORE_HANDLE hSubnet, // subnet object
  2884. IN DWORD Reserved, // for future use, reserved
  2885. IN LPWSTR ServerName, // name of server we're using
  2886. IN DHCP_SUBNET_ELEMENT_TYPE ElementType, // what kind of elt to enum?
  2887. OUT LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *ElementInfo
  2888. ) //EndExport(function)
  2889. {
  2890. DWORD Err;
  2891. switch(ElementType) {
  2892. case DhcpIpRanges:
  2893. Err = DhcpDsEnumRangesOrExcl(
  2894. hDhcpC,
  2895. hServer,
  2896. hSubnet,
  2897. Reserved,
  2898. ServerName,
  2899. TRUE,
  2900. ElementInfo
  2901. );
  2902. break;
  2903. case DhcpExcludedIpRanges:
  2904. Err = DhcpDsEnumRangesOrExcl(
  2905. hDhcpC,
  2906. hServer,
  2907. hSubnet,
  2908. Reserved,
  2909. ServerName,
  2910. FALSE,
  2911. ElementInfo
  2912. );
  2913. break;
  2914. case DhcpReservedIps:
  2915. Err = DhcpDsEnumReservations(
  2916. hDhcpC,
  2917. hServer,
  2918. hSubnet,
  2919. Reserved,
  2920. ServerName,
  2921. ElementInfo
  2922. );
  2923. break;
  2924. default:
  2925. return ERROR_CALL_NOT_IMPLEMENTED;
  2926. }
  2927. return Err;
  2928. }
  2929. //================================================================================
  2930. // end of file
  2931. //================================================================================