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.

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