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.

780 lines
22 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. sockreg.cxx
  5. Abstract:
  6. Contains the registry/ini-file specific functions from gethost.c
  7. Taken from Win95 Winsock 1.1 project
  8. Contents:
  9. SockGetSingleValue
  10. (CheckRegistryForParameter)
  11. Author:
  12. Richard L Firth (rfirth) 10-Feb-1994
  13. Environment:
  14. Win32 user-mode DLL
  15. Revision History:
  16. 10-Feb-1994 (rfirth)
  17. Created
  18. 24-Feb-2001 (ssulzer)
  19. Updated for WinHttp5
  20. --*/
  21. //
  22. // includes
  23. //
  24. #include <wininetp.h>
  25. #include "aproxp.h"
  26. //
  27. // manifests
  28. //
  29. //#define PLATFORM_TYPE_UNKNOWN ((DWORD)(-1))
  30. //#define PLATFORM_TYPE_WIN95 ((DWORD)(0))
  31. //#define PLATFORM_TYPE_WINNT ((DWORD)(1))
  32. //#define PLATFORM_SUPPORTS_UNICODE 0x00000001
  33. #define DEVICE_PREFIX "\\Device\\"
  34. //
  35. // manifests
  36. //
  37. //
  38. // macros
  39. //
  40. #define FSTRLEN(p) lstrlen((LPSTR)(p))
  41. #define FSTRCPY(p1, p2) lstrcpy((LPSTR)(p1), (LPSTR)(p2))
  42. #define FSTRCAT(p1, p2) lstrcat((LPSTR)(p1), (LPSTR)(p2))
  43. //
  44. // MAP_PARAMETER_ID - returns a string corresponding to the database parameter
  45. //
  46. // N.B. id MUST start at 1
  47. //
  48. #define MAP_PARAMETER_ID(id) ParameterNames[(id) - 1]
  49. //
  50. // globally available registry keys
  51. //
  52. extern HKEY ServicesKey; // = INVALID_HANDLE_VALUE;
  53. //
  54. // private prototypes
  55. //
  56. PRIVATE
  57. UINT
  58. CheckRegistryForParameter(
  59. IN UINT ParameterId,
  60. OUT LPBYTE Data,
  61. IN UINT DataLength
  62. );
  63. //
  64. // private data
  65. //
  66. //
  67. // ParameterNames - the names of the registry values corresponding to the
  68. // variables retrieved by SockGetSingleValue.
  69. //
  70. // N.B. These MUST be in order of the CONFIG_ manifests in sockreg.h
  71. //
  72. PRIVATE const LPCSTR ParameterNames[] = {
  73. "HostName",
  74. "Domain",
  75. "SearchList",
  76. "NameServer"
  77. };
  78. //
  79. // functions
  80. //
  81. /*******************************************************************************
  82. *
  83. * GetBoundAdapterList
  84. *
  85. * Gets a list of names of all adapters bound to a protocol (TCP/IP). Returns
  86. * a pointer to an array of pointers to strings - basically an argv list. The
  87. * memory for the strings is concatenated to the array and the array is NULL
  88. * terminated. If Elnkii1 and IbmTok2 are bound to TCP/IP then this function
  89. * will return:
  90. *
  91. * ---> addr of string1 \
  92. * addr of string2 \
  93. * NULL > allocated as one block
  94. * &string1: "Elnkii1" /
  95. * &string2: "IbmTok2" /
  96. *
  97. * ENTRY BindingsSectionKey
  98. * - Open registry handle to a linkage key (e.g. Tcpip\Linkage)
  99. *
  100. * EXIT
  101. *
  102. * RETURNS pointer to argv[] style array, or NULL
  103. *
  104. * ASSUMES
  105. *
  106. ******************************************************************************/
  107. LPSTR* GetBoundAdapterList(HKEY BindingsSectionKey)
  108. {
  109. LPSTR* resultBuffer;
  110. LONG err;
  111. DWORD valueType;
  112. PBYTE valueBuffer = NULL;
  113. DWORD valueLength;
  114. LPSTR* nextResult;
  115. int len;
  116. DWORD resultLength;
  117. LPSTR nextValue;
  118. LPSTR variableData;
  119. DWORD numberOfBindings;
  120. //
  121. // get required size of value buffer
  122. //
  123. valueLength = 0;
  124. resultBuffer = NULL;
  125. err = RegQueryValueEx(BindingsSectionKey,
  126. "Bind",
  127. NULL, // reserved
  128. &valueType,
  129. NULL,
  130. &valueLength
  131. );
  132. if (err != ERROR_SUCCESS) {
  133. goto quit;
  134. }
  135. if (valueType != REG_MULTI_SZ) {
  136. goto quit;
  137. }
  138. if (!valueLength) {
  139. goto quit;
  140. }
  141. valueBuffer = (PBYTE)ALLOCATE_ZERO_MEMORY(valueLength);
  142. if ( valueBuffer == NULL ) {
  143. goto quit;
  144. }
  145. err = RegQueryValueEx(BindingsSectionKey,
  146. "Bind",
  147. NULL, // reserved
  148. &valueType,
  149. valueBuffer,
  150. &valueLength
  151. );
  152. if (err != ERROR_SUCCESS) {
  153. goto quit;
  154. }
  155. resultLength = sizeof(LPSTR); // the NULL at the end of the list
  156. numberOfBindings = 0;
  157. nextValue = (LPSTR)valueBuffer;
  158. while (0 != (len = strlen(nextValue))) {
  159. resultLength += sizeof(LPSTR) + len + 1;
  160. if (!_strnicmp(nextValue, DEVICE_PREFIX, sizeof(DEVICE_PREFIX) - 1)) {
  161. resultLength -= sizeof(DEVICE_PREFIX) - 1;
  162. }
  163. nextValue += len + 1;
  164. ++numberOfBindings;
  165. }
  166. resultBuffer = (LPSTR*)ALLOCATE_ZERO_MEMORY(resultLength);
  167. if ( resultBuffer == NULL ) {
  168. goto quit;
  169. }
  170. nextValue = (LPSTR)valueBuffer;
  171. nextResult = resultBuffer;
  172. variableData = (LPSTR)(((LPSTR*)resultBuffer) + numberOfBindings + 1);
  173. while (numberOfBindings--) {
  174. LPSTR adapterName;
  175. adapterName = nextValue;
  176. if (!_strnicmp(adapterName, DEVICE_PREFIX, sizeof(DEVICE_PREFIX) - 1)) {
  177. adapterName += sizeof(DEVICE_PREFIX) - 1;
  178. }
  179. *nextResult++ = variableData;
  180. strcpy(variableData, adapterName);
  181. while (*variableData) {
  182. ++variableData;
  183. }
  184. ++variableData;
  185. while (*nextValue) {
  186. ++nextValue;
  187. }
  188. ++nextValue;
  189. }
  190. *nextResult = NULL;
  191. quit:
  192. if ( valueBuffer != NULL )
  193. {
  194. FREE_MEMORY(valueBuffer);
  195. }
  196. return resultBuffer;
  197. }
  198. /*******************************************************************************
  199. *
  200. * OpenAdapterKey
  201. *
  202. * Opens one of the 2 per-adapter registry keys: <Adapter>\Parameters\Tcpip, or
  203. * NetBT\Adapters\<Adapter>
  204. *
  205. * ENTRY KeyType - KEY_TCP or KEY_NBT
  206. * Name - pointer to adapter name to use
  207. * Key - pointer to returned key
  208. *
  209. * EXIT Key updated
  210. *
  211. * RETURNS TRUE if success
  212. *
  213. * ASSUMES
  214. *
  215. ******************************************************************************/
  216. BOOL OpenAdapterKey(DWORD KeyType, LPSTR Name, PHKEY Key)
  217. {
  218. LONG err;
  219. CHAR keyName[MAX_ADAPTER_NAME_LENGTH + sizeof("\\Parameters\\Tcpip")];
  220. if ((lstrlen(Name)+sizeof("\\Parameters\\Tcpip")) < ARRAY_ELEMENTS(keyName))
  221. {
  222. if (KeyType == KEY_TCP) {
  223. //
  224. // open the handle to this adapter's TCPIP parameter key
  225. //
  226. strcpy(keyName, Name);
  227. strcat(keyName, "\\Parameters\\Tcpip");
  228. } else if (KeyType == KEY_NBT) {
  229. //
  230. // open the handle to the NetBT\Adapters\<Adapter> handle
  231. //
  232. strcpy(keyName, "NetBT\\Adapters\\");
  233. strcat(keyName, Name);
  234. }
  235. }
  236. else
  237. {
  238. INET_ASSERT((lstrlen(Name)+sizeof("\\Parameters\\Tcpip")) < ARRAY_ELEMENTS(keyName));
  239. return FALSE;
  240. }
  241. err = REGOPENKEY(ServicesKey,
  242. keyName,
  243. Key
  244. );
  245. DEBUG_PRINT( SOCKETS,
  246. INFO,
  247. ("RegOpenKey %s %s %s %d\n",
  248. SERVICES_KEY_NAME, keyName,
  249. (err != ERROR_SUCCESS )? "failed":"success",
  250. GetLastError() ));
  251. return (err == ERROR_SUCCESS);
  252. }
  253. /*******************************************************************************
  254. *
  255. * ReadRegistryDword
  256. *
  257. * Reads a registry value that is stored as a DWORD
  258. *
  259. * ENTRY Key - open registry key where value resides
  260. * ParameterName - name of value to read from registry
  261. * Value - pointer to returned value
  262. *
  263. * EXIT *Value = value read
  264. *
  265. * RETURNS TRUE if success
  266. *
  267. * ASSUMES
  268. *
  269. ******************************************************************************/
  270. BOOL ReadRegistryDword(HKEY Key, LPSTR ParameterName, LPDWORD Value)
  271. {
  272. LONG err;
  273. DWORD valueLength;
  274. DWORD valueType;
  275. valueLength = sizeof(*Value);
  276. err = RegQueryValueEx(Key,
  277. ParameterName,
  278. NULL, // reserved
  279. &valueType,
  280. (LPBYTE)Value,
  281. &valueLength
  282. );
  283. if( (err == ERROR_SUCCESS )
  284. && (valueType == REG_DWORD )
  285. && (valueLength == sizeof(DWORD))) {
  286. return 1;
  287. } else {
  288. DEBUG_PRINT(SOCKETS, INFO,
  289. ("ReadRegistryDword(%s): err=%d\n", ParameterName, err ));
  290. return 0;
  291. }
  292. }
  293. /*******************************************************************************
  294. *
  295. * ReadRegistryString
  296. *
  297. * Reads a registry value that is stored as a string
  298. *
  299. * ENTRY Key - open registry key
  300. * ParameterName - name of value to read from registry
  301. * String - pointer to returned string
  302. * Length - IN: length of String buffer. OUT: length of returned string
  303. *
  304. * EXIT String contains string read
  305. *
  306. * RETURNS TRUE if success
  307. *
  308. * ASSUMES
  309. *
  310. ******************************************************************************/
  311. BOOL
  312. ReadRegistryString(HKEY Key, LPSTR ParameterName, LPSTR String, LPDWORD Length)
  313. {
  314. LONG err;
  315. DWORD valueType;
  316. *String = '\0';
  317. err = RegQueryValueEx(Key,
  318. ParameterName,
  319. NULL, // reserved
  320. &valueType,
  321. (LPBYTE)String,
  322. Length
  323. );
  324. if (err == ERROR_SUCCESS) {
  325. INET_ASSERT(valueType == REG_SZ || valueType == REG_MULTI_SZ);
  326. return (*Length) > sizeof(char);
  327. } else {
  328. DEBUG_PRINT(SOCKETS,
  329. INFO,
  330. ("ReadRegistryString(%s): err=%d\n", ParameterName, err ));
  331. return 0;
  332. }
  333. }
  334. UINT
  335. SockGetSingleValue(
  336. IN UINT ParameterId,
  337. OUT LPBYTE Data,
  338. IN UINT DataLength
  339. )
  340. /*++
  341. Routine Description:
  342. Retrieve parameter from Registry/DHCP/TCPIP
  343. This is what we look for and where:
  344. HostName: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\HostName (Win95)
  345. HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\Hostname (NT)
  346. 2. (SYSTEM.INI:DNS.HostName)* (N/A)
  347. 3. GetComputerName()
  348. DomainName: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\Domain (Win95)
  349. HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\DhcpDomain (NT)
  350. HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\Domain (NT)
  351. 2. (SYSTEM.INI:DNS.DomainName)* (N/A)
  352. 3. DHCP (Win95)
  353. SearchList: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\SearchList (Win95)
  354. HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\SearchList (NT)
  355. 2. (SYSTEM.INI:DNS.DNSDomains)* (N/A)
  356. NameServer: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\NameServer (Win95)
  357. HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\DhcpNameServer (NT)
  358. HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\NameServer (NT)
  359. 2. (SYSTEM.INI:DNS.DNSServers)* (N/A)
  360. 3. DHCP (Win95)
  361. * Entries marked thus are registry backups from SYSTEM.INI until all
  362. keys are moved into registry or if platform is WFW 3.11 (in which
  363. case there is no registry)
  364. ASSUMES 1. Data is big enough to hold the default value (single byte for
  365. strings, dword for dwords)
  366. 2. Registry is accessible from 16-bit code too
  367. Arguments:
  368. ParameterId - identifier of parameter to retrieve
  369. Data - pointer to untyped storage space for parameter
  370. DataLength - length of data returned (in bytes)
  371. Return Value:
  372. UINT
  373. Success - ERROR_SUCCESS
  374. Failure - ERROR_PATH_NOT_FOUND
  375. can't locate required parameter in registry/ini/etc.
  376. --*/
  377. {
  378. UINT error = CheckRegistryForParameter(ParameterId, Data, DataLength);
  379. //
  380. // if the value was not in the registry then we must attempt to get it from
  381. // another place, specific to the particular variable requested
  382. //
  383. if (error != ERROR_SUCCESS) {
  384. if (ParameterId == CONFIG_HOSTNAME) {
  385. //
  386. // on Win32 platform we can call GetComputerName() to provide the
  387. // computer name, which is the default host name, if none is
  388. // specified elsewhere
  389. //
  390. DWORD length;
  391. length = DataLength;
  392. if (!GetComputerName((LPSTR)Data, &length)) {
  393. error = GetLastError();
  394. }
  395. } else if (ParameterId == CONFIG_DOMAIN) {
  396. if (GlobalPlatformType == PLATFORM_TYPE_WIN95) {
  397. // error = GetDomainNameFromDhcp(Data, DataLength);
  398. INET_ASSERT(FALSE && "Not implemented on Win9x; port code from WinInet");
  399. }
  400. } else if (ParameterId == CONFIG_NAME_SERVER) {
  401. if (GlobalPlatformType == PLATFORM_TYPE_WIN95) {
  402. // error = GetDnsServerListFromDhcp(Data, DataLength);
  403. INET_ASSERT(FALSE && "Not implemented on Win9x; port code from WinInet");
  404. }
  405. } else {
  406. //
  407. // the caller is requesting the domain list (or an invalid config
  408. // parameter value?!?). We have nowhere else to get this value -
  409. // return an error
  410. //
  411. error = ERROR_PATH_NOT_FOUND;
  412. }
  413. }
  414. IF_DEBUG(REGISTRY) {
  415. if (error != ERROR_SUCCESS) {
  416. DEBUG_PRINT(SOCKETS, INFO,
  417. ("SockGetSingleValue(%s) returns %d\r",
  418. MAP_PARAMETER_ID(ParameterId),
  419. error
  420. ));
  421. } else {
  422. DEBUG_PRINT(SOCKETS, INFO,
  423. ("SockGetSingleValue(%s) returns \"%s\"\n",
  424. MAP_PARAMETER_ID(ParameterId),
  425. Data
  426. ));
  427. }
  428. }
  429. return error;
  430. }
  431. PRIVATE
  432. UINT
  433. CheckRegistryForParameter(
  434. IN UINT ParameterId,
  435. OUT LPBYTE Data,
  436. IN UINT DataLength
  437. )
  438. /*++
  439. Routine Description:
  440. Retrieve parameter from registry
  441. ASSUMES 1. Data is big enough to hold the default value (single byte for
  442. strings, dword for dwords)
  443. Arguments:
  444. ParameterId - identifier of parameter to retrieve
  445. Data - pointer to untyped storage space for parameter
  446. DataLength - length of data returned (in bytes)
  447. Return Value:
  448. UINT
  449. Success - ERROR_SUCCESS
  450. Failure - ERROR_PATH_NOT_FOUND
  451. ERROR_INSUFFICIENT_BUFFER
  452. --*/
  453. {
  454. HKEY key;
  455. LONG error = REGOPENKEY(HKEY_LOCAL_MACHINE,
  456. (GlobalPlatformType == PLATFORM_TYPE_WINNT)
  457. ? "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
  458. : "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
  459. &key
  460. );
  461. if (error == ERROR_SUCCESS) {
  462. char dhcpBuffer[128]; // arbitrary
  463. LPSTR p;
  464. DWORD length;
  465. DWORD type;
  466. BOOL tryDhcp;
  467. if (GlobalPlatformType == PLATFORM_TYPE_WINNT) {
  468. FSTRCPY(dhcpBuffer, "Dhcp");
  469. p = &dhcpBuffer[sizeof("Dhcp") - 1];
  470. tryDhcp = TRUE;
  471. } else {
  472. p = dhcpBuffer;
  473. tryDhcp = FALSE;
  474. }
  475. FSTRCPY(p, MAP_PARAMETER_ID(ParameterId));
  476. //
  477. // on NT, we look first for the manually-entered variables e.g. "Domain"
  478. // and if not found, we look a second time for the DHCP-configured
  479. // variant, e.g. "DhcpDomain"
  480. //
  481. for (int i = 0; i < 2; ++i) {
  482. //
  483. // if NT, first we try the transient key which is written to the
  484. // registry when we have a dial-up connection
  485. //
  486. if ((i == 0) && (GlobalPlatformType == PLATFORM_TYPE_WINNT)) {
  487. HKEY transientKey;
  488. error = REGOPENKEY(key, "Transient", &transientKey);
  489. if (error == ERROR_SUCCESS) {
  490. length = DataLength;
  491. error = RegQueryValueEx(transientKey,
  492. p,
  493. NULL, // reserved
  494. &type,
  495. Data,
  496. &length
  497. );
  498. REGCLOSEKEY(transientKey);
  499. //
  500. // if we succeeded in retrieving a non-empty string then
  501. // we're done.
  502. //
  503. // We test for > 1 because the registry returns the length
  504. // including the zero-terminator
  505. //
  506. if ((error == ERROR_SUCCESS) && (length > 1)) {
  507. break;
  508. }
  509. }
  510. }
  511. length = DataLength;
  512. error = RegQueryValueEx(key,
  513. p,
  514. NULL, // reserved
  515. &type,
  516. Data,
  517. &length
  518. );
  519. //
  520. // if the key exists, but there is no value then return an error OR
  521. // if we didn't find the key (or value) AND NT then try for the DHCP
  522. // version (Note: We try for DhcpSearchList even though it doesn't
  523. // exist)
  524. //
  525. if ((error != ERROR_SUCCESS)
  526. || (length == 0)
  527. || ((length == 1) && (Data[0] == '\0'))) {
  528. if (tryDhcp) {
  529. p = dhcpBuffer;
  530. tryDhcp = FALSE;
  531. continue;
  532. } else {
  533. error = ERROR_PATH_NOT_FOUND;
  534. break;
  535. }
  536. } else if ((UINT)length > DataLength) {
  537. error = ERROR_INSUFFICIENT_BUFFER;
  538. break;
  539. }
  540. }
  541. REGCLOSEKEY(key);
  542. }
  543. IF_DEBUG(REGISTRY) {
  544. DEBUG_PRINT(SOCKETS, INFO,
  545. ("CheckRegistryForParameter(%s): returning %d\n",
  546. MAP_PARAMETER_ID(ParameterId),
  547. error
  548. ));
  549. }
  550. return (UINT)error;
  551. }
  552. UINT
  553. GetDhcpServerFromDhcp(
  554. IN OUT CAdapterInterface * paiInterface
  555. )
  556. /*******************************************************************************
  557. *
  558. * GetDhcpServerFromDhcp
  559. *
  560. * Updates an CAdapterInterface with the DHCP server from the DHCP info
  561. *
  562. * ENTRY paiInterface - pointer to CAdapterInterface to update
  563. *
  564. * EXIT paiInterface - DhcpServer may be updated
  565. *
  566. * RETURNS TRUE if AdapterInfo->DhcpServer updated
  567. *
  568. * ASSUMES 1. AdapterInfo->Address is valid
  569. *
  570. ******************************************************************************/
  571. {
  572. if ( GlobalPlatformType == PLATFORM_TYPE_WINNT )
  573. {
  574. HKEY key;
  575. if (paiInterface->GetAdapterName() &&
  576. OpenAdapterKey(KEY_TCP, paiInterface->GetAdapterName(), &key))
  577. {
  578. char dhcpServerAddress[4 * 4];
  579. DWORD addressLength;
  580. DWORD fDhcpEnabled = FALSE;
  581. ReadRegistryDword(key,
  582. "EnableDHCP",
  583. &fDhcpEnabled
  584. );
  585. if ( fDhcpEnabled )
  586. {
  587. addressLength = sizeof(dhcpServerAddress);
  588. if (ReadRegistryString(key,
  589. "DhcpServer",
  590. dhcpServerAddress,
  591. &addressLength
  592. ))
  593. {
  594. DWORD ipAddress = _I_inet_addr(dhcpServerAddress);
  595. if ( IS_VALID_NON_LOOPBACK_IP_ADDRESS(ipAddress) )
  596. {
  597. paiInterface->AddDhcpServer(ipAddress);
  598. paiInterface->SetDhcp();
  599. }
  600. }
  601. }
  602. //ReadRegistryDword(key,
  603. // "LeaseObtainedTime",
  604. // &AdapterInfo->LeaseObtained
  605. // );
  606. //ReadRegistryDword(key,
  607. // "LeaseTerminatesTime",
  608. // &AdapterInfo->LeaseExpires
  609. // );
  610. REGCLOSEKEY(key);
  611. return fDhcpEnabled;
  612. }
  613. }
  614. else
  615. {
  616. INET_ASSERT(FALSE && "GetDhcpServerFromDhcp() not implemented on Win9x; port code from WinInet");
  617. }
  618. return FALSE;
  619. }