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.

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