Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4796 lines
118 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcstub.c
  5. Abstract:
  6. Client stubs of the DHCP server service APIs.
  7. Author:
  8. Madan Appiah (madana) 10-Sep-1993
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include "dhcpcli.h"
  14. #include <dhcpds.h> // this is from dhcpds directory
  15. #include <stdlib.h>
  16. #include <winsock2.h>
  17. #include <rpcasync.h>
  18. CRITICAL_SECTION DhcpsapiDllCritSect;
  19. static DWORD Initialized = 0;
  20. static DWORD TlsIndex = 0xFFFFFFFF;
  21. // This flag is used to set a shorter bind timeout value
  22. extern BOOL fShortTimeOut;
  23. BOOLEAN
  24. DllMain (
  25. IN PVOID DllHandle,
  26. IN ULONG Reason,
  27. IN PCONTEXT Context OPTIONAL
  28. )
  29. /*++
  30. Routine Description:
  31. This is the DLL initialization routine for dhcpsapi.dll.
  32. Arguments:
  33. Standard.
  34. Return Value:
  35. TRUE iff initialization succeeded.
  36. --*/
  37. {
  38. DWORD Error = ERROR_SUCCESS;
  39. BOOL BoolError;
  40. DWORD Length;
  41. UNREFERENCED_PARAMETER(DllHandle); // avoid compiler warnings
  42. UNREFERENCED_PARAMETER(Context); // avoid compiler warnings
  43. //
  44. // Handle attaching netlogon.dll to a new process.
  45. //
  46. if (Reason == DLL_PROCESS_ATTACH) {
  47. if ( !DisableThreadLibraryCalls( DllHandle ) ) {
  48. return( FALSE );
  49. }
  50. try {
  51. InitializeCriticalSection(&DhcpsapiDllCritSect);
  52. } except ( I_RpcExceptionFilter(RpcExceptionCode())) {
  53. Error = GetLastError( );
  54. return FALSE;
  55. }
  56. } else if (Reason == DLL_PROCESS_DETACH) {
  57. DeleteCriticalSection( &DhcpsapiDllCritSect );
  58. }
  59. return( TRUE );
  60. }
  61. VOID _cdecl
  62. DbgPrint( char *, ... );
  63. LPWSTR _inline
  64. DhcpOemToUnicode( // convert from ansi buffer to uni buffer
  65. IN LPSTR Ansi,
  66. IN OUT LPWSTR Unicode
  67. )
  68. {
  69. if( NULL == Unicode || NULL == Ansi ) { // should not happen
  70. return NULL;
  71. }
  72. if( -1 == mbstowcs(Unicode, Ansi, 1+strlen(Ansi))) {
  73. return NULL;
  74. }
  75. return Unicode;
  76. }
  77. //DOC DhcpDsInit must be called exactly once per process.. this initializes the
  78. //DOC memory and other structures for this process. This initializes some DS
  79. //DOC object handles (memory), and hence is slow as this has to read from DS.
  80. DWORD
  81. DhcpDsInit(
  82. VOID
  83. )
  84. {
  85. DWORD Err = NO_ERROR;
  86. EnterCriticalSection(&DhcpsapiDllCritSect);
  87. do {
  88. if( 0 != Initialized ) {
  89. break;
  90. }
  91. TlsIndex = TlsAlloc();
  92. if( 0xFFFFFFFF == TlsIndex ) {
  93. Err = GetLastError();
  94. break;
  95. }
  96. Err = DhcpDsInitDS(0, NULL);
  97. if( ERROR_SUCCESS != Err ) {
  98. TlsFree(TlsIndex);
  99. TlsIndex = 0xFFFFFFFF;
  100. }
  101. break;
  102. } while ( 0 );
  103. if( NO_ERROR == Err ) Initialized ++;
  104. LeaveCriticalSection(&DhcpsapiDllCritSect);
  105. return Err;
  106. }
  107. //DOC DhcpDsCleanup undoes the effect of any DhcpDsInit. This function should be
  108. //DOC called exactly once for each process, and only at termination. Note that
  109. //DOC it is safe to call this function even if DhcpDsInit does not succeed.
  110. VOID
  111. DhcpDsCleanup(
  112. VOID
  113. )
  114. {
  115. EnterCriticalSection(&DhcpsapiDllCritSect);
  116. do {
  117. if( 0 == Initialized ) break;
  118. Initialized --;
  119. if( 0 != Initialized ) break;
  120. TlsFree(TlsIndex);
  121. DhcpDsCleanupDS();
  122. TlsIndex = 0xFFFFFFFF;
  123. } while ( 0 );
  124. LeaveCriticalSection(&DhcpsapiDllCritSect);
  125. }
  126. #define DHCP_FLAGS_DONT_ACCESS_DS 0x01
  127. #define DHCP_FLAGS_DONT_DO_RPC 0x02
  128. //DOC DhcpSetThreadOptions currently allows only one option to be set. This is the
  129. //DOC flag DHCP_FLAGS_DONT_ACCESS_DS. This affects only the current executing thread.
  130. //DOC When this function is executed, all calls made further DONT access the registry,
  131. //DOC excepting the DhcpEnumServers, DhcpAddServer and DhcpDeleteServer calls.
  132. DWORD
  133. DhcpSetThreadOptions( // set options for current thread
  134. IN DWORD Flags, // options, currently 0 or DHCP_FLAGS_DONT_ACCESS_DS
  135. IN LPVOID Reserved // must be NULL, reserved for future
  136. )
  137. {
  138. BOOL Err;
  139. Err = TlsSetValue(TlsIndex, ULongToPtr(Flags));
  140. if( FALSE == Err ) { // could not set the value?
  141. return GetLastError();
  142. }
  143. return ERROR_SUCCESS;
  144. }
  145. //DOC DhcpGetThreadOptions retrieves the current thread options as set by DhcpSetThreadOptions.
  146. //DOC If none were set, the return value is zero.
  147. DWORD
  148. DhcpGetThreadOptions( // get current thread options
  149. OUT LPDWORD pFlags, // this DWORD is filled with current optiosn..
  150. IN OUT LPVOID Reserved // must be NULL, reserved for future
  151. )
  152. {
  153. if( NULL == pFlags ) return ERROR_INVALID_PARAMETER;
  154. *pFlags = (DWORD)((DWORD_PTR)TlsGetValue(TlsIndex));
  155. if( 0 == *pFlags ) return GetLastError(); // dont know if there were no options or error
  156. return ERROR_SUCCESS;
  157. }
  158. //DOC DontAccessDs is an inline that checks to see if requested NOT to access DS ..
  159. BOOL _inline // TRUE ==> Dont access DS.
  160. DontAccessDs( // check to see if requested NOT to access DS
  161. VOID
  162. )
  163. {
  164. DWORD Flags;
  165. if( CFLAG_DONT_DO_DSWORK ) return TRUE; // if DS is turned off return TRUE immediately..
  166. Flags = (DWORD)((DWORD_PTR)TlsGetValue(TlsIndex)); // dont bother if it fails, as this would be 0 then.
  167. return (Flags & DHCP_FLAGS_DONT_ACCESS_DS)? TRUE : FALSE;
  168. }
  169. //DOC DontDoRPC is an inline that checks to see if requested NOT to do RPC (maybe only DS)..
  170. BOOL _inline // TRUE ==> Dont do RPC
  171. DontDoRPC( // check to see if requested not to do RPC
  172. VOID
  173. )
  174. {
  175. DWORD Flags;
  176. Flags = (DWORD)((DWORD_PTR)TlsGetValue(TlsIndex)); // dont bother if it fails, as this would be 0 then.
  177. return (Flags & DHCP_FLAGS_DONT_DO_RPC)? TRUE : FALSE;
  178. }
  179. //
  180. // API proto types
  181. //
  182. //
  183. // Subnet APIs
  184. //
  185. DWORD
  186. DhcpCreateSubnet(
  187. LPWSTR ServerIpAddress,
  188. DHCP_IP_ADDRESS SubnetAddress,
  189. LPDHCP_SUBNET_INFO SubnetInfo
  190. )
  191. /*++
  192. Routine Description:
  193. This function creates a new subnet structure in the server
  194. registry database. The server will start managing the new subnet
  195. and distribute IP address to clients from that subnet. However
  196. the administrator should call DhcpAddSubnetElement() to add an
  197. address range for distribution. The PrimaryHost field specified in
  198. the SubnetInfo should be same as the server pointed by
  199. ServerIpAddress.
  200. Arguments:
  201. ServerIpAddress : IP address string of the DHCP server (Primary).
  202. SubnetAddress : IP Address of the new subnet.
  203. SubnetInfo : Pointer to the new subnet information structure.
  204. Return Value:
  205. ERROR_DHCP_SUBNET_EXISTS - if the subnet is already managed.
  206. ERROR_INVALID_PARAMETER - if the information structure contains an
  207. inconsistent fields.
  208. other WINDOWS errors.
  209. --*/
  210. {
  211. DWORD Status;
  212. Status = ERROR_SUCCESS;
  213. RedoRpc: RpcTryExcept {
  214. Status = R_DhcpCreateSubnet(
  215. ServerIpAddress,
  216. SubnetAddress,
  217. SubnetInfo
  218. );
  219. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  220. Status = RpcExceptionCode();
  221. } RpcEndExcept;
  222. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  223. !DhcpGlobalTryDownlevel ) {
  224. DhcpGlobalTryDownlevel = TRUE;
  225. goto RedoRpc;
  226. }
  227. return Status;
  228. }
  229. DWORD
  230. DhcpSetSubnetInfo(
  231. LPWSTR ServerIpAddress,
  232. DHCP_IP_ADDRESS SubnetAddress,
  233. LPDHCP_SUBNET_INFO SubnetInfo
  234. )
  235. /*++
  236. Routine Description:
  237. This function sets the information fields of the subnet that is already
  238. managed by the server. The valid fields that can be modified are 1.
  239. SubnetName, 2. SubnetComment, 3. PrimaryHost.NetBiosName and 4.
  240. PrimaryHost.HostName. Other fields can't be modified.
  241. Arguments:
  242. ServerIpAddress : IP address string of the DHCP server.
  243. SubnetAddress : IP Address of the subnet.
  244. SubnetInfo : Pointer to the subnet information structure.
  245. Return Value:
  246. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  247. Other WINDOWS errors.
  248. --*/
  249. {
  250. DWORD Status;
  251. Status = ERROR_SUCCESS;
  252. RedoRpc: RpcTryExcept {
  253. Status = R_DhcpSetSubnetInfo(
  254. ServerIpAddress,
  255. SubnetAddress,
  256. SubnetInfo
  257. );
  258. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  259. Status = RpcExceptionCode();
  260. } RpcEndExcept;
  261. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  262. !DhcpGlobalTryDownlevel ) {
  263. DhcpGlobalTryDownlevel = TRUE;
  264. goto RedoRpc;
  265. }
  266. return Status;
  267. }
  268. DWORD
  269. DhcpGetSubnetInfo(
  270. LPWSTR ServerIpAddress,
  271. DHCP_IP_ADDRESS SubnetAddress,
  272. LPDHCP_SUBNET_INFO *SubnetInfo
  273. )
  274. /*++
  275. Routine Description:
  276. This function retrieves the information of the subnet managed by
  277. the server.
  278. Arguments:
  279. ServerIpAddress : IP address string of the DHCP server.
  280. SubnetAddress : IP Address of the subnet.
  281. SubnetInfo : Pointer to a location where the subnet information
  282. structure pointer is returned. Caller should free up
  283. this buffer after use by calling DhcpRPCFreeMemory().
  284. Return Value:
  285. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  286. Other WINDOWS errors.
  287. --*/
  288. {
  289. DWORD Status;
  290. RedoRpc: RpcTryExcept {
  291. Status = R_DhcpGetSubnetInfo(
  292. ServerIpAddress,
  293. SubnetAddress,
  294. SubnetInfo
  295. );
  296. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  297. Status = RpcExceptionCode();
  298. } RpcEndExcept;
  299. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  300. !DhcpGlobalTryDownlevel ) {
  301. DhcpGlobalTryDownlevel = TRUE;
  302. goto RedoRpc;
  303. }
  304. return Status;
  305. }
  306. DWORD
  307. DhcpEnumSubnets(
  308. DHCP_CONST WCHAR *ServerIpAddress,
  309. DHCP_RESUME_HANDLE *ResumeHandle,
  310. DWORD PreferredMaximum,
  311. LPDHCP_IP_ARRAY *EnumInfo,
  312. DWORD *ElementsRead,
  313. DWORD *ElementsTotal
  314. )
  315. /*++
  316. Routine Description:
  317. This function enumerates the available subnets.
  318. Arguments:
  319. ServerIpAddress : IP address string of the DHCP server.
  320. ResumeHandle : Pointer to a resume handle where the resume
  321. information is returned. The resume handle should be set to
  322. zero on first call and left unchanged for subsequent calls.
  323. PreferredMaximum : Preferred maximum length of the return buffer.
  324. EnumInfo : Pointer to a location where the return buffer
  325. pointer is stored. Caller should free up the buffer after use
  326. by calling DhcpRPCFreeMemory().
  327. ElementsRead : Pointer to a DWORD where the number of subnet
  328. elements in the above buffer is returned.
  329. ElementsTotal : Pointer to a DWORD where the total number of
  330. elements remaining from the current position is returned.
  331. Return Value:
  332. ERROR_MORE_DATA - if more elements available to enumerate.
  333. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  334. Other WINDOWS errors.
  335. --*/
  336. {
  337. DWORD Status;
  338. RedoRpc: RpcTryExcept {
  339. Status = R_DhcpEnumSubnets(
  340. ServerIpAddress,
  341. ResumeHandle,
  342. PreferredMaximum,
  343. EnumInfo,
  344. ElementsRead,
  345. ElementsTotal
  346. );
  347. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  348. Status = RpcExceptionCode();
  349. } RpcEndExcept;
  350. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  351. !DhcpGlobalTryDownlevel ) {
  352. DhcpGlobalTryDownlevel = TRUE;
  353. goto RedoRpc;
  354. }
  355. return Status;
  356. }
  357. DWORD
  358. DhcpAddSubnetElement(
  359. LPWSTR ServerIpAddress,
  360. DHCP_IP_ADDRESS SubnetAddress,
  361. LPDHCP_SUBNET_ELEMENT_DATA AddElementInfo
  362. )
  363. /*++
  364. Routine Description:
  365. This function adds a enumerable type of subnet elements to the
  366. specified subnet. The new elements that are added to the subnet will
  367. come into effect immediately.
  368. NOTE: It is not clear now how do we handle the new secondary hosts.
  369. Arguments:
  370. ServerIpAddress : IP address string of the DHCP server.
  371. SubnetAddress : IP Address of the subnet.
  372. AddElementInfo : Pointer to an element information structure
  373. containing new element that is added to the subnet.
  374. DhcpIPClusters element type is invalid to specify.
  375. Return Value:
  376. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  377. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  378. data.
  379. Other WINDOWS errors.
  380. --*/
  381. {
  382. DWORD Status;
  383. Status = ERROR_SUCCESS;
  384. RedoRpc: RpcTryExcept {
  385. Status = R_DhcpAddSubnetElement(
  386. ServerIpAddress,
  387. SubnetAddress,
  388. AddElementInfo
  389. );
  390. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  391. Status = RpcExceptionCode();
  392. } RpcEndExcept;
  393. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  394. !DhcpGlobalTryDownlevel ) {
  395. DhcpGlobalTryDownlevel = TRUE;
  396. goto RedoRpc;
  397. }
  398. return Status;
  399. }
  400. DWORD
  401. DhcpEnumSubnetElements(
  402. LPWSTR ServerIpAddress,
  403. DHCP_IP_ADDRESS SubnetAddress,
  404. DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
  405. DHCP_RESUME_HANDLE *ResumeHandle,
  406. DWORD PreferredMaximum,
  407. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY *EnumElementInfo,
  408. DWORD *ElementsRead,
  409. DWORD *ElementsTotal
  410. )
  411. /*++
  412. Routine Description:
  413. This function enumerates the eumerable fields of a subnet.
  414. Arguments:
  415. ServerIpAddress : IP address string of the DHCP server.
  416. SubnetAddress : IP Address of the subnet.
  417. EnumElementType : Type of the subnet element that are enumerated.
  418. ResumeHandle : Pointer to a resume handle where the resume
  419. information is returned. The resume handle should be set to
  420. zero on first call and left unchanged for subsequent calls.
  421. PreferredMaximum : Preferred maximum length of the return buffer.
  422. EnumElementInfo : Pointer to a location where the return buffer
  423. pointer is stored. Caller should free up the buffer after use
  424. by calling DhcpRPCFreeMemory().
  425. ElementsRead : Pointer to a DWORD where the number of subnet
  426. elements in the above buffer is returned.
  427. ElementsTotal : Pointer to a DWORD where the total number of
  428. elements remaining from the current position is returned.
  429. Return Value:
  430. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  431. ERROR_MORE_DATA - if more elements available to enumerate.
  432. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  433. Other WINDOWS errors.
  434. --*/
  435. {
  436. DWORD Status;
  437. RedoRpc: RpcTryExcept {
  438. Status = R_DhcpEnumSubnetElements(
  439. ServerIpAddress,
  440. SubnetAddress,
  441. EnumElementType,
  442. ResumeHandle,
  443. PreferredMaximum,
  444. EnumElementInfo,
  445. ElementsRead,
  446. ElementsTotal
  447. );
  448. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  449. Status = RpcExceptionCode();
  450. } RpcEndExcept;
  451. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  452. !DhcpGlobalTryDownlevel ) {
  453. DhcpGlobalTryDownlevel = TRUE;
  454. goto RedoRpc;
  455. }
  456. return Status;
  457. }
  458. DWORD
  459. DhcpRemoveSubnetElement(
  460. LPWSTR ServerIpAddress,
  461. DHCP_IP_ADDRESS SubnetAddress,
  462. LPDHCP_SUBNET_ELEMENT_DATA RemoveElementInfo,
  463. DHCP_FORCE_FLAG ForceFlag
  464. )
  465. /*++
  466. Routine Description:
  467. This function removes a subnet element from managing. If the subnet
  468. element is in use (for example, if the IpRange is in use) then it
  469. returns error according to the ForceFlag specified.
  470. Arguments:
  471. ServerIpAddress : IP address string of the DHCP server.
  472. SubnetAddress : IP Address of the subnet.
  473. RemoveElementInfo : Pointer to an element information structure
  474. containing element that should be removed from the subnet.
  475. DhcpIPClusters element type is invalid to specify.
  476. ForceFlag - Indicates how forcefully this element is removed.
  477. Return Value:
  478. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  479. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  480. data.
  481. DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
  482. reason it is has been used.
  483. Other WINDOWS errors.
  484. --*/
  485. {
  486. DWORD Status;
  487. Status = ERROR_SUCCESS;
  488. RedoRpc: RpcTryExcept {
  489. Status = R_DhcpRemoveSubnetElement(
  490. ServerIpAddress,
  491. SubnetAddress,
  492. RemoveElementInfo,
  493. ForceFlag
  494. );
  495. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  496. Status = RpcExceptionCode();
  497. } RpcEndExcept;
  498. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  499. !DhcpGlobalTryDownlevel ) {
  500. DhcpGlobalTryDownlevel = TRUE;
  501. goto RedoRpc;
  502. }
  503. return Status;
  504. }
  505. DWORD
  506. DhcpDeleteSubnet(
  507. LPWSTR ServerIpAddress,
  508. DHCP_IP_ADDRESS SubnetAddress,
  509. DHCP_FORCE_FLAG ForceFlag
  510. )
  511. /*++
  512. Routine Description:
  513. This function removes a subnet from DHCP server management. If the
  514. subnet is in use (for example, if the IpRange is in use)
  515. then it returns error according to the ForceFlag specified.
  516. Arguments:
  517. ServerIpAddress : IP address string of the DHCP server.
  518. SubnetAddress : IP Address of the subnet.
  519. ForceFlag - Indicates how forcefully this element is removed.
  520. Return Value:
  521. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  522. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  523. data.
  524. DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
  525. reason it is has been used.
  526. Other WINDOWS errors.
  527. --*/
  528. {
  529. DWORD Status;
  530. Status = ERROR_SUCCESS;
  531. RedoRpc: RpcTryExcept {
  532. Status = R_DhcpDeleteSubnet(
  533. ServerIpAddress,
  534. SubnetAddress,
  535. ForceFlag
  536. );
  537. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  538. Status = RpcExceptionCode();
  539. } RpcEndExcept;
  540. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  541. !DhcpGlobalTryDownlevel ) {
  542. DhcpGlobalTryDownlevel = TRUE;
  543. goto RedoRpc;
  544. }
  545. return Status;
  546. }
  547. //
  548. // Option APIs
  549. //
  550. DWORD
  551. DhcpCreateOption(
  552. LPWSTR ServerIpAddress,
  553. DHCP_OPTION_ID OptionID,
  554. LPDHCP_OPTION OptionInfo
  555. )
  556. /*++
  557. Routine Description:
  558. This function creates a new option that will be managed by the
  559. server. The optionID specified the ID of the new option, it should
  560. be within 0-255 range. If no default value is specified for this
  561. option, then this API automatically adds a default value from RFC
  562. 1122 doc. (if it is defined).
  563. Arguments:
  564. ServerIpAddress : IP address string of the DHCP server.
  565. OptionID : The ID of the new option.
  566. OptionInfo : Pointer to new option information structure.
  567. Return Value:
  568. ERROR_DHCP_OPTION_EXISTS - if the option exists already.
  569. other WINDOWS errors.
  570. --*/
  571. {
  572. DWORD Status;
  573. Status = ERROR_SUCCESS;
  574. RedoRpc: RpcTryExcept {
  575. Status = R_DhcpCreateOption(
  576. ServerIpAddress,
  577. OptionID,
  578. OptionInfo
  579. );
  580. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  581. Status = RpcExceptionCode();
  582. } RpcEndExcept;
  583. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  584. !DhcpGlobalTryDownlevel ) {
  585. DhcpGlobalTryDownlevel = TRUE;
  586. goto RedoRpc;
  587. }
  588. return Status;
  589. }
  590. DWORD
  591. DhcpSetOptionInfo(
  592. LPWSTR ServerIpAddress,
  593. DHCP_OPTION_ID OptionID,
  594. LPDHCP_OPTION OptionInfo
  595. )
  596. /*++
  597. Routine Description:
  598. This functions sets the Options information fields.
  599. Arguments:
  600. ServerIpAddress : IP address string of the DHCP server.
  601. OptionID : The ID of the option to be set.
  602. OptionInfo : Pointer to new option information structure.
  603. Return Value:
  604. ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
  605. other WINDOWS errors.
  606. --*/
  607. {
  608. DWORD Status;
  609. Status = ERROR_SUCCESS;
  610. RedoRpc: RpcTryExcept {
  611. Status = R_DhcpSetOptionInfo(
  612. ServerIpAddress,
  613. OptionID,
  614. OptionInfo
  615. );
  616. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  617. Status = RpcExceptionCode();
  618. } RpcEndExcept;
  619. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  620. !DhcpGlobalTryDownlevel ) {
  621. DhcpGlobalTryDownlevel = TRUE;
  622. goto RedoRpc;
  623. }
  624. return Status;
  625. }
  626. DWORD
  627. DhcpGetOptionInfo(
  628. LPWSTR ServerIpAddress,
  629. DHCP_OPTION_ID OptionID,
  630. LPDHCP_OPTION *OptionInfo
  631. )
  632. /*++
  633. Routine Description:
  634. This function retrieves the current information structure of the specified
  635. option.
  636. Arguments:
  637. ServerIpAddress : IP address string of the DHCP server.
  638. OptionID : The ID of the option to be retrieved.
  639. OptionInfo : Pointer to a location where the retrieved option
  640. structure pointer is returned. Caller should free up
  641. the buffer after use by calling DhcpRPCFreeMemory().
  642. Return Value:
  643. ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
  644. other WINDOWS errors.
  645. --*/
  646. {
  647. DWORD Status;
  648. RedoRpc: RpcTryExcept {
  649. Status = R_DhcpGetOptionInfo(
  650. ServerIpAddress,
  651. OptionID,
  652. OptionInfo
  653. );
  654. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  655. Status = RpcExceptionCode();
  656. } RpcEndExcept;
  657. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  658. !DhcpGlobalTryDownlevel ) {
  659. DhcpGlobalTryDownlevel = TRUE;
  660. goto RedoRpc;
  661. }
  662. return Status;
  663. }
  664. DWORD
  665. DhcpEnumOptions(
  666. LPWSTR ServerIpAddress,
  667. DHCP_RESUME_HANDLE *ResumeHandle,
  668. DWORD PreferredMaximum,
  669. LPDHCP_OPTION_ARRAY *Options,
  670. DWORD *OptionsRead,
  671. DWORD *OptionsTotal
  672. )
  673. /*++
  674. Routine Description:
  675. This functions retrieves the information of all known options.
  676. Arguments:
  677. ServerIpAddress : IP address string of the DHCP server.
  678. ResumeHandle : Pointer to a resume handle where the resume
  679. information is returned. The resume handle should be set to
  680. zero on first call and left unchanged for subsequent calls.
  681. PreferredMaximum : Preferred maximum length of the return buffer.
  682. Options : Pointer to a location where the return buffer
  683. pointer is stored. Caller should free up this buffer
  684. after use by calling DhcpRPCFreeMemory().
  685. OptionsRead : Pointer to a DWORD where the number of options
  686. in the above buffer is returned.
  687. OptionsTotal : Pointer to a DWORD where the total number of
  688. options remaining from the current position is returned.
  689. Return Value:
  690. ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
  691. other WINDOWS errors.
  692. --*/
  693. {
  694. DWORD Status;
  695. RedoRpc: RpcTryExcept {
  696. Status = R_DhcpEnumOptions(
  697. ServerIpAddress,
  698. ResumeHandle,
  699. PreferredMaximum,
  700. Options,
  701. OptionsRead,
  702. OptionsTotal
  703. );
  704. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  705. Status = RpcExceptionCode();
  706. } RpcEndExcept;
  707. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  708. !DhcpGlobalTryDownlevel ) {
  709. DhcpGlobalTryDownlevel = TRUE;
  710. goto RedoRpc;
  711. }
  712. return Status;
  713. }
  714. DWORD
  715. DhcpRemoveOption(
  716. LPWSTR ServerIpAddress,
  717. DHCP_OPTION_ID OptionID
  718. )
  719. /*++
  720. Routine Description:
  721. This function removes the specified option from the server database.
  722. Also it browses through the Global/Subnet/ReservedIP
  723. option lists and deletes them too (?? This will be too expensive.).
  724. Arguments:
  725. ServerIpAddress : IP address string of the DHCP server.
  726. OptionID : The ID of the option to be removed.
  727. Return Value:
  728. ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
  729. other WINDOWS errors.
  730. --*/
  731. {
  732. DWORD Status;
  733. Status = ERROR_SUCCESS;
  734. RedoRpc: RpcTryExcept {
  735. Status = R_DhcpRemoveOption(
  736. ServerIpAddress,
  737. OptionID
  738. );
  739. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  740. Status = RpcExceptionCode();
  741. } RpcEndExcept;
  742. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  743. !DhcpGlobalTryDownlevel ) {
  744. DhcpGlobalTryDownlevel = TRUE;
  745. goto RedoRpc;
  746. }
  747. return Status;
  748. }
  749. DWORD
  750. DhcpSetOptionValue(
  751. LPWSTR ServerIpAddress,
  752. DHCP_OPTION_ID OptionID,
  753. LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  754. LPDHCP_OPTION_DATA OptionValue
  755. )
  756. /*++
  757. Routine Description:
  758. The function sets a new option value at the specified scope. If
  759. there is already a value available for the specified option at
  760. specified scope then this function will replace it otherwise it will
  761. create a new entry at that scope.
  762. Arguments:
  763. ServerIpAddress : IP address string of the DHCP server.
  764. OptionID : The ID of the option whose value should be set.
  765. ScopeInfo : Pointer to the scope information structure.
  766. OptionValue : Pointer to the option value structure.
  767. Return Value:
  768. ERROR_DHCP_OPTION_NOT_PRESENT - if the option is unknown.
  769. ERROR_INVALID_PARAMETER - if the scope information specified is invalid.
  770. other WINDOWS errors.
  771. --*/
  772. {
  773. DWORD Status;
  774. Status = ERROR_SUCCESS;
  775. RedoRpc: RpcTryExcept {
  776. Status = R_DhcpSetOptionValue(
  777. ServerIpAddress,
  778. OptionID,
  779. ScopeInfo,
  780. OptionValue
  781. );
  782. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  783. Status = RpcExceptionCode();
  784. } RpcEndExcept;
  785. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  786. !DhcpGlobalTryDownlevel ) {
  787. DhcpGlobalTryDownlevel = TRUE;
  788. goto RedoRpc;
  789. }
  790. return Status;
  791. }
  792. DWORD
  793. DhcpSetOptionValues(
  794. LPWSTR ServerIpAddress,
  795. LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  796. LPDHCP_OPTION_VALUE_ARRAY OptionValues
  797. )
  798. /*++
  799. Routine Description:
  800. The function sets a set of new options value at the specified scope.
  801. If there is already a value available for the specified option at
  802. specified scope then this function will replace it otherwise it will
  803. create a new entry at that scope.
  804. Arguments:
  805. ServerIpAddress : IP address string of the DHCP server.
  806. ScopeInfo : Pointer to the scope information structure.
  807. OptionValue : Pointer to the option value structure.
  808. Return Value:
  809. ERROR_DHCP_OPTION_NOT_PRESENT - if the option is unknown.
  810. ERROR_INVALID_PARAMETER - if the scope information specified is invalid.
  811. other WINDOWS errors.
  812. --*/
  813. {
  814. DWORD Status;
  815. Status = ERROR_SUCCESS;
  816. RedoRpc: RpcTryExcept {
  817. Status = R_DhcpSetOptionValues(
  818. ServerIpAddress,
  819. ScopeInfo,
  820. OptionValues
  821. );
  822. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  823. Status = RpcExceptionCode();
  824. } RpcEndExcept;
  825. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  826. !DhcpGlobalTryDownlevel ) {
  827. DhcpGlobalTryDownlevel = TRUE;
  828. goto RedoRpc;
  829. }
  830. return Status;
  831. }
  832. DWORD
  833. DhcpGetOptionValue(
  834. LPWSTR ServerIpAddress,
  835. DHCP_OPTION_ID OptionID,
  836. LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  837. LPDHCP_OPTION_VALUE *OptionValue
  838. )
  839. /*++
  840. Routine Description:
  841. This function retrieves the current option value at the specified
  842. scope. It returns error if there is no option value is available at
  843. the specified scope.
  844. Arguments:
  845. ServerIpAddress : IP address string of the DHCP server.
  846. OptionID : The ID of the option whose value is returned.
  847. ScopeInfo : Pointer to the scope information structure.
  848. OptionValue : Pointer to a location where the pointer to the option
  849. value structure is returned. Caller should free up this buffer
  850. after use by calling DhcpRPCFreeMemory().
  851. Return Value:
  852. ERROR_DHCP_OPTION_NOT_PRESENT - if the option is unknown.
  853. ERROR_DHCP_NO_OPTION_VALUE - if no the option value is available at
  854. the specified scope.
  855. other WINDOWS errors.
  856. --*/
  857. {
  858. DWORD Status;
  859. RedoRpc: RpcTryExcept {
  860. Status = R_DhcpGetOptionValue(
  861. ServerIpAddress,
  862. OptionID,
  863. ScopeInfo,
  864. OptionValue
  865. );
  866. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  867. Status = RpcExceptionCode();
  868. } RpcEndExcept;
  869. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  870. !DhcpGlobalTryDownlevel ) {
  871. DhcpGlobalTryDownlevel = TRUE;
  872. goto RedoRpc;
  873. }
  874. return Status;
  875. }
  876. DWORD
  877. DhcpEnumOptionValues(
  878. LPWSTR ServerIpAddress,
  879. LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  880. DHCP_RESUME_HANDLE *ResumeHandle,
  881. DWORD PreferredMaximum,
  882. LPDHCP_OPTION_VALUE_ARRAY *OptionValues,
  883. DWORD *OptionsRead,
  884. DWORD *OptionsTotal
  885. )
  886. /*++
  887. Routine Description:
  888. This function enumerates the available options values at the
  889. specified scope.
  890. Arguments:
  891. ServerIpAddress : IP address string of the DHCP server.
  892. ScopeInfo : Pointer to the scope information structure.
  893. ResumeHandle : Pointer to a resume handle where the resume
  894. information is returned. The resume handle should be set to
  895. zero on first call and left unchanged for subsequent calls.
  896. PreferredMaximum : Preferred maximum length of the return buffer.
  897. OptionValues : Pointer to a location where the return buffer
  898. pointer is stored. Caller should free up this buffer
  899. after use by calling DhcpRPCFreeMemory().
  900. OptionsRead : Pointer to a DWORD where the number of options
  901. in the above buffer is returned.
  902. OptionsTotal : Pointer to a DWORD where the total number of
  903. options remaining from the current position is returned.
  904. Return Value:
  905. ERROR_DHCP_SCOPE_NOT_PRESENT - if the scope is unknown.
  906. ERROR_MORE_DATA - if more options available to enumerate.
  907. ERROR_NO_MORE_ITEMS - if no more option to enumerate.
  908. Other WINDOWS errors.
  909. --*/
  910. {
  911. DWORD Status;
  912. RedoRpc: RpcTryExcept {
  913. Status = R_DhcpEnumOptionValues(
  914. ServerIpAddress,
  915. ScopeInfo,
  916. ResumeHandle,
  917. PreferredMaximum,
  918. OptionValues,
  919. OptionsRead,
  920. OptionsTotal
  921. );
  922. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  923. Status = RpcExceptionCode();
  924. } RpcEndExcept;
  925. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  926. !DhcpGlobalTryDownlevel ) {
  927. DhcpGlobalTryDownlevel = TRUE;
  928. goto RedoRpc;
  929. }
  930. return Status;
  931. }
  932. DWORD
  933. DhcpRemoveOptionValue(
  934. LPWSTR ServerIpAddress,
  935. DHCP_OPTION_ID OptionID,
  936. LPDHCP_OPTION_SCOPE_INFO ScopeInfo
  937. )
  938. /*++
  939. Routine Description:
  940. This function removes the specified option from specified scope.
  941. Arguments:
  942. ServerIpAddress : IP address string of the DHCP server.
  943. OptionID : The ID of the option to be removed.
  944. ScopeInfo : Pointer to the scope information structure.
  945. Return Value:
  946. ERROR_DHCP_OPTION_NOT_PRESENT - if the option does not exist.
  947. other WINDOWS errors.
  948. --*/
  949. {
  950. DWORD Status;
  951. Status = ERROR_SUCCESS;
  952. RedoRpc: RpcTryExcept {
  953. Status = R_DhcpRemoveOptionValue(
  954. ServerIpAddress,
  955. OptionID,
  956. ScopeInfo
  957. );
  958. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  959. Status = RpcExceptionCode();
  960. } RpcEndExcept;
  961. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  962. !DhcpGlobalTryDownlevel ) {
  963. DhcpGlobalTryDownlevel = TRUE;
  964. goto RedoRpc;
  965. }
  966. return Status;
  967. }
  968. //
  969. // Client APIs
  970. //
  971. DWORD
  972. DhcpCreateClientInfo(
  973. LPWSTR ServerIpAddress,
  974. LPDHCP_CLIENT_INFO ClientInfo
  975. )
  976. /*++
  977. Routine Description:
  978. This function creates a client record in server's database. Also
  979. this marks the specified client IP address as unavailable (or
  980. distributed). This function returns error under the following cases :
  981. 1. If the specified client IP address is not within the server
  982. management.
  983. 2. If the specified client IP address is already unavailable.
  984. 3. If the specified client record is already in the server's
  985. database.
  986. This function may be used to distribute IP addresses manually.
  987. Arguments:
  988. ServerIpAddress : IP address string of the DHCP server.
  989. ClientInfo : Pointer to the client information structure.
  990. Return Value:
  991. ERROR_DHCP_IP_ADDRESS_NOT_MANAGED - if the specified client
  992. IP address is not managed by the server.
  993. ERROR_DHCP_IP_ADDRESS_NOT_AVAILABLE - if the specified client IP
  994. address is not available. May be in use by some other client.
  995. ERROR_DHCP_CLIENT_EXISTS - if the client record exists already in
  996. server's database.
  997. Other WINDOWS errors.
  998. --*/
  999. {
  1000. DWORD Status;
  1001. Status = ERROR_SUCCESS;
  1002. RedoRpc: RpcTryExcept {
  1003. Status = R_DhcpCreateClientInfo(
  1004. ServerIpAddress,
  1005. ClientInfo
  1006. );
  1007. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1008. Status = RpcExceptionCode();
  1009. } RpcEndExcept;
  1010. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1011. !DhcpGlobalTryDownlevel ) {
  1012. DhcpGlobalTryDownlevel = TRUE;
  1013. goto RedoRpc;
  1014. }
  1015. return Status;
  1016. }
  1017. DWORD
  1018. DhcpSetClientInfo(
  1019. LPWSTR ServerIpAddress,
  1020. LPDHCP_CLIENT_INFO ClientInfo
  1021. )
  1022. /*++
  1023. Routine Description:
  1024. This function sets client information record on the server's
  1025. database.
  1026. Arguments:
  1027. ServerIpAddress : IP address string of the DHCP server.
  1028. ClientInfo : Pointer to the client information structure.
  1029. Return Value:
  1030. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  1031. not exist on the server's database.
  1032. ERROR_INVALID_PARAMETER - if the client information structure
  1033. contains inconsistent data.
  1034. Other WINDOWS errors.
  1035. --*/
  1036. {
  1037. DWORD Status;
  1038. RedoRpc: RpcTryExcept {
  1039. Status = R_DhcpSetClientInfo(
  1040. ServerIpAddress,
  1041. ClientInfo
  1042. );
  1043. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1044. Status = RpcExceptionCode();
  1045. } RpcEndExcept;
  1046. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1047. !DhcpGlobalTryDownlevel ) {
  1048. DhcpGlobalTryDownlevel = TRUE;
  1049. goto RedoRpc;
  1050. }
  1051. return Status;
  1052. }
  1053. DWORD
  1054. DhcpGetClientInfo(
  1055. LPWSTR ServerIpAddress,
  1056. LPDHCP_SEARCH_INFO SearchInfo,
  1057. LPDHCP_CLIENT_INFO *ClientInfo
  1058. )
  1059. /*++
  1060. Routine Description:
  1061. This function retrieves client information record from the server's
  1062. database.
  1063. Arguments:
  1064. ServerIpAddress : IP address string of the DHCP server.
  1065. SearchInfo : Pointer to a search information record which is the key
  1066. for the client's record search.
  1067. ClientInfo : Pointer to a location where the pointer to the client
  1068. information structure is returned. This caller should free up
  1069. this buffer after use by calling DhcpRPCFreeMemory().
  1070. Return Value:
  1071. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  1072. not exist on the server's database.
  1073. ERROR_INVALID_PARAMETER - if the search information invalid.
  1074. Other WINDOWS errors.
  1075. --*/
  1076. {
  1077. DWORD Status;
  1078. RedoRpc: RpcTryExcept {
  1079. Status = R_DhcpGetClientInfo(
  1080. ServerIpAddress,
  1081. SearchInfo,
  1082. ClientInfo
  1083. );
  1084. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1085. Status = RpcExceptionCode();
  1086. } RpcEndExcept;
  1087. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1088. !DhcpGlobalTryDownlevel ) {
  1089. DhcpGlobalTryDownlevel = TRUE;
  1090. goto RedoRpc;
  1091. }
  1092. return Status;
  1093. }
  1094. DWORD
  1095. DhcpDeleteClientInfo(
  1096. LPWSTR ServerIpAddress,
  1097. LPDHCP_SEARCH_INFO ClientInfo
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. This function deletes the specified client record. Also it frees up
  1102. the client IP address for redistribution.
  1103. Arguments:
  1104. ServerIpAddress : IP address string of the DHCP server.
  1105. ClientInfo : Pointer to a client information which is the key for
  1106. the client's record search.
  1107. Return Value:
  1108. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  1109. not exist on the server's database.
  1110. Other WINDOWS errors.
  1111. --*/
  1112. {
  1113. DWORD Status;
  1114. Status = ERROR_SUCCESS;
  1115. RedoRpc: RpcTryExcept {
  1116. Status = R_DhcpDeleteClientInfo(
  1117. ServerIpAddress,
  1118. ClientInfo
  1119. );
  1120. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1121. Status = RpcExceptionCode();
  1122. } RpcEndExcept;
  1123. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1124. !DhcpGlobalTryDownlevel ) {
  1125. DhcpGlobalTryDownlevel = TRUE;
  1126. goto RedoRpc;
  1127. }
  1128. return Status;
  1129. }
  1130. DWORD
  1131. DhcpEnumSubnetClients(
  1132. LPWSTR ServerIpAddress,
  1133. DHCP_IP_ADDRESS SubnetAddress,
  1134. DHCP_RESUME_HANDLE *ResumeHandle,
  1135. DWORD PreferredMaximum,
  1136. LPDHCP_CLIENT_INFO_ARRAY *ClientInfo,
  1137. DWORD *ClientsRead,
  1138. DWORD *ClientsTotal
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. This function returns all registered clients of the specified
  1143. subnet.
  1144. Arguments:
  1145. ServerIpAddress : IP address string of the DHCP server.
  1146. SubnetAddress : IP Address of the subnet.
  1147. ResumeHandle : Pointer to a resume handle where the resume
  1148. information is returned. The resume handle should be set to zero on
  1149. first call and left unchanged for subsequent calls.
  1150. PreferredMaximum : Preferred maximum length of the return buffer.
  1151. ClientInfo : Pointer to a location where the return buffer
  1152. pointer is stored. Caller should free up this buffer
  1153. after use by calling DhcpRPCFreeMemory().
  1154. ClientsRead : Pointer to a DWORD where the number of clients
  1155. that in the above buffer is returned.
  1156. ClientsTotal : Pointer to a DWORD where the total number of
  1157. clients remaining from the current position is returned.
  1158. Return Value:
  1159. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  1160. ERROR_MORE_DATA - if more elements available to enumerate.
  1161. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  1162. Other WINDOWS errors.
  1163. --*/
  1164. {
  1165. DWORD Status;
  1166. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1167. RedoRpc: RpcTryExcept {
  1168. Status = R_DhcpEnumSubnetClients(
  1169. ServerIpAddress,
  1170. SubnetAddress,
  1171. ResumeHandle,
  1172. PreferredMaximum,
  1173. ClientInfo,
  1174. ClientsRead,
  1175. ClientsTotal
  1176. );
  1177. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1178. Status = RpcExceptionCode();
  1179. } RpcEndExcept;
  1180. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1181. !DhcpGlobalTryDownlevel ) {
  1182. DhcpGlobalTryDownlevel = TRUE;
  1183. goto RedoRpc;
  1184. }
  1185. return Status;
  1186. }
  1187. DWORD
  1188. DhcpGetClientOptions(
  1189. LPWSTR ServerIpAddress,
  1190. DHCP_IP_ADDRESS ClientIpAddress,
  1191. DHCP_IP_MASK ClientSubnetMask,
  1192. LPDHCP_OPTION_LIST *ClientOptions
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This function retrieves the options that are given to the
  1197. specified client on boot request.
  1198. Arguments:
  1199. ServerIpAddress : IP address string of the DHCP server.
  1200. ClientIpAddress : IP Address of the client whose options to be
  1201. retrieved
  1202. ClientSubnetMask : Subnet mask of the client.
  1203. ClientOptions : Pointer to a location where the retrieved option
  1204. structure pointer is returned. Caller should free up
  1205. the buffer after use by calling DhcpRPCFreeMemory().
  1206. Return Value:
  1207. ERROR_DHCP_SUBNET_NOT_PRESENT - if the specified client subnet is
  1208. not managed by the server.
  1209. ERROR_DHCP_IP_ADDRESS_NOT_MANAGED - if the specified client
  1210. IP address is not managed by the server.
  1211. Other WINDOWS errors.
  1212. --*/
  1213. {
  1214. DWORD Status;
  1215. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1216. RedoRpc: RpcTryExcept {
  1217. Status = R_DhcpGetClientOptions(
  1218. ServerIpAddress,
  1219. ClientIpAddress,
  1220. ClientSubnetMask,
  1221. ClientOptions
  1222. );
  1223. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1224. Status = RpcExceptionCode();
  1225. } RpcEndExcept;
  1226. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1227. !DhcpGlobalTryDownlevel ) {
  1228. DhcpGlobalTryDownlevel = TRUE;
  1229. goto RedoRpc;
  1230. }
  1231. return Status;
  1232. }
  1233. DWORD
  1234. DhcpGetMibInfo(
  1235. LPWSTR ServerIpAddress,
  1236. LPDHCP_MIB_INFO *MibInfo
  1237. )
  1238. /*++
  1239. Routine Description:
  1240. This function retrieves all counter values of the DHCP server
  1241. service.
  1242. Arguments:
  1243. ServerIpAddress : IP address string of the DHCP server.
  1244. MibInfo : pointer a counter/table buffer. Caller should free up this
  1245. buffer after usage.
  1246. Return Value:
  1247. WINDOWS errors.
  1248. --*/
  1249. {
  1250. DWORD Status;
  1251. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1252. RedoRpc: RpcTryExcept {
  1253. Status = R_DhcpGetMibInfo(
  1254. ServerIpAddress,
  1255. MibInfo );
  1256. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1257. Status = RpcExceptionCode();
  1258. } RpcEndExcept;
  1259. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1260. !DhcpGlobalTryDownlevel ) {
  1261. DhcpGlobalTryDownlevel = TRUE;
  1262. goto RedoRpc;
  1263. }
  1264. return Status;
  1265. }
  1266. DWORD
  1267. DhcpServerSetConfig(
  1268. LPWSTR ServerIpAddress,
  1269. DWORD FieldsToSet,
  1270. LPDHCP_SERVER_CONFIG_INFO ConfigInfo
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. This function sets the DHCP server configuration information.
  1275. Serveral of the configuration information will become effective
  1276. immediately.
  1277. The following parameters require restart of the service after this
  1278. API is called successfully.
  1279. Set_APIProtocolSupport
  1280. Set_DatabaseName
  1281. Set_DatabasePath
  1282. Set_DatabaseLoggingFlag
  1283. Set_RestoreFlag
  1284. Arguments:
  1285. ServerIpAddress : IP address string of the DHCP server.
  1286. FieldsToSet : Bit mask of the fields in the ConfigInfo structure to
  1287. be set.
  1288. ConfigInfo: Pointer to the info structure to be set.
  1289. Return Value:
  1290. WINDOWS errors.
  1291. --*/
  1292. {
  1293. DWORD Status;
  1294. Status = ERROR_SUCCESS;
  1295. RedoRpc: RpcTryExcept {
  1296. Status = R_DhcpServerSetConfig(
  1297. ServerIpAddress,
  1298. FieldsToSet,
  1299. ConfigInfo );
  1300. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1301. Status = RpcExceptionCode();
  1302. } RpcEndExcept;
  1303. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1304. !DhcpGlobalTryDownlevel ) {
  1305. DhcpGlobalTryDownlevel = TRUE;
  1306. goto RedoRpc;
  1307. }
  1308. return Status;
  1309. }
  1310. DWORD
  1311. DhcpServerGetConfig(
  1312. LPWSTR ServerIpAddress,
  1313. LPDHCP_SERVER_CONFIG_INFO *ConfigInfo
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. This function retrieves the current configuration information of the
  1318. server.
  1319. Arguments:
  1320. ServerIpAddress : IP address string of the DHCP server.
  1321. ConfigInfo: Pointer to a location where the pointer to the dhcp
  1322. server config info structure is returned. Caller should free up
  1323. this structure after use.
  1324. Return Value:
  1325. WINDOWS errors.
  1326. --*/
  1327. {
  1328. DWORD Status;
  1329. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1330. RedoRpc: RpcTryExcept {
  1331. Status = R_DhcpServerGetConfig(
  1332. ServerIpAddress,
  1333. ConfigInfo );
  1334. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1335. Status = RpcExceptionCode();
  1336. } RpcEndExcept;
  1337. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1338. !DhcpGlobalTryDownlevel ) {
  1339. DhcpGlobalTryDownlevel = TRUE;
  1340. goto RedoRpc;
  1341. }
  1342. return Status;
  1343. }
  1344. DWORD
  1345. DhcpScanDatabase(
  1346. LPWSTR ServerIpAddress,
  1347. DHCP_IP_ADDRESS SubnetAddress,
  1348. DWORD FixFlag,
  1349. LPDHCP_SCAN_LIST *ScanList
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. This function scans the database entries and registry bit-map for
  1354. specified subnet scope and veryfies to see they match. If they
  1355. don't match, this api will return the list of inconsistent entries.
  1356. Optionally FixFlag can be used to fix the bad entries.
  1357. Arguments:
  1358. ServerIpAddress : IP address string of the DHCP server.
  1359. SubnetAddress : Address of the subnet scope to verify.
  1360. FixFlag : If this flag is TRUE, this api will fix the bad entries.
  1361. ScanList : List of bad entries returned. The caller should free up
  1362. this memory after it has been used.
  1363. Return Value:
  1364. WINDOWS errors.
  1365. --*/
  1366. {
  1367. DWORD Status;
  1368. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1369. RedoRpc: RpcTryExcept {
  1370. Status = R_DhcpScanDatabase(
  1371. ServerIpAddress,
  1372. SubnetAddress,
  1373. FixFlag,
  1374. ScanList );
  1375. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1376. Status = RpcExceptionCode();
  1377. } RpcEndExcept;
  1378. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1379. !DhcpGlobalTryDownlevel ) {
  1380. DhcpGlobalTryDownlevel = TRUE;
  1381. goto RedoRpc;
  1382. }
  1383. return Status;
  1384. }
  1385. DWORD
  1386. DhcpGetVersion(
  1387. LPWSTR ServerIpAddress,
  1388. LPDWORD MajorVersion,
  1389. LPDWORD MinorVersion
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. This function returns the major and minor version numbers of the
  1394. server.
  1395. Arguments:
  1396. ServerIpAddress : IP address string of the DHCP server.
  1397. MajorVersion : pointer to a location where the major version of the
  1398. server is returned.
  1399. MinorVersion : pointer to a location where the minor version of the
  1400. server is returned.
  1401. Return Value:
  1402. WINDOWS errors.
  1403. --*/
  1404. {
  1405. DWORD Status;
  1406. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1407. RedoRpc: RpcTryExcept {
  1408. Status = R_DhcpGetVersion(
  1409. ServerIpAddress,
  1410. MajorVersion,
  1411. MinorVersion );
  1412. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1413. Status = RpcExceptionCode();
  1414. } RpcEndExcept;
  1415. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1416. !DhcpGlobalTryDownlevel ) {
  1417. DhcpGlobalTryDownlevel = TRUE;
  1418. goto RedoRpc;
  1419. }
  1420. return Status;
  1421. }
  1422. VOID
  1423. DhcpRpcFreeMemory(
  1424. PVOID BufferPointer
  1425. )
  1426. /*++
  1427. Routine Description:
  1428. This function deallocates the memory that was alloted by the RPC and
  1429. given to the client as part of the retrun info structures.
  1430. Arguments:
  1431. BufferPointer : pointer to a memory block that is deallocated.
  1432. Return Value:
  1433. none.
  1434. --*/
  1435. {
  1436. MIDL_user_free( BufferPointer );
  1437. }
  1438. //
  1439. // NT4 SP1 interface
  1440. //
  1441. DWORD
  1442. DhcpAddSubnetElementV4(
  1443. DHCP_CONST WCHAR *ServerIpAddress,
  1444. DHCP_IP_ADDRESS SubnetAddress,
  1445. DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V4 * AddElementInfo
  1446. )
  1447. {
  1448. DWORD Status;
  1449. Status = ERROR_SUCCESS;
  1450. RedoRpc: RpcTryExcept {
  1451. Status = R_DhcpAddSubnetElementV4(
  1452. ServerIpAddress,
  1453. SubnetAddress,
  1454. AddElementInfo );
  1455. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1456. Status = RpcExceptionCode();
  1457. } RpcEndExcept;
  1458. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1459. !DhcpGlobalTryDownlevel ) {
  1460. DhcpGlobalTryDownlevel = TRUE;
  1461. goto RedoRpc;
  1462. }
  1463. return Status;
  1464. }
  1465. DWORD
  1466. DhcpEnumSubnetElementsV4(
  1467. LPWSTR ServerIpAddress,
  1468. DHCP_IP_ADDRESS SubnetAddress,
  1469. DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
  1470. DHCP_RESUME_HANDLE *ResumeHandle,
  1471. DWORD PreferredMaximum,
  1472. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *EnumElementInfo,
  1473. DWORD *ElementsRead,
  1474. DWORD *ElementsTotal
  1475. )
  1476. /*++
  1477. Routine Description:
  1478. This function enumerates the eumerable fields of a subnet.
  1479. Arguments:
  1480. ServerIpAddress : IP address string of the DHCP server.
  1481. SubnetAddress : IP Address of the subnet.
  1482. EnumElementType : Type of the subnet element that are enumerated.
  1483. ResumeHandle : Pointer to a resume handle where the resume
  1484. information is returned. The resume handle should be set to
  1485. zero on first call and left unchanged for subsequent calls.
  1486. PreferredMaximum : Preferred maximum length of the return buffer.
  1487. EnumElementInfo : Pointer to a location where the return buffer
  1488. pointer is stored. Caller should free up the buffer after use
  1489. by calling DhcpRPCFreeMemory().
  1490. ElementsRead : Pointer to a DWORD where the number of subnet
  1491. elements in the above buffer is returned.
  1492. ElementsTotal : Pointer to a DWORD where the total number of
  1493. elements remaining from the current position is returned.
  1494. Return Value:
  1495. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  1496. ERROR_MORE_DATA - if more elements available to enumerate.
  1497. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  1498. Other WINDOWS errors.
  1499. --*/
  1500. {
  1501. DWORD Status;
  1502. RedoRpc: RpcTryExcept {
  1503. Status = R_DhcpEnumSubnetElementsV4(
  1504. ServerIpAddress,
  1505. SubnetAddress,
  1506. EnumElementType,
  1507. ResumeHandle,
  1508. PreferredMaximum,
  1509. EnumElementInfo,
  1510. ElementsRead,
  1511. ElementsTotal
  1512. );
  1513. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1514. Status = RpcExceptionCode();
  1515. } RpcEndExcept;
  1516. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1517. !DhcpGlobalTryDownlevel ) {
  1518. DhcpGlobalTryDownlevel = TRUE;
  1519. goto RedoRpc;
  1520. }
  1521. return Status;
  1522. }
  1523. DWORD
  1524. DhcpRemoveSubnetElementV4(
  1525. LPWSTR ServerIpAddress,
  1526. DHCP_IP_ADDRESS SubnetAddress,
  1527. LPDHCP_SUBNET_ELEMENT_DATA_V4 RemoveElementInfo,
  1528. DHCP_FORCE_FLAG ForceFlag
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. This function removes a subnet element from managing. If the subnet
  1533. element is in use (for example, if the IpRange is in use) then it
  1534. returns error according to the ForceFlag specified.
  1535. Arguments:
  1536. ServerIpAddress : IP address string of the DHCP server.
  1537. SubnetAddress : IP Address of the subnet.
  1538. RemoveElementInfo : Pointer to an element information structure
  1539. containing element that should be removed from the subnet.
  1540. DhcpIPClusters element type is invalid to specify.
  1541. ForceFlag - Indicates how forcefully this element is removed.
  1542. Return Value:
  1543. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  1544. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  1545. data.
  1546. DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
  1547. reason it is has been used.
  1548. Other WINDOWS errors.
  1549. --*/
  1550. {
  1551. DWORD Status;
  1552. Status = ERROR_SUCCESS;
  1553. RedoRpc: RpcTryExcept {
  1554. Status = R_DhcpRemoveSubnetElementV4(
  1555. ServerIpAddress,
  1556. SubnetAddress,
  1557. RemoveElementInfo,
  1558. ForceFlag
  1559. );
  1560. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1561. Status = RpcExceptionCode();
  1562. } RpcEndExcept;
  1563. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1564. !DhcpGlobalTryDownlevel ) {
  1565. DhcpGlobalTryDownlevel = TRUE;
  1566. goto RedoRpc;
  1567. }
  1568. return Status;
  1569. }
  1570. DWORD
  1571. DhcpCreateClientInfoV4(
  1572. LPWSTR ServerIpAddress,
  1573. LPDHCP_CLIENT_INFO_V4 ClientInfo
  1574. )
  1575. /*++
  1576. Routine Description:
  1577. This function creates a client record in server's database. Also
  1578. this marks the specified client IP address as unavailable (or
  1579. distributed). This function returns error under the following cases :
  1580. 1. If the specified client IP address is not within the server
  1581. management.
  1582. 2. If the specified client IP address is already unavailable.
  1583. 3. If the specified client record is already in the server's
  1584. database.
  1585. This function may be used to distribute IP addresses manually.
  1586. Arguments:
  1587. ServerIpAddress : IP address string of the DHCP server.
  1588. ClientInfo : Pointer to the client information structure.
  1589. Return Value:
  1590. ERROR_DHCP_IP_ADDRESS_NOT_MANAGED - if the specified client
  1591. IP address is not managed by the server.
  1592. ERROR_DHCP_IP_ADDRESS_NOT_AVAILABLE - if the specified client IP
  1593. address is not available. May be in use by some other client.
  1594. ERROR_DHCP_CLIENT_EXISTS - if the client record exists already in
  1595. server's database.
  1596. Other WINDOWS errors.
  1597. --*/
  1598. {
  1599. DWORD Status;
  1600. Status = ERROR_SUCCESS;
  1601. RedoRpc: RpcTryExcept {
  1602. Status = R_DhcpCreateClientInfoV4(
  1603. ServerIpAddress,
  1604. ClientInfo
  1605. );
  1606. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1607. Status = RpcExceptionCode();
  1608. } RpcEndExcept;
  1609. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1610. !DhcpGlobalTryDownlevel ) {
  1611. DhcpGlobalTryDownlevel = TRUE;
  1612. goto RedoRpc;
  1613. }
  1614. return Status;
  1615. }
  1616. DWORD
  1617. DhcpGetClientInfoV4(
  1618. LPWSTR ServerIpAddress,
  1619. LPDHCP_SEARCH_INFO SearchInfo,
  1620. LPDHCP_CLIENT_INFO_V4 *ClientInfo
  1621. )
  1622. /*++
  1623. Routine Description:
  1624. This function retrieves client information record from the server's
  1625. database.
  1626. Arguments:
  1627. ServerIpAddress : IP address string of the DHCP server.
  1628. SearchInfo : Pointer to a search information record which is the key
  1629. for the client's record search.
  1630. ClientInfo : Pointer to a location where the pointer to the client
  1631. information structure is returned. This caller should free up
  1632. this buffer after use by calling DhcpRPCFreeMemory().
  1633. Return Value:
  1634. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  1635. not exist on the server's database.
  1636. ERROR_INVALID_PARAMETER - if the search information invalid.
  1637. Other WINDOWS errors.
  1638. --*/
  1639. {
  1640. DWORD Status;
  1641. RedoRpc: RpcTryExcept {
  1642. Status = R_DhcpGetClientInfoV4(
  1643. ServerIpAddress,
  1644. SearchInfo,
  1645. ClientInfo
  1646. );
  1647. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1648. Status = RpcExceptionCode();
  1649. } RpcEndExcept;
  1650. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1651. !DhcpGlobalTryDownlevel ) {
  1652. DhcpGlobalTryDownlevel = TRUE;
  1653. goto RedoRpc;
  1654. }
  1655. return Status;
  1656. }
  1657. DWORD
  1658. DhcpSetClientInfoV4(
  1659. LPWSTR ServerIpAddress,
  1660. LPDHCP_CLIENT_INFO_V4 ClientInfo
  1661. )
  1662. /*++
  1663. Routine Description:
  1664. This function sets client information record on the server's
  1665. database.
  1666. Arguments:
  1667. ServerIpAddress : IP address string of the DHCP server.
  1668. ClientInfo : Pointer to the client information structure.
  1669. Return Value:
  1670. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  1671. not exist on the server's database.
  1672. ERROR_INVALID_PARAMETER - if the client information structure
  1673. contains inconsistent data.
  1674. Other WINDOWS errors.
  1675. --*/
  1676. {
  1677. DWORD Status;
  1678. Status = ERROR_SUCCESS;
  1679. RedoRpc: RpcTryExcept {
  1680. Status = R_DhcpSetClientInfoV4(
  1681. ServerIpAddress,
  1682. ClientInfo
  1683. );
  1684. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1685. Status = RpcExceptionCode();
  1686. } RpcEndExcept;
  1687. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1688. !DhcpGlobalTryDownlevel ) {
  1689. DhcpGlobalTryDownlevel = TRUE;
  1690. goto RedoRpc;
  1691. }
  1692. return Status;
  1693. }
  1694. DWORD
  1695. DhcpEnumSubnetClientsV4(
  1696. LPWSTR ServerIpAddress,
  1697. DHCP_IP_ADDRESS SubnetAddress,
  1698. DHCP_RESUME_HANDLE *ResumeHandle,
  1699. DWORD PreferredMaximum,
  1700. LPDHCP_CLIENT_INFO_ARRAY_V4 *ClientInfo,
  1701. DWORD *ClientsRead,
  1702. DWORD *ClientsTotal
  1703. )
  1704. /*++
  1705. Routine Description:
  1706. This function returns all registered clients of the specified
  1707. subnet.
  1708. Arguments:
  1709. ServerIpAddress : IP address string of the DHCP server.
  1710. SubnetAddress : IP Address of the subnet.
  1711. ResumeHandle : Pointer to a resume handle where the resume
  1712. information is returned. The resume handle should be set to zero on
  1713. first call and left unchanged for subsequent calls.
  1714. PreferredMaximum : Preferred maximum length of the return buffer.
  1715. ClientInfo : Pointer to a location where the return buffer
  1716. pointer is stored. Caller should free up this buffer
  1717. after use by calling DhcpRPCFreeMemory().
  1718. ClientsRead : Pointer to a DWORD where the number of clients
  1719. that in the above buffer is returned.
  1720. ClientsTotal : Pointer to a DWORD where the total number of
  1721. clients remaining from the current position is returned.
  1722. Return Value:
  1723. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  1724. ERROR_MORE_DATA - if more elements available to enumerate.
  1725. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  1726. Other WINDOWS errors.
  1727. --*/
  1728. {
  1729. DWORD Status;
  1730. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1731. RedoRpc: RpcTryExcept {
  1732. Status = R_DhcpEnumSubnetClientsV4(
  1733. ServerIpAddress,
  1734. SubnetAddress,
  1735. ResumeHandle,
  1736. PreferredMaximum,
  1737. ClientInfo,
  1738. ClientsRead,
  1739. ClientsTotal
  1740. );
  1741. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1742. Status = RpcExceptionCode();
  1743. } RpcEndExcept;
  1744. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1745. !DhcpGlobalTryDownlevel ) {
  1746. DhcpGlobalTryDownlevel = TRUE;
  1747. goto RedoRpc;
  1748. }
  1749. return Status;
  1750. }
  1751. DWORD
  1752. DhcpEnumSubnetClientsV5(
  1753. LPWSTR ServerIpAddress,
  1754. DHCP_IP_ADDRESS SubnetAddress,
  1755. DHCP_RESUME_HANDLE *ResumeHandle,
  1756. DWORD PreferredMaximum,
  1757. LPDHCP_CLIENT_INFO_ARRAY_V5 *ClientInfo,
  1758. DWORD *ClientsRead,
  1759. DWORD *ClientsTotal
  1760. )
  1761. /*++
  1762. Routine Description:
  1763. This function returns all registered clients of the specified
  1764. subnet.
  1765. Arguments:
  1766. ServerIpAddress : IP address string of the DHCP server.
  1767. SubnetAddress : IP Address of the subnet.
  1768. ResumeHandle : Pointer to a resume handle where the resume
  1769. information is returned. The resume handle should be set to zero on
  1770. first call and left unchanged for subsequent calls.
  1771. PreferredMaximum : Preferred maximum length of the return buffer.
  1772. ClientInfo : Pointer to a location where the return buffer
  1773. pointer is stored. Caller should free up this buffer
  1774. after use by calling DhcpRPCFreeMemory().
  1775. ClientsRead : Pointer to a DWORD where the number of clients
  1776. that in the above buffer is returned.
  1777. ClientsTotal : Pointer to a DWORD where the total number of
  1778. clients remaining from the current position is returned.
  1779. Return Value:
  1780. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  1781. ERROR_MORE_DATA - if more elements available to enumerate.
  1782. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  1783. Other WINDOWS errors.
  1784. --*/
  1785. {
  1786. DWORD Status;
  1787. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1788. RedoRpc: RpcTryExcept {
  1789. Status = R_DhcpEnumSubnetClientsV5(
  1790. ServerIpAddress,
  1791. SubnetAddress,
  1792. ResumeHandle,
  1793. PreferredMaximum,
  1794. ClientInfo,
  1795. ClientsRead,
  1796. ClientsTotal
  1797. );
  1798. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1799. Status = RpcExceptionCode();
  1800. } RpcEndExcept;
  1801. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1802. !DhcpGlobalTryDownlevel ) {
  1803. DhcpGlobalTryDownlevel = TRUE;
  1804. goto RedoRpc;
  1805. }
  1806. return Status;
  1807. }
  1808. DWORD
  1809. DhcpServerSetConfigV4(
  1810. LPWSTR ServerIpAddress,
  1811. DWORD FieldsToSet,
  1812. LPDHCP_SERVER_CONFIG_INFO_V4 ConfigInfo
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. This function sets the DHCP server configuration information.
  1817. Serveral of the configuration information will become effective
  1818. immediately.
  1819. The following parameters require restart of the service after this
  1820. API is called successfully.
  1821. Set_APIProtocolSupport
  1822. Set_DatabaseName
  1823. Set_DatabasePath
  1824. Set_DatabaseLoggingFlag
  1825. Set_RestoreFlag
  1826. Arguments:
  1827. ServerIpAddress : IP address string of the DHCP server.
  1828. FieldsToSet : Bit mask of the fields in the ConfigInfo structure to
  1829. be set.
  1830. ConfigInfo: Pointer to the info structure to be set.
  1831. Return Value:
  1832. WINDOWS errors.
  1833. --*/
  1834. {
  1835. DWORD Status;
  1836. Status = ERROR_SUCCESS;
  1837. RedoRpc: RpcTryExcept {
  1838. Status = R_DhcpServerSetConfigV4(
  1839. ServerIpAddress,
  1840. FieldsToSet,
  1841. ConfigInfo );
  1842. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1843. Status = RpcExceptionCode();
  1844. } RpcEndExcept;
  1845. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1846. !DhcpGlobalTryDownlevel ) {
  1847. DhcpGlobalTryDownlevel = TRUE;
  1848. goto RedoRpc;
  1849. }
  1850. return Status;
  1851. }
  1852. DWORD
  1853. DhcpServerGetConfigV4(
  1854. LPWSTR ServerIpAddress,
  1855. LPDHCP_SERVER_CONFIG_INFO_V4 *ConfigInfo
  1856. )
  1857. /*++
  1858. Routine Description:
  1859. This function retrieves the current configuration information of the
  1860. server.
  1861. Arguments:
  1862. ServerIpAddress : IP address string of the DHCP server.
  1863. ConfigInfo: Pointer to a location where the pointer to the dhcp
  1864. server config info structure is returned. Caller should free up
  1865. this structure after use.
  1866. Return Value:
  1867. WINDOWS errors.
  1868. --*/
  1869. {
  1870. DWORD Status;
  1871. Status = ERROR_CALL_NOT_IMPLEMENTED;
  1872. RedoRpc: RpcTryExcept {
  1873. Status = R_DhcpServerGetConfigV4(
  1874. ServerIpAddress,
  1875. ConfigInfo );
  1876. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1877. Status = RpcExceptionCode();
  1878. } RpcEndExcept;
  1879. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1880. !DhcpGlobalTryDownlevel ) {
  1881. DhcpGlobalTryDownlevel = TRUE;
  1882. goto RedoRpc;
  1883. }
  1884. return Status;
  1885. }
  1886. DWORD
  1887. DhcpSetSuperScopeV4(
  1888. DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
  1889. DHCP_CONST DHCP_IP_ADDRESS SubnetAddress,
  1890. DHCP_CONST LPWSTR SuperScopeName,
  1891. DHCP_CONST BOOL ChangeExisting
  1892. )
  1893. {
  1894. DWORD Status;
  1895. Status = ERROR_SUCCESS;
  1896. RedoRpc: RpcTryExcept
  1897. {
  1898. Status = R_DhcpSetSuperScopeV4(
  1899. ServerIpAddress,
  1900. SubnetAddress,
  1901. SuperScopeName,
  1902. ChangeExisting
  1903. );
  1904. }
  1905. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
  1906. {
  1907. Status = RpcExceptionCode();
  1908. } RpcEndExcept;
  1909. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1910. !DhcpGlobalTryDownlevel ) {
  1911. DhcpGlobalTryDownlevel = TRUE;
  1912. goto RedoRpc;
  1913. }
  1914. return Status;
  1915. }
  1916. DWORD
  1917. DhcpDeleteSuperScopeV4(
  1918. DHCP_CONST WCHAR *ServerIpAddress,
  1919. DHCP_CONST LPWSTR SuperScopeName
  1920. )
  1921. {
  1922. DWORD Status;
  1923. Status = ERROR_SUCCESS;
  1924. RedoRpc: RpcTryExcept
  1925. {
  1926. Status = R_DhcpDeleteSuperScopeV4(
  1927. ServerIpAddress,
  1928. SuperScopeName
  1929. );
  1930. }
  1931. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
  1932. {
  1933. Status = RpcExceptionCode();
  1934. } RpcEndExcept;
  1935. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1936. !DhcpGlobalTryDownlevel ) {
  1937. DhcpGlobalTryDownlevel = TRUE;
  1938. goto RedoRpc;
  1939. }
  1940. return Status;
  1941. }
  1942. DWORD
  1943. DhcpGetSuperScopeInfoV4(
  1944. DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
  1945. LPDHCP_SUPER_SCOPE_TABLE *SuperScopeTable
  1946. )
  1947. {
  1948. DWORD Status;
  1949. RedoRpc: RpcTryExcept {
  1950. Status = R_DhcpGetSuperScopeInfoV4(
  1951. ServerIpAddress,
  1952. SuperScopeTable
  1953. );
  1954. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1955. Status = RpcExceptionCode();
  1956. } RpcEndExcept;
  1957. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1958. !DhcpGlobalTryDownlevel ) {
  1959. DhcpGlobalTryDownlevel = TRUE;
  1960. goto RedoRpc;
  1961. }
  1962. return Status;
  1963. }
  1964. //================================================================================
  1965. // V5 NT 5.0 Beta2 work (ClassId and Vendor specific stuff)
  1966. // In the following function, if flags is DHCP_FLAGS_OPTION_IS_VENDOR
  1967. // implies the option being considered is vendor, otherwise the option is normal...
  1968. // ClasName = NULL imples there is no class (otherwise the class is named)
  1969. //================================================================================
  1970. DWORD // ERROR_DHCP_OPTION_EXITS if option is already there
  1971. DhcpCreateOptionV5( // create a new option (must not exist)
  1972. IN LPWSTR ServerIpAddress,
  1973. IN DWORD Flags,
  1974. IN DHCP_OPTION_ID OptionId, // must be between 0-255 or 256-511 (for vendor stuff)
  1975. IN LPWSTR ClassName,
  1976. IN LPWSTR VendorName,
  1977. IN LPDHCP_OPTION OptionInfo
  1978. )
  1979. {
  1980. DWORD Status;
  1981. Status = ERROR_SUCCESS;
  1982. RedoRpc: RpcTryExcept {
  1983. Status = R_DhcpCreateOptionV5(
  1984. ServerIpAddress,
  1985. Flags,
  1986. OptionId,
  1987. ClassName,
  1988. VendorName,
  1989. OptionInfo
  1990. );
  1991. }
  1992. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1993. Status = RpcExceptionCode();
  1994. } RpcEndExcept;
  1995. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  1996. !DhcpGlobalTryDownlevel ) {
  1997. DhcpGlobalTryDownlevel = TRUE;
  1998. goto RedoRpc;
  1999. }
  2000. return Status;
  2001. }
  2002. DWORD // ERROR_DHCP_OPTION_NOT_PRESENT if option does not exist
  2003. DhcpSetOptionInfoV5( // Modify existing option's fields
  2004. IN LPWSTR ServerIpAddress,
  2005. IN DWORD Flags,
  2006. IN DHCP_OPTION_ID OptionID,
  2007. IN LPWSTR ClassName,
  2008. IN LPWSTR VendorName,
  2009. IN LPDHCP_OPTION OptionInfo
  2010. )
  2011. {
  2012. DWORD Status;
  2013. Status = ERROR_SUCCESS;
  2014. RedoRpc: RpcTryExcept {
  2015. Status = R_DhcpSetOptionInfoV5(
  2016. ServerIpAddress,
  2017. Flags,
  2018. OptionID,
  2019. ClassName,
  2020. VendorName,
  2021. OptionInfo
  2022. );
  2023. }
  2024. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2025. Status = RpcExceptionCode();
  2026. } RpcEndExcept;
  2027. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2028. !DhcpGlobalTryDownlevel ) {
  2029. DhcpGlobalTryDownlevel = TRUE;
  2030. goto RedoRpc;
  2031. }
  2032. return Status;
  2033. }
  2034. DWORD // ERROR_DHCP_OPTION_NOT_PRESENT
  2035. DhcpGetOptionInfoV5( // retrieve the information from off the mem structures
  2036. IN LPWSTR ServerIpAddress,
  2037. IN DWORD Flags,
  2038. IN DHCP_OPTION_ID OptionID,
  2039. IN LPWSTR ClassName,
  2040. IN LPWSTR VendorName,
  2041. OUT LPDHCP_OPTION *OptionInfo // allocate memory using MIDL functions
  2042. )
  2043. {
  2044. DWORD Status;
  2045. RedoRpc: RpcTryExcept {
  2046. Status = R_DhcpGetOptionInfoV5(
  2047. ServerIpAddress,
  2048. Flags,
  2049. OptionID,
  2050. ClassName,
  2051. VendorName,
  2052. OptionInfo
  2053. );
  2054. }
  2055. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2056. Status = RpcExceptionCode();
  2057. } RpcEndExcept;
  2058. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2059. !DhcpGlobalTryDownlevel ) {
  2060. DhcpGlobalTryDownlevel = TRUE;
  2061. goto RedoRpc;
  2062. }
  2063. return Status;
  2064. }
  2065. DWORD // ERROR_DHCP_OPTION_NOT_PRESENT if option does not exist
  2066. DhcpEnumOptionsV5( // enumerate the options defined
  2067. IN LPWSTR ServerIpAddress,
  2068. IN DWORD Flags,
  2069. IN LPWSTR ClassName,
  2070. IN LPWSTR VendorName,
  2071. IN OUT DHCP_RESUME_HANDLE *ResumeHandle, // must be zero intially and then never touched
  2072. IN DWORD PreferredMaximum, // max # of bytes of info to pass along
  2073. OUT LPDHCP_OPTION_ARRAY *Options, // fill this option array
  2074. OUT DWORD *OptionsRead, // fill in the # of options read
  2075. OUT DWORD *OptionsTotal // fill in the total # here
  2076. )
  2077. {
  2078. DWORD Status;
  2079. RedoRpc: RpcTryExcept {
  2080. Status = R_DhcpEnumOptionsV5(
  2081. ServerIpAddress,
  2082. Flags,
  2083. ClassName,
  2084. VendorName,
  2085. ResumeHandle,
  2086. PreferredMaximum,
  2087. Options,
  2088. OptionsRead,
  2089. OptionsTotal
  2090. );
  2091. }
  2092. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2093. Status = RpcExceptionCode();
  2094. } RpcEndExcept;
  2095. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2096. !DhcpGlobalTryDownlevel ) {
  2097. DhcpGlobalTryDownlevel = TRUE;
  2098. goto RedoRpc;
  2099. }
  2100. return Status;
  2101. }
  2102. DWORD // ERROR_DHCP_OPTION_NOT_PRESENT if option not existent
  2103. DhcpRemoveOptionV5( // remove the option definition from the registry
  2104. IN LPWSTR ServerIpAddress,
  2105. IN DWORD Flags,
  2106. IN DHCP_OPTION_ID OptionID,
  2107. IN LPWSTR ClassName,
  2108. IN LPWSTR VendorName
  2109. )
  2110. {
  2111. DWORD Status;
  2112. Status = ERROR_SUCCESS;
  2113. RedoRpc: RpcTryExcept {
  2114. Status = R_DhcpRemoveOptionV5(
  2115. ServerIpAddress,
  2116. Flags,
  2117. OptionID,
  2118. ClassName,
  2119. VendorName
  2120. );
  2121. }
  2122. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2123. Status = RpcExceptionCode();
  2124. } RpcEndExcept;
  2125. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2126. !DhcpGlobalTryDownlevel ) {
  2127. DhcpGlobalTryDownlevel = TRUE;
  2128. goto RedoRpc;
  2129. }
  2130. return Status;
  2131. }
  2132. DWORD // OPTION_NOT_PRESENT if option is not defined
  2133. DhcpSetOptionValueV5( // replace or add a new option value
  2134. IN LPWSTR ServerIpAddress,
  2135. IN DWORD Flags,
  2136. IN DHCP_OPTION_ID OptionId,
  2137. IN LPWSTR ClassName,
  2138. IN LPWSTR VendorName,
  2139. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  2140. IN LPDHCP_OPTION_DATA OptionValue
  2141. )
  2142. {
  2143. DWORD Status;
  2144. Status = ERROR_SUCCESS;
  2145. RedoRpc: RpcTryExcept {
  2146. Status = R_DhcpSetOptionValueV5(
  2147. ServerIpAddress,
  2148. Flags,
  2149. OptionId,
  2150. ClassName,
  2151. VendorName,
  2152. ScopeInfo,
  2153. OptionValue
  2154. );
  2155. }
  2156. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2157. Status = RpcExceptionCode();
  2158. } RpcEndExcept;
  2159. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2160. !DhcpGlobalTryDownlevel ) {
  2161. DhcpGlobalTryDownlevel = TRUE;
  2162. goto RedoRpc;
  2163. }
  2164. return Status;
  2165. }
  2166. DWORD // not atomic!!!!
  2167. DhcpSetOptionValuesV5( // set a bunch of options
  2168. IN LPWSTR ServerIpAddress,
  2169. IN DWORD Flags,
  2170. IN LPWSTR ClassName,
  2171. IN LPWSTR VendorName,
  2172. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  2173. IN LPDHCP_OPTION_VALUE_ARRAY OptionValues
  2174. )
  2175. {
  2176. DWORD Status;
  2177. Status = ERROR_SUCCESS;
  2178. RedoRpc: RpcTryExcept {
  2179. Status = R_DhcpSetOptionValuesV5(
  2180. ServerIpAddress,
  2181. Flags,
  2182. ClassName,
  2183. VendorName,
  2184. ScopeInfo,
  2185. OptionValues
  2186. );
  2187. }
  2188. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2189. Status = RpcExceptionCode();
  2190. } RpcEndExcept;
  2191. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2192. !DhcpGlobalTryDownlevel ) {
  2193. DhcpGlobalTryDownlevel = TRUE;
  2194. goto RedoRpc;
  2195. }
  2196. return Status;
  2197. }
  2198. DWORD
  2199. DhcpGetOptionValueV5( // fetch the required option at required level
  2200. IN LPWSTR ServerIpAddress,
  2201. IN DWORD Flags,
  2202. IN DHCP_OPTION_ID OptionID,
  2203. IN LPWSTR ClassName,
  2204. IN LPWSTR VendorName,
  2205. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  2206. OUT LPDHCP_OPTION_VALUE *OptionValue // allocate memory using MIDL_user_allocate
  2207. )
  2208. {
  2209. DWORD Status;
  2210. RedoRpc: RpcTryExcept {
  2211. Status = R_DhcpGetOptionValueV5(
  2212. ServerIpAddress,
  2213. Flags,
  2214. OptionID,
  2215. ClassName,
  2216. VendorName,
  2217. ScopeInfo,
  2218. OptionValue
  2219. );
  2220. }
  2221. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2222. Status = RpcExceptionCode();
  2223. } RpcEndExcept;
  2224. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2225. !DhcpGlobalTryDownlevel ) {
  2226. DhcpGlobalTryDownlevel = TRUE;
  2227. goto RedoRpc;
  2228. }
  2229. return Status;
  2230. }
  2231. DWORD
  2232. DhcpEnumOptionValuesV5(
  2233. IN LPWSTR ServerIpAddress,
  2234. IN DWORD Flags,
  2235. IN LPWSTR ClassName,
  2236. IN LPWSTR VendorName,
  2237. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  2238. IN DHCP_RESUME_HANDLE *ResumeHandle,
  2239. IN DWORD PreferredMaximum,
  2240. OUT LPDHCP_OPTION_VALUE_ARRAY *OptionValues,
  2241. OUT DWORD *OptionsRead,
  2242. OUT DWORD *OptionsTotal
  2243. )
  2244. {
  2245. DWORD Status;
  2246. RedoRpc: RpcTryExcept {
  2247. Status = R_DhcpEnumOptionValuesV5(
  2248. ServerIpAddress,
  2249. Flags,
  2250. ClassName,
  2251. VendorName,
  2252. ScopeInfo,
  2253. ResumeHandle,
  2254. PreferredMaximum,
  2255. OptionValues,
  2256. OptionsRead,
  2257. OptionsTotal
  2258. );
  2259. }
  2260. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2261. Status = RpcExceptionCode();
  2262. } RpcEndExcept;
  2263. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2264. !DhcpGlobalTryDownlevel ) {
  2265. DhcpGlobalTryDownlevel = TRUE;
  2266. goto RedoRpc;
  2267. }
  2268. return Status;
  2269. }
  2270. DWORD
  2271. DhcpRemoveOptionValueV5(
  2272. IN LPWSTR ServerIpAddress,
  2273. IN DWORD Flags,
  2274. IN DHCP_OPTION_ID OptionID,
  2275. IN LPWSTR ClassName,
  2276. IN LPWSTR VendorName,
  2277. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo
  2278. )
  2279. {
  2280. DWORD Status;
  2281. Status = ERROR_SUCCESS;
  2282. RedoRpc: RpcTryExcept {
  2283. Status = R_DhcpRemoveOptionValueV5(
  2284. ServerIpAddress,
  2285. Flags,
  2286. OptionID,
  2287. ClassName,
  2288. VendorName,
  2289. ScopeInfo
  2290. );
  2291. }
  2292. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2293. Status = RpcExceptionCode();
  2294. } RpcEndExcept;
  2295. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2296. !DhcpGlobalTryDownlevel ) {
  2297. DhcpGlobalTryDownlevel = TRUE;
  2298. goto RedoRpc;
  2299. }
  2300. return Status;
  2301. }
  2302. DWORD
  2303. DhcpCreateClass(
  2304. IN LPWSTR ServerIpAddress,
  2305. IN DWORD ReservedMustBeZero,
  2306. IN LPDHCP_CLASS_INFO ClassInfo
  2307. )
  2308. {
  2309. DWORD Status;
  2310. Status = ERROR_SUCCESS;
  2311. RedoRpc: RpcTryExcept {
  2312. Status = R_DhcpCreateClass(
  2313. ServerIpAddress,
  2314. ReservedMustBeZero,
  2315. ClassInfo
  2316. );
  2317. }
  2318. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2319. Status = RpcExceptionCode();
  2320. } RpcEndExcept;
  2321. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2322. !DhcpGlobalTryDownlevel ) {
  2323. DhcpGlobalTryDownlevel = TRUE;
  2324. goto RedoRpc;
  2325. }
  2326. return Status;
  2327. }
  2328. DWORD
  2329. DhcpModifyClass(
  2330. IN LPWSTR ServerIpAddress,
  2331. IN DWORD ReservedMustBeZero,
  2332. IN LPDHCP_CLASS_INFO ClassInfo
  2333. )
  2334. {
  2335. DWORD Status;
  2336. Status = ERROR_SUCCESS;
  2337. RedoRpc: RpcTryExcept {
  2338. Status = R_DhcpModifyClass(
  2339. ServerIpAddress,
  2340. ReservedMustBeZero,
  2341. ClassInfo
  2342. );
  2343. }
  2344. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2345. Status = RpcExceptionCode();
  2346. } RpcEndExcept;
  2347. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2348. !DhcpGlobalTryDownlevel ) {
  2349. DhcpGlobalTryDownlevel = TRUE;
  2350. goto RedoRpc;
  2351. }
  2352. return Status;
  2353. }
  2354. DWORD
  2355. DhcpDeleteClass(
  2356. IN LPWSTR ServerIpAddress,
  2357. IN DWORD ReservedMustBeZero,
  2358. IN LPWSTR ClassName
  2359. )
  2360. {
  2361. DWORD Status;
  2362. Status = ERROR_SUCCESS;
  2363. RedoRpc: RpcTryExcept {
  2364. Status = R_DhcpDeleteClass(
  2365. ServerIpAddress,
  2366. ReservedMustBeZero,
  2367. ClassName
  2368. );
  2369. }
  2370. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2371. Status = RpcExceptionCode();
  2372. } RpcEndExcept;
  2373. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2374. !DhcpGlobalTryDownlevel ) {
  2375. DhcpGlobalTryDownlevel = TRUE;
  2376. goto RedoRpc;
  2377. }
  2378. return Status;
  2379. }
  2380. DWORD
  2381. DhcpGetClassInfo(
  2382. IN LPWSTR ServerIpAddress,
  2383. IN DWORD ReservedMustBeZero,
  2384. IN LPDHCP_CLASS_INFO PartialClassInfo,
  2385. OUT LPDHCP_CLASS_INFO *FilledClassInfo
  2386. )
  2387. {
  2388. DWORD Status;
  2389. RedoRpc: RpcTryExcept {
  2390. Status = R_DhcpGetClassInfo(
  2391. ServerIpAddress,
  2392. ReservedMustBeZero,
  2393. PartialClassInfo,
  2394. FilledClassInfo
  2395. );
  2396. }
  2397. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2398. Status = RpcExceptionCode();
  2399. } RpcEndExcept;
  2400. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2401. !DhcpGlobalTryDownlevel ) {
  2402. DhcpGlobalTryDownlevel = TRUE;
  2403. goto RedoRpc;
  2404. }
  2405. return Status;
  2406. }
  2407. DWORD
  2408. DhcpEnumClasses(
  2409. IN LPWSTR ServerIpAddress,
  2410. IN DWORD ReservedMustBeZero,
  2411. IN OUT DHCP_RESUME_HANDLE *ResumeHandle,
  2412. IN DWORD PreferredMaximum,
  2413. OUT LPDHCP_CLASS_INFO_ARRAY *ClassInfoArray,
  2414. OUT DWORD *nRead,
  2415. OUT DWORD *nTotal
  2416. )
  2417. {
  2418. DWORD Status;
  2419. *nRead = *nTotal =0;
  2420. RedoRpc: RpcTryExcept {
  2421. Status = R_DhcpEnumClasses(
  2422. ServerIpAddress,
  2423. ReservedMustBeZero,
  2424. ResumeHandle,
  2425. PreferredMaximum,
  2426. ClassInfoArray,
  2427. nRead,
  2428. nTotal
  2429. );
  2430. }
  2431. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2432. Status = RpcExceptionCode();
  2433. } RpcEndExcept;
  2434. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2435. !DhcpGlobalTryDownlevel ) {
  2436. DhcpGlobalTryDownlevel = TRUE;
  2437. goto RedoRpc;
  2438. }
  2439. return Status;
  2440. }
  2441. DWORD
  2442. DhcpGetAllOptions(
  2443. IN LPWSTR ServerIpAddress,
  2444. IN DWORD Flags, // what do we care about vendor/classid stuff?
  2445. OUT LPDHCP_ALL_OPTIONS *OptionStruct // fill the fields of this structure
  2446. )
  2447. {
  2448. DWORD Status;
  2449. RedoRpc: RpcTryExcept {
  2450. Status = R_DhcpGetAllOptions(
  2451. ServerIpAddress,
  2452. Flags,
  2453. OptionStruct
  2454. );
  2455. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2456. Status = RpcExceptionCode();
  2457. } RpcEndExcept;
  2458. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2459. !DhcpGlobalTryDownlevel ) {
  2460. DhcpGlobalTryDownlevel = TRUE;
  2461. goto RedoRpc;
  2462. }
  2463. return Status;
  2464. }
  2465. DWORD
  2466. DhcpGetAllOptionValues(
  2467. IN LPWSTR ServerIpAddress,
  2468. IN DWORD Flags,
  2469. IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo,
  2470. OUT LPDHCP_ALL_OPTION_VALUES *Values
  2471. )
  2472. {
  2473. DWORD Status;
  2474. RedoRpc: RpcTryExcept {
  2475. Status = R_DhcpGetAllOptionValues(
  2476. ServerIpAddress,
  2477. Flags,
  2478. ScopeInfo,
  2479. Values
  2480. );
  2481. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2482. Status = RpcExceptionCode();
  2483. } RpcEndExcept;
  2484. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2485. !DhcpGlobalTryDownlevel ) {
  2486. DhcpGlobalTryDownlevel = TRUE;
  2487. goto RedoRpc;
  2488. }
  2489. return Status;
  2490. }
  2491. //DOC DhcpEnumServers enumerates the list of servers found in the DS. If the DS
  2492. //DOC is not accessible, it returns an error. The only currently used parameter
  2493. //DOC is the out parameter Servers. This is a SLOW call.
  2494. DWORD
  2495. DhcpEnumServers(
  2496. IN DWORD Flags, // must be zero
  2497. IN LPVOID IdInfo, // must be NULL
  2498. OUT LPDHCP_SERVER_INFO_ARRAY *Servers, // output servers list
  2499. IN LPVOID CallbackFn, // must be NULL
  2500. IN LPVOID CallbackData // must be NULL
  2501. )
  2502. {
  2503. DWORD Result;
  2504. Result = DhcpEnumServersDS(Flags,IdInfo,Servers,CallbackFn,CallbackData);
  2505. return Result;
  2506. }
  2507. //DOC DhcpAddServer tries to add a new server to the existing list of servers in
  2508. //DOC the DS. The function returns error if the Server already exists in the DS.
  2509. //DOC The function tries to upload the server configuration to the DS..
  2510. //DOC This is a SLOW call. Currently, the DsLocation and DsLocType are not valid
  2511. //DOC fields in the NewServer and they'd be ignored. Version must be zero.
  2512. DWORD
  2513. DhcpAddServer(
  2514. IN DWORD Flags, // must be zero
  2515. IN LPVOID IdInfo, // must be NULL
  2516. IN LPDHCP_SERVER_INFO NewServer, // input server information
  2517. IN LPVOID CallbackFn, // must be NULL
  2518. IN LPVOID CallbackData // must be NULL
  2519. )
  2520. {
  2521. DWORD Err, IpAddress;
  2522. WCHAR wBuf[sizeof("xxx.xxx.xxx.xxx")];
  2523. Err = DhcpAddServerDS(Flags,IdInfo,NewServer,CallbackFn,CallbackData);
  2524. if( ERROR_SUCCESS != Err ) return Err;
  2525. IpAddress = htonl(NewServer->ServerAddress);
  2526. (void)DhcpServerRedoAuthorization(
  2527. DhcpOemToUnicode( inet_ntoa(*(struct in_addr*)&IpAddress), wBuf),
  2528. 0
  2529. );
  2530. return ERROR_SUCCESS;
  2531. }
  2532. //DOC DhcpDeleteServer tries to delete the server from DS. It is an error if the
  2533. //DOC server does not already exist. This also deletes any objects related to
  2534. //DOC this server in the DS (like subnet, reservations etc.).
  2535. DWORD
  2536. DhcpDeleteServer(
  2537. IN DWORD Flags, // must be zero
  2538. IN LPVOID IdInfo, // must be NULL
  2539. IN LPDHCP_SERVER_INFO NewServer, // input server information
  2540. IN LPVOID CallbackFn, // must be NULL
  2541. IN LPVOID CallbackData // must be NULL
  2542. )
  2543. {
  2544. DWORD Err, IpAddress;
  2545. WCHAR wBuf[sizeof("xxx.xxx.xxx.xxx")];
  2546. Err = DhcpDeleteServerDS(Flags,IdInfo,NewServer,CallbackFn,CallbackData);
  2547. if( ERROR_SUCCESS != Err ) return Err;
  2548. IpAddress = htonl(NewServer->ServerAddress);
  2549. (void)DhcpServerRedoAuthorization(
  2550. DhcpOemToUnicode( inet_ntoa(*(struct in_addr*)&IpAddress), wBuf),
  2551. 0
  2552. );
  2553. return ERROR_SUCCESS;
  2554. }
  2555. //================================================================================
  2556. // Multicast stuff
  2557. //================================================================================
  2558. DWORD
  2559. DhcpSetMScopeInfo(
  2560. DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
  2561. LPWSTR MScopeName,
  2562. LPDHCP_MSCOPE_INFO MScopeInfo,
  2563. BOOL NewScope
  2564. )
  2565. {
  2566. DWORD Status;
  2567. RedoRpc: RpcTryExcept
  2568. {
  2569. Status = R_DhcpSetMScopeInfo(
  2570. ServerIpAddress,
  2571. MScopeName,
  2572. MScopeInfo,
  2573. NewScope
  2574. );
  2575. }
  2576. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
  2577. {
  2578. Status = RpcExceptionCode();
  2579. } RpcEndExcept;
  2580. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2581. !DhcpGlobalTryDownlevel ) {
  2582. DhcpGlobalTryDownlevel = TRUE;
  2583. goto RedoRpc;
  2584. }
  2585. return Status;
  2586. }
  2587. DWORD
  2588. DhcpGetMScopeInfo(
  2589. DHCP_CONST DHCP_SRV_HANDLE ServerIpAddress,
  2590. LPWSTR MScopeName,
  2591. LPDHCP_MSCOPE_INFO *MScopeInfo
  2592. )
  2593. {
  2594. DWORD Status;
  2595. RedoRpc: RpcTryExcept
  2596. {
  2597. Status = R_DhcpGetMScopeInfo(
  2598. ServerIpAddress,
  2599. MScopeName,
  2600. MScopeInfo
  2601. );
  2602. }
  2603. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
  2604. {
  2605. Status = RpcExceptionCode();
  2606. } RpcEndExcept;
  2607. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2608. !DhcpGlobalTryDownlevel ) {
  2609. DhcpGlobalTryDownlevel = TRUE;
  2610. goto RedoRpc;
  2611. }
  2612. return Status;
  2613. }
  2614. DWORD
  2615. DhcpEnumMScopes(
  2616. DHCP_CONST WCHAR *ServerIpAddress,
  2617. DHCP_RESUME_HANDLE *ResumeHandle,
  2618. DWORD PreferredMaximum,
  2619. LPDHCP_MSCOPE_TABLE *MScopeTable,
  2620. DWORD *ElementsRead,
  2621. DWORD *ElementsTotal
  2622. )
  2623. /*++
  2624. Routine Description:
  2625. This function enumerates the available subnets.
  2626. Arguments:
  2627. ServerIpAddress : IP address string of the DHCP server.
  2628. ResumeHandle : Pointer to a resume handle where the resume
  2629. information is returned. The resume handle should be set to
  2630. zero on first call and left unchanged for subsequent calls.
  2631. PreferredMaximum : Preferred maximum length of the return buffer.
  2632. ElementsRead : Pointer to a DWORD where the number of subnet
  2633. elements in the above buffer is returned.
  2634. ElementsTotal : Pointer to a DWORD where the total number of
  2635. elements remaining from the current position is returned.
  2636. Return Value:
  2637. ERROR_MORE_DATA - if more elements available to enumerate.
  2638. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  2639. Other WINDOWS errors.
  2640. --*/
  2641. {
  2642. DWORD Status;
  2643. RedoRpc: RpcTryExcept {
  2644. Status = R_DhcpEnumMScopes(
  2645. ServerIpAddress,
  2646. ResumeHandle,
  2647. PreferredMaximum,
  2648. MScopeTable,
  2649. ElementsRead,
  2650. ElementsTotal
  2651. );
  2652. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2653. Status = RpcExceptionCode();
  2654. } RpcEndExcept;
  2655. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2656. !DhcpGlobalTryDownlevel ) {
  2657. DhcpGlobalTryDownlevel = TRUE;
  2658. goto RedoRpc;
  2659. }
  2660. return Status;
  2661. }
  2662. DWORD
  2663. DhcpAddMScopeElement(
  2664. LPWSTR ServerIpAddress,
  2665. LPWSTR MScopeName,
  2666. LPDHCP_SUBNET_ELEMENT_DATA_V4 AddElementInfo
  2667. )
  2668. /*++
  2669. Routine Description:
  2670. This function adds a enumerable type of subnet elements to the
  2671. specified subnet. The new elements that are added to the subnet will
  2672. come into effect immediately.
  2673. NOTE: It is not clear now how do we handle the new secondary hosts.
  2674. Arguments:
  2675. ServerIpAddress : IP address string of the DHCP server.
  2676. SubnetAddress : IP Address of the subnet.
  2677. AddElementInfo : Pointer to an element information structure
  2678. containing new element that is added to the subnet.
  2679. DhcpIPClusters element type is invalid to specify.
  2680. Return Value:
  2681. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  2682. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  2683. data.
  2684. Other WINDOWS errors.
  2685. --*/
  2686. {
  2687. DWORD Status;
  2688. RedoRpc: RpcTryExcept {
  2689. Status = R_DhcpAddMScopeElement(
  2690. ServerIpAddress,
  2691. MScopeName,
  2692. AddElementInfo
  2693. );
  2694. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2695. Status = RpcExceptionCode();
  2696. } RpcEndExcept;
  2697. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2698. !DhcpGlobalTryDownlevel ) {
  2699. DhcpGlobalTryDownlevel = TRUE;
  2700. goto RedoRpc;
  2701. }
  2702. return Status;
  2703. }
  2704. DWORD
  2705. DhcpEnumMScopeElements(
  2706. LPWSTR ServerIpAddress,
  2707. LPWSTR MScopeName,
  2708. DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
  2709. DHCP_RESUME_HANDLE *ResumeHandle,
  2710. DWORD PreferredMaximum,
  2711. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *EnumElementInfo,
  2712. DWORD *ElementsRead,
  2713. DWORD *ElementsTotal
  2714. )
  2715. /*++
  2716. Routine Description:
  2717. This function enumerates the eumerable fields of a subnet.
  2718. Arguments:
  2719. ServerIpAddress : IP address string of the DHCP server.
  2720. SubnetAddress : IP Address of the subnet.
  2721. EnumElementType : Type of the subnet element that are enumerated.
  2722. ResumeHandle : Pointer to a resume handle where the resume
  2723. information is returned. The resume handle should be set to
  2724. zero on first call and left unchanged for subsequent calls.
  2725. PreferredMaximum : Preferred maximum length of the return buffer.
  2726. EnumElementInfo : Pointer to a location where the return buffer
  2727. pointer is stored. Caller should free up the buffer after use
  2728. by calling DhcpRPCFreeMemory().
  2729. ElementsRead : Pointer to a DWORD where the number of subnet
  2730. elements in the above buffer is returned.
  2731. ElementsTotal : Pointer to a DWORD where the total number of
  2732. elements remaining from the current position is returned.
  2733. Return Value:
  2734. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  2735. ERROR_MORE_DATA - if more elements available to enumerate.
  2736. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  2737. Other WINDOWS errors.
  2738. --*/
  2739. {
  2740. DWORD Status;
  2741. RedoRpc: RpcTryExcept {
  2742. Status = R_DhcpEnumMScopeElements(
  2743. ServerIpAddress,
  2744. MScopeName,
  2745. EnumElementType,
  2746. ResumeHandle,
  2747. PreferredMaximum,
  2748. EnumElementInfo,
  2749. ElementsRead,
  2750. ElementsTotal
  2751. );
  2752. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2753. Status = RpcExceptionCode();
  2754. } RpcEndExcept;
  2755. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2756. !DhcpGlobalTryDownlevel ) {
  2757. DhcpGlobalTryDownlevel = TRUE;
  2758. goto RedoRpc;
  2759. }
  2760. return Status;
  2761. }
  2762. DWORD
  2763. DhcpRemoveMScopeElement(
  2764. LPWSTR ServerIpAddress,
  2765. LPWSTR MScopeName,
  2766. LPDHCP_SUBNET_ELEMENT_DATA_V4 RemoveElementInfo,
  2767. DHCP_FORCE_FLAG ForceFlag
  2768. )
  2769. /*++
  2770. Routine Description:
  2771. This function removes a subnet element from managing. If the subnet
  2772. element is in use (for example, if the IpRange is in use) then it
  2773. returns error according to the ForceFlag specified.
  2774. Arguments:
  2775. ServerIpAddress : IP address string of the DHCP server.
  2776. SubnetAddress : IP Address of the subnet.
  2777. RemoveElementInfo : Pointer to an element information structure
  2778. containing element that should be removed from the subnet.
  2779. DhcpIPClusters element type is invalid to specify.
  2780. ForceFlag - Indicates how forcefully this element is removed.
  2781. Return Value:
  2782. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  2783. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  2784. data.
  2785. DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
  2786. reason it is has been used.
  2787. Other WINDOWS errors.
  2788. --*/
  2789. {
  2790. DWORD Status;
  2791. RedoRpc: RpcTryExcept {
  2792. Status = R_DhcpRemoveMScopeElement(
  2793. ServerIpAddress,
  2794. MScopeName,
  2795. RemoveElementInfo,
  2796. ForceFlag
  2797. );
  2798. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2799. Status = RpcExceptionCode();
  2800. } RpcEndExcept;
  2801. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2802. !DhcpGlobalTryDownlevel ) {
  2803. DhcpGlobalTryDownlevel = TRUE;
  2804. goto RedoRpc;
  2805. }
  2806. return Status;
  2807. }
  2808. DWORD
  2809. DhcpDeleteMScope(
  2810. LPWSTR ServerIpAddress,
  2811. LPWSTR MScopeName,
  2812. DHCP_FORCE_FLAG ForceFlag
  2813. )
  2814. /*++
  2815. Routine Description:
  2816. This function removes a subnet from DHCP server management. If the
  2817. subnet is in use (for example, if the IpRange is in use)
  2818. then it returns error according to the ForceFlag specified.
  2819. Arguments:
  2820. ServerIpAddress : IP address string of the DHCP server.
  2821. SubnetAddress : IP Address of the subnet.
  2822. ForceFlag - Indicates how forcefully this element is removed.
  2823. Return Value:
  2824. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  2825. ERROR_INVALID_PARAMETER - if the information structure contains invalid
  2826. data.
  2827. DHCP_ELEMENT_CANT_REMOVE - if the element can't be removed for the
  2828. reason it is has been used.
  2829. Other WINDOWS errors.
  2830. --*/
  2831. {
  2832. DWORD Status;
  2833. RedoRpc: RpcTryExcept {
  2834. Status = R_DhcpDeleteMScope(
  2835. ServerIpAddress,
  2836. MScopeName,
  2837. ForceFlag
  2838. );
  2839. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2840. Status = RpcExceptionCode();
  2841. } RpcEndExcept;
  2842. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2843. !DhcpGlobalTryDownlevel ) {
  2844. DhcpGlobalTryDownlevel = TRUE;
  2845. goto RedoRpc;
  2846. }
  2847. return Status;
  2848. }
  2849. DWORD
  2850. DhcpGetMClientInfo(
  2851. LPWSTR ServerIpAddress,
  2852. LPDHCP_SEARCH_INFO SearchInfo,
  2853. LPDHCP_MCLIENT_INFO *ClientInfo
  2854. )
  2855. /*++
  2856. Routine Description:
  2857. This function retrieves client information record from the server's
  2858. database.
  2859. Arguments:
  2860. ServerIpAddress : IP address string of the DHCP server.
  2861. SearchInfo : Pointer to a search information record which is the key
  2862. for the client's record search.
  2863. ClientInfo : Pointer to a location where the pointer to the client
  2864. information structure is returned. This caller should free up
  2865. this buffer after use by calling DhcpRPCFreeMemory().
  2866. Return Value:
  2867. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  2868. not exist on the server's database.
  2869. ERROR_INVALID_PARAMETER - if the search information invalid.
  2870. Other WINDOWS errors.
  2871. --*/
  2872. {
  2873. DWORD Status;
  2874. RedoRpc: RpcTryExcept {
  2875. Status = R_DhcpGetMClientInfo(
  2876. ServerIpAddress,
  2877. SearchInfo,
  2878. ClientInfo
  2879. );
  2880. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2881. Status = RpcExceptionCode();
  2882. } RpcEndExcept;
  2883. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2884. !DhcpGlobalTryDownlevel ) {
  2885. DhcpGlobalTryDownlevel = TRUE;
  2886. goto RedoRpc;
  2887. }
  2888. return Status;
  2889. }
  2890. DWORD
  2891. DhcpDeleteMClientInfo(
  2892. LPWSTR ServerIpAddress,
  2893. LPDHCP_SEARCH_INFO ClientInfo
  2894. )
  2895. /*++
  2896. Routine Description:
  2897. This function deletes the specified client record. Also it frees up
  2898. the client IP address for redistribution.
  2899. Arguments:
  2900. ServerIpAddress : IP address string of the DHCP server.
  2901. ClientInfo : Pointer to a client information which is the key for
  2902. the client's record search.
  2903. Return Value:
  2904. ERROR_DHCP_CLIENT_NOT_PRESENT - if the specified client record does
  2905. not exist on the server's database.
  2906. Other WINDOWS errors.
  2907. --*/
  2908. {
  2909. DWORD Status;
  2910. RedoRpc: RpcTryExcept {
  2911. Status = R_DhcpDeleteMClientInfo(
  2912. ServerIpAddress,
  2913. ClientInfo
  2914. );
  2915. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2916. Status = RpcExceptionCode();
  2917. } RpcEndExcept;
  2918. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2919. !DhcpGlobalTryDownlevel ) {
  2920. DhcpGlobalTryDownlevel = TRUE;
  2921. goto RedoRpc;
  2922. }
  2923. return Status;
  2924. }
  2925. DWORD
  2926. DhcpEnumMScopeClients(
  2927. LPWSTR ServerIpAddress,
  2928. LPWSTR MScopeName,
  2929. DHCP_RESUME_HANDLE *ResumeHandle,
  2930. DWORD PreferredMaximum,
  2931. LPDHCP_MCLIENT_INFO_ARRAY *ClientInfo,
  2932. DWORD *ClientsRead,
  2933. DWORD *ClientsTotal
  2934. )
  2935. /*++
  2936. Routine Description:
  2937. This function returns all registered clients of the specified
  2938. subnet.
  2939. Arguments:
  2940. ServerIpAddress : IP address string of the DHCP server.
  2941. SubnetAddress : IP Address of the subnet.
  2942. ResumeHandle : Pointer to a resume handle where the resume
  2943. information is returned. The resume handle should be set to zero on
  2944. first call and left unchanged for subsequent calls.
  2945. PreferredMaximum : Preferred maximum length of the return buffer.
  2946. ClientInfo : Pointer to a location where the return buffer
  2947. pointer is stored. Caller should free up this buffer
  2948. after use by calling DhcpRPCFreeMemory().
  2949. ClientsRead : Pointer to a DWORD where the number of clients
  2950. that in the above buffer is returned.
  2951. ClientsTotal : Pointer to a DWORD where the total number of
  2952. clients remaining from the current position is returned.
  2953. Return Value:
  2954. ERROR_DHCP_SUBNET_NOT_PRESENT - if the subnet is not managed by the server.
  2955. ERROR_MORE_DATA - if more elements available to enumerate.
  2956. ERROR_NO_MORE_ITEMS - if no more element to enumerate.
  2957. Other WINDOWS errors.
  2958. --*/
  2959. {
  2960. DWORD Status;
  2961. RedoRpc: RpcTryExcept {
  2962. Status = R_DhcpEnumMScopeClients(
  2963. ServerIpAddress,
  2964. MScopeName,
  2965. ResumeHandle,
  2966. PreferredMaximum,
  2967. ClientInfo,
  2968. ClientsRead,
  2969. ClientsTotal
  2970. );
  2971. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2972. Status = RpcExceptionCode();
  2973. } RpcEndExcept;
  2974. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  2975. !DhcpGlobalTryDownlevel ) {
  2976. DhcpGlobalTryDownlevel = TRUE;
  2977. goto RedoRpc;
  2978. }
  2979. return Status;
  2980. }
  2981. DWORD
  2982. DhcpScanMDatabase(
  2983. LPWSTR ServerIpAddress,
  2984. LPWSTR MScopeName,
  2985. DWORD FixFlag,
  2986. LPDHCP_SCAN_LIST *ScanList
  2987. )
  2988. /*++
  2989. Routine Description:
  2990. This function scans the database entries and registry bit-map for
  2991. specified subnet scope and veryfies to see they match. If they
  2992. don't match, this api will return the list of inconsistent entries.
  2993. Optionally FixFlag can be used to fix the bad entries.
  2994. Arguments:
  2995. ServerIpAddress : IP address string of the DHCP server.
  2996. SubnetAddress : Address of the subnet scope to verify.
  2997. FixFlag : If this flag is TRUE, this api will fix the bad entries.
  2998. ScanList : List of bad entries returned. The caller should free up
  2999. this memory after it has been used.
  3000. Return Value:
  3001. WINDOWS errors.
  3002. --*/
  3003. {
  3004. DWORD Status;
  3005. RedoRpc: RpcTryExcept {
  3006. Status = R_DhcpScanMDatabase(
  3007. ServerIpAddress,
  3008. MScopeName,
  3009. FixFlag,
  3010. ScanList );
  3011. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3012. Status = RpcExceptionCode();
  3013. } RpcEndExcept;
  3014. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3015. !DhcpGlobalTryDownlevel ) {
  3016. DhcpGlobalTryDownlevel = TRUE;
  3017. goto RedoRpc;
  3018. }
  3019. return Status;
  3020. }
  3021. DWORD
  3022. DhcpGetMCastMibInfo(
  3023. LPWSTR ServerIpAddress,
  3024. LPDHCP_MCAST_MIB_INFO *MibInfo
  3025. )
  3026. /*++
  3027. Routine Description:
  3028. This function retrieves all counter values of the DHCP server
  3029. service.
  3030. Arguments:
  3031. ServerIpAddress : IP address string of the DHCP server.
  3032. MibInfo : pointer a counter/table buffer. Caller should free up this
  3033. buffer after usage.
  3034. Return Value:
  3035. WINDOWS errors.
  3036. --*/
  3037. {
  3038. DWORD Status;
  3039. RedoRpc: RpcTryExcept {
  3040. Status = R_DhcpGetMCastMibInfo(
  3041. ServerIpAddress,
  3042. MibInfo );
  3043. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3044. Status = RpcExceptionCode();
  3045. } RpcEndExcept;
  3046. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3047. !DhcpGlobalTryDownlevel ) {
  3048. DhcpGlobalTryDownlevel = TRUE;
  3049. goto RedoRpc;
  3050. }
  3051. return Status;
  3052. }
  3053. DWORD
  3054. DhcpAuditLogSetParams( // set some auditlogging params
  3055. IN LPWSTR ServerIpAddress,
  3056. IN DWORD Flags, // currently must be zero
  3057. IN LPWSTR AuditLogDir, // directory to log files in..
  3058. IN DWORD DiskCheckInterval, // how often to check disk space?
  3059. IN DWORD MaxLogFilesSize, // how big can all logs files be..
  3060. IN DWORD MinSpaceOnDisk // mininum amt of free disk space
  3061. )
  3062. {
  3063. DWORD Status;
  3064. RedoRpc: RpcTryExcept {
  3065. Status = R_DhcpAuditLogSetParams(
  3066. ServerIpAddress,
  3067. Flags,
  3068. AuditLogDir,
  3069. DiskCheckInterval,
  3070. MaxLogFilesSize,
  3071. MinSpaceOnDisk
  3072. );
  3073. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3074. Status = RpcExceptionCode();
  3075. } RpcEndExcept;
  3076. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3077. !DhcpGlobalTryDownlevel ) {
  3078. DhcpGlobalTryDownlevel = TRUE;
  3079. goto RedoRpc;
  3080. }
  3081. return Status;
  3082. }
  3083. DWORD
  3084. DhcpAuditLogGetParams( // get the auditlogging params
  3085. IN LPWSTR ServerIpAddress,
  3086. IN DWORD Flags, // must be zero
  3087. OUT LPWSTR *AuditLogDir, // same meaning as in AuditLogSetParams
  3088. OUT DWORD *DiskCheckInterval, // ditto
  3089. OUT DWORD *MaxLogFilesSize, // ditto
  3090. OUT DWORD *MinSpaceOnDisk // ditto
  3091. )
  3092. {
  3093. DWORD Status;
  3094. RedoRpc: RpcTryExcept {
  3095. Status = R_DhcpAuditLogGetParams(
  3096. ServerIpAddress,
  3097. Flags,
  3098. AuditLogDir,
  3099. DiskCheckInterval,
  3100. MaxLogFilesSize,
  3101. MinSpaceOnDisk
  3102. );
  3103. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3104. Status = RpcExceptionCode();
  3105. } RpcEndExcept;
  3106. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3107. !DhcpGlobalTryDownlevel ) {
  3108. DhcpGlobalTryDownlevel = TRUE;
  3109. goto RedoRpc;
  3110. }
  3111. return Status;
  3112. }
  3113. DWORD // Status code
  3114. DhcpServerQueryAttribute( // get a server status
  3115. IN LPWSTR ServerIpAddr, // String form of server IP
  3116. IN ULONG dwReserved, // reserved for future
  3117. IN DHCP_ATTRIB_ID DhcpAttribId, // the attrib being queried
  3118. OUT LPDHCP_ATTRIB *pDhcpAttrib // fill in this field
  3119. )
  3120. {
  3121. ULONG Status;
  3122. RedoRpc: RpcTryExcept {
  3123. Status = R_DhcpServerQueryAttribute(
  3124. ServerIpAddr,
  3125. dwReserved,
  3126. DhcpAttribId,
  3127. pDhcpAttrib
  3128. );
  3129. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3130. Status = RpcExceptionCode();
  3131. } RpcEndExcept;
  3132. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3133. !DhcpGlobalTryDownlevel ) {
  3134. DhcpGlobalTryDownlevel = TRUE;
  3135. goto RedoRpc;
  3136. }
  3137. return Status;
  3138. }
  3139. DWORD // Status code
  3140. DhcpServerQueryAttributes( // query multiple attributes
  3141. IN LPWSTR ServerIpAddr, // String form of server IP
  3142. IN ULONG dwReserved, // reserved for future
  3143. IN ULONG dwAttribCount, // # of attribs being queried
  3144. IN DHCP_ATTRIB_ID pDhcpAttribs[],// array of attribs
  3145. OUT LPDHCP_ATTRIB_ARRAY *pDhcpAttribArr // Ptr is filled w/ array
  3146. )
  3147. {
  3148. ULONG Status;
  3149. RedoRpc: RpcTryExcept {
  3150. Status = R_DhcpServerQueryAttributes(
  3151. ServerIpAddr,
  3152. dwReserved,
  3153. dwAttribCount,
  3154. pDhcpAttribs,
  3155. pDhcpAttribArr
  3156. );
  3157. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3158. Status = RpcExceptionCode();
  3159. } RpcEndExcept;
  3160. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3161. !DhcpGlobalTryDownlevel ) {
  3162. DhcpGlobalTryDownlevel = TRUE;
  3163. goto RedoRpc;
  3164. }
  3165. return Status;
  3166. }
  3167. DWORD // Status code
  3168. DhcpServerRedoAuthorization( // retry the rogue server stuff
  3169. IN LPWSTR ServerIpAddr, // String form of server IP
  3170. IN ULONG dwReserved // reserved for future
  3171. )
  3172. {
  3173. ULONG Status;
  3174. // Use a short timeout value
  3175. fShortTimeOut = TRUE;
  3176. RpcTryExcept {
  3177. Status = R_DhcpServerRedoAuthorization(
  3178. ServerIpAddr,
  3179. dwReserved
  3180. );
  3181. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3182. Status = RpcExceptionCode();
  3183. } RpcEndExcept;
  3184. return Status;
  3185. }
  3186. DWORD DHCP_API_FUNCTION
  3187. DhcpAddSubnetElementV5(
  3188. DHCP_CONST WCHAR *ServerIpAddress,
  3189. DHCP_IP_ADDRESS SubnetAddress,
  3190. DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V5 * AddElementInfo
  3191. )
  3192. {
  3193. ULONG Status;
  3194. RedoRpc: RpcTryExcept {
  3195. Status = R_DhcpAddSubnetElementV5(
  3196. ServerIpAddress,
  3197. SubnetAddress,
  3198. AddElementInfo
  3199. );
  3200. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3201. Status = RpcExceptionCode();
  3202. } RpcEndExcept;
  3203. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3204. !DhcpGlobalTryDownlevel ) {
  3205. DhcpGlobalTryDownlevel = TRUE;
  3206. goto RedoRpc;
  3207. }
  3208. return Status;
  3209. }
  3210. DWORD DHCP_API_FUNCTION
  3211. DhcpEnumSubnetElementsV5(
  3212. DHCP_CONST WCHAR *ServerIpAddress,
  3213. DHCP_IP_ADDRESS SubnetAddress,
  3214. DHCP_SUBNET_ELEMENT_TYPE EnumElementType,
  3215. DHCP_RESUME_HANDLE *ResumeHandle,
  3216. DWORD PreferredMaximum,
  3217. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5 *EnumElementInfo,
  3218. DWORD *ElementsRead,
  3219. DWORD *ElementsTotal
  3220. )
  3221. {
  3222. ULONG Status;
  3223. RedoRpc: RpcTryExcept {
  3224. Status = R_DhcpEnumSubnetElementsV5(
  3225. ServerIpAddress,
  3226. SubnetAddress,
  3227. EnumElementType,
  3228. ResumeHandle,
  3229. PreferredMaximum,
  3230. EnumElementInfo,
  3231. ElementsRead,
  3232. ElementsTotal
  3233. );
  3234. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3235. Status = RpcExceptionCode();
  3236. } RpcEndExcept;
  3237. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3238. !DhcpGlobalTryDownlevel ) {
  3239. DhcpGlobalTryDownlevel = TRUE;
  3240. goto RedoRpc;
  3241. }
  3242. return Status;
  3243. }
  3244. DWORD DHCP_API_FUNCTION
  3245. DhcpRemoveSubnetElementV5(
  3246. DHCP_CONST WCHAR *ServerIpAddress,
  3247. DHCP_IP_ADDRESS SubnetAddress,
  3248. DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V5 * RemoveElementInfo,
  3249. DHCP_FORCE_FLAG ForceFlag
  3250. )
  3251. {
  3252. ULONG Status;
  3253. RedoRpc: RpcTryExcept {
  3254. Status = R_DhcpRemoveSubnetElementV5(
  3255. ServerIpAddress,
  3256. SubnetAddress,
  3257. RemoveElementInfo,
  3258. ForceFlag
  3259. );
  3260. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3261. Status = RpcExceptionCode();
  3262. } RpcEndExcept;
  3263. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3264. !DhcpGlobalTryDownlevel ) {
  3265. DhcpGlobalTryDownlevel = TRUE;
  3266. goto RedoRpc;
  3267. }
  3268. return Status;
  3269. }
  3270. DWORD DHCP_API_FUNCTION
  3271. DhcpSetServerBindingInfo(
  3272. IN DHCP_CONST WCHAR *ServerIpAddress,
  3273. IN ULONG Flags,
  3274. IN LPDHCP_BIND_ELEMENT_ARRAY BindInfo
  3275. )
  3276. {
  3277. ULONG Status;
  3278. RedoRpc: RpcTryExcept {
  3279. Status = R_DhcpSetServerBindingInfo(
  3280. ServerIpAddress,
  3281. Flags,
  3282. BindInfo
  3283. );
  3284. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3285. Status = RpcExceptionCode();
  3286. } RpcEndExcept;
  3287. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3288. !DhcpGlobalTryDownlevel ) {
  3289. DhcpGlobalTryDownlevel = TRUE;
  3290. goto RedoRpc;
  3291. }
  3292. return Status;
  3293. }
  3294. DWORD DHCP_API_FUNCTION
  3295. DhcpGetServerBindingInfo(
  3296. IN DHCP_CONST WCHAR *ServerIpAddress,
  3297. IN ULONG Flags,
  3298. OUT LPDHCP_BIND_ELEMENT_ARRAY *BindInfo
  3299. )
  3300. {
  3301. ULONG Status;
  3302. RedoRpc: RpcTryExcept {
  3303. Status = R_DhcpGetServerBindingInfo(
  3304. ServerIpAddress,
  3305. Flags,
  3306. BindInfo
  3307. );
  3308. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3309. Status = RpcExceptionCode();
  3310. } RpcEndExcept;
  3311. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3312. !DhcpGlobalTryDownlevel ) {
  3313. DhcpGlobalTryDownlevel = TRUE;
  3314. goto RedoRpc;
  3315. }
  3316. return Status;
  3317. }
  3318. DWORD
  3319. DhcpServerQueryDnsRegCredentials(
  3320. IN LPWSTR ServerIpAddress,
  3321. IN ULONG UnameSize, //in BYTES
  3322. OUT LPWSTR Uname,
  3323. IN ULONG DomainSize, // in BYTES
  3324. OUT LPWSTR Domain
  3325. )
  3326. {
  3327. ULONG Status;
  3328. RedoRpc: RpcTryExcept {
  3329. Status = R_DhcpQueryDnsRegCredentials(
  3330. ServerIpAddress,
  3331. UnameSize/sizeof(WCHAR), Uname,
  3332. DomainSize/sizeof(WCHAR), Domain );
  3333. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3334. Status = RpcExceptionCode();
  3335. } RpcEndExcept;
  3336. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3337. !DhcpGlobalTryDownlevel ) {
  3338. DhcpGlobalTryDownlevel = TRUE;
  3339. goto RedoRpc;
  3340. }
  3341. return Status;
  3342. }
  3343. DWORD
  3344. DhcpServerSetDnsRegCredentials(
  3345. IN LPWSTR ServerIpAddress,
  3346. IN LPWSTR Uname,
  3347. IN LPWSTR Domain,
  3348. IN LPWSTR Passwd
  3349. )
  3350. {
  3351. ULONG Status;
  3352. RedoRpc: RpcTryExcept {
  3353. Status = R_DhcpSetDnsRegCredentials(
  3354. ServerIpAddress, Uname, Domain, Passwd );
  3355. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3356. Status = RpcExceptionCode();
  3357. } RpcEndExcept;
  3358. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3359. !DhcpGlobalTryDownlevel ) {
  3360. DhcpGlobalTryDownlevel = TRUE;
  3361. goto RedoRpc;
  3362. }
  3363. return Status;
  3364. }
  3365. DWORD
  3366. DhcpServerBackupDatabase(
  3367. IN LPWSTR ServerIpAddress,
  3368. IN LPWSTR Path
  3369. )
  3370. {
  3371. ULONG Status;
  3372. RedoRpc: RpcTryExcept {
  3373. Status = R_DhcpBackupDatabase(
  3374. ServerIpAddress, Path );
  3375. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3376. Status = RpcExceptionCode();
  3377. } RpcEndExcept;
  3378. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3379. !DhcpGlobalTryDownlevel ) {
  3380. DhcpGlobalTryDownlevel = TRUE;
  3381. goto RedoRpc;
  3382. }
  3383. return Status;
  3384. }
  3385. DWORD
  3386. DhcpServerRestoreDatabase(
  3387. IN LPWSTR ServerIpAddress,
  3388. IN LPWSTR Path
  3389. )
  3390. {
  3391. ULONG Status;
  3392. RedoRpc: RpcTryExcept {
  3393. Status = R_DhcpRestoreDatabase(
  3394. ServerIpAddress, Path );
  3395. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  3396. Status = RpcExceptionCode();
  3397. } RpcEndExcept;
  3398. if( Status == RPC_S_UNKNOWN_AUTHN_SERVICE &&
  3399. !DhcpGlobalTryDownlevel ) {
  3400. DhcpGlobalTryDownlevel = TRUE;
  3401. goto RedoRpc;
  3402. }
  3403. return Status;
  3404. }
  3405. #define BINL_SVC_NAME L"binlsvc"
  3406. BOOL
  3407. BinlServiceInstalled(
  3408. VOID
  3409. )
  3410. /*++
  3411. Routine Description:
  3412. This routine checks if BINL service has been installed.
  3413. BINL service is "binlsvc"
  3414. Return Values;
  3415. TRUE -- binl service is installed
  3416. FALSE -- binl service is not installed
  3417. --*/
  3418. {
  3419. SC_HANDLE hScManager, hService;
  3420. ULONG Error, Attempt;
  3421. SERVICE_STATUS ServiceStatus;
  3422. hScManager = OpenSCManager(
  3423. NULL, NULL,
  3424. STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE
  3425. );
  3426. if( NULL == hScManager ) {
  3427. DbgPrint("DHCP: OpenSCManager failed 0x%lx\n", GetLastError());
  3428. //ASSERT(FALSE);
  3429. return FALSE;
  3430. }
  3431. hService = OpenService(
  3432. hScManager, BINL_SVC_NAME,
  3433. SERVICE_QUERY_STATUS
  3434. );
  3435. #if DBG
  3436. if( NULL == hService ) {
  3437. Error = GetLastError();
  3438. if( ERROR_SERVICE_DOES_NOT_EXIST != Error ) {
  3439. //ASSERT(FALSE);
  3440. }
  3441. DbgPrint("DHCP: Can't open BINLSVC service: 0x%lx\n", Error);
  3442. }
  3443. #endif
  3444. CloseServiceHandle(hService);
  3445. CloseServiceHandle(hScManager);
  3446. return (NULL != hService);
  3447. }
  3448. VOID
  3449. WINAPI
  3450. DhcpDsClearHostServerEntries(
  3451. VOID
  3452. )
  3453. /*++
  3454. Routine Description:
  3455. This routine clears off any entries in DS for the current host assuming
  3456. it has permissions to do so..
  3457. --*/
  3458. {
  3459. ULONG Error;
  3460. struct hostent *HostEnt;
  3461. int i, j;
  3462. WSADATA wsadata;
  3463. LPDHCP_SERVER_INFO_ARRAY Servers = NULL;
  3464. if( BinlServiceInstalled() ) {
  3465. //
  3466. // Do not do anything if BINL is installed
  3467. //
  3468. return ;
  3469. }
  3470. Error = WSAStartup( 0x0101, &wsadata);
  3471. if( ERROR_SUCCESS != Error ) {
  3472. return;
  3473. }
  3474. do {
  3475. HostEnt = gethostbyname( NULL );
  3476. if( NULL == HostEnt ) break;
  3477. //
  3478. // Now try to start the DS module..
  3479. //
  3480. Error = DhcpDsInit();
  3481. if( ERROR_SUCCESS != Error ) break;
  3482. do {
  3483. Error = DhcpEnumServers(
  3484. 0,
  3485. NULL,
  3486. &Servers,
  3487. 0,
  3488. 0
  3489. );
  3490. if( ERROR_SUCCESS != Error ) break;
  3491. i = 0;
  3492. if( !Servers ) break;
  3493. while( HostEnt->h_addr_list[i] ) {
  3494. ULONG Addr = *(ULONG *)(HostEnt->h_addr_list[i]);
  3495. i ++;
  3496. if( Addr == 0 || Addr == ~0 || Addr == INADDR_LOOPBACK )
  3497. continue;
  3498. for( j = 0; j < (int)Servers->NumElements; j ++ ) {
  3499. if( Addr == ntohl(Servers->Servers[j].ServerAddress )) {
  3500. DhcpDeleteServer(
  3501. 0,
  3502. NULL,
  3503. &Servers->Servers[j],
  3504. NULL,
  3505. NULL
  3506. );
  3507. }
  3508. }
  3509. }
  3510. DhcpRpcFreeMemory( Servers );
  3511. } while ( 0 );
  3512. DhcpDsCleanup();
  3513. } while ( 0 );
  3514. WSACleanup();
  3515. }
  3516. //================================================================================
  3517. // end of file
  3518. //================================================================================