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.

2498 lines
70 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. rasprocs.c
  5. ABSTRACT
  6. RAS utility routines.
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 23-Mar-1995
  9. REVISION HISTORY
  10. Original version from Gurdeep
  11. --*/
  12. #define UNICODE
  13. #define _UNICODE
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <stdlib.h>
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <npapi.h>
  21. #include <ras.h>
  22. #include <raserror.h>
  23. #include <rasman.h>
  24. #include <winsock.h>
  25. #include <acd.h>
  26. #include <tapi.h>
  27. #include <debug.h>
  28. #include <userenv.h>
  29. #include "reg.h"
  30. #include "table.h"
  31. #include "addrmap.h"
  32. #include "access.h"
  33. #include "misc.h"
  34. #include "process.h"
  35. #include "rasprocs.h"
  36. #include "tapiproc.h"
  37. #include "imperson.h"
  38. extern HKEY hkeyCUG;
  39. extern PHASH_TABLE pDisabledAddressesG;
  40. //
  41. // rasdlui command line strings.
  42. //
  43. #define RASAUTOUI_EXE L"rasautou.exe" // .exe name
  44. #define RASAUTOUI_NOENTRY L"rasautou -a \"%s\""
  45. #define RASAUTOUI_CUSTOMDIALENTRY L"rasautou -d \"%s\" -p \"%s\" -e \"%s\""
  46. #define RASAUTOUI_DEFAULTDIALENTRY L"rasautou -a \"%s\" -e \"%s\""
  47. #define RASAUTOUI_DEFAULTDIALENTRY2 L"rasautou -q -a \"%s\" -e \"%s\""
  48. #define RASAUTOUI_REDIALENTRY L"rasautou -r -f \"%s\" -e \"%s\""
  49. //
  50. // DLL module handles for rasapi32.dll and rasman.dll.
  51. //
  52. #define RASAPI_MODULE L"RASAPI32"
  53. HANDLE hRasApiG;
  54. #define RASMAN_MODULE L"RASMAN"
  55. HANDLE hRasManG;
  56. //
  57. // DLL entrypoints for rasapi32.dll.
  58. //
  59. #define RASDIAL "RasDialW"
  60. FARPROC lpfnRasDialG;
  61. #define RASENUMCONNECTIONS "RasEnumConnectionsW"
  62. FARPROC lpfnRasEnumConnectionsG;
  63. #define RASENUMENTRIES "RasEnumEntriesW"
  64. FARPROC lpfnRasEnumEntriesG;
  65. #define RASGETCONNECTSTATUS "RasGetConnectStatusW"
  66. FARPROC lpfnRasGetConnectStatusG;
  67. #define RASGETHPORT "RasGetHport"
  68. FARPROC lpfnRasGetHportG;
  69. #define RASGETPROJECTIONINFO "RasGetProjectionInfoW"
  70. FARPROC lpfnRasGetProjectionInfoG;
  71. #define RASGETENTRYPROPERTIES "RasGetEntryPropertiesW"
  72. FARPROC lpfnRasGetEntryPropertiesG;
  73. #define RASGETAUTODIALADDRESS "RasGetAutodialAddressW"
  74. FARPROC lpfnRasGetAutodialAddressG;
  75. #define RASSETAUTODIALADDRESS "RasSetAutodialAddressW"
  76. FARPROC lpfnRasSetAutodialAddressG;
  77. #define RASENUMAUTODIALADDRESSES "RasEnumAutodialAddressesW"
  78. FARPROC lpfnRasEnumAutodialAddressesG;
  79. #define RASGETAUTODIALENABLE "RasGetAutodialEnableW"
  80. FARPROC lpfnRasGetAutodialEnableG;
  81. #define RASSETAUTODIALENABLE "RasSetAutodialEnableW"
  82. FARPROC lpfnRasSetAutodialEnableG;
  83. #define RASAUTODIALADDRESSTONETWORK "RasAutodialAddressToNetwork"
  84. FARPROC lpfnRasAutodialAddressToNetworkG;
  85. #define RASAUTODIALENTRYTONETWORK "RasAutodialEntryToNetwork"
  86. FARPROC lpfnRasAutodialEntryToNetworkG;
  87. #define RASCONNECTIONNOTIFICATION "RasConnectionNotificationW"
  88. FARPROC lpfnRasConnectionNotificationG;
  89. #define RASGETAUTODIALPARAM "RasGetAutodialParamW"
  90. FARPROC lpfnRasGetAutodialParamG;
  91. #define RASSETAUTODIALPARAM "RasSetAutodialParamW"
  92. FARPROC lpfnRasSetAutodialParamG;
  93. #define RASQUERYSHAREDAUTODIAL "RasQuerySharedAutoDial"
  94. FARPROC lpfnRasQuerySharedAutoDialG;
  95. #define RASQUERYSHAREDCONNECTION "RasQuerySharedConnection"
  96. FARPROC lpfnRasQuerySharedConnectionG;
  97. #define RASQUERYREDIALONLINKFAILURE "RasQueryRedialOnLinkFailure"
  98. FARPROC lpfnRasQueryRedialOnLinkFailureG;
  99. #define RASGETCREDENTIALS "RasGetCredentialsW"
  100. FARPROC lpfnRasGetCredentialsG;
  101. #define RASHANGUP "RasHangUpW"
  102. FARPROC lpfnRasHangUpG;
  103. //
  104. // DLL entrypoints for rasman.dll.
  105. //
  106. #define RASPORTRETRIEVEUSERDATA "RasPortRetrieveUserData"
  107. FARPROC lpfnRasPortRetrieveUserDataG;
  108. #define RASPORTENUMPROTOCOLS "RasPortEnumProtocols"
  109. FARPROC lpfnRasPortEnumProtocolsG;
  110. #define RASPORTENUM "RasPortEnum"
  111. FARPROC lpfnRasPortEnumG;
  112. #define RASINITIALIZE "RasInitialize"
  113. FARPROC lpfnRasInitializeG;
  114. #define RASREFERENCERASMAN "RasReferenceRasman"
  115. FARPROC lpfnRasReferenceRasmanG;
  116. #define RASPORTOPEN "RasPortOpen"
  117. FARPROC lpfnRasPortOpenG;
  118. #define RASPORTCLOSE "RasPortClose"
  119. FARPROC lpfnRasPortCloseG;
  120. #define RASGETINFO "RasGetInfo"
  121. FARPROC lpfnRasGetInfoG;
  122. #define RASGETPORTUSERDATA "RasGetPortUserData"
  123. FARPROC lpfnRasGetPortUserDataG;
  124. #define RASREGISTERREDIALCALLBACK "RasRegisterRedialCallback"
  125. FARPROC lpfnRasRegisterRedialCallbackG;
  126. //
  127. // Hostent cache.
  128. //
  129. #define HOSTENTCACHESIZ 10
  130. typedef struct _HOSTENT_CACHE {
  131. CHAR szDns[ACD_ADDR_INET_LEN];
  132. ULONG ulIpaddr;
  133. } HOSTENT_CACHE, *PHOSTENT_CACHE;
  134. //
  135. // External definitions
  136. //
  137. VOID
  138. AcsRedialOnLinkFailure(
  139. LPSTR lpszPhonebook,
  140. LPSTR lpszEntry);
  141. //
  142. // Global variables
  143. //
  144. CRITICAL_SECTION csRasG;
  145. INT nRasReferencesG;
  146. BOOLEAN fAutoDialRegChangeG;
  147. HKEY hkeyAutoDialRegChangeG;
  148. HANDLE hConnectionEventG = NULL;
  149. HOSTENT_CACHE hostentCacheG[HOSTENTCACHESIZ];
  150. INT iHostentCacheG = 0;
  151. //
  152. // Private structure returned by
  153. // RasPortRetrieveUserData().
  154. //
  155. typedef struct _StoredData {
  156. DWORD arg;
  157. BOOLEAN fAuthenticated;
  158. } StoredData;
  159. //
  160. // External variables
  161. //
  162. extern HANDLE hAcdG;
  163. extern HANDLE hTerminatingG;
  164. BOOLEAN
  165. LoadRasDlls()
  166. {
  167. BOOLEAN fSuccess = FALSE;
  168. SC_HANDLE hSCManager, hService;
  169. SERVICE_STATUS status;
  170. DWORD dwErr, dwcDevices, dwDisp;
  171. //
  172. // Since these DLLs will be loaded/unloaded
  173. // by multiple threads, we must do this under
  174. // a mutex.
  175. //
  176. EnterCriticalSection(&csRasG);
  177. //
  178. // If the DLLs have already been successfully
  179. // loaded, no further processing is necessary.
  180. //
  181. if (nRasReferencesG) {
  182. fSuccess = TRUE;
  183. goto done;
  184. }
  185. #ifdef notdef
  186. //
  187. // Get a service controller handle on
  188. // the rasman service.
  189. //
  190. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  191. if (hSCManager == NULL)
  192. goto done;
  193. hService = OpenService(
  194. hSCManager,
  195. TEXT(RASMAN_SERVICE_NAME),
  196. SERVICE_START|SERVICE_QUERY_STATUS);
  197. if (hService == NULL) {
  198. CloseServiceHandle(hSCManager);
  199. goto done;
  200. }
  201. //
  202. // Start the rasman service if necessary.
  203. //
  204. do {
  205. if (!QueryServiceStatus(hService, &status))
  206. break;
  207. switch (status.dwCurrentState) {
  208. case SERVICE_STOP_PENDING:
  209. case SERVICE_START_PENDING:
  210. Sleep(500);
  211. break;
  212. case SERVICE_STOPPED:
  213. StartService(hService, 0, NULL);
  214. break;
  215. case SERVICE_RUNNING:
  216. break;
  217. }
  218. } while (status.dwCurrentState != SERVICE_RUNNING);
  219. CloseServiceHandle(hService);
  220. CloseServiceHandle(hSCManager);
  221. if (status.dwCurrentState != SERVICE_RUNNING) {
  222. RASAUTO_TRACE("LoadRasDlls: Could not start rasman service");
  223. goto done;
  224. }
  225. #endif
  226. //
  227. // Load rasapi32.dll.
  228. //
  229. hRasApiG = LoadLibrary(RASAPI_MODULE);
  230. if (hRasApiG == NULL) {
  231. RASAUTO_TRACE("LoadRasDlls: couldn't load rasapi32.dll");
  232. goto done;
  233. }
  234. lpfnRasDialG = GetProcAddress(hRasApiG, RASDIAL);
  235. lpfnRasEnumConnectionsG = GetProcAddress(hRasApiG, RASENUMCONNECTIONS);
  236. lpfnRasEnumEntriesG = GetProcAddress(hRasApiG, RASENUMENTRIES);
  237. lpfnRasGetConnectStatusG = GetProcAddress(hRasApiG, RASGETCONNECTSTATUS );
  238. lpfnRasGetHportG = GetProcAddress(hRasApiG, RASGETHPORT);
  239. lpfnRasGetProjectionInfoG = GetProcAddress(hRasApiG, RASGETPROJECTIONINFO);
  240. lpfnRasGetEntryPropertiesG = GetProcAddress(hRasApiG, RASGETENTRYPROPERTIES);
  241. lpfnRasGetAutodialAddressG = GetProcAddress(hRasApiG, RASGETAUTODIALADDRESS);
  242. lpfnRasSetAutodialAddressG = GetProcAddress(hRasApiG, RASSETAUTODIALADDRESS);
  243. lpfnRasEnumAutodialAddressesG = GetProcAddress(hRasApiG, RASENUMAUTODIALADDRESSES);
  244. lpfnRasGetAutodialEnableG = GetProcAddress(hRasApiG, RASGETAUTODIALENABLE);
  245. lpfnRasSetAutodialEnableG = GetProcAddress(hRasApiG, RASSETAUTODIALENABLE);
  246. lpfnRasAutodialAddressToNetworkG =
  247. GetProcAddress(hRasApiG, RASAUTODIALADDRESSTONETWORK);
  248. lpfnRasAutodialEntryToNetworkG =
  249. GetProcAddress(hRasApiG, RASAUTODIALENTRYTONETWORK);
  250. lpfnRasConnectionNotificationG =
  251. GetProcAddress(hRasApiG, RASCONNECTIONNOTIFICATION);
  252. lpfnRasGetAutodialParamG = GetProcAddress(hRasApiG, RASGETAUTODIALPARAM);
  253. lpfnRasSetAutodialParamG = GetProcAddress(hRasApiG, RASSETAUTODIALPARAM);
  254. lpfnRasQuerySharedAutoDialG = GetProcAddress(hRasApiG, RASQUERYSHAREDAUTODIAL);
  255. lpfnRasQuerySharedConnectionG = GetProcAddress(hRasApiG, RASQUERYSHAREDCONNECTION);
  256. lpfnRasQueryRedialOnLinkFailureG = GetProcAddress(hRasApiG, RASQUERYREDIALONLINKFAILURE);
  257. lpfnRasGetCredentialsG = GetProcAddress(hRasApiG, RASGETCREDENTIALS);
  258. lpfnRasHangUpG = GetProcAddress(hRasApiG, RASHANGUP);
  259. if (!lpfnRasEnumConnectionsG || !lpfnRasEnumEntriesG ||
  260. !lpfnRasGetConnectStatusG || !lpfnRasGetHportG ||
  261. !lpfnRasGetProjectionInfoG || !lpfnRasGetAutodialAddressG ||
  262. !lpfnRasSetAutodialAddressG || !lpfnRasEnumAutodialAddressesG ||
  263. !lpfnRasGetAutodialEnableG || !lpfnRasSetAutodialEnableG ||
  264. !lpfnRasAutodialAddressToNetworkG || !lpfnRasAutodialEntryToNetworkG ||
  265. !lpfnRasConnectionNotificationG || !lpfnRasGetAutodialParamG ||
  266. !lpfnRasSetAutodialParamG || !lpfnRasQuerySharedConnectionG ||
  267. !lpfnRasQuerySharedAutoDialG || !lpfnRasQueryRedialOnLinkFailureG ||
  268. !lpfnRasGetCredentialsG || !lpfnRasHangUpG)
  269. {
  270. RASAUTO_TRACE("LoadRasDlls: couldn't find entrypoints in rasapi32.dll");
  271. goto done;
  272. }
  273. //
  274. // Load rasman.dll.
  275. //
  276. hRasManG = LoadLibrary(RASMAN_MODULE);
  277. if (hRasManG == NULL) {
  278. RASAUTO_TRACE("LoadRasDlls: couldn't load rasman.dll");
  279. goto done;
  280. }
  281. lpfnRasPortRetrieveUserDataG = GetProcAddress(
  282. hRasManG,
  283. RASPORTRETRIEVEUSERDATA);
  284. lpfnRasPortEnumProtocolsG = GetProcAddress(hRasManG, RASPORTENUMPROTOCOLS);
  285. lpfnRasPortEnumG = GetProcAddress(hRasManG, RASPORTENUM);
  286. lpfnRasInitializeG = GetProcAddress(hRasManG, RASINITIALIZE);
  287. lpfnRasReferenceRasmanG = GetProcAddress(hRasManG, RASREFERENCERASMAN);
  288. lpfnRasPortOpenG = GetProcAddress(hRasManG, RASPORTOPEN);
  289. lpfnRasPortCloseG = GetProcAddress(hRasManG, RASPORTCLOSE);
  290. lpfnRasGetInfoG = GetProcAddress(hRasManG, RASGETINFO);
  291. lpfnRasGetPortUserDataG = GetProcAddress(hRasManG, RASGETPORTUSERDATA);
  292. lpfnRasRegisterRedialCallbackG = GetProcAddress(
  293. hRasManG,
  294. RASREGISTERREDIALCALLBACK);
  295. if (!lpfnRasPortRetrieveUserDataG ||
  296. !lpfnRasPortEnumProtocolsG ||
  297. !lpfnRasPortEnumG ||
  298. !lpfnRasInitializeG ||
  299. !lpfnRasReferenceRasmanG ||
  300. !lpfnRasPortOpenG ||
  301. !lpfnRasPortCloseG ||
  302. !lpfnRasGetInfoG ||
  303. !lpfnRasGetPortUserDataG ||
  304. !lpfnRasRegisterRedialCallbackG ||
  305. (*lpfnRasInitializeG)() ||
  306. (*lpfnRasReferenceRasmanG)(TRUE))
  307. {
  308. RASAUTO_TRACE("LoadRasDlls: couldn't find entrypoints in rasman.dll");
  309. goto done;
  310. }
  311. //
  312. // rasman will let us know when to invoke redial-on-link-failure
  313. // and for which phonebook entry.
  314. //
  315. SetRedialOnLinkFailureHandler((FARPROC)AcsRedialOnLinkFailure);
  316. RASAUTO_TRACE("LoadRasDlls: set redial-on-link-failure handler");
  317. //
  318. // rasapi32 will let us when new RAS connections
  319. // are created or destroyed by signaling our
  320. // event.
  321. //
  322. dwErr = (DWORD)(*lpfnRasConnectionNotificationG)(
  323. INVALID_HANDLE_VALUE,
  324. hConnectionEventG,
  325. RASCN_Connection|RASCN_Disconnection);
  326. RASAUTO_TRACE1("LoadRasDlls: RasConnectionNotification returned dwErr=%d", dwErr);
  327. fSuccess = !dwErr;
  328. done:
  329. if (fSuccess) {
  330. #ifdef notdef
  331. // for now, we don't need multiple references
  332. nRasReferencesG++;
  333. #endif
  334. nRasReferencesG = 1;
  335. }
  336. else {
  337. if (hRasManG != NULL)
  338. FreeLibrary(hRasManG);
  339. if (hRasApiG != NULL)
  340. FreeLibrary(hRasApiG);
  341. hRasManG = hRasApiG = NULL;
  342. }
  343. LeaveCriticalSection(&csRasG);
  344. return fSuccess;
  345. } // LoadRasDlls
  346. VOID
  347. UnloadRasDlls()
  348. {
  349. DWORD dwErr;
  350. //
  351. // Since these DLLs will be loaded/unloaded
  352. // by multiple threads, we must do this under
  353. // a mutex.
  354. //
  355. EnterCriticalSection(&csRasG);
  356. if (nRasReferencesG) {
  357. //
  358. // Unregister the callback function for
  359. // redial on link failure
  360. //
  361. (void)(*lpfnRasRegisterRedialCallbackG)(NULL);
  362. //
  363. // Inform rasman.dll we are unloading it.
  364. //
  365. (void)(*lpfnRasReferenceRasmanG)(FALSE);
  366. if (hRasApiG != NULL)
  367. FreeLibrary(hRasApiG);
  368. if (hRasManG != NULL)
  369. FreeLibrary(hRasManG);
  370. nRasReferencesG--;
  371. }
  372. LeaveCriticalSection(&csRasG);
  373. } // UnloadRasDlls
  374. BOOLEAN
  375. RasDllsLoaded()
  376. {
  377. BOOLEAN fLoaded;
  378. EnterCriticalSection(&csRasG);
  379. fLoaded = (BOOLEAN)nRasReferencesG;
  380. LeaveCriticalSection(&csRasG);
  381. return fLoaded;
  382. } // RasDllsLoaded
  383. DWORD
  384. ActiveConnections(
  385. IN BOOLEAN fAuthenticated,
  386. OUT LPTSTR **lppEntryNames,
  387. OUT HRASCONN **lpphRasConn
  388. )
  389. /*++
  390. DESCRIPTION
  391. Enumerate the list of active RAS connections, and put the
  392. phone book entry names in lppEntryNames. Return the number
  393. of entries in the list.
  394. ARGUMENTS
  395. fAuthenticated: TRUE if the resulting arrays should contain
  396. only authenticated entries.
  397. lppEntryNames: a pointer which is set to the allocated array
  398. of phone book entry names.
  399. lpphRasConn: a pointer which is set to the allocated array
  400. of RASCONN descriptors corresponding to the phone book
  401. entries.
  402. RETURN VALUE
  403. The number of entries in lppEntryNames.
  404. --*/
  405. {
  406. RASCONN RasCon;
  407. RASCONN *lpRasCon = NULL;
  408. DWORD dwStatus;
  409. DWORD dwSize;
  410. DWORD dwConnections;
  411. DWORD dwRealConnections = 0;
  412. DWORD dwIndex;
  413. RASCONNSTATUS RasConStatus;
  414. HPORT hPort;
  415. PBYTE lpUserData = NULL;
  416. BOOLEAN fEntryAuthenticated;
  417. //
  418. // Initialize return values.
  419. //
  420. if (lppEntryNames != NULL)
  421. *lppEntryNames = NULL;
  422. if (lpphRasConn != NULL)
  423. *lpphRasConn = NULL;
  424. //
  425. // Allow this routine to be called
  426. // even when the RAS dlls are not loaded.
  427. //
  428. if (!RasDllsLoaded())
  429. goto done;
  430. //
  431. // Get the number of active connections. We
  432. // allocate a buffer large enough for one connection
  433. // initially, and reallocate it if it's too small.
  434. //
  435. lpRasCon = LocalAlloc(LPTR, sizeof (RASCONN));
  436. if (lpRasCon == NULL) {
  437. RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
  438. goto done;
  439. }
  440. lpRasCon[0].dwSize = sizeof (RASCONN);
  441. dwSize = sizeof (RASCONN);
  442. dwStatus = (DWORD)(*lpfnRasEnumConnectionsG)(lpRasCon, &dwSize, &dwConnections);
  443. if (dwStatus == ERROR_BUFFER_TOO_SMALL) {
  444. //
  445. // Buffer's too small. Reallocate and try again.
  446. //
  447. LocalFree(lpRasCon);
  448. lpRasCon = LocalAlloc(LPTR, dwSize);
  449. if (lpRasCon == NULL) {
  450. RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
  451. goto done;
  452. }
  453. lpRasCon[0].dwSize = sizeof (RASCONN);
  454. dwStatus = (DWORD)(*lpfnRasEnumConnectionsG)(
  455. lpRasCon,
  456. &dwSize,
  457. &dwConnections);
  458. }
  459. if (dwStatus) {
  460. RASAUTO_TRACE1(
  461. "ActiveConnections: RasEnumConnections failed (dwStatus=0x%x)",
  462. dwStatus);
  463. goto done;
  464. }
  465. //
  466. // Short-circuit the rest if there
  467. // are no connections.
  468. //
  469. if (!dwConnections)
  470. goto done;
  471. //
  472. // Allocate the user's return buffers,
  473. // if necessary.
  474. //
  475. if (lppEntryNames != NULL) {
  476. *lppEntryNames = LocalAlloc(LPTR, (dwConnections+1) * sizeof (LPTSTR));
  477. if (*lppEntryNames == NULL) {
  478. RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
  479. goto done;
  480. }
  481. }
  482. if (lpphRasConn != NULL) {
  483. *lpphRasConn = LocalAlloc(LPTR, (dwConnections+1) * sizeof (HRASCONN));
  484. if (*lpphRasConn == NULL) {
  485. RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
  486. goto done;
  487. }
  488. }
  489. //
  490. // Go through each connection, and
  491. // check to see if the connection's
  492. // passed the authentication phase yet.
  493. //
  494. for (dwIndex = 0; dwIndex < dwConnections; dwIndex++) {
  495. RasConStatus.dwSize = sizeof (RASCONNSTATUS);
  496. dwStatus = (DWORD)(*lpfnRasGetConnectStatusG)(
  497. lpRasCon[dwIndex].hrasconn,
  498. &RasConStatus);
  499. if (dwStatus) {
  500. RASAUTO_TRACE2(
  501. "ActiveConnections: RasGetConnectStatus(%S) failed (dwStatus=0x%x)",
  502. lpRasCon[dwIndex].szEntryName,
  503. dwStatus);
  504. continue;
  505. }
  506. //
  507. // If the connection is not connected,
  508. // then skip it.
  509. //
  510. RASAUTO_TRACE2("ActiveConnections: state for hrasconn 0x%x is %d",
  511. lpRasCon[dwIndex].hrasconn,
  512. RasConStatus.rasconnstate);
  513. //
  514. // If the caller specified only authenticated entries
  515. // and the entry is not yet connected, then skip it.
  516. //
  517. if (fAuthenticated && RasConStatus.rasconnstate != RASCS_Connected)
  518. continue;
  519. if (lppEntryNames != NULL) {
  520. (*lppEntryNames)[dwRealConnections] =
  521. CopyString(lpRasCon[dwIndex].szEntryName);
  522. }
  523. if (lpphRasConn != NULL)
  524. (*lpphRasConn)[dwRealConnections] = lpRasCon[dwIndex].hrasconn;
  525. RASAUTO_TRACE2(
  526. "ActiveConnections: (%S, 0x%x)",
  527. lpRasCon[dwIndex].szEntryName,
  528. lpRasCon[dwIndex].hrasconn);
  529. dwRealConnections++;
  530. }
  531. done:
  532. if (lpRasCon != NULL)
  533. LocalFree(lpRasCon);
  534. if (lpUserData != NULL)
  535. LocalFree(lpUserData);
  536. if (!dwRealConnections) {
  537. if (lppEntryNames != NULL) {
  538. if (*lppEntryNames != NULL) {
  539. LocalFree(*lppEntryNames);
  540. *lppEntryNames = NULL;
  541. }
  542. }
  543. if (lpphRasConn != NULL) {
  544. if (*lpphRasConn != NULL) {
  545. LocalFree(*lpphRasConn);
  546. *lpphRasConn = NULL;
  547. }
  548. }
  549. }
  550. return dwRealConnections;
  551. } // ActiveConnections
  552. LPTSTR
  553. AddressToNetwork(
  554. LPTSTR pszAddress
  555. )
  556. {
  557. DWORD dwErr, dwSize;
  558. LPTSTR pszNetwork = NULL;
  559. //
  560. // Map an address to a network name
  561. // by calling a (currently) private rasapi32 API.
  562. //
  563. dwSize = 0;
  564. dwErr = (DWORD)(*lpfnRasAutodialAddressToNetworkG)(pszAddress, NULL, &dwSize);
  565. if (dwErr)
  566. goto done;
  567. pszNetwork = LocalAlloc(LPTR, dwSize);
  568. if (pszNetwork == NULL) {
  569. dwErr = GetLastError();
  570. goto done;
  571. }
  572. dwErr = (DWORD)(*lpfnRasAutodialAddressToNetworkG)(
  573. pszAddress,
  574. pszNetwork,
  575. &dwSize);
  576. done:
  577. return (!dwErr ? pszNetwork : NULL);
  578. } // AddressToNetwork
  579. LPTSTR
  580. EntryToNetwork(
  581. LPTSTR pszEntry
  582. )
  583. {
  584. DWORD dwErr, dwSize;
  585. LPTSTR pszNetwork = NULL;
  586. //
  587. // Map an address to a network name
  588. // by calling a (currently) private rasapi32 API.
  589. //
  590. dwSize = 0;
  591. dwErr = (DWORD)(*lpfnRasAutodialEntryToNetworkG)(pszEntry, NULL, &dwSize);
  592. if (dwErr)
  593. goto done;
  594. pszNetwork = LocalAlloc(LPTR, dwSize);
  595. if (pszNetwork == NULL) {
  596. dwErr = GetLastError();
  597. goto done;
  598. }
  599. dwErr = (DWORD)(*lpfnRasAutodialEntryToNetworkG)(
  600. pszEntry,
  601. pszNetwork,
  602. &dwSize);
  603. done:
  604. return (!dwErr ? pszNetwork : NULL);
  605. } // EntryToNetwork
  606. DWORD
  607. AutoDialEnabled(
  608. IN PBOOLEAN lpfEnabled
  609. )
  610. {
  611. DWORD dwErr, dwLocationID;
  612. BOOL fEnabled;
  613. //
  614. // If there is no dialing location
  615. // defined, then return FALSE.
  616. //
  617. dwErr = TapiCurrentDialingLocation(&dwLocationID);
  618. if (dwErr) {
  619. *lpfEnabled = FALSE;
  620. return 0;
  621. }
  622. dwErr = (DWORD)(*lpfnRasGetAutodialEnableG)(dwLocationID, &fEnabled);
  623. if (dwErr)
  624. return dwErr;
  625. *lpfEnabled = (BOOLEAN)fEnabled;
  626. return 0;
  627. } // AutoDialEnabled
  628. DWORD
  629. DisableAutoDial()
  630. {
  631. DWORD dwErr, dwLocationID;
  632. dwErr = TapiCurrentDialingLocation(&dwLocationID);
  633. if (dwErr)
  634. return dwErr;
  635. return (DWORD)(*lpfnRasSetAutodialEnableG)(dwLocationID, (BOOL)FALSE);
  636. } // DisableAutoDial
  637. BOOLEAN
  638. PortAvailable(
  639. IN LPTSTR lpszDeviceType,
  640. IN LPTSTR lpszDeviceName
  641. )
  642. /*++
  643. DESCRIPTION
  644. Determines whether there is a free port
  645. available to dial the specified entry.
  646. ARGUMENTS
  647. lpszDeviceType: a pointer to the device type string
  648. lpszDeviceName: a pointer to the device name string
  649. RETURN VALUE
  650. TRUE if one or more of the correct port
  651. type is free; FALSE otherwise.
  652. --*/
  653. {
  654. DWORD dwErr;
  655. DWORD dwSize = 0,
  656. dwEntries, i;
  657. RASMAN_PORT *pPorts = NULL;
  658. BOOLEAN fFound = FALSE,
  659. fOtherType;
  660. BOOLEAN fTypeMatch, fNameMatch;
  661. LPSTR lpszAnsiDeviceType = NULL,
  662. lpszAnsiDeviceName = NULL;
  663. //
  664. // If fOtherType is TRUE, then we compare
  665. // the RASMAN media type with the device type.
  666. //
  667. fOtherType = (_wcsicmp(lpszDeviceType, RASDT_Modem) &&
  668. _wcsicmp(lpszDeviceType, RASDT_Isdn) &&
  669. _wcsicmp(lpszDeviceType, RASDT_X25) &&
  670. _wcsicmp(lpszDeviceType, L"VPN"));
  671. //
  672. // Convert lpszDeviceType to Ansi so
  673. // we can compare with rasman's version.
  674. //
  675. lpszAnsiDeviceType = UnicodeStringToAnsiString(
  676. lpszDeviceType,
  677. NULL,
  678. 0);
  679. if (lpszAnsiDeviceType == NULL)
  680. goto done;
  681. lpszAnsiDeviceName = UnicodeStringToAnsiString(
  682. lpszDeviceName,
  683. NULL,
  684. 0);
  685. if (lpszAnsiDeviceName == NULL)
  686. goto done;
  687. //
  688. // Get a list of ports.
  689. //
  690. dwErr = (DWORD)(*lpfnRasPortEnumG)(NULL, NULL, &dwSize, &dwEntries);
  691. if (!dwErr || dwErr != ERROR_BUFFER_TOO_SMALL) {
  692. RASAUTO_TRACE1("PortAvailable: RasPortEnum failed (dwErr=%d)", dwErr);
  693. goto done;
  694. }
  695. pPorts = LocalAlloc(LPTR, dwSize);
  696. if (pPorts == NULL) {
  697. RASAUTO_TRACE("PortAvailable: LocalAlloc failed");
  698. goto done;
  699. }
  700. dwErr = (DWORD)(*lpfnRasPortEnumG)(NULL, pPorts, &dwSize, &dwEntries);
  701. if (dwErr) {
  702. RASAUTO_TRACE1("PortAvailable: RasPortEnum failed (dwErr=%d)", dwErr);
  703. goto done;
  704. }
  705. for (i = 0; i < dwEntries; i++) {
  706. RASMAN_INFO info;
  707. RASAUTO_TRACE6(
  708. "PortAvailable: lpszAnsiDeviceType=%s, lpszAnsiDeviceName=%s, "
  709. "media=%s, type=%s, name=%s, usage=%d",
  710. lpszAnsiDeviceType,
  711. lpszAnsiDeviceName,
  712. pPorts[i].P_MediaName,
  713. pPorts[i].P_DeviceType,
  714. pPorts[i].P_DeviceName,
  715. pPorts[i].P_ConfiguredUsage);
  716. RASAUTO_TRACE2("PortAvailable: status=%d, current usage=%d",
  717. pPorts[i].P_Status,
  718. pPorts[i].P_CurrentUsage);
  719. //
  720. // Only interested in dial-out and biplex ports.
  721. //
  722. if (!(pPorts[i].P_ConfiguredUsage & CALL_OUT)
  723. && !(pPorts[i].P_ConfiguredUsage & CALL_OUT_ONLY))
  724. continue;
  725. RtlZeroMemory(&info, sizeof (info));
  726. //
  727. // If the port has already been opened for call out
  728. // fail the call.
  729. //
  730. ZeroMemory(&info, sizeof(RASMAN_INFO));
  731. dwErr = RasGetInfo(NULL,
  732. pPorts[i].P_Handle,
  733. &info);
  734. if(NO_ERROR == dwErr)
  735. {
  736. if(info.RI_dwFlags & RASMAN_OPEN_CALLOUT)
  737. {
  738. RASAUTO_TRACE("Port already open for call out");
  739. continue;
  740. }
  741. }
  742. if (pPorts[i].P_Status == OPEN) {
  743. dwErr = (DWORD)(*lpfnRasGetInfoG)(NULL, pPorts[i].P_Handle, &info);
  744. if (dwErr) {
  745. RASAUTO_TRACE1("PortAvailable: RasGetInfo failed (dwErr=%d)", dwErr);
  746. goto statecheck;
  747. }
  748. }
  749. #if 0
  750. //
  751. // Determine if the connection associated with a
  752. // disconnected port has gone away. In this case,
  753. // we can close the port and attempt to reopen
  754. // it. This is essentially what rasapi32/RasDial()
  755. // when it determines if a port is available for
  756. // dialing out.
  757. //
  758. if (pPorts[i].P_Status == OPEN &&
  759. info.RI_ConnState == DISCONNECTED &&
  760. info.RI_ConnectionHandle)
  761. {
  762. RASCONNSTATE connstate;
  763. DWORD dwSize = sizeof (RASCONNSTATE);
  764. RASAUTO_TRACE1(
  765. "PortAvailable: Open disconnected port %d found",
  766. pPorts[i].P_Handle);
  767. dwErr = (DWORD)(*lpfnRasGetPortUserDataG)(
  768. pPorts[i].P_Handle,
  769. 3, // PORT_CONNSTATE_INDEX
  770. &connstate,
  771. &dwSize);
  772. RASAUTO_TRACE2(
  773. "PortAvailable: RasGetPortUserData(%d), connstate=%d",
  774. dwErr,
  775. connstate);
  776. if (!dwErr &&
  777. (connstate < RASCS_PrepareForCallback ||
  778. connstate > RASCS_WaitForCallback))
  779. {
  780. RASAUTO_TRACE1(
  781. "PortAvailable: RasPortClose(%d)...",
  782. pPorts[i].P_Handle);
  783. dwErr = (DWORD)(*lpfnRasPortCloseG)(pPorts[i].P_Handle);
  784. RASAUTO_TRACE1("PortAvailable: RasPortClose done(%d)", dwErr);
  785. //
  786. // Since we've closed the port,
  787. // update the P_Status field manually.
  788. //
  789. if (!dwErr)
  790. pPorts[i].P_Status = CLOSED;
  791. }
  792. }
  793. #endif
  794. //
  795. // Only interested in dial-out ports if the port
  796. // is closed. Biplex port opens, on the other
  797. // hand, may succeed even if the port is
  798. // open.
  799. //
  800. statecheck:
  801. if (pPorts[i].P_ConfiguredUsage == CALL_OUT
  802. && pPorts[i].P_Status != CLOSED)
  803. {
  804. RASAUTO_TRACE("Port is not available for call_out");
  805. continue;
  806. }
  807. fTypeMatch =
  808. (!_stricmp(lpszAnsiDeviceType, pPorts[i].P_DeviceType)) ||
  809. (fOtherType && !_stricmp(lpszAnsiDeviceType, pPorts[i].P_MediaName));
  810. fNameMatch = !_stricmp(lpszAnsiDeviceName, pPorts[i].P_DeviceName);
  811. if (fTypeMatch && fNameMatch) {
  812. fFound = TRUE;
  813. }
  814. }
  815. done:
  816. //
  817. // Free resources.
  818. //
  819. if (lpszAnsiDeviceType != NULL)
  820. LocalFree(lpszAnsiDeviceType);
  821. if (lpszAnsiDeviceName != NULL)
  822. LocalFree(lpszAnsiDeviceName);
  823. if (pPorts != NULL)
  824. LocalFree(pPorts);
  825. return fFound;
  826. } // PortAvailable
  827. DWORD
  828. DisableAddress(PACD_ADDR pAddr)
  829. {
  830. DWORD retcode = SUCCESS;
  831. LPTSTR pszAddress = NULL;
  832. LockDisabledAddresses();
  833. ASSERT(NULL != pDisabledAddressesG);
  834. pszAddress = AddressToUnicodeString(pAddr);
  835. if(NULL == pszAddress)
  836. {
  837. retcode = ERROR_NOT_ENOUGH_MEMORY;
  838. goto done;
  839. }
  840. PutTableEntry(pDisabledAddressesG, pszAddress, NULL);
  841. done:
  842. if(NULL != pszAddress)
  843. {
  844. LocalFree(pszAddress);
  845. }
  846. UnlockDisabledAddresses();
  847. return retcode;
  848. }
  849. BOOLEAN
  850. StartAutoDialer(
  851. IN HANDLE hProcess,
  852. IN PACD_ADDR pAddr,
  853. IN LPTSTR lpAddress,
  854. IN LPTSTR lpEntryName,
  855. IN BOOLEAN fSharedAccess,
  856. OUT PBOOLEAN pfInvalidEntry
  857. )
  858. {
  859. NTSTATUS status;
  860. BOOLEAN fSuccess = FALSE, fEntryFound = FALSE;
  861. BOOLEAN fUseRasDial, fDialerPresent, fDialerKilled;
  862. DWORD dwStatus, dwSize, dwIndex, dwEntries, dwCount = 0;
  863. TCHAR *pszCmdLine = NULL;
  864. STARTUPINFO StartupInfo;
  865. PROCESS_INFORMATION ProcessInfo;
  866. DWORD dwPreConnections, dwConnections;
  867. DWORD dwExitCode = STILL_ACTIVE;
  868. HANDLE hToken;
  869. IO_STATUS_BLOCK ioStatusBlock;
  870. ACD_STATUS connStatus;
  871. DWORD dwErr;
  872. BOOL fDisableAddress = FALSE;
  873. PVOID pEnvBlock = NULL;
  874. //
  875. // Initialization of various variables.
  876. //
  877. *pfInvalidEntry = FALSE;
  878. memset(&StartupInfo, 0, sizeof (StartupInfo));
  879. memset(&ProcessInfo, 0, sizeof (ProcessInfo));
  880. StartupInfo.cb = sizeof(StartupInfo);
  881. StartupInfo.lpDesktop = TEXT("winsta0\\default");
  882. //
  883. // Read the phonebook entry to determine whether
  884. // we need to load a custom AutoDial UI.
  885. //
  886. if (lpEntryName != NULL) {
  887. DWORD dwIgnore;
  888. LPRASENTRY lpEntry;
  889. dwErr = (DWORD)(*lpfnRasGetEntryPropertiesG)(
  890. NULL,
  891. lpEntryName,
  892. NULL,
  893. &dwSize,
  894. NULL,
  895. &dwIgnore);
  896. if (dwErr == ERROR_CANNOT_FIND_PHONEBOOK_ENTRY) {
  897. //
  898. // If the phonebook entry has been renamed
  899. // or deleted, then ask again for an entry.
  900. //
  901. lpEntryName = NULL;
  902. dwErr = 0;
  903. goto fmtcmd;
  904. }
  905. else if (dwErr != ERROR_BUFFER_TOO_SMALL) {
  906. *pfInvalidEntry = TRUE;
  907. RASAUTO_TRACE2(
  908. "StartAutoDialer: RasGetEntryProperties(%S) failed (dwErr=%d)",
  909. RASAUTO_TRACESTRW(lpEntryName),
  910. dwErr);
  911. goto done;
  912. }
  913. lpEntry = LocalAlloc(LPTR, dwSize);
  914. if (lpEntry == NULL) {
  915. RASAUTO_TRACE("StartAutoDialer: LocalAlloc failed");
  916. goto done;
  917. }
  918. lpEntry->dwSize = sizeof (RASENTRY);
  919. dwErr = (DWORD)(*lpfnRasGetEntryPropertiesG)(
  920. NULL,
  921. lpEntryName,
  922. lpEntry,
  923. &dwSize,
  924. NULL,
  925. &dwIgnore);
  926. if (dwErr) {
  927. *pfInvalidEntry = TRUE;
  928. RASAUTO_TRACE2(
  929. "StartAutoDialer: RasGetEntryProperties(%S) failed (dwErr=%d)",
  930. RASAUTO_TRACESTRW(lpEntryName),
  931. dwErr);
  932. LocalFree(lpEntry);
  933. lpEntry = NULL;
  934. goto done;
  935. }
  936. //
  937. // While we have the phonebook entry
  938. // verify there is an available port
  939. // to dial.
  940. //
  941. if (!PortAvailable(lpEntry->szDeviceType, lpEntry->szDeviceName)) {
  942. RASAUTO_TRACE("StartAutoDialer: no port available");
  943. LocalFree(lpEntry);
  944. goto done;
  945. }
  946. if (*lpEntry->szAutodialDll != L'\0' &&
  947. *lpEntry->szAutodialFunc != L'\0')
  948. {
  949. //
  950. // Allocate pszCmdLine
  951. //
  952. pszCmdLine = LocalAlloc(
  953. LPTR,
  954. ( lstrlen(RASAUTOUI_CUSTOMDIALENTRY)
  955. + lstrlen(lpEntry->szAutodialDll)
  956. + lstrlen(lpEntry->szAutodialFunc)
  957. + lstrlen(lpEntryName)
  958. + 1) * sizeof(TCHAR));
  959. if(NULL == pszCmdLine)
  960. {
  961. RASAUTO_TRACE1("StartAutoDialer: Failed to allocate pszcmdline. 0x%x",
  962. dwErr);
  963. goto done;
  964. }
  965. //
  966. // Run a special program that loads the
  967. // AutoDial DLL and calls the correct
  968. // DLL entrypoint.
  969. //
  970. wsprintf(
  971. pszCmdLine,
  972. RASAUTOUI_CUSTOMDIALENTRY,
  973. lpEntry->szAutodialDll,
  974. lpEntry->szAutodialFunc,
  975. lpEntryName);
  976. }
  977. LocalFree(lpEntry);
  978. }
  979. fmtcmd:
  980. //
  981. // Ping the driver before we start
  982. // the dialing dialer to make sure
  983. // the connection is still valid.
  984. //
  985. if (pAddr)
  986. {
  987. connStatus.fSuccess = FALSE;
  988. RtlCopyMemory(&connStatus.addr, pAddr, sizeof (ACD_ADDR));
  989. status = NtDeviceIoControlFile(
  990. hAcdG,
  991. NULL,
  992. NULL,
  993. NULL,
  994. &ioStatusBlock,
  995. IOCTL_ACD_KEEPALIVE,
  996. &connStatus,
  997. sizeof (connStatus),
  998. NULL,
  999. 0);
  1000. if (status != STATUS_SUCCESS) {
  1001. RASAUTO_TRACE1(
  1002. "StartAutoDialer: NtDeviceIoControlFile(IOCTL_ACD_KEEPALIVE) failed (status=0x%x)",
  1003. status);
  1004. goto done;
  1005. }
  1006. }
  1007. if (NULL == pszCmdLine)
  1008. {
  1009. //
  1010. // Construct the command line when there
  1011. // is not a custom dial DLL.
  1012. //
  1013. if (lpEntryName != NULL)
  1014. {
  1015. pszCmdLine = LocalAlloc(
  1016. LPTR,
  1017. ( lstrlen(RASAUTOUI_DEFAULTDIALENTRY2)
  1018. + lstrlen(lpAddress)
  1019. + lstrlen(lpEntryName)
  1020. + 1) * sizeof(TCHAR));
  1021. if(NULL == pszCmdLine)
  1022. {
  1023. dwErr = GetLastError();
  1024. goto done;
  1025. }
  1026. if (fSharedAccess)
  1027. wsprintf(pszCmdLine, RASAUTOUI_DEFAULTDIALENTRY2, lpAddress, lpEntryName);
  1028. else
  1029. wsprintf(pszCmdLine, RASAUTOUI_DEFAULTDIALENTRY, lpAddress, lpEntryName);
  1030. }
  1031. else
  1032. {
  1033. pszCmdLine = LocalAlloc(
  1034. LPTR,
  1035. ( lstrlen(RASAUTOUI_NOENTRY)
  1036. + lstrlen(lpAddress)
  1037. + 1) * sizeof(TCHAR));
  1038. if(NULL == pszCmdLine)
  1039. {
  1040. dwErr = GetLastError();
  1041. goto done;
  1042. }
  1043. wsprintf(pszCmdLine, RASAUTOUI_NOENTRY, lpAddress);
  1044. }
  1045. }
  1046. RASAUTO_TRACE1("StartAutoDialer: szCmdLine=%S", pszCmdLine);
  1047. //
  1048. // Exec the process.
  1049. //
  1050. if (!OpenProcessToken(
  1051. hProcess,
  1052. TOKEN_ALL_ACCESS,
  1053. &hToken))
  1054. {
  1055. RASAUTO_TRACE1(
  1056. "StartAutoDialer: OpenProcessToken failed (dwErr=%d)",
  1057. GetLastError());
  1058. goto done;
  1059. }
  1060. if (!CreateEnvironmentBlock(
  1061. &pEnvBlock,
  1062. hToken,
  1063. FALSE))
  1064. {
  1065. TRACE1(
  1066. "StartAutoDialer: CreateEnvironmentBlock failed (dwErr=%d)",
  1067. GetLastError());
  1068. goto done;
  1069. }
  1070. if (!CreateProcessAsUser(
  1071. hToken,
  1072. NULL,
  1073. pszCmdLine,
  1074. NULL,
  1075. NULL,
  1076. FALSE,
  1077. NORMAL_PRIORITY_CLASS|DETACHED_PROCESS|CREATE_UNICODE_ENVIRONMENT,
  1078. pEnvBlock,
  1079. NULL,
  1080. &StartupInfo,
  1081. &ProcessInfo))
  1082. {
  1083. RASAUTO_TRACE2(
  1084. "StartAutoDialer: CreateProcessAsUser(%S) failed (error=0x%x)",
  1085. pszCmdLine,
  1086. GetLastError());
  1087. CloseHandle(hToken);
  1088. goto done;
  1089. }
  1090. RASAUTO_TRACE1("StartAutoDialer: started pid %d", ProcessInfo.dwProcessId);
  1091. CloseHandle(hToken);
  1092. CloseHandle(ProcessInfo.hThread);
  1093. //
  1094. // Now that we've started the process, we need to
  1095. // wait until we think the connection has
  1096. // been made.
  1097. //
  1098. fDialerPresent = TRUE;
  1099. dwPreConnections = ActiveConnections(TRUE, NULL, NULL);
  1100. while (dwCount++ < 0xffffffff) {
  1101. //
  1102. // Sleep for one second.
  1103. //
  1104. status = WaitForSingleObject(hTerminatingG, 1000);
  1105. if (status == WAIT_OBJECT_0)
  1106. goto done;
  1107. //
  1108. // Ping the driver to let it
  1109. // know we are working on the
  1110. // request.
  1111. //
  1112. if (pAddr)
  1113. {
  1114. connStatus.fSuccess = FALSE;
  1115. RtlCopyMemory(&connStatus.addr, pAddr, sizeof (ACD_ADDR));
  1116. status = NtDeviceIoControlFile(
  1117. hAcdG,
  1118. NULL,
  1119. NULL,
  1120. NULL,
  1121. &ioStatusBlock,
  1122. IOCTL_ACD_KEEPALIVE,
  1123. &connStatus,
  1124. sizeof (connStatus),
  1125. NULL,
  1126. 0);
  1127. if (status != STATUS_SUCCESS) {
  1128. RASAUTO_TRACE1(
  1129. "StartAutoDialer: NtDeviceIoControlFile(IOCTL_ACD_KEEPALIVE) failed (status=0x%x)",
  1130. status);
  1131. // goto done;
  1132. }
  1133. }
  1134. //
  1135. // Check to see if there are any connections yet.
  1136. // If there are, then we are done.
  1137. //
  1138. dwConnections = ActiveConnections(TRUE, NULL, NULL);
  1139. if (dwConnections > dwPreConnections) {
  1140. RASAUTO_TRACE("StartAutoDialer: connection started");
  1141. fSuccess = TRUE;
  1142. goto done;
  1143. }
  1144. //
  1145. // After we have determined there are
  1146. // no active connections, check to see
  1147. // if the dialer is still present. This
  1148. // was calculated on the *previous* iteration
  1149. // of the loop. We do this to avoid a race
  1150. // condition of having the dialer go away
  1151. // after we call ActiveConnections().
  1152. //
  1153. if (!fDialerPresent) {
  1154. BOOLEAN fFound = FALSE;
  1155. LPTSTR *lpConnections;
  1156. RASAUTO_TRACE("StartAutoDialer: dialer went away!");
  1157. if (lpEntryName != NULL) {
  1158. //
  1159. // Make absolutely sure if an entry was specified,
  1160. // it is not connected before we return FALSE.
  1161. // It's possible a connection could have been
  1162. // in progress before we started the dialer.
  1163. //
  1164. dwConnections = ActiveConnections(TRUE, &lpConnections, NULL);
  1165. if (dwConnections) {
  1166. for (dwIndex = 0; dwIndex < dwConnections; dwIndex++) {
  1167. if (!_wcsicmp(lpConnections[dwIndex], lpEntryName)) {
  1168. fFound = TRUE;
  1169. break;
  1170. }
  1171. }
  1172. FreeStringArray(lpConnections, dwConnections);
  1173. if (fFound) {
  1174. RASAUTO_TRACE1(
  1175. "StartAutoDialer: found %S on final check!",
  1176. RASAUTO_TRACESTRW(lpEntryName));
  1177. }
  1178. }
  1179. }
  1180. fSuccess = fFound;
  1181. goto done;
  1182. }
  1183. //
  1184. // After 5 seconds, check to see if
  1185. // the dialer has terminated.
  1186. //
  1187. if (dwCount > 5) {
  1188. fDialerPresent =
  1189. GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode) &&
  1190. dwExitCode == STILL_ACTIVE;
  1191. RASAUTO_TRACE2(
  1192. "StartAutoDialer: GetExitCodeProcess returned %d, dwExitCode=%d",
  1193. fDialerPresent,
  1194. dwExitCode);
  1195. if(ERROR_CANCELLED == dwExitCode)
  1196. {
  1197. RASAUTO_TRACE("User cancelled the connection attempt");
  1198. fDisableAddress = TRUE;
  1199. }
  1200. }
  1201. }
  1202. done:
  1203. //
  1204. // We timed out waiting for a connection.
  1205. // If the dialer is still running kill it.
  1206. //
  1207. if (ProcessInfo.hProcess != NULL)
  1208. CloseHandle(ProcessInfo.hProcess);
  1209. //
  1210. // Complete the connection request
  1211. // in the driver.
  1212. //
  1213. if (pAddr)
  1214. {
  1215. connStatus.fSuccess = fSuccess;
  1216. RtlCopyMemory(&connStatus.addr, pAddr, sizeof (ACD_ADDR));
  1217. status = NtDeviceIoControlFile(
  1218. hAcdG,
  1219. NULL,
  1220. NULL,
  1221. NULL,
  1222. &ioStatusBlock,
  1223. IOCTL_ACD_COMPLETION,
  1224. &connStatus,
  1225. sizeof (connStatus),
  1226. NULL,
  1227. 0);
  1228. if (status != STATUS_SUCCESS) {
  1229. RASAUTO_TRACE1(
  1230. "StartAutoDialer: NtDeviceIoControlFile(IOCTL_ACD_COMPLETION) failed (status=0x%x)",
  1231. status);
  1232. }
  1233. if(fDisableAddress)
  1234. {
  1235. DWORD retcode;
  1236. retcode = DisableAddress(pAddr);
  1237. RASAUTO_TRACE2("StartAutodialer: Disabled %S. rc=0x%x",
  1238. RASAUTO_TRACESTRW(lpAddress),
  1239. retcode);
  1240. }
  1241. }
  1242. if (NULL != pEnvBlock)
  1243. {
  1244. DestroyEnvironmentBlock(pEnvBlock);
  1245. }
  1246. if(NULL != pszCmdLine)
  1247. {
  1248. LocalFree(pszCmdLine);
  1249. }
  1250. return fSuccess;
  1251. } // StartAutoDialer
  1252. BOOLEAN
  1253. StartReDialer(
  1254. IN HANDLE hProcess,
  1255. IN LPTSTR lpPhonebook,
  1256. IN LPTSTR lpEntry
  1257. )
  1258. {
  1259. TCHAR szCmdLine[100];
  1260. TCHAR *pszCmdLine = NULL;
  1261. STARTUPINFO StartupInfo;
  1262. PROCESS_INFORMATION ProcessInfo;
  1263. HANDLE hToken;
  1264. PVOID pEnvBlock = NULL;
  1265. //
  1266. // Initialization of various variables.
  1267. //
  1268. memset(&StartupInfo, 0, sizeof (StartupInfo));
  1269. memset(&ProcessInfo, 0, sizeof (ProcessInfo));
  1270. StartupInfo.cb = sizeof(StartupInfo);
  1271. //
  1272. // Construct the command line when there
  1273. // is not a custom dial DLL.
  1274. //
  1275. pszCmdLine = LocalAlloc(
  1276. LPTR,
  1277. ( lstrlen(RASAUTOUI_REDIALENTRY)
  1278. + lstrlen(lpPhonebook)
  1279. + lstrlen(lpEntry)
  1280. + 1) * sizeof(TCHAR));
  1281. if(NULL == pszCmdLine)
  1282. {
  1283. RASAUTO_TRACE1("StartReDialer: failed to allocate pszCmdLine. 0x%x",
  1284. GetLastError());
  1285. return FALSE;
  1286. }
  1287. wsprintf(pszCmdLine, RASAUTOUI_REDIALENTRY, lpPhonebook, lpEntry);
  1288. RASAUTO_TRACE1("StartReDialer: szCmdLine=%S", pszCmdLine);
  1289. //
  1290. // Exec the process.
  1291. //
  1292. if (!OpenProcessToken(
  1293. hProcess,
  1294. TOKEN_ALL_ACCESS,
  1295. &hToken))
  1296. {
  1297. RASAUTO_TRACE1(
  1298. "StartReDialer: OpenProcessToken failed (dwErr=%d)",
  1299. GetLastError());
  1300. LocalFree(pszCmdLine);
  1301. return FALSE;
  1302. }
  1303. if (!CreateEnvironmentBlock(
  1304. &pEnvBlock,
  1305. hToken,
  1306. FALSE))
  1307. {
  1308. TRACE1(
  1309. "StartReDialer: CreateEnvironmentBlock failed (dwErr=%d)",
  1310. GetLastError());
  1311. LocalFree(pszCmdLine);
  1312. return FALSE;
  1313. }
  1314. if (!CreateProcessAsUser(
  1315. hToken,
  1316. NULL,
  1317. pszCmdLine,
  1318. NULL,
  1319. NULL,
  1320. FALSE,
  1321. NORMAL_PRIORITY_CLASS|DETACHED_PROCESS|CREATE_UNICODE_ENVIRONMENT,
  1322. pEnvBlock,
  1323. NULL,
  1324. &StartupInfo,
  1325. &ProcessInfo))
  1326. {
  1327. RASAUTO_TRACE2(
  1328. "StartReDialer: CreateProcessAsUser(%S) failed (error=0x%x)",
  1329. pszCmdLine,
  1330. GetLastError());
  1331. CloseHandle(hToken);
  1332. LocalFree(pszCmdLine);
  1333. if (pEnvBlock)
  1334. {
  1335. DestroyEnvironmentBlock(pEnvBlock);
  1336. }
  1337. return FALSE;
  1338. }
  1339. RASAUTO_TRACE1("StartReDialer: started pid %d", ProcessInfo.dwProcessId);
  1340. CloseHandle(hToken);
  1341. CloseHandle(ProcessInfo.hThread);
  1342. LocalFree(pszCmdLine);
  1343. if (pEnvBlock)
  1344. {
  1345. DestroyEnvironmentBlock(pEnvBlock);
  1346. }
  1347. return TRUE;
  1348. } // StartReDialer
  1349. DWORD
  1350. GetAddressDialingLocationInfo(
  1351. IN LPTSTR pszAddress,
  1352. OUT PADDRESS_LOCATION_INFORMATION *lppDialingInfo,
  1353. OUT LPDWORD lpdwcDialingInfo
  1354. )
  1355. {
  1356. DWORD dwErr, dwcb, dwcEntries, i;
  1357. LPRASAUTODIALENTRY lpAutoDialEntries;
  1358. PADDRESS_LOCATION_INFORMATION lpDialingInfo;
  1359. //
  1360. // Call RAS to find out how many
  1361. // dialing location entries there are.
  1362. //
  1363. dwcb = 0;
  1364. dwErr = (DWORD)(*lpfnRasGetAutodialAddressG)(
  1365. pszAddress,
  1366. NULL,
  1367. NULL,
  1368. &dwcb,
  1369. &dwcEntries);
  1370. if (dwErr && dwErr != ERROR_BUFFER_TOO_SMALL)
  1371. return dwErr;
  1372. if (!dwcEntries) {
  1373. *lppDialingInfo = NULL;
  1374. *lpdwcDialingInfo = 0;
  1375. return 0;
  1376. }
  1377. lpAutoDialEntries = LocalAlloc(LPTR, dwcb);
  1378. if (lpAutoDialEntries == NULL)
  1379. return ERROR_NOT_ENOUGH_MEMORY;
  1380. lpAutoDialEntries->dwSize = sizeof (RASAUTODIALENTRY);
  1381. dwErr = (DWORD)(*lpfnRasGetAutodialAddressG)(
  1382. pszAddress,
  1383. NULL,
  1384. lpAutoDialEntries,
  1385. &dwcb,
  1386. &dwcEntries);
  1387. if (dwErr || (0 == dwcEntries)) {
  1388. LocalFree(lpAutoDialEntries);
  1389. if(0 == dwcEntries)
  1390. {
  1391. dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  1392. }
  1393. return dwErr;
  1394. }
  1395. //
  1396. // Allocate our buffer.
  1397. //
  1398. lpDialingInfo = LocalAlloc(
  1399. LPTR,
  1400. dwcEntries * sizeof (ADDRESS_LOCATION_INFORMATION));
  1401. if (lpDialingInfo == NULL) {
  1402. LocalFree(lpAutoDialEntries);
  1403. return ERROR_NOT_ENOUGH_MEMORY;
  1404. }
  1405. //
  1406. // Copy this information over to our
  1407. // buffer.
  1408. //
  1409. for (i = 0; i < dwcEntries; i++) {
  1410. lpDialingInfo[i].dwLocation = lpAutoDialEntries[i].dwDialingLocation;
  1411. lpDialingInfo[i].pszEntryName =
  1412. CopyString(lpAutoDialEntries[i].szEntry);
  1413. }
  1414. //
  1415. // Free the RAS buffer.
  1416. //
  1417. LocalFree(lpAutoDialEntries);
  1418. //
  1419. // Set return values.
  1420. //
  1421. *lppDialingInfo = lpDialingInfo;
  1422. *lpdwcDialingInfo = dwcEntries;
  1423. return 0;
  1424. } // GetAddressDialingLocationInfo
  1425. DWORD
  1426. SetAddressDialingLocationInfo(
  1427. IN LPTSTR pszAddress,
  1428. IN PADDRESS_LOCATION_INFORMATION lpDialingInfo
  1429. )
  1430. {
  1431. RASAUTODIALENTRY rasAutoDialEntry;
  1432. //
  1433. // Copy the caller's buffer over
  1434. // to the RAS buffer.
  1435. //
  1436. rasAutoDialEntry.dwSize = sizeof (RASAUTODIALENTRY);
  1437. rasAutoDialEntry.dwDialingLocation = lpDialingInfo->dwLocation;
  1438. wcscpy(rasAutoDialEntry.szEntry, lpDialingInfo->pszEntryName);
  1439. return (DWORD)(*lpfnRasSetAutodialAddressG)(
  1440. pszAddress,
  1441. 0,
  1442. &rasAutoDialEntry,
  1443. sizeof (RASAUTODIALENTRY),
  1444. 1);
  1445. } // SetAddressDialingLocationInfo
  1446. DWORD
  1447. ClearAddressDialingLocationInfo(
  1448. IN LPTSTR pszAddress
  1449. )
  1450. {
  1451. return (DWORD)(*lpfnRasSetAutodialAddressG)(pszAddress, 0, NULL, 0, 0);
  1452. } // ClearAddressDialingLocationInfo
  1453. DWORD
  1454. GetAddressParams(
  1455. IN LPTSTR pszAddress,
  1456. IN PADDRESS_PARAMS lpParams
  1457. )
  1458. {
  1459. HKEY hkey;
  1460. DWORD dwErr, dwSize, dwType;
  1461. LPTSTR lpszAddressKey;
  1462. //
  1463. // Initialize address map fields.
  1464. //
  1465. lpParams->dwTag = ADDRMAP_TAG_NONE;
  1466. lpParams->dwModifiedTime = 0;
  1467. //
  1468. // Read the values from the registry.
  1469. //
  1470. lpszAddressKey = LocalAlloc(
  1471. LPTR,
  1472. (lstrlen(AUTODIAL_REGADDRESSBASE) +
  1473. lstrlen(pszAddress) + 2) * sizeof (TCHAR));
  1474. if (lpszAddressKey == NULL)
  1475. return 0;
  1476. wsprintf(lpszAddressKey, L"%s\\%s", AUTODIAL_REGADDRESSBASE, pszAddress);
  1477. LockImpersonation();
  1478. //
  1479. // Make sure we have hkcu
  1480. //
  1481. dwErr = DwGetHkcu();
  1482. if(ERROR_SUCCESS != dwErr)
  1483. {
  1484. goto done;
  1485. }
  1486. dwErr = RegOpenKeyEx(
  1487. hkeyCUG,
  1488. lpszAddressKey,
  1489. 0,
  1490. KEY_READ,
  1491. &hkey);
  1492. if (dwErr) {
  1493. LocalFree(lpszAddressKey);
  1494. goto done;
  1495. }
  1496. dwSize = sizeof (DWORD);
  1497. dwErr = RegQueryValueEx(
  1498. hkey,
  1499. AUTODIAL_REGTAGVALUE,
  1500. NULL,
  1501. &dwType,
  1502. (PVOID)&lpParams->dwTag,
  1503. &dwSize);
  1504. if (dwErr || dwType != REG_DWORD)
  1505. lpParams->dwTag = ADDRMAP_TAG_NONE;
  1506. dwSize = sizeof (DWORD);
  1507. dwErr = RegQueryValueEx(
  1508. hkey,
  1509. AUTODIAL_REGMTIMEVALUE,
  1510. NULL,
  1511. &dwType,
  1512. (PVOID)&lpParams->dwModifiedTime,
  1513. &dwSize);
  1514. if (dwErr || dwType != REG_DWORD)
  1515. lpParams->dwModifiedTime = 0;
  1516. RegCloseKey(hkey);
  1517. LocalFree(lpszAddressKey);
  1518. dwErr = ERROR_SUCCESS;
  1519. done:
  1520. UnlockImpersonation();
  1521. return dwErr;
  1522. } // GetAddressParams
  1523. DWORD
  1524. SetAddressParams(
  1525. IN LPTSTR pszAddress,
  1526. IN PADDRESS_PARAMS lpParams
  1527. )
  1528. {
  1529. HKEY hkey;
  1530. DWORD dwErr, dwSize, dwDisp;
  1531. LPTSTR lpszAddressKey;
  1532. //
  1533. // Write the values to the registry.
  1534. //
  1535. lpszAddressKey = LocalAlloc(
  1536. LPTR,
  1537. (lstrlen(AUTODIAL_REGADDRESSBASE) +
  1538. lstrlen(pszAddress) + 2) * sizeof (TCHAR));
  1539. if (lpszAddressKey == NULL)
  1540. return 0;
  1541. wsprintf(lpszAddressKey, L"%s\\%s", AUTODIAL_REGADDRESSBASE, pszAddress);
  1542. LockImpersonation();
  1543. //
  1544. // Make sure we have hkcu
  1545. //
  1546. dwErr = DwGetHkcu();
  1547. if(ERROR_SUCCESS != dwErr)
  1548. {
  1549. goto done;
  1550. }
  1551. dwErr = RegCreateKeyEx(
  1552. hkeyCUG,
  1553. lpszAddressKey,
  1554. 0,
  1555. NULL,
  1556. REG_OPTION_NON_VOLATILE,
  1557. KEY_ALL_ACCESS,
  1558. NULL,
  1559. &hkey,
  1560. &dwDisp);
  1561. if (dwErr) {
  1562. LocalFree(lpszAddressKey);
  1563. goto done;
  1564. }
  1565. dwErr = RegSetValueEx(
  1566. hkey,
  1567. AUTODIAL_REGTAGVALUE,
  1568. 0,
  1569. REG_DWORD,
  1570. (PVOID)&lpParams->dwTag,
  1571. sizeof (DWORD));
  1572. dwErr = RegSetValueEx(
  1573. hkey,
  1574. AUTODIAL_REGMTIMEVALUE,
  1575. 0,
  1576. REG_DWORD,
  1577. (PVOID)&lpParams->dwModifiedTime,
  1578. sizeof (DWORD));
  1579. RegCloseKey(hkey);
  1580. LocalFree(lpszAddressKey);
  1581. dwErr = ERROR_SUCCESS;
  1582. done:
  1583. UnlockImpersonation();
  1584. return dwErr;
  1585. } // SetAddressParams
  1586. DWORD
  1587. EnumAutodialAddresses(
  1588. IN LPTSTR *ppAddresses,
  1589. IN LPDWORD lpdwcbAddresses,
  1590. IN LPDWORD lpdwcAddresses
  1591. )
  1592. {
  1593. return (DWORD)(*lpfnRasEnumAutodialAddressesG)(
  1594. ppAddresses,
  1595. lpdwcbAddresses,
  1596. lpdwcAddresses);
  1597. } // EnumAutodialAddresses
  1598. DWORD
  1599. GetAutodialParam(
  1600. IN DWORD dwKey
  1601. )
  1602. {
  1603. DWORD dwValue, dwcb = sizeof (DWORD);
  1604. (void)(*lpfnRasGetAutodialParamG)(dwKey, &dwValue, &dwcb);
  1605. return dwValue;
  1606. } // GetAutodialParam
  1607. VOID
  1608. SetAutodialParam(
  1609. IN DWORD dwKey,
  1610. IN DWORD dwValue
  1611. )
  1612. {
  1613. (void)(*lpfnRasSetAutodialParamG)(dwKey, &dwValue, sizeof (DWORD));
  1614. } // SetAutodialParam
  1615. DWORD
  1616. NotifyAutoDialChangeEvent(
  1617. IN HANDLE hEvent
  1618. )
  1619. {
  1620. DWORD dwErr, dwDisp;
  1621. //
  1622. // Make sure we have hkcu
  1623. //
  1624. LockImpersonation();
  1625. dwErr = DwGetHkcu();
  1626. if(ERROR_SUCCESS != dwErr)
  1627. {
  1628. goto done;
  1629. }
  1630. //
  1631. // Open the AutoDial registry key.
  1632. //
  1633. if (hkeyAutoDialRegChangeG == NULL) {
  1634. dwErr = RegCreateKeyEx(
  1635. hkeyCUG,
  1636. L"Software\\Microsoft\\RAS AutoDial",
  1637. 0,
  1638. NULL,
  1639. REG_OPTION_NON_VOLATILE,
  1640. KEY_NOTIFY,
  1641. NULL,
  1642. &hkeyAutoDialRegChangeG,
  1643. &dwDisp);
  1644. if (dwErr)
  1645. {
  1646. goto done;
  1647. }
  1648. }
  1649. //
  1650. // Set the notification change.
  1651. //
  1652. dwErr = RegNotifyChangeKeyValue(
  1653. hkeyAutoDialRegChangeG,
  1654. TRUE,
  1655. REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_ATTRIBUTES|REG_NOTIFY_CHANGE_LAST_SET|REG_NOTIFY_CHANGE_SECURITY,
  1656. hEvent,
  1657. TRUE);
  1658. done:
  1659. UnlockImpersonation();
  1660. return dwErr;
  1661. } // NotifyAutoDialChangeEvent
  1662. DWORD
  1663. CreateAutoDialChangeEvent(
  1664. IN PHANDLE phEvent
  1665. )
  1666. {
  1667. //
  1668. // Reset the internal change flag.
  1669. //
  1670. fAutoDialRegChangeG = TRUE;
  1671. //
  1672. // Create the event.
  1673. //
  1674. *phEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1675. if (*phEvent == NULL)
  1676. return GetLastError();
  1677. //
  1678. // Register it.
  1679. //
  1680. return NotifyAutoDialChangeEvent(*phEvent);
  1681. } // CreateAutoDialChangeEvent
  1682. VOID
  1683. EnableAutoDialChangeEvent(
  1684. IN HANDLE hEvent,
  1685. IN BOOLEAN fEnabled
  1686. )
  1687. {
  1688. EnterCriticalSection(&csRasG);
  1689. //
  1690. // If the event was disabled, and now
  1691. // it is being enabled, then we reset
  1692. // the event.
  1693. //
  1694. if (!fAutoDialRegChangeG && fEnabled)
  1695. ResetEvent(hEvent);
  1696. fAutoDialRegChangeG = fEnabled;
  1697. LeaveCriticalSection(&csRasG);
  1698. }
  1699. BOOLEAN
  1700. ExternalAutoDialChangeEvent()
  1701. {
  1702. BOOLEAN fChanged;
  1703. EnterCriticalSection(&csRasG);
  1704. fChanged = fAutoDialRegChangeG;
  1705. LeaveCriticalSection(&csRasG);
  1706. return fChanged;
  1707. } // ExternalAutoDialChangeEvent
  1708. VOID
  1709. CloseAutoDialChangeEvent(
  1710. IN HANDLE hEvent
  1711. )
  1712. {
  1713. if (hkeyAutoDialRegChangeG != NULL) {
  1714. RegCloseKey(hkeyAutoDialRegChangeG);
  1715. hkeyAutoDialRegChangeG = NULL;
  1716. }
  1717. CloseHandle(hEvent);
  1718. } // CloseAutoDialChangeEvent
  1719. VOID
  1720. SetHostentCache(
  1721. IN PCHAR pszDns,
  1722. IN ULONG ulIpaddr
  1723. )
  1724. {
  1725. EnterCriticalSection(&csRasG);
  1726. lstrcpynA(
  1727. (PCHAR)&hostentCacheG[iHostentCacheG].szDns,
  1728. pszDns,
  1729. ACD_ADDR_INET_LEN);
  1730. hostentCacheG[iHostentCacheG].ulIpaddr = ulIpaddr;
  1731. iHostentCacheG = (iHostentCacheG + 1) % HOSTENTCACHESIZ;
  1732. LeaveCriticalSection(&csRasG);
  1733. } // SetHostentCache
  1734. PCHAR
  1735. GetHostentCache(
  1736. IN ULONG ulIpaddr
  1737. )
  1738. {
  1739. PCHAR pszDns = NULL;
  1740. INT i;
  1741. EnterCriticalSection(&csRasG);
  1742. for (i = 0; i < HOSTENTCACHESIZ; i++) {
  1743. if (hostentCacheG[i].ulIpaddr == ulIpaddr) {
  1744. pszDns = hostentCacheG[i].szDns;
  1745. break;
  1746. }
  1747. }
  1748. LeaveCriticalSection(&csRasG);
  1749. return pszDns;
  1750. } // GetHostentCache
  1751. LPTSTR
  1752. GetNetbiosDevice(
  1753. IN HRASCONN hrasconn
  1754. )
  1755. {
  1756. INT i, nProtocols;
  1757. RAS_PROTOCOLS Protocols;
  1758. HPORT hPort;
  1759. RASMAN_ROUTEINFO *pRoute;
  1760. WCHAR szDevice[MAX_DEVICE_NAME + 1];
  1761. DWORD dwErr;
  1762. nProtocols = 0;
  1763. hPort = (HPORT) (*lpfnRasGetHportG)(hrasconn);
  1764. if(INVALID_HPORT == hPort)
  1765. {
  1766. return NULL;
  1767. }
  1768. if(ERROR_SUCCESS != (dwErr = (DWORD)(*lpfnRasPortEnumProtocolsG)(
  1769. NULL, hPort,
  1770. &Protocols, &nProtocols)))
  1771. {
  1772. RASAUTO_TRACE1("GetNetbiosDevice: RasPortEnumProtocolsG failed"
  1773. " and returned 0x%x", dwErr);
  1774. return NULL;
  1775. }
  1776. for (i = 0; i < nProtocols; i++) {
  1777. pRoute = &Protocols.RP_ProtocolInfo[i];
  1778. RASAUTO_TRACE3(
  1779. "GetNetbiosDevice: lana=%d, xport=%S, adapter=%S",
  1780. pRoute->RI_LanaNum,
  1781. pRoute->RI_XportName,
  1782. pRoute->RI_AdapterName);
  1783. switch (pRoute->RI_Type) {
  1784. case IPX:
  1785. return CopyString(L"\\Device\\Nwlnknb");
  1786. case IP:
  1787. wsprintf(szDevice, L"\\Device\\NetBT_Tcpip%s", &pRoute->RI_AdapterName[8]);
  1788. return CopyString(szDevice);
  1789. case ASYBEUI:
  1790. wsprintf(szDevice, L"\\Device\\Nbf_%s", &pRoute->RI_AdapterName[8]);
  1791. return CopyString(szDevice);
  1792. }
  1793. }
  1794. return NULL;
  1795. } // GetNetbiosDevice
  1796. DWORD
  1797. DwGetDefaultEntryName(LPTSTR *ppszEntryName)
  1798. {
  1799. DWORD dwErr = ERROR_SUCCESS;
  1800. DWORD dwcb = sizeof(RASAUTODIALENTRY);
  1801. RASAUTODIALENTRY Entry;
  1802. DWORD dwEntries = 0;
  1803. LPTSTR pszEntryName = NULL;
  1804. if(NULL == ppszEntryName)
  1805. {
  1806. dwErr = E_INVALIDARG;
  1807. goto done;
  1808. }
  1809. ZeroMemory(&Entry, sizeof(RASAUTODIALENTRY));
  1810. Entry.dwSize = sizeof(RASAUTODIALENTRY);
  1811. dwErr = (DWORD) (*lpfnRasGetAutodialAddressG)(
  1812. NULL, NULL, &Entry,
  1813. &dwcb, &dwEntries);
  1814. if(ERROR_SUCCESS != dwErr)
  1815. {
  1816. goto done;
  1817. }
  1818. if(0 != dwEntries)
  1819. {
  1820. pszEntryName = LocalAlloc(LPTR,
  1821. sizeof(TCHAR) * (lstrlen(Entry.szEntry) + 1));
  1822. if(NULL != pszEntryName)
  1823. {
  1824. //
  1825. // Got a default entry.
  1826. //
  1827. lstrcpy(pszEntryName, Entry.szEntry);
  1828. }
  1829. else
  1830. {
  1831. dwErr = E_OUTOFMEMORY;
  1832. }
  1833. }
  1834. else
  1835. {
  1836. RASAUTO_TRACE("No default connection defined");
  1837. dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  1838. }
  1839. *ppszEntryName = pszEntryName;
  1840. done:
  1841. return dwErr;
  1842. }
  1843. VOID
  1844. ProcessLearnedAddress(
  1845. IN ACD_ADDR_TYPE fType,
  1846. IN LPTSTR pszAddress,
  1847. IN PACD_ADAPTER pAdapter
  1848. )
  1849. {
  1850. BOOLEAN fStatus;
  1851. DWORD dwConn, dwConnections, dwSize;
  1852. LPTSTR *pEntryNames, pszEntryName = NULL;
  1853. HRASCONN *phRasConn;
  1854. union {
  1855. RASPPPNBF pppNbf;
  1856. RASPPPIP pppIp;
  1857. RASPPPIPX pppIpx;
  1858. } projBuf;
  1859. RASPROJECTION fProjection;
  1860. INT i, nProtocols;
  1861. RAS_PROTOCOLS Protocols;
  1862. RASMAN_ROUTEINFO *pRoute;
  1863. HPORT hPort;
  1864. PCHAR pszIpAddr, pszMac = NULL;
  1865. WCHAR szIpAddr[17], *p, *pwszMac;
  1866. UCHAR cMac[6];
  1867. struct in_addr in;
  1868. LPTSTR pszDefaultEntry = NULL;
  1869. RASAUTO_TRACE2("ProcessLearnedAddress(%S,%d)", RASAUTO_TRACESTRW(pszAddress), pAdapter->fType);
  1870. dwConnections = ActiveConnections(TRUE, &pEntryNames, &phRasConn);
  1871. if (!dwConnections)
  1872. return;
  1873. (VOID) DwGetDefaultEntryName(&pszDefaultEntry);
  1874. if(NULL != pszDefaultEntry)
  1875. {
  1876. //
  1877. // Check to see if we have default entries as one of the
  1878. // connected entries. If it is we don't learn the address
  1879. //
  1880. for(dwConn = 0; dwConn < dwConnections; dwConn++)
  1881. {
  1882. if(0 == lstrcmpi(pEntryNames[dwConn], pszDefaultEntry))
  1883. {
  1884. break;
  1885. }
  1886. }
  1887. LocalFree(pszDefaultEntry);
  1888. if(dwConn != dwConnections)
  1889. {
  1890. RASAUTO_TRACE("ProcessLearnedAddress: not processing the address since"
  1891. " its learned over the default connection");
  1892. return;
  1893. }
  1894. }
  1895. //
  1896. // If this is a DNS-to-IP address mapping,
  1897. // then simply enter it into the hostent
  1898. // cache and return.
  1899. //
  1900. if (fType == ACD_ADDR_INET && pAdapter->fType == ACD_ADAPTER_IP) {
  1901. PCHAR pszDns = UnicodeStringToAnsiString(pszAddress, NULL, 0);
  1902. if (pszDns != NULL)
  1903. {
  1904. SetHostentCache(pszDns, pAdapter->ulIpaddr);
  1905. LocalFree(pszDns);
  1906. }
  1907. // return;
  1908. }
  1909. //
  1910. // Set the buffer size according to the
  1911. // adapter's type.
  1912. //
  1913. switch (pAdapter->fType) {
  1914. case ACD_ADAPTER_LANA:
  1915. RASAUTO_TRACE1(
  1916. "ProcessLearnedAddress: ACD_ADAPTER_LANA: bLana=%d",
  1917. pAdapter->bLana);
  1918. fProjection = RASP_PppNbf;
  1919. dwSize = sizeof (RASPPPNBF);
  1920. break;
  1921. case ACD_ADAPTER_IP:
  1922. fProjection = RASP_PppIp;
  1923. dwSize = sizeof (RASPPPIP);
  1924. //
  1925. // Convert the ULONG into a formatted IP address.
  1926. //
  1927. in.s_addr = pAdapter->ulIpaddr;
  1928. pszIpAddr = inet_ntoa(in);
  1929. RASAUTO_TRACE1(
  1930. "ProcessLearnedAddress: ACD_ADAPTER_IPADDR: %s",
  1931. pszIpAddr);
  1932. AnsiStringToUnicodeString(
  1933. pszIpAddr,
  1934. szIpAddr,
  1935. sizeof (szIpAddr) / sizeof(WCHAR));
  1936. break;
  1937. case ACD_ADAPTER_NAME:
  1938. RASAUTO_TRACE1(
  1939. "ProcessLearnedAddress: ACD_ADAPTER_NAME: %S",
  1940. pAdapter->szName);
  1941. dwSize = 0;
  1942. break;
  1943. case ACD_ADAPTER_MAC:
  1944. RASAUTO_TRACE6(
  1945. "ProcessLearnedAddress: ACD_ADAPTER_MAC: %02x:%02x:%02x:%02x:%02x:%02x",
  1946. pAdapter->cMac[0],
  1947. pAdapter->cMac[1],
  1948. pAdapter->cMac[2],
  1949. pAdapter->cMac[3],
  1950. pAdapter->cMac[4],
  1951. pAdapter->cMac[5]);
  1952. fProjection = RASP_PppIpx;
  1953. dwSize = sizeof (RASPPPIPX);
  1954. break;
  1955. }
  1956. for (dwConn = 0; dwConn < dwConnections; dwConn++) {
  1957. //
  1958. // If we are looking for a device name,
  1959. // we have to use RasPortEnumProtocols(),
  1960. // otherwise it's easier to use
  1961. // RasGetProjectionInfo.
  1962. //
  1963. if (pAdapter->fType != ACD_ADAPTER_NAME) {
  1964. //
  1965. // Note: the following statement assumes the
  1966. // dwSize field is at the same offset for
  1967. // all members of the union.
  1968. //
  1969. projBuf.pppNbf.dwSize = dwSize;
  1970. if ((*lpfnRasGetProjectionInfoG)(
  1971. phRasConn[dwConn],
  1972. fProjection,
  1973. &projBuf,
  1974. &dwSize))
  1975. {
  1976. RASAUTO_TRACE1(
  1977. "ProcessLearnedAddress: RasGetProjectionInfo(%S) failed",
  1978. RASAUTO_TRACESTRW(pEntryNames[dwConn]));
  1979. continue;
  1980. }
  1981. RASAUTO_TRACE3(
  1982. "ProcessLearnedAddress: RasGetProjectionInfo returned dwSize=%d, dwError=%d, szIpAddress=%S",
  1983. projBuf.pppIp.dwSize,
  1984. projBuf.pppIp.dwError,
  1985. projBuf.pppIp.szIpAddress);
  1986. //
  1987. // Note: the following statement assumes the
  1988. // dwError field is at the same offset for
  1989. // all members of the union.
  1990. //
  1991. if (projBuf.pppNbf.dwError) {
  1992. RASAUTO_TRACE2(
  1993. "ProcessLearnedAddress: %S: dwError=0x%x",
  1994. RASAUTO_TRACESTRW(pEntryNames[dwConn]),
  1995. projBuf.pppNbf.dwError);
  1996. continue;
  1997. }
  1998. switch (pAdapter->fType) {
  1999. case ACD_ADAPTER_LANA:
  2000. RASAUTO_TRACE2(
  2001. "ProcessLearnedAddress: comparing lanas (%d, %d)",
  2002. pAdapter->bLana,
  2003. projBuf.pppNbf.bLana);
  2004. if (pAdapter->bLana == projBuf.pppNbf.bLana) {
  2005. pszEntryName = CopyString(pEntryNames[dwConn]);
  2006. goto done;
  2007. }
  2008. break;
  2009. case ACD_ADAPTER_IP:
  2010. RASAUTO_TRACE2(
  2011. "ProcessLearnedAddress: comparing ipaddrs (%S, %S)",
  2012. szIpAddr,
  2013. projBuf.pppIp.szIpAddress);
  2014. // if (!_wcsicmp(szIpAddr, projBuf.pppIp.szIpAddress)) {
  2015. pszEntryName = CopyString(pEntryNames[dwConn]);
  2016. goto done;
  2017. //}
  2018. break;
  2019. case ACD_ADAPTER_MAC:
  2020. //
  2021. // Terminate IPX address after network number.
  2022. //
  2023. pwszMac = wcschr(projBuf.pppIpx.szIpxAddress, '.');
  2024. if (pwszMac == NULL)
  2025. goto done;
  2026. pszMac = UnicodeStringToAnsiString(pwszMac + 1, NULL, 0);
  2027. if (pszMac == NULL)
  2028. goto done;
  2029. StringToNodeNumber(pszMac, cMac);
  2030. RASAUTO_TRACE6(
  2031. "ProcessLearnedAddress: mac addr #1: %02x:%02x:%02x:%02x:%02x:%02x",
  2032. pAdapter->cMac[0],
  2033. pAdapter->cMac[1],
  2034. pAdapter->cMac[2],
  2035. pAdapter->cMac[3],
  2036. pAdapter->cMac[4],
  2037. pAdapter->cMac[5]);
  2038. RASAUTO_TRACE6(
  2039. "ProcessLearnedAddress: mac addr #2: %02x:%02x:%02x:%02x:%02x:%02x",
  2040. cMac[0],
  2041. cMac[1],
  2042. cMac[2],
  2043. cMac[3],
  2044. cMac[4],
  2045. cMac[5]);
  2046. if (RtlEqualMemory(pAdapter->cMac, cMac, sizeof (cMac)))
  2047. {
  2048. pszEntryName = CopyString(pEntryNames[dwConn]);
  2049. goto done;
  2050. }
  2051. break;
  2052. }
  2053. }
  2054. else {
  2055. nProtocols = 0;
  2056. hPort = (HPORT)(*lpfnRasGetHportG)(phRasConn[dwConn]);
  2057. (*lpfnRasPortEnumProtocolsG)(NULL, hPort, &Protocols, &nProtocols);
  2058. for (i = 0; i < nProtocols; i++) {
  2059. pRoute = &Protocols.RP_ProtocolInfo[i];
  2060. RASAUTO_TRACE2(
  2061. "ProcessLearnedAddress: comparing (%S, %S)",
  2062. pAdapter->szName,
  2063. &pRoute->RI_AdapterName[8]);
  2064. //
  2065. // Skip the "/Device/" prefix in
  2066. // RI_AdapterName for the comparison.
  2067. //
  2068. if (!_wcsicmp(
  2069. pAdapter->szName,
  2070. &pRoute->RI_AdapterName[8]))
  2071. {
  2072. pszEntryName = CopyString(pEntryNames[dwConn]);
  2073. goto done;
  2074. }
  2075. }
  2076. }
  2077. }
  2078. done:
  2079. //
  2080. // Create a mapping for the original address
  2081. // if we found one.
  2082. //
  2083. if (pszEntryName != NULL) {
  2084. LPTSTR pszNetbiosName, pszAlias = NULL;
  2085. CHAR szIpAddress[17], *psz;
  2086. ULONG inaddr;
  2087. struct hostent *hp;
  2088. switch (fType) {
  2089. case ACD_ADDR_IP:
  2090. //
  2091. // Get the Netbios name from the IP address,
  2092. // if any.
  2093. //
  2094. hPort = (HPORT)(*lpfnRasGetHportG)(phRasConn[dwConn]);
  2095. pszNetbiosName = IpAddressToNetbiosName(pszAddress, hPort);
  2096. if (pszNetbiosName != NULL) {
  2097. RASAUTO_TRACE2(
  2098. "ProcessLearnedAddress: ipaddr %S maps to Netbios name %S",
  2099. pszAddress,
  2100. pszNetbiosName);
  2101. LockAddressMap();
  2102. fStatus = SetAddressDialingLocationEntry(
  2103. pszNetbiosName,
  2104. pszEntryName);
  2105. fStatus = SetAddressTag(
  2106. pszNetbiosName,
  2107. ADDRMAP_TAG_LEARNED);
  2108. UnlockAddressMap();
  2109. LocalFree(pszNetbiosName);
  2110. }
  2111. //
  2112. // Get the DNS name from the IP address,
  2113. // if any.
  2114. //
  2115. UnicodeStringToAnsiString(
  2116. pszAddress,
  2117. szIpAddress,
  2118. sizeof (szIpAddress));
  2119. inaddr = inet_addr(szIpAddress);
  2120. psz = GetHostentCache(inaddr);
  2121. if (psz != NULL)
  2122. pszAlias = AnsiStringToUnicodeString(psz, NULL, 0);
  2123. if (pszAlias != NULL) {
  2124. RASAUTO_TRACE2(
  2125. "ProcessLearnedAddress: ipaddr %S maps to DNS %S",
  2126. pszAddress,
  2127. pszAlias);
  2128. LockAddressMap();
  2129. fStatus = SetAddressDialingLocationEntry(
  2130. pszAlias,
  2131. pszEntryName);
  2132. fStatus = SetAddressTag(
  2133. pszAlias,
  2134. ADDRMAP_TAG_LEARNED);
  2135. UnlockAddressMap();
  2136. LocalFree(pszAlias);
  2137. }
  2138. break;
  2139. case ACD_ADDR_IPX:
  2140. //
  2141. // Get the Netbios name from the IPX address,
  2142. // if any.
  2143. //
  2144. pszNetbiosName = IpxAddressToNetbiosName(pszAddress);
  2145. if (pszNetbiosName != NULL) {
  2146. RASAUTO_TRACE2(
  2147. "ProcessLearnedAddress: ipaddr %S maps to Netbios name %S",
  2148. pszAddress,
  2149. pszNetbiosName);
  2150. LockAddressMap();
  2151. fStatus = SetAddressDialingLocationEntry(
  2152. pszNetbiosName,
  2153. pszEntryName);
  2154. fStatus = SetAddressTag(
  2155. pszNetbiosName,
  2156. ADDRMAP_TAG_LEARNED);
  2157. UnlockAddressMap();
  2158. LocalFree(pszNetbiosName);
  2159. }
  2160. break;
  2161. }
  2162. RASAUTO_TRACE2(
  2163. "ProcessLearnedAddress: learned %S->%S",
  2164. pszAddress,
  2165. pszEntryName);
  2166. LockAddressMap();
  2167. fStatus = SetAddressDialingLocationEntry(
  2168. pszAddress,
  2169. pszEntryName);
  2170. fStatus = SetAddressTag(
  2171. pszAddress,
  2172. ADDRMAP_TAG_LEARNED);
  2173. UnlockAddressMap();
  2174. LocalFree(pszEntryName);
  2175. }
  2176. //
  2177. // Free resources.
  2178. //
  2179. if (dwConnections) {
  2180. FreeStringArray(pEntryNames, dwConnections);
  2181. LocalFree(phRasConn);
  2182. }
  2183. if(NULL != pszMac)
  2184. {
  2185. LocalFree(pszMac);
  2186. }
  2187. } // ProcessLearnedAddress
  2188. VOID
  2189. SetRedialOnLinkFailureHandler(
  2190. IN FARPROC lpProc
  2191. )
  2192. {
  2193. (*lpfnRasRegisterRedialCallbackG)(lpProc);
  2194. } // SetRedialOnLinkFailureHandler
  2195. VOID
  2196. GetPortProtocols(
  2197. IN HPORT hPort,
  2198. IN RAS_PROTOCOLS *pProtocols,
  2199. IN LPDWORD lpdwcProtocols
  2200. )
  2201. {
  2202. (*lpfnRasPortEnumProtocolsG)(NULL, hPort, pProtocols, lpdwcProtocols);
  2203. }