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.

657 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. iphlpapi\lanmap.c
  5. Abstract:
  6. This module maps lan adapter GUIDs to friendly names.
  7. Revision History:
  8. AmritanR Created
  9. --*/
  10. #include "inc.h"
  11. LIST_ENTRY g_LanGuidHashTable[LAN_HASH_TABLE_SIZE];
  12. LIST_ENTRY g_LanNameHashTable[LAN_HASH_TABLE_SIZE];
  13. CRITICAL_SECTION g_LanTableLock;
  14. ULONG
  15. __inline
  16. LAN_NAME_HASH(
  17. IN PWCHAR pwszName
  18. )
  19. {
  20. ULONG ulLen, ulNumChars, i, ulIndex = 0;
  21. ulLen = wcslen(pwszName);
  22. ulNumChars = ulLen < 6 ? ulLen : 6;
  23. ulLen--;
  24. for(i = 0; i < ulNumChars; i++)
  25. {
  26. ulIndex += pwszName[i];
  27. ulIndex += pwszName[ulLen - i];
  28. }
  29. return ulIndex % LAN_HASH_TABLE_SIZE;
  30. }
  31. DWORD
  32. InitLanNameMapper(
  33. VOID
  34. )
  35. {
  36. ULONG i;
  37. for(i = 0; i < LAN_HASH_TABLE_SIZE; i ++)
  38. {
  39. InitializeListHead(&(g_LanGuidHashTable[i]));
  40. InitializeListHead(&(g_LanNameHashTable[i]));
  41. }
  42. InitializeCriticalSection(&g_LanTableLock);
  43. return NO_ERROR;
  44. }
  45. VOID
  46. DeinitLanNameMapper(
  47. VOID
  48. )
  49. {
  50. ULONG i;
  51. for(i = 0; i < LAN_HASH_TABLE_SIZE; i ++)
  52. {
  53. while(!IsListEmpty(&(g_LanGuidHashTable[i])))
  54. {
  55. PLIST_ENTRY pleNode;
  56. pleNode = RemoveHeadList(&(g_LanGuidHashTable[i]));
  57. HeapFree(g_hPrivateHeap,
  58. 0,
  59. pleNode);
  60. }
  61. }
  62. DeleteCriticalSection(&g_LanTableLock);
  63. }
  64. DWORD
  65. OpenConnectionKey(
  66. IN GUID *pGuid,
  67. OUT PHKEY phkey
  68. )
  69. {
  70. WCHAR wszRegPath[256];
  71. WCHAR wszGuid[40];
  72. DWORD dwResult;
  73. *phkey = NULL;
  74. ConvertGuidToString(pGuid,
  75. wszGuid);
  76. wsprintfW(wszRegPath,
  77. CONN_KEY_FORMAT_W,
  78. wszGuid);
  79. dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  80. wszRegPath,
  81. 0,
  82. KEY_READ,
  83. phkey);
  84. return dwResult;
  85. }
  86. DWORD
  87. NhiGetLanConnectionNameFromGuid(
  88. IN GUID *pGuid,
  89. OUT PWCHAR pwszBuffer,
  90. IN OUT PULONG pulBufferLength,
  91. IN BOOL bRefresh,
  92. IN BOOL bCache
  93. )
  94. {
  95. DWORD dwType, dwResult;
  96. HKEY hkey;
  97. PLAN_NODE pNode;
  98. if(*pulBufferLength < (MAX_INTERFACE_NAME_LEN * sizeof(WCHAR)))
  99. {
  100. return ERROR_INSUFFICIENT_BUFFER;
  101. }
  102. if(!bCache)
  103. {
  104. dwResult = OpenConnectionKey(pGuid,
  105. &hkey);
  106. if(dwResult isnot NO_ERROR)
  107. {
  108. return dwResult;
  109. }
  110. dwResult = RegQueryValueExW(hkey,
  111. REG_VALUE_CONN_NAME_W,
  112. NULL,
  113. &dwType,
  114. (LPBYTE)pwszBuffer,
  115. pulBufferLength);
  116. RegCloseKey(hkey);
  117. if(dwResult isnot NO_ERROR)
  118. {
  119. return dwResult;
  120. }
  121. if(dwType isnot REG_SZ)
  122. {
  123. return ERROR_REGISTRY_CORRUPT;
  124. }
  125. return NO_ERROR;
  126. }
  127. //
  128. // Lock the table
  129. //
  130. EnterCriticalSection(&g_LanTableLock);
  131. if(bRefresh)
  132. {
  133. //
  134. // refresh the cache
  135. //
  136. dwResult = UpdateLanLookupTable();
  137. if(dwResult isnot NO_ERROR)
  138. {
  139. LeaveCriticalSection(&g_LanTableLock);
  140. return dwResult;
  141. }
  142. }
  143. //
  144. // Now lookup the table
  145. //
  146. pNode = LookupLanNodeByGuid(pGuid);
  147. if(pNode is NULL)
  148. {
  149. LeaveCriticalSection(&g_LanTableLock);
  150. return ERROR_NOT_FOUND;
  151. }
  152. wcscpy(pwszBuffer,
  153. pNode->rgwcName);
  154. LeaveCriticalSection(&g_LanTableLock);
  155. return NO_ERROR;
  156. }
  157. DWORD
  158. NhiGetGuidFromLanConnectionName(
  159. IN PWCHAR pwszName,
  160. OUT GUID *pGuid,
  161. IN BOOL bRefresh,
  162. IN BOOL bCache
  163. )
  164. {
  165. DWORD dwResult;
  166. PLAN_NODE pNode;
  167. //
  168. // Lock the table
  169. //
  170. EnterCriticalSection(&g_LanTableLock);
  171. if(bRefresh)
  172. {
  173. //
  174. // refresh the cache
  175. //
  176. dwResult = UpdateLanLookupTable();
  177. if(dwResult isnot NO_ERROR)
  178. {
  179. LeaveCriticalSection(&g_LanTableLock);
  180. return dwResult;
  181. }
  182. }
  183. //
  184. // Now lookup the table
  185. //
  186. pNode = LookupLanNodeByName(pwszName);
  187. if(pNode is NULL)
  188. {
  189. LeaveCriticalSection(&g_LanTableLock);
  190. return ERROR_NOT_FOUND;
  191. }
  192. *pGuid = pNode->Guid;
  193. LeaveCriticalSection(&g_LanTableLock);
  194. return NO_ERROR;
  195. }
  196. DWORD
  197. NhiGetLanConnectionDescriptionFromGuid(
  198. IN GUID *pGuid,
  199. OUT PWCHAR pwszBuffer,
  200. IN OUT PULONG pulBufferSize,
  201. IN BOOL bCache,
  202. IN BOOL bRefresh
  203. )
  204. {
  205. return NO_ERROR;
  206. }
  207. PLAN_NODE
  208. LookupLanNodeByGuid(
  209. IN GUID *pGuid
  210. )
  211. /*++
  212. Routine Description:
  213. Looks up the ipip node in the hash table
  214. Locks:
  215. Called with the ipip table lock held
  216. Arguments:
  217. pGuid Guid for the node
  218. Return Value:
  219. LanNode if found
  220. NULL otherwise
  221. --*/
  222. {
  223. ULONG ulIndex;
  224. PLIST_ENTRY pleNode;
  225. ulIndex = LAN_GUID_HASH(pGuid);
  226. for(pleNode = g_LanGuidHashTable[ulIndex].Flink;
  227. pleNode isnot &(g_LanGuidHashTable[ulIndex]);
  228. pleNode = pleNode->Flink)
  229. {
  230. PLAN_NODE pLanNode;
  231. pLanNode = CONTAINING_RECORD(pleNode,
  232. LAN_NODE,
  233. leGuidLink);
  234. if(IsEqualGUID(&(pLanNode->Guid),
  235. pGuid))
  236. {
  237. return pLanNode;
  238. }
  239. }
  240. return NULL;
  241. }
  242. PLAN_NODE
  243. LookupLanNodeByName(
  244. IN PWCHAR pwszName
  245. )
  246. /*++
  247. Routine Description:
  248. Looks up the ipip node in the hash table
  249. Locks:
  250. Called with the ipip table lock held
  251. Arguments:
  252. pwszName Name of the phonebook entry
  253. Return Value:
  254. RasNode if found
  255. NULL otherwise
  256. --*/
  257. {
  258. ULONG ulIndex;
  259. PLIST_ENTRY pleNode;
  260. ulIndex = LAN_NAME_HASH(pwszName);
  261. for(pleNode = g_LanNameHashTable[ulIndex].Flink;
  262. pleNode isnot &(g_LanNameHashTable[ulIndex]);
  263. pleNode = pleNode->Flink)
  264. {
  265. PLAN_NODE pLanNode;
  266. pLanNode = CONTAINING_RECORD(pleNode,
  267. LAN_NODE,
  268. leNameLink);
  269. if(_wcsicmp(pLanNode->rgwcName,
  270. pwszName) is 0)
  271. {
  272. return pLanNode;
  273. }
  274. }
  275. return NULL;
  276. }
  277. DWORD
  278. AddLanNode(
  279. IN GUID *pGuid,
  280. IN PWCHAR pwszName
  281. )
  282. /*++
  283. Routine Description:
  284. Creates a node in the hash table for the given ipip info
  285. Locks:
  286. Called with the LAN table lock held
  287. Arguments:
  288. pInfo Lan name info
  289. Return Value:
  290. NO_ERROR
  291. ERROR_NOT_ENOUGH_MEMORY
  292. --*/
  293. {
  294. ULONG ulGuidIndex, ulNameIndex;
  295. PLAN_NODE pLanNode;
  296. pLanNode = HeapAlloc(g_hPrivateHeap,
  297. 0,
  298. sizeof(LAN_NODE));
  299. if(pLanNode is NULL)
  300. {
  301. return ERROR_NOT_ENOUGH_MEMORY;
  302. }
  303. pLanNode->Guid = *pGuid;
  304. wcscpy(pLanNode->rgwcName,
  305. pwszName);
  306. ulGuidIndex = LAN_GUID_HASH(pGuid);
  307. ulNameIndex = LAN_NAME_HASH(pwszName);
  308. InsertHeadList(&(g_LanGuidHashTable[ulGuidIndex]),
  309. &(pLanNode->leGuidLink));
  310. InsertHeadList(&(g_LanNameHashTable[ulNameIndex]),
  311. &(pLanNode->leNameLink));
  312. return NO_ERROR;
  313. }
  314. VOID
  315. RemoveLanNode(
  316. IN PLAN_NODE pNode
  317. )
  318. /*++
  319. Routine Description:
  320. Removes the given node from the hash tables
  321. Locks:
  322. Called with the LAN table lock held
  323. Arguments:
  324. pNode Node to remove
  325. Return Value:
  326. None
  327. --*/
  328. {
  329. RemoveEntryList(&(pNode->leGuidLink));
  330. RemoveEntryList(&(pNode->leNameLink));
  331. }
  332. DWORD
  333. UpdateLanLookupTable(
  334. VOID
  335. )
  336. /*++
  337. Routine Description:
  338. This routine is invoked to retrieve an array of LAN connections,
  339. Arguments:
  340. None
  341. Return Value:
  342. DWORD - Win32 status code.
  343. --*/
  344. {
  345. BOOLEAN bCleanupOle = TRUE;
  346. ULONG ulConCount;
  347. HRESULT hrErr;
  348. ULONG i, j;
  349. DWORD dwResult;
  350. NETCON_STATUS ncs;
  351. NTSTATUS status;
  352. INetConnection *rgpConArray[32];
  353. NETCON_PROPERTIES *pLanProps;
  354. INetConnectionManager *pConMan = NULL;
  355. IEnumNetConnection *pEnumCon = NULL;
  356. UNICODE_STRING UnicodeString;
  357. hrErr = CoInitializeEx(NULL,
  358. COINIT_MULTITHREADED|COINIT_DISABLE_OLE1DDE);
  359. if(!SUCCEEDED(hrErr))
  360. {
  361. if(hrErr is RPC_E_CHANGED_MODE)
  362. {
  363. bCleanupOle = FALSE;
  364. }
  365. else
  366. {
  367. return ERROR_CAN_NOT_COMPLETE;
  368. }
  369. }
  370. i = 0;
  371. do
  372. {
  373. //
  374. // Instantiate the connection manager
  375. //
  376. hrErr = CoCreateInstance(&CLSID_ConnectionManager,
  377. NULL,
  378. CLSCTX_SERVER,
  379. &IID_INetConnectionManager,
  380. (PVOID*)&pConMan);
  381. if(!SUCCEEDED(hrErr))
  382. {
  383. pConMan = NULL;
  384. break;
  385. }
  386. //
  387. // Instantiate a connection-enumerator
  388. //
  389. hrErr = INetConnectionManager_EnumConnections(pConMan,
  390. NCME_DEFAULT,
  391. &pEnumCon);
  392. if(!SUCCEEDED(hrErr))
  393. {
  394. pEnumCon = NULL;
  395. break;
  396. }
  397. hrErr = CoSetProxyBlanket((IUnknown*)pEnumCon,
  398. RPC_C_AUTHN_WINNT,
  399. RPC_C_AUTHN_NONE,
  400. NULL,
  401. RPC_C_AUTHN_LEVEL_CALL,
  402. RPC_C_IMP_LEVEL_IMPERSONATE,
  403. NULL,
  404. EOAC_NONE);
  405. //
  406. // Enumerate the items
  407. //
  408. while(TRUE)
  409. {
  410. hrErr = IEnumNetConnection_Next(pEnumCon,
  411. sizeof(rgpConArray)/sizeof(rgpConArray[0]),
  412. rgpConArray,
  413. &ulConCount);
  414. if(!SUCCEEDED(hrErr) or
  415. !ulConCount)
  416. {
  417. hrErr = S_OK;
  418. break;
  419. }
  420. //
  421. // Examine the properties for the connections retrieved
  422. //
  423. for(j = 0; j < ulConCount; j++)
  424. {
  425. hrErr = INetConnection_GetProperties(rgpConArray[j],
  426. &pLanProps);
  427. INetConnection_Release(rgpConArray[j]);
  428. if(SUCCEEDED(hrErr) and
  429. pLanProps->MediaType is NCM_LAN)
  430. {
  431. PLAN_NODE pNode;
  432. pNode = LookupLanNodeByGuid(&(pLanProps->guidId));
  433. if(!pNode)
  434. {
  435. dwResult = AddLanNode(&(pLanProps->guidId),
  436. pLanProps->pszwName);
  437. }
  438. else
  439. {
  440. //
  441. // Node exists, if different remove and re-add
  442. //
  443. if(_wcsicmp(pNode->rgwcName,
  444. pLanProps->pszwName) isnot 0)
  445. {
  446. RemoveLanNode(pNode);
  447. dwResult = AddLanNode(&(pLanProps->guidId),
  448. pLanProps->pszwName);
  449. }
  450. }
  451. }
  452. CoTaskMemFree(pLanProps->pszwName);
  453. CoTaskMemFree(pLanProps->pszwDeviceName);
  454. CoTaskMemFree(pLanProps);
  455. }
  456. }
  457. } while(FALSE);
  458. if(pEnumCon)
  459. {
  460. IEnumNetConnection_Release(pEnumCon);
  461. }
  462. if(pConMan)
  463. {
  464. INetConnectionManager_Release(pConMan);
  465. }
  466. if(bCleanupOle)
  467. {
  468. CoUninitialize();
  469. }
  470. return NO_ERROR;
  471. }