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.

1534 lines
45 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. connect.c
  5. ABSTRACT
  6. Connection routines for the automatic connection service.
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 23-Feb-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 <rasman.h>
  23. #include <raserror.h>
  24. #include <rasuip.h>
  25. #include <acd.h>
  26. #include <debug.h>
  27. #include <nouiutil.h>
  28. #include <pbk.h>
  29. #include "table.h"
  30. #include "addrmap.h"
  31. #include "netmap.h"
  32. #include "rasprocs.h"
  33. #include "reg.h"
  34. #include "misc.h"
  35. #include "imperson.h"
  36. #include "init.h"
  37. #include "process.h"
  38. extern LONG g_lRasAutoRunning;
  39. //
  40. // A request from the driver.
  41. //
  42. typedef struct _REQUEST_ENTRY {
  43. LIST_ENTRY listEntry; // link to other requests
  44. ACD_NOTIFICATION notif; // the driver request
  45. } REQUEST_ENTRY, *PREQUEST_ENTRY;
  46. //
  47. // The list of requests from the driver.
  48. //
  49. typedef struct _REQUEST_LIST {
  50. CRITICAL_SECTION csLock; // list lock
  51. HANDLE hEvent; // non-empty transistion event
  52. LIST_ENTRY listHead; // list head
  53. } REQUEST_LIST, *PREQUEST_LIST;
  54. //
  55. // Arguments we pass to AcsCreateConnectionThread().
  56. //
  57. typedef struct _CREATION_ARGS {
  58. HANDLE hProcess; // process handle to impersonate
  59. ACD_ADDR addr; // original type/address from driver
  60. LPTSTR pszAddress; // canonicalized address
  61. DWORD dwTimeout; // RASADP_FailedConnectionTimeout
  62. } CREATION_ARGS, *PCREATION_ARGS;
  63. //
  64. // Arguments we pass to AcsProcessLearnedAddressThread().
  65. //
  66. typedef struct _PROCESS_ADDR_ARGS {
  67. ACD_ADDR_TYPE fType; // address type
  68. LPTSTR pszAddress; // canonicalized address
  69. ACD_ADAPTER adapter; // adapter structure
  70. } PROCESS_ADDR_ARGS, *PPROCESS_ADDR_ARGS;
  71. //
  72. // Information we need to pass to ResetEntryName()
  73. // to reset an invalid address map entry name.
  74. //
  75. typedef struct _RESET_ENTRY_INFO {
  76. LPTSTR pszOldEntryName;
  77. LPTSTR pszNewEntryName;
  78. } RESET_ENTRY_INFO, *PRESET_ENTRY_INFO;
  79. //
  80. // Arguments we pass to AcsRedialOnLinkFailureThread().
  81. //
  82. typedef struct _REDIAL_ARGS {
  83. LPTSTR pszPhonebook; // the phonebook
  84. LPTSTR pszEntry; // the phonebook entry
  85. } REDIAL_ARGS, *PREDIAL_ARGS;
  86. //
  87. // Global variables
  88. //
  89. HANDLE hAcdG;
  90. REQUEST_LIST RequestListG;
  91. //
  92. // External variables
  93. //
  94. extern HANDLE hTerminatingG;
  95. extern HANDLE hSharedConnectionG;
  96. extern PHASH_TABLE pDisabledAddressesG;
  97. extern FARPROC lpfnRasDialG;
  98. extern FARPROC lpfnRasQuerySharedAutoDialG;
  99. extern FARPROC lpfnRasQuerySharedConnectionG;
  100. extern FARPROC lpfnRasQueryRedialOnLinkFailureG;
  101. extern FARPROC lpfnRasGetCredentialsG;
  102. extern FARPROC lpfnRasHangUpG;
  103. extern FARPROC lpfnRasGetEntryPropertiesG;
  104. //
  105. // Forward declarations
  106. //
  107. BOOLEAN
  108. CreateConnection(
  109. IN HANDLE hToken,
  110. IN PACD_ADDR pAddr,
  111. IN LPTSTR lpRemoteName,
  112. IN DWORD dwTimeout
  113. );
  114. DWORD
  115. AcsRedialOnLinkFailureThread(
  116. LPVOID lpArg
  117. );
  118. VOID
  119. AcsRedialOnLinkFailure(
  120. IN LPSTR lpszPhonebook,
  121. IN LPSTR lpszEntry
  122. );
  123. VOID
  124. AcsDialSharedConnection(
  125. HANDLE *phProcess
  126. );
  127. DWORD WINAPI
  128. AcsDialSharedConnectionNoUser(
  129. PVOID Parameter
  130. );
  131. DWORD
  132. AcsRequestWorkerThread(
  133. LPVOID pArgs
  134. )
  135. {
  136. HANDLE hProcess = NULL, hEvents[3];
  137. NTSTATUS status;
  138. PLIST_ENTRY pEntry;
  139. PREQUEST_ENTRY pRequest = NULL;
  140. LPTSTR pszAddress = NULL;
  141. IO_STATUS_BLOCK ioStatusBlock;
  142. hEvents[0] = hTerminatingG;
  143. hEvents[1] = RequestListG.hEvent;
  144. hEvents[2] = hSharedConnectionG;
  145. for (;;) {
  146. //
  147. // Unload any user-based resources before
  148. // a potentially long-term wait.
  149. //
  150. // PrepareForLongWait();
  151. //
  152. // Wait for something to do.
  153. //
  154. RASAUTO_TRACE("AcsRequestWorkerThread: waiting...");
  155. status = WaitForMultipleObjects(3, hEvents, FALSE, INFINITE);
  156. if (status == WAIT_OBJECT_0 || status == WAIT_FAILED) {
  157. RASAUTO_TRACE1("AcsRequestWorkerThread: status=%d: shutting down", status);
  158. break;
  159. }
  160. if (status == WAIT_OBJECT_0 + 2) {
  161. //
  162. // Check to see if connections are disabled
  163. // for this dialing location.
  164. //
  165. BOOL fEnabled;
  166. if ((*lpfnRasQuerySharedAutoDialG)(&fEnabled) || !fEnabled) {
  167. RASAUTO_TRACE("AcsRequestWorkerThread: shared-autodial disabled!");
  168. continue;
  169. }
  170. //
  171. // Dial the shared connection
  172. //
  173. if ((hProcess = RefreshImpersonation(hProcess)) == NULL) {
  174. RASAUTO_TRACE("AcsRequestWorkerThread: no currently logged-on user!");
  175. QueueUserWorkItem(AcsDialSharedConnectionNoUser, NULL, 0);
  176. continue;
  177. }
  178. AcsDialSharedConnection(&hProcess);
  179. continue;
  180. }
  181. //
  182. // RASAUTO_TRACE() who we think the current user is.
  183. //
  184. TraceCurrentUser();
  185. //
  186. // Process all requests in the list.
  187. //
  188. for (;;) {
  189. //
  190. // Make sure we aren't shutting down
  191. // before processing the next request.
  192. //
  193. if (WaitForSingleObject(hTerminatingG, 0) != WAIT_TIMEOUT) {
  194. RASAUTO_TRACE("AcsRequestWorkerThread: shutting down");
  195. return 0;
  196. }
  197. //
  198. // Get the next request.
  199. //
  200. EnterCriticalSection(&RequestListG.csLock);
  201. if (IsListEmpty(&RequestListG.listHead)) {
  202. LeaveCriticalSection(&RequestListG.csLock);
  203. break;
  204. }
  205. pEntry = RemoveHeadList(&RequestListG.listHead);
  206. LeaveCriticalSection(&RequestListG.csLock);
  207. pRequest = CONTAINING_RECORD(pEntry, REQUEST_ENTRY, listEntry);
  208. //
  209. // Make sure the current thread is impersonating
  210. // the currently logged-on user.
  211. //
  212. if ((hProcess = RefreshImpersonation(hProcess)) == NULL) {
  213. RASAUTO_TRACE("AcsRequestWorkerThread: no currently logged-on user!");
  214. goto done;
  215. }
  216. //
  217. // Handle the request.
  218. //
  219. pszAddress = AddressToUnicodeString(&pRequest->notif.addr);
  220. if (pszAddress == NULL) {
  221. RASAUTO_TRACE("AcsRequestWorkerThread: AddressToUnicodeString failed");
  222. goto done;
  223. }
  224. RASAUTO_TRACE2(
  225. "AcsRequestWorkerThread: pszAddress=%S, ulFlags=0x%x",
  226. pszAddress,
  227. pRequest->notif.ulFlags);
  228. if (pRequest->notif.ulFlags & ACD_NOTIFICATION_SUCCESS) {
  229. //
  230. // Process a learned address.
  231. //
  232. ProcessLearnedAddress(
  233. pRequest->notif.addr.fType,
  234. pszAddress,
  235. &pRequest->notif.adapter);
  236. }
  237. else {
  238. ACD_STATUS connStatus;
  239. DWORD dwTimeout;
  240. //
  241. // Get the connection timeout value.
  242. //
  243. dwTimeout = GetAutodialParam(RASADP_FailedConnectionTimeout);
  244. //
  245. // Create the new connection.
  246. //
  247. connStatus.fSuccess = CreateConnection(
  248. hProcess,
  249. &pRequest->notif.addr,
  250. pszAddress,
  251. dwTimeout);
  252. RASAUTO_TRACE1(
  253. "AcsRequestWorkerThread: CreateConnection returned %d",
  254. connStatus.fSuccess);
  255. //
  256. // Complete the connection by issuing
  257. // the completion ioctl to the driver.
  258. //
  259. RtlCopyMemory(
  260. &connStatus.addr,
  261. &pRequest->notif.addr,
  262. sizeof (ACD_ADDR));
  263. status = NtDeviceIoControlFile(
  264. hAcdG,
  265. NULL,
  266. NULL,
  267. NULL,
  268. &ioStatusBlock,
  269. IOCTL_ACD_COMPLETION,
  270. &connStatus,
  271. sizeof (connStatus),
  272. NULL,
  273. 0);
  274. if (status != STATUS_SUCCESS) {
  275. RASAUTO_TRACE1(
  276. "AcsRequestWorkerThread: NtDeviceIoControlFile(IOCTL_ACD_COMPLETION) failed (status=0x%x)",
  277. status);
  278. }
  279. }
  280. done:
  281. if (pszAddress != NULL) {
  282. LocalFree(pszAddress);
  283. pszAddress = NULL;
  284. }
  285. if (pRequest != NULL) {
  286. LocalFree(pRequest);
  287. pRequest = NULL;
  288. }
  289. }
  290. }
  291. return 0;
  292. } // AcsRequestWorkerThread
  293. BOOL
  294. fProcessDisabled(HANDLE hPid)
  295. {
  296. PSYSTEM_PROCESS_INFORMATION pProcessInfo;
  297. ULONG ulTotalOffset = 0;
  298. PUCHAR pLargeBuffer = NULL;
  299. BOOL fProcessDisabled = FALSE;
  300. pProcessInfo = GetSystemProcessInfo();
  301. if(NULL == pProcessInfo)
  302. {
  303. goto done;
  304. }
  305. pLargeBuffer = (PUCHAR)pProcessInfo;
  306. //
  307. // Look in the process list for svchost.exe and services.exe
  308. //
  309. for (;;)
  310. {
  311. if ( (pProcessInfo->ImageName.Buffer != NULL)
  312. && (hPid == pProcessInfo->UniqueProcessId))
  313. {
  314. if( (0 == _wcsicmp(
  315. pProcessInfo->ImageName.Buffer,
  316. L"svchost.exe"))
  317. || (0 == _wcsicmp(
  318. pProcessInfo->ImageName.Buffer,
  319. L"services.exe"))
  320. || (0 == _wcsicmp(
  321. pProcessInfo->ImageName.Buffer,
  322. L"llssrv.exe")))
  323. {
  324. fProcessDisabled = TRUE;
  325. }
  326. break;
  327. }
  328. //
  329. // Increment offset to next process information block.
  330. //
  331. if (!pProcessInfo->NextEntryOffset)
  332. {
  333. break;
  334. }
  335. ulTotalOffset += pProcessInfo->NextEntryOffset;
  336. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pLargeBuffer[ulTotalOffset];
  337. }
  338. done:
  339. if(NULL != pLargeBuffer)
  340. {
  341. FreeSystemProcessInfo((PSYSTEM_PROCESS_INFORMATION)pLargeBuffer);
  342. }
  343. return fProcessDisabled;
  344. }
  345. VOID
  346. AcsDoService()
  347. {
  348. HANDLE hProcess = NULL, hNotif, hObjects[2];
  349. HANDLE hWorkerThread;
  350. PWCHAR pszAddr;
  351. LONG cbAddr;
  352. NTSTATUS status;
  353. BOOLEAN fDisabled, fStatus, fEnabled;
  354. BOOLEAN fAsynchronousRequest;
  355. IO_STATUS_BLOCK ioStatusBlock;
  356. PREQUEST_ENTRY pRequest;
  357. ACD_NOTIFICATION connInfo;
  358. DWORD dwErr, dwThreadId, dwfDisableLoginSession;
  359. ULONG ulAttributes;
  360. {
  361. LONG l;
  362. l = InterlockedIncrement(&g_lRasAutoRunning);
  363. // DbgPrint("RASAUTO: AcsDoService: lrasautorunning=%d\n",
  364. // l);
  365. }
  366. //
  367. // Initialize the request list.
  368. //
  369. InitializeCriticalSection(&RequestListG.csLock);
  370. RequestListG.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  371. if (RequestListG.hEvent == NULL) {
  372. RASAUTO_TRACE1(
  373. "AcsDoService: CreateEvent failed (error=0x%x)",
  374. GetLastError());
  375. DeleteCriticalSection(&RequestListG.csLock);
  376. return;
  377. }
  378. InitializeListHead(&RequestListG.listHead);
  379. //
  380. // Start the asynchronous request worker
  381. // thread.
  382. //
  383. hWorkerThread = CreateThread(
  384. NULL,
  385. 10000L,
  386. (LPTHREAD_START_ROUTINE)AcsRequestWorkerThread,
  387. NULL,
  388. 0,
  389. &dwThreadId);
  390. if (hWorkerThread == NULL) {
  391. RASAUTO_TRACE1(
  392. "AcsDoService: CreateThread failed (error=0x%x)",
  393. GetLastError());
  394. goto done;
  395. }
  396. //
  397. // Create an event to wait for
  398. // the ioctl completion.
  399. //
  400. hNotif = CreateEvent(NULL, FALSE, FALSE, NULL);
  401. if (hNotif == NULL) {
  402. RASAUTO_TRACE1(
  403. "AcsDoService: CreateEvent failed (error=0x%x)",
  404. GetLastError());
  405. DeleteCriticalSection(&RequestListG.csLock);
  406. return;
  407. }
  408. //
  409. // Initialize the array of events
  410. // we need to wait for with WaitForMultipleObjects()
  411. // below.
  412. //
  413. hObjects[0] = hNotif;
  414. hObjects[1] = hTerminatingG;
  415. for (;;) {
  416. //
  417. // Unload any user-based resources before
  418. // a potentially long-term wait.
  419. //
  420. // PrepareForLongWait();
  421. //
  422. // Initialize the connection information.
  423. //
  424. pszAddr = NULL;
  425. RtlZeroMemory(&connInfo, sizeof (connInfo));
  426. //
  427. // Wait for a connection notification.
  428. //
  429. status = NtDeviceIoControlFile(
  430. hAcdG,
  431. hNotif,
  432. NULL,
  433. NULL,
  434. &ioStatusBlock,
  435. IOCTL_ACD_NOTIFICATION,
  436. NULL,
  437. 0,
  438. &connInfo,
  439. sizeof (connInfo));
  440. if (status == STATUS_PENDING) {
  441. RASAUTO_TRACE("AcsDoService: waiting for notification");
  442. status = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
  443. RASAUTO_TRACE1(
  444. "AcsDoService: WaitForMultipleObjects returned 0x%x",
  445. status);
  446. if (status == WAIT_OBJECT_0 + 1)
  447. break;
  448. status = ioStatusBlock.Status;
  449. }
  450. if (status != STATUS_SUCCESS) {
  451. RASAUTO_TRACE1(
  452. "AcsDoService: NtDeviceIoControlFile(IOCTL_ACD_NOTIFICATION) failed (status=0x%x)",
  453. status);
  454. return;
  455. }
  456. //
  457. // Initialize the flag that notes whether
  458. // the request is added to the list of
  459. // asynchronous requests.
  460. //
  461. fAsynchronousRequest = FALSE;
  462. //
  463. // RASAUTO_TRACE() who we think the currently
  464. // impersonated user is.
  465. //
  466. TraceCurrentUser();
  467. //
  468. // Convert the address structure to a Unicode string.
  469. //
  470. pszAddr = AddressToUnicodeString(&connInfo.addr);
  471. if (pszAddr == NULL) {
  472. RASAUTO_TRACE("AcsDoService: AddressToUnicodeString failed");
  473. continue;
  474. }
  475. //
  476. // If we get a bogus address from
  477. // the driver, ignore it.
  478. //
  479. if (!wcslen(pszAddr)) {
  480. RASAUTO_TRACE("AcsDoService: ignoring null address");
  481. LocalFree(pszAddr);
  482. continue;
  483. }
  484. RASAUTO_TRACE2(
  485. "AcsDoService: got notification: address: %S, ulFlags=0x%x",
  486. pszAddr,
  487. connInfo.ulFlags);
  488. //
  489. // Make sure the current thread is impersonating
  490. // the currently logged-on user. We need this
  491. // so the RAS utilities run with the user's credentials.
  492. //
  493. if ((hProcess = RefreshImpersonation(hProcess)) == NULL) {
  494. RASAUTO_TRACE("AcsDoService: no currently logged-on user!");
  495. goto done;
  496. }
  497. //
  498. // Check to see if this address is in the list
  499. // of disabled addresses.
  500. //
  501. LockDisabledAddresses();
  502. if (GetTableEntry(pDisabledAddressesG, pszAddr, NULL)) {
  503. RASAUTO_TRACE1("AcsDoService: %S: is disabled", pszAddr);
  504. UnlockDisabledAddresses();
  505. goto done;
  506. }
  507. UnlockDisabledAddresses();
  508. //
  509. // Check to see if connections are disabled
  510. // for this login session.
  511. //
  512. dwfDisableLoginSession = GetAutodialParam(RASADP_LoginSessionDisable);
  513. if (dwfDisableLoginSession) {
  514. RASAUTO_TRACE("AcsDoService: connections disabled for this login session");
  515. goto done;
  516. }
  517. //
  518. // Check to see if connections are disabled
  519. // for this dialing location.
  520. //
  521. dwErr = AutoDialEnabled(&fEnabled);
  522. if (!dwErr && !fEnabled) {
  523. RASAUTO_TRACE("AcsDoService: connections disabled for this dialing location");
  524. goto done;
  525. }
  526. //
  527. // If the address we're trying to connect
  528. // to is on the disabled list, then fail
  529. // this connection attempt.
  530. //
  531. LockAddressMap();
  532. GetAddressDisabled(pszAddr, &fDisabled);
  533. UnlockAddressMap();
  534. if (fDisabled) {
  535. RASAUTO_TRACE1("AcsDoService: %S: address disabled", RASAUTO_TRACESTRW(pszAddr));
  536. goto done;
  537. }
  538. RASAUTO_TRACE1("AcsDoService: notif.ulFlags=0x%x", connInfo.ulFlags);
  539. //
  540. // If autodial is disabled for this pid, don't start autodial and bail
  541. //
  542. if( (0 == (connInfo.ulFlags & ACD_NOTIFICATION_SUCCESS))
  543. && fProcessDisabled(connInfo.Pid))
  544. {
  545. RASAUTO_TRACE1("AcsDoService: Autodial is disabled for process 0x%lx",
  546. connInfo.Pid);
  547. goto done;
  548. }
  549. else
  550. {
  551. RASAUTO_TRACE1("AcsDoService: process 0x%lx is not disabled",
  552. connInfo.Pid);
  553. }
  554. //
  555. // We need to process this request
  556. // asynchronously. Create and initialize
  557. // a request entry.
  558. //
  559. pRequest = LocalAlloc(LPTR, sizeof (REQUEST_ENTRY));
  560. if (pRequest == NULL) {
  561. RASAUTO_TRACE("AcsDoService: LocalAlloc failed");
  562. goto done;
  563. }
  564. RtlCopyMemory(&pRequest->notif, &connInfo, sizeof (ACD_NOTIFICATION));
  565. //
  566. // Add this request to the list of
  567. // requests to be processed asynchronously.
  568. //
  569. EnterCriticalSection(&RequestListG.csLock);
  570. InsertTailList(&RequestListG.listHead, &pRequest->listEntry);
  571. SetEvent(RequestListG.hEvent);
  572. LeaveCriticalSection(&RequestListG.csLock);
  573. fAsynchronousRequest = TRUE;
  574. done:
  575. if (pszAddr != NULL)
  576. LocalFree(pszAddr);
  577. //
  578. // If we aren't going to process this request
  579. // asynchronously, then we need to signal the
  580. // (unsuccessful) completion of the connection
  581. // attempt. Only signal completion of
  582. // non-ACD_NOTIFICATION_SUCCESS requests.
  583. //
  584. if (!fAsynchronousRequest) {
  585. if (!(connInfo.ulFlags & ACD_NOTIFICATION_SUCCESS)) {
  586. ACD_STATUS connStatus;
  587. connStatus.fSuccess = FALSE;
  588. RtlCopyMemory(&connStatus.addr, &connInfo.addr, sizeof (ACD_ADDR));
  589. status = NtDeviceIoControlFile(
  590. hAcdG,
  591. NULL,
  592. NULL,
  593. NULL,
  594. &ioStatusBlock,
  595. IOCTL_ACD_COMPLETION,
  596. &connStatus,
  597. sizeof (connStatus),
  598. NULL,
  599. 0);
  600. if (status != STATUS_SUCCESS) {
  601. RASAUTO_TRACE1(
  602. "AcsDoService: NtDeviceIoControlFile(IOCTL_ACD_COMPLETION) failed (status=0x%x)",
  603. status);
  604. }
  605. }
  606. }
  607. }
  608. //
  609. // Clean up the worker thread.
  610. //
  611. RASAUTO_TRACE("AcsDoService: signaling worker thread to shutdown");
  612. WaitForSingleObject(hWorkerThread, INFINITE);
  613. if(RequestListG.hEvent != NULL)
  614. {
  615. CloseHandle(RequestListG.hEvent);
  616. RequestListG.hEvent = NULL;
  617. }
  618. DeleteCriticalSection(&RequestListG.csLock);
  619. CloseHandle(hWorkerThread);
  620. RASAUTO_TRACE("AcsDoService: worker thread shutdown done");
  621. //
  622. // Clean up all resources associated
  623. // with the service.
  624. //
  625. CloseHandle(hNotif);
  626. AcsCleanup();
  627. RASAUTO_TRACE("AcsDoService: exiting");
  628. } // AcsDoService
  629. VOID
  630. AcsDialSharedConnection(
  631. HANDLE *phProcess
  632. )
  633. /*++
  634. DESCRIPTION
  635. Looks for a shared connection and initiates a connection for it.
  636. ARGUMENTS
  637. phProcess: pointer to the handle to the process token that we inherit the
  638. security attributes from when we exec the dialer
  639. RETURN VALUE
  640. none
  641. --*/
  642. {
  643. DWORD dwErr;
  644. BOOLEAN fEntryInvalid;
  645. BOOLEAN fRasLoaded;
  646. RASSHARECONN rsc;
  647. TCHAR* pszEntryName;
  648. TCHAR szEntryName[RAS_MaxEntryName + 1];
  649. RASAUTO_TRACE("AcsDialSharedConnection");
  650. //
  651. // Load RAS entrypoints
  652. //
  653. fRasLoaded = LoadRasDlls();
  654. if (!fRasLoaded) {
  655. RASAUTO_TRACE("AcsDialSharedConnection: Could not load RAS DLLs.");
  656. return;
  657. }
  658. //
  659. // A guest isn't able to dial a RAS connection, so if we're currently
  660. // impersonating a guest we need to perform a no-user autodial
  661. //
  662. if (ImpersonatingGuest()) {
  663. QueueUserWorkItem(AcsDialSharedConnectionNoUser, NULL, 0);
  664. return;
  665. }
  666. //
  667. // Get the shared connection, if any. We can't do this in an impersonated
  668. // context, as the user we're impersonating may not have sufficient access
  669. // to retrieve the current shared connection.
  670. //
  671. RevertImpersonation();
  672. *phProcess = NULL;
  673. dwErr = (DWORD)(*lpfnRasQuerySharedConnectionG)(&rsc);
  674. if ((*phProcess = RefreshImpersonation(NULL)) == NULL) {
  675. RASAUTO_TRACE("AcsDialSharedConnection: unable to refresh impersonation!");
  676. if (NO_ERROR == dwErr && !rsc.fIsLanConnection) {
  677. //
  678. // Attempt to do no-user autodial
  679. //
  680. QueueUserWorkItem(AcsDialSharedConnectionNoUser, NULL, 0);
  681. return;
  682. }
  683. }
  684. if (dwErr) {
  685. RASAUTO_TRACE1("AcsDialSharedConnection: RasQuerySharedConnection=%d", dwErr);
  686. return;
  687. } else if (rsc.fIsLanConnection) {
  688. RASAUTO_TRACE("AcsDialSharedConnection: shared connection is LAN adapter");
  689. return;
  690. }
  691. #ifdef UNICODE
  692. pszEntryName = rsc.name.szEntryName;
  693. #else
  694. //
  695. // Convert to ANSI
  696. //
  697. pszEntryName = szEntryName;
  698. wcstombs(pszEntryName, rsc.name.szEntryName, RAS_MaxEntryName);
  699. #endif
  700. //
  701. // Initiate a dial-attempt
  702. //
  703. StartAutoDialer(
  704. *phProcess,
  705. NULL,
  706. pszEntryName,
  707. pszEntryName,
  708. TRUE,
  709. &fEntryInvalid);
  710. }
  711. DWORD WINAPI
  712. AcsDialSharedConnectionNoUser(
  713. PVOID Parameter
  714. )
  715. /*++
  716. DESCRIPTION
  717. Looks for a shared connection and initiates a connection for it
  718. using RasDial and the cached credentials for the connection.
  719. ARGUMENTS
  720. none
  721. RETURN VALUE
  722. none
  723. --*/
  724. {
  725. DWORD dwErr;
  726. BOOLEAN fRasLoaded;
  727. HRASCONN hrasconn;
  728. RASCREDENTIALSW rc;
  729. RASDIALEXTENSIONS rde;
  730. RASDIALPARAMSW rdp;
  731. RASSHARECONN rsc;
  732. RASAUTO_TRACE("AcsDialSharedConnectionNoUser");
  733. //
  734. // Load RAS entrypoints
  735. //
  736. fRasLoaded = LoadRasDlls();
  737. if (!fRasLoaded) {
  738. RASAUTO_TRACE("AcsDialSharedConnectionNoUser: Could not load RAS DLLs.");
  739. return NO_ERROR;
  740. }
  741. //
  742. // Get the shared connection, if any
  743. //
  744. dwErr = (DWORD)(*lpfnRasQuerySharedConnectionG)(&rsc);
  745. if (dwErr) {
  746. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: RasQuerySharedConnection=%d",
  747. dwErr);
  748. return NO_ERROR;
  749. } else if (rsc.fIsLanConnection) {
  750. RASAUTO_TRACE("AcsDialSharedConnectionNoUser: shared connection is LAN");
  751. return NO_ERROR;
  752. }
  753. //
  754. // Retrieve the credentials for the shared connection.
  755. //
  756. rc.dwSize = sizeof(rc);
  757. rc.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain | RASCM_DefaultCreds;
  758. dwErr = (DWORD)(*lpfnRasGetCredentialsG)(
  759. rsc.name.szPhonebookPath, rsc.name.szEntryName, &rc
  760. );
  761. if (dwErr) {
  762. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: "
  763. "RasGetCredentials=%d", dwErr);
  764. return NO_ERROR;
  765. }
  766. //
  767. // Prepare to initiate the connection, setting up the dial-extensions
  768. // and the dial-parameters.
  769. //
  770. ZeroMemory(&rde, sizeof(rde));
  771. rde.dwSize = sizeof(rde);
  772. rde.dwfOptions = RDEOPT_NoUser;
  773. ZeroMemory(&rdp, sizeof(rdp));
  774. rdp.dwSize = sizeof(rdp);
  775. lstrcpyW(rdp.szEntryName, rsc.name.szEntryName);
  776. lstrcpyW(rdp.szUserName, rc.szUserName);
  777. lstrcpyW(rdp.szDomain, rc.szDomain);
  778. lstrcpyW(rdp.szPassword, rc.szPassword);
  779. //
  780. // Clear the credentials from memory, and dial the connection.
  781. //
  782. RASAUTO_TRACE("AcsDialSharedConnectionNoUser: RasDial");
  783. hrasconn = NULL;
  784. ZeroMemory(&rc, sizeof(rc));
  785. dwErr = (DWORD)(*lpfnRasDialG)(
  786. &rde, rsc.name.szPhonebookPath, &rdp, 0, NULL, &hrasconn
  787. );
  788. ZeroMemory(&rdp, sizeof(rdp));
  789. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: RasDial=%d", dwErr);
  790. if (E_NOTIMPL == dwErr)
  791. {
  792. //
  793. // This is possibly a Connection Manager connection since it's returning E_NOTIMPL,
  794. // we should check the phonebook entry for the type and then call the RasDialDlg
  795. // with the RASDDFLAG_NoPrompt flag.
  796. //
  797. RASDIALDLG info;
  798. BOOL fRetVal = FALSE;
  799. HINSTANCE hRasDlgDll = NULL;
  800. FARPROC lpfnRasDialDlg = NULL;
  801. RASENTRY re;
  802. DWORD dwRasEntrySize;
  803. DWORD dwIgnore;
  804. typedef BOOL (*lpfnRasDialDlgFunc)(LPWSTR, LPWSTR, LPWSTR, LPRASDIALDLG);
  805. ZeroMemory(&info, sizeof(info));
  806. info.dwSize = sizeof(info);
  807. ZeroMemory(&re, sizeof(re));
  808. dwRasEntrySize = sizeof(re);
  809. re.dwSize = dwRasEntrySize;
  810. dwErr = (DWORD)(*lpfnRasGetEntryPropertiesG)(
  811. rsc.name.szPhonebookPath,
  812. rsc.name.szEntryName,
  813. &re,
  814. &dwRasEntrySize,
  815. NULL,
  816. &dwIgnore);
  817. if (ERROR_SUCCESS == dwErr)
  818. {
  819. dwErr = ERROR_NOT_SUPPORTED;
  820. //
  821. // Check if this is a Connection Manager entry
  822. //
  823. if (RASET_Internet == re.dwType)
  824. {
  825. //
  826. // Prevent the DialerDialog
  827. //
  828. info.dwFlags |= RASDDFLAG_NoPrompt;
  829. hRasDlgDll = LoadLibrary(L"RASDLG.DLL");
  830. if (hRasDlgDll)
  831. {
  832. lpfnRasDialDlgFunc lpfnRasDialDlg = (lpfnRasDialDlgFunc)GetProcAddress(hRasDlgDll, "RasDialDlgW");
  833. if (lpfnRasDialDlg)
  834. {
  835. fRetVal = (BOOL)(lpfnRasDialDlg)(rsc.name.szPhonebookPath, rsc.name.szEntryName, NULL, &info );
  836. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: lpfnRasDialDlg returns %d", (DWORD)fRetVal);
  837. if (fRetVal)
  838. {
  839. dwErr = ERROR_SUCCESS;
  840. }
  841. }
  842. else
  843. {
  844. RASAUTO_TRACE("AcsDialSharedConnectionNoUser: Failed to get procaddress for RasDialDlgW");
  845. }
  846. FreeLibrary(hRasDlgDll);
  847. hRasDlgDll = NULL;
  848. }
  849. else
  850. {
  851. RASAUTO_TRACE("AcsDialSharedConnectionNoUser: Failed to load RASDLG.dll");
  852. }
  853. }
  854. else
  855. {
  856. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: Wrong type. RASENTRY.dwType=%d", re.dwType);
  857. }
  858. }
  859. else
  860. {
  861. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: lpfnRasGetEntryPropertiesG=%d", dwErr);
  862. }
  863. }
  864. //
  865. // If RasDial returned an error and passed back a valid connection
  866. // handle we need to call RasHangUp on that handle.
  867. //
  868. if (ERROR_SUCCESS != dwErr && NULL != hrasconn) {
  869. dwErr = (DWORD)(*lpfnRasHangUpG)(hrasconn);
  870. RASAUTO_TRACE1("AcsDialSharedConnectionNoUser: RasHangUp=%d", dwErr);
  871. }
  872. return NO_ERROR;
  873. }
  874. BOOLEAN
  875. ResetEntryName(
  876. IN PVOID pArg,
  877. IN LPTSTR pszAddress,
  878. IN PVOID pData
  879. )
  880. /*++
  881. DESCRIPTION
  882. A table enumerator procedure to reset all
  883. address map entries referencing an old RAS
  884. phonebook entry to a new one.
  885. ARGUMENTS
  886. pArg: a pointer to a RESET_ENTRY_INFO structure
  887. pszAddress: a pointer to the address string
  888. pData: ignored
  889. RETURN VALUE
  890. Always TRUE to continue the enumeration.
  891. --*/
  892. {
  893. PRESET_ENTRY_INFO pResetEntryInfo = (PRESET_ENTRY_INFO)pArg;
  894. LPTSTR pszEntryName;
  895. if (GetAddressDialingLocationEntry(pszAddress, &pszEntryName)) {
  896. if (!_wcsicmp(pszEntryName, pResetEntryInfo->pszOldEntryName)) {
  897. if (!SetAddressDialingLocationEntry(
  898. pszAddress,
  899. pResetEntryInfo->pszNewEntryName))
  900. {
  901. RASAUTO_TRACE("ResetEntryName: SetAddressEntryName failed");
  902. }
  903. }
  904. LocalFree(pszEntryName);
  905. }
  906. return TRUE;
  907. } // ResetEntryName
  908. BOOL
  909. fRequestToSelf(LPTSTR lpRemoteName)
  910. {
  911. BOOL fRet = FALSE;
  912. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  913. DWORD dwSize;
  914. RASAUTO_TRACE1("fRequestToSelf. lpRemoteName=%S", lpRemoteName);
  915. dwSize = MAX_COMPUTERNAME_LENGTH;
  916. if(GetComputerName(szComputerName, &dwSize))
  917. {
  918. if(0 == lstrcmpi(lpRemoteName, szComputerName))
  919. {
  920. fRet = TRUE;
  921. }
  922. }
  923. return fRet;
  924. }
  925. BOOLEAN
  926. CreateConnection(
  927. IN HANDLE hProcess,
  928. IN PACD_ADDR pAddr,
  929. IN LPTSTR lpRemoteName,
  930. IN DWORD dwTimeout
  931. )
  932. /*++
  933. DESCRIPTION
  934. Take a notification and figure out what to do with it.
  935. ARGUMENTS
  936. hToken: the handle to the process token that we inherit the
  937. security attributes from when we exec the dialer
  938. pAddr: a pointer to the original address from the driver
  939. lpRemoteName: a pointer to the address of the connection attempt
  940. dwTimeout: number of seconds to disable the address between
  941. failed connections
  942. RETURN VALUE
  943. Returns TRUE if the net attempt should be retried, FALSE otherwise.
  944. --*/
  945. {
  946. DWORD dwStatus = WN_SUCCESS;
  947. RASENTRYNAME entry;
  948. DWORD dwErr, dwSize, dwEntries;
  949. DWORD dwPreConnections, dwPostConnections, i;
  950. DWORD dwTicks;
  951. BOOLEAN fRasLoaded;
  952. BOOLEAN fMappingExists, fRasConnectSuccess = FALSE;
  953. BOOLEAN fStatus, fEntryInvalid;
  954. BOOLEAN fFailedConnection = FALSE;
  955. LPTSTR lpEntryName = NULL;
  956. LPTSTR *lpPreActiveEntries = NULL, *lpPostActiveEntries = NULL;
  957. LPTSTR lpNewConnection, lpNetworkName = NULL;
  958. BOOL fDefault = FALSE;
  959. RASAUTO_TRACE1("CreateConnection: lpRemoteName=%S", RASAUTO_TRACESTRW(lpRemoteName));
  960. //
  961. // Load the RAS DLLs.
  962. //
  963. fRasLoaded = LoadRasDlls();
  964. if (!fRasLoaded) {
  965. RASAUTO_TRACE("CreateConnection: Could not load RAS DLLs.");
  966. goto done;
  967. }
  968. //
  969. // Check to see if the request is for the same machine. Bail if so.
  970. // we don't want autodial to kick in if the connection request is
  971. // to the same machine.
  972. //
  973. if(fRequestToSelf(lpRemoteName))
  974. {
  975. RASAUTO_TRACE("CreateConnetion: Request to self. Bailing.");
  976. goto done;
  977. }
  978. //
  979. // Get a list of the active RAS connections before
  980. // we attempt to create a new one.
  981. //
  982. dwPreConnections = ActiveConnections(TRUE, &lpPreActiveEntries, NULL);
  983. RASAUTO_TRACE1("CreateConnection: dwPreConnections=%d", dwPreConnections);
  984. //
  985. // If we reach this point, we have an unsuccessful
  986. // network connection without any active RAS
  987. // connections. Try to start the implicit connection
  988. // machinery. See if there already exists a mapping
  989. // for the address.
  990. //
  991. LockAddressMap();
  992. //
  993. // Make sure we have the current information
  994. // about this address from the registry.
  995. //
  996. ResetAddressMapAddress(lpRemoteName);
  997. fMappingExists = GetAddressDialingLocationEntry(lpRemoteName, &lpEntryName);
  998. //
  999. // If the entry doesn't exist, and this is a
  1000. // Internet hostname, then see if we can find
  1001. // an address with the same organization name.
  1002. //
  1003. if (!fMappingExists && pAddr->fType == ACD_ADDR_INET)
  1004. fMappingExists = GetSimilarDialingLocationEntry(lpRemoteName, &lpEntryName);
  1005. fFailedConnection = GetAddressLastFailedConnectTime(
  1006. lpRemoteName,
  1007. &dwTicks);
  1008. UnlockAddressMap();
  1009. RASAUTO_TRACE2(
  1010. "CreateConnection: lookup of %S returned %S",
  1011. RASAUTO_TRACESTRW(lpRemoteName),
  1012. RASAUTO_TRACESTRW(lpEntryName));
  1013. //
  1014. // If we know nothing about the address, and
  1015. // we are connected to some network, then ignore
  1016. // the request.
  1017. //
  1018. if (!fMappingExists && IsNetworkConnected()) {
  1019. RASAUTO_TRACE1(
  1020. "CreateConnection: no mapping for lpRemoteName=%S and connected to a network",
  1021. lpRemoteName);
  1022. goto done;
  1023. }
  1024. //
  1025. // If no mapping exists and not connected to network,
  1026. // check to see if theres a default internet connection.
  1027. //
  1028. if(!fMappingExists && !IsNetworkConnected())
  1029. {
  1030. RASAUTO_TRACE1(
  1031. "CreateConnection: no mapping for lpRemoteName=%S and"
  1032. " not connected to a network", lpRemoteName);
  1033. dwErr = DwGetDefaultEntryName(&lpEntryName);
  1034. RASAUTO_TRACE1(
  1035. "CreateConnection: found default entry %S",
  1036. (NULL == lpEntryName)?TEXT("NULL"):lpEntryName);
  1037. if(NULL != lpEntryName)
  1038. {
  1039. fMappingExists = TRUE;
  1040. fDefault = TRUE;
  1041. }
  1042. }
  1043. //
  1044. // If there is a mapping, but the phonebook
  1045. // entry is missing from the mapping, then
  1046. // ignore the request. Also check to make
  1047. // sure the phonebook entry isn't already
  1048. // connected.
  1049. //
  1050. //
  1051. // Perform various checks on the mapping.
  1052. //
  1053. if (fMappingExists) {
  1054. BOOLEAN bStatus, bConnected = FALSE;
  1055. //
  1056. // Make sure it's not NULL.
  1057. //
  1058. if (!wcslen(lpEntryName)) {
  1059. RASAUTO_TRACE1(
  1060. "CreateConnection: lpRemoteName=%S is permanently disabled",
  1061. RASAUTO_TRACESTRW(lpRemoteName));
  1062. goto done;
  1063. }
  1064. //
  1065. // If the network associated with this
  1066. // entry is connected, then ignore the
  1067. // request.
  1068. //
  1069. lpNetworkName = EntryToNetwork(lpEntryName);
  1070. RASAUTO_TRACE2(
  1071. "CreateConnection: network for entry %S is %S",
  1072. lpEntryName,
  1073. RASAUTO_TRACESTRW(lpNetworkName));
  1074. if (lpNetworkName != NULL) {
  1075. LockNetworkMap();
  1076. bStatus = GetNetworkConnected(lpNetworkName, &bConnected);
  1077. UnlockNetworkMap();
  1078. if (bStatus && bConnected) {
  1079. RASAUTO_TRACE1(
  1080. "CreateConnection: %S is already connected!",
  1081. RASAUTO_TRACESTRW(lpEntryName));
  1082. fRasConnectSuccess = TRUE;
  1083. goto done;
  1084. }
  1085. }
  1086. //
  1087. // If the entry itself is connected,
  1088. // then ignore the request. We need
  1089. // to do this check as well as the one
  1090. // above, because the mapping may not
  1091. // have a network assigned to it yet.
  1092. //
  1093. for (i = 0; i < dwPreConnections; i++) {
  1094. if (!_wcsicmp(lpEntryName, lpPreActiveEntries[i])) {
  1095. RASAUTO_TRACE1(
  1096. "CreateConnection: lpEntryName=%S is already connected!", lpEntryName);
  1097. goto done;
  1098. }
  1099. }
  1100. }
  1101. //
  1102. // Check for a recent failed connection
  1103. // attempt.
  1104. //
  1105. if (fFailedConnection) {
  1106. RASAUTO_TRACE1(
  1107. "CreateConnection: RASADP_FailedConnectionTimeout=%d",
  1108. dwTimeout);
  1109. if (GetTickCount() - dwTicks < dwTimeout * 1000) {
  1110. RASAUTO_TRACE2(
  1111. "CreateConnection: lpRemoteName=%S is temporarily disabled (failed connection %d ticks ago)",
  1112. RASAUTO_TRACESTRW(lpRemoteName),
  1113. GetTickCount() - dwTicks);
  1114. goto done;
  1115. }
  1116. else {
  1117. //
  1118. // Reset last failed tick count.
  1119. //
  1120. fFailedConnection = FALSE;
  1121. }
  1122. }
  1123. //
  1124. // If a mapping already exists for the address, then
  1125. // start rasphone with the address. Otherwise, simply
  1126. // have rasphone show the entire phonebook.
  1127. //
  1128. fEntryInvalid = FALSE;
  1129. fRasConnectSuccess = StartAutoDialer(
  1130. hProcess,
  1131. pAddr,
  1132. lpRemoteName,
  1133. fMappingExists ? lpEntryName : NULL,
  1134. FALSE,
  1135. &fEntryInvalid);
  1136. RASAUTO_TRACE1(
  1137. "CreateConnection: StartDialer returned %d",
  1138. fRasConnectSuccess);
  1139. if (fRasConnectSuccess) {
  1140. //
  1141. // Get the list of active connections again. We will
  1142. // compare the lists to determine which is the new
  1143. // entry.
  1144. //
  1145. dwPostConnections = ActiveConnections(
  1146. TRUE,
  1147. &lpPostActiveEntries,
  1148. NULL);
  1149. //
  1150. // If the number of active connections before and after
  1151. // the newly created connection differs by more than 1,
  1152. // then we have to skip saving the mapping in the registry,
  1153. // since we cannot determine which is the right one!
  1154. //
  1155. if (dwPostConnections - dwPreConnections == 1) {
  1156. lpNewConnection = CompareConnectionLists(
  1157. lpPreActiveEntries,
  1158. dwPreConnections,
  1159. lpPostActiveEntries,
  1160. dwPostConnections);
  1161. RASAUTO_TRACE2(
  1162. "CreateConnection: mapped %S->%S",
  1163. RASAUTO_TRACESTRW(lpRemoteName),
  1164. RASAUTO_TRACESTRW(lpNewConnection));
  1165. LockAddressMap();
  1166. if (!fEntryInvalid) {
  1167. //
  1168. // Store the new RAS phonebook entry, since
  1169. // it could be different from the one we
  1170. // retrieved in the mapping.
  1171. //
  1172. // #ifdef notdef
  1173. if(!fDefault)
  1174. {
  1175. //
  1176. // We do not want to do this because the
  1177. // user may have selected the wrong phonebook
  1178. // entry. We will let a successful connection
  1179. // notification map it for us.
  1180. //
  1181. fStatus = SetAddressDialingLocationEntry(lpRemoteName, lpNewConnection);
  1182. // #endif
  1183. fStatus = SetAddressTag(lpRemoteName, ADDRMAP_TAG_USED);
  1184. }
  1185. }
  1186. else {
  1187. RESET_ENTRY_INFO resetEntryInfo;
  1188. //
  1189. // If the RAS phonebook entry in the mapping
  1190. // was invalid, then automatically
  1191. // remap all other mappings referencing that
  1192. // entry to the newly selected phonebook entry.
  1193. //
  1194. resetEntryInfo.pszOldEntryName = lpEntryName;
  1195. resetEntryInfo.pszNewEntryName = lpNewConnection;
  1196. EnumAddressMap(ResetEntryName, &resetEntryInfo);
  1197. }
  1198. //
  1199. // Flush this mapping to the registry now
  1200. // and reload the address info. We do this to
  1201. // get the network name for a new address/network
  1202. // pair.
  1203. //
  1204. FlushAddressMap();
  1205. ResetAddressMapAddress(lpRemoteName);
  1206. if (lpNetworkName == NULL &&
  1207. GetAddressNetwork(lpRemoteName, &lpNetworkName))
  1208. {
  1209. LockNetworkMap();
  1210. SetNetworkConnected(lpNetworkName, TRUE);
  1211. UnlockNetworkMap();
  1212. }
  1213. UnlockAddressMap();
  1214. if (!fStatus)
  1215. RASAUTO_TRACE("CreateConnection: SetAddressEntryName failed");
  1216. }
  1217. else {
  1218. RASAUTO_TRACE1(
  1219. "CreateConnection: %d (> 1) new RAS connections! (can't write registry)",
  1220. dwPostConnections - dwPreConnections);
  1221. }
  1222. }
  1223. done:
  1224. #ifdef notdef
  1225. // we only unload rasman.dll if we are going to exit
  1226. if (fRasLoaded)
  1227. UnloadRasDlls();
  1228. #endif
  1229. if (!fFailedConnection && !fRasConnectSuccess) {
  1230. //
  1231. // If the connection attempt wasn't successful,
  1232. // then we disable future connections to that
  1233. // address for a while.
  1234. //
  1235. RASAUTO_TRACE1("CreateConnection: disabling %S", RASAUTO_TRACESTRW(lpRemoteName));
  1236. LockAddressMap();
  1237. fStatus = SetAddressLastFailedConnectTime(lpRemoteName);
  1238. UnlockAddressMap();
  1239. if (!fStatus)
  1240. RASAUTO_TRACE("CreateConnection: SetAddressAttribute failed");
  1241. }
  1242. //
  1243. // Free resources.
  1244. //
  1245. if (lpEntryName != NULL)
  1246. LocalFree(lpEntryName);
  1247. if (lpNetworkName != NULL)
  1248. LocalFree(lpNetworkName);
  1249. if (lpPreActiveEntries != NULL)
  1250. FreeStringArray(lpPreActiveEntries, dwPreConnections);
  1251. if (lpPostActiveEntries != NULL)
  1252. FreeStringArray(lpPostActiveEntries, dwPostConnections);
  1253. return fRasConnectSuccess;
  1254. } // CreateConnection
  1255. DWORD
  1256. AcsRedialOnLinkFailureThread(
  1257. LPVOID lpArg
  1258. )
  1259. {
  1260. DWORD dwErr;
  1261. PREDIAL_ARGS pRedial = (PREDIAL_ARGS)lpArg;
  1262. HANDLE hProcess = NULL;
  1263. RASAUTO_TRACE2(
  1264. "AcsRedialOnLinkFailureThread: lpszPhonebook=%s, lpszEntry=%s",
  1265. RASAUTO_TRACESTRW(pRedial->pszPhonebook),
  1266. RASAUTO_TRACESTRW(pRedial->pszEntry));
  1267. //
  1268. // Make sure the current thread is impersonating
  1269. // the currently logged-on user. We need this
  1270. // so the RAS utilities run with the user's credentials.
  1271. //
  1272. if ((hProcess = RefreshImpersonation(hProcess)) == NULL) {
  1273. RASAUTO_TRACE("AcsRedialOnLinkFailureThread: no currently logged-on user!");
  1274. return 0;
  1275. }
  1276. //
  1277. // Reset HKEY_CURRENT_USER to get the
  1278. // correct value with the new impersonation
  1279. // token.
  1280. //
  1281. // RegCloseKey(HKEY_CURRENT_USER);
  1282. /* Check that user has enabled redial on link failure.
  1283. */
  1284. {
  1285. BOOL fRedial = FALSE;
  1286. dwErr = (DWORD)(lpfnRasQueryRedialOnLinkFailureG)(
  1287. pRedial->pszPhonebook,
  1288. pRedial->pszEntry,
  1289. &fRedial);
  1290. if(!fRedial)
  1291. {
  1292. PBUSER user;
  1293. dwErr = GetUserPreferences( NULL, &user, FALSE );
  1294. if (dwErr == 0)
  1295. {
  1296. fRedial = user.fRedialOnLinkFailure;
  1297. DestroyUserPreferences( &user );
  1298. }
  1299. }
  1300. if (!fRedial)
  1301. {
  1302. RASAUTO_TRACE1("Skip redial,e=%d",dwErr);
  1303. return 0;
  1304. }
  1305. }
  1306. //
  1307. // Redial the entry.
  1308. //
  1309. dwErr = StartReDialer(hProcess, pRedial->pszPhonebook, pRedial->pszEntry);
  1310. //
  1311. // Free the parameter block we were passed.
  1312. //
  1313. if (pRedial->pszPhonebook != NULL)
  1314. LocalFree(pRedial->pszPhonebook);
  1315. if (pRedial->pszEntry != NULL)
  1316. LocalFree(pRedial->pszEntry);
  1317. LocalFree(pRedial);
  1318. return dwErr;
  1319. } // AcsRedialOnLinkFailureThread
  1320. VOID
  1321. AcsRedialOnLinkFailure(
  1322. IN LPSTR lpszPhonebook,
  1323. IN LPSTR lpszEntry
  1324. )
  1325. /*++
  1326. DESCRIPTION
  1327. This is the redial-on-link-failure handler we give to rasman
  1328. via RasRegisterRedialCallback. It gets called when the final
  1329. port of a connection is disconnected due to a hardware failure.
  1330. We package up the parameters rasman gives us an create a thread
  1331. because the callback is made within rasman's worker thread
  1332. context.
  1333. ARGUMENTS
  1334. lpszPhonebook: the phonebook string of the connection
  1335. lpszEntry: the entry name of the connection
  1336. RETURN VALUE
  1337. None.
  1338. --*/
  1339. {
  1340. PREDIAL_ARGS lpRedial = LocalAlloc(LPTR, sizeof (REDIAL_ARGS));
  1341. HANDLE hThread;
  1342. DWORD dwThreadId;
  1343. if (lpRedial == NULL)
  1344. return;
  1345. lpRedial->pszPhonebook = AnsiStringToUnicodeString(
  1346. lpszPhonebook,
  1347. NULL,
  1348. 0);
  1349. if (lpszPhonebook != NULL && lpRedial->pszPhonebook == NULL) {
  1350. RASAUTO_TRACE("AcsRedialOnLinkFailure: LocalAlloc failed");
  1351. LocalFree(lpRedial);
  1352. return;
  1353. }
  1354. lpRedial->pszEntry = AnsiStringToUnicodeString(
  1355. lpszEntry,
  1356. NULL,
  1357. 0);
  1358. if (lpszEntry != NULL && lpRedial->pszEntry == NULL) {
  1359. RASAUTO_TRACE("AcsRedialOnLinkFailure: LocalAlloc failed");
  1360. LocalFree(lpRedial->pszPhonebook);
  1361. LocalFree(lpRedial);
  1362. return;
  1363. }
  1364. //
  1365. // Start the connection.
  1366. //
  1367. hThread = CreateThread(
  1368. NULL,
  1369. 10000L,
  1370. (LPTHREAD_START_ROUTINE)AcsRedialOnLinkFailureThread,
  1371. (LPVOID)lpRedial,
  1372. 0,
  1373. &dwThreadId);
  1374. if (hThread == NULL) {
  1375. RASAUTO_TRACE1(
  1376. "AcsRedialOnLinkFailure: CreateThread failed (error=0x%x)",
  1377. GetLastError());
  1378. LocalFree(lpRedial->pszEntry);
  1379. LocalFree(lpRedial->pszPhonebook);
  1380. LocalFree(lpRedial);
  1381. return;
  1382. }
  1383. CloseHandle(hThread);
  1384. } // AcsRedialOnLinkFailure