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.

1375 lines
34 KiB

  1. #define UNICODE
  2. #define _UNICODE
  3. #include <nt.h>
  4. #include <ntrtl.h>
  5. #include <nturtl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <windows.h>
  9. #include <npapi.h>
  10. #include <winsock.h>
  11. #include <wsnetbs.h>
  12. #include <ras.h>
  13. #include <raserror.h>
  14. #include <rasdlg.h>
  15. #include <tapi.h>
  16. #include <commctrl.h> // added to be "Fusionized"
  17. #include <shfusion.h> // added to be "Fusionized"
  18. #include "process.h"
  19. //
  20. // Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized" for
  21. // UI conistency w/Connections Folder
  22. //
  23. HANDLE g_hModule = NULL;
  24. //
  25. // All projection types. Used to
  26. // determine if a connection was
  27. // completed.
  28. //
  29. #define MAX_PROJECTIONS 5
  30. struct RASPROJECTIONINFO {
  31. DWORD dwTag;
  32. DWORD dwSize;
  33. } projections[MAX_PROJECTIONS] = {
  34. RASP_Amb, sizeof (RASAMB),
  35. RASP_PppNbf, sizeof (RASPPPNBF),
  36. RASP_PppIpx, sizeof (RASPPPIPX),
  37. RASP_PppIp, sizeof (RASPPPIP),
  38. RASP_PppLcp, sizeof (RASPPPLCP)
  39. };
  40. //
  41. // Timer thread information.
  42. //
  43. typedef struct _TIMER_INFO {
  44. HANDLE hEvent;
  45. DWORD dwTimeout;
  46. } TIMER_INFO, *PTIMER_INFO;
  47. //
  48. // Private rasdlg functions.
  49. //
  50. DWORD
  51. RasAutodialQueryDlgW(
  52. IN HWND hwnd,
  53. IN PWCHAR pszAddress,
  54. IN PWCHAR pszEntry,
  55. IN DWORD dwTimeout,
  56. OUT PWCHAR pszEntrySelectedByUser
  57. );
  58. BOOLEAN
  59. RasAutodialDisableDlgW(
  60. HWND hwnd
  61. );
  62. PSYSTEM_PROCESS_INFORMATION
  63. GetSystemProcessInfo()
  64. /*++
  65. DESCRIPTION
  66. Return a block containing information about all processes
  67. currently running in the system.
  68. ARGUMENTS
  69. None.
  70. RETURN VALUE
  71. A pointer to the system process information or NULL if it could
  72. not be allocated or retrieved.
  73. --*/
  74. {
  75. NTSTATUS status = STATUS_SUCCESS;
  76. PUCHAR pLargeBuffer;
  77. ULONG ulcbLargeBuffer = 64 * 1024;
  78. //
  79. // Get the process list.
  80. //
  81. for (;;) {
  82. pLargeBuffer = VirtualAlloc(
  83. NULL,
  84. ulcbLargeBuffer, MEM_COMMIT, PAGE_READWRITE);
  85. if (pLargeBuffer == NULL) {
  86. printf(
  87. "GetSystemProcessInfo: VirtualAlloc failed (status=0x%x)\n",
  88. status);
  89. return NULL;
  90. }
  91. status = NtQuerySystemInformation(
  92. SystemProcessInformation,
  93. pLargeBuffer,
  94. ulcbLargeBuffer,
  95. NULL);
  96. if (status == STATUS_SUCCESS) break;
  97. if (status == STATUS_INFO_LENGTH_MISMATCH) {
  98. VirtualFree(pLargeBuffer, 0, MEM_RELEASE);
  99. ulcbLargeBuffer += 8192;
  100. }
  101. }
  102. return (PSYSTEM_PROCESS_INFORMATION)pLargeBuffer;
  103. } // GetSystemProcessInfo
  104. PSYSTEM_PROCESS_INFORMATION
  105. FindProcessByName(
  106. IN PSYSTEM_PROCESS_INFORMATION pProcessInfo,
  107. IN LPWSTR lpExeName
  108. )
  109. /*++
  110. DESCRIPTION
  111. Given a pointer returned by GetSystemProcessInfo(), find
  112. a process by name.
  113. ARGUMENTS
  114. pProcessInfo: a pointer returned by GetSystemProcessInfo().
  115. lpExeName: a pointer to a Unicode string containing the
  116. process to be found.
  117. RETURN VALUE
  118. A pointer to the process information for the supplied
  119. process or NULL if it could not be found.
  120. --*/
  121. {
  122. PUCHAR pLargeBuffer = (PUCHAR)pProcessInfo;
  123. ULONG ulTotalOffset = 0;
  124. //
  125. // Look in the process list for lpExeName.
  126. //
  127. for (;;) {
  128. if (pProcessInfo->ImageName.Buffer != NULL) {
  129. if (!_wcsicmp(pProcessInfo->ImageName.Buffer, lpExeName))
  130. return pProcessInfo;
  131. }
  132. //
  133. // Increment offset to next process information block.
  134. //
  135. if (!pProcessInfo->NextEntryOffset)
  136. break;
  137. ulTotalOffset += pProcessInfo->NextEntryOffset;
  138. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pLargeBuffer[ulTotalOffset];
  139. }
  140. return NULL;
  141. } // FindProcessByName
  142. VOID
  143. FreeSystemProcessInfo(
  144. IN PSYSTEM_PROCESS_INFORMATION pProcessInfo
  145. )
  146. /*++
  147. DESCRIPTION
  148. Free a buffer returned by GetSystemProcessInfo().
  149. ARGUMENTS
  150. pProcessInfo: the pointer returned by GetSystemProcessInfo().
  151. RETURN VALUE
  152. None.
  153. --*/
  154. {
  155. VirtualFree((PUCHAR)pProcessInfo, 0, MEM_RELEASE);
  156. } // FreeSystemProcessInfo
  157. DWORD
  158. ActiveConnections()
  159. {
  160. DWORD dwErr, dwcbConnections = 0, dwcConnections = 0;
  161. DWORD i, j, dwTmp, dwSize;
  162. RASCONN rasconn;
  163. LPRASCONN lpRasCon = &rasconn;
  164. RASCONNSTATUS rasconnstatus;
  165. //
  166. // Determine how much memory we
  167. // need to allocate.
  168. //
  169. lpRasCon->dwSize = sizeof (RASCONN);
  170. dwErr = RasEnumConnections(lpRasCon, &dwcbConnections, &dwcConnections);
  171. if (dwErr == ERROR_BUFFER_TOO_SMALL) {
  172. lpRasCon = LocalAlloc(LPTR, dwcbConnections);
  173. if (lpRasCon == NULL)
  174. return 0;
  175. //
  176. // Call again to fill the buffer.
  177. //
  178. lpRasCon->dwSize = sizeof (RASCONN);
  179. dwErr = RasEnumConnections(lpRasCon, &dwcbConnections, &dwcConnections);
  180. }
  181. if (dwErr)
  182. goto done;
  183. dwTmp = dwcConnections;
  184. for (i = 0; i < dwTmp; i++) {
  185. rasconnstatus.dwSize = sizeof (RASCONNSTATUS);
  186. dwErr = RasGetConnectStatus(
  187. lpRasCon[i].hrasconn,
  188. &rasconnstatus);
  189. if (dwErr || rasconnstatus.rasconnstate != RASCS_Connected)
  190. dwcConnections--;
  191. }
  192. done:
  193. if (lpRasCon != &rasconn)
  194. LocalFree(lpRasCon);
  195. return dwErr ? 0 : dwcConnections;
  196. } // ActiveConnections
  197. void
  198. TapiLineCallback(
  199. IN DWORD hDevice,
  200. IN DWORD dwMessage,
  201. IN ULONG_PTR dwInstance,
  202. IN ULONG_PTR dwParam1,
  203. IN ULONG_PTR dwParam2,
  204. IN ULONG_PTR dwParam3
  205. )
  206. {
  207. } // TapiLineCallback
  208. DWORD
  209. GetCurrentDialingLocation()
  210. {
  211. DWORD dwErr, dwcDevices, dwLocationID;
  212. HLINEAPP hlineApp;
  213. LINETRANSLATECAPS caps;
  214. LINETRANSLATECAPS *pCaps;
  215. //
  216. // Initialize TAPI.
  217. //
  218. dwErr = lineInitialize(
  219. &hlineApp,
  220. GetModuleHandle(NULL),
  221. TapiLineCallback,
  222. NULL,
  223. &dwcDevices);
  224. if (dwErr)
  225. return 0;
  226. //
  227. // Get the dialing location from TAPI.
  228. //
  229. RtlZeroMemory(&caps, sizeof (LINETRANSLATECAPS));
  230. caps.dwTotalSize = sizeof (LINETRANSLATECAPS);
  231. dwErr = lineGetTranslateCaps(hlineApp, 0x10004, &caps);
  232. if (dwErr)
  233. return 0;
  234. pCaps = (LINETRANSLATECAPS *)LocalAlloc(LPTR, caps.dwNeededSize);
  235. if (pCaps == NULL)
  236. return 0;
  237. RtlZeroMemory(pCaps, sizeof (LINETRANSLATECAPS));
  238. pCaps->dwTotalSize = caps.dwNeededSize;
  239. dwErr = lineGetTranslateCaps(hlineApp, 0x10004, pCaps);
  240. if (dwErr) {
  241. LocalFree(pCaps);
  242. return 0;
  243. }
  244. dwLocationID = pCaps->dwCurrentLocationID;
  245. LocalFree(pCaps);
  246. //
  247. // Shutdown TAPI.
  248. //
  249. dwErr = lineShutdown(hlineApp);
  250. return dwLocationID;
  251. } // GetCurrentDialingLocation
  252. DWORD
  253. TimerThread(
  254. LPVOID lpArg
  255. )
  256. {
  257. NTSTATUS status;
  258. PTIMER_INFO pTimerInfo = (PTIMER_INFO)lpArg;
  259. HANDLE hEvent = pTimerInfo->hEvent;
  260. DWORD dwTimeout = pTimerInfo->dwTimeout;
  261. LocalFree(pTimerInfo);
  262. //
  263. // Wait for the timeout period. If hEvent
  264. // gets signaled before the timeout period
  265. // expires, then the user has addressed the
  266. // dialog and we return. Otherwise, we simply
  267. // exit.
  268. //
  269. if (WaitForSingleObject(hEvent, dwTimeout * 1000) == WAIT_TIMEOUT)
  270. exit(1);
  271. return 0;
  272. } // TimerThread
  273. DWORD
  274. DisplayRasDialog(
  275. IN LPTSTR pszPhonebook,
  276. IN LPTSTR pszEntry,
  277. IN LPTSTR pszAddress,
  278. IN BOOLEAN fRedialMode,
  279. IN BOOLEAN fQuiet
  280. )
  281. {
  282. NTSTATUS status;
  283. DWORD dwErr = 0, dwSize, dwCount = 0;
  284. DWORD dwcConnections, dwfDisableConnectionQuery;
  285. DWORD dwPreDialingLocation, dwPostDialingLocation;
  286. DWORD dwConnectionQueryTimeout;
  287. STARTUPINFO StartupInfo;
  288. PROCESS_INFORMATION ProcessInfo;
  289. PSYSTEM_PROCESS_INFORMATION pSystemInfo;
  290. BOOLEAN fCancelled;
  291. LPRASAUTODIALENTRY pAutodialEntries = NULL;
  292. DWORD dwcbAutodialEntries = 0, dwcAutodialEntries = 0;
  293. WCHAR pszNewEntry[RAS_MaxEntryName + 1];
  294. wcscpy(pszNewEntry, L"\0");
  295. //
  296. // Check to see if the user has disabled
  297. // the Autodial query dialog when the
  298. // phonebook entry to dial is known.
  299. //
  300. if (fRedialMode || fQuiet)
  301. dwfDisableConnectionQuery = TRUE;
  302. else {
  303. dwSize = sizeof (DWORD);
  304. (void)RasGetAutodialParam(
  305. RASADP_DisableConnectionQuery,
  306. &dwfDisableConnectionQuery,
  307. &dwSize);
  308. }
  309. //
  310. // Ask the user if he wants to dial if either the
  311. // phonebook entry is not known or the user has
  312. // not disabled the "always ask me before dialing"
  313. // parameter.
  314. //
  315. // If RasDialDlg() returns FALSE, the user didn't
  316. // want to dial.
  317. //
  318. if (pszEntry == NULL || !dwfDisableConnectionQuery) {
  319. dwSize = sizeof (DWORD);
  320. (void)RasGetAutodialParam(
  321. RASADP_ConnectionQueryTimeout,
  322. &dwConnectionQueryTimeout,
  323. &dwSize);
  324. //
  325. // Save the current dialing location to
  326. // see if the user changed it inside the
  327. // dialog.
  328. //
  329. dwPreDialingLocation = GetCurrentDialingLocation();
  330. dwErr = RasAutodialQueryDlgW(
  331. NULL, pszAddress, pszEntry, dwConnectionQueryTimeout, pszNewEntry);
  332. // Whistler: 255816
  333. //
  334. // Only disable the address if an error occurs.
  335. // If the user simply types 'no' then CANCEL is
  336. // returned from rasdlg, but we'll return NO_ERROR to the
  337. // rasauto service so that the address remains enabled.
  338. //
  339. if (dwErr == ERROR_CANCELLED)
  340. {
  341. return NO_ERROR;
  342. }
  343. else if (dwErr != NO_ERROR)
  344. {
  345. return ERROR_CANCELLED;
  346. }
  347. dwPostDialingLocation = GetCurrentDialingLocation();
  348. //
  349. // If the user changed the dialing location
  350. // within the dialog, then get the new entry.
  351. //
  352. if (dwPreDialingLocation != dwPostDialingLocation) {
  353. pszEntry = NULL;
  354. dwErr = RasGetAutodialAddress(
  355. pszAddress,
  356. NULL,
  357. NULL,
  358. &dwcbAutodialEntries,
  359. &dwcAutodialEntries);
  360. if (dwErr == ERROR_BUFFER_TOO_SMALL && dwcAutodialEntries)
  361. pAutodialEntries = LocalAlloc(LPTR, dwcbAutodialEntries);
  362. if (dwcAutodialEntries && pAutodialEntries != NULL) {
  363. pAutodialEntries[0].dwSize = sizeof (RASAUTODIALENTRY);
  364. dwErr = RasGetAutodialAddress(
  365. pszAddress,
  366. NULL,
  367. pAutodialEntries,
  368. &dwcbAutodialEntries,
  369. &dwcAutodialEntries);
  370. if (!dwErr) {
  371. DWORD i;
  372. for (i = 0; i < dwcAutodialEntries; i++) {
  373. if (pAutodialEntries[i].dwDialingLocation ==
  374. dwPostDialingLocation)
  375. {
  376. pszEntry = pAutodialEntries[i].szEntry;
  377. break;
  378. }
  379. }
  380. }
  381. }
  382. }
  383. // Whistler: new autodial UI
  384. //
  385. // The connection that the user wants to dial will be in
  386. // pszNewEntry.
  387. //
  388. else
  389. {
  390. if (*pszNewEntry)
  391. {
  392. pszEntry = pszNewEntry;
  393. }
  394. }
  395. }
  396. if (pszEntry)
  397. {
  398. RASDIALDLG info;
  399. ZeroMemory( &info, sizeof(info) );
  400. info.dwSize = sizeof(info);
  401. //
  402. // Prevent the DialerDialog to come up only if the
  403. // user has checked the don't query before dialing
  404. // checkbox. Otherwise we bringup the dialog.
  405. //
  406. if(dwfDisableConnectionQuery)
  407. {
  408. info.dwFlags |= RASDDFLAG_NoPrompt;
  409. }
  410. if (fRedialMode)
  411. {
  412. /* Set this flag to tell RasDialDlg to popup the "reconnect
  413. ** pending" countdown dialog before redialing.
  414. */
  415. info.dwFlags |= RASDDFLAG_LinkFailure;
  416. }
  417. /* Popup the "Dial-Up Networking" dialing dialogs.
  418. */
  419. fCancelled = !RasDialDlg( pszPhonebook, pszEntry, NULL, &info );
  420. }
  421. else if (!fQuiet)
  422. {
  423. RASPBDLG info;
  424. ZeroMemory( &info, sizeof(info) );
  425. info.dwSize = sizeof(info);
  426. info.dwFlags = RASPBDFLAG_ForceCloseOnDial;
  427. /* Popup the main "Dial-Up Networking" dialog.
  428. */
  429. fCancelled = !RasPhonebookDlg( pszPhonebook, NULL, &info );
  430. }
  431. if (!fRedialMode && !fQuiet && fCancelled)
  432. {
  433. /* User did not make a connection. Ask him if he wants to nix
  434. ** auto-dial for this location.
  435. */
  436. // if (RasAutodialDisableDlgW( NULL ))
  437. // RasSetAutodialEnable( GetCurrentDialingLocation(), FALSE );
  438. }
  439. if (pAutodialEntries != NULL)
  440. LocalFree(pAutodialEntries);
  441. return 0;
  442. } // DisplayRasDialog
  443. DWORD
  444. GetExpandedDllPath(LPTSTR pszDllPath,
  445. LPTSTR *ppszExpandedDllPath)
  446. {
  447. DWORD dwErr = 0;
  448. DWORD dwSize = 0;
  449. //
  450. // find the size of the expanded string
  451. //
  452. if (0 == (dwSize =
  453. ExpandEnvironmentStrings(pszDllPath,
  454. NULL,
  455. 0)))
  456. {
  457. dwErr = GetLastError();
  458. goto done;
  459. }
  460. *ppszExpandedDllPath = LocalAlloc(
  461. LPTR,
  462. dwSize * sizeof (TCHAR));
  463. if (NULL == *ppszExpandedDllPath)
  464. {
  465. dwErr = GetLastError();
  466. goto done;
  467. }
  468. //
  469. // Get the expanded string
  470. //
  471. if (0 == ExpandEnvironmentStrings(
  472. pszDllPath,
  473. *ppszExpandedDllPath,
  474. dwSize))
  475. {
  476. dwErr = GetLastError();
  477. }
  478. done:
  479. return dwErr;
  480. }
  481. LPWSTR
  482. ConvertToUnicodeString(
  483. LPSTR psz
  484. )
  485. // Modified to use code from nouiutil
  486. {
  487. WCHAR* pszNew = NULL;
  488. if (psz)
  489. {
  490. DWORD cb;
  491. cb = MultiByteToWideChar( CP_ACP, 0, psz, -1, NULL, 0 );
  492. ASSERT(cb);
  493. pszNew = LocalAlloc( LPTR, (cb + 1) * sizeof(TCHAR) );
  494. if (!pszNew)
  495. {
  496. printf("rasautou: LocalAlloc failed\n");
  497. return NULL;
  498. }
  499. cb = MultiByteToWideChar( CP_ACP, 0, psz, -1, pszNew, cb );
  500. if (cb == 0)
  501. {
  502. LocalFree( pszNew );
  503. printf("rasautou: multibyte string conversion failed\n");
  504. return NULL;
  505. }
  506. }
  507. return pszNew;
  508. } // ConvertToUnicodeString
  509. LPSTR
  510. ConvertToAnsiString(
  511. PWCHAR psz
  512. )
  513. // Modified to use code from nouiutil
  514. {
  515. CHAR* pszNew = NULL;
  516. if (psz)
  517. {
  518. DWORD cb;
  519. cb = WideCharToMultiByte( CP_ACP, 0, psz, -1, NULL, 0, NULL, NULL );
  520. ASSERT(cb);
  521. pszNew = (CHAR* )LocalAlloc( LPTR, cb + 1 );
  522. if (!pszNew)
  523. {
  524. printf("rasautou: LocalAlloc failed");
  525. return NULL;
  526. }
  527. cb = WideCharToMultiByte( CP_ACP, 0, psz, -1, pszNew, cb, NULL, NULL );
  528. if (cb == 0)
  529. {
  530. LocalFree( pszNew );
  531. printf("rasautou: wide-character string conversion failed");
  532. return NULL;
  533. }
  534. }
  535. return pszNew;
  536. } // ConvertToUnicodeString
  537. DWORD
  538. DisplayCustomDialog(
  539. IN LPTSTR pszDll,
  540. IN LPTSTR pszFunc,
  541. IN LPTSTR pszPhonebook,
  542. IN LPTSTR pszEntry,
  543. IN LPTSTR pszAddress
  544. )
  545. {
  546. DWORD dwErr, dwRetCode;
  547. HINSTANCE hLibrary;
  548. CHAR szFuncNew[64], szFuncOld[64], *pszOldFunc = NULL;
  549. ORASADFUNC pfnOldStyleFunc;
  550. RASADFUNC pfnFunc;
  551. RASADPARAMS params;
  552. LPTSTR pszExpandedPath = NULL;
  553. CHAR * pszEntryA = NULL;
  554. dwErr = GetExpandedDllPath(pszDll,
  555. &pszExpandedPath);
  556. if(ERROR_SUCCESS != dwErr)
  557. {
  558. return dwErr;
  559. }
  560. //
  561. // Load the library.
  562. //
  563. hLibrary = LoadLibrary(pszExpandedPath);
  564. if (hLibrary == NULL) {
  565. dwErr = GetLastError();
  566. printf(
  567. "rasdlui: %s: AutoDial DLL cannot be loaded (dwErr=%d)\n",
  568. pszDll,
  569. dwErr);
  570. LocalFree(pszExpandedPath);
  571. return dwErr;
  572. }
  573. //
  574. // Get the procedure address. First,
  575. // we check for a new-style entry point,
  576. // and then check for an old-style entry
  577. // point if the new-style one doesn't exist.
  578. //
  579. #ifdef UNICODE
  580. sprintf(szFuncNew, "%SW", pszFunc);
  581. pszOldFunc = ConvertToAnsiString(pszFunc);
  582. pszEntryA = ConvertToAnsiString(pszEntry);
  583. if (!pszOldFunc || !pszEntryA)
  584. {
  585. printf("rasautou: Allocation failed. Exiting\n");
  586. exit(1);
  587. }
  588. #else
  589. sprintf(szFuncNew, "%sA", pszFunc);
  590. strcpy(szFuncOld, pszFunc);
  591. pszOldFunc = szFuncOld;
  592. pszEntryA = pszEntry;
  593. #endif
  594. pfnFunc = (RASADFUNC)GetProcAddress(hLibrary, szFuncNew);
  595. if (pfnFunc != NULL)
  596. {
  597. //
  598. // Initialize the param block.
  599. //
  600. params.hwndOwner = NULL;
  601. params.dwFlags = 0;
  602. params.xDlg = params.yDlg = 0;
  603. //params.dwCallbackId = 0;
  604. //params.pCallback = NULL;
  605. //
  606. // Call the procedure.
  607. //
  608. (*pfnFunc)(pszPhonebook, pszEntry, &params, &dwRetCode);
  609. }
  610. else
  611. {
  612. pfnOldStyleFunc = (ORASADFUNC)GetProcAddress(hLibrary, pszOldFunc);
  613. if (pfnOldStyleFunc != NULL)
  614. {
  615. (*pfnOldStyleFunc)(NULL, pszEntryA, 0, &dwRetCode);
  616. }
  617. else
  618. {
  619. #ifdef UNICODE
  620. printf(
  621. "rasautou: %S: Function cannot be loaded from AutoDial DLL %S\n",
  622. pszDll,
  623. pszFunc);
  624. #else
  625. printf(
  626. "rasautou: %s: Function cannot be loaded from AutoDial DLL %s\n",
  627. pszDll,
  628. pszFunc);
  629. #endif
  630. exit(1);
  631. }
  632. }
  633. //
  634. // Clean up.
  635. //
  636. FreeLibrary(hLibrary);
  637. #ifdef UNICODE
  638. if (pszOldFunc)
  639. {
  640. LocalFree(pszOldFunc);
  641. }
  642. if (pszEntryA)
  643. {
  644. LocalFree(pszOldFunc);
  645. }
  646. #endif
  647. LocalFree(pszExpandedPath);
  648. return dwRetCode;
  649. } // DisplayCustomDialog
  650. VOID
  651. FreeConvertedString(
  652. IN LPWSTR pwsz
  653. )
  654. {
  655. if (pwsz != NULL)
  656. LocalFree(pwsz);
  657. } // FreeConvertedString
  658. BOOLEAN
  659. RegGetValueA(
  660. IN HKEY hkey,
  661. IN LPSTR pszKey,
  662. OUT PVOID *ppvData,
  663. OUT LPDWORD pdwcbData
  664. )
  665. {
  666. DWORD dwError, dwType, dwSize;
  667. PVOID pvData;
  668. //
  669. // Get the length of the string.
  670. //
  671. dwError = RegQueryValueExA(
  672. hkey,
  673. pszKey,
  674. NULL,
  675. &dwType,
  676. NULL,
  677. &dwSize);
  678. if (dwError != ERROR_SUCCESS)
  679. return FALSE;
  680. pvData = LocalAlloc(LPTR, dwSize);
  681. if (pvData == NULL) {
  682. DbgPrint("RegGetValueA: LocalAlloc failed\n");
  683. return FALSE;
  684. }
  685. //
  686. // Read the value for real this time.
  687. //
  688. dwError = RegQueryValueExA(
  689. hkey,
  690. pszKey,
  691. NULL,
  692. NULL,
  693. (LPBYTE)pvData,
  694. &dwSize);
  695. if (dwError != ERROR_SUCCESS) {
  696. LocalFree(pvData);
  697. return FALSE;
  698. }
  699. *ppvData = pvData;
  700. if (pdwcbData != NULL)
  701. *pdwcbData = dwSize;
  702. return TRUE;
  703. } // RegGetValueA
  704. VOID
  705. NetworkConnected()
  706. /*++
  707. DESCRIPTION
  708. Determine whether there exists some network connection.
  709. Note: This code was stolen from sockit.c courtesy of ArnoldM.
  710. ARGUMENTS
  711. None
  712. RETURN VALUE
  713. TRUE if one exists, FALSE otherwise.
  714. --*/
  715. {
  716. typedef struct _LANA_MAP {
  717. BOOLEAN fEnum;
  718. UCHAR bLana;
  719. } LANA_MAP, *PLANA_MAP;
  720. BOOLEAN fNetworkPresent = FALSE;
  721. HKEY hKey;
  722. PLANA_MAP pLanaMap = NULL, pLana;
  723. DWORD dwError, dwcbLanaMap;
  724. PCHAR pMultiSzLanasA = NULL, paszTemp;
  725. DWORD dwcBindings, dwcMaxLanas, i, dwcbLanas;
  726. LONG iLana;
  727. DWORD dwZero = 0;
  728. PCHAR *paszLanas = NULL;
  729. SOCKET s;
  730. SOCKADDR_NB nbaddress, nbsendto;
  731. NTSTATUS status;
  732. UNICODE_STRING deviceName;
  733. OBJECT_ATTRIBUTES attributes;
  734. IO_STATUS_BLOCK iosb;
  735. HANDLE handle;
  736. PWCHAR pwsz;
  737. dwError = RegOpenKeyEx(
  738. HKEY_LOCAL_MACHINE,
  739. L"System\\CurrentControlSet\\Services\\Netbios\\Linkage",
  740. 0,
  741. KEY_READ,
  742. &hKey);
  743. if (dwError != ERROR_SUCCESS) {
  744. printf(
  745. "NetworkConnected: RegKeyOpenEx failed (dwError=%d)\n",
  746. GetLastError());
  747. return;
  748. }
  749. //
  750. // Read in the LanaMap.
  751. //
  752. if (!RegGetValueA(hKey, "LanaMap", &pLanaMap, &dwcbLanaMap)) {
  753. printf("NetworkConnected: RegGetValueA(LanaMap) failed\n");
  754. goto done;
  755. }
  756. dwcBindings = dwcbLanaMap / sizeof (LANA_MAP);
  757. //
  758. // Read in the bindings.
  759. //
  760. if (!RegGetValueA(hKey, "bind", &pMultiSzLanasA, &dwcbLanas)) {
  761. printf("NetworkConnected: RegGetValueA(bind) failed\n");
  762. goto done;
  763. }
  764. //
  765. // Allocate a buffer for the binding array.
  766. //
  767. paszLanas = LocalAlloc(LPTR, (dwcBindings+1) * sizeof (PCHAR));
  768. if (paszLanas == NULL) {
  769. printf("NetworkConnected: LocalAlloc failed\n");
  770. goto done;
  771. }
  772. //
  773. // Parse the bindings into an array of strings.
  774. //
  775. for (dwcMaxLanas = 0, paszTemp = pMultiSzLanasA; *paszTemp; paszTemp++) {
  776. paszLanas[dwcMaxLanas++] = paszTemp;
  777. while(*++paszTemp);
  778. }
  779. //
  780. // Finally enumerate the bindings and
  781. // attempt to create a socket on each.
  782. //
  783. nbaddress.snb_family = AF_NETBIOS;
  784. nbaddress.snb_type = 0;
  785. memcpy(nbaddress.snb_name, "yahooyahoo ", 16);
  786. nbsendto.snb_family = AF_NETBIOS;
  787. nbsendto.snb_type = 0;
  788. memcpy(nbsendto.snb_name, "billybob ", 16);
  789. for (iLana = 0, pLana = pLanaMap; dwcBindings--; iLana++, pLana++) {
  790. int iLanaMap = (int)pLana->bLana;
  791. if (pLana->fEnum && (DWORD)iLana < dwcMaxLanas) {
  792. int iError;
  793. if (!_stricmp(paszLanas[iLana], "\\Device\\NwlnkNb") ||
  794. strstr(paszLanas[iLana], "_NdisWan") != NULL)
  795. {
  796. printf("NetworkConnected: ignoring %s\n", paszLanas[iLana]);
  797. continue;
  798. }
  799. #ifdef notdef
  800. s = socket(AF_NETBIOS, SOCK_DGRAM, -iLanaMap);
  801. if (s == INVALID_SOCKET) {
  802. printf(
  803. "NetworkConnected: socket(%s, %d) failed (error=%d)\n",
  804. paszLanas[iLana],
  805. iLana,
  806. WSAGetLastError());
  807. continue;
  808. }
  809. //printf("s=0x%x, iLana=%d, %s\n", s, iLana, paszLanas[iLana]);
  810. iError = ioctlsocket(s, FIONBIO, &dwZero);
  811. if (iError == SOCKET_ERROR) {
  812. printf(
  813. "NetworkConnected: ioctlsocket(%s) failed (error=%d)\n",
  814. paszLanas[iLana],
  815. iLana,
  816. WSAGetLastError());
  817. goto cleanup;
  818. }
  819. iError = bind(
  820. s,
  821. (struct sockaddr *)&nbaddress,
  822. sizeof(nbaddress));
  823. if (iError == SOCKET_ERROR) {
  824. printf(
  825. "NetworkConnected: bind(%s, %d) failed (error=%d)\n",
  826. paszLanas[iLana],
  827. iLana,
  828. WSAGetLastError());
  829. goto cleanup;
  830. }
  831. iError = sendto(
  832. s,
  833. (PCHAR)&nbsendto,
  834. sizeof (nbsendto),
  835. 0,
  836. (struct sockaddr *)&nbsendto,
  837. sizeof (nbsendto));
  838. if (iError == SOCKET_ERROR) {
  839. printf(
  840. "NetworkConnected: sendto(%s, %d) failed (error=%d)\n",
  841. paszLanas[iLana],
  842. iLana,
  843. WSAGetLastError());
  844. }
  845. cleanup:
  846. closesocket(s);
  847. if (iError != SOCKET_ERROR) {
  848. printf("NetworkConnected: network (%s, %d) is up\n",
  849. paszLanas[iLana],
  850. iLana);
  851. fNetworkPresent = TRUE;
  852. break;
  853. }
  854. #else
  855. pwsz = ConvertToUnicodeString(paszLanas[iLana]);
  856. RtlInitUnicodeString(&deviceName, pwsz);
  857. InitializeObjectAttributes(
  858. &attributes,
  859. &deviceName,
  860. OBJ_CASE_INSENSITIVE,
  861. NULL,
  862. NULL);
  863. status = NtOpenFile(&handle, READ_CONTROL, &attributes, &iosb, 0, 0);
  864. NtClose(handle);
  865. LocalFree(pwsz);
  866. if (NT_SUCCESS(status)) {
  867. printf(
  868. "NetworkConnected: network (%s, %d) is up\n",
  869. paszLanas[iLana],
  870. iLana);
  871. fNetworkPresent = TRUE;
  872. break;
  873. }
  874. else {
  875. printf(
  876. "NetworkConnected: NtOpenFile on %s failed (status=0x%x)\n",
  877. paszLanas[iLana],
  878. status);
  879. }
  880. #endif
  881. }
  882. }
  883. //
  884. // Free resources.
  885. //
  886. done:
  887. if (paszLanas != NULL)
  888. LocalFree(paszLanas);
  889. if (pMultiSzLanasA != NULL)
  890. LocalFree(pMultiSzLanasA);
  891. if (pLanaMap != NULL)
  892. LocalFree(pLanaMap);
  893. RegCloseKey(hKey);
  894. } // NetworkConnected
  895. VOID
  896. DumpAutoDialAddresses()
  897. {
  898. DWORD dwErr, i, dwcb, dwcAddresses;
  899. LPTSTR *lppAddresses = NULL;
  900. dwErr = RasEnumAutodialAddresses(NULL, &dwcb, &dwcAddresses);
  901. if (dwErr && dwErr != ERROR_BUFFER_TOO_SMALL) {
  902. printf("RasEnumAutodialAddresses failed (dwErr=%d)\n", dwErr);
  903. return;
  904. }
  905. if (dwcAddresses) {
  906. lppAddresses = (LPTSTR *)LocalAlloc(LPTR, dwcb);
  907. if (lppAddresses == NULL) {
  908. printf("LocalAlloc failed\n");
  909. return;
  910. }
  911. dwErr = RasEnumAutodialAddresses(lppAddresses, &dwcb, &dwcAddresses);
  912. if (dwErr) {
  913. printf("RasEnumAutodialAddresses failed (dwErr=%d)\n", dwErr);
  914. LocalFree(lppAddresses);
  915. return;
  916. }
  917. }
  918. printf("There are %d Autodial addresses:\n", dwcAddresses);
  919. for (i = 0; i < dwcAddresses; i++)
  920. #ifdef UNICODE
  921. printf("%S\n", lppAddresses[i]);
  922. #else
  923. printf("%s\n", lppAddresses[i]);
  924. #endif
  925. if (lppAddresses != NULL)
  926. LocalFree(lppAddresses);
  927. } // DumpAutoDialAddresses
  928. VOID
  929. DumpStatus()
  930. {
  931. DWORD dwErr;
  932. WSADATA wsaData;
  933. //
  934. // Initialize winsock.
  935. //
  936. dwErr = WSAStartup(MAKEWORD(2,0), &wsaData);
  937. if (dwErr) {
  938. DbgPrint("AcsInitialize: WSAStartup failed (dwErr=%d)\n", dwErr);
  939. return;
  940. }
  941. //
  942. // Display network connectivity.
  943. //
  944. printf("Checking netcard bindings...\n");
  945. NetworkConnected();
  946. //
  947. // Display AutoDial address table.
  948. //
  949. printf("\nEnumerating AutoDial addresses...\n");
  950. DumpAutoDialAddresses();
  951. } // DumpStatus
  952. // Returns true if a redial-on-link-failure process is
  953. // active.
  954. //
  955. BOOL
  956. OtherRasautouExists(
  957. IN PSYSTEM_PROCESS_INFORMATION pProcessInfo)
  958. {
  959. PUCHAR pLargeBuffer = (PUCHAR)pProcessInfo;
  960. ULONG ulTotalOffset = 0;
  961. DWORD dwProcId, dwSessId = 0;
  962. BOOL fValidSessId = FALSE;
  963. dwProcId = GetCurrentProcessId();
  964. fValidSessId = ProcessIdToSessionId(dwProcId, &dwSessId);
  965. //printf(
  966. // "ProcId=%d, SessId=%d, ValSess=%d\n", dwProcId, dwSessId, fValidSessId);
  967. //
  968. // Look in the process list for lpExeName.
  969. //
  970. for (;;)
  971. {
  972. if (pProcessInfo->ImageName.Buffer != NULL)
  973. {
  974. // If
  975. // 1. The process is in our session
  976. // 2. It is not us
  977. // 3. It is rasautou
  978. //
  979. // Then another rasautou is already active -- we should
  980. // return success so that no ui is raised.
  981. //
  982. //printf(
  983. // "id=%-2d, sess=%-4d, %S\n",
  984. // PtrToUlong(pProcessInfo->UniqueProcessId),
  985. // pProcessInfo->SessionId,
  986. // pProcessInfo->ImageName.Buffer);
  987. if (
  988. ((dwSessId == pProcessInfo->SessionId) || (!fValidSessId)) &&
  989. (PtrToUlong(pProcessInfo->UniqueProcessId) != dwProcId) &&
  990. (_wcsicmp(pProcessInfo->ImageName.Buffer, L"rasautou.exe") == 0)
  991. )
  992. {
  993. //
  994. // We could actually check that
  995. // 4. That rasautou function is started with the -r flag
  996. //
  997. // However, it doesn't hurt to return if this is any rasautou
  998. // prompt.
  999. //
  1000. return TRUE;
  1001. }
  1002. }
  1003. //
  1004. // Increment offset to next process information block.
  1005. //
  1006. if (!pProcessInfo->NextEntryOffset)
  1007. {
  1008. break;
  1009. }
  1010. ulTotalOffset += pProcessInfo->NextEntryOffset;
  1011. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pLargeBuffer[ulTotalOffset];
  1012. }
  1013. return FALSE;
  1014. } // FindProcessByName
  1015. //
  1016. // Determines whether any redial on link failure prompts are
  1017. // currently active.
  1018. //
  1019. BOOL
  1020. OtherRasautouActive()
  1021. {
  1022. BOOL bRet = FALSE;
  1023. PSYSTEM_PROCESS_INFORMATION pSysInfo = NULL;
  1024. do
  1025. {
  1026. // Discover the processes on the system
  1027. //
  1028. pSysInfo = GetSystemProcessInfo();
  1029. if (pSysInfo == NULL)
  1030. {
  1031. break;
  1032. }
  1033. // Find out if any rasautou processes are active
  1034. //
  1035. bRet = OtherRasautouExists(pSysInfo);
  1036. } while (FALSE);
  1037. // Cleanup
  1038. //
  1039. {
  1040. if (pSysInfo)
  1041. {
  1042. FreeSystemProcessInfo(pSysInfo);
  1043. }
  1044. }
  1045. //printf("OtherRasautouActive() returned %s", (bRet) ? "true" : "false");
  1046. return bRet;
  1047. }
  1048. VOID _cdecl
  1049. wmain(
  1050. INT argc,
  1051. WCHAR **argv
  1052. )
  1053. {
  1054. DWORD dwErr = 0;
  1055. BOOLEAN fStatusFlag = FALSE, fRedialFlag = FALSE, fQuiet = FALSE;
  1056. PWCHAR pszPhonebookArg, pszEntryArg, pszDllArg, pszFuncArg, pszAddressArg;
  1057. LPTSTR pszPhonebook, pszEntry, pszDll, pszFunc, pszAddress;
  1058. //
  1059. // Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized"
  1060. // for UI conistency w/Connections Folder
  1061. //
  1062. if (g_hModule = GetModuleHandle( NULL )) {
  1063. SHFusionInitializeFromModule( g_hModule );
  1064. }
  1065. if (argc < 2) {
  1066. usage:
  1067. printf(
  1068. "Usage: rasautou [-f phonebook] [-d dll -p proc] [-a address] [-e entry] [-s]\n");
  1069. exit(1);
  1070. }
  1071. //
  1072. // Initialize the command line argument pointers.
  1073. //
  1074. pszPhonebookArg = NULL;
  1075. pszEntryArg = NULL;
  1076. pszDllArg = NULL;
  1077. pszFuncArg = NULL;
  1078. pszAddressArg = NULL;
  1079. //
  1080. // Crack command line parameters.
  1081. //
  1082. while (--argc && argv++) {
  1083. if (**argv != L'-')
  1084. break;
  1085. switch ((*argv)[1]) {
  1086. case L'a':
  1087. argc--;
  1088. if (!argc)
  1089. goto usage;
  1090. pszAddressArg = *(++argv);
  1091. break;
  1092. case L'd':
  1093. argc--;
  1094. if (!argc)
  1095. goto usage;
  1096. pszDllArg = *(++argv);
  1097. break;
  1098. case L'e':
  1099. argc--;
  1100. if (!argc)
  1101. goto usage;
  1102. pszEntryArg = *(++argv);
  1103. break;
  1104. case L'f':
  1105. argc--;
  1106. if (!argc)
  1107. goto usage;
  1108. pszPhonebookArg = *(++argv);
  1109. break;
  1110. case L'p':
  1111. argc--;
  1112. if (!argc)
  1113. goto usage;
  1114. pszFuncArg = *(++argv);
  1115. break;
  1116. case L'q':
  1117. fQuiet = TRUE;
  1118. break;
  1119. case L'r':
  1120. fRedialFlag = TRUE;
  1121. break;
  1122. case L's':
  1123. fStatusFlag = TRUE;
  1124. break;
  1125. default:
  1126. goto usage;
  1127. }
  1128. }
  1129. //
  1130. // If either the DLL name or the function
  1131. // name is missing, then display usage.
  1132. //
  1133. if ((pszDllArg == NULL) != (pszFuncArg == NULL) && !fStatusFlag)
  1134. goto usage;
  1135. //
  1136. // We can't dial an entry unless we
  1137. // know which one!
  1138. //
  1139. if (pszDllArg != NULL && pszFuncArg != NULL && pszEntryArg == NULL &&
  1140. !fStatusFlag)
  1141. {
  1142. goto usage;
  1143. }
  1144. if (fStatusFlag)
  1145. DumpStatus();
  1146. else {
  1147. //
  1148. // Convert to Unicode, if necessary.
  1149. //
  1150. #ifdef UNICODE
  1151. pszPhonebook = pszPhonebookArg;
  1152. pszEntry = pszEntryArg;
  1153. pszDll = pszDllArg;
  1154. pszFunc = pszFuncArg;
  1155. pszAddress = pszAddressArg;
  1156. #else
  1157. pszPhonebook = ConvertToAnsiString(pszPhonebookArg);
  1158. pszEntry = ConvertToAnsiString(pszEntryArg);
  1159. pszDll = ConvertToAnsiString(pszDllArg);
  1160. pszFunc = ConvertToAnsiString(pszFuncArg);
  1161. pszAddress = ConvertToAnsiString(pszAddressArg);
  1162. #endif
  1163. // XP 394237
  1164. //
  1165. // Supress the autodial prompt if a redial-on-link-failure
  1166. // prompt is already active
  1167. //
  1168. if ((fRedialFlag) || (fQuiet) || (!OtherRasautouActive()))
  1169. {
  1170. //
  1171. // Call the appropriate DLL entrypoint.
  1172. //
  1173. if ((pszDll == NULL && pszFunc == NULL) || fRedialFlag)
  1174. {
  1175. dwErr = DisplayRasDialog(
  1176. pszPhonebook,
  1177. pszEntry,
  1178. pszAddress,
  1179. fRedialFlag,
  1180. fQuiet);
  1181. }
  1182. else
  1183. {
  1184. dwErr = DisplayCustomDialog(
  1185. pszDll,
  1186. pszFunc,
  1187. pszPhonebook,
  1188. pszEntry,
  1189. pszAddress);
  1190. }
  1191. }
  1192. #ifndef UNICODE
  1193. FreeConvertedString(pszPhonebook);
  1194. FreeConvertedString(pszEntry);
  1195. FreeConvertedString(pszDll);
  1196. FreeConvertedString(pszFunc);
  1197. FreeConvertedString(pszAddress);
  1198. #endif
  1199. }
  1200. //
  1201. // Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized"
  1202. // for UI conistency w/Connections Folder
  1203. //
  1204. if (g_hModule)
  1205. {
  1206. SHFusionUninitialize();
  1207. }
  1208. //
  1209. // Return status.
  1210. //
  1211. exit(dwErr);
  1212. }