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.

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