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.

2147 lines
58 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Domain Name System (DNS) API
  7. Registry management routines.
  8. Author:
  9. Jim Gilroy (jamesg) March, 2000
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "registry.h"
  14. //
  15. // Globals
  16. //
  17. // DWORD globals blob
  18. //
  19. // g_IsRegReady protects needs init and protects (requires)
  20. // global init.
  21. //
  22. // See registry.h for discussion of how these globals are
  23. // exposed both internal to the DLL and external.
  24. //
  25. DNS_GLOBALS_BLOB DnsGlobals;
  26. BOOL g_IsRegReady = FALSE;
  27. PWSTR g_pwsRemoteResolver = NULL;
  28. //
  29. // Property table
  30. //
  31. //
  32. // WARNING: table must be in sync with DNS_REGID definitions
  33. //
  34. // For simplicity I did not provide a separate index field and
  35. // a lookup function (or alternatively a function that returned
  36. // all the properties or a property pointer).
  37. //
  38. // The DNS_REGID values ARE the INDEXES!
  39. // Hence the table MUST be in sync or the whole deal blows up
  40. // If you make a change to either -- you must change the other!
  41. //
  42. REG_PROPERTY RegPropertyTable[] =
  43. {
  44. // Basic
  45. HOST_NAME ,
  46. 0 , // Default FALSE
  47. 0 , // No policy
  48. 1 , // Client
  49. 1 , // TcpIp
  50. 0 , // No Cache
  51. DOMAIN_NAME ,
  52. 0 , // Default FALSE
  53. 1 , // Policy
  54. 0 , // No Client
  55. 1 , // TcpIp
  56. 0 , // No Cache
  57. DHCP_DOMAIN_NAME ,
  58. 0 , // Default FALSE
  59. 1 , // Policy
  60. 0 , // No Client
  61. 1 , // TcpIp
  62. 0 , // No Cache
  63. ADAPTER_DOMAIN_NAME ,
  64. 0 , // Default FALSE
  65. 1 , // Policy
  66. 1 , // Client
  67. 0 , // No TcpIp
  68. 0 , // No Cache
  69. PRIMARY_DOMAIN_NAME ,
  70. 0 , // Default FALSE
  71. 1 , // Policy
  72. 1 , // Client
  73. 0 , // No TcpIp
  74. 0 , // No Cache
  75. PRIMARY_SUFFIX ,
  76. 0 , // Default FALSE
  77. 1 , // Policy
  78. 1 , // Client
  79. 1 , // TcpIp
  80. 0 , // No Cache
  81. ALTERNATE_NAMES ,
  82. 0 , // Default NULL
  83. 0 , // No Policy
  84. 0 , // No Client
  85. 0 , // No TcpIp
  86. 1 , // Cache
  87. DNS_SERVERS ,
  88. 0 , // Default FALSE
  89. 0 , // Policy
  90. 0 , // Client
  91. 0 , // TcpIp
  92. 0 , // No Cache
  93. SEARCH_LIST_KEY ,
  94. 0 , // Default FALSE
  95. 1 , // Policy
  96. 1 , // Client
  97. 1 , // TcpIp
  98. 0 , // No Cache
  99. // not in use
  100. UPDATE_ZONE_EXCLUSIONS ,
  101. 0 , // Default
  102. 1 , // Policy
  103. 1 , // Client
  104. 0 , // No TcpIp
  105. 1 , // Cache
  106. // Query
  107. QUERY_ADAPTER_NAME ,
  108. 1 , // Default TRUE
  109. 1 , // Policy
  110. 1 , // Client
  111. 0 , // No TcpIp
  112. 1 , // Cache
  113. USE_DOMAIN_NAME_DEVOLUTION ,
  114. 1 , // Default TRUE
  115. 1 , // Policy
  116. 1 , // Client
  117. 1 , // TcpIp
  118. 1 , // Cache
  119. PRIORITIZE_RECORD_DATA ,
  120. 1 , // Default TRUE
  121. 1 , // Policy
  122. 1 , // Client
  123. 1 , // TcpIp
  124. 1 , // Cache
  125. ALLOW_UNQUALIFIED_QUERY ,
  126. 0 , // Default FALSE
  127. 1 , // Policy
  128. 1 , // Client
  129. 1 , // TcpIp
  130. 1 , // Cache
  131. APPEND_TO_MULTI_LABEL_NAME ,
  132. 1 , // Default TRUE
  133. 1 , // Policy
  134. 1 , // Client
  135. 0 , // No TcpIp
  136. 1 , // Cache
  137. SCREEN_BAD_TLDS ,
  138. DNS_TLD_SCREEN_DEFAULT , // Default
  139. 1 , // Policy
  140. 1 , // Client
  141. 0 , // No TcpIp
  142. 1 , // Cache
  143. SCREEN_UNREACHABLE_SERVERS ,
  144. 1 , // Default TRUE
  145. 1 , // Policy
  146. 1 , // Client
  147. 0 , // No TcpIp
  148. 1 , // Cache
  149. FILTER_CLUSTER_IP ,
  150. 0 , // Default FALSE
  151. 1 , // Policy
  152. 1 , // Client
  153. 0 , // No TcpIp
  154. 1 , // Cache
  155. WAIT_FOR_NAME_ERROR_ON_ALL ,
  156. 1 , // Default TRUE
  157. 1 , // Policy
  158. 1 , // Client
  159. 0 , // No TcpIp
  160. 1 , // Cache
  161. USE_EDNS ,
  162. //REG_EDNS_TRY , // Default TRY EDNS
  163. 0 , // Default FALSE
  164. 1 , // Policy
  165. 1 , // Client
  166. 0 , // No TcpIp
  167. 1 , // Cache
  168. QUERY_IP_MATCHING ,
  169. 1 , // Default TRUE
  170. 1 , // Policy
  171. 1 , // Client
  172. 1 , // TcpIp (in Win2k)
  173. 1 , // Cache
  174. // Update
  175. REGISTRATION_ENABLED ,
  176. 1 , // Default TRUE
  177. 1 , // Policy
  178. 1 , // Client
  179. 0 , // No TcpIp
  180. 1 , // Cache
  181. REGISTER_PRIMARY_NAME ,
  182. 1 , // Default TRUE
  183. 1 , // Policy
  184. 1 , // Client
  185. 0 , // No TcpIp
  186. 1 , // Cache
  187. REGISTER_ADAPTER_NAME ,
  188. 1 , // Default TRUE
  189. 1 , // Policy
  190. 1 , // Client
  191. 0 , // No TcpIp
  192. 1 , // Cache
  193. REGISTER_REVERSE_LOOKUP ,
  194. 1 , // Default TRUE
  195. 1 , // Policy
  196. 1 , // Client
  197. 0 , // No TcpIp
  198. 1 , // Cache
  199. REGISTER_WAN_ADAPTERS ,
  200. 1 , // Default TRUE
  201. 1 , // Policy
  202. 1 , // Client
  203. 0 , // No TcpIp
  204. 1 , // Cache
  205. REGISTRATION_TTL ,
  206. REGDEF_REGISTRATION_TTL ,
  207. 1 , // Policy
  208. 1 , // Client
  209. 0 , // No TcpIp
  210. 1 , // Cache
  211. REGISTRATION_REFRESH_INTERVAL ,
  212. REGDEF_REGISTRATION_REFRESH_INTERVAL ,
  213. 1 , // Policy
  214. 1 , // Client
  215. 0 , // No TcpIp
  216. 1 , // Cache
  217. REGISTRATION_MAX_ADDRESS_COUNT ,
  218. 1 , // Default register 1 address
  219. 1 , // Policy
  220. 1 , // Client
  221. 0 , // No TcpIp
  222. 1 , // Cache
  223. UPDATE_SECURITY_LEVEL ,
  224. DNS_UPDATE_SECURITY_USE_DEFAULT ,
  225. 1 , // Policy
  226. 1 , // Client
  227. 1 , // TcpIp
  228. 1 , // Cache
  229. // not in use
  230. UPDATE_ZONE_EXCLUDE_FILE ,
  231. 0 , // Default OFF
  232. 1 , // Policy
  233. 1 , // Client
  234. 0 , // No TcpIp
  235. 1 , // Cache
  236. UPDATE_TOP_LEVEL_DOMAINS ,
  237. 0 , // Default OFF
  238. 1 , // Policy
  239. 1 , // Client
  240. 0 , // No TcpIp
  241. 1 , // Cache
  242. //
  243. // Backcompat
  244. //
  245. // DCR: once policy fixed, policy should be OFF on all backcompat
  246. //
  247. DISABLE_ADAPTER_DOMAIN_NAME ,
  248. 0 , // Default FALSE
  249. 0 , // Policy
  250. 0 , // Client
  251. 1 , // TcpIp
  252. 0 , // No Cache
  253. DISABLE_DYNAMIC_UPDATE ,
  254. 0 , // Default FALSE
  255. 0 , // Policy
  256. 0 , // Client
  257. 1 , // TcpIp
  258. 0 , // No Cache
  259. ENABLE_ADAPTER_DOMAIN_NAME_REGISTRATION ,
  260. 0 , // Default TRUE
  261. 0 , // Policy
  262. 0 , // Client
  263. 1 , // TcpIp
  264. 0 , // No Cache
  265. DISABLE_REVERSE_ADDRESS_REGISTRATIONS ,
  266. 0 , // Default FALSE
  267. 0 , // Policy
  268. 0 , // Client
  269. 1 , // TcpIp
  270. 0 , // No Cache
  271. DISABLE_WAN_DYNAMIC_UPDATE ,
  272. 0 , // Default FALSE
  273. 0 , // Policy OFF
  274. 0 , // Client
  275. 1 , // TcpIp
  276. 0 , // No Cache
  277. ENABLE_WAN_UPDATE_EVENT_LOG ,
  278. 0 , // Default FALSE
  279. 0 , // Policy OFF
  280. 0 , // Client
  281. 1 , // TcpIp
  282. 0 , // No Cache
  283. DEFAULT_REGISTRATION_TTL ,
  284. REGDEF_REGISTRATION_TTL ,
  285. 0 , // Policy OFF
  286. 0 , // Client
  287. 1 , // TcpIp
  288. 0 , // No Cache
  289. DEFAULT_REGISTRATION_REFRESH_INTERVAL ,
  290. REGDEF_REGISTRATION_REFRESH_INTERVAL ,
  291. 0 , // Policy
  292. 0 , // Client
  293. 1 , // TcpIp
  294. 0 , // No Cache
  295. MAX_NUMBER_OF_ADDRESSES_TO_REGISTER ,
  296. 1 , // Default register 1 address
  297. 0 , // Policy
  298. 0 , // Client
  299. 1 , // TcpIp
  300. 0 , // No Cache
  301. // Micellaneous
  302. NT_SETUP_MODE ,
  303. 0 , // Default FALSE
  304. 0 , // No policy
  305. 0 , // Client
  306. 0 , // No TcpIp
  307. 0 , // No Cache
  308. DNS_TEST_MODE ,
  309. 0 , // Default FALSE
  310. 0 , // No policy
  311. 0 , // No Client
  312. 0 , // No TcpIp
  313. 1 , // In Cache
  314. REMOTE_DNS_RESOLVER ,
  315. 0 , // Default FALSE
  316. 1 , // Policy
  317. 1 , // Client
  318. 0 , // No TcpIp
  319. 1 , // In Cache
  320. // Resolver
  321. MAX_CACHE_SIZE ,
  322. 1000 , // Default 1000 record sets
  323. 1 , // Policy
  324. 1 , // Client
  325. 0 , // No TcpIp
  326. 1 , // Cache
  327. MAX_CACHE_TTL ,
  328. 86400 , // Default 1 day
  329. 1 , // Policy
  330. 1 , // Client
  331. 0 , // No TcpIp
  332. 1 , // Cache
  333. MAX_NEGATIVE_CACHE_TTL ,
  334. 900 , // Default 15 minutes
  335. 1 , // Policy
  336. 1 , // Client
  337. 0 , // No TcpIp
  338. 1 , // Cache
  339. ADAPTER_TIMEOUT_LIMIT ,
  340. 600 , // Default 10 minutes
  341. 1 , // Policy
  342. 1 , // Client
  343. 0 , // No TcpIp
  344. 1 , // Cache
  345. SERVER_PRIORITY_TIME_LIMIT ,
  346. 300 , // Default 5 minutes
  347. 1 , // Policy
  348. 1 , // Client
  349. 0 , // No TcpIp
  350. 1 , // Cache
  351. MAX_CACHED_SOCKETS ,
  352. 10 , // Default 10
  353. 1 , // Policy
  354. 1 , // Client
  355. 0 , // No TcpIp
  356. 1 , // Cache
  357. // Multicast
  358. MULTICAST_LISTEN_LEVEL ,
  359. MCAST_LISTEN_FULL_IP6_ONLY , // Default IP6 only
  360. 1 , // Policy
  361. 0 , // No Client
  362. 0 , // No TcpIp
  363. 1 , // Cache
  364. MULTICAST_SEND_LEVEL ,
  365. MCAST_SEND_FULL_IP6_ONLY , // Default IP6 only
  366. 1 , // Policy
  367. 0 , // No Client
  368. 0 , // No TcpIp
  369. 1 , // Cache
  370. //
  371. // DHCP registration regkeys
  372. //
  373. // note, these are not part of the normal DNS client\resolver
  374. // registry settings; they are only here to provide the
  375. // regid to regname mapping so they can be read and written
  376. // with the standard registry functions
  377. //
  378. DHCP_REGISTERED_DOMAIN_NAME ,
  379. 0 , // No Default
  380. 0 , // No Policy
  381. 0 , // No Client
  382. 0 , // No TcpIp
  383. 0 , // No Cache
  384. DHCP_SENT_UPDATE_TO_IP ,
  385. 0 , // No Default
  386. 0 , // No Policy
  387. 0 , // No Client
  388. 0 , // No TcpIp
  389. 0 , // No Cache
  390. DHCP_SENT_PRI_UPDATE_TO_IP ,
  391. 0 , // No Default
  392. 0 , // No Policy
  393. 0 , // No Client
  394. 0 , // No TcpIp
  395. 0 , // No Cache
  396. DHCP_REGISTERED_TTL ,
  397. 0 , // No Default
  398. 0 , // No Policy
  399. 0 , // No Client
  400. 0 , // No TcpIp
  401. 0 , // No Cache
  402. DHCP_REGISTERED_FLAGS ,
  403. 0 , // No Default
  404. 0 , // No Policy
  405. 0 , // No Client
  406. 0 , // No TcpIp
  407. 0 , // No Cache
  408. DHCP_REGISTERED_SINCE_BOOT ,
  409. 0 , // No Default
  410. 0 , // No Policy
  411. 0 , // No Client
  412. 0 , // No TcpIp
  413. 0 , // No Cache
  414. DHCP_DNS_SERVER_ADDRS ,
  415. 0 , // No Default
  416. 0 , // No Policy
  417. 0 , // No Client
  418. 0 , // No TcpIp
  419. 0 , // No Cache
  420. DHCP_DNS_SERVER_ADDRS_COUNT ,
  421. 0 , // No Default
  422. 0 , // No Policy
  423. 0 , // No Client
  424. 0 , // No TcpIp
  425. 0 , // No Cache
  426. DHCP_REGISTERED_ADDRS ,
  427. 0 , // No Default
  428. 0 , // No Policy
  429. 0 , // No Client
  430. 0 , // No TcpIp
  431. 0 , // No Cache
  432. DHCP_REGISTERED_ADDRS_COUNT ,
  433. 0 , // No Default
  434. 0 , // No Policy
  435. 0 , // No Client
  436. 0 , // No TcpIp
  437. 0 , // No Cache
  438. // Termination
  439. NULL, 0, 0, 0, 0, 0
  440. };
  441. //
  442. // Backward compatibility list
  443. //
  444. // Maps new reg id to old reg id.
  445. // Flag fReverse indicates need to reverse (!) the value.
  446. //
  447. #define NO_BACK_VALUE ((DWORD)(0xffffffff))
  448. typedef struct _Backpat
  449. {
  450. DWORD NewId;
  451. DWORD OldId;
  452. BOOL fReverse;
  453. }
  454. BACKPAT;
  455. BACKPAT BackpatArray[] =
  456. {
  457. RegIdQueryAdapterName,
  458. RegIdDisableAdapterDomainName,
  459. TRUE,
  460. RegIdRegistrationEnabled,
  461. RegIdDisableDynamicUpdate,
  462. TRUE,
  463. RegIdRegisterAdapterName,
  464. RegIdEnableAdapterDomainNameRegistration,
  465. FALSE,
  466. RegIdRegisterReverseLookup,
  467. RegIdDisableReverseAddressRegistrations,
  468. TRUE,
  469. RegIdRegisterWanAdapters,
  470. RegIdDisableWanDynamicUpdate,
  471. TRUE,
  472. RegIdRegistrationTtl,
  473. RegIdDefaultRegistrationTTL,
  474. FALSE,
  475. RegIdRegistrationRefreshInterval,
  476. RegIdDefaultRegistrationRefreshInterval,
  477. FALSE,
  478. RegIdRegistrationMaxAddressCount,
  479. RegIdMaxNumberOfAddressesToRegister,
  480. FALSE,
  481. NO_BACK_VALUE, 0, 0
  482. };
  483. VOID
  484. Reg_Init(
  485. VOID
  486. )
  487. /*++
  488. Routine Description:
  489. Init DNS registry stuff.
  490. Essentially this means get system version info.
  491. Arguments:
  492. None.
  493. Globals:
  494. Sets the system info globals above:
  495. g_IsWorkstation
  496. g_IsServer
  497. g_IsDomainController
  498. g_IsRegReady
  499. Return Value:
  500. None.
  501. --*/
  502. {
  503. OSVERSIONINFOEX osvi;
  504. BOOL bversionInfoEx;
  505. //
  506. // do this just once
  507. //
  508. if ( g_IsRegReady )
  509. {
  510. return;
  511. }
  512. //
  513. // code validity check
  514. // property table should have entry for every reg value plus an
  515. // extra one for the terminator
  516. //
  517. DNS_ASSERT( (RegIdMax+2)*sizeof(REG_PROPERTY) ==
  518. sizeof(RegPropertyTable) );
  519. //
  520. // clear globals blob
  521. //
  522. // DCR: warning clearing DnsGlobals but don't read them all
  523. // this is protected by read-once deal but still kind of
  524. //
  525. RtlZeroMemory(
  526. & DnsGlobals,
  527. sizeof(DnsGlobals) );
  528. //
  529. // get version info
  530. //
  531. g_IsWin2000 = TRUE;
  532. ZeroMemory( &osvi, sizeof(OSVERSIONINFOEX) );
  533. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  534. bversionInfoEx = GetVersionEx( (OSVERSIONINFO*) &osvi );
  535. if ( !bversionInfoEx)
  536. {
  537. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  538. if ( ! GetVersionEx( (OSVERSIONINFO *) &osvi ) )
  539. {
  540. DNS_ASSERT( FALSE );
  541. return;
  542. }
  543. }
  544. //
  545. // get system type -- workstation, server, DC
  546. //
  547. if ( bversionInfoEx )
  548. {
  549. if ( osvi.wProductType == VER_NT_WORKSTATION )
  550. {
  551. g_IsWorkstation = TRUE;
  552. }
  553. else if ( osvi.wProductType == VER_NT_SERVER )
  554. {
  555. g_IsServer = TRUE;
  556. }
  557. else if ( osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
  558. {
  559. g_IsServer = TRUE;
  560. g_IsDomainController = TRUE;
  561. }
  562. ELSE_ASSERT( FALSE );
  563. }
  564. g_IsRegReady = TRUE;
  565. DNSDBG( REGISTRY, (
  566. "DNS registry init:\n"
  567. "\tWorksta = %d\n"
  568. "\tServer = %d\n"
  569. "\tDC = %d\n",
  570. g_IsWorkstation,
  571. g_IsServer,
  572. g_IsDomainController ));
  573. }
  574. //
  575. // Registry table routines
  576. //
  577. PWSTR
  578. regValueNameForId(
  579. IN DWORD RegId
  580. )
  581. /*++
  582. Routine Description:
  583. Return registry value name for reg ID
  584. Arguments:
  585. RegId -- ID for value
  586. Return Value:
  587. Ptr to reg value name.
  588. NULL on error.
  589. --*/
  590. {
  591. DNSDBG( REGISTRY, (
  592. "regValueNameForId( id=%d )\n",
  593. RegId ));
  594. //
  595. // validate ID
  596. //
  597. if ( RegId > RegIdMax )
  598. {
  599. return( NULL );
  600. }
  601. //
  602. // index into table
  603. //
  604. return( REGPROP_NAME(RegId) );
  605. }
  606. DWORD
  607. checkBackCompat(
  608. IN DWORD NewId,
  609. OUT PBOOL pfReverse
  610. )
  611. /*++
  612. Routine Description:
  613. Check if have backward compatible regkey.
  614. Arguments:
  615. NewId -- id to check for old backward compatible id
  616. pfReverse -- addr to receive reverse flag
  617. Return Value:
  618. Reg Id of old backward compatible value.
  619. NO_BACK_VALUE if no old value.
  620. --*/
  621. {
  622. DWORD i = 0;
  623. DWORD id;
  624. //
  625. // loop through backcompat list looking for value
  626. //
  627. while ( 1 )
  628. {
  629. id = BackpatArray[i].NewId;
  630. if ( id == NO_BACK_VALUE )
  631. {
  632. return( NO_BACK_VALUE );
  633. }
  634. if ( id != NewId )
  635. {
  636. i++;
  637. continue;
  638. }
  639. // found value in backcompat array
  640. break;
  641. }
  642. *pfReverse = BackpatArray[i].fReverse;
  643. return BackpatArray[i].OldId;
  644. }
  645. //
  646. // Registry session handle
  647. //
  648. DNS_STATUS
  649. WINAPI
  650. Reg_OpenSession(
  651. OUT PREG_SESSION pRegSession,
  652. IN DWORD Level,
  653. IN DWORD RegId
  654. )
  655. /*++
  656. Routine Description:
  657. Open registry for DNS client info.
  658. Arguments:
  659. pRegSession -- ptr to unitialize reg session blob
  660. Level -- level of access to get
  661. RegId -- ID of value we're interested in
  662. Return Value:
  663. None.
  664. --*/
  665. {
  666. DWORD status = NO_ERROR;
  667. HKEY hkey = NULL;
  668. DWORD disposition;
  669. // auto init
  670. Reg_Init();
  671. //
  672. // clear handles
  673. //
  674. RtlZeroMemory(
  675. pRegSession,
  676. sizeof( REG_SESSION ) );
  677. //
  678. // DCR: handle multiple access levels
  679. //
  680. // For know assume that if getting access to "standard"
  681. // section we'll need both policy and regular.
  682. //
  683. //
  684. // NT
  685. // - Win2000
  686. // - open TCPIP
  687. // note, always open TCPIP as may not be any policy
  688. // for some or all of our desired reg values, even
  689. // if policy key is available
  690. // - open policy (only if standard successful)
  691. //
  692. status = RegCreateKeyExW(
  693. HKEY_LOCAL_MACHINE,
  694. TCPIP_PARAMETERS_KEY,
  695. 0,
  696. L"Class",
  697. REG_OPTION_NON_VOLATILE,
  698. KEY_READ,
  699. NULL,
  700. &hkey,
  701. &disposition );
  702. if ( status != ERROR_SUCCESS )
  703. {
  704. goto Done;
  705. }
  706. #ifdef DNSCLIENTKEY
  707. // open DNS client key
  708. //
  709. // DCR: currently no DNSClient regkey
  710. RegOpenKeyExW(
  711. HKEY_LOCAL_MACHINE,
  712. DNS_CLIENT_KEY,
  713. 0,
  714. KEY_READ,
  715. & pRegSession->hClient );
  716. #endif
  717. // open DNS cache key
  718. RegOpenKeyExW(
  719. HKEY_LOCAL_MACHINE,
  720. DNS_CACHE_KEY,
  721. 0,
  722. KEY_READ,
  723. & pRegSession->hCache );
  724. // open DNS policy key
  725. RegOpenKeyExW(
  726. HKEY_LOCAL_MACHINE,
  727. DNS_POLICY_KEY,
  728. 0,
  729. KEY_READ,
  730. & pRegSession->hPolicy );
  731. Done:
  732. //
  733. // all OS versions return TCP/IP key
  734. //
  735. if ( status == ERROR_SUCCESS )
  736. {
  737. pRegSession->hTcpip = hkey;
  738. }
  739. else
  740. {
  741. Reg_CloseSession( pRegSession );
  742. }
  743. DNSDBG( TRACE, (
  744. "Leave: Reg_OpenSession( s=%d, t=%p, p=%p, c=%p )\n",
  745. status,
  746. pRegSession->hTcpip,
  747. pRegSession->hPolicy,
  748. pRegSession->hClient ));
  749. return( status );
  750. }
  751. VOID
  752. WINAPI
  753. Reg_CloseSession(
  754. IN OUT PREG_SESSION pRegSession
  755. )
  756. /*++
  757. Routine Description:
  758. Close registry session handle.
  759. This means close underlying regkeys.
  760. Arguments:
  761. pSessionHandle -- ptr to registry session handle
  762. Return Value:
  763. None.
  764. --*/
  765. {
  766. //
  767. // allow sloppy cleanup
  768. //
  769. if ( !pRegSession )
  770. {
  771. return;
  772. }
  773. //
  774. // close any non-NULL handles
  775. //
  776. if ( pRegSession->hPolicy )
  777. {
  778. RegCloseKey( pRegSession->hPolicy );
  779. }
  780. if ( pRegSession->hTcpip )
  781. {
  782. RegCloseKey( pRegSession->hTcpip );
  783. }
  784. #ifdef DNSCLIENTKEY
  785. if ( pRegSession->hClient )
  786. {
  787. RegCloseKey( pRegSession->hClient );
  788. }
  789. #endif
  790. if ( pRegSession->hCache )
  791. {
  792. RegCloseKey( pRegSession->hCache );
  793. }
  794. //
  795. // clear handles (just for safety)
  796. //
  797. RtlZeroMemory(
  798. pRegSession,
  799. sizeof(REG_SESSION) );
  800. }
  801. //
  802. // Registry reading routines
  803. //
  804. DNS_STATUS
  805. Reg_GetDword(
  806. IN PREG_SESSION pRegSession, OPTIONAL
  807. IN HKEY hRegKey, OPTIONAL
  808. IN PWSTR pwsKeyName, OPTIONAL
  809. IN DWORD RegId,
  810. OUT PDWORD pResult
  811. )
  812. /*++
  813. Routine Description:
  814. Read REG_DWORD value from registry.
  815. //
  816. // DCR: do we need to expose location result?
  817. // (explicit, policy, defaulted)
  818. //
  819. Arguments:
  820. pRegSession -- ptr to reg session already opened (OPTIONAL)
  821. hRegKey -- explicit regkey
  822. pwsKeyName -- key name OR dummy key
  823. RegId -- ID for value
  824. pResult -- addr of DWORD to recv result
  825. pfRead -- addr to recv result of how value read
  826. 0 -- defaulted
  827. 1 -- read
  828. Currently just use ERROR_SUCCESS to mean read rather
  829. than defaulted.
  830. Return Value:
  831. ERROR_SUCCESS on success.
  832. ErrorCode on failure -- value is then defaulted.
  833. --*/
  834. {
  835. DNS_STATUS status;
  836. REG_SESSION session;
  837. PREG_SESSION psession = pRegSession;
  838. PWSTR pname;
  839. DWORD regType = REG_DWORD;
  840. DWORD dataLength = sizeof(DWORD);
  841. HKEY hkey;
  842. HKEY hlocalKey = NULL;
  843. DNSDBG( REGISTRY, (
  844. "Reg_GetDword( s=%p, k=%p, a=%p, id=%d )\n",
  845. pRegSession,
  846. hRegKey,
  847. pwsKeyName,
  848. RegId ));
  849. // auto init
  850. Reg_Init();
  851. //
  852. // clear result for error case
  853. //
  854. *pResult = 0;
  855. //
  856. // get proper regval name
  857. // - wide for NT
  858. // - narrow for 9X
  859. //
  860. pname = regValueNameForId( RegId );
  861. if ( !pname )
  862. {
  863. DNS_ASSERT( FALSE );
  864. return( ERROR_INVALID_PARAMETER );
  865. }
  866. //
  867. // DCR: can use function pointers for wide narrow
  868. //
  869. //
  870. // three paradigms
  871. //
  872. // 1) specific key (adapter or something else)
  873. // => use it
  874. //
  875. // 2) specific key name (adapter or dummy key location)
  876. // => open key
  877. // => use it
  878. // => close
  879. //
  880. // 3) session -- passed in or created (default)
  881. // => use pRegSession or open new
  882. // => try policy first then TCPIP parameters
  883. // => close if open
  884. //
  885. if ( hRegKey )
  886. {
  887. hkey = hRegKey;
  888. }
  889. else if ( pwsKeyName )
  890. {
  891. hkey = Reg_CreateKey(
  892. pwsKeyName,
  893. FALSE // read access
  894. );
  895. if ( !hkey )
  896. {
  897. status = GetLastError();
  898. goto Done;
  899. }
  900. hlocalKey = hkey;
  901. }
  902. else
  903. {
  904. // open reg handle if not open
  905. if ( !psession )
  906. {
  907. status = Reg_OpenSession(
  908. &session,
  909. 0, // standard level
  910. RegId // target key
  911. );
  912. if ( status != ERROR_SUCCESS )
  913. {
  914. goto Done;
  915. }
  916. psession = &session;
  917. }
  918. // try policy section -- if available
  919. hkey = psession->hPolicy;
  920. if ( hkey && REGPROP_POLICY(RegId) )
  921. {
  922. status = RegQueryValueExW(
  923. hkey,
  924. pname,
  925. 0,
  926. & regType,
  927. (PBYTE) pResult,
  928. & dataLength
  929. );
  930. if ( status == ERROR_SUCCESS )
  931. {
  932. goto DoneSuccess;
  933. }
  934. }
  935. // unsuccessful -- try DnsClient
  936. #ifdef DNSCLIENTKEY
  937. hkey = psession->hClient;
  938. if ( hkey && REGPROP_CLIENT(RegId) )
  939. {
  940. status = RegQueryValueExW(
  941. hkey,
  942. pname,
  943. 0,
  944. & regType,
  945. (PBYTE) pResult,
  946. & dataLength
  947. );
  948. if ( status == ERROR_SUCCESS )
  949. {
  950. goto DoneSuccess;
  951. }
  952. }
  953. #endif
  954. // unsuccessful -- try DnsCache
  955. hkey = psession->hCache;
  956. if ( hkey && REGPROP_CACHE(RegId) )
  957. {
  958. status = RegQueryValueExW(
  959. hkey,
  960. pname,
  961. 0,
  962. & regType,
  963. (PBYTE) pResult,
  964. & dataLength
  965. );
  966. if ( status == ERROR_SUCCESS )
  967. {
  968. goto DoneSuccess;
  969. }
  970. }
  971. // unsuccessful -- try TCPIP key
  972. // - if have open session it MUST include TCPIP key
  973. hkey = psession->hTcpip;
  974. if ( hkey && REGPROP_TCPIP(RegId) )
  975. {
  976. status = RegQueryValueExW(
  977. hkey,
  978. pname,
  979. 0,
  980. & regType,
  981. (PBYTE) pResult,
  982. & dataLength
  983. );
  984. if ( status == ERROR_SUCCESS )
  985. {
  986. goto DoneSuccess;
  987. }
  988. }
  989. status = ERROR_FILE_NOT_FOUND;
  990. goto Done;
  991. }
  992. //
  993. // explict key (passed in or from name)
  994. //
  995. if ( hkey )
  996. {
  997. status = RegQueryValueExW(
  998. hkey,
  999. pname,
  1000. 0,
  1001. & regType,
  1002. (PBYTE) pResult,
  1003. & dataLength
  1004. );
  1005. }
  1006. ELSE_ASSERT_FALSE;
  1007. Done:
  1008. //
  1009. // if value not found, check for backward compatibility value
  1010. //
  1011. if ( status != ERROR_SUCCESS )
  1012. {
  1013. DWORD oldId;
  1014. BOOL freverse;
  1015. oldId = checkBackCompat( RegId, &freverse );
  1016. if ( oldId != NO_BACK_VALUE )
  1017. {
  1018. DWORD backValue;
  1019. status = Reg_GetDword(
  1020. psession,
  1021. ( psession ) ? NULL : hkey,
  1022. ( psession ) ? NULL : pwsKeyName,
  1023. oldId,
  1024. & backValue );
  1025. if ( status == ERROR_SUCCESS )
  1026. {
  1027. if ( freverse )
  1028. {
  1029. backValue = !backValue;
  1030. }
  1031. *pResult = backValue;
  1032. }
  1033. }
  1034. }
  1035. // default the value if read failed
  1036. if ( status != ERROR_SUCCESS )
  1037. {
  1038. *pResult = REGPROP_DEFAULT( RegId );
  1039. }
  1040. DoneSuccess:
  1041. // cleanup any regkey's opened
  1042. if ( psession == &session )
  1043. {
  1044. Reg_CloseSession( psession );
  1045. }
  1046. else if ( hlocalKey )
  1047. {
  1048. RegCloseKey( hlocalKey );
  1049. }
  1050. return( status );
  1051. }
  1052. //
  1053. // Reg utilities
  1054. //
  1055. DNS_STATUS
  1056. privateRegReadValue(
  1057. IN HKEY hKey,
  1058. IN DWORD RegId,
  1059. IN DWORD Flag,
  1060. OUT PBYTE * ppBuffer,
  1061. OUT PDWORD pBufferLength
  1062. )
  1063. /*++
  1064. Routine Description:
  1065. Main registry reading routine.
  1066. Handles sizing, allocations and conversions as necessary.
  1067. Arguments:
  1068. hKey -- handle of the key whose value field is retrieved.
  1069. RegId -- reg value ID, assumed to be validated (in table)
  1070. Flag -- reg flags
  1071. DNSREG_FLAG_DUMP_EMPTY
  1072. DNSREG_FLAG_GET_UTF8
  1073. ppBuffer -- ptr to address to receive buffer ptr
  1074. pBufferLength -- addr to receive buffer length
  1075. Return Value:
  1076. ERROR_SUCCESS if successful.
  1077. ErrorCode on failure.
  1078. --*/
  1079. {
  1080. DWORD status;
  1081. PWSTR pname;
  1082. DWORD valueType = 0; // prefix
  1083. DWORD valueSize = 0; // prefix
  1084. PBYTE pdataBuffer;
  1085. PBYTE pallocBuffer = NULL;
  1086. //
  1087. // query for buffer size
  1088. //
  1089. pname = REGPROP_NAME( RegId );
  1090. status = RegQueryValueExW(
  1091. hKey,
  1092. pname,
  1093. 0,
  1094. &valueType,
  1095. NULL,
  1096. &valueSize );
  1097. if ( status != ERROR_SUCCESS )
  1098. {
  1099. return( status );
  1100. }
  1101. //
  1102. // setup result buffer
  1103. //
  1104. switch( valueType )
  1105. {
  1106. case REG_DWORD:
  1107. pdataBuffer = (PBYTE) ppBuffer;
  1108. break;
  1109. case REG_SZ:
  1110. case REG_MULTI_SZ:
  1111. case REG_EXPAND_SZ:
  1112. case REG_BINARY:
  1113. // if size is zero, still allocate empty string
  1114. // - min alloc DWORD
  1115. // - can't possibly alloc smaller
  1116. // - good clean init to zero includes MULTISZ zero
  1117. // - need at least WCHAR string zero init
  1118. // and much catch small regbinary (1,2,3)
  1119. if ( valueSize <= sizeof(DWORD) )
  1120. {
  1121. valueSize = sizeof(DWORD);
  1122. }
  1123. pallocBuffer = pdataBuffer = ALLOCATE_HEAP( valueSize );
  1124. if ( !pdataBuffer )
  1125. {
  1126. return( DNS_ERROR_NO_MEMORY );
  1127. }
  1128. *(PDWORD)pdataBuffer = 0;
  1129. break;
  1130. default:
  1131. return( ERROR_INVALID_PARAMETER );
  1132. }
  1133. //
  1134. // query for data
  1135. //
  1136. status = RegQueryValueExW(
  1137. hKey,
  1138. pname,
  1139. 0,
  1140. &valueType,
  1141. pdataBuffer,
  1142. &valueSize );
  1143. if ( status != ERROR_SUCCESS )
  1144. {
  1145. goto Cleanup;
  1146. }
  1147. //
  1148. // setup return buffer
  1149. //
  1150. switch( valueType )
  1151. {
  1152. case REG_DWORD:
  1153. case REG_BINARY:
  1154. break;
  1155. case REG_SZ:
  1156. case REG_EXPAND_SZ:
  1157. case REG_MULTI_SZ:
  1158. //
  1159. // dump empty strings?
  1160. //
  1161. // note: we always allocate at least a DWORD and
  1162. // set it NULL, so rather than a complex test for
  1163. // different reg types and char sets, can just test
  1164. // if that DWORD is still NULL
  1165. //
  1166. // DCR: do we want to screen whitespace-empty strings
  1167. // - example blank string
  1168. //
  1169. if ( Flag & DNSREG_FLAG_DUMP_EMPTY )
  1170. {
  1171. if ( valueSize==0 ||
  1172. *(PDWORD)pdataBuffer == 0 )
  1173. {
  1174. status = ERROR_INVALID_DATA;
  1175. goto Cleanup;
  1176. }
  1177. }
  1178. //
  1179. // force NULL termination
  1180. // - during security push, someone raised the question of whether
  1181. // the registry guarantees NULL termination on corrupted data
  1182. //
  1183. if ( valueSize == 0 )
  1184. {
  1185. *(PDWORD)pdataBuffer = 0;
  1186. }
  1187. else
  1188. {
  1189. INT lastChar = valueSize/sizeof(WCHAR) - 1;
  1190. if ( lastChar >= 0 )
  1191. {
  1192. ((PWSTR)pdataBuffer)[ lastChar ] = 0;
  1193. }
  1194. }
  1195. //
  1196. // by default we return strings as unicode
  1197. //
  1198. // if flagged, return in UTF8
  1199. //
  1200. if ( Flag & DNSREG_FLAG_GET_UTF8 )
  1201. {
  1202. PBYTE putf8Buffer = ALLOCATE_HEAP( valueSize * 2 );
  1203. if ( !putf8Buffer )
  1204. {
  1205. status = DNS_ERROR_NO_MEMORY;
  1206. goto Cleanup;
  1207. }
  1208. if ( !Dns_UnicodeToUtf8(
  1209. (PWSTR) pdataBuffer,
  1210. valueSize / sizeof(WCHAR),
  1211. putf8Buffer,
  1212. valueSize * 2 ) )
  1213. {
  1214. FREE_HEAP( putf8Buffer );
  1215. status = ERROR_INVALID_DATA;
  1216. goto Cleanup;
  1217. }
  1218. FREE_HEAP( pallocBuffer );
  1219. pallocBuffer = NULL;
  1220. pdataBuffer = putf8Buffer;
  1221. }
  1222. break;
  1223. default:
  1224. break;
  1225. }
  1226. Cleanup:
  1227. //
  1228. // set return
  1229. // - REG_DWORD writes DWORD to ppBuffer directly
  1230. // - otherwise ppBuffer set to allocated buffer ptr
  1231. // or cleanup
  1232. // - on failure dump allocated buffer
  1233. //
  1234. if ( status == ERROR_SUCCESS )
  1235. {
  1236. if ( valueType != REG_DWORD )
  1237. {
  1238. *ppBuffer = pdataBuffer;
  1239. }
  1240. *pBufferLength = valueSize;
  1241. }
  1242. else
  1243. {
  1244. if ( valueType != REG_DWORD )
  1245. {
  1246. *ppBuffer = NULL;
  1247. }
  1248. else
  1249. {
  1250. *(PDWORD)ppBuffer = 0;
  1251. }
  1252. *pBufferLength = 0;
  1253. FREE_HEAP( pallocBuffer );
  1254. }
  1255. return( status );
  1256. }
  1257. DNS_STATUS
  1258. Reg_GetValueEx(
  1259. IN PREG_SESSION pRegSession, OPTIONAL
  1260. IN HKEY hRegKey, OPTIONAL
  1261. IN PWSTR pwsAdapter, OPTIONAL
  1262. IN DWORD RegId,
  1263. IN DWORD ValueType,
  1264. IN DWORD Flag,
  1265. OUT PBYTE * ppBuffer
  1266. )
  1267. /*++
  1268. Routine Description:
  1269. Arguments:
  1270. pRegSession -- ptr to registry session, OPTIONAL
  1271. hRegKey -- handle to open regkey OPTIONAL
  1272. pwsAdapter -- name of adapter to query under OPTIONAL
  1273. RegId -- value ID
  1274. ValueType -- reg type of value
  1275. Flag -- flags with tweaks to lookup
  1276. ppBuffer -- addr to receive buffer ptr
  1277. Note, for REG_DWORD, DWORD data is written directly to this
  1278. location instead of a buffer being allocated and it's ptr
  1279. being written.
  1280. Return Value:
  1281. ERROR_SUCCESS if successful.
  1282. Registry error code on failure.
  1283. --*/
  1284. {
  1285. DNS_STATUS status = ERROR_FILE_NOT_FOUND;
  1286. REG_SESSION session;
  1287. PREG_SESSION psession = pRegSession;
  1288. PWSTR pname;
  1289. DWORD regType = REG_DWORD;
  1290. DWORD dataLength;
  1291. HKEY hkey;
  1292. HKEY hadapterKey = NULL;
  1293. DNSDBG( REGISTRY, (
  1294. "Reg_GetValueEx( s=%p, k=%p, id=%d )\n",
  1295. pRegSession,
  1296. hRegKey,
  1297. RegId ));
  1298. ASSERT( !pwsAdapter );
  1299. // auto init
  1300. Reg_Init();
  1301. //
  1302. // get regval name
  1303. //
  1304. pname = regValueNameForId( RegId );
  1305. if ( !pname )
  1306. {
  1307. DNS_ASSERT( FALSE );
  1308. status = ERROR_INVALID_PARAMETER;
  1309. goto FailedDone;
  1310. }
  1311. //
  1312. // two paradigms
  1313. //
  1314. // 1) specific key (adapter or something else)
  1315. // => use it
  1316. // => open adapter subkey if necessary
  1317. //
  1318. // 2) standard
  1319. // => try policy first, then DNSCache, then TCPIP
  1320. // => use pRegSession or open it
  1321. //
  1322. if ( hRegKey )
  1323. {
  1324. hkey = hRegKey;
  1325. // need to open adapter subkey
  1326. if ( pwsAdapter )
  1327. {
  1328. status = RegOpenKeyExW(
  1329. hkey,
  1330. pwsAdapter,
  1331. 0,
  1332. KEY_QUERY_VALUE,
  1333. & hadapterKey );
  1334. if ( status != ERROR_SUCCESS )
  1335. {
  1336. goto FailedDone;
  1337. }
  1338. hkey = hadapterKey;
  1339. }
  1340. }
  1341. else
  1342. {
  1343. // open reg handle if not open
  1344. if ( !pRegSession )
  1345. {
  1346. status = Reg_OpenSession(
  1347. &session,
  1348. 0, // standard level
  1349. RegId // target key
  1350. );
  1351. if ( status != ERROR_SUCCESS )
  1352. {
  1353. goto FailedDone;
  1354. }
  1355. psession = &session;
  1356. }
  1357. // try policy section -- if available
  1358. hkey = psession->hPolicy;
  1359. if ( hkey && REGPROP_POLICY(RegId) )
  1360. {
  1361. status = privateRegReadValue(
  1362. hkey,
  1363. RegId,
  1364. Flag,
  1365. ppBuffer,
  1366. & dataLength
  1367. );
  1368. if ( status == ERROR_SUCCESS )
  1369. {
  1370. goto Done;
  1371. }
  1372. }
  1373. // try DNS cache -- if available
  1374. hkey = psession->hCache;
  1375. if ( hkey && REGPROP_CACHE(RegId) )
  1376. {
  1377. status = privateRegReadValue(
  1378. hkey,
  1379. RegId,
  1380. Flag,
  1381. ppBuffer,
  1382. & dataLength
  1383. );
  1384. if ( status == ERROR_SUCCESS )
  1385. {
  1386. goto Done;
  1387. }
  1388. }
  1389. // unsuccessful -- use TCPIP key
  1390. hkey = psession->hTcpip;
  1391. if ( !hkey )
  1392. {
  1393. goto Done;
  1394. }
  1395. }
  1396. //
  1397. // explict key OR standard key case
  1398. //
  1399. status = privateRegReadValue(
  1400. hkey,
  1401. RegId,
  1402. Flag,
  1403. ppBuffer,
  1404. & dataLength
  1405. );
  1406. if ( status == ERROR_SUCCESS )
  1407. {
  1408. goto Done;
  1409. }
  1410. FailedDone:
  1411. //
  1412. // if failed
  1413. // - for REG_DWORD, default the value
  1414. // - for strings, ensure NULL return buffer
  1415. // this takes care of cases where privateRegReadValue()
  1416. // never got called
  1417. //
  1418. if ( status != ERROR_SUCCESS )
  1419. {
  1420. if ( ValueType == REG_DWORD )
  1421. {
  1422. *(PDWORD) ppBuffer = REGPROP_DEFAULT( RegId );
  1423. }
  1424. else
  1425. {
  1426. *ppBuffer = NULL;
  1427. }
  1428. }
  1429. Done:
  1430. // cleanup any regkey's opened
  1431. if ( psession == &session )
  1432. {
  1433. Reg_CloseSession( psession );
  1434. }
  1435. if ( hadapterKey )
  1436. {
  1437. RegCloseKey( hadapterKey );
  1438. }
  1439. return( status );
  1440. }
  1441. DNS_STATUS
  1442. Reg_GetIpArray(
  1443. IN PREG_SESSION pRegSession, OPTIONAL
  1444. IN HKEY hRegKey, OPTIONAL
  1445. IN PWSTR pwsAdapter, OPTIONAL
  1446. IN DWORD RegId,
  1447. IN DWORD ValueType,
  1448. OUT PIP4_ARRAY * ppIpArray
  1449. )
  1450. /*++
  1451. Routine Description:
  1452. Arguments:
  1453. pRegSession -- ptr to registry session, OPTIONAL
  1454. hRegKey -- handle to open regkey OPTIONAL
  1455. pwsAdapter -- name of adapter to query under OPTIONAL
  1456. RegId -- value ID
  1457. ValueType -- currently ignored, but could later use
  1458. to distinguish REG_SZ from REG_MULTI_SZ
  1459. processing
  1460. ppIpArray -- addr to receive IP array ptr
  1461. - array is allocated with Dns_Alloc(),
  1462. caller must free with Dns_Free()
  1463. Return Value:
  1464. ERROR_SUCCESS if successful.
  1465. Registry error code on failure.
  1466. --*/
  1467. {
  1468. DNS_STATUS status;
  1469. PSTR pstring = NULL;
  1470. DNSDBG( REGISTRY, (
  1471. "Reg_GetIpArray( s=%p, k=%p, id=%d )\n",
  1472. pRegSession,
  1473. hRegKey,
  1474. RegId ));
  1475. //
  1476. // make call to get IP array as string
  1477. //
  1478. status = Reg_GetValueEx(
  1479. pRegSession,
  1480. hRegKey,
  1481. pwsAdapter,
  1482. RegId,
  1483. REG_SZ, // only supported type is REG_SZ
  1484. DNSREG_FLAG_GET_UTF8, // get as narrow
  1485. & pstring );
  1486. if ( status != ERROR_SUCCESS )
  1487. {
  1488. ASSERT( pstring == NULL );
  1489. return( status );
  1490. }
  1491. //
  1492. // convert from string to IP array
  1493. //
  1494. // note: this call is limited to a parsing limit
  1495. // but it is a large number suitable for stuff
  1496. // like DNS server lists
  1497. //
  1498. // DCR: use IP array builder for local IP address
  1499. // then need Dns_CreateIpArrayFromMultiIpString()
  1500. // to use count\alloc method when buffer overflows
  1501. //
  1502. status = Dns_CreateIpArrayFromMultiIpString(
  1503. pstring,
  1504. ppIpArray );
  1505. // cleanup
  1506. if ( pstring )
  1507. {
  1508. FREE_HEAP( pstring );
  1509. }
  1510. return( status );
  1511. }
  1512. //
  1513. // Registry writing routines
  1514. //
  1515. HKEY
  1516. WINAPI
  1517. Reg_CreateKey(
  1518. IN PWSTR pwsKeyName,
  1519. IN BOOL bWrite
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. Open registry key.
  1524. The purpose of this routine is simply to functionalize
  1525. opening with\without an adapter name.
  1526. So caller can pass through adapter name argument instead
  1527. of building key name or doing two opens for adapter
  1528. present\absent.
  1529. This is NT only.
  1530. Arguments:
  1531. pwsKeyName -- key "name"
  1532. this is one of the REGKEY_X from registry.h
  1533. OR
  1534. adapter name
  1535. bWrite -- TRUE for write access, FALSE for read
  1536. Return Value:
  1537. New opened key.
  1538. --*/
  1539. {
  1540. HKEY hkey = NULL;
  1541. DWORD disposition;
  1542. DWORD status;
  1543. PWSTR pnameKey;
  1544. WCHAR nameBuffer[ MAX_PATH+1 ];
  1545. //
  1546. // determine key name
  1547. //
  1548. // this is either DNSKEY_X dummy pointer from registry.h
  1549. // OR
  1550. // is an adapter name;
  1551. //
  1552. // - if adapter given, open under it
  1553. // adapters are under TCPIP\Interfaces
  1554. // - any other specific key
  1555. // - default is TCPIP params key
  1556. //
  1557. // note: if if grows too big, turn into table
  1558. //
  1559. if ( pwsKeyName <= REGKEY_DNS_MAX )
  1560. {
  1561. if ( pwsKeyName == REGKEY_TCPIP_PARAMETERS )
  1562. {
  1563. pnameKey = TCPIP_PARAMETERS_KEY;
  1564. }
  1565. else if ( pwsKeyName == REGKEY_DNS_CACHE )
  1566. {
  1567. pnameKey = DNS_CACHE_KEY;
  1568. }
  1569. else if ( pwsKeyName == REGKEY_DNS_POLICY )
  1570. {
  1571. pnameKey = DNS_POLICY_KEY;
  1572. }
  1573. else if ( pwsKeyName == REGKEY_SETUP_MODE_LOCATION )
  1574. {
  1575. pnameKey = NT_SETUP_MODE_KEY;
  1576. }
  1577. else
  1578. {
  1579. pnameKey = TCPIP_PARAMETERS_KEY;
  1580. }
  1581. }
  1582. else // adapter name
  1583. {
  1584. _snwprintf(
  1585. nameBuffer,
  1586. MAX_PATH,
  1587. L"%s%s",
  1588. TCPIP_INTERFACES_KEY,
  1589. pwsKeyName );
  1590. pnameKey = nameBuffer;
  1591. }
  1592. //
  1593. // create\open key
  1594. //
  1595. if ( bWrite )
  1596. {
  1597. status = RegCreateKeyExW(
  1598. HKEY_LOCAL_MACHINE,
  1599. pnameKey,
  1600. 0,
  1601. L"Class",
  1602. REG_OPTION_NON_VOLATILE,
  1603. KEY_WRITE,
  1604. NULL,
  1605. & hkey,
  1606. & disposition );
  1607. }
  1608. else
  1609. {
  1610. status = RegOpenKeyExW(
  1611. HKEY_LOCAL_MACHINE,
  1612. pnameKey,
  1613. 0,
  1614. KEY_QUERY_VALUE,
  1615. & hkey );
  1616. }
  1617. if ( status != ERROR_SUCCESS )
  1618. {
  1619. SetLastError( status );
  1620. }
  1621. ELSE_ASSERT( hkey != NULL );
  1622. return( hkey );
  1623. }
  1624. DNS_STATUS
  1625. WINAPI
  1626. Reg_SetDwordValueByName(
  1627. IN PVOID pReserved,
  1628. IN HKEY hRegKey,
  1629. IN PWSTR pwsNameKey, OPTIONAL
  1630. IN PWSTR pwsNameValue, OPTIONAL
  1631. IN DWORD dwValue
  1632. )
  1633. /*++
  1634. Routine Description:
  1635. Set DWORD regkey.
  1636. Arguments:
  1637. pReserved -- reserved (may become session)
  1638. hRegKey -- existing key to set under OPTIONAL
  1639. pwsNameKey -- name of key or adapter to set under
  1640. pwsNameValue -- name of reg value to set
  1641. dwValue -- value to set
  1642. Return Value:
  1643. ERROR_SUCCESS if successful.
  1644. ErrorCode on failure.
  1645. --*/
  1646. {
  1647. HKEY hkey;
  1648. DNS_STATUS status;
  1649. //
  1650. // open key, if not provided
  1651. // - if adapter given, open under it
  1652. // - otherwise TCPIP params key
  1653. //
  1654. hkey = hRegKey;
  1655. if ( !hkey )
  1656. {
  1657. hkey = Reg_CreateKey(
  1658. pwsNameKey,
  1659. TRUE // open for write
  1660. );
  1661. if ( !hkey )
  1662. {
  1663. return( GetLastError() );
  1664. }
  1665. }
  1666. //
  1667. // write back value
  1668. //
  1669. status = RegSetValueExW(
  1670. hkey,
  1671. pwsNameValue,
  1672. 0,
  1673. REG_DWORD,
  1674. (LPBYTE) &dwValue,
  1675. sizeof(DWORD) );
  1676. if ( !hRegKey )
  1677. {
  1678. RegCloseKey( hkey );
  1679. }
  1680. return status;
  1681. }
  1682. DNS_STATUS
  1683. WINAPI
  1684. Reg_SetDwordValue(
  1685. IN PVOID pReserved,
  1686. IN HKEY hRegKey,
  1687. IN PWSTR pwsNameKey, OPTIONAL
  1688. IN DWORD RegId,
  1689. IN DWORD dwValue
  1690. )
  1691. /*++
  1692. Routine Description:
  1693. Set DWORD regkey.
  1694. Arguments:
  1695. pReserved -- reserved (may become session)
  1696. hRegKey -- existing key to set under OPTIONAL
  1697. pwsNameKey -- name of key or adapter to set under
  1698. RegId -- id of value to set
  1699. dwValue -- value to set
  1700. Return Value:
  1701. ERROR_SUCCESS if successful.
  1702. ErrorCode on failure.
  1703. --*/
  1704. {
  1705. //
  1706. // write back value using name of id
  1707. //
  1708. return Reg_SetDwordValueByName(
  1709. pReserved,
  1710. hRegKey,
  1711. pwsNameKey,
  1712. REGPROP_NAME( RegId ),
  1713. dwValue );
  1714. }
  1715. //
  1716. // End registry.c
  1717. //