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

1573 lines
42 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. netcfg.c
  5. Abstract:
  6. System network configuration grovelling routines
  7. Author:
  8. Mike Massa (mikemas) May 19, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 05-19-97 created
  13. --*/
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windows.h>
  18. #include <winsock2.h>
  19. #include <cluster.h>
  20. #include <objbase.h>
  21. #include <devguid.h>
  22. #include <netcon.h>
  23. #include <regstr.h>
  24. #include <iphlpapi.h>
  25. //
  26. // Private Constants
  27. //
  28. #define TCPIP_INTERFACES_KEY L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"
  29. #define STRING_ARRAY_DELIMITERS " \t,;"
  30. //
  31. // Allocing and cloning helper functions
  32. //
  33. #define AllocGracefully(status, result, len, name) \
  34. result = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, len); \
  35. if (!result) { \
  36. status = GetLastError(); \
  37. ClRtlLogPrint(LOG_CRITICAL, \
  38. "[ClNet] alloc of %1!hs! (%2!d! bytes) failed, status %3!d!\n", \
  39. name,len,status); \
  40. goto exit_gracefully; \
  41. } else { \
  42. status = ERROR_SUCCESS; \
  43. }
  44. #define CloneAnsiString(Status,AnsiStr,WideResult) { \
  45. SIZE_T len = _mbstrlen(AnsiStr) + 1; \
  46. AllocGracefully(status, WideResult, len * sizeof(WCHAR), # AnsiStr); \
  47. mbstowcs(WideResult, AnsiStr, len); \
  48. }
  49. #define CloneWideString(Status,WideStr,WideResult) { \
  50. SIZE_T _size = (wcslen(WideStr) + 1) * sizeof(WCHAR); \
  51. AllocGracefully(Status, WideResult, _size * sizeof(WCHAR), # WideStr); \
  52. memcpy(WideResult, WideStr, _size); \
  53. }
  54. VOID
  55. ClRtlpDeleteInterfaceInfo(
  56. PCLRTL_NET_INTERFACE_INFO InterfaceInfo
  57. )
  58. {
  59. if (InterfaceInfo) {
  60. LocalFree(InterfaceInfo->InterfaceAddressString);
  61. LocalFree(InterfaceInfo->NetworkAddressString);
  62. LocalFree(InterfaceInfo->NetworkMaskString);
  63. LocalFree(InterfaceInfo);
  64. }
  65. } // DeleteInterfaceInfo
  66. PCLRTL_NET_INTERFACE_INFO
  67. ClRtlpCreateInterfaceInfo(
  68. IN CONST PIP_ADDR_STRING IpAddr
  69. )
  70. {
  71. DWORD status;
  72. PCLRTL_NET_INTERFACE_INFO This = 0;
  73. ULONG Addr, Mask, Network;
  74. Addr = inet_addr(IpAddr->IpAddress.String);
  75. Mask = inet_addr(IpAddr->IpMask.String);
  76. Network = Addr & Mask;
  77. if ( (INADDR_NONE == Addr) ||
  78. (INADDR_NONE == Mask) ||
  79. ((0 == Network) && Addr && Mask)
  80. )
  81. {
  82. ClRtlLogPrint(LOG_CRITICAL,
  83. "[ClNet] Bad ip addr/mask: %1!X! %2!X! %3!X!\n",
  84. Addr,
  85. Mask,
  86. Network
  87. );
  88. status = ERROR_INVALID_PARAMETER;
  89. goto exit_gracefully;
  90. }
  91. AllocGracefully(
  92. status,
  93. This,
  94. sizeof(CLRTL_NET_INTERFACE_INFO),
  95. "CLRTL_NET_INTERFACE_INFO"
  96. );
  97. This->Context = IpAddr -> Context;
  98. This->InterfaceAddress = Addr;
  99. This->NetworkMask = Mask;
  100. This->NetworkAddress = Network;
  101. CloneAnsiString(
  102. status,
  103. IpAddr->IpAddress.String,
  104. This->InterfaceAddressString
  105. );
  106. CloneAnsiString(
  107. status,
  108. IpAddr->IpMask.String,
  109. This->NetworkMaskString
  110. );
  111. status = ClRtlTcpipAddressToString(
  112. Network,
  113. &(This->NetworkAddressString)
  114. );
  115. if (status != ERROR_SUCCESS) {
  116. ClRtlLogPrint(LOG_CRITICAL,
  117. "[ClNet] ClRtlTcpipAddressToString of %1!X! failed, "
  118. "status %2!d!\n",
  119. Network,
  120. status
  121. );
  122. goto exit_gracefully;
  123. }
  124. exit_gracefully:
  125. if (status != ERROR_SUCCESS) {
  126. SetLastError(status);
  127. if (This) {
  128. ClRtlpDeleteInterfaceInfo(This);
  129. This = 0;
  130. }
  131. }
  132. return This;
  133. } // CreateInterfaceInfo
  134. VOID
  135. ClRtlpDeleteAdapter(
  136. PCLRTL_NET_ADAPTER_INFO adapterInfo
  137. )
  138. {
  139. if (adapterInfo) {
  140. PCLRTL_NET_INTERFACE_INFO interfaceInfo;
  141. interfaceInfo = adapterInfo->InterfaceList;
  142. while (interfaceInfo != NULL) {
  143. PCLRTL_NET_INTERFACE_INFO next = interfaceInfo->Next;
  144. ClRtlpDeleteInterfaceInfo(interfaceInfo);
  145. interfaceInfo = next;
  146. }
  147. LocalFree(adapterInfo->DeviceGuid);
  148. LocalFree(adapterInfo->ConnectoidName);
  149. LocalFree(adapterInfo->DeviceName);
  150. LocalFree(adapterInfo->AdapterDomainName);
  151. LocalFree(adapterInfo->DnsServerList);
  152. LocalFree(adapterInfo);
  153. return;
  154. }
  155. } // DeleteAdapter
  156. DWORD
  157. ClRtlpCreateAdapter(
  158. IN PIP_ADAPTER_INFO AdapterInfo,
  159. OUT PCLRTL_NET_ADAPTER_INFO * ppAdapter)
  160. {
  161. DWORD status;
  162. PCLRTL_NET_ADAPTER_INFO adapter = 0;
  163. *ppAdapter = 0;
  164. AllocGracefully(status, adapter, sizeof(*adapter), "NET_ADAPTER_INFO");
  165. ZeroMemory(adapter, sizeof(*adapter));
  166. //
  167. // Assumption here is that:
  168. //
  169. // AdapterName contains Guid in the form {4082164E-A4B5-11D2-89C3-E37CB6BB13FC}
  170. // We need to store it without curly brackets
  171. //
  172. {
  173. SIZE_T len = _mbstrlen(AdapterInfo->AdapterName); // not including 0, but including { and } //
  174. AllocGracefully(status, adapter->DeviceGuid,
  175. sizeof(WCHAR) * (len - 1), "adapter->DeviceGuid");
  176. mbstowcs(adapter->DeviceGuid, AdapterInfo->AdapterName+1, len-1);
  177. adapter->DeviceGuid[len - 2] = UNICODE_NULL;
  178. }
  179. adapter->Index = AdapterInfo->Index;
  180. {
  181. PIP_ADDR_STRING IpAddr = &AdapterInfo->IpAddressList;
  182. while ( IpAddr ) {
  183. PCLRTL_NET_INTERFACE_INFO interfaceInfo;
  184. interfaceInfo = ClRtlpCreateInterfaceInfo(IpAddr);
  185. if (!interfaceInfo) {
  186. // CreateInterfaceInfo logs the error message //
  187. // clean up will be done by DeleteAdapter //
  188. status = GetLastError();
  189. goto exit_gracefully;
  190. }
  191. interfaceInfo->Next = adapter->InterfaceList;
  192. adapter->InterfaceList = interfaceInfo;
  193. ++(adapter->InterfaceCount);
  194. IpAddr = IpAddr -> Next;
  195. }
  196. if (adapter->InterfaceList) {
  197. adapter->InterfaceList->Flags |= CLRTL_NET_INTERFACE_PRIMARY;
  198. }
  199. }
  200. exit_gracefully:
  201. if (status != ERROR_SUCCESS) {
  202. ClRtlpDeleteAdapter(adapter);
  203. } else {
  204. *ppAdapter = adapter;
  205. }
  206. return status;
  207. } // CreateAdapter
  208. PCLRTL_NET_ADAPTER_ENUM
  209. ClRtlpCreateAdapterEnum()
  210. {
  211. DWORD status;
  212. DWORD len;
  213. PIP_ADAPTER_INFO SingleAdapter = 0;
  214. PIP_ADAPTER_INFO AdapterInfo = 0;
  215. PCLRTL_NET_ADAPTER_ENUM AdapterEnum = 0;
  216. len = 0;
  217. for(;;) {
  218. status = GetAdaptersInfo(AdapterInfo, &len);
  219. if (status == ERROR_SUCCESS) {
  220. break;
  221. }
  222. if (status != ERROR_BUFFER_OVERFLOW) {
  223. ClRtlLogPrint(LOG_CRITICAL,
  224. "[ClNet] GetAdaptersInfo returned %1!d!\n", status);
  225. goto exit_gracefully;
  226. }
  227. LocalFree(AdapterInfo); // LocalFree(0) is OK //
  228. AllocGracefully(status, AdapterInfo, len, "IP_ADAPTER_INFO");
  229. }
  230. AllocGracefully(status, AdapterEnum,
  231. sizeof(*AdapterEnum), "PCLRTL_NET_ADAPTER_ENUM");
  232. ZeroMemory(AdapterEnum, sizeof(*AdapterEnum));
  233. SingleAdapter = AdapterInfo;
  234. while (SingleAdapter) {
  235. if (SingleAdapter->Type != MIB_IF_TYPE_LOOPBACK &&
  236. SingleAdapter->Type != MIB_IF_TYPE_PPP &&
  237. SingleAdapter->Type != MIB_IF_TYPE_SLIP )
  238. {
  239. PCLRTL_NET_ADAPTER_INFO Adapter = 0;
  240. status = ClRtlpCreateAdapter(SingleAdapter, &Adapter);
  241. if (status != ERROR_SUCCESS) {
  242. ClRtlLogPrint(LOG_CRITICAL,
  243. "[ClNet] CreateAdapter %1!d! failed, status %2!d!\n",
  244. AdapterEnum->AdapterCount, status);
  245. goto exit_gracefully;
  246. }
  247. //
  248. // Push the adapter into Enumeration List
  249. //
  250. Adapter->Next = AdapterEnum->AdapterList;
  251. AdapterEnum->AdapterList = Adapter;
  252. ++(AdapterEnum->AdapterCount);
  253. }
  254. SingleAdapter = SingleAdapter->Next;
  255. }
  256. exit_gracefully:
  257. if (status != ERROR_SUCCESS) {
  258. SetLastError(status);
  259. ClRtlFreeNetAdapterEnum(AdapterEnum);
  260. AdapterEnum = 0;
  261. }
  262. LocalFree(AdapterInfo);
  263. return AdapterEnum;
  264. } // CreateAdapterEnum
  265. HKEY
  266. ClRtlpFindAdapterKey(
  267. HKEY TcpInterfacesKey,
  268. LPWSTR AdapterGuidString
  269. )
  270. /*++
  271. Routine Description:
  272. Given the adapter GUID, look through the key names under
  273. TCP's Interfaces key and see if a match can be found. The
  274. key names should have the GUID as some part of the name.
  275. Arguments:
  276. TcpInterfacesKey - handle to TCP's interfaces area
  277. AdapterGuidString - pointer to string representing adapter's GUID
  278. Return Value:
  279. Handle to the interface key; otherwise NULL
  280. --*/
  281. {
  282. HKEY AdapterInterfaceKey = NULL;
  283. WCHAR KeyName[REGSTR_MAX_VALUE_LENGTH + 1];
  284. DWORD KeyLength = sizeof( KeyName )/sizeof(TCHAR);
  285. DWORD index = 0;
  286. BOOL FoundMatch = FALSE;
  287. size_t SubStringPos;
  288. DWORD Status;
  289. FILETIME FileTime;
  290. //
  291. // enum the key names under the interfaces
  292. //
  293. do {
  294. Status = RegEnumKeyEx(TcpInterfacesKey,
  295. index,
  296. KeyName,
  297. &KeyLength,
  298. NULL,
  299. NULL,
  300. NULL,
  301. &FileTime);
  302. if ( Status != ERROR_SUCCESS ) {
  303. break;
  304. }
  305. //
  306. // find the beginning of the match
  307. //
  308. _wcsupr( KeyName );
  309. if (wcsstr( KeyName, AdapterGuidString )) {
  310. FoundMatch = TRUE;
  311. break;
  312. }
  313. ++index;
  314. KeyLength = sizeof( KeyName );
  315. } while ( TRUE );
  316. if ( FoundMatch ) {
  317. Status = RegOpenKeyW(TcpInterfacesKey,
  318. KeyName,
  319. &AdapterInterfaceKey);
  320. if ( Status != ERROR_SUCCESS ) {
  321. AdapterInterfaceKey = NULL;
  322. }
  323. }
  324. return AdapterInterfaceKey;
  325. } // FindAdapterKey
  326. DWORD
  327. ClRtlpConvertIPAddressString(
  328. LPSTR DnsServerString,
  329. PDWORD ServerCount,
  330. PDWORD * ServerList)
  331. /*++
  332. Routine Description:
  333. Convert the string of DNS server addresses to binary
  334. Arguments:
  335. DnsServerString - concat'ed string of IP addresses that can be separated
  336. by white space of commas
  337. ServerCount - pointer to DWORD that receives # of addresses detected
  338. ServerList - pointer to DWORD array of converted IP addresses
  339. Return Value:
  340. ERROR_SUCCESS if everything went ok
  341. --*/
  342. {
  343. #define MAX_DNS_SERVER_ADDRESSES 100
  344. PCHAR stringPointer = DnsServerString;
  345. DWORD stringCount = 0;
  346. PDWORD serverList = NULL;
  347. LPSTR stringAddress[ MAX_DNS_SERVER_ADDRESSES ];
  348. //
  349. // count how many addresses are in the string and null terminate them for
  350. // inet_addr
  351. //
  352. stringPointer += strspn(stringPointer, STRING_ARRAY_DELIMITERS);
  353. stringAddress[0] = stringPointer;
  354. stringCount = 1;
  355. while (stringCount < MAX_DNS_SERVER_ADDRESSES &&
  356. (stringPointer = strpbrk(stringPointer, STRING_ARRAY_DELIMITERS)))
  357. {
  358. *stringPointer++ = '\0';
  359. stringPointer += strspn(stringPointer, STRING_ARRAY_DELIMITERS);
  360. stringAddress[stringCount] = stringPointer;
  361. if (*stringPointer) {
  362. ++stringCount;
  363. }
  364. }
  365. serverList = LocalAlloc( LMEM_FIXED, stringCount * sizeof( DWORD ));
  366. if ( serverList == NULL ) {
  367. return GetLastError();
  368. }
  369. *ServerCount = stringCount;
  370. *ServerList = serverList;
  371. while ( stringCount-- ) {
  372. serverList[ stringCount ] = inet_addr( stringAddress[ stringCount ]);
  373. }
  374. return ERROR_SUCCESS;
  375. } // ConvertIPAddressString
  376. typedef BOOLEAN (*ENUM_CALLBACK)(NETCON_PROPERTIES *,
  377. INetConnection*,
  378. PVOID Context);
  379. HRESULT
  380. ClRtlpHrEnumConnections(
  381. IN ENUM_CALLBACK enumCallback,
  382. IN PVOID Context
  383. )
  384. /*++
  385. Routine Description:
  386. Enumerate Connection Manager Connections
  387. Arguments:
  388. enumCallback - callback to be called for every connection
  389. Context - to be passed to a callback
  390. Return Value:
  391. S_OK or HRESULT error code
  392. --*/
  393. {
  394. HRESULT hr;
  395. INetConnectionManager * NcManager = NULL;
  396. IEnumNetConnection * EnumNc = NULL;
  397. INetConnection * NetConnection = NULL;
  398. NETCON_PROPERTIES * NcProps = NULL;
  399. DWORD dwNumConnectionsReturned;
  400. LPWSTR deviceGuidString = NULL;
  401. //
  402. // instantiate a connection mgr object and enum the connections
  403. //
  404. hr = CoCreateInstance((REFCLSID)&CLSID_ConnectionManager,
  405. NULL,
  406. CLSCTX_LOCAL_SERVER,
  407. (REFIID)&IID_INetConnectionManager,
  408. &NcManager);
  409. if (FAILED(hr)) {
  410. ClRtlLogPrint(LOG_CRITICAL,
  411. "[ClNet] INetConnectionManager_CoCreateInstance failed, status %1!X!\n",
  412. hr);
  413. goto exit_gracefully;
  414. }
  415. hr = INetConnectionManager_EnumConnections(NcManager,
  416. NCME_DEFAULT,
  417. &EnumNc);
  418. if (FAILED(hr)) {
  419. ClRtlLogPrint(LOG_CRITICAL,
  420. "[ClNet] INetConnectionManager_EnumConnections failed, status %1!X!\n",
  421. hr);
  422. goto exit_gracefully;
  423. }
  424. IEnumNetConnection_Reset( EnumNc );
  425. while (TRUE) {
  426. hr = IEnumNetConnection_Next(EnumNc,
  427. 1,
  428. &NetConnection,
  429. &dwNumConnectionsReturned);
  430. if (FAILED(hr)) {
  431. ClRtlLogPrint(LOG_CRITICAL,
  432. "[ClNet] IEnumNetConnection_Next failed, status %1!X!\n",
  433. hr);
  434. goto exit_gracefully;
  435. }
  436. if ( dwNumConnectionsReturned == 0 ) {
  437. hr = S_OK;
  438. break;
  439. }
  440. hr = INetConnection_GetProperties(NetConnection, &NcProps);
  441. if (SUCCEEDED( hr )) {
  442. BOOLEAN bCont;
  443. bCont = enumCallback(NcProps, NetConnection, Context);
  444. NcFreeNetconProperties(NcProps);
  445. NcProps = 0;
  446. if (!bCont) {
  447. break;
  448. }
  449. }
  450. INetConnection_Release( NetConnection ); NetConnection = NULL;
  451. }
  452. exit_gracefully:
  453. if (EnumNc != NULL) {
  454. IEnumNetConnection_Release( EnumNc );
  455. }
  456. if (NcManager != NULL) {
  457. INetConnectionManager_Release( NcManager );
  458. }
  459. return hr;
  460. } // HrEnumConnections
  461. VOID
  462. ClRtlpProcessNetConfigurationAdapter(
  463. HKEY TcpInterfacesKey,
  464. PCLRTL_NET_ADAPTER_ENUM adapterEnum,
  465. NETCON_PROPERTIES * NCProps,
  466. LPWSTR DeviceGuidString
  467. )
  468. /*++
  469. Routine Description:
  470. For a given conn mgr object, determine if it is in use by
  471. TCP. This is acheived by comparing the adapter ID in the tcpip
  472. adapter enumeration with the connection object's guid.
  473. Arguments:
  474. TcpInterfacessKey - handle to the root of the TCP\Parameters\Interfaces area
  475. adapterEnum - pointer to enumeration of adapters and their interfaces
  476. actually in use by TCP
  477. NCProps - Connectoid properties.
  478. DeviceGuidString - Guid for the connectoid (and for the associated adapter).
  479. Return Value:
  480. None
  481. --*/
  482. {
  483. HKEY AdaptersKey;
  484. HKEY DHCPAdaptersKey = NULL;
  485. HKEY InterfacesKey = NULL;
  486. PCLRTL_NET_ADAPTER_INFO adapterInfo = NULL;
  487. DWORD valueSize;
  488. DWORD valueType;
  489. LPWSTR valueName;
  490. LPSTR ansiValueName;
  491. BOOL ignoreAdapter = FALSE;
  492. DWORD NTEContext;
  493. DWORD Status;
  494. BOOL dhcpEnabled;
  495. //
  496. // Get the TCP/IP interfaces registry key for this adapter.
  497. //
  498. InterfacesKey = ClRtlpFindAdapterKey(
  499. TcpInterfacesKey,
  500. DeviceGuidString
  501. );
  502. if (InterfacesKey == NULL) {
  503. ClRtlLogPrint(LOG_CRITICAL,
  504. "[ClNet] No Interfaces key for %1!ws!\n",
  505. DeviceGuidString
  506. );
  507. goto exit_gracefully;
  508. }
  509. //
  510. // see if we should be ignoring this adapter per the registry
  511. //
  512. valueSize = sizeof(DWORD);
  513. Status = RegQueryValueExW(InterfacesKey,
  514. L"MSCSHidden",
  515. NULL,
  516. &valueType,
  517. (LPBYTE) &ignoreAdapter,
  518. &valueSize);
  519. if ( Status != ERROR_SUCCESS ) {
  520. ignoreAdapter = FALSE;
  521. }
  522. //
  523. // Search the enum for this adapter.
  524. //
  525. adapterInfo = ClRtlFindNetAdapterById(adapterEnum, DeviceGuidString);
  526. if (adapterInfo != NULL) {
  527. CloneWideString(Status, NCProps->pszwDeviceName, adapterInfo->DeviceName);
  528. CloneWideString(Status, NCProps->pszwName, adapterInfo->ConnectoidName);
  529. //
  530. // Check if this is a hidden netcard.
  531. //
  532. if ( ignoreAdapter ) {
  533. adapterInfo->Flags |= CLRTL_NET_ADAPTER_HIDDEN;
  534. }
  535. //
  536. // Store the NCStatus in the adapter info structure
  537. //
  538. adapterInfo->NCStatus = NCProps->Status;
  539. //
  540. // get the domain name and DHCP server list (if any) associated
  541. // with this adapter. The Domain value has precedence over
  542. // DhcpDomain. If that value is empty/doesn't exist, then use
  543. // DhcpDomain only if EnableDHCP is set to one.
  544. //
  545. Status = ClRtlRegQueryDword(InterfacesKey,
  546. L"EnableDHCP",
  547. &dhcpEnabled,
  548. NULL);
  549. if ( Status != ERROR_SUCCESS ) {
  550. dhcpEnabled = FALSE;
  551. }
  552. valueName = L"Domain";
  553. valueSize = 0;
  554. Status = RegQueryValueExW(InterfacesKey,
  555. valueName,
  556. NULL,
  557. &valueType,
  558. (LPBYTE)NULL,
  559. &valueSize);
  560. if ( Status != ERROR_SUCCESS || valueSize == sizeof(UNICODE_NULL)) {
  561. //
  562. // it didn't exist or the value was NULL. if were using DHCP,
  563. // then check to see if DHCP supplied domain name was
  564. // specified
  565. //
  566. if ( dhcpEnabled ) {
  567. valueName = L"DhcpDomain";
  568. Status = RegQueryValueExW(InterfacesKey,
  569. valueName,
  570. NULL,
  571. &valueType,
  572. (LPBYTE)NULL,
  573. &valueSize);
  574. } else {
  575. Status = ERROR_FILE_NOT_FOUND;
  576. }
  577. }
  578. if ( Status == ERROR_SUCCESS && valueSize > sizeof(UNICODE_NULL)) {
  579. //
  580. // legit domain name was found (somewhere). store it in the
  581. // adapter info
  582. //
  583. adapterInfo->AdapterDomainName = LocalAlloc(LMEM_FIXED,
  584. valueSize +
  585. sizeof(UNICODE_NULL));
  586. if ( adapterInfo->AdapterDomainName != NULL ) {
  587. Status = RegQueryValueExW(InterfacesKey,
  588. valueName,
  589. NULL,
  590. &valueType,
  591. (LPBYTE)adapterInfo->AdapterDomainName,
  592. &valueSize);
  593. if ( Status != ERROR_SUCCESS ) {
  594. LocalFree( adapterInfo->AdapterDomainName );
  595. adapterInfo->AdapterDomainName = NULL;
  596. }
  597. #if CLUSTER_BETA
  598. else {
  599. ClRtlLogPrint(LOG_NOISE,
  600. " %1!ws! key: %2!ws!\n",
  601. valueName,
  602. adapterInfo->AdapterDomainName);
  603. }
  604. #endif
  605. } else {
  606. Status = GetLastError();
  607. }
  608. }
  609. //
  610. // now get the DNS server list in a similar fashion. The
  611. // NameServer value has precedence over DhcpNameServer but we only
  612. // check the DHCP values if DHCP is enabled (just like
  613. // above). Note that we use the Ansi APIs since we need to convert
  614. // the IP addresses into binary form and there is no wide char
  615. // form of inet_addr.
  616. //
  617. ansiValueName = "NameServer";
  618. valueSize = 0;
  619. Status = RegQueryValueExA(InterfacesKey,
  620. ansiValueName,
  621. NULL,
  622. &valueType,
  623. (LPBYTE)NULL,
  624. &valueSize);
  625. if ( Status != ERROR_SUCCESS || valueSize == 1 ) {
  626. if ( dhcpEnabled ) {
  627. ansiValueName = "DhcpNameServer";
  628. Status = RegQueryValueExA(InterfacesKey,
  629. ansiValueName,
  630. NULL,
  631. &valueType,
  632. (LPBYTE)NULL,
  633. &valueSize);
  634. } else {
  635. Status = ERROR_FILE_NOT_FOUND;
  636. }
  637. }
  638. if ( Status == ERROR_SUCCESS && valueSize > 0 ) {
  639. PCHAR nameServerString;
  640. nameServerString = LocalAlloc( LMEM_FIXED, valueSize + 1 );
  641. if ( nameServerString != NULL ) {
  642. Status = RegQueryValueExA(InterfacesKey,
  643. ansiValueName,
  644. NULL,
  645. &valueType,
  646. (LPBYTE)nameServerString,
  647. &valueSize);
  648. if ( Status == ERROR_SUCCESS ) {
  649. DWORD serverCount;
  650. PDWORD serverList;
  651. #if CLUSTER_BETA
  652. ClRtlLogPrint(LOG_NOISE,
  653. " %1!hs! key: %2!hs!\n",
  654. ansiValueName,
  655. nameServerString);
  656. #endif
  657. Status = ClRtlpConvertIPAddressString(
  658. nameServerString,
  659. &serverCount,
  660. &serverList
  661. );
  662. if ( Status == ERROR_SUCCESS ) {
  663. adapterInfo->DnsServerCount = serverCount;
  664. adapterInfo->DnsServerList = serverList;
  665. } else {
  666. adapterInfo->DnsServerCount = 0;
  667. adapterInfo->DnsServerList = NULL;
  668. }
  669. } else {
  670. adapterInfo->DnsServerCount = 0;
  671. adapterInfo->DnsServerList = NULL;
  672. }
  673. LocalFree( nameServerString );
  674. } else {
  675. Status = GetLastError();
  676. }
  677. }
  678. }
  679. if ( adapterInfo == NULL ) {
  680. //
  681. // TCP/IP is not bound to this adapter right now. PnP?
  682. //
  683. ClRtlLogPrint(LOG_UNUSUAL,
  684. "[ClNet] Tcpip is not bound to adapter %1!ws!.\n",
  685. DeviceGuidString
  686. );
  687. }
  688. exit_gracefully:
  689. if (InterfacesKey != NULL) {
  690. RegCloseKey( InterfacesKey );
  691. }
  692. return;
  693. } // ProcessNetConfigurationAdapter
  694. typedef struct _CONFIGURATION_CONTEXT
  695. {
  696. PCLRTL_NET_ADAPTER_ENUM adapterEnum;
  697. HKEY TcpInterfacesKey;
  698. }
  699. CONFIGURATION_CONTEXT, *PCONFIGURATION_CONTEXT;
  700. typedef WCHAR GUIDSTR[32 * 3];
  701. VOID GuidToStr(LPGUID Guid, PWCHAR buf)
  702. {
  703. //
  704. // GUIDs look like this: 4082164E-A4B5-11D2-89C3-E37CB6BB13FC
  705. //
  706. wsprintfW(
  707. buf,
  708. L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  709. Guid->Data1, Guid->Data2, Guid->Data3,
  710. Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3],
  711. Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]
  712. );
  713. }
  714. BOOLEAN
  715. ClRtlpProcessConfigurationCallback(
  716. NETCON_PROPERTIES * NCProps,
  717. INetConnection * NetConnection,
  718. PVOID Context
  719. )
  720. {
  721. PCONFIGURATION_CONTEXT Ctx =
  722. (PCONFIGURATION_CONTEXT) Context;
  723. if ( NCProps->MediaType == NCM_LAN &&
  724. NCProps->Status != NCS_HARDWARE_NOT_PRESENT &&
  725. NCProps->Status != NCS_HARDWARE_DISABLED &&
  726. NCProps->Status != NCS_HARDWARE_MALFUNCTION)
  727. {
  728. GUIDSTR deviceGuidString;
  729. GuidToStr(&NCProps->guidId, deviceGuidString);
  730. ClRtlpProcessNetConfigurationAdapter(
  731. Ctx->TcpInterfacesKey,
  732. Ctx->adapterEnum,
  733. NCProps,
  734. deviceGuidString
  735. );
  736. //
  737. // the strings in the properties struct are either kept or
  738. // or freed in ProcessNetConfigurationAdapter. If they are
  739. // used, then they are freed when the adapter enum is freed
  740. //
  741. }
  742. return TRUE;
  743. } // ProcessConfigurationCallback
  744. PCLRTL_NET_ADAPTER_ENUM
  745. ClRtlEnumNetAdapters(
  746. VOID
  747. )
  748. /*++
  749. Routine Description:
  750. Enumerates all of the installed network adapters to which TCP/IP
  751. is bound.
  752. Arguments:
  753. None.
  754. Return Value:
  755. A pointer to a network adapter enumeration, if successful.
  756. NULL if unsuccessful. Extended error information is available from
  757. GetLastError().
  758. --*/
  759. {
  760. DWORD status;
  761. PCLRTL_NET_ADAPTER_INFO adapterInfo = NULL;
  762. CONFIGURATION_CONTEXT Ctx;
  763. PVOID wTimer;
  764. ZeroMemory(&Ctx, sizeof(Ctx));
  765. //
  766. // First get the list of bound adapters & interfaces from the
  767. // tcpip stack.
  768. //
  769. Ctx.adapterEnum = ClRtlpCreateAdapterEnum();
  770. if (Ctx.adapterEnum == NULL) {
  771. status = GetLastError();
  772. ClRtlLogPrint(LOG_CRITICAL,
  773. "[ClNet] GetTcpipAdaptersAndInterfaces failed %1!u!\n", status);
  774. SetLastError(status);
  775. return(NULL);
  776. }
  777. //
  778. // Open the Services portion of the registry
  779. //
  780. status = RegOpenKeyW(HKEY_LOCAL_MACHINE,
  781. TCPIP_INTERFACES_KEY,
  782. &Ctx.TcpInterfacesKey);
  783. if (status != ERROR_SUCCESS) {
  784. ClRtlLogPrint(LOG_CRITICAL,
  785. "[ClNet] Open of TCP Params key failed - %1!u!\n",
  786. status
  787. );
  788. goto exit_gracefully;
  789. }
  790. // This function might hang, so setting the watchdog timer to 2 mins (2 * 60 * 1000) ms
  791. wTimer = ClRtlSetWatchdogTimer(120000, L"Calling EnumConnections");
  792. status = ClRtlpHrEnumConnections(
  793. ClRtlpProcessConfigurationCallback,
  794. &Ctx
  795. );
  796. ClRtlCancelWatchdogTimer(wTimer);
  797. if (status != S_OK) {
  798. goto exit_gracefully;
  799. }
  800. //
  801. // Finally, ensure that we found a name for each adapter in the enum.
  802. //
  803. for (adapterInfo = Ctx.adapterEnum->AdapterList;
  804. adapterInfo != NULL;
  805. adapterInfo = adapterInfo->Next
  806. )
  807. {
  808. if (adapterInfo->ConnectoidName == NULL) {
  809. if ( adapterInfo->InterfaceCount > 0 ) {
  810. ClRtlLogPrint(LOG_CRITICAL,
  811. "[ClNet] No installed adapter was found for IP address %1!ws!\n",
  812. adapterInfo->InterfaceList->InterfaceAddressString
  813. );
  814. } else {
  815. ClRtlLogPrint(LOG_CRITICAL,
  816. "[ClNet] No installed adapter was found for Tcpip IF entity %1!u!\n",
  817. adapterInfo->Index
  818. );
  819. }
  820. status = ERROR_FILE_NOT_FOUND;
  821. goto exit_gracefully;
  822. }
  823. }
  824. #if CLUSTER_BETA
  825. ClRtlLogPrint(LOG_NOISE,
  826. "[ClNet] Successfully enumerated all adapters and interfaces\n");
  827. #endif
  828. status = ERROR_SUCCESS;
  829. exit_gracefully:
  830. if (Ctx.TcpInterfacesKey != NULL) {
  831. RegCloseKey(Ctx.TcpInterfacesKey);
  832. }
  833. if (status != ERROR_SUCCESS) {
  834. if (Ctx.adapterEnum != NULL) {
  835. ClRtlFreeNetAdapterEnum(Ctx.adapterEnum);
  836. Ctx.adapterEnum = NULL;
  837. }
  838. SetLastError(status);
  839. }
  840. return(Ctx.adapterEnum);
  841. } // ClRtlEnumNetAdapters
  842. VOID
  843. ClRtlFreeNetAdapterEnum(
  844. IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum
  845. )
  846. /*++
  847. Routine Description:
  848. Frees a network adapter enumeration structure.
  849. Arguments:
  850. AdapterEnum - A pointer to the structure to be freed.
  851. Return Value:
  852. None.
  853. --*/
  854. {
  855. if (AdapterEnum) {
  856. PCLRTL_NET_ADAPTER_INFO p = AdapterEnum -> AdapterList;
  857. while (p) {
  858. PCLRTL_NET_ADAPTER_INFO next = p->Next;
  859. ClRtlpDeleteAdapter(p);
  860. p = next;
  861. }
  862. LocalFree(AdapterEnum);
  863. }
  864. } // ClRtlFreeNetAdapterEnum
  865. PCLRTL_NET_ADAPTER_INFO
  866. ClRtlFindNetAdapterById(
  867. PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
  868. LPWSTR AdapterId
  869. )
  870. {
  871. PCLRTL_NET_ADAPTER_INFO adapterInfo;
  872. for ( adapterInfo = AdapterEnum->AdapterList;
  873. adapterInfo != NULL;
  874. adapterInfo = adapterInfo->Next
  875. )
  876. {
  877. if (wcscmp(AdapterId, adapterInfo->DeviceGuid) == 0) {
  878. if (!adapterInfo->Ignore) {
  879. return(adapterInfo);
  880. }
  881. else {
  882. return(NULL);
  883. }
  884. }
  885. }
  886. return(NULL);
  887. } // ClRtlFindNetAdapterById
  888. PCLRTL_NET_INTERFACE_INFO
  889. ClRtlFindNetInterfaceByNetworkAddress(
  890. IN PCLRTL_NET_ADAPTER_INFO AdapterInfo,
  891. IN LPWSTR NetworkAddress
  892. )
  893. {
  894. PCLRTL_NET_INTERFACE_INFO interfaceInfo;
  895. for (interfaceInfo = AdapterInfo->InterfaceList;
  896. interfaceInfo != NULL;
  897. interfaceInfo = interfaceInfo->Next
  898. )
  899. {
  900. if (interfaceInfo->Ignore == FALSE) {
  901. //
  902. // We only look at the primary interface on the
  903. // adapter right now.
  904. //
  905. if (interfaceInfo->Flags & CLRTL_NET_INTERFACE_PRIMARY)
  906. {
  907. if ( wcscmp(
  908. interfaceInfo->NetworkAddressString,
  909. NetworkAddress
  910. ) == 0 )
  911. {
  912. return(interfaceInfo);
  913. }
  914. }
  915. }
  916. }
  917. return(NULL);
  918. } // ClRtlFindNetInterfaceByNetworkAddress
  919. PCLRTL_NET_ADAPTER_INFO
  920. ClRtlFindNetAdapterByNetworkAddress(
  921. IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
  922. IN LPWSTR NetworkAddress,
  923. OUT PCLRTL_NET_INTERFACE_INFO * InterfaceInfo
  924. )
  925. {
  926. PCLRTL_NET_ADAPTER_INFO adapterInfo;
  927. PCLRTL_NET_INTERFACE_INFO interfaceInfo;
  928. for ( adapterInfo = AdapterEnum->AdapterList;
  929. adapterInfo != NULL;
  930. adapterInfo = adapterInfo->Next
  931. )
  932. {
  933. if (adapterInfo->Ignore == FALSE) {
  934. for (interfaceInfo = adapterInfo->InterfaceList;
  935. interfaceInfo != NULL;
  936. interfaceInfo = interfaceInfo->Next
  937. )
  938. {
  939. if (interfaceInfo->Ignore == FALSE) {
  940. //
  941. // We only look at the primary interface on the
  942. // adapter right now.
  943. //
  944. if (interfaceInfo->Flags & CLRTL_NET_INTERFACE_PRIMARY) {
  945. if ( wcscmp(
  946. interfaceInfo->NetworkAddressString,
  947. NetworkAddress
  948. ) == 0 )
  949. {
  950. *InterfaceInfo = interfaceInfo;
  951. return(adapterInfo);
  952. }
  953. }
  954. }
  955. }
  956. }
  957. }
  958. *InterfaceInfo = NULL;
  959. return(NULL);
  960. } // ClRtlFindNetAdapterByNetworkAddress
  961. PCLRTL_NET_ADAPTER_INFO
  962. ClRtlFindNetAdapterByInterfaceAddress(
  963. IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
  964. IN LPWSTR InterfaceAddressString,
  965. OUT PCLRTL_NET_INTERFACE_INFO * InterfaceInfo
  966. )
  967. /*++
  968. For a given IP interface address, find the
  969. adapter that is hosting that address.
  970. --*/
  971. {
  972. PCLRTL_NET_ADAPTER_INFO adapterInfo;
  973. PCLRTL_NET_INTERFACE_INFO interfaceInfo;
  974. for ( adapterInfo = AdapterEnum->AdapterList;
  975. adapterInfo != NULL;
  976. adapterInfo = adapterInfo->Next
  977. )
  978. {
  979. if (adapterInfo->Ignore == FALSE) {
  980. for (interfaceInfo = adapterInfo->InterfaceList;
  981. interfaceInfo != NULL;
  982. interfaceInfo = interfaceInfo->Next
  983. )
  984. {
  985. if (interfaceInfo->Ignore == FALSE ) {
  986. if ( wcscmp( interfaceInfo->InterfaceAddressString,
  987. InterfaceAddressString ) == 0 ) {
  988. *InterfaceInfo = interfaceInfo;
  989. return(adapterInfo);
  990. }
  991. }
  992. }
  993. }
  994. }
  995. *InterfaceInfo = NULL;
  996. return(NULL);
  997. } // ClRtlFindNetAdapterByInterfaceAddress
  998. PCLRTL_NET_INTERFACE_INFO
  999. ClRtlGetPrimaryNetInterface(
  1000. IN PCLRTL_NET_ADAPTER_INFO AdapterInfo
  1001. )
  1002. {
  1003. PCLRTL_NET_INTERFACE_INFO interfaceInfo;
  1004. for (interfaceInfo = AdapterInfo->InterfaceList;
  1005. interfaceInfo != NULL;
  1006. interfaceInfo = interfaceInfo->Next
  1007. )
  1008. {
  1009. if (interfaceInfo->Flags & CLRTL_NET_INTERFACE_PRIMARY) {
  1010. if (!interfaceInfo->Ignore) {
  1011. return(interfaceInfo);
  1012. }
  1013. else {
  1014. return(NULL);
  1015. }
  1016. }
  1017. }
  1018. return(NULL);
  1019. } // ClRtlGetPrimaryNetInterface
  1020. LPWSTR
  1021. ClRtlGetConnectoidName(
  1022. INetConnection * NetConnection
  1023. )
  1024. {
  1025. DWORD status;
  1026. NETCON_PROPERTIES * NcProps = NULL;
  1027. LPWSTR name = NULL;
  1028. status = INetConnection_GetProperties(NetConnection, &NcProps);
  1029. if (SUCCEEDED( status )) {
  1030. DWORD nameLength = (lstrlenW(NcProps->pszwName) * sizeof(WCHAR)) +
  1031. sizeof(UNICODE_NULL);
  1032. name = LocalAlloc(LMEM_FIXED, nameLength);
  1033. if (name != NULL) {
  1034. lstrcpyW(name, NcProps->pszwName);
  1035. }
  1036. else {
  1037. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1038. }
  1039. NcFreeNetconProperties( NcProps );
  1040. }
  1041. else {
  1042. SetLastError(status);
  1043. }
  1044. return(name);
  1045. } // ClRtlGetConnectoidName
  1046. typedef struct _FIND_CONNECTOID_CONTEXT
  1047. {
  1048. GUID ConnectoidGuid;
  1049. LPCWSTR ConnectoidName;
  1050. INetConnection * NetConnection;
  1051. }
  1052. FIND_CONNECTOID_CONTEXT, *PFIND_CONNECTOID_CONTEXT;
  1053. BOOLEAN
  1054. ClRtlpFindConnectoidByGuidCallback(
  1055. NETCON_PROPERTIES * NcProp,
  1056. INetConnection * NetConnection,
  1057. PVOID Context
  1058. )
  1059. {
  1060. PFIND_CONNECTOID_CONTEXT Ctx =
  1061. (PFIND_CONNECTOID_CONTEXT) Context;
  1062. if ( IsEqualGUID(&Ctx->ConnectoidGuid, &NcProp->guidId) ) {
  1063. INetConnection_AddRef(NetConnection);
  1064. Ctx->NetConnection = NetConnection;
  1065. return FALSE;
  1066. }
  1067. return TRUE;
  1068. } // FindConnectoidByGuidCallback
  1069. INetConnection *
  1070. ClRtlFindConnectoidByGuid(
  1071. LPWSTR ConnectoidGuidStr
  1072. )
  1073. {
  1074. FIND_CONNECTOID_CONTEXT Ctx;
  1075. HRESULT hr;
  1076. RPC_STATUS rpcStatus;
  1077. ZeroMemory(&Ctx, sizeof(Ctx));
  1078. rpcStatus = UuidFromStringW (
  1079. (LPWSTR)ConnectoidGuidStr,
  1080. &Ctx.ConnectoidGuid);
  1081. if (rpcStatus != ERROR_SUCCESS) {
  1082. SetLastError( HRESULT_FROM_WIN32(rpcStatus) );
  1083. return 0;
  1084. }
  1085. hr = ClRtlpHrEnumConnections(ClRtlpFindConnectoidByGuidCallback, &Ctx);
  1086. if (hr != S_OK) {
  1087. SetLastError(hr);
  1088. return 0;
  1089. } else {
  1090. return Ctx.NetConnection;
  1091. }
  1092. } // ClRtlFindConnectoidByGuid
  1093. BOOLEAN
  1094. ClRtlpFindConnectoidByNameCallback(
  1095. NETCON_PROPERTIES * NcProp,
  1096. INetConnection * NetConnection,
  1097. PVOID Context
  1098. )
  1099. {
  1100. PFIND_CONNECTOID_CONTEXT Ctx =
  1101. (PFIND_CONNECTOID_CONTEXT) Context;
  1102. if ( lstrcmpiW(Ctx->ConnectoidName, NcProp->pszwName) == 0 ) {
  1103. INetConnection_AddRef(NetConnection);
  1104. Ctx->NetConnection = NetConnection;
  1105. return FALSE;
  1106. }
  1107. return TRUE;
  1108. } // FindConnectoidByNameCallback
  1109. INetConnection *
  1110. ClRtlFindConnectoidByName(
  1111. LPCWSTR ConnectoidName
  1112. )
  1113. {
  1114. FIND_CONNECTOID_CONTEXT Ctx;
  1115. HRESULT hr;
  1116. ZeroMemory(&Ctx, sizeof(Ctx));
  1117. Ctx.ConnectoidName = ConnectoidName;
  1118. hr = ClRtlpHrEnumConnections(ClRtlpFindConnectoidByNameCallback, &Ctx);
  1119. if (hr != S_OK) {
  1120. SetLastError(hr);
  1121. return 0;
  1122. } else {
  1123. return Ctx.NetConnection;
  1124. }
  1125. } // ClRtlFindConnectoidByName
  1126. DWORD
  1127. ClRtlSetConnectoidName(
  1128. INetConnection * NetConnection,
  1129. LPWSTR NewConnectoidName
  1130. )
  1131. /*++
  1132. Routine Description:
  1133. Set the conn mgr object in the connections folder to the
  1134. supplied name. This routine must deal with collisions since
  1135. the name change could be the result of a node joining the
  1136. cluster whose conn obj name in the connection folder had
  1137. changed while the cluster service was stopped on that node.
  1138. If a collision is detected, the existing name is changed to
  1139. have an "(previous)" appended to it.
  1140. Arguments:
  1141. NetConnection - Connect object to set.
  1142. NewConnectoidName - new name
  1143. Return Value:
  1144. Win32 error status
  1145. --*/
  1146. {
  1147. DWORD status = E_UNEXPECTED;
  1148. INetConnection * connectoidObj;
  1149. LPWSTR tempName;
  1150. ULONG iteration = 2;
  1151. GUIDSTR connectoidGuid;
  1152. //
  1153. // first see if there is a collision with the new name. If so,
  1154. // we'll rename the collided name, since we need to make all
  1155. // the cluster connectoids the same.
  1156. //
  1157. connectoidObj = ClRtlFindConnectoidByName( NewConnectoidName );
  1158. if ( connectoidObj != NULL ) {
  1159. NETCON_PROPERTIES * NcProps = NULL;
  1160. status = INetConnection_GetProperties(connectoidObj, &NcProps);
  1161. if (SUCCEEDED( status )) {
  1162. GuidToStr(&NcProps->guidId, connectoidGuid);
  1163. NcFreeNetconProperties( NcProps );
  1164. }
  1165. else {
  1166. wsprintf(
  1167. &(connectoidGuid[0]),
  1168. L"????????-????-????-????-??????????????"
  1169. );
  1170. }
  1171. ClRtlLogPrint(LOG_UNUSUAL,
  1172. "[ClNet] New connectoid name '%1!ws!' collides with name of "
  1173. "existing connectoid (%2!ws!). Renaming existing connectoid.\n",
  1174. NewConnectoidName,
  1175. connectoidGuid
  1176. );
  1177. //
  1178. // allocate enough space for the connectoid name with a trailing
  1179. // "(ddd)". 3 digits for the number should be enough
  1180. //
  1181. tempName = LocalAlloc(
  1182. LMEM_FIXED,
  1183. (wcslen( NewConnectoidName ) + 6) * sizeof(WCHAR)
  1184. );
  1185. if ( tempName == NULL ) {
  1186. INetConnection_Release( connectoidObj );
  1187. return ERROR_OUTOFMEMORY;
  1188. }
  1189. do {
  1190. wsprintf( tempName, L"%s(%u)", NewConnectoidName, iteration++ );
  1191. status = INetConnection_Rename( connectoidObj, tempName );
  1192. } while ( !SUCCEEDED( status ) && iteration <= 999 );
  1193. if ( iteration > 999 ) {
  1194. ClRtlLogPrint(LOG_UNUSUAL,
  1195. "[ClNet] Failed to create a unique name for connectoid "
  1196. "'%1!ws!' (%2!ws!)\n",
  1197. NewConnectoidName,
  1198. connectoidGuid
  1199. );
  1200. INetConnection_Release( connectoidObj );
  1201. return(ERROR_DUP_NAME);
  1202. }
  1203. ClRtlLogPrint(LOG_NOISE,
  1204. "[ClNet] Renamed existing connectoid '%1!ws!' (%2!ws!) to '%3!ws!' "
  1205. "due to a collision with the name of cluster network.\n",
  1206. NewConnectoidName,
  1207. connectoidGuid,
  1208. tempName
  1209. );
  1210. INetConnection_Release( connectoidObj );
  1211. }
  1212. //
  1213. // now set the connectoid to the new name
  1214. //
  1215. status = INetConnection_Rename( NetConnection, NewConnectoidName );
  1216. return status;
  1217. } // ClRtlSetConnectoidName
  1218. DWORD
  1219. ClRtlFindConnectoidByNameAndSetName(
  1220. LPWSTR ConnectoidName,
  1221. LPWSTR NewConnectoidName
  1222. )
  1223. {
  1224. DWORD status = E_UNEXPECTED;
  1225. INetConnection * connectoidObj;
  1226. connectoidObj = ClRtlFindConnectoidByName( ConnectoidName );
  1227. if ( connectoidObj != NULL ) {
  1228. status = ClRtlSetConnectoidName(connectoidObj, NewConnectoidName);
  1229. INetConnection_Release( connectoidObj );
  1230. }
  1231. else {
  1232. status = GetLastError();
  1233. }
  1234. return(status);
  1235. } // ClRtlFindConnectoidByNameAndSetName
  1236. DWORD
  1237. ClRtlFindConnectoidByGuidAndSetName(
  1238. LPWSTR ConnectoidGuid,
  1239. LPWSTR NewConnectoidName
  1240. )
  1241. {
  1242. DWORD status = E_UNEXPECTED;
  1243. INetConnection * connectoidObj;
  1244. connectoidObj = ClRtlFindConnectoidByGuid( ConnectoidGuid );
  1245. if ( connectoidObj != NULL ) {
  1246. status = ClRtlSetConnectoidName(connectoidObj, NewConnectoidName);
  1247. INetConnection_Release( connectoidObj );
  1248. }
  1249. else {
  1250. status = GetLastError();
  1251. }
  1252. return(status);
  1253. } // ClRtlFindConnectoidByGuidAndSetName
  1254.