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

2674 lines
80 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcpreg.c
  5. Abstract:
  6. Stubs functions that manipulate NT registry.
  7. Author:
  8. Madan Appiah (madana) 7-Dec-1993.
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "dhcpglobal.h"
  15. #include <dhcploc.h>
  16. #include <dhcppro.h>
  17. #include <dhcpcapi.h>
  18. #include <dnsapi.h>
  19. #include <align.h>
  20. #include <lmcons.h>
  21. #include <ntddndis.h>
  22. #define DEFAULT_METRIC (1)
  23. extern ULONG
  24. FixupDhcpClassId(
  25. IN LPWSTR AdapterName,
  26. IN BOOL SkipClassEnum
  27. );
  28. //
  29. // Local function prototypes
  30. //
  31. DWORD
  32. DhcpRegQueryInfoKey(
  33. HKEY KeyHandle,
  34. LPDHCP_KEY_QUERY_INFO QueryInfo
  35. )
  36. /*++
  37. Routine Description:
  38. This function retrieves information about given key.
  39. Arguments:
  40. KeyHandle - handle to a registry key whose info will be retrieved.
  41. QueryInfo - pointer to a info structure where the key info will be
  42. returned.
  43. Return Value:
  44. Registry Errors.
  45. --*/
  46. {
  47. DWORD Error;
  48. QueryInfo->ClassSize = DHCP_CLASS_SIZE;
  49. Error = RegQueryInfoKey(
  50. KeyHandle,
  51. QueryInfo->Class,
  52. &QueryInfo->ClassSize,
  53. NULL,
  54. &QueryInfo->NumSubKeys,
  55. &QueryInfo->MaxSubKeyLen,
  56. &QueryInfo->MaxClassLen,
  57. &QueryInfo->NumValues,
  58. &QueryInfo->MaxValueNameLen,
  59. &QueryInfo->MaxValueLen,
  60. &QueryInfo->SecurityDescriptorLen,
  61. &QueryInfo->LastWriteTime
  62. );
  63. DhcpAssert( Error != ERROR_MORE_DATA );
  64. if( Error == ERROR_MORE_DATA ){
  65. Error = ERROR_SUCCESS;
  66. }
  67. return( Error );
  68. }
  69. DWORD
  70. GetRegistryString(
  71. HKEY Key,
  72. LPWSTR ValueStringName,
  73. LPWSTR *String,
  74. LPDWORD StringSize
  75. )
  76. /*++
  77. Routine Description:
  78. This function retrieves the specified string value from the
  79. registry. It allocates local memory for the returned string.
  80. Arguments:
  81. Key : registry handle to the key where the value is.
  82. ValueStringName : name of the value string.
  83. String : pointer to a location where the string pointer is returned.
  84. StringSize : size of the string data returned. Optional
  85. Return Value:
  86. The status of the operation.
  87. --*/
  88. {
  89. DWORD Error;
  90. DWORD LocalValueType;
  91. DWORD ValueSize;
  92. LPWSTR LocalString;
  93. DhcpAssert( *String == NULL );
  94. //
  95. // Query DataType and BufferSize.
  96. //
  97. Error = RegQueryValueEx(
  98. Key,
  99. ValueStringName,
  100. 0,
  101. &LocalValueType,
  102. NULL,
  103. &ValueSize );
  104. if( Error != ERROR_SUCCESS ) {
  105. return(Error);
  106. }
  107. DhcpAssert( (LocalValueType == REG_SZ) ||
  108. (LocalValueType == REG_MULTI_SZ) );
  109. if( ValueSize == 0 ) {
  110. if( StringSize != NULL ) {
  111. *StringSize = 0;
  112. }
  113. *String = NULL;
  114. return( ERROR_SUCCESS );
  115. }
  116. //
  117. // now allocate memory for string data.
  118. //
  119. LocalString = DhcpAllocateMemory( ValueSize );
  120. if(LocalString == NULL) {
  121. return( ERROR_NOT_ENOUGH_MEMORY );
  122. }
  123. //
  124. // Now query the string data.
  125. //
  126. Error = RegQueryValueEx(
  127. Key,
  128. ValueStringName,
  129. 0,
  130. &LocalValueType,
  131. (LPBYTE)(LocalString),
  132. &ValueSize );
  133. if( Error != ERROR_SUCCESS ) {
  134. DhcpFreeMemory(LocalString);
  135. return(Error);
  136. }
  137. *String = LocalString;
  138. if( StringSize != NULL ) {
  139. *StringSize = ValueSize;
  140. }
  141. return( ERROR_SUCCESS );
  142. }
  143. DWORD
  144. ParseIpString(
  145. WCHAR *AddressString,
  146. DHCP_IP_ADDRESS *IpAddress
  147. )
  148. /*++
  149. Routine Description
  150. This function converts an Internet standard 4-octet dotted decimal
  151. IP address string into a numeric IP address. Unlike inet_addr(), this
  152. routine does not support address strings of less than 4 octets nor does
  153. it support octal and hexadecimal octets.
  154. Lifted from tcpip\driver\ipv4\ntip.c
  155. Arguments
  156. AddressString - IP address in dotted decimal notation
  157. IpAddress - Pointer to a variable to hold the resulting address
  158. Return Value:
  159. ERROR_SUCCESS if the address string was converted.
  160. --*/
  161. {
  162. WCHAR *cp, *startPointer, *endPointer;
  163. ULONG digit, multiplier;
  164. int i;
  165. *IpAddress = 0;
  166. startPointer = AddressString;
  167. endPointer = AddressString;
  168. i = 3;
  169. while (i >= 0) {
  170. //
  171. // Collect the characters up to a '.' or the end of the string.
  172. //
  173. while ((*endPointer != L'.') && (*endPointer != L'\0')) {
  174. endPointer++;
  175. }
  176. if (startPointer == endPointer) {
  177. return ERROR_INVALID_DATA;
  178. }
  179. //
  180. // Convert the number.
  181. //
  182. for (cp = (endPointer - 1), multiplier = 1, digit = 0;
  183. cp >= startPointer;
  184. cp--, multiplier *= 10
  185. ) {
  186. if ((*cp < L'0') || (*cp > L'9') || (multiplier > 100)) {
  187. return ERROR_INVALID_DATA;
  188. }
  189. digit += (multiplier * ((ULONG) (*cp - L'0')));
  190. }
  191. if (digit > 255) {
  192. return ERROR_INVALID_DATA;
  193. }
  194. digit <<= ((3-i) * 8);
  195. (*IpAddress) |= digit;
  196. //
  197. // We are finished if we have found and converted 4 octets and have
  198. // no other characters left in the string.
  199. //
  200. if ((i-- == 0) &&
  201. ((*endPointer == L'\0') || (*endPointer == L' '))
  202. ) {
  203. return ERROR_SUCCESS;
  204. }
  205. if (*endPointer == L'\0') {
  206. return ERROR_INVALID_DATA;
  207. }
  208. startPointer = ++endPointer;
  209. }
  210. return ERROR_INVALID_DATA;
  211. }
  212. DWORD
  213. RegGetIpAndSubnet(
  214. IN DHCP_CONTEXT *dhcpContext,
  215. OUT PIP_SUBNET *TcpConf,
  216. OUT int *Count
  217. )
  218. /*++
  219. Routine Description
  220. This function read a list of <IP,SubnetMask> pairs from TCPIP registry parameters.
  221. Lifted from tcpip\driver\ipv4\ntip.c
  222. Arguments
  223. KeyHandle keyhandle NOT location
  224. TcpConf The pointer to the array of <IP,SubnetMask>
  225. Count The # of records.
  226. Return Value:
  227. ERROR_SUCCESS if succeed, otherfise fail.
  228. --*/
  229. {
  230. DWORD Error;
  231. WCHAR *IpList, *SubnetList, *IpListTmp, *SubnetListTmp;
  232. int i, cnt;
  233. PIP_SUBNET IpSubnetArray;
  234. *Count = 0;
  235. *TcpConf = NULL;
  236. IpList = NULL;
  237. SubnetList = NULL;
  238. IpSubnetArray = NULL;
  239. Error = DhcpGetRegistryValueWithKey(
  240. dhcpContext->AdapterInfoKey,
  241. DHCP_STATIC_IP_ADDRESS_STRING,
  242. DHCP_STATIC_IP_ADDRESS_STRING_TYPE,
  243. &IpList);
  244. if (Error != ERROR_SUCCESS) {
  245. DhcpAssert(IpList == NULL);
  246. goto cleanup;
  247. }
  248. Error = DhcpGetRegistryValueWithKey(
  249. dhcpContext->AdapterInfoKey,
  250. DHCP_STATIC_SUBNET_MASK_STRING,
  251. DHCP_STATIC_SUBNET_MASK_STRING_TYPE,
  252. &SubnetList);
  253. if (Error != ERROR_SUCCESS) {
  254. DhcpAssert(SubnetList == NULL);
  255. goto cleanup;
  256. }
  257. DhcpAssert(IpList && SubnetList);
  258. /*
  259. * Count the # of valid <IP,subnet_mask>
  260. */
  261. cnt = 0;
  262. IpListTmp = IpList;
  263. SubnetListTmp = SubnetList;
  264. while(*IpListTmp && *SubnetListTmp) {
  265. DHCP_IP_ADDRESS SubnetMask;
  266. DHCP_IP_ADDRESS IpAddress;
  267. Error = ParseIpString(IpListTmp, &IpAddress);
  268. if (Error == ERROR_SUCCESS && IpAddress != 0xffffffff && IpAddress) {
  269. Error = ParseIpString(SubnetListTmp, &SubnetMask);
  270. if (Error == ERROR_SUCCESS) {
  271. cnt++;
  272. }
  273. }
  274. SubnetListTmp += wcslen(SubnetListTmp) + 1;
  275. IpListTmp += wcslen(IpListTmp) + 1;
  276. }
  277. if (cnt == 0) {
  278. DhcpPrint(( DEBUG_ERRORS, "No valid IP/SubnetMask pair\n"));
  279. Error = ERROR_BAD_FORMAT;
  280. goto cleanup;
  281. }
  282. IpSubnetArray = (PIP_SUBNET)DhcpAllocateMemory(cnt * sizeof(IP_SUBNET));
  283. if (IpSubnetArray == NULL) {
  284. Error = ERROR_NOT_ENOUGH_MEMORY;
  285. goto cleanup;
  286. }
  287. /*
  288. * copy the Ip and subnet mask
  289. */
  290. *Count = cnt;
  291. *TcpConf = IpSubnetArray;
  292. cnt = 0;
  293. IpListTmp = IpList;
  294. SubnetListTmp = SubnetList;
  295. while(*IpListTmp && *SubnetListTmp) {
  296. DHCP_IP_ADDRESS SubnetMask;
  297. DHCP_IP_ADDRESS IpAddress;
  298. Error = ParseIpString(IpListTmp, &IpAddress);
  299. if (Error == ERROR_SUCCESS && IpAddress != 0xffffffff && IpAddress) {
  300. Error = ParseIpString(SubnetListTmp, &SubnetMask);
  301. if (Error == ERROR_SUCCESS) {
  302. DhcpAssert(cnt < *Count);
  303. IpSubnetArray[cnt].IpAddress = IpAddress;
  304. IpSubnetArray[cnt].SubnetMask = SubnetMask;
  305. cnt++;
  306. }
  307. }
  308. SubnetListTmp += wcslen(SubnetListTmp) + 1;
  309. IpListTmp += wcslen(IpListTmp) + 1;
  310. }
  311. Error = ERROR_SUCCESS;
  312. cleanup:
  313. if (IpList) DhcpFreeMemory(IpList);
  314. if (SubnetList) DhcpFreeMemory(SubnetList);
  315. return Error;
  316. }
  317. DWORD
  318. RegSetIpAddress(
  319. HKEY KeyHandle,
  320. LPWSTR ValueName,
  321. DWORD ValueType,
  322. DHCP_IP_ADDRESS IpAddress
  323. )
  324. /*++
  325. Routine Description:
  326. This function sets IpAddress Value in the registry.
  327. Arguments:
  328. KeyHandle - handle to the key.
  329. ValueName - name of the value field.
  330. ValueType - Type of the value field.
  331. IpAddress - Ipaddress to be set.
  332. Return Value:
  333. Registry Error.
  334. --*/
  335. {
  336. DWORD Error;
  337. LPSTR AnsiAddressString;
  338. WCHAR UnicodeAddressBuf[DOT_IP_ADDR_SIZE];
  339. LPWSTR UnicodeAddressString;
  340. LPWSTR MultiIpAddressString = NULL;
  341. LPWSTR NewMultiIpAddressString = NULL;
  342. DWORD MultiIpAddressStringSize;
  343. DWORD NewMultiIpAddressStringSize;
  344. DWORD FirstOldIpAddressSize;
  345. AnsiAddressString = inet_ntoa( *(struct in_addr *)&IpAddress );
  346. UnicodeAddressString = DhcpOemToUnicode(
  347. AnsiAddressString,
  348. UnicodeAddressBuf );
  349. DhcpAssert( UnicodeAddressString != NULL );
  350. if( ValueType == REG_SZ ) {
  351. Error = RegSetValueEx(
  352. KeyHandle,
  353. ValueName,
  354. 0,
  355. ValueType,
  356. (LPBYTE)UnicodeAddressString,
  357. (wcslen(UnicodeAddressString) + 1) * sizeof(WCHAR) );
  358. goto Cleanup;
  359. }
  360. DhcpAssert( ValueType == REG_MULTI_SZ );
  361. //
  362. // replace the first IpAddress.
  363. //
  364. //
  365. // query current multi-IpAddress string.
  366. //
  367. Error = GetRegistryString(
  368. KeyHandle,
  369. ValueName,
  370. &MultiIpAddressString,
  371. &MultiIpAddressStringSize );
  372. if( Error != ERROR_SUCCESS ) {
  373. goto Cleanup;
  374. }
  375. //
  376. // allocate new address string.
  377. //
  378. DhcpAssert(MultiIpAddressString != NULL);
  379. FirstOldIpAddressSize =
  380. (wcslen(MultiIpAddressString) + 1) * sizeof(WCHAR);
  381. NewMultiIpAddressStringSize =
  382. MultiIpAddressStringSize - FirstOldIpAddressSize +
  383. (wcslen(UnicodeAddressString) + 1) * sizeof(WCHAR);
  384. NewMultiIpAddressString = DhcpAllocateMemory( NewMultiIpAddressStringSize );
  385. if( NewMultiIpAddressString == NULL ) {
  386. Error = ERROR_NOT_ENOUGH_MEMORY;
  387. goto Cleanup;
  388. }
  389. //
  390. // make new address string first.
  391. //
  392. wcscpy( NewMultiIpAddressString, UnicodeAddressString );
  393. //
  394. // copy rest of the old addresses
  395. //
  396. RtlCopyMemory(
  397. (LPBYTE)NewMultiIpAddressString +
  398. (wcslen(UnicodeAddressString) + 1) * sizeof(WCHAR),
  399. (LPBYTE)MultiIpAddressString + FirstOldIpAddressSize,
  400. MultiIpAddressStringSize - FirstOldIpAddressSize );
  401. Error = RegSetValueEx(
  402. KeyHandle,
  403. ValueName,
  404. 0,
  405. ValueType,
  406. (LPBYTE)NewMultiIpAddressString,
  407. NewMultiIpAddressStringSize );
  408. Cleanup:
  409. if( MultiIpAddressString != NULL) {
  410. DhcpFreeMemory( MultiIpAddressString );
  411. }
  412. if( NewMultiIpAddressString != NULL) {
  413. DhcpFreeMemory( NewMultiIpAddressString );
  414. }
  415. return( Error );
  416. }
  417. #if DBG
  418. DWORD
  419. RegSetTimeField(
  420. HKEY KeyHandle,
  421. LPWSTR ValueName,
  422. DWORD ValueType,
  423. time_t Time
  424. )
  425. /*++
  426. Routine Description:
  427. This function sets time Value in string form in the registry.
  428. Arguments:
  429. KeyHandle - handle to the key.
  430. ValueName - name of the value field.
  431. ValueType - Type of the value field.
  432. Time - time value to be set.
  433. Return Value:
  434. Registry Error.
  435. --*/
  436. {
  437. DWORD Error;
  438. WCHAR UnicodeTimeBuf[TIME_STRING_LEN];
  439. LPWSTR UnicodeTimeString;
  440. UnicodeTimeString =
  441. DhcpOemToUnicode( ctime( &Time ), UnicodeTimeBuf ) ;
  442. DhcpAssert( UnicodeTimeString != NULL );
  443. DhcpAssert( ValueType == REG_SZ );
  444. Error = RegSetValueEx(
  445. KeyHandle,
  446. ValueName,
  447. 0,
  448. ValueType,
  449. (LPBYTE)UnicodeTimeString,
  450. (wcslen(UnicodeTimeString) + 1) * sizeof(WCHAR) );
  451. return( Error );
  452. }
  453. #endif
  454. DWORD // status
  455. DhcpGetRegistryValueWithKey( // see defn of GetRegistryValue
  456. IN HKEY KeyHandle, // keyhandle NOT location
  457. IN LPWSTR ValueName, // value to read from registry
  458. IN DWORD ValueType, // type of value
  459. OUT LPVOID *Data // this will be filled in
  460. ) {
  461. DWORD Error;
  462. DWORD LocalValueType;
  463. DWORD ValueSize;
  464. LPWSTR LocalString;
  465. //
  466. // Query DataType and BufferSize.
  467. //
  468. Error = RegQueryValueEx(
  469. KeyHandle,
  470. ValueName,
  471. 0,
  472. &LocalValueType,
  473. NULL,
  474. &ValueSize
  475. );
  476. if( Error != ERROR_SUCCESS ) goto Cleanup;
  477. if( LocalValueType != ValueType ) {
  478. Error = ERROR_INVALID_PARAMETER;
  479. goto Cleanup;
  480. }
  481. switch( LocalValueType ) {
  482. case REG_DWORD:
  483. DhcpAssert( ValueSize == sizeof(DWORD) );
  484. Error = RegQueryValueEx(
  485. KeyHandle,
  486. ValueName,
  487. 0,
  488. &LocalValueType,
  489. (LPBYTE)Data,
  490. &ValueSize
  491. );
  492. if( Error != ERROR_SUCCESS ) goto Cleanup;
  493. DhcpAssert( LocalValueType == REG_DWORD );
  494. DhcpAssert( ValueSize == sizeof(DWORD) );
  495. break;
  496. case REG_SZ :
  497. case REG_MULTI_SZ:
  498. DhcpAssert(*Data == NULL);
  499. if( ValueSize == 0 ) {
  500. Error = ERROR_SUCCESS;
  501. break;
  502. }
  503. //
  504. // now allocate memory for string data.
  505. //
  506. LocalString = DhcpAllocateMemory( ValueSize );
  507. if(LocalString == NULL) {
  508. Error = ERROR_NOT_ENOUGH_MEMORY;
  509. goto Cleanup;
  510. }
  511. //
  512. // Now query the string data.
  513. //
  514. Error = RegQueryValueEx(
  515. KeyHandle,
  516. ValueName,
  517. 0,
  518. &LocalValueType,
  519. (LPBYTE)(LocalString),
  520. &ValueSize
  521. );
  522. if( Error != ERROR_SUCCESS ) {
  523. DhcpFreeMemory(LocalString);
  524. goto Cleanup;
  525. }
  526. DhcpAssert( (LocalValueType == REG_SZ) ||
  527. (LocalValueType == REG_MULTI_SZ) );
  528. *Data = (LPBYTE)LocalString;
  529. Error = ERROR_SUCCESS;
  530. break;
  531. default:
  532. Error = ERROR_INVALID_PARAMETER;
  533. break;
  534. }
  535. Cleanup:
  536. return( Error );
  537. }
  538. DWORD
  539. DhcpGetRegistryValue(
  540. LPWSTR RegKey,
  541. LPWSTR ValueName,
  542. DWORD ValueType,
  543. PVOID *Data
  544. )
  545. /*++
  546. Routine Description:
  547. This function retrieves the option information from registry.
  548. Arguments:
  549. RegKey - pointer to registry location. like
  550. system\currentcontrolset\services\..
  551. ValueName - name of the value to read.
  552. ValueType - type of reg value, REG_DWORD, REG_SZ ..
  553. Data - pointer to a location where the data will be returned.
  554. For string data and binary data, the function allocates
  555. memory, the caller is responsible to free it.
  556. Return Value:
  557. Registry Errors.
  558. --*/
  559. {
  560. DWORD Error;
  561. HKEY KeyHandle = NULL;
  562. DWORD LocalValueType;
  563. DWORD ValueSize;
  564. LPWSTR LocalString;
  565. Error = RegOpenKeyEx(
  566. HKEY_LOCAL_MACHINE,
  567. RegKey,
  568. 0 /* Reserved */,
  569. DHCP_CLIENT_KEY_ACCESS,
  570. &KeyHandle
  571. );
  572. if( Error != ERROR_SUCCESS ) return Error;
  573. Error = DhcpGetRegistryValueWithKey(
  574. KeyHandle,
  575. ValueName,
  576. ValueType,
  577. Data
  578. );
  579. RegCloseKey(KeyHandle);
  580. return Error;
  581. }
  582. DWORD // win32
  583. DhcpRegRecurseDeleteSub( // delete the key's subkeys, recursing downwards
  584. IN HKEY Key,
  585. IN LPWSTR KeyName
  586. ) {
  587. HKEY SubKey;
  588. DWORD Error;
  589. DWORD Index;
  590. WCHAR NameBuf[512];
  591. FILETIME Unused;
  592. Error = RegOpenKeyEx( // open this key to get its sub keys
  593. Key,
  594. KeyName,
  595. 0 /* Reserved */,
  596. KEY_ALL_ACCESS,
  597. &SubKey
  598. );
  599. if( ERROR_SUCCESS != Error ) return Error;
  600. Error = ERROR_SUCCESS;
  601. Index = 0;
  602. while( ERROR_SUCCESS == Error ) { // scan looking for sub keys
  603. DWORD Size;
  604. memset(NameBuf, 0, sizeof(NameBuf)); sizeof(NameBuf);
  605. Size = sizeof(NameBuf)/sizeof(NameBuf[0]);
  606. Error = RegEnumKeyEx(
  607. SubKey,
  608. Index,
  609. NameBuf,
  610. &Size, // In # of characters
  611. NULL /* Reserved */,
  612. NULL /* Class */,
  613. NULL /* Class size */,
  614. &Unused
  615. );
  616. if( ERROR_SUCCESS != Error ) break;
  617. Error = DhcpRegRecurseDelete(SubKey, NameBuf);
  618. if( ERROR_SUCCESS != Error ) break;
  619. memset(NameBuf, 0, sizeof(NameBuf)); sizeof(NameBuf);
  620. Size = sizeof(NameBuf)/sizeof(NameBuf[0]);
  621. Error = RegEnumKeyEx(
  622. SubKey,
  623. Index,
  624. NameBuf,
  625. &Size,
  626. NULL /* Reserved */,
  627. NULL /* Class */,
  628. NULL /* Class size */,
  629. &Unused
  630. );
  631. if( ERROR_SUCCESS != Error ) break;
  632. Error = RegDeleteKey(SubKey, NameBuf);
  633. if( ERROR_SUCCESS != Error ) break;
  634. Index ++;
  635. }
  636. RegCloseKey(SubKey);
  637. if( ERROR_NO_MORE_ITEMS != Error ) return Error;
  638. return ERROR_SUCCESS;
  639. }
  640. DWORD // win32 status
  641. DhcpRegRecurseDelete( // delete the specified key AND its sub keys
  642. IN HKEY Key, // root key
  643. IN LPWSTR KeyName // the key to delete along with subkeys
  644. ) {
  645. DWORD Error;
  646. DWORD Error2;
  647. Error = DhcpRegRecurseDeleteSub(Key,KeyName);
  648. Error2 = RegDeleteKey(Key,KeyName);
  649. if( ERROR_SUCCESS != Error ) {
  650. return Error;
  651. }
  652. return Error2;
  653. }
  654. BOOL
  655. SetOverRideDefaultGateway(
  656. LPWSTR AdapterName
  657. )
  658. /*++
  659. Routine Description:
  660. This function reads the override default gateway parameter from
  661. registry and if this parameter is non-null, it sets the gateway
  662. value in the TCP/IP stack and return TRUE, otherwise it returns
  663. FALSE.
  664. Arguments:
  665. AdapterName - name of the adapter we are working on.
  666. Return Value:
  667. TRUE: If the override gateway parameter is specified in the registry
  668. and it is succssfully set in the TCP/IP router table.
  669. FALSE : Otherwise.
  670. --*/
  671. {
  672. DWORD Error;
  673. LPWSTR RegKey = NULL;
  674. DWORD RegKeyLength;
  675. HKEY KeyHandle = NULL;
  676. LPWSTR DefaultGatewayString = NULL;
  677. DWORD DefaultGatewayStringSize;
  678. BOOL EmptyDefaultGatewayString = FALSE;
  679. LPWSTR DefaultGatewayMetricString = NULL;
  680. DWORD DefaultGatewayMetricStringSize;
  681. LPWSTR String;
  682. LPWSTR Metric;
  683. DWORD ValueSize,ValueType;
  684. DWORD DontAddGatewayFlag;
  685. RegKeyLength = (DWORD)(sizeof(DHCP_SERVICES_KEY) +
  686. sizeof(REGISTRY_CONNECT_STRING) +
  687. wcslen(AdapterName) * sizeof(WCHAR) +
  688. sizeof(DHCP_ADAPTER_PARAMETERS_KEY));
  689. RegKey = DhcpAllocateMemory( RegKeyLength );
  690. if( RegKey == NULL ) {
  691. Error = ERROR_NOT_ENOUGH_MEMORY;
  692. goto Cleanup;
  693. }
  694. wcscpy( RegKey, DHCP_SERVICES_KEY );
  695. wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
  696. wcscat( RegKey, REGISTRY_CONNECT_STRING );
  697. wcscat( RegKey, AdapterName);
  698. Error = RegOpenKeyEx(
  699. HKEY_LOCAL_MACHINE,
  700. RegKey,
  701. 0, // Reserved field
  702. DHCP_CLIENT_KEY_ACCESS,
  703. &KeyHandle
  704. );
  705. DhcpFreeMemory(RegKey);
  706. RegKey = NULL;
  707. if( Error != ERROR_SUCCESS ) {
  708. goto Cleanup;
  709. }
  710. DhcpAssert( KeyHandle != NULL );
  711. ValueSize = sizeof(DWORD);
  712. Error = RegQueryValueEx(
  713. KeyHandle,
  714. DHCP_DONT_ADD_DEFAULT_GATEWAY_FLAG,
  715. 0,
  716. &ValueType,
  717. (LPBYTE)&DontAddGatewayFlag,
  718. &ValueSize );
  719. if ( Error == ERROR_SUCCESS && DontAddGatewayFlag > 0 ) {
  720. RegCloseKey(KeyHandle);
  721. return TRUE;
  722. }
  723. Error = GetRegistryString(
  724. KeyHandle,
  725. DHCP_DEFAULT_GATEWAY_PARAMETER,
  726. &DefaultGatewayString,
  727. &DefaultGatewayStringSize );
  728. if( Error != ERROR_SUCCESS ) {
  729. goto Cleanup;
  730. }
  731. if ( (DefaultGatewayStringSize == 0) ||
  732. (wcslen(DefaultGatewayString) == 0) ) {
  733. EmptyDefaultGatewayString = TRUE;
  734. goto Cleanup;
  735. }
  736. Error = GetRegistryString(
  737. KeyHandle,
  738. DHCP_DEFAULT_GATEWAY_METRIC_PARAMETER,
  739. &DefaultGatewayMetricString,
  740. &DefaultGatewayMetricStringSize
  741. );
  742. if( 0 == DefaultGatewayMetricStringSize ) {
  743. Metric = NULL;
  744. } else {
  745. Metric = DefaultGatewayMetricString;
  746. }
  747. for( String = DefaultGatewayString;
  748. wcslen(String) != 0;
  749. String += (wcslen(String) + 1) ) {
  750. CHAR OemIpAddressBuffer[DOT_IP_ADDR_SIZE];
  751. LPSTR OemIpAddressString;
  752. DHCP_IP_ADDRESS GatewayAddress;
  753. DWORD GatewayMetric = 1;
  754. OemIpAddressString = DhcpUnicodeToOem( String, OemIpAddressBuffer );
  755. GatewayAddress = DhcpDottedStringToIpAddress( OemIpAddressString );
  756. if( Metric && Metric[0] ) {
  757. LPWSTR MetricEnd;
  758. GatewayMetric = wcstoul(Metric, &MetricEnd, 0);
  759. if( GatewayMetric && GatewayMetric != MAXULONG ) {
  760. Metric += wcslen(Metric) + 1;
  761. } else {
  762. GatewayMetric = DEFAULT_METRIC;
  763. Metric = NULL;
  764. }
  765. }
  766. Error = SetDefaultGateway(
  767. DEFAULT_GATEWAY_ADD,
  768. GatewayAddress,
  769. GatewayMetric
  770. );
  771. if( Error != ERROR_SUCCESS ) {
  772. goto Cleanup;
  773. }
  774. }
  775. Cleanup:
  776. if( RegKey != NULL ) {
  777. DhcpFreeMemory( RegKey );
  778. }
  779. if( KeyHandle != NULL ) {
  780. RegCloseKey( KeyHandle );
  781. }
  782. if( DefaultGatewayString != NULL ) {
  783. DhcpFreeMemory( DefaultGatewayString );
  784. }
  785. if( DefaultGatewayMetricString != NULL ) {
  786. DhcpFreeMemory( DefaultGatewayMetricString );
  787. }
  788. if( Error != ERROR_SUCCESS ) {
  789. DhcpPrint((DEBUG_ERRORS,
  790. "SetOverRideDefaultGateway failed, %ld.\n", Error ));
  791. return( FALSE );
  792. }
  793. if( EmptyDefaultGatewayString ) {
  794. return( FALSE );
  795. }
  796. return( TRUE );
  797. }
  798. DWORD
  799. SetDhcpOption(
  800. LPWSTR AdapterName,
  801. DHCP_OPTION_ID OptionId,
  802. LPBOOL DefaultGatewaysSet,
  803. BOOL LastKnownDefaultGateway
  804. ) {
  805. DhcpAssert(FALSE);
  806. return 0;
  807. }
  808. DWORD
  809. DhcpMakeNICEntry(
  810. PDHCP_CONTEXT *ReturnDhcpContext,
  811. BYTE HardwareAddressType,
  812. LPBYTE HardwareAddress,
  813. DWORD HardwareAddressLength,
  814. DHCP_CLIENT_IDENTIFIER *pClientID,
  815. LPWSTR AdapterName,
  816. LPWSTR RegKey
  817. )
  818. /*++
  819. Routine Description:
  820. This function allocates memory and fills in the fields that are passed as
  821. parameter. (Only the variable length fields must be here).
  822. Arguments:
  823. Parameter for new entry :
  824. HardwareAddressType,
  825. HardwareAddress,
  826. HardwareAddressLength,
  827. ClientId,
  828. AdapterName,
  829. RegKey
  830. Return Value:
  831. Windows Error.
  832. History:
  833. 8/26/96 Frankbee Added Client ID (option 61) support
  834. --*/
  835. {
  836. PDHCP_CONTEXT DhcpContext = NULL;
  837. ULONG DhcpContextSize;
  838. PLOCAL_CONTEXT_INFO LocalInfo;
  839. LPVOID Ptr;
  840. BYTE StateStringBuffer[200];
  841. DWORD AdapterNameLen;
  842. DWORD DeviceNameLen;
  843. DWORD NetBTDeviceNameLen;
  844. DWORD RegKeyLen;
  845. AdapterNameLen = ((wcslen(AdapterName) + 1) * sizeof(WCHAR));
  846. NetBTDeviceNameLen =
  847. ((wcslen(DHCP_ADAPTERS_DEVICE_STRING) +
  848. wcslen(DHCP_NETBT_DEVICE_STRING) +
  849. wcslen(AdapterName) + 1) * sizeof(WCHAR));
  850. RegKeyLen = ((wcslen(RegKey) + 1) * sizeof(WCHAR));
  851. DhcpContextSize =
  852. ROUND_UP_COUNT(sizeof(DHCP_CONTEXT), ALIGN_WORST) +
  853. ROUND_UP_COUNT(HardwareAddressLength, ALIGN_WORST) +
  854. ROUND_UP_COUNT(sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST) +
  855. ROUND_UP_COUNT(AdapterNameLen, ALIGN_WORST) +
  856. ROUND_UP_COUNT(NetBTDeviceNameLen, ALIGN_WORST) +
  857. ROUND_UP_COUNT(RegKeyLen, ALIGN_WORST) +
  858. ROUND_UP_COUNT(DHCP_RECV_MESSAGE_SIZE, ALIGN_WORST);
  859. if ( pClientID->fSpecified ) {
  860. DhcpAssert( pClientID->cbID );
  861. DhcpContextSize += ROUND_UP_COUNT( pClientID->cbID, ALIGN_WORST );
  862. }
  863. Ptr = DhcpAllocateMemory( DhcpContextSize );
  864. if ( Ptr == NULL ) return ERROR_NOT_ENOUGH_MEMORY;
  865. RtlZeroMemory(Ptr, DhcpContextSize);
  866. DhcpContext = Ptr;
  867. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(DHCP_CONTEXT), ALIGN_WORST);
  868. DhcpContext->HardwareAddress = Ptr;
  869. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + HardwareAddressLength, ALIGN_WORST);
  870. if ( pClientID->fSpecified ) {
  871. DhcpContext->ClientIdentifier.pbID = Ptr;
  872. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + pClientID->cbID, ALIGN_WORST );
  873. }
  874. DhcpContext->LocalInformation = Ptr;
  875. LocalInfo = Ptr;
  876. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST);
  877. LocalInfo->AdapterName= Ptr;
  878. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + AdapterNameLen, ALIGN_WORST);
  879. LocalInfo->NetBTDeviceName= Ptr;
  880. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + NetBTDeviceNameLen, ALIGN_WORST);
  881. LocalInfo->RegistryKey= Ptr;
  882. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + RegKeyLen, ALIGN_WORST);
  883. DhcpContext->MessageBuffer = Ptr;
  884. //
  885. // Fill in the fields
  886. //
  887. DhcpContext->HardwareAddressType = HardwareAddressType;
  888. DhcpContext->HardwareAddressLength = HardwareAddressLength;
  889. RtlCopyMemory(DhcpContext->HardwareAddress, HardwareAddress,HardwareAddressLength);
  890. DhcpContext->ClientIdentifier.fSpecified = pClientID->fSpecified;
  891. if ( pClientID->fSpecified ) {
  892. DhcpContext->ClientIdentifier.bType = pClientID->bType;
  893. DhcpContext->ClientIdentifier.cbID = pClientID->cbID;
  894. RtlCopyMemory(DhcpContext->ClientIdentifier.pbID,pClientID->pbID,pClientID->cbID);
  895. }
  896. RtlCopyMemory(LocalInfo->AdapterName, AdapterName, AdapterNameLen);
  897. wcscpy( LocalInfo->NetBTDeviceName, DHCP_ADAPTERS_DEVICE_STRING );
  898. wcscat( LocalInfo->NetBTDeviceName, DHCP_NETBT_DEVICE_STRING );
  899. wcscat( LocalInfo->NetBTDeviceName, AdapterName );
  900. RtlCopyMemory(LocalInfo->RegistryKey, RegKey, RegKeyLen);
  901. if( ReturnDhcpContext != NULL ) *ReturnDhcpContext = DhcpContext;
  902. return( ERROR_SUCCESS );
  903. }
  904. BOOL
  905. ReadClientID(
  906. HKEY hKey,
  907. BYTE *pbClientIDType,
  908. DWORD *pcbClientID,
  909. BYTE *ppbClientID[]
  910. )
  911. /*++
  912. Function:
  913. ReadClientID
  914. Routine Description:
  915. Reads and validates the optional Client-Identifier option
  916. Arguments:
  917. hKey - handle to a registry key whose info will be retrieved.
  918. pbClientIDType - Recieves the client ID option type
  919. pcbClientID - Receives the size of the client id option
  920. ppbClientID - Receives a pointer to a buffer containing the
  921. client ID option
  922. Return Value:
  923. TRUE - A valid client ID was read from the registry
  924. FALSE - Client ID could not be read
  925. Comments:
  926. If ReadClientID returns false, pbClientIDType, pcbClientID and ppbClientID
  927. will be set to NULL.
  928. History
  929. 7/14/96 Frankbee Created
  930. --*/
  931. {
  932. DWORD dwResult,
  933. dwDataType,
  934. dwcb,
  935. dwClientIDType,
  936. dwClientID;
  937. BYTE *pbClientID;
  938. BOOL fClientIDSpecified = FALSE;
  939. //
  940. // read the client id and client id type, if present
  941. //
  942. dwcb = sizeof(dwClientIDType);
  943. dwResult = RegQueryValueEx(
  944. hKey,
  945. DHCP_CLIENT_IDENTIFIER_FORMAT,
  946. 0,
  947. &dwDataType,
  948. (LPBYTE)&dwClientIDType,
  949. &dwcb );
  950. if ( ERROR_SUCCESS != dwResult )
  951. {
  952. DhcpPrint( (DEBUG_MISC,
  953. "Client-Indentifier type not present in registry.\n" ));
  954. //
  955. // specify ID type 0 to indicate that the client ID is not a hardware
  956. // address
  957. //
  958. dwClientIDType = 0;
  959. }
  960. else
  961. {
  962. //
  963. // the client id type is present, make sure it is the correct
  964. // data type and within range
  965. //
  966. if ( DHCP_CLIENT_IDENTIFIER_FORMAT_TYPE != dwDataType || dwClientIDType > 0xFF )
  967. {
  968. DhcpPrint( (DEBUG_MISC,
  969. "Invalid Client-Indentifier type: %d\n", dwClientIDType ));
  970. goto done;
  971. }
  972. }
  973. //
  974. // Now try to read the client ID
  975. //
  976. // first try to read the size
  977. dwcb = 0;
  978. dwResult = RegQueryValueEx(
  979. hKey,
  980. DHCP_CLIENT_IDENTIFIER_VALUE,
  981. 0,
  982. 0, // don't care about the type
  983. NULL, // specify null buffer to obtain size
  984. &dwcb );
  985. // make the the value is present
  986. if ( ERROR_SUCCESS != dwResult || !dwcb )
  987. {
  988. DhcpPrint( (DEBUG_MISC,
  989. "Client-Identifier is not present or invalid.\n" ));
  990. goto done;
  991. }
  992. // allocate the buffer and read the value
  993. pbClientID = (BYTE*) DhcpAllocateMemory ( dwcb );
  994. if ( !pbClientID )
  995. {
  996. DhcpPrint( (DEBUG_ERRORS,
  997. "Unable to allocate memory for Client-Identifier "));
  998. goto done;
  999. }
  1000. dwResult = RegQueryValueEx(
  1001. hKey,
  1002. DHCP_CLIENT_IDENTIFIER_VALUE,
  1003. 0,
  1004. 0, // client id can be any type
  1005. pbClientID,
  1006. &dwcb );
  1007. if ( ERROR_SUCCESS != dwResult )
  1008. {
  1009. DhcpPrint( (DEBUG_ERRORS,
  1010. "Unable to read Client-Identifier from registry: %d\n", dwResult ));
  1011. DhcpFreeMemory( pbClientID );
  1012. goto done;
  1013. }
  1014. //
  1015. // we have a client id
  1016. //
  1017. fClientIDSpecified = TRUE;
  1018. done:
  1019. if ( fClientIDSpecified )
  1020. {
  1021. *pbClientIDType = (BYTE) dwClientIDType;
  1022. *pcbClientID = dwcb;
  1023. *ppbClientID = pbClientID;
  1024. }
  1025. else
  1026. {
  1027. *pbClientIDType = 0;
  1028. *pcbClientID = 0;
  1029. *ppbClientID = NULL;
  1030. }
  1031. if ( fClientIDSpecified )
  1032. {
  1033. int i;
  1034. //
  1035. // A valid client-identifier was obtained from the registry. dump out
  1036. // the contents
  1037. //
  1038. DhcpPrint( (DEBUG_MISC,
  1039. "A Client Identifier was obtained from the registry:\n" ));
  1040. DhcpPrint( (DEBUG_MISC,
  1041. "Client-Identifier Type == %#2x\n", (int) *pbClientIDType ));
  1042. DhcpPrint( (DEBUG_MISC,
  1043. "Client-Indentifier length == %d\n", (int) *pcbClientID ));
  1044. DhcpPrint( (DEBUG_MISC,
  1045. "Client-Identifier == " ));
  1046. for ( i = 0; i < (int) *pcbClientID; i++ )
  1047. DhcpPrint((DEBUG_MISC, "%#2x ", (int) ((*ppbClientID)[i]) ));
  1048. DhcpPrint( (DEBUG_MISC, "\n" ));
  1049. }
  1050. return fClientIDSpecified;
  1051. }
  1052. BOOL
  1053. GuidToClientID(
  1054. IN LPWSTR GuidString,
  1055. BYTE *pbClientIDType,
  1056. DWORD *pcbClientID,
  1057. BYTE *ppbClientID[]
  1058. )
  1059. {
  1060. GUID guid;
  1061. UNICODE_STRING unGuid;
  1062. BYTE *pbClientID;
  1063. RtlInitUnicodeString(&unGuid, GuidString);
  1064. if (RtlGUIDFromString(&unGuid, &guid) != STATUS_SUCCESS) {
  1065. return FALSE;
  1066. }
  1067. pbClientID = (BYTE*) DhcpAllocateMemory (sizeof(GUID));
  1068. if (pbClientID == NULL) {
  1069. return FALSE;
  1070. }
  1071. memcpy(pbClientID, &guid, sizeof(GUID));
  1072. *pbClientIDType = 0; // per RFC 2132, 0 should be used when the ID is not a hardware address
  1073. *pcbClientID = sizeof(GUID);
  1074. *ppbClientID = pbClientID;
  1075. return TRUE;
  1076. }
  1077. DWORD // status
  1078. DhcpRegExpandString( // replace '?' with AdapterName
  1079. IN LPWSTR InString, // input string to expand
  1080. IN LPCWSTR AdapterName, // the adapter name
  1081. OUT LPWSTR *OutString, // the output ptr to store string
  1082. IN OUT LPWSTR Buffer // the buffer to use if non NULL
  1083. ) {
  1084. LPWSTR Mem; // the real mem to use
  1085. LPWSTR Tmp, Tmp2, MemTmp;
  1086. DWORD MemSize; // the size of this memory
  1087. DWORD AdapterNameLen;// the amt of bytes for adapter name
  1088. *OutString = NULL;
  1089. AdapterNameLen = wcslen(AdapterName) * sizeof(WCHAR);
  1090. if( NULL != Buffer ) { // Buffer already provided
  1091. Mem = Buffer;
  1092. MemSize = 0;
  1093. } else { // need to allocate buffer
  1094. MemSize = wcslen(InString)+1; // calculate memory size needed
  1095. MemSize *= sizeof(WCHAR);
  1096. Tmp = InString;
  1097. while( Tmp = wcschr(Tmp, OPTION_REPLACE_CHAR ) ) {
  1098. Tmp ++;
  1099. MemSize += AdapterNameLen - sizeof(OPTION_REPLACE_CHAR);
  1100. }
  1101. Mem = DhcpAllocateMemory(MemSize); // allocate the buffer
  1102. if( NULL == Mem ) return ERROR_NOT_ENOUGH_MEMORY;
  1103. }
  1104. Tmp = InString; MemTmp = Mem;
  1105. while( Tmp2 = wcschr(Tmp, OPTION_REPLACE_CHAR) ) {
  1106. memcpy(MemTmp, Tmp, (int)(Tmp2 - Tmp) * sizeof(WCHAR) );
  1107. MemTmp += (Tmp2-Tmp);
  1108. memcpy(MemTmp, AdapterName, AdapterNameLen);
  1109. MemTmp += AdapterNameLen/sizeof(WCHAR);
  1110. Tmp = Tmp2+1;
  1111. }
  1112. wcscpy(MemTmp, Tmp);
  1113. *OutString = Mem;
  1114. return ERROR_SUCCESS;
  1115. }
  1116. DWORD // status
  1117. DhcpRegReadFromLocation( // read from one location
  1118. IN LPWSTR OneLocation, // value to read from
  1119. IN LPWSTR AdapterName, // replace '?' with adapternames
  1120. OUT LPBYTE *Value, // output value
  1121. OUT DWORD *ValueType, // data type of value
  1122. OUT DWORD *ValueSize // the size in bytes
  1123. ) {
  1124. DWORD Error;
  1125. LPWSTR NewRegLocation;
  1126. HKEY KeyHandle;
  1127. LPWSTR ValueName;
  1128. Error = DhcpRegExpandString( // replace all occurences of '?'
  1129. OneLocation,
  1130. AdapterName,
  1131. &NewRegLocation,
  1132. NULL
  1133. );
  1134. if( ERROR_SUCCESS != Error ) return Error;
  1135. ValueName = wcsrchr(NewRegLocation, REGISTRY_CONNECT);
  1136. if( NULL != ValueName ) *ValueName++ = L'\0'; // split to reg loc and value name
  1137. Error = RegOpenKeyEx( // open the required key
  1138. HKEY_LOCAL_MACHINE, // running in some process -- expect full path
  1139. NewRegLocation, // this is the new key
  1140. 0 /* Reserved */,
  1141. DHCP_CLIENT_KEY_ACCESS,
  1142. &KeyHandle
  1143. );
  1144. if( ERROR_SUCCESS != Error ) {
  1145. DhcpPrint((DEBUG_ERRORS, "RegOpenKeyEx(%ws):%ld\n", NewRegLocation, Error));
  1146. DhcpFreeMemory(NewRegLocation);
  1147. return Error;
  1148. }
  1149. *ValueSize = 0;
  1150. *Value = NULL;
  1151. Error = RegQueryValueEx( // first find out how much space reqd
  1152. KeyHandle,
  1153. ValueName,
  1154. 0 /* Reserved */,
  1155. ValueType,
  1156. NULL,
  1157. ValueSize
  1158. );
  1159. *Value = NULL;
  1160. if( ERROR_SUCCESS != Error || 0 == *ValueSize ) {
  1161. DhcpPrint((DEBUG_ERRORS, "RegQueryValueEx(%ws, %ws):%ld\n", NewRegLocation, ValueName, Error));
  1162. DhcpFreeMemory(NewRegLocation);
  1163. RegCloseKey(KeyHandle);
  1164. return Error;
  1165. }
  1166. if( NULL == (*Value = DhcpAllocateMemory(*ValueSize))) {
  1167. DhcpPrint((DEBUG_ERRORS, "RegReadFromLocation(%s):Allocate(%ld)failed\n", NewRegLocation, *ValueSize));
  1168. DhcpFreeMemory(NewRegLocation);
  1169. RegCloseKey(KeyHandle);
  1170. return ERROR_NOT_ENOUGH_MEMORY;
  1171. }
  1172. Error = RegQueryValueEx(
  1173. KeyHandle,
  1174. ValueName,
  1175. 0 /* Reserved */,
  1176. ValueType,
  1177. *Value,
  1178. ValueSize
  1179. );
  1180. DhcpFreeMemory(NewRegLocation);
  1181. RegCloseKey(KeyHandle);
  1182. return Error;
  1183. }
  1184. DWORD // status
  1185. DhcpRegReadFromAnyLocation( // read from one of many locations
  1186. IN LPWSTR MzRegLocation, // multiple locations thru REG_MULTI_MZ
  1187. IN LPWSTR AdapterName, // may have to replace '?' with AdapterName
  1188. OUT LPBYTE *Value, // data for the value read
  1189. OUT DWORD *ValueType, // type of the data
  1190. OUT DWORD *ValueSize // the size of data
  1191. ) {
  1192. DWORD StringSize;
  1193. DWORD Error;
  1194. if( NULL == Value || NULL == ValueType || NULL == ValueSize ) {
  1195. DhcpAssert( Value && ValueType && ValueSize && "DhcpRegReadFromAnyLocation" );
  1196. return ERROR_INVALID_PARAMETER;
  1197. }
  1198. while( StringSize = wcslen(MzRegLocation) ) { // read in sequence and see if anything hits
  1199. Error = DhcpRegReadFromLocation(
  1200. MzRegLocation,
  1201. AdapterName,
  1202. Value,
  1203. ValueType,
  1204. ValueSize
  1205. );
  1206. if( ERROR_SUCCESS == Error) return ERROR_SUCCESS;
  1207. MzRegLocation += StringSize + 1;
  1208. }
  1209. return ERROR_FILE_NOT_FOUND;
  1210. }
  1211. VOID
  1212. DhcpRegReadClassId( // Read the class id stuff
  1213. IN PDHCP_CONTEXT DhcpContext // Input context to read for
  1214. ) {
  1215. PLOCAL_CONTEXT_INFO LocalInfo;
  1216. LPWSTR AdapterName;
  1217. LPWSTR RegLocation;
  1218. LPWSTR ValueName;
  1219. LPBYTE Value;
  1220. DWORD ValueSize;
  1221. DWORD ValueType;
  1222. DWORD Error;
  1223. DhcpContext->ClassId = NULL;
  1224. DhcpContext->ClassIdLength = 0;
  1225. RegLocation = NULL;
  1226. LocalInfo = DhcpContext->LocalInformation;
  1227. AdapterName = LocalInfo->AdapterName;
  1228. Error = GetRegistryString(
  1229. DhcpGlobalParametersKey,
  1230. DHCP_CLASS_LOCATION_VALUE,
  1231. &RegLocation,
  1232. NULL
  1233. );
  1234. if( ERROR_SUCCESS != Error || NULL == RegLocation ) {
  1235. RegLocation = NULL;
  1236. }
  1237. Error = DhcpRegReadFromAnyLocation(
  1238. RegLocation?RegLocation:DEFAULT_USER_CLASS_LOC_FULL,
  1239. AdapterName,
  1240. &Value,
  1241. &ValueType,
  1242. &ValueSize
  1243. );
  1244. if( ERROR_SUCCESS != Error || NULL == Value ) {
  1245. Error = FixupDhcpClassId(AdapterName, TRUE);
  1246. if (ERROR_SUCCESS == Error) {
  1247. Error = DhcpRegReadFromAnyLocation(
  1248. RegLocation?RegLocation:DEFAULT_USER_CLASS_LOC_FULL,
  1249. AdapterName,
  1250. &Value,
  1251. &ValueType,
  1252. &ValueSize
  1253. );
  1254. }
  1255. }
  1256. if( NULL != RegLocation ) DhcpFreeMemory(RegLocation);
  1257. if( ERROR_SUCCESS != Error || NULL == Value ) return;
  1258. DhcpContext->ClassId = DhcpAddClass(&DhcpGlobalClassesList,Value, ValueSize);
  1259. if( NULL != DhcpContext->ClassId ) DhcpContext->ClassIdLength = ValueSize;
  1260. DhcpFreeMemory(Value);
  1261. }
  1262. DWORD INLINE // win32 status
  1263. DhcpMakeContext( // allocate and create a context
  1264. IN LPWSTR AdapterName, // name of adapter
  1265. IN DWORD IpInterfaceContext,
  1266. OUT PDHCP_CONTEXT *pDhcpContext // fill this with the ptr to allocated block
  1267. )
  1268. {
  1269. LPWSTR RegKey;
  1270. HKEY KeyHandle;
  1271. DHCP_CLIENT_IDENTIFIER ClientID;
  1272. BYTE HardwareAddressType;
  1273. LPBYTE HardwareAddress;
  1274. DWORD HardwareAddressLength;
  1275. DWORD Error, OldIpAddress, OldIpMask;
  1276. DWORD IpInterfaceInstance;
  1277. BOOL fInterfaceDown;
  1278. PLOCAL_CONTEXT_INFO LocalInfo;
  1279. DWORD IfIndex;
  1280. ClientID.pbID = NULL;
  1281. RegKey = NULL;
  1282. KeyHandle = NULL;
  1283. HardwareAddress = NULL;
  1284. RegKey = DhcpAllocateMemory(
  1285. sizeof(WCHAR) * (
  1286. wcslen(DHCP_SERVICES_KEY) + wcslen(REGISTRY_CONNECT_STRING) +
  1287. wcslen(AdapterName) + wcslen(DHCP_ADAPTER_PARAMETERS_KEY) + 1
  1288. )
  1289. );
  1290. if( RegKey == NULL ) return ERROR_NOT_ENOUGH_MEMORY;
  1291. wcscpy( RegKey, DHCP_SERVICES_KEY );
  1292. wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
  1293. wcscat( RegKey, REGISTRY_CONNECT_STRING );
  1294. wcscat( RegKey, AdapterName );
  1295. DhcpPrint((DEBUG_INIT, "Opening Adapter Key - %ws.\n", RegKey));
  1296. Error = RegOpenKeyEx(
  1297. HKEY_LOCAL_MACHINE,
  1298. RegKey,
  1299. 0, // Reserved field
  1300. DHCP_CLIENT_KEY_ACCESS,
  1301. &KeyHandle
  1302. );
  1303. if( ERROR_SUCCESS != Error ) {
  1304. DhcpPrint((DEBUG_ERRORS, "RegOpenKeyEx(%ws):0x%lx\n", AdapterName, Error));
  1305. DhcpFreeMemory(RegKey);
  1306. return Error;
  1307. }
  1308. ClientID.fSpecified = ReadClientID(
  1309. KeyHandle,
  1310. &ClientID.bType,
  1311. &ClientID.cbID,
  1312. &ClientID.pbID
  1313. );
  1314. #ifdef BOOTPERF
  1315. Error = DhcpQueryHWInfoEx( // query the stack for hw info
  1316. IpInterfaceContext,
  1317. &IpInterfaceInstance,
  1318. &OldIpAddress,
  1319. &OldIpMask,
  1320. &fInterfaceDown,
  1321. &HardwareAddressType,
  1322. &HardwareAddress,
  1323. &HardwareAddressLength
  1324. );
  1325. #else
  1326. Error = DhcpQueryHWInfo( // query the stack for hw info
  1327. IpInterfaceContext,
  1328. &IpInterfaceInstance,
  1329. &HardwareAddressType,
  1330. &HardwareAddress,
  1331. &HardwareAddressLength
  1332. );
  1333. #endif BOOTPERF
  1334. if (HardwareAddressType == HARDWARE_1394 && !ClientID.fSpecified) {
  1335. //
  1336. // Generate a client identifier for 1394 interface
  1337. //
  1338. ClientID.fSpecified = GuidToClientID(
  1339. AdapterName,
  1340. &ClientID.bType,
  1341. &ClientID.cbID,
  1342. &ClientID.pbID
  1343. );
  1344. if (!ClientID.fSpecified) {
  1345. Error = ERROR_BAD_DEVICE;
  1346. }
  1347. }
  1348. if( ERROR_SUCCESS == Error ) { // now do the real allocate part and get the context
  1349. IfIndex = QueryIfIndex(IpInterfaceContext, IpInterfaceInstance);
  1350. Error = DhcpMakeNICEntry(
  1351. pDhcpContext,
  1352. HardwareAddressType,
  1353. HardwareAddress,
  1354. HardwareAddressLength,
  1355. &ClientID,
  1356. AdapterName,
  1357. RegKey
  1358. );
  1359. if( ERROR_SUCCESS == Error ) { // if everything went fine, store the KeyHandle
  1360. ULONG Caps;
  1361. DhcpAssert((*pDhcpContext));
  1362. (*pDhcpContext)->AdapterInfoKey = KeyHandle;
  1363. (*pDhcpContext)->RefCount = 1;
  1364. KeyHandle = NULL; // null it so that it does not get closed below
  1365. LocalInfo = (PLOCAL_CONTEXT_INFO)((*pDhcpContext)->LocalInformation);
  1366. LocalInfo->IpInterfaceContext = IpInterfaceContext;
  1367. LocalInfo->IpInterfaceInstance = IpInterfaceInstance;
  1368. LocalInfo->IfIndex = IfIndex;
  1369. // IpInterfaceInstance is filled in make context
  1370. LocalInfo->Socket = INVALID_SOCKET;
  1371. // LocalInfo->AdapterName, RegistryKey, NetBtDeviceName ALREADY set in MakeNICEntry
  1372. #ifdef BOOTPERF
  1373. LocalInfo->OldIpAddress = OldIpAddress;
  1374. LocalInfo->OldIpMask = OldIpMask;
  1375. LocalInfo->fInterfaceDown = fInterfaceDown;
  1376. #endif BOOTPERF
  1377. (*pDhcpContext)->fTimersEnabled = FALSE;
  1378. Error = IPGetWOLCapability(DhcpIpGetIfIndex(*pDhcpContext),&Caps);
  1379. if( NO_ERROR == Error ) {
  1380. if( Caps & NDIS_DEVICE_WAKE_UP_ENABLE ) {
  1381. (*pDhcpContext)->fTimersEnabled = TRUE;
  1382. }
  1383. }
  1384. Error = NO_ERROR;
  1385. }
  1386. } else {
  1387. DhcpPrint((DEBUG_ERRORS, "QueryHwInfo(0x%lx)=0x%lx\n", IpInterfaceContext, Error));
  1388. }
  1389. if( KeyHandle ) RegCloseKey(KeyHandle);
  1390. if( ClientID.pbID ) DhcpFreeMemory(ClientID.pbID);
  1391. if( RegKey ) DhcpFreeMemory(RegKey);
  1392. if( HardwareAddress ) DhcpFreeMemory(HardwareAddress);
  1393. if (Error == NO_ERROR) {
  1394. (*pDhcpContext)->State.UniDirectional = (IsUnidirectionalAdapter(IpInterfaceContext))? 1: 0;
  1395. }
  1396. return Error;
  1397. }
  1398. DWORD // win32 status
  1399. DhcpRegFillParams( // re-read all the parameters for this adapter?
  1400. IN OUT PDHCP_CONTEXT DhcpContext, // read for this context
  1401. IN BOOL ReadAllInfo // read all information or just config stuff?
  1402. )
  1403. {
  1404. // currently ReadAllInfo parameter is ignored
  1405. HKEY KeyHandle;
  1406. DWORD Error;
  1407. DWORD DwordValue;
  1408. DWORD ValueType;
  1409. DWORD ValueSize;
  1410. DWORD AddressType;
  1411. DWORD i;
  1412. DWORD EnableDhcp;
  1413. DWORD dwIPAutoconfigurationEnabled;
  1414. DWORD DontPingGatewayFlag;
  1415. DWORD UseInformFlag;
  1416. DWORD InformSeparationInterval;
  1417. DWORD DwordValuesCount;
  1418. DWORD IpAddrValuesCount;
  1419. DWORD ReleaseOnShutdown;
  1420. DWORD fQuickBootEnabled;
  1421. DHCP_IP_ADDRESS Address;
  1422. DHCP_IP_ADDRESS IpAddress;
  1423. DHCP_IP_ADDRESS SubnetMask;
  1424. DHCP_IP_ADDRESS DhcpServerAddress;
  1425. DHCP_IP_ADDRESS DesiredIpAddress;
  1426. DWORD Lease;
  1427. LONG LeaseObtainedTime;
  1428. LONG T1Time;
  1429. LONG T2Time;
  1430. LONG LeaseTerminatedTime;
  1431. LPWSTR AdapterName;
  1432. LPWSTR ValueName;
  1433. LPWSTR IpAddressString;
  1434. CHAR IpAddressStringBuffer[DOT_IP_ADDR_SIZE];
  1435. DHCP_IPAUTOCONFIGURATION_CONTEXT IPAutoconfigContext;
  1436. struct /* anonymous */ {
  1437. LPDWORD Value;
  1438. LPWSTR ValueName;
  1439. } DwordValuesList[] = {
  1440. &EnableDhcp, DHCP_ENABLE_STRING,
  1441. &Lease, DHCP_LEASE,
  1442. &LeaseObtainedTime, DHCP_LEASE_OBTAINED_TIME,
  1443. &T1Time, DHCP_LEASE_T1_TIME,
  1444. &T2Time, DHCP_LEASE_T2_TIME,
  1445. &LeaseTerminatedTime, DHCP_LEASE_TERMINATED_TIME,
  1446. &dwIPAutoconfigurationEnabled, DHCP_IPAUTOCONFIGURATION_ENABLED,
  1447. &IPAutoconfigContext.Seed, DHCP_IPAUTOCONFIGURATION_SEED,
  1448. &AddressType, DHCP_ADDRESS_TYPE_VALUE,
  1449. &DontPingGatewayFlag, DHCP_DONT_PING_GATEWAY_FLAG,
  1450. &UseInformFlag, DHCP_USE_INFORM_FLAG,
  1451. #ifdef BOOTPERF
  1452. &fQuickBootEnabled, DHCP_QUICK_BOOT_FLAG,
  1453. #endif BOOTPERF
  1454. &InformSeparationInterval, DHCP_INFORM_SEPARATION_INTERVAL,
  1455. &ReleaseOnShutdown, DHCP_RELEASE_ON_SHUTDOWN_VALUE
  1456. };
  1457. struct /* anonymous */ {
  1458. LPDHCP_IP_ADDRESS Address;
  1459. LPWSTR ValueName;
  1460. } IpAddressValuesList[] = {
  1461. // The first element *HAS* to be Ip address -- see the function for why
  1462. &IpAddress, DHCP_IP_ADDRESS_STRING,
  1463. &SubnetMask, DHCP_SUBNET_MASK_STRING,
  1464. &DhcpServerAddress, DHCP_SERVER,
  1465. &IPAutoconfigContext.Address, DHCP_IPAUTOCONFIGURATION_ADDRESS,
  1466. &IPAutoconfigContext.Subnet, DHCP_IPAUTOCONFIGURATION_SUBNET,
  1467. &IPAutoconfigContext.Mask, DHCP_IPAUTOCONFIGURATION_MASK,
  1468. };
  1469. //
  1470. // Initialize locals
  1471. //
  1472. KeyHandle = DhcpContext->AdapterInfoKey;
  1473. EnableDhcp = FALSE;
  1474. Lease = 0;
  1475. LeaseObtainedTime = 0;
  1476. T1Time = 0;
  1477. T2Time = 0;
  1478. LeaseTerminatedTime = 0;
  1479. dwIPAutoconfigurationEnabled = (DhcpGlobalAutonetEnabled?TRUE:FALSE);
  1480. AddressType = ADDRESS_TYPE_DHCP;
  1481. DontPingGatewayFlag = DhcpGlobalDontPingGatewayFlag;
  1482. UseInformFlag = DhcpGlobalUseInformFlag;
  1483. #ifdef BOOTPERF
  1484. fQuickBootEnabled = DhcpGlobalQuickBootEnabledFlag;
  1485. #endif BOOTPERF
  1486. IpAddress = 0;
  1487. SubnetMask = 0;
  1488. DhcpServerAddress = 0;
  1489. IPAutoconfigContext.Address = 0;
  1490. IPAutoconfigContext.Subnet = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET);
  1491. IPAutoconfigContext.Mask = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK);
  1492. IPAutoconfigContext.Seed = 0;
  1493. InformSeparationInterval = DHCP_DEFAULT_INFORM_SEPARATION_INTERVAL;
  1494. ReleaseOnShutdown = DEFAULT_RELEASE_ON_SHUTDOWN;
  1495. AdapterName = ((PLOCAL_CONTEXT_INFO)(DhcpContext->LocalInformation))->AdapterName;
  1496. DwordValuesCount = sizeof(DwordValuesList)/sizeof(DwordValuesList[0]);
  1497. IpAddrValuesCount = sizeof(IpAddressValuesList)/sizeof(IpAddressValuesList[0]);
  1498. for( i = 0; i < DwordValuesCount ; i ++ ) {
  1499. ValueSize = sizeof(DWORD);
  1500. ValueName = DwordValuesList[i].ValueName;
  1501. Error = RegQueryValueEx(
  1502. KeyHandle,
  1503. ValueName,
  1504. 0 /* Reserved */,
  1505. &ValueType,
  1506. (LPBYTE)&DwordValue,
  1507. &ValueSize
  1508. );
  1509. if( ERROR_SUCCESS != Error ) {
  1510. DhcpPrint((DEBUG_ERRORS, "RegValue %ws is not found? Error: %ld. Defaults used\n", ValueName, Error));
  1511. continue;
  1512. }
  1513. if( REG_DWORD != ValueType ) {
  1514. DhcpPrint((DEBUG_ERRORS, "RegValue %ws is not a DWORD. Defaults used\n", ValueName));
  1515. continue;
  1516. }
  1517. DhcpAssert( sizeof(DWORD) == ValueSize);
  1518. *DwordValuesList[i].Value = DwordValue;
  1519. DhcpPrint((DEBUG_TRACE, "RegValue %ws is [%ld]\n", ValueName, DwordValue));
  1520. }
  1521. if (IS_UNIDIRECTIONAL(DhcpContext)) {
  1522. DhcpPrint((DEBUG_MEDIA, "Detect Unidirectional Adapter: %ws\n", AdapterName));
  1523. EnableDhcp = FALSE;
  1524. dwIPAutoconfigurationEnabled = FALSE;
  1525. }
  1526. //For this to work correctly, the first element of array has to be the IPADDRESS
  1527. // RAS folks still use the DhcpIpAddress value in the registry, so dont change for them
  1528. if( !EnableDhcp && !NdisWanAdapter(DhcpContext) )
  1529. IpAddressValuesList[0].ValueName = DHCP_IPADDRESS_VALUE;
  1530. for( i = 0; i < IpAddrValuesCount ; i ++ ) {
  1531. ValueName = IpAddressValuesList[i].ValueName;
  1532. IpAddressString = NULL;
  1533. Error = GetRegistryString(
  1534. KeyHandle,
  1535. ValueName,
  1536. &IpAddressString,
  1537. NULL
  1538. );
  1539. if( ERROR_SUCCESS != Error ) {
  1540. DhcpPrint((DEBUG_ERRORS, "RegValue %ws : %ld -- Default used\n", ValueName, Error));
  1541. if( IpAddressString ) DhcpFreeMemory(IpAddressString);
  1542. continue;
  1543. }
  1544. if( wcslen(IpAddressString) >= DOT_IP_ADDR_SIZE ) {
  1545. // either the format is wrong or this is a ' ' separated string?
  1546. DhcpPrint((DEBUG_ERRORS, "String <%ws> is too long, will try to take first address\n", IpAddressString));
  1547. if( wcschr(IpAddressString, L' ') )
  1548. *wcschr(IpAddressString, L' ') = L'\0' ;
  1549. if( wcschr(IpAddressString, L',') )
  1550. *wcschr(IpAddressString, L',') = L'\0' ;
  1551. if( wcslen(IpAddressString) >= DOT_IP_ADDR_SIZE ) {
  1552. DhcpPrint((DEBUG_ERRORS, "Unable to split string <%ws> to DOT_IP_ADDR_SIZE -- ignoring string\n", IpAddressString));
  1553. if( IpAddressString ) DhcpFreeMemory(IpAddressString);
  1554. continue;
  1555. }
  1556. }
  1557. Address = inet_addr(DhcpUnicodeToOem(IpAddressString, IpAddressStringBuffer));
  1558. *IpAddressValuesList[i].Address = Address;
  1559. if( IpAddressString ) DhcpFreeMemory(IpAddressString);
  1560. DhcpPrint((DEBUG_TRACE, "RegValue %ws is ip-address %s\n", ValueName,
  1561. inet_ntoa(*(struct in_addr *)&Address)));
  1562. }
  1563. if( IpAddress == 0 ) DhcpServerAddress = 0;
  1564. //
  1565. // Sanity check read parameters
  1566. //
  1567. if( 0 == IPAutoconfigContext.Mask ) {
  1568. IPAutoconfigContext.Mask = inet_addr( DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK);
  1569. IPAutoconfigContext.Subnet = inet_addr( DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET);
  1570. }
  1571. if( (IPAutoconfigContext.Subnet & IPAutoconfigContext.Mask) != IPAutoconfigContext.Subnet) {
  1572. DhcpPrint((DEBUG_ERRORS, "Illegal (auto) Subnet address or mask\n"));
  1573. IPAutoconfigContext.Mask = inet_addr( DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK);
  1574. IPAutoconfigContext.Subnet = inet_addr( DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET);
  1575. }
  1576. if( 0 != IPAutoconfigContext.Address &&
  1577. (IPAutoconfigContext.Address & IPAutoconfigContext.Mask) != IPAutoconfigContext.Subnet) {
  1578. DhcpPrint((DEBUG_ERRORS, "Illegal (auto) IP address: %s\n",
  1579. inet_ntoa(*(struct in_addr *)&IPAutoconfigContext.Address)));
  1580. // cant use the specified address.. really.
  1581. IPAutoconfigContext.Address = 0;
  1582. }
  1583. DesiredIpAddress = IpAddress;
  1584. if( EnableDhcp && (time( NULL ) > LeaseTerminatedTime) || 0 == IpAddress ) {
  1585. IpAddress = 0;
  1586. SubnetMask = htonl(DhcpDefaultSubnetMask( IpAddress ));
  1587. Lease = 0;
  1588. LeaseObtainedTime = T1Time = T2Time = LeaseTerminatedTime = 0;
  1589. }
  1590. //
  1591. // fill in the fields of the context
  1592. //
  1593. // DhcpContext->NicListEntry will be done at the end
  1594. // DhcpContext->Haredware* already done in MakeNICEntry
  1595. DhcpContext->IpAddress = IpAddress;
  1596. DhcpContext->SubnetMask = SubnetMask;
  1597. DhcpContext->DhcpServerAddress = DhcpServerAddress;
  1598. if( ReadAllInfo ) DhcpContext->DesiredIpAddress = DesiredIpAddress;
  1599. DhcpContext->IPAutoconfigurationContext = IPAutoconfigContext;
  1600. // ClientID is filled in in MakeNICEntry
  1601. if( ReadAllInfo ) {
  1602. DhcpContext->Lease = Lease;
  1603. DhcpContext->LeaseObtained = LeaseObtainedTime;
  1604. DhcpContext->T1Time = T1Time;
  1605. DhcpContext->T2Time = T2Time;
  1606. DhcpContext->LeaseExpires = LeaseTerminatedTime;
  1607. }
  1608. // renewal list entry, run time, seconds since boot, renewal function
  1609. // send list, recd list, option cache, renew handle, class id
  1610. // --- all the above are handled elsewhere
  1611. DhcpContext->DontPingGatewayFlag = (DontPingGatewayFlag)?TRUE:FALSE;
  1612. DhcpContext->UseInformFlag = (UseInformFlag)?TRUE:FALSE;
  1613. DhcpContext->InformSeparationInterval = InformSeparationInterval;
  1614. DhcpContext->ReleaseOnShutdown = ReleaseOnShutdown;
  1615. #ifdef BOOTPERF
  1616. DhcpContext->fQuickBootEnabled = (fQuickBootEnabled ? TRUE : FALSE);
  1617. #endif BOOTPERF
  1618. // AdapterInfoKey is set in MakeContext
  1619. // RenewHandle is set in AddNICtoListEx
  1620. // DhcpContext->MessageBuffer set in MakeNICEntry
  1621. if( dwIPAutoconfigurationEnabled ) AUTONET_ENABLED(DhcpContext); else AUTONET_DISABLED(DhcpContext);
  1622. if( ReadAllInfo ) {
  1623. // DhcpContext->MessageBuffer set in MakeNICEntry
  1624. if( EnableDhcp ) ADDRESS_UNPLUMBED(DhcpContext); else ADDRESS_PLUMBED(DhcpContext);
  1625. SERVER_UNREACHED(DhcpContext);
  1626. if( dwIPAutoconfigurationEnabled ) AUTONET_ENABLED(DhcpContext); else AUTONET_DISABLED(DhcpContext);
  1627. CTXT_WAS_NOT_LOOKED(DhcpContext);
  1628. if( EnableDhcp ) DHCP_ENABLED(DhcpContext); else DHCP_DISABLED(DhcpContext);
  1629. if( ADDRESS_TYPE_AUTO != AddressType ) ACQUIRED_DHCP_ADDRESS(DhcpContext); else ACQUIRED_AUTO_ADDRESS(DhcpContext);
  1630. if( IS_ADDRESS_AUTO(DhcpContext) ) {
  1631. DhcpContext->IpAddress = 0; // this is useless if it is an autonet address
  1632. }
  1633. MEDIA_CONNECTED(DhcpContext);
  1634. // local info is setup in make context
  1635. }
  1636. return ERROR_SUCCESS;
  1637. }
  1638. DWORD // win32 status
  1639. DhcpRegFillFallbackConfig( // get the fallback config for this adapter
  1640. IN OUT PDHCP_CONTEXT DhcpContext // adapter context to fill in
  1641. )
  1642. {
  1643. DWORD Error; // returned error code
  1644. HKEY KeyHandle; // registry key to the configurations location
  1645. LPWSTR FbConfigName = NULL; // fallback configuration name
  1646. DWORD FbConfigNameLen; // length of the fallback configuration name
  1647. DWORD FbConfigNameType; // reg type of the configuration name
  1648. // start assuming there is no fallback configuration set
  1649. FALLBACK_DISABLED(DhcpContext);
  1650. // get the list of active configurations for this adapter.
  1651. // For now we expect (and handle) only one, the fallback config.
  1652. // For the future, the MULTI_SZ might contain several config names
  1653. // that will be involved in autodetection.
  1654. // query the registry for the configuration's name size
  1655. // [HKLM\SYSTEM\CCS\Services\Tcpip\Parameters\Interfaces\{Intf_GUID}]
  1656. // ActiveConfigurations = (REG_MULTI_SZ)
  1657. Error = RegQueryValueEx(
  1658. DhcpContext->AdapterInfoKey,
  1659. DHCP_IPAUTOCONFIGURATION_CFG,
  1660. NULL,
  1661. &FbConfigNameType,
  1662. NULL,
  1663. &FbConfigNameLen);
  1664. // if something went wrong or the value has not the
  1665. // expected type, break out with an error
  1666. if (Error != ERROR_SUCCESS ||
  1667. FbConfigNameType != DHCP_IPAUTOCONFIGURATION_CFG_TYPE)
  1668. {
  1669. // if no error was signaled it means we found a key but
  1670. // its type is different from the one expected. Convert
  1671. // the success to an ERROR_BAD_FORMAT failure
  1672. if (Error == ERROR_SUCCESS)
  1673. Error = ERROR_BAD_FORMAT;
  1674. // if we didn't find the pointer to the fallback config,
  1675. // it means we don't have one, hence is pure autonet.
  1676. // this is not a failure so return success
  1677. if (Error == ERROR_FILE_NOT_FOUND)
  1678. Error = ERROR_SUCCESS;
  1679. return Error;
  1680. }
  1681. // allocate space for the registry path where the configuration is stored.
  1682. // [HKLM\SYSTEM\CCS\Services\Dhcp\Configurations\{configuration_name}]
  1683. FbConfigName = DhcpAllocateMemory(
  1684. sizeof(DHCP_CLIENT_CONFIGURATIONS_KEY) +
  1685. sizeof(REGISTRY_CONNECT_STRING) +
  1686. FbConfigNameLen);
  1687. // if allocation failed, break out with error.
  1688. if (FbConfigName == NULL)
  1689. return ERROR_NOT_ENOUGH_MEMORY;
  1690. // build up the prefix of the path: "SYSTEM\CCS\Services\Dhcp\Configurations\"
  1691. wcscpy(FbConfigName, DHCP_CLIENT_CONFIGURATIONS_KEY REGISTRY_CONNECT_STRING);
  1692. // now, since we know what to expect and we have the storage
  1693. // for it, get the config name from the same location as above
  1694. Error = RegQueryValueEx(
  1695. DhcpContext->AdapterInfoKey,
  1696. DHCP_IPAUTOCONFIGURATION_CFG,
  1697. NULL,
  1698. &FbConfigNameType,
  1699. (LPBYTE)(FbConfigName + wcslen(FbConfigName)),
  1700. &FbConfigNameLen);
  1701. // the registry call above is expected to succeed and data
  1702. // to have the right type - we tested this before.
  1703. DhcpAssert(Error == ERROR_SUCCESS &&
  1704. FbConfigNameType == DHCP_IPAUTOCONFIGURATION_CFG_TYPE);
  1705. // open the registry key for this configuration
  1706. // [HKLM\SYSTEM\CCS\Services\Dhcp\Configurations\{Config_Name}]
  1707. Error = RegOpenKey(
  1708. HKEY_LOCAL_MACHINE,
  1709. FbConfigName,
  1710. &KeyHandle);
  1711. // in case of success...
  1712. if (Error == ERROR_SUCCESS)
  1713. {
  1714. // ...build up the FbOptionsList from that registry location
  1715. // from the "Options" value (REG_BINARY)
  1716. Error = DhcpRegReadOptionCache(
  1717. &DhcpContext->FbOptionsList,
  1718. KeyHandle,
  1719. DHCP_IPAUTOCONFIGURATION_CFGOPT,
  1720. TRUE // Add DhcpGlobalClassesList
  1721. );
  1722. if (Error == ERROR_SUCCESS)
  1723. {
  1724. // At this point we know for sure a fallback configuration
  1725. // is available. Set its flag accordingly
  1726. FALLBACK_ENABLED(DhcpContext);
  1727. }
  1728. // regardless success or failure, cleanup.
  1729. RegCloseKey(KeyHandle);
  1730. }
  1731. // free up the memory previously allocated
  1732. DhcpFreeMemory(FbConfigName);
  1733. // return the error code
  1734. return Error;
  1735. }
  1736. DWORD // win32 status
  1737. DhcpAddNICtoListEx( // create a context and add it to renew list
  1738. IN LPWSTR AdapterName, // adapter to create context for
  1739. IN DWORD IpInterfaceContext,
  1740. OUT PDHCP_CONTEXT *pDhcpContext // allocate a structure and fill this ptr
  1741. ) {
  1742. DWORD Error;
  1743. HANDLE RenewHandle;
  1744. PDHCP_CONTEXT DhcpContext;
  1745. CHAR StateStringBuffer[200];
  1746. PLOCAL_CONTEXT_INFO LocalInfo;
  1747. RenewHandle = CreateSemaphore(
  1748. NULL, // No security
  1749. 1, // count = 1
  1750. 1, // MaxCount = 1
  1751. NULL // No name
  1752. );
  1753. if( NULL == RenewHandle ) {
  1754. Error = GetLastError();
  1755. DhcpPrint((DEBUG_ERRORS, "CreateSemaphore: %ld\n", Error));
  1756. return Error;
  1757. }
  1758. (*pDhcpContext) = NULL;
  1759. Error = DhcpMakeContext(AdapterName, IpInterfaceContext, pDhcpContext);
  1760. if( Error != ERROR_SUCCESS ) {
  1761. CloseHandle(RenewHandle);
  1762. return Error;
  1763. }
  1764. DhcpContext = (*pDhcpContext); // initialize some simple params
  1765. DhcpContext->RenewHandle = RenewHandle;
  1766. DhcpContext->NumberOfWaitingThreads = 0;
  1767. DhcpContext->CancelEvent = WSACreateEvent();
  1768. if (DhcpContext->CancelEvent == WSA_INVALID_EVENT) {
  1769. DhcpPrint((DEBUG_ERRORS, "WSAEvent 0x%lx could not be created: 0x%lx.\n",
  1770. DhcpContext->CancelEvent,
  1771. WSAGetLastError()));
  1772. }
  1773. DhcpContext->RunTime = 0;
  1774. DhcpContext->SecondsSinceBoot = 0;
  1775. DhcpContext->RenewalFunction = NULL;
  1776. InitializeListHead(&DhcpContext->RenewalListEntry);
  1777. InitializeListHead(&DhcpContext->SendOptionsList);
  1778. InitializeListHead(&DhcpContext->RecdOptionsList);
  1779. InitializeListHead(&DhcpContext->FbOptionsList);
  1780. Error = DhcpRegFillParams( // read all the registry parameters
  1781. DhcpContext,
  1782. TRUE // and yes, fill em up in the context
  1783. );
  1784. // read the fallback configuration (if any)
  1785. Error = DhcpRegFillFallbackConfig(
  1786. DhcpContext
  1787. );
  1788. DhcpPrint((DEBUG_TRACK,"Fallback: Loading returned %d.\n", Error));
  1789. #ifdef BOOTPERF
  1790. LocalInfo = (PLOCAL_CONTEXT_INFO)DhcpContext->LocalInformation;
  1791. if( IS_DHCP_DISABLED(DhcpContext) ) {
  1792. //
  1793. // Don't care about interface down info.
  1794. //
  1795. LocalInfo->fInterfaceDown = 0;
  1796. LocalInfo->OldIpAddress = 0;
  1797. LocalInfo->OldIpMask = 0;
  1798. } else {
  1799. //
  1800. // For DHCP enabled interfaces, if the interface is down,
  1801. // then bring it up with zero ip address. The protocol will
  1802. // take care of using the right IP address later on.
  1803. //
  1804. if( LocalInfo->fInterfaceDown ) {
  1805. DhcpPrint((DEBUG_ERRORS, "Interface already down\n"));
  1806. LocalInfo->OldIpAddress = 0;
  1807. LocalInfo->OldIpMask = 0;
  1808. LocalInfo->fInterfaceDown = 0;
  1809. IPResetIPAddress(
  1810. LocalInfo->IpInterfaceContext,
  1811. DhcpDefaultSubnetMask(0)
  1812. );
  1813. Error = BringUpInterface(LocalInfo);
  1814. if( ERROR_SUCCESS != Error ) {
  1815. DhcpPrint((DEBUG_ERRORS, "Interface can't be brought up: 0x%lx\n", Error));
  1816. }
  1817. }
  1818. }
  1819. #endif BOOTPERF
  1820. LOCK_OPTIONS_LIST();
  1821. DhcpRegReadClassId(DhcpContext); // fill in the class id first
  1822. Error = DhcpRegFillSendOptions( // figure the default list of options to send
  1823. &DhcpContext->SendOptionsList,
  1824. AdapterName,
  1825. DhcpContext->ClassId,
  1826. DhcpContext->ClassIdLength
  1827. );
  1828. if( ERROR_SUCCESS != Error ) {
  1829. DhcpPrint((DEBUG_ERRORS, "DhcpRegFillSendOptions(%ws):%ld\n", Error));
  1830. }
  1831. if( IS_DHCP_ENABLED( DhcpContext ) ) {
  1832. // read in the list of options we had before?
  1833. Error = DhcpRegReadOptionCache(
  1834. &DhcpContext->RecdOptionsList,
  1835. DhcpGlobalParametersKey,
  1836. AdapterName,
  1837. TRUE // Add DhcpGlobalClassesList
  1838. );
  1839. if( ERROR_SUCCESS != Error ) {
  1840. DhcpPrint((DEBUG_ERRORS, "DhcpRegReadOptionCache(%ws): %ld\n", AdapterName, Error));
  1841. }
  1842. } else {
  1843. //
  1844. // ignore any option cache for static addresses because
  1845. // of bug # 413319. Instead for non-ndiswan stuff, clear
  1846. // the option cache.
  1847. //
  1848. if( !NdisWanAdapter(DhcpContext) ) {
  1849. DhcpRegSaveOptions(
  1850. &DhcpContext->RecdOptionsList, AdapterName,
  1851. DhcpContext->ClassId, DhcpContext->ClassIdLength
  1852. );
  1853. }
  1854. }
  1855. UNLOCK_OPTIONS_LIST();
  1856. if (NdisWanAdapter(DhcpContext))
  1857. InterlockedIncrement(&DhcpGlobalNdisWanAdaptersCount);
  1858. LOCK_RENEW_LIST(); // insert this into the renew list
  1859. InsertTailList( &DhcpGlobalNICList, &DhcpContext->NicListEntry );
  1860. UNLOCK_RENEW_LIST();
  1861. DhcpPrint((DEBUG_INIT, "DhcpMakeAndInsertNICEntryEx: DhcpContext %lx, Flags %s\n",
  1862. DhcpContext, ConvertStateToString(DhcpContext, StateStringBuffer)));
  1863. return ERROR_SUCCESS;
  1864. }
  1865. #ifdef BOOTPERF
  1866. VOID
  1867. DhcpRegDeleteQuickBootValues(
  1868. IN HKEY Key
  1869. )
  1870. /*++
  1871. Routine Description:
  1872. This routine deletes the values used for quickboot.
  1873. (If the values are not presentt they are ignored).
  1874. The values deleted are:
  1875. "TempIpAddress", "TempMask" and "TempLeaseExpirationTime"
  1876. Arguments:
  1877. Key -- key under which these values are deleted.
  1878. --*/
  1879. {
  1880. //
  1881. // ignore errors and silently delete values..
  1882. //
  1883. (void) RegDeleteValue(Key, DHCP_TEMP_IPADDRESS_VALUE );
  1884. (void) RegDeleteValue(Key, DHCP_TEMP_MASK_VALUE );
  1885. (void) RegDeleteValue(Key, DHCP_TEMP_LEASE_EXP_TIME_VALUE );
  1886. }
  1887. VOID
  1888. DhcpRegSaveQuickBootValues(
  1889. IN HKEY Key,
  1890. IN ULONG IpAddress,
  1891. IN ULONG Mask,
  1892. IN ULONGLONG LeaseExpirationTime
  1893. )
  1894. /*++
  1895. Routine Description:
  1896. This routine saves the values needed to the registry.
  1897. Values saved are:
  1898. "TempIpAddress", "TempMask", "TempLeaseExpirationTime"
  1899. Arguments:
  1900. Key -- key to save under
  1901. IpAddress -- non-zero Ip address value
  1902. Mask -- non-zero mask value
  1903. LeaseExpirationTime -- lease expiration value.
  1904. --*/
  1905. {
  1906. ULONG Error;
  1907. if( NULL == Key ) return;
  1908. DhcpAssert( 0 != IpAddress || 0 != Mask );
  1909. Error = RegSetIpAddress(
  1910. Key, DHCP_TEMP_IPADDRESS_VALUE, REG_SZ, IpAddress
  1911. );
  1912. DhcpAssert( ERROR_SUCCESS == Error );
  1913. Error = RegSetIpAddress(
  1914. Key, DHCP_TEMP_MASK_VALUE, REG_SZ, Mask
  1915. );
  1916. DhcpAssert( ERROR_SUCCESS == Error );
  1917. Error = RegSetValueEx(
  1918. Key,
  1919. DHCP_TEMP_LEASE_EXP_TIME_VALUE,
  1920. 0 /* Reserved */,
  1921. REG_BINARY,
  1922. (PVOID)&LeaseExpirationTime,
  1923. sizeof(LeaseExpirationTime)
  1924. );
  1925. DhcpAssert(ERROR_SUCCESS == Error);
  1926. }
  1927. #endif BOOTPERF
  1928. DHCP_IP_ADDRESS // the static ip address of the adapter
  1929. DhcpRegReadIpAddress( // get the first ip address
  1930. LPWSTR AdapterName, // the adaptor of interest
  1931. LPWSTR ValueName // the ip address value to read
  1932. ) {
  1933. DWORD Error;
  1934. LPWSTR RegKey;
  1935. HKEY KeyHandle;
  1936. DWORD ValueType;
  1937. DWORD ValueSize;
  1938. LPWSTR IpAddressString;
  1939. CHAR OemIpAddressString[DOT_IP_ADDR_SIZE];
  1940. DHCP_IP_ADDRESS RetVal;
  1941. RetVal = inet_addr("0.0.0.0");
  1942. RegKey = NULL;
  1943. KeyHandle = NULL;
  1944. IpAddressString = NULL;
  1945. Error = ERROR_NOT_ENOUGH_MEMORY;
  1946. RegKey = DhcpAllocateMemory(
  1947. (wcslen(DHCP_SERVICES_KEY) +
  1948. wcslen(REGISTRY_CONNECT_STRING) +
  1949. wcslen(AdapterName) +
  1950. wcslen(DHCP_ADAPTER_PARAMETERS_KEY) + 1) *
  1951. sizeof(WCHAR) ); // termination char.
  1952. if( RegKey == NULL ) goto Cleanup;
  1953. wcscpy( RegKey, DHCP_SERVICES_KEY );
  1954. wcscat( RegKey, DHCP_ADAPTER_PARAMETERS_KEY );
  1955. wcscat( RegKey, REGISTRY_CONNECT_STRING );
  1956. wcscat( RegKey, AdapterName );
  1957. Error = RegOpenKeyEx(
  1958. HKEY_LOCAL_MACHINE,
  1959. RegKey,
  1960. 0, // Reserved field
  1961. DHCP_CLIENT_KEY_ACCESS,
  1962. &KeyHandle
  1963. );
  1964. if( Error != ERROR_SUCCESS ) goto Cleanup;
  1965. Error = GetRegistryString(
  1966. KeyHandle,
  1967. ValueName,
  1968. &IpAddressString,
  1969. NULL
  1970. );
  1971. if( ERROR_SUCCESS != Error ) goto Cleanup;
  1972. DhcpPrint((DEBUG_MISC, "Static adapter <%ws> has ip address %ws\n",
  1973. AdapterName, IpAddressString));
  1974. DhcpAssert(NULL != IpAddressString);
  1975. RetVal = inet_addr(DhcpUnicodeToOem(IpAddressString, OemIpAddressString));
  1976. Cleanup:
  1977. if( RegKey) DhcpFreeMemory(RegKey);
  1978. if( KeyHandle ) DhcpFreeMemory(KeyHandle);
  1979. if( IpAddressString ) DhcpFreeMemory(IpAddressString);
  1980. if( ERROR_SUCCESS != Error ) {
  1981. DhcpPrint((DEBUG_ERRORS, "DhcpRegReadIpAddress: %ld\n", Error));
  1982. }
  1983. return RetVal;
  1984. }
  1985. BOOL // obtained a static address?
  1986. DhcpRegDomainName( // get the static domain name if any
  1987. IN PDHCP_CONTEXT DhcpContext, // adapter to get static domain for..
  1988. IN OUT LPBYTE DomainNameBuf, // buffer to fill with static domain name
  1989. IN ULONG BufSize // size of above buffer in bytes..
  1990. )
  1991. {
  1992. WCHAR DomBuf[260];
  1993. DWORD Result;
  1994. DWORD ValueType;
  1995. DWORD Size;
  1996. #if 0 // this is not really needed.
  1997. if( NULL == DhcpGlobalTcpipParametersKey ) { // maybe running in RAS context?
  1998. return FALSE; // no domain name in this context..
  1999. }
  2000. Size = BufSize;
  2001. Result = RegQueryValueExA( // first read the value from global
  2002. DhcpGlobalTcpipParametersKey, // Tcpip\Parameters\Domain key
  2003. DHCP_STATIC_DOMAIN_VALUE_A, // "Domain"
  2004. 0,
  2005. &ValueType,
  2006. DomainNameBuf,
  2007. &BufSize
  2008. );
  2009. if( ERROR_SUCCESS == Result && REG_SZ == ValueType && BufSize > 1 ) {
  2010. return TRUE; // got a domain name! aha
  2011. }
  2012. BufSize = Size;
  2013. #endif
  2014. if( NULL == DhcpContext->AdapterInfoKey ) { // uh? dont know what this means..
  2015. return FALSE; // cant get global information in this case
  2016. }
  2017. Size = sizeof(DomBuf);
  2018. Result = RegQueryValueExW( // now try to read the per-adapter stuff..
  2019. DhcpContext->AdapterInfoKey, // per-adapter key is already there for us
  2020. DHCP_DOMAINNAME_VALUE, // same value.. "Domain"
  2021. 0,
  2022. &ValueType,
  2023. (LPBYTE)DomBuf,
  2024. &Size
  2025. );
  2026. if( ERROR_SUCCESS == Result && REG_SZ == ValueType && Size > sizeof(WCHAR) ) {
  2027. if( NULL == DhcpUnicodeToOem(DomBuf, DomainNameBuf) ) return FALSE;
  2028. return TRUE;
  2029. }
  2030. return FALSE; // did not find a static domain in either place..
  2031. }
  2032. STATIC
  2033. struct /* anonymous */ {
  2034. DHCPKEY *GlobalKey;
  2035. LPWSTR KeyLocation;
  2036. } GlobalKeyList[] = { // the list of keys that need to be opened
  2037. &DhcpGlobalParametersKey, DHCP_CLIENT_PARAMETER_KEY,
  2038. &DhcpGlobalTcpipParametersKey, DHCP_TCPIP_PARAMETERS_KEY,
  2039. &DhcpGlobalClientOptionKey, DHCP_CLIENT_OPTION_KEY,
  2040. NULL, NULL,
  2041. };
  2042. ULONG DwordDisplayPopup;
  2043. STATIC
  2044. struct /* anonymous */ {
  2045. DWORD *DwordValue;
  2046. LPWSTR ValueName;
  2047. } GlobalTcpipDwordParameters[] = { // The global list of DWORDS
  2048. &UseMHAsyncDns, DHCP_USE_MHASYNCDNS_FLAG,
  2049. &DhcpGlobalAutonetEnabled, DHCP_IPAUTOCONFIGURATION_ENABLED,
  2050. &AutonetRetriesSeconds, DHCP_AUTONET_RETRIES_VALUE,
  2051. &DhcpGlobalUseInformFlag, DHCP_USE_INFORM_FLAG,
  2052. &DhcpGlobalDontPingGatewayFlag,DHCP_DONT_PING_GATEWAY_FLAG,
  2053. #ifdef BOOTPERF
  2054. &DhcpGlobalQuickBootEnabledFlag,DHCP_QUICK_BOOT_FLAG,
  2055. #endif BOOTPERF
  2056. NULL, NULL,
  2057. },
  2058. GlobalDhcpDwordParameters[] = { // stored in Services\Dhcp\Params..
  2059. #if DBG
  2060. &DhcpGlobalDebugFlag, DHCP_DEBUG_FLAG_VALUE,
  2061. &DhcpGlobalServerPort, DHCP_SERVER_PORT_VALUE,
  2062. &DhcpGlobalClientPort, DHCP_CLIENT_PORT_VALUE,
  2063. #endif DBG
  2064. &DwordDisplayPopup, DHCP_DISPLAY_POPUPS_FLAG,
  2065. NULL, NULL,
  2066. };
  2067. DWORD // Win32 status
  2068. DhcpInitRegistry( // Initialize registry based globals
  2069. VOID
  2070. ) {
  2071. DWORD Error;
  2072. DWORD i;
  2073. DWORD Type;
  2074. DWORD Size;
  2075. DWORD DwordValue;
  2076. LPWSTR ValueName;
  2077. DhcpGlobalAutonetEnabled = TRUE;
  2078. i = 0;
  2079. while( NULL != GlobalKeyList[i].GlobalKey ) {
  2080. Error = RegOpenKeyEx(
  2081. HKEY_LOCAL_MACHINE,
  2082. GlobalKeyList[i].KeyLocation,
  2083. 0 /* Reserved */,
  2084. DHCP_CLIENT_KEY_ACCESS,
  2085. GlobalKeyList[i].GlobalKey
  2086. );
  2087. if( ERROR_SUCCESS != Error ) return Error;
  2088. i ++;
  2089. }
  2090. i = 0;
  2091. while( NULL != GlobalTcpipDwordParameters[i].DwordValue ) {
  2092. ValueName = GlobalTcpipDwordParameters[i++].ValueName;
  2093. Size = sizeof(DwordValue);
  2094. Error = RegQueryValueEx(
  2095. DhcpGlobalTcpipParametersKey,
  2096. ValueName,
  2097. 0 /* Reserved */,
  2098. &Type,
  2099. (LPBYTE)&DwordValue,
  2100. &Size
  2101. );
  2102. if( ERROR_SUCCESS != Error ) {
  2103. DhcpPrint((DEBUG_INIT, "Did not find value %ws in the registry\n", ValueName));
  2104. continue;
  2105. }
  2106. if( REG_DWORD != Type ) {
  2107. DhcpPrint((DEBUG_ERRORS, "RegValue %ws is not DWORD type -- ignored\n", ValueName));
  2108. continue;
  2109. }
  2110. DhcpAssert(sizeof(DWORD) == Size);
  2111. *GlobalTcpipDwordParameters[i-1].DwordValue = DwordValue;
  2112. DhcpPrint((DEBUG_TRACE, "RegValue %ws = %ld = 0x%X\n", ValueName, DwordValue, DwordValue));
  2113. }
  2114. DwordDisplayPopup = 0;
  2115. i = 0;
  2116. while( NULL != GlobalDhcpDwordParameters[i].DwordValue ) {
  2117. ValueName = GlobalDhcpDwordParameters[i++].ValueName;
  2118. Size = sizeof(DwordValue);
  2119. Error = RegQueryValueEx(
  2120. DhcpGlobalParametersKey,
  2121. ValueName,
  2122. 0 /* Reserved */,
  2123. &Type,
  2124. (LPBYTE)&DwordValue,
  2125. &Size
  2126. );
  2127. if( ERROR_SUCCESS != Error ) {
  2128. DhcpPrint((DEBUG_INIT, "Did not find value %ws in the registry\n", ValueName));
  2129. continue;
  2130. }
  2131. if( REG_DWORD != Type ) {
  2132. DhcpPrint((DEBUG_ERRORS, "RegValue %ws is not DWORD type -- ignored\n", ValueName));
  2133. continue;
  2134. }
  2135. DhcpAssert(sizeof(DWORD) == Size);
  2136. *GlobalDhcpDwordParameters[i-1].DwordValue = DwordValue;
  2137. DhcpPrint((DEBUG_TRACE, "RegValue %ws = %ld = 0x%X\n", ValueName, DwordValue, DwordValue));
  2138. }
  2139. if( DwordDisplayPopup ) DhcpGlobalDisplayPopup = TRUE ; else DhcpGlobalDisplayPopup = FALSE;
  2140. return DhcpRegReadOptionDefList();
  2141. }
  2142. VOID
  2143. DhcpCleanupRegistry( // undo the effects of InitReg call
  2144. VOID
  2145. ) {
  2146. DWORD i;
  2147. DhcpCleanupOptionDefList(&DhcpGlobalOptionDefList);
  2148. i = 0;
  2149. while( NULL != GlobalKeyList[i].GlobalKey ) {
  2150. if( *GlobalKeyList[i].GlobalKey ) RegCloseKey(*GlobalKeyList[i].GlobalKey);
  2151. (*GlobalKeyList[i].GlobalKey) = NULL;
  2152. i ++ ;
  2153. }
  2154. }
  2155. //--------------------------------------------------------------------------------
  2156. // End of file
  2157. //--------------------------------------------------------------------------------