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.

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