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.

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