Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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