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.

729 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. iphlpapi\rasmap.c
  5. Abstract:
  6. This module maps ras dial out and router names to friendly names.
  7. Revision History:
  8. AmritanR Created
  9. --*/
  10. #include "inc.h"
  11. #pragma hdrstop
  12. #include <ifguid.h>
  13. LIST_ENTRY g_RasGuidHashTable[RAS_HASH_TABLE_SIZE];
  14. LIST_ENTRY g_RasNameHashTable[RAS_HASH_TABLE_SIZE];
  15. PRAS_INFO_TABLE g_pRasTable, g_pRouterTable;
  16. CRITICAL_SECTION g_RasTableLock;
  17. WCHAR g_rgwcRasServerIf[MAX_INTERFACE_NAME_LEN + 2];
  18. ULONG g_ulRasServerIfSize;
  19. ULONG
  20. __inline
  21. RAS_NAME_HASH(
  22. IN PWCHAR pwszName
  23. )
  24. {
  25. ULONG ulLen, ulNumChars, i, ulIndex = 0;
  26. ulLen = wcslen(pwszName);
  27. ulNumChars = ulLen < 6 ? ulLen : 6;
  28. ulLen--;
  29. for(i = 0; i < ulNumChars; i++)
  30. {
  31. ulIndex += pwszName[i];
  32. ulIndex += pwszName[ulLen - i];
  33. }
  34. return ulIndex % RAS_HASH_TABLE_SIZE;
  35. }
  36. DWORD
  37. InitRasNameMapper(
  38. VOID
  39. )
  40. {
  41. ULONG i;
  42. for(i = 0; i < RAS_HASH_TABLE_SIZE; i ++)
  43. {
  44. InitializeListHead(&(g_RasNameHashTable[i]));
  45. InitializeListHead(&(g_RasGuidHashTable[i]));
  46. }
  47. InitializeCriticalSection(&g_RasTableLock);
  48. if(!LoadStringW(g_hModule,
  49. STRING_RAS_SERVER_INTERFACE,
  50. g_rgwcRasServerIf,
  51. MAX_INTERFACE_NAME_LEN + 1))
  52. {
  53. return GetLastError();
  54. }
  55. g_ulRasServerIfSize = (wcslen(g_rgwcRasServerIf) + 1) * sizeof(WCHAR);
  56. return NO_ERROR;
  57. }
  58. VOID
  59. DeinitRasNameMapper(
  60. VOID
  61. )
  62. {
  63. ULONG i;
  64. for(i = 0; i < RAS_HASH_TABLE_SIZE; i ++)
  65. {
  66. while(!IsListEmpty(&(g_RasGuidHashTable[i])))
  67. {
  68. PLIST_ENTRY pleNode;
  69. PRAS_NODE pRasNode;
  70. pleNode = RemoveHeadList(&(g_RasGuidHashTable[i]));
  71. pRasNode = CONTAINING_RECORD(pleNode,
  72. RAS_NODE,
  73. leGuidLink);
  74. RemoveEntryList(&(pRasNode->leNameLink));
  75. HeapFree(g_hPrivateHeap,
  76. 0,
  77. pleNode);
  78. }
  79. }
  80. if(g_pRasTable)
  81. {
  82. HeapFree(g_hPrivateHeap,
  83. 0,
  84. g_pRasTable);
  85. g_pRasTable = NULL;
  86. }
  87. DeleteCriticalSection(&g_RasTableLock);
  88. }
  89. DWORD
  90. NhiGetPhonebookNameFromGuid(
  91. IN GUID *pGuid,
  92. OUT PWCHAR pwszBuffer,
  93. IN OUT PDWORD pdwBufferSize,
  94. IN BOOL bRefresh,
  95. IN BOOL bCache
  96. )
  97. {
  98. DWORD dwResult;
  99. PRAS_NODE pNode = NULL;
  100. WCHAR wszRouterPbk[MAX_PATH + 2];
  101. if(IsEqualGUID(pGuid, &GUID_IpRasServerInterface))
  102. {
  103. if(*pdwBufferSize < g_ulRasServerIfSize)
  104. {
  105. *pdwBufferSize = g_ulRasServerIfSize;
  106. return ERROR_INSUFFICIENT_BUFFER;
  107. }
  108. wcscpy(pwszBuffer,
  109. g_rgwcRasServerIf);
  110. *pdwBufferSize = g_ulRasServerIfSize;
  111. return NO_ERROR;
  112. }
  113. //
  114. // Lock the table
  115. //
  116. EnterCriticalSection(&g_RasTableLock);
  117. //
  118. // Check if a refresh of the Ras Table is needed.
  119. //
  120. if((g_pRasTable is NULL) or
  121. bRefresh)
  122. {
  123. //
  124. // refresh the Ras Table cache
  125. //
  126. dwResult = RefreshRasCache(NULL,
  127. &g_pRasTable);
  128. //
  129. // Now lookup the table
  130. //
  131. pNode = LookupRasNodeByGuid(pGuid);
  132. }
  133. //
  134. // Check if a refresh of the Ras Router Table is needed.
  135. //
  136. if(((g_pRouterTable is NULL) and (pNode is NULL)) or
  137. bRefresh)
  138. {
  139. //
  140. // refresh the Router Table cache
  141. //
  142. ZeroMemory(wszRouterPbk, (MAX_PATH + 2) * sizeof(WCHAR));
  143. GetSystemDirectoryW(wszRouterPbk, MAX_PATH + 1);
  144. wcscat(wszRouterPbk, L"\\ras\\router.pbk");
  145. wszRouterPbk[MAX_PATH + 1] = 0;
  146. dwResult = RefreshRasCache(wszRouterPbk,
  147. &g_pRouterTable);
  148. //
  149. // Now lookup the table
  150. //
  151. pNode = LookupRasNodeByGuid(pGuid);
  152. }
  153. if(pNode is NULL)
  154. {
  155. LeaveCriticalSection(&g_RasTableLock);
  156. return ERROR_NOT_FOUND;
  157. }
  158. wcscpy(pwszBuffer,
  159. pNode->rgwcName);
  160. LeaveCriticalSection(&g_RasTableLock);
  161. return NO_ERROR;
  162. }
  163. DWORD
  164. NhiGetGuidFromPhonebookName(
  165. IN PWCHAR pwszName,
  166. OUT GUID *pGuid,
  167. IN BOOL bRefresh,
  168. IN BOOL bCache
  169. )
  170. {
  171. DWORD dwResult;
  172. PRAS_NODE pNode = NULL;
  173. if(_wcsicmp(pwszName, g_rgwcRasServerIf) == 0)
  174. {
  175. //
  176. // Structure copy
  177. //
  178. *pGuid = GUID_IpRasServerInterface;
  179. return NO_ERROR;
  180. }
  181. //
  182. // Lock the table
  183. //
  184. EnterCriticalSection(&g_RasTableLock);
  185. //
  186. // Check if a refresh of the Ras Table is needed.
  187. //
  188. if((g_pRasTable is NULL) or
  189. bRefresh)
  190. {
  191. //
  192. // refresh the Ras Table cache
  193. //
  194. dwResult = RefreshRasCache(NULL,
  195. &g_pRasTable);
  196. //
  197. // Now lookup the table
  198. //
  199. pNode = LookupRasNodeByGuid(pGuid);
  200. }
  201. //
  202. // Check if a refresh of the Ras Router Table is needed.
  203. //
  204. if(((g_pRouterTable is NULL) and (pNode is NULL)) or
  205. bRefresh)
  206. {
  207. //
  208. // refresh the Router Table cache
  209. //
  210. dwResult = RefreshRasCache(L"router.pbk",
  211. &g_pRouterTable);
  212. //
  213. // Now lookup the table
  214. //
  215. pNode = LookupRasNodeByGuid(pGuid);
  216. }
  217. if(pNode is NULL)
  218. {
  219. LeaveCriticalSection(&g_RasTableLock);
  220. return ERROR_NOT_FOUND;
  221. }
  222. *pGuid = pNode->Guid;
  223. LeaveCriticalSection(&g_RasTableLock);
  224. return NO_ERROR;
  225. }
  226. DWORD
  227. NhiGetPhonebookDescriptionFromGuid(
  228. IN GUID *pGuid,
  229. OUT PWCHAR pwszBuffer,
  230. IN OUT PULONG pulBufferSize,
  231. IN BOOL bCache,
  232. IN BOOL bRefresh
  233. )
  234. {
  235. return NO_ERROR;
  236. }
  237. DWORD
  238. RefreshRasCache(
  239. IN PWCHAR pwszPhonebook,
  240. IN OUT RAS_INFO_TABLE **ppTable
  241. )
  242. /*++
  243. Routine Description:
  244. This functions refreshes the ras cache for a given phonebook entry
  245. As a side effect, it also return the table of phonebook entries.
  246. It tries to overwrite the given table, if there is space, otherwise
  247. frees the given table and allocates a new table
  248. Locks:
  249. None needed. If the ppTable points to some global, then the function
  250. needs to be synchronized since it frees the table
  251. Arguments:
  252. pwszPhonebook
  253. ppTable
  254. Return Value:
  255. NO_ERROR
  256. ERROR_NOT_ENOUGH_MEMORY
  257. ERROR_CAN_NOT_COMPLETE
  258. --*/
  259. {
  260. DWORD dwResult;
  261. ULONG ulSize;
  262. ULONG i, ulCount, ulCurrentCount;
  263. if(*ppTable is NULL)
  264. {
  265. //
  266. // If there is no table present, allocate the minimum
  267. //
  268. *ppTable = HeapAlloc(g_hPrivateHeap,
  269. 0,
  270. SIZEOF_RASTABLE(INIT_RAS_ENTRY_COUNT));
  271. if(*ppTable is NULL)
  272. {
  273. return ERROR_NOT_ENOUGH_MEMORY;
  274. }
  275. (*ppTable)->ulTotalCount = INIT_RAS_ENTRY_COUNT;
  276. }
  277. (*ppTable)->ulValidCount = 0;
  278. ulCurrentCount = (*ppTable)->ulTotalCount;
  279. i = 0;
  280. while(i < 3)
  281. {
  282. ulSize = (*ppTable)->ulTotalCount * sizeof(RASENUMENTRYDETAILS);
  283. (*ppTable)->rgEntries[0].dwSize = sizeof(RASENUMENTRYDETAILS);
  284. dwResult = DwEnumEntryDetails(pwszPhonebook,
  285. (*ppTable)->rgEntries,
  286. &ulSize,
  287. &ulCount);
  288. if(dwResult is NO_ERROR)
  289. {
  290. //
  291. // Things are good, update the hash table and move on
  292. //
  293. (*ppTable)->ulValidCount = ulCount;
  294. dwResult = UpdateRasLookupTable(*ppTable);
  295. if(dwResult isnot NO_ERROR)
  296. {
  297. //
  298. // Free the ras table so that we can try next time
  299. //
  300. HeapFree(g_hPrivateHeap,
  301. 0,
  302. *ppTable);
  303. *ppTable = NULL;
  304. return ERROR_CAN_NOT_COMPLETE;
  305. }
  306. break;
  307. }
  308. else
  309. {
  310. //
  311. // Free the old buffer
  312. //
  313. HeapFree(g_hPrivateHeap,
  314. 0,
  315. *ppTable);
  316. *ppTable = NULL;
  317. if(dwResult is ERROR_BUFFER_TOO_SMALL)
  318. {
  319. //
  320. // Go back and recalculate
  321. // See what size RAS required, add an overflow
  322. //
  323. ulCurrentCount += ulCount;
  324. *ppTable = HeapAlloc(g_hPrivateHeap,
  325. 0,
  326. SIZEOF_RASTABLE(ulCurrentCount));
  327. if(*ppTable is NULL)
  328. {
  329. return ERROR_NOT_ENOUGH_MEMORY;
  330. }
  331. (*ppTable)->ulTotalCount = ulCurrentCount;
  332. i++;
  333. }
  334. else
  335. {
  336. return dwResult;
  337. }
  338. }
  339. }
  340. return NO_ERROR;
  341. }
  342. DWORD
  343. UpdateRasLookupTable(
  344. IN PRAS_INFO_TABLE pTable
  345. )
  346. /*++
  347. Routine Description:
  348. Updates the fast lookup table for ras entries
  349. If even one fails, we bail out of the function
  350. Locks:
  351. Called with the RAS lock held
  352. Arguments:
  353. pTable
  354. Return Value:
  355. NO_ERROR
  356. --*/
  357. {
  358. PRAS_NODE pNode;
  359. ULONG i;
  360. DWORD dwResult;
  361. //
  362. // Go through the entries in the phone book table and put them in
  363. // the hash table
  364. //
  365. for(i = 0; i < pTable->ulValidCount; i++)
  366. {
  367. pNode = LookupRasNodeByGuid(&(pTable->rgEntries[i].guidId));
  368. if(!pNode)
  369. {
  370. dwResult = AddRasNode(&(pTable->rgEntries[i]));
  371. if(dwResult isnot NO_ERROR)
  372. {
  373. return dwResult;
  374. }
  375. }
  376. else
  377. {
  378. //
  379. // Node exists, if different remove and re-add
  380. //
  381. if(wcscmp(pNode->rgwcName,
  382. pTable->rgEntries[i].szEntryName) isnot 0)
  383. {
  384. RemoveRasNode(pNode);
  385. dwResult = AddRasNode(&(pTable->rgEntries[i]));
  386. if(dwResult isnot NO_ERROR)
  387. {
  388. return dwResult;
  389. }
  390. }
  391. }
  392. }
  393. return NO_ERROR;
  394. }
  395. PRAS_NODE
  396. LookupRasNodeByGuid(
  397. IN GUID *pGuid
  398. )
  399. /*++
  400. Routine Description:
  401. Looks up the ras node in the hash table
  402. Locks:
  403. Called with the ras table lock held
  404. Arguments:
  405. pGuid Guid for the node
  406. Return Value:
  407. RasNode if found
  408. NULL otherwise
  409. --*/
  410. {
  411. ULONG ulIndex;
  412. PLIST_ENTRY pleNode;
  413. ulIndex = RAS_GUID_HASH(pGuid);
  414. for(pleNode = g_RasGuidHashTable[ulIndex].Flink;
  415. pleNode isnot &(g_RasGuidHashTable[ulIndex]);
  416. pleNode = pleNode->Flink)
  417. {
  418. PRAS_NODE pRasNode;
  419. pRasNode = CONTAINING_RECORD(pleNode,
  420. RAS_NODE,
  421. leGuidLink);
  422. if(IsEqualGUID(&(pRasNode->Guid),
  423. pGuid))
  424. {
  425. return pRasNode;
  426. }
  427. }
  428. return NULL;
  429. }
  430. PRAS_NODE
  431. LookupRasNodeByName(
  432. IN PWCHAR pwszName
  433. )
  434. /*++
  435. Routine Description:
  436. Looks up the ras node in the hash table
  437. Locks:
  438. Called with the ras table lock held
  439. Arguments:
  440. pwszName Name of the phonebook entry
  441. Return Value:
  442. RasNode if found
  443. NULL otherwise
  444. --*/
  445. {
  446. ULONG ulIndex;
  447. PLIST_ENTRY pleNode;
  448. ulIndex = RAS_NAME_HASH(pwszName);
  449. for(pleNode = g_RasNameHashTable[ulIndex].Flink;
  450. pleNode isnot &(g_RasNameHashTable[ulIndex]);
  451. pleNode = pleNode->Flink)
  452. {
  453. PRAS_NODE pRasNode;
  454. pRasNode = CONTAINING_RECORD(pleNode,
  455. RAS_NODE,
  456. leNameLink);
  457. if(_wcsicmp(pRasNode->rgwcName,
  458. pwszName) is 0)
  459. {
  460. return pRasNode;
  461. }
  462. }
  463. return NULL;
  464. }
  465. DWORD
  466. AddRasNode(
  467. IN LPRASENUMENTRYDETAILS pInfo
  468. )
  469. /*++
  470. Routine Description:
  471. Creates a node in the hash table for the given ras info
  472. Locks:
  473. Called with the RAS table lock held
  474. Arguments:
  475. pInfo Phonebook entry info
  476. Return Value:
  477. NO_ERROR
  478. ERROR_NOT_ENOUGH_MEMORY
  479. --*/
  480. {
  481. ULONG ulGuidIndex, ulNameIndex;
  482. PRAS_NODE pRasNode;
  483. pRasNode = HeapAlloc(g_hPrivateHeap,
  484. 0,
  485. sizeof(RAS_NODE));
  486. if(pRasNode is NULL)
  487. {
  488. return ERROR_NOT_ENOUGH_MEMORY;
  489. }
  490. pRasNode->Guid = pInfo->guidId;
  491. wcscpy(pRasNode->rgwcName,
  492. pInfo->szEntryName);
  493. ulGuidIndex = RAS_GUID_HASH(&(pInfo->guidId));
  494. ulNameIndex = RAS_NAME_HASH(pInfo->szEntryName);
  495. InsertHeadList(&(g_RasGuidHashTable[ulGuidIndex]),
  496. &(pRasNode->leGuidLink));
  497. InsertHeadList(&(g_RasNameHashTable[ulNameIndex]),
  498. &(pRasNode->leNameLink));
  499. return NO_ERROR;
  500. }
  501. VOID
  502. RemoveRasNode(
  503. IN PRAS_NODE pNode
  504. )
  505. /*++
  506. Routine Description:
  507. Removes the given node from the hash tables
  508. Locks:
  509. Called with the RAS table lock held
  510. Arguments:
  511. pNode Node to remove
  512. Return Value:
  513. None
  514. --*/
  515. {
  516. RemoveEntryList(&(pNode->leGuidLink));
  517. RemoveEntryList(&(pNode->leNameLink));
  518. }