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.

3985 lines
107 KiB

  1. // Copyright (c) 1995, Microsoft Corporation, all rights reserved
  2. //
  3. // entry.c
  4. // Remote Access Common Dialog APIs
  5. // {Ras,Router}PhonebookEntryDlg APIs and general entry utilities
  6. //
  7. // 06/20/95 Steve Cobb
  8. //
  9. // Eu, Cu, and Su utilities sets:
  10. //
  11. // This file contains 3 sets of high-level phone book entry UI utilities
  12. // shared by the phonebook entry property sheet and the add entry wizard. The
  13. // highest level set of "Eu" utilities is based on the EINFO block and is
  14. // specific to the entry property sheet and add entry wizards. The other two
  15. // utilities may be used by other dialogs without an EINFO context. The "Cu"
  16. // utility set based on the CUINFO block encapsulates all complex phone number
  17. // logic. The "Su" utility set, based on the SUINFO block, encapsulates
  18. // scripting logic.
  19. #include "rasdlgp.h"
  20. #include <serial.h> // for SERIAL_TXT
  21. #include <mprapi.h> // for MprAdmin API declarations
  22. #include <lmaccess.h> // for NetUserAdd declarations
  23. #include <lmerr.h> // for NERR_* declarations. pmay bug 232983
  24. #include <rasapip.h>
  25. #include <mprerror.h>
  26. // Target machine for RouterEntryDlg{A,W} in "\\server" form. See
  27. // "limitation" comment in RouterEntryDlgW.
  28. //
  29. static WCHAR g_wszServer[ MAX_COMPUTERNAME_LENGTH + 3] = L"";
  30. //-----------------------------------------------------------------------------
  31. // Local structures
  32. //-----------------------------------------------------------------------------
  33. typedef struct _FREE_COM_PORTS_DATA {
  34. DTLLIST* pListPortsInUse; // Ports currently in use
  35. DTLLIST* pListFreePorts; // Ports currently free
  36. DWORD dwCount; // Count of com ports
  37. } FREE_COM_PORTS_DATA;
  38. typedef struct _COM_PORT_INFO {
  39. PWCHAR pszFriendlyName;
  40. PWCHAR pszPort;
  41. } COM_PORT_INFO;
  42. //-----------------------------------------------------------------------------
  43. // Local prototypes
  44. //-----------------------------------------------------------------------------
  45. //
  46. // Prototype of the RouterEntryDlg func
  47. //
  48. typedef
  49. BOOL
  50. (APIENTRY * ROUTER_ENTRY_DLG_FUNC) (
  51. IN LPWSTR lpszServer,
  52. IN LPWSTR lpszPhonebook,
  53. IN LPWSTR lpszEntry,
  54. IN OUT LPRASENTRYDLGW lpInfo );
  55. VOID
  56. AppendDisabledPorts(
  57. IN EINFO* pInfo,
  58. IN DWORD dwType );
  59. BOOL
  60. BuildFreeComPortList(
  61. IN PWCHAR pszPort,
  62. IN HANDLE hData);
  63. //-----------------------------------------------------------------------------
  64. // External entry points
  65. //-----------------------------------------------------------------------------
  66. DWORD
  67. GetRasDialOutProtocols()
  68. // This is called by WinLogon to determine if RAS is installed.
  69. //
  70. // !!! RaoS is working on cleaning this up, i.e. making it a "real" RAS
  71. // API or removing the need for it.
  72. //
  73. {
  74. #if 1
  75. return g_pGetInstalledProtocolsEx( NULL, FALSE, TRUE, FALSE );
  76. #else
  77. return NP_Ip;
  78. #endif
  79. }
  80. BOOL APIENTRY
  81. RasEntryDlgA(
  82. IN LPSTR lpszPhonebook,
  83. IN LPSTR lpszEntry,
  84. IN OUT LPRASENTRYDLGA lpInfo )
  85. // Win32 ANSI entrypoint that displays the modal Phonebook Entry property
  86. // sheet. 'LpszPhonebook' is the full path to the phonebook file or NULL
  87. // to use the default phonebook. 'LpszEntry' is the entry to edit or the
  88. // default name of the new entry. 'LpInfo' is caller's additional
  89. // input/output parameters.
  90. //
  91. // Returns true if user presses OK and succeeds, false on error or Cancel.
  92. //
  93. {
  94. WCHAR* pszPhonebookW;
  95. WCHAR* pszEntryW;
  96. RASENTRYDLGW infoW;
  97. BOOL fStatus;
  98. TRACE( "RasEntryDlgA" );
  99. if (!lpInfo)
  100. {
  101. SetLastError( ERROR_INVALID_PARAMETER );
  102. return FALSE;
  103. }
  104. if (lpInfo->dwSize != sizeof(RASENTRYDLGA))
  105. {
  106. lpInfo->dwError = ERROR_INVALID_SIZE;
  107. return FALSE;
  108. }
  109. // Thunk "A" arguments to "W" arguments.
  110. //
  111. if (lpszPhonebook)
  112. {
  113. pszPhonebookW = StrDupTFromA( lpszPhonebook );
  114. if (!pszPhonebookW)
  115. {
  116. lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
  117. return FALSE;
  118. }
  119. }
  120. else
  121. pszPhonebookW = NULL;
  122. if (lpszEntry)
  123. {
  124. pszEntryW = StrDupTFromA( lpszEntry );
  125. if (!pszEntryW)
  126. {
  127. Free0( pszPhonebookW );
  128. {
  129. lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
  130. return FALSE;
  131. }
  132. }
  133. }
  134. else
  135. pszEntryW = NULL;
  136. ZeroMemory( &infoW, sizeof(infoW) );
  137. infoW.dwSize = sizeof(infoW);
  138. infoW.hwndOwner = lpInfo->hwndOwner;
  139. infoW.dwFlags = lpInfo->dwFlags;
  140. infoW.xDlg = lpInfo->xDlg;
  141. infoW.yDlg = lpInfo->yDlg;
  142. infoW.reserved = lpInfo->reserved;
  143. infoW.reserved2 = lpInfo->reserved2;
  144. // Thunk to the equivalent "W" API.
  145. //
  146. fStatus = RasEntryDlgW( pszPhonebookW, pszEntryW, &infoW );
  147. Free0( pszPhonebookW );
  148. Free0( pszEntryW );
  149. // Thunk "W" results to "A" results.
  150. //
  151. StrCpyAFromW(lpInfo->szEntry, infoW.szEntry, sizeof(lpInfo->szEntry));
  152. lpInfo->dwError = infoW.dwError;
  153. return fStatus;
  154. }
  155. BOOL APIENTRY
  156. RasEntryDlgW(
  157. IN LPWSTR lpszPhonebook,
  158. IN LPWSTR lpszEntry,
  159. IN OUT LPRASENTRYDLGW lpInfo )
  160. // Win32 Unicode entrypoint that displays the modal Phonebook Entry
  161. // property sheet. 'LpszPhonebook' is the full path to the phonebook file
  162. // or NULL to use the default phonebook. 'LpszEntry' is the entry to edit
  163. // or the default name of the new entry. 'LpInfo' is caller's additional
  164. // input/output parameters.
  165. //
  166. // Returns true if user presses OK and succeeds, false on error or Cancel.
  167. //
  168. {
  169. DWORD dwErr;
  170. EINFO* pEinfo;
  171. BOOL fStatus;
  172. HWND hwndOwner;
  173. DWORD dwOp;
  174. BOOL fRouter;
  175. BOOL fShellOwned;
  176. TRACE( "RasEntryDlgW" );
  177. if (!lpInfo)
  178. {
  179. SetLastError( ERROR_INVALID_PARAMETER );
  180. return FALSE;
  181. }
  182. if (lpInfo->dwSize != sizeof(RASENTRYDLGW))
  183. {
  184. lpInfo->dwError = ERROR_INVALID_SIZE;
  185. return FALSE;
  186. }
  187. // The "ShellOwned" mode is required for Connections. In this mode, the
  188. // API returns before the sheet is dismissed, does not fill in outputs,
  189. // and the wizard and property sheets are responsible for calling EuCommit
  190. // (if necessary) and then EuFree. Otherwise, EuCommit/EuFree are called
  191. // below.
  192. //
  193. fShellOwned = lpInfo->dwFlags & RASEDFLAG_ShellOwned;
  194. if (fShellOwned)
  195. {
  196. RASEDSHELLOWNEDR2* pShellOwnedInfo;
  197. pShellOwnedInfo = (RASEDSHELLOWNEDR2*)lpInfo->reserved2;
  198. if (!pShellOwnedInfo ||
  199. IsBadWritePtr (&pShellOwnedInfo->pvWizardCtx,
  200. sizeof(pShellOwnedInfo->pvWizardCtx)))
  201. {
  202. lpInfo->dwError = ERROR_INVALID_PARAMETER;
  203. return FALSE;
  204. }
  205. }
  206. // Eliminate some invalid flag combinations up front.
  207. //
  208. if (lpInfo->dwFlags & RASEDFLAG_CloneEntry)
  209. {
  210. lpInfo->dwFlags &= ~(RASEDFLAG_AnyNewEntry | RASEDFLAG_NoRename);
  211. }
  212. // fRouter = RasRpcDllLoaded();
  213. if(lpInfo->reserved)
  214. {
  215. fRouter = IsRasRemoteConnection(((INTERNALARGS *)lpInfo->reserved)->hConnection);
  216. }
  217. else
  218. {
  219. fRouter = FALSE;
  220. }
  221. if (!fRouter)
  222. {
  223. // DwCustomEntryDlg returns ERROR_SUCCESS if it handled
  224. // the CustomEntryDlg. returns E_NOINTERFACE otherwise
  225. // which implies that there is no custom dlg interface
  226. // supported for this entry and the default Entrydlg
  227. // should be displayed
  228. //
  229. dwErr = DwCustomEntryDlg(
  230. lpszPhonebook,
  231. lpszEntry,
  232. lpInfo,
  233. &fStatus);
  234. if(ERROR_SUCCESS == dwErr)
  235. {
  236. return fStatus;
  237. }
  238. // Load RAS DLL entrypoints which starts RASMAN, if necessary. The
  239. // entrypoints are already loaded in the router case. The limitations
  240. // this creates are discussed in RasEntryDlgW.
  241. //
  242. dwErr = LoadRas( g_hinstDll, lpInfo->hwndOwner );
  243. if (dwErr != 0)
  244. {
  245. if (!fShellOwned)
  246. {
  247. ErrorDlg( lpInfo->hwndOwner, SID_OP_LoadRas, dwErr, NULL );
  248. }
  249. lpInfo->dwError = dwErr;
  250. return FALSE;
  251. }
  252. {
  253. // Commented it out For whistler bug 445424 gangz
  254. // We move the Tapi first area Dialog to dialing rules check
  255. // box
  256. /*
  257. HLINEAPP hlineapp;
  258. // Popup TAPI's "first location" dialog if they are uninitialized.
  259. // An error here is treated as a "cancel" per bug 288385. This
  260. // ridiculous exercise is necessary due to TAPI's inability to (a)
  261. // provide a default location or (b) create a location
  262. // programatically.
  263. //
  264. hlineapp = (HLINEAPP )0;
  265. if (TapiNoLocationDlg(
  266. g_hinstDll, &hlineapp, lpInfo->hwndOwner ) == 0)
  267. {
  268. TapiShutdown( hlineapp );
  269. }
  270. else
  271. {
  272. lpInfo->dwError = 0;
  273. return FALSE;
  274. }
  275. */
  276. #if 0
  277. RAS_DEVICE_INFO *pDeviceInfo = NULL;
  278. DWORD dwVersion = RAS_VERSION,
  279. dwEntries = 0,
  280. dwcb = 0, i;
  281. dwErr = RasGetDeviceConfigInfo(NULL, &dwVersion,
  282. &dwEntries, &dwcb,
  283. NULL);
  284. if(dwErr == ERROR_BUFFER_TOO_SMALL)
  285. {
  286. pDeviceInfo = LocalAlloc(LPTR,
  287. dwcb);
  288. if(NULL == pDeviceInfo)
  289. {
  290. lpInfo->dwError = GetLastError();
  291. return FALSE;
  292. }
  293. dwErr = RasGetDeviceConfigInfo(NULL,
  294. &dwVersion,
  295. &dwEntries,
  296. &dwcb,
  297. (PBYTE) pDeviceInfo);
  298. //
  299. // Check to see if there is a modem device
  300. //
  301. for(i = 0; i < dwEntries; i++)
  302. {
  303. if(RAS_DEVICE_TYPE(pDeviceInfo[i].eDeviceType)
  304. == RDT_Modem)
  305. {
  306. break;
  307. }
  308. }
  309. LocalFree(pDeviceInfo);
  310. if(i < dwEntries)
  311. {
  312. // Popup TAPI's "first location" dialog if they are uninitialized.
  313. // An error here is treated as a "cancel" per bug 288385. This
  314. // ridiculous exercise is necessary due to TAPI's inability to (a)
  315. // provide a default location or (b) create a location
  316. // programatically.
  317. //
  318. hlineapp = (HLINEAPP )0;
  319. if (TapiNoLocationDlg(
  320. g_hinstDll, &hlineapp, lpInfo->hwndOwner ) == 0)
  321. {
  322. TapiShutdown( hlineapp );
  323. }
  324. else
  325. {
  326. lpInfo->dwError = 0;
  327. return FALSE;
  328. }
  329. }
  330. }
  331. #endif
  332. }
  333. }
  334. // Initialize the entry common context block.
  335. //
  336. dwErr = EuInit( lpszPhonebook, lpszEntry, lpInfo, fRouter, &pEinfo, &dwOp );
  337. if (dwErr == 0)
  338. {
  339. BOOL fShowWizard = FALSE;
  340. if (lpInfo->dwFlags & RASEDFLAG_AnyNewEntry)
  341. {
  342. fShowWizard = (pEinfo->pUser->fNewEntryWizard || fShellOwned);
  343. }
  344. else if (lpInfo->dwFlags & RASEDFLAG_CloneEntry)
  345. {
  346. // Need the wizard to gather the cloned entry's name.
  347. fShowWizard = TRUE;
  348. }
  349. if (fShowWizard)
  350. {
  351. if (pEinfo->fRouter)
  352. {
  353. #if 1
  354. AiWizard( pEinfo );
  355. #else
  356. pEinfo->fChainPropertySheet = TRUE;
  357. #endif
  358. }
  359. else
  360. {
  361. AeWizard( pEinfo );
  362. }
  363. if (pEinfo->fChainPropertySheet && lpInfo->dwError == 0)
  364. {
  365. PePropertySheet( pEinfo );
  366. }
  367. }
  368. else
  369. {
  370. PePropertySheet( pEinfo );
  371. }
  372. }
  373. else
  374. {
  375. ErrorDlg( lpInfo->hwndOwner, dwOp, dwErr, NULL );
  376. lpInfo->dwError = dwErr;
  377. }
  378. // Clean up here, but only in non-Shell-owned mode.
  379. //
  380. if (fShellOwned)
  381. {
  382. fStatus = TRUE;
  383. }
  384. else
  385. {
  386. if( NULL != pEinfo)
  387. {
  388. fStatus = (pEinfo->fCommit && EuCommit( pEinfo ));
  389. EuFree( pEinfo );
  390. }
  391. else
  392. {
  393. fStatus = FALSE;
  394. }
  395. }
  396. return fStatus;
  397. }
  398. //
  399. // Raises the NT4 ui.
  400. //
  401. BOOL
  402. RouterEntryDlgNt4W(
  403. IN LPWSTR lpszServer,
  404. IN LPWSTR lpszPhonebook,
  405. IN LPWSTR lpszEntry,
  406. IN OUT LPRASENTRYDLGW lpInfo )
  407. {
  408. HMODULE hLib = NULL;
  409. ROUTER_ENTRY_DLG_FUNC pFunc = NULL;
  410. BOOL bOk = FALSE;
  411. do
  412. {
  413. // Load the library
  414. hLib = LoadLibraryA("rasdlg4.dll");
  415. if (hLib == NULL)
  416. {
  417. lpInfo->dwError = GetLastError();
  418. break;
  419. }
  420. // Get the func pointer
  421. pFunc = (ROUTER_ENTRY_DLG_FUNC)
  422. GetProcAddress(hLib, "RouterEntryDlgW");
  423. if (pFunc == NULL)
  424. {
  425. lpInfo->dwError = ERROR_CAN_NOT_COMPLETE;
  426. break;
  427. }
  428. // Call the function
  429. //
  430. bOk = pFunc(lpszServer, lpszPhonebook, lpszEntry, lpInfo);
  431. } while (FALSE);
  432. if (hLib)
  433. {
  434. FreeLibrary(hLib);
  435. }
  436. return bOk;
  437. }
  438. BOOL APIENTRY
  439. RouterEntryDlgA(
  440. IN LPSTR lpszServer,
  441. IN LPSTR lpszPhonebook,
  442. IN LPSTR lpszEntry,
  443. IN OUT LPRASENTRYDLGA lpInfo )
  444. // Router-specific version of RasEntryDlgA. 'LpszServer' is the name of
  445. // the target server in "\\server" form or NULL for the local machine.
  446. // Other arguments are as for RasEntryDlgA. See "limitation" comment in
  447. // RouterEntryDlgW.
  448. //
  449. {
  450. BOOL fSuccess;
  451. DWORD dwErr;
  452. HANDLE hConnection = NULL;
  453. BOOL fAllocatedIArgs = FALSE;
  454. WCHAR wszServer[ MAX_COMPUTERNAME_LENGTH + 3];
  455. TRACE( "RouterEntryDlgA" );
  456. // Load RAS entrypoints or set up RPC to them, if remote server.
  457. //
  458. if (lpszServer)
  459. {
  460. StrCpyWFromAUsingAnsiEncoding(
  461. wszServer,
  462. lpszServer,
  463. MAX_COMPUTERNAME_LENGTH+3);
  464. }
  465. else
  466. {
  467. wszServer[ 0 ] = L'\0';
  468. }
  469. // Load RAS entrypoints or set up RPC to them, if remote server.
  470. //
  471. dwErr = InitializeConnection(wszServer, &hConnection);
  472. if(dwErr)
  473. {
  474. lpInfo->dwError = dwErr;
  475. return FALSE;
  476. }
  477. // Use the reserved parameter to pass the handle to the api - allocate
  478. // this parameter if not already present - very sleazy - (RaoS)
  479. //
  480. if (NULL == (INTERNALARGS *)lpInfo->reserved)
  481. {
  482. INTERNALARGS *pIArgs = Malloc(sizeof(INTERNALARGS));
  483. if(NULL == pIArgs)
  484. {
  485. lpInfo->dwError = GetLastError();
  486. return FALSE;
  487. }
  488. ZeroMemory(pIArgs, sizeof(INTERNALARGS));
  489. pIArgs->fInvalid = TRUE;
  490. lpInfo->reserved = (ULONG_PTR )pIArgs;
  491. fAllocatedIArgs = TRUE;
  492. }
  493. ((INTERNALARGS *)lpInfo->reserved)->hConnection = hConnection;
  494. // Load MPR entrypoints.
  495. //
  496. dwErr = LoadMpradminDll();
  497. if (dwErr)
  498. {
  499. dwErr = UnloadRasRpcDll();
  500. lpInfo->dwError = dwErr;
  501. return FALSE;
  502. }
  503. // Call the normal dial-out UI.
  504. //
  505. fSuccess = RasEntryDlgA( lpszPhonebook, lpszEntry, lpInfo );
  506. // Unload DLLs.
  507. //
  508. UnloadMpradminDll();
  509. UninitializeConnection(hConnection);
  510. ((INTERNALARGS *)lpInfo->reserved)->hConnection = NULL;
  511. if(fAllocatedIArgs)
  512. {
  513. Free((PVOID)lpInfo->reserved);
  514. (PVOID)lpInfo->reserved = NULL;
  515. }
  516. return fSuccess;
  517. }
  518. BOOL APIENTRY
  519. RouterEntryDlgW(
  520. IN LPWSTR lpszServer,
  521. IN LPWSTR lpszPhonebook,
  522. IN LPWSTR lpszEntry,
  523. IN OUT LPRASENTRYDLGW lpInfo )
  524. // Router-specific version of RasEntryDlgA. 'LpszServer' is the name of
  525. // the target server in "\\server" form or NULL for the local machine.
  526. // Other arguments are as for RasEntryDlgW.
  527. //
  528. // LIMITATION: As implemented with the 'g_wszServer' global and global RPC
  529. // entrypoints, the following single process limitations apply to this
  530. // (currently undocumented) API. First, it cannot be called
  531. // simultaneously for two different servers. Second, it cannot be
  532. // called simultaneously with RasEntryDlg.
  533. {
  534. BOOL fSuccess;
  535. DWORD dwErr, dwVersion;
  536. HANDLE hConnection = NULL;
  537. BOOL fAllocatedIArgs = FALSE;
  538. WCHAR wszServer[ MAX_COMPUTERNAME_LENGTH + 3];
  539. TRACE( "RouterEntryDlgW" );
  540. TRACEW1( " s=%s", (lpszServer) ? lpszServer : TEXT("") );
  541. TRACEW1( " p=%s", (lpszPhonebook) ? lpszPhonebook : TEXT("") );
  542. TRACEW1( " e=%s", (lpszEntry) ? lpszEntry : TEXT("") );
  543. if (lpszServer)
  544. {
  545. lstrcpynW( wszServer, lpszServer, sizeof(wszServer) / sizeof(WCHAR) );
  546. }
  547. else
  548. {
  549. wszServer[0] = L'\0';
  550. }
  551. // Load RAS entrypoints or set up RPC to them, if remote server.
  552. //
  553. dwErr = InitializeConnection(lpszServer, &hConnection);
  554. if(dwErr)
  555. {
  556. lpInfo->dwError = dwErr;
  557. return FALSE;
  558. }
  559. // If this is a downlevel machine, use the downlevel
  560. // UI
  561. //
  562. if (IsRasRemoteConnection(hConnection))
  563. {
  564. dwVersion = RemoteGetServerVersion(hConnection);
  565. if (dwVersion == VERSION_40)
  566. {
  567. UninitializeConnection(hConnection);
  568. dwErr = RouterEntryDlgNt4W(
  569. lpszServer,
  570. lpszPhonebook,
  571. lpszEntry,
  572. lpInfo );
  573. return dwErr;
  574. }
  575. }
  576. //
  577. // Use the reserved parameter to pass the handle to the
  578. // api - allocate this parameter if not already present
  579. // - very sleazy -
  580. //
  581. if(NULL == (INTERNALARGS *) lpInfo->reserved)
  582. {
  583. INTERNALARGS *pIArgs = Malloc(sizeof(INTERNALARGS));
  584. if(NULL == pIArgs)
  585. {
  586. lpInfo->dwError = GetLastError();
  587. return FALSE;
  588. }
  589. ZeroMemory(pIArgs, sizeof(INTERNALARGS));
  590. pIArgs->fInvalid = TRUE;
  591. lpInfo->reserved = (ULONG_PTR ) pIArgs;
  592. fAllocatedIArgs = TRUE;
  593. }
  594. ((INTERNALARGS *)lpInfo->reserved)->hConnection = hConnection;
  595. // Load MPR entrypoints.
  596. //
  597. dwErr = LoadMpradminDll();
  598. if (dwErr)
  599. {
  600. dwErr = UnloadRasRpcDll();
  601. lpInfo->dwError = dwErr;
  602. return FALSE;
  603. }
  604. // Call the normal dial-out UI.
  605. //
  606. fSuccess = RasEntryDlgW( lpszPhonebook, lpszEntry, lpInfo );
  607. // Unload DLLs.
  608. //
  609. UnloadMpradminDll();
  610. UninitializeConnection(hConnection);
  611. ((INTERNALARGS *)lpInfo->reserved)->hConnection = NULL;
  612. if(fAllocatedIArgs)
  613. {
  614. Free((PVOID) lpInfo->reserved);
  615. (PVOID)lpInfo->reserved = 0;
  616. }
  617. return fSuccess;
  618. }
  619. //----------------------------------------------------------------------------
  620. // Phonebook Entry common routines (Eu utilities)
  621. // Listed alphabetically
  622. //----------------------------------------------------------------------------
  623. VOID
  624. AppendDisabledPorts(
  625. IN EINFO* pInfo,
  626. IN DWORD dwType )
  627. // Utility to append links containing all remaining configured ports of
  628. // RASET_* type 'dwType' to the list of links with the new links marked
  629. // "unenabled". If 'dwType' is -1 all configured ports are appended.
  630. //
  631. {
  632. DTLNODE* pNodeP;
  633. DTLNODE* pNodeL;
  634. for (pNodeP = DtlGetFirstNode( pInfo->pListPorts );
  635. pNodeP;
  636. pNodeP = DtlGetNextNode( pNodeP ))
  637. {
  638. PBPORT* pPort;
  639. BOOL fSkipPort;
  640. DTLNODE* pNode;
  641. pPort = (PBPORT* )DtlGetData( pNodeP );
  642. fSkipPort = FALSE;
  643. if (dwType != RASET_P_AllTypes)
  644. {
  645. // pmay: 233287
  646. //
  647. // The port should not be included if:
  648. // 1. The mode is non-tunnel and the port is vpn type
  649. // 2. The mode is normal and the port type mismatches
  650. //
  651. if (dwType == RASET_P_NonVpnTypes)
  652. {
  653. if (pPort->dwType == RASET_Vpn)
  654. {
  655. continue;
  656. }
  657. }
  658. else
  659. {
  660. if (pPort->dwType != dwType)
  661. {
  662. continue;
  663. }
  664. }
  665. }
  666. for (pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  667. pNodeL;
  668. pNodeL = DtlGetNextNode( pNodeL ))
  669. {
  670. PBLINK* pLink = (PBLINK* )DtlGetData( pNodeL );
  671. ASSERT( pPort->pszPort );
  672. ASSERT( pLink->pbport.pszPort );
  673. if (lstrcmp( pLink->pbport.pszPort, pPort->pszPort ) == 0
  674. && lstrcmp( pLink->pbport.pszDevice, pPort->pszDevice ) == 0)
  675. {
  676. // The port already appears in a link in the list.
  677. //
  678. fSkipPort = TRUE;
  679. break;
  680. }
  681. }
  682. if (fSkipPort)
  683. {
  684. continue;
  685. }
  686. pNode = CreateLinkNode();
  687. if (pNode)
  688. {
  689. PBLINK* pLink = (PBLINK* )DtlGetData( pNode );
  690. if (CopyToPbport( &pLink->pbport, pPort ) != 0)
  691. {
  692. DestroyLinkNode( pNode );
  693. }
  694. else
  695. {
  696. if ((pPort->pbdevicetype == PBDT_Modem) ||
  697. (pPort->dwFlags & PBP_F_NullModem)
  698. )
  699. {
  700. SetDefaultModemSettings( pLink );
  701. }
  702. pLink->fEnabled = FALSE;
  703. DtlAddNodeLast( pInfo->pEntry->pdtllistLinks, pNode );
  704. }
  705. }
  706. }
  707. // Set "multiple devices" flag if there is more than one device of this
  708. // type for convenient reference elsewhere.
  709. //
  710. pInfo->fMultipleDevices =
  711. (DtlGetNodes( pInfo->pEntry->pdtllistLinks ) > 1);
  712. }
  713. BOOL
  714. BuildFreeComPortList(
  715. IN PWCHAR pszPort,
  716. IN HANDLE hData)
  717. // Com port enumeration function that generates a list of
  718. // free com ports. Returns TRUE to stop enumeration (see
  719. // MdmEnumComPorts)
  720. {
  721. FREE_COM_PORTS_DATA* pfcpData = (FREE_COM_PORTS_DATA*)hData;
  722. DTLLIST* pListUsed = pfcpData->pListPortsInUse;
  723. DTLLIST* pListFree = pfcpData->pListFreePorts;
  724. DTLNODE* pNodeP, *pNodeL, *pNode;
  725. // If the given port is in the used list, then return
  726. // so that it is not added to the list of free ports and
  727. // so that enumeration continues.
  728. for (pNodeL = DtlGetFirstNode( pListUsed );
  729. pNodeL;
  730. pNodeL = DtlGetNextNode( pNodeL ))
  731. {
  732. PBLINK* pLink = (PBLINK* )DtlGetData( pNodeL );
  733. ASSERT( pLink->pbport.pszPort );
  734. // The port already appears in a link in the list.
  735. if (lstrcmp( pLink->pbport.pszPort, pszPort ) == 0)
  736. return FALSE;
  737. }
  738. // The port is not in use. Add it to the free list.
  739. pNode = DtlCreateSizedNode( sizeof(COM_PORT_INFO), 0L );
  740. if (pNode)
  741. {
  742. COM_PORT_INFO* pComInfo;
  743. TCHAR* pszFriendlyName;
  744. pszFriendlyName = PszFromId(g_hinstDll, SID_FriendlyComPort);
  745. pComInfo = (COM_PORT_INFO* )DtlGetData( pNode );
  746. pComInfo->pszFriendlyName = pszFriendlyName;
  747. pComInfo->pszPort = StrDup(pszPort);
  748. DtlAddNodeLast( pListFree, pNode );
  749. pfcpData->dwCount += 1;
  750. }
  751. return FALSE;
  752. }
  753. DWORD
  754. EuMergeAvailableComPorts(
  755. IN EINFO* pInfo,
  756. OUT DTLNODE** ppNodeP,
  757. IN OUT LPDWORD lpdwCount)
  758. // Adds all the available com ports in the system
  759. // as modem devices.
  760. {
  761. FREE_COM_PORTS_DATA fcpData;
  762. DTLLIST* pListFreeComPorts = NULL;
  763. DTLNODE* pNodeL;
  764. // Initialize the list of com ports
  765. pListFreeComPorts = DtlCreateList(0L);
  766. if(NULL == pListFreeComPorts)
  767. {
  768. return ERROR_NOT_ENOUGH_MEMORY;
  769. }
  770. fcpData.pListPortsInUse = pInfo->pListPorts;
  771. fcpData.pListFreePorts = pListFreeComPorts;
  772. fcpData.dwCount = 0;
  773. // Enumerate the com ports
  774. MdmEnumComPorts (
  775. BuildFreeComPortList,
  776. (HANDLE)(&fcpData));
  777. // Go throught the list of free com ports and create
  778. // a bogus device for each one.
  779. for (pNodeL = DtlGetFirstNode( pListFreeComPorts );
  780. pNodeL;
  781. pNodeL = DtlGetNextNode( pNodeL ))
  782. {
  783. COM_PORT_INFO* pComInfo;
  784. DTLNODE* pNode;
  785. // Get the info about the com port
  786. pComInfo = (COM_PORT_INFO* )DtlGetData( pNodeL );
  787. // Create a new device for it
  788. pNode = CreateLinkNode();
  789. if (pNode)
  790. {
  791. PBLINK* pLink = (PBLINK* )DtlGetData( pNode );
  792. pLink->pbport.pszPort = pComInfo->pszPort;
  793. pLink->pbport.pszDevice = pComInfo->pszFriendlyName;
  794. pLink->pbport.pszMedia = StrDup( TEXT(SERIAL_TXT) );
  795. pLink->pbport.pbdevicetype = PBDT_ComPort;
  796. pLink->pbport.dwType = RASET_Direct;
  797. pLink->fEnabled = TRUE;
  798. // If the first node hasn't been identified yet,
  799. // assign it to this one.
  800. //
  801. // ppNode is assumed to have been added to the
  802. // list pInfo->pEntry->pdtllistLinks (#348920)
  803. //
  804. if (! (*ppNodeP))
  805. {
  806. *ppNodeP = pNode;
  807. }
  808. else
  809. {
  810. DtlAddNodeLast( pInfo->pEntry->pdtllistLinks, pNode );
  811. }
  812. }
  813. }
  814. // Free up the resources held by the list of
  815. // free com ports
  816. DtlDestroyList(pListFreeComPorts, NULL);
  817. // Update the count
  818. *lpdwCount += fcpData.dwCount;
  819. return NO_ERROR;
  820. }
  821. DWORD
  822. EuChangeEntryType(
  823. IN EINFO* pInfo,
  824. IN DWORD dwType )
  825. // Changes the work entry node to the default settings for the RASET_*
  826. // entry type 'dwType', or if -1 to phone defaults with a full list of
  827. // available links. 'PInfo' is the common entry information block. As
  828. // this routine is intended for use only on new entries, information
  829. // stored in the entries existing list of links, if any, is discarded.
  830. //
  831. // Returns 0 if successful or an error code.
  832. //
  833. {
  834. DTLNODE* pNode;
  835. DTLNODE* pNodeP;
  836. DTLNODE* pNodeL;
  837. PBLINK* pLink;
  838. DWORD cDevices, cPorts;
  839. // Change the default settings of the phonebook entry, i.e. those not
  840. // specific to the way the UI manipulates the PBLINK list.
  841. //
  842. // pmay: 233287. Special types can be considered phone entries.
  843. //
  844. if ((dwType == RASET_P_AllTypes) || (dwType == RASET_P_NonVpnTypes))
  845. {
  846. ChangeEntryType( pInfo->pEntry, RASET_Phone );
  847. }
  848. else
  849. {
  850. ChangeEntryType( pInfo->pEntry, dwType );
  851. }
  852. // Update the list of PBLINKs to include only links of the appropriate
  853. // type. First, delete the old links, if any, and add one default link.
  854. // This resets the links to the what they are just after CreateEntryNode.
  855. //
  856. while (pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks ))
  857. {
  858. DtlRemoveNode( pInfo->pEntry->pdtllistLinks, pNodeL );
  859. DestroyLinkNode( pNodeL );
  860. }
  861. pNodeL = CreateLinkNode();
  862. if (!pNodeL)
  863. {
  864. return ERROR_NOT_ENOUGH_MEMORY;
  865. }
  866. DtlAddNodeLast( pInfo->pEntry->pdtllistLinks, pNodeL );
  867. pLink = (PBLINK* )DtlGetData( pNodeL );
  868. ASSERT( pLink );
  869. // Count the configured links of the indicated type, noting the first node
  870. // of the correct type.
  871. //
  872. cDevices = 0;
  873. pNodeP = NULL;
  874. for (pNode = DtlGetFirstNode( pInfo->pListPorts );
  875. pNode;
  876. pNode = DtlGetNextNode( pNode ))
  877. {
  878. PBPORT* pPort;
  879. pPort = (PBPORT* )DtlGetData( pNode );
  880. if ((dwType == RASET_P_AllTypes) ||
  881. ((dwType == RASET_P_NonVpnTypes) && (pPort->dwType != RASET_Vpn))||
  882. (pPort->dwType == dwType)
  883. )
  884. {
  885. ++cDevices;
  886. if (!pNodeP)
  887. {
  888. pNodeP = pNode;
  889. }
  890. }
  891. }
  892. // If this is a direct connect device, merge in the
  893. // com ports since they will be available to have
  894. // null modems installed over them
  895. if (pInfo->pEntry->dwType == RASET_Direct)
  896. {
  897. // pmay: 249346
  898. //
  899. // Only merge the com ports if the user is an admin since
  900. // admin privilege is required to install a null modem.
  901. //
  902. if (pInfo->fIsUserAdminOrPowerUser)
  903. {
  904. EuMergeAvailableComPorts(pInfo, &pNodeP, &cDevices);
  905. }
  906. }
  907. if (pNodeP)
  908. {
  909. pInfo->fNoPortsConfigured = FALSE;
  910. }
  911. else
  912. {
  913. TRACE( "No ports configured" );
  914. pInfo->fNoPortsConfigured = TRUE;
  915. pNodeP = CreatePortNode();
  916. }
  917. if (pNodeP)
  918. {
  919. PBPORT* pPort;
  920. pPort = (PBPORT* )DtlGetData( pNodeP );
  921. if (cDevices <= 0)
  922. {
  923. if (pInfo->pEntry->dwType == RASET_Phone)
  924. {
  925. // Make up a bogus COM port with unknown Unimodem
  926. // attached. Hereafter, this will behave like an entry
  927. // whose modem has been de-installed.
  928. //
  929. pPort->pszPort = PszFromId( g_hinstDll, SID_DefaultPort );
  930. pPort->pszMedia = StrDup( TEXT(SERIAL_TXT) );
  931. pPort->pbdevicetype = PBDT_Modem;
  932. // pmay: 233287
  933. // We need to track bogus devices so that the dd interface
  934. // wizard can prevent interfaces with these from being
  935. // created.
  936. pPort->dwFlags |= PBP_F_BogusDevice;
  937. }
  938. else if (pInfo->pEntry->dwType == RASET_Vpn)
  939. {
  940. pPort->pszPort = PszFromId( g_hinstDll, SID_DefaultVpnPort );
  941. pPort->pszMedia = StrDup( TEXT("rastapi") );
  942. pPort->pbdevicetype = PBDT_Vpn;
  943. }
  944. else if (pInfo->pEntry->dwType == RASET_Broadband)
  945. {
  946. pPort->pszPort = PszFromId( g_hinstDll, SID_DefaultBbPort );
  947. pPort->pszMedia = StrDup( TEXT("rastapi") );
  948. pPort->pbdevicetype = PBDT_PPPoE;
  949. pPort->dwFlags |= PBP_F_BogusDevice;
  950. }
  951. else
  952. {
  953. ASSERT( pInfo->pEntry->dwType == RASET_Direct );
  954. // Make up a bogus COM port with unknown Unimodem
  955. // attached. Hereafter, this will behave like an entry
  956. // whose modem has been de-installed.
  957. //
  958. pPort->pszPort = PszFromId( g_hinstDll, SID_DefaultPort );
  959. pPort->pszMedia = StrDup( TEXT(SERIAL_TXT) );
  960. pPort->pbdevicetype = PBDT_Null;
  961. // pmay: 233287
  962. // We need to track bogus devices so that the dd interface
  963. // wizard can prevent interfaces with these from being
  964. // created.
  965. pPort->dwFlags |= PBP_F_BogusDevice;
  966. }
  967. pPort->fConfigured = FALSE;
  968. }
  969. // If a bogus port was created, copy it into the
  970. // new node
  971. CopyToPbport( &pLink->pbport, pPort );
  972. if ((pLink->pbport.pbdevicetype == PBDT_Modem) ||
  973. (pLink->pbport.dwFlags & PBP_F_NullModem)
  974. )
  975. {
  976. SetDefaultModemSettings( pLink );
  977. }
  978. }
  979. if (pInfo->fNoPortsConfigured)
  980. {
  981. if(NULL != pNodeP)
  982. {
  983. DestroyPortNode( pNodeP );
  984. }
  985. }
  986. if (!pNodeP || !pLink->pbport.pszPort || !pLink->pbport.pszMedia)
  987. {
  988. return ERROR_NOT_ENOUGH_MEMORY;
  989. }
  990. // Append all non-configured ports of the entries type to the list of
  991. // links. This is for the convenience of the UI. The non-configured
  992. // ports are removed after editing prior to saving.
  993. //
  994. AppendDisabledPorts( pInfo, dwType );
  995. return NO_ERROR;
  996. }
  997. BOOL
  998. EuRouterInterfaceIsNew(
  999. IN EINFO * pInfo )
  1000. {
  1001. if ((pInfo->pApiArgs->dwFlags & RASEDFLAG_AnyNewEntry)
  1002. && pInfo->fRouter
  1003. && pInfo->pUser->fNewEntryWizard
  1004. && !pInfo->fChainPropertySheet)
  1005. {
  1006. return TRUE;
  1007. }
  1008. return FALSE;
  1009. } //EuRouterInterfaceIsNew()
  1010. BOOL
  1011. EuCommit(
  1012. IN EINFO* pInfo )
  1013. // Commits the new or changed entry node to the phonebook file and list.
  1014. // Also adds the area code to the per-user list, if indicated. 'PInfo' is
  1015. // the common entry information block.
  1016. //
  1017. // Returns true if successful, false otherwise.
  1018. //
  1019. {
  1020. DWORD dwErr;
  1021. BOOL fEditMode;
  1022. BOOL fChangedNameInEditMode;
  1023. // If shared phone number, copy the phone number information from the
  1024. // shared link to each enabled link.
  1025. //
  1026. if (pInfo->pEntry->fSharedPhoneNumbers)
  1027. {
  1028. DTLNODE* pNode;
  1029. ASSERT( pInfo->pEntry->dwType == RASET_Phone );
  1030. for (pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  1031. pNode;
  1032. pNode = DtlGetNextNode( pNode ))
  1033. {
  1034. PBLINK* pLink = (PBLINK* )DtlGetData( pNode );
  1035. ASSERT(pLink);
  1036. if (pLink->fEnabled)
  1037. {
  1038. CopyLinkPhoneNumberInfo( pNode, pInfo->pSharedNode );
  1039. }
  1040. }
  1041. }
  1042. // Delete all disabled link nodes.
  1043. //
  1044. if (pInfo->fMultipleDevices)
  1045. {
  1046. DTLNODE* pNode;
  1047. pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  1048. while (pNode)
  1049. {
  1050. PBLINK* pLink = (PBLINK* )DtlGetData( pNode );
  1051. DTLNODE* pNextNode = DtlGetNextNode( pNode );
  1052. if (!pLink->fEnabled)
  1053. {
  1054. DtlRemoveNode( pInfo->pEntry->pdtllistLinks, pNode );
  1055. DestroyLinkNode( pNode );
  1056. }
  1057. pNode = pNextNode;
  1058. }
  1059. }
  1060. // pmay: 277801
  1061. //
  1062. // Update the preferred device if the one selected is different
  1063. // from the device this page was initialized with.
  1064. //
  1065. if ((pInfo->fMultipleDevices) &&
  1066. (DtlGetNodes(pInfo->pEntry->pdtllistLinks) == 1))
  1067. {
  1068. DTLNODE* pNodeL;
  1069. PBLINK* pLink;
  1070. BOOL bUpdatePref = FALSE;
  1071. pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  1072. //For whistler bug 428308
  1073. //
  1074. if(pNodeL)
  1075. {
  1076. pLink = (PBLINK*) DtlGetData( pNodeL );
  1077. TRACE( "Mult devs, only one selected -- check preferred dev." );
  1078. if ((pInfo->pszCurDevice == NULL) || (pInfo->pszCurPort == NULL))
  1079. {
  1080. TRACE( "No preferred device. Resetting preferred to current." );
  1081. bUpdatePref = TRUE;
  1082. }
  1083. else if (
  1084. (lstrcmpi(pInfo->pszCurDevice, pLink->pbport.pszDevice)) ||
  1085. (lstrcmpi(pInfo->pszCurPort, pLink->pbport.pszPort)) ||
  1086. ( pInfo->pEntry->dwPreferredBps != pLink->dwBps ) ||
  1087. ( pInfo->pEntry->fPreferredHwFlow != pLink->fHwFlow ) ||//XPSP1 664578, .Net 639551
  1088. ( pInfo->pEntry->fPreferredEc != pLink->fEc ) ||
  1089. ( pInfo->pEntry->fPreferredEcc != pLink->fEcc ) ||
  1090. ( pInfo->pEntry->fPreferredSpeaker != pLink->fSpeaker ) ||
  1091. ( pInfo->pEntry->dwPreferredModemProtocol != //whistler 402522
  1092. pLink->dwModemProtocol) )
  1093. {
  1094. TRACE( "New device selected as preferred device" );
  1095. bUpdatePref = TRUE;
  1096. }
  1097. if (bUpdatePref)
  1098. {
  1099. // Assign new values to the preferred parameters
  1100. //
  1101. Free0(pInfo->pEntry->pszPreferredDevice);
  1102. Free0(pInfo->pEntry->pszPreferredPort);
  1103. pInfo->pEntry->pszPreferredDevice =
  1104. StrDup(pLink->pbport.pszDevice);
  1105. pInfo->pEntry->pszPreferredPort =
  1106. StrDup(pLink->pbport.pszPort);
  1107. // For XPSP1 664578, .Net bug 639551 gangz
  1108. //
  1109. pInfo->pEntry->dwPreferredBps = pLink->dwBps;
  1110. pInfo->pEntry->fPreferredHwFlow = pLink->fHwFlow;
  1111. pInfo->pEntry->fPreferredEc = pLink->fEc;
  1112. pInfo->pEntry->fPreferredEcc = pLink->fEcc;
  1113. pInfo->pEntry->fPreferredSpeaker = pLink->fSpeaker;
  1114. // For whistler bug 402522
  1115. //
  1116. pInfo->pEntry->dwPreferredModemProtocol =
  1117. pLink->dwModemProtocol;
  1118. }
  1119. }
  1120. }
  1121. // Save preferences if they've changed.
  1122. //
  1123. if (pInfo->pUser->fDirty)
  1124. {
  1125. INTERNALARGS *pIArgs = (INTERNALARGS *)pInfo->pApiArgs->reserved;
  1126. if (g_pSetUserPreferences(
  1127. (pIArgs) ? pIArgs->hConnection : NULL,
  1128. pInfo->pUser,
  1129. (pInfo->fRouter) ? UPM_Router : UPM_Normal ) != 0)
  1130. {
  1131. return FALSE;
  1132. }
  1133. }
  1134. // Save the changed phonebook entry.
  1135. //
  1136. pInfo->pEntry->fDirty = TRUE;
  1137. // The final name of the entry is output to caller via API structure.
  1138. //
  1139. lstrcpyn(
  1140. pInfo->pApiArgs->szEntry,
  1141. pInfo->pEntry->pszEntryName,
  1142. RAS_MaxEntryName + 1);
  1143. // Delete the old node if in edit mode, then add the new node.
  1144. //
  1145. EuGetEditFlags( pInfo, &fEditMode, &fChangedNameInEditMode );
  1146. if (fEditMode)
  1147. {
  1148. DtlDeleteNode( pInfo->pFile->pdtllistEntries, pInfo->pOldNode );
  1149. }
  1150. DtlAddNodeLast( pInfo->pFile->pdtllistEntries, pInfo->pNode );
  1151. pInfo->pNode = NULL;
  1152. // Write the change to the phone book file.
  1153. //
  1154. dwErr = WritePhonebookFile( pInfo->pFile,
  1155. (fChangedNameInEditMode) ? pInfo->szOldEntryName : NULL );
  1156. if (dwErr != 0)
  1157. {
  1158. ErrorDlg( pInfo->pApiArgs->hwndOwner, SID_OP_WritePhonebook, dwErr,
  1159. NULL );
  1160. // shaunco - fix RAID 171651 by assigning dwErr to callers structure.
  1161. pInfo->pApiArgs->dwError = dwErr;
  1162. return FALSE;
  1163. }
  1164. // Notify through rasman that the entry has changed
  1165. //
  1166. if(pInfo->pApiArgs->dwFlags & (RASEDFLAG_AnyNewEntry | RASEDFLAG_CloneEntry))
  1167. {
  1168. dwErr = DwSendRasNotification(
  1169. ENTRY_ADDED,
  1170. pInfo->pEntry,
  1171. pInfo->pFile->pszPath,
  1172. NULL);
  1173. }
  1174. else
  1175. {
  1176. dwErr = DwSendRasNotification(
  1177. ENTRY_MODIFIED,
  1178. pInfo->pEntry,
  1179. pInfo->pFile->pszPath,
  1180. NULL);
  1181. }
  1182. // Ignore the error returned from DwSendRasNotification - we don't want
  1183. // to fail the operation in this case. The worst case scenario is that
  1184. // the connections folder won't refresh automatically.
  1185. //
  1186. dwErr = ERROR_SUCCESS;
  1187. // If EuCommit is being called as a result of completing the "new demand
  1188. // dial interface" wizard, then we need to create the new demand dial
  1189. // interface now.
  1190. //
  1191. if ( EuRouterInterfaceIsNew( pInfo ) )
  1192. {
  1193. //Create Router MPR interface and save user credentials
  1194. //like UserName, Domain and Password
  1195. //IPSec credentials are save in EuCredentialsCommitRouterIPSec
  1196. //
  1197. dwErr = EuRouterInterfaceCreate( pInfo );
  1198. // If we weren't successful at commiting the interface's
  1199. // credentials, then delete the new phonebook entry.
  1200. //
  1201. if ( dwErr != NO_ERROR )
  1202. {
  1203. WritePhonebookFile( pInfo->pFile, pInfo->pApiArgs->szEntry );
  1204. pInfo->pApiArgs->dwError = dwErr;
  1205. return FALSE;
  1206. }
  1207. }
  1208. // Now save any per-connection credentials
  1209. //
  1210. dwErr = EuCredentialsCommit( pInfo );
  1211. // If we weren't successful at commiting the interface's
  1212. // credentials, then delete the new phonebook entry.
  1213. //
  1214. if ( dwErr != NO_ERROR )
  1215. {
  1216. ErrorDlg( pInfo->pApiArgs->hwndOwner,
  1217. SID_OP_CredCommit,
  1218. dwErr,
  1219. NULL );
  1220. pInfo->pApiArgs->dwError = dwErr;
  1221. return FALSE;
  1222. }
  1223. // Save the default Internet connection settings as appropriate. Igonre
  1224. // the error returned as failure to set the connection as default need
  1225. // not prevent the connection/interface creation.
  1226. //
  1227. dwErr = EuInternetSettingsCommitDefault( pInfo );
  1228. dwErr = NO_ERROR;
  1229. // If the user edited/created a router-phonebook entry, store the bitmask
  1230. // of selected network-protocols in 'reserved2'.
  1231. //
  1232. if (pInfo->fRouter)
  1233. {
  1234. pInfo->pApiArgs->reserved2 =
  1235. ((NP_Ip | NP_Ipx) & ~pInfo->pEntry->dwfExcludedProtocols);
  1236. }
  1237. // Commit the user's changes to home networking settings.
  1238. // Ignore the return value.
  1239. //
  1240. dwErr = EuHomenetCommitSettings(pInfo);
  1241. dwErr = NO_ERROR;
  1242. pInfo->pApiArgs->dwError = 0;
  1243. return TRUE;
  1244. }
  1245. DWORD
  1246. EuCredentialsCommit(
  1247. IN EINFO * pInfo )
  1248. {
  1249. // If the user is creating a new router-phonebook entry, and the user is
  1250. // using the router wizard to create it, and the user did not edit
  1251. // properties directly, save the dial-out credentials, and optionally, the
  1252. // dial-in credentials.
  1253. //
  1254. DWORD dwErr = NO_ERROR;
  1255. //Save the IPSec Credentials Info
  1256. //
  1257. if ( pInfo->fRouter )
  1258. {
  1259. // Save the router ipsec settings
  1260. //
  1261. dwErr = EuCredentialsCommitRouterIPSec( pInfo );
  1262. // If this is a new router connection, save the
  1263. // credentials. Currently, we only persist the
  1264. // standard credentials when it's a new router
  1265. // interface because there is no UI in the properties
  1266. // of a router interface that sets the standard
  1267. // credentials.
  1268. //
  1269. if ( (NO_ERROR == dwErr) && EuRouterInterfaceIsNew ( pInfo ) )
  1270. {
  1271. dwErr = EuCredentialsCommitRouterStandard( pInfo );
  1272. }
  1273. }
  1274. else
  1275. {
  1276. dwErr = EuCredentialsCommitRasIPSec( pInfo );
  1277. if (dwErr == NO_ERROR)
  1278. {
  1279. dwErr = EuCredentialsCommitRasGlobal( pInfo );
  1280. }
  1281. }
  1282. return dwErr;
  1283. } //end of EuCredentialsCommit()
  1284. DWORD
  1285. EuCredentialsCommitRouterStandard(
  1286. IN EINFO* pInfo )
  1287. {
  1288. DWORD dwErr = NO_ERROR;
  1289. HANDLE hServer = NULL;
  1290. WCHAR* pwszInterface = NULL;
  1291. HANDLE hInterface = NULL;
  1292. TRACE( "EuCredentialsCommitRouterStandard" );
  1293. // Generate the interface name based on the
  1294. // phonebook entry name
  1295. dwErr = g_pMprAdminServerConnect(pInfo->pszRouter, &hServer);
  1296. if (dwErr != NO_ERROR)
  1297. {
  1298. return dwErr;
  1299. }
  1300. do{
  1301. //Get the interface handle
  1302. //
  1303. pwszInterface = StrDupWFromT( pInfo->pEntry->pszEntryName );
  1304. if (!pwszInterface)
  1305. {
  1306. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1307. break;
  1308. }
  1309. dwErr = g_pMprAdminInterfaceGetHandle(
  1310. hServer,
  1311. pwszInterface,
  1312. &hInterface,
  1313. FALSE);
  1314. if (dwErr)
  1315. {
  1316. TRACE1(
  1317. "EuCredComRouterStandard: MprAdminInterfaceGetHandle error %d",
  1318. dwErr);
  1319. break;
  1320. }
  1321. // Whistler bug 254385 encode password when not being used
  1322. // Assumed password was encoded previously
  1323. //
  1324. DecodePassword( pInfo->pszRouterPassword );
  1325. dwErr = g_pMprAdminInterfaceSetCredentials(
  1326. pInfo->pszRouter,
  1327. pwszInterface,
  1328. pInfo->pszRouterUserName,
  1329. pInfo->pszRouterDomain,
  1330. pInfo->pszRouterPassword );
  1331. EncodePassword( pInfo->pszRouterPassword );
  1332. if(dwErr)
  1333. {
  1334. TRACE1(
  1335. "EuCredComRouterStndrd: MprAdminInterfaceSetCredentials error %d",
  1336. dwErr);
  1337. break;
  1338. }
  1339. }
  1340. while(FALSE);
  1341. if (pwszInterface)
  1342. {
  1343. Free0(pwszInterface);
  1344. }
  1345. if (hServer)
  1346. {
  1347. g_pMprAdminServerDisconnect( hServer );
  1348. }
  1349. return dwErr;
  1350. } //EuCredentialsCommitRouterStandard()
  1351. //
  1352. //Save IPSec keys
  1353. //
  1354. DWORD
  1355. EuCredentialsCommitRouterIPSec(
  1356. IN EINFO* pInfo )
  1357. {
  1358. DWORD dwErr = NO_ERROR;
  1359. HANDLE hServer = NULL;
  1360. HANDLE hInterface = NULL;
  1361. WCHAR* pwszInterface = NULL;
  1362. WCHAR pszComputer[512];
  1363. BOOL bComputer, bUserAdded = FALSE;
  1364. MPR_INTERFACE_0 mi0;
  1365. MPR_CREDENTIALSEX_1 mc1;
  1366. TRACE( "EuCredComRouterIPSec" );
  1367. //
  1368. //Save PSK only when User changed it in the Property UI
  1369. //
  1370. if ( !pInfo->fPSKCached )
  1371. {
  1372. return NO_ERROR;
  1373. }
  1374. // Connect to the router service.
  1375. //
  1376. dwErr = g_pMprAdminServerConnect(pInfo->pszRouter, &hServer);
  1377. if (dwErr != NO_ERROR)
  1378. {
  1379. return dwErr;
  1380. }
  1381. do
  1382. {
  1383. // Initialize the interface-information structure.
  1384. //
  1385. ZeroMemory( &mi0, sizeof(mi0) );
  1386. mi0.dwIfType = ROUTER_IF_TYPE_FULL_ROUTER;
  1387. mi0.fEnabled = TRUE;
  1388. pwszInterface = StrDupWFromT( pInfo->pEntry->pszEntryName );
  1389. if (!pwszInterface)
  1390. {
  1391. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1392. break;
  1393. }
  1394. lstrcpynW(
  1395. mi0.wszInterfaceName,
  1396. pwszInterface,
  1397. MAX_INTERFACE_NAME_LEN+1 );
  1398. //
  1399. //Get the interface handle
  1400. //
  1401. dwErr = g_pMprAdminInterfaceGetHandle(
  1402. hServer,
  1403. pwszInterface,
  1404. &hInterface,
  1405. FALSE);
  1406. if (dwErr)
  1407. {
  1408. TRACE1( "EuCredComRouterIPSec: MprAdminInterfaceGetHandle error %d", dwErr);
  1409. break;
  1410. }
  1411. // Set the dial-out credentials for the interface. Stop after this if
  1412. // an error occurs, or if we don't need to add a user-account.
  1413. //
  1414. //Save the IPSec Policy keys(PSK for Whislter)
  1415. //
  1416. ASSERT( g_pMprAdminInterfaceSetCredentialsEx );
  1417. ZeroMemory( &mc1, sizeof(mc1) );
  1418. mc1.dwSize = sizeof( pInfo->szPSK );
  1419. mc1.lpbCredentialsInfo = (LPBYTE)(pInfo->szPSK);
  1420. // Whistler bug 254385 encode password when not being used
  1421. // Assumed password was encoded previously
  1422. //
  1423. DecodePassword( pInfo->szPSK );
  1424. dwErr = g_pMprAdminInterfaceSetCredentialsEx(
  1425. hServer,
  1426. hInterface,
  1427. 1,
  1428. (LPBYTE)&mc1);
  1429. EncodePassword( pInfo->szPSK );
  1430. if(dwErr)
  1431. {
  1432. TRACE1(
  1433. "EuCredComRouterIPSec: MprAdminInterfaceSetCredentialsEx error %d",
  1434. dwErr);
  1435. break;
  1436. }
  1437. }
  1438. while (FALSE);
  1439. // Cleanup
  1440. {
  1441. // Close all handles, free all strings.
  1442. if (pwszInterface)
  1443. {
  1444. Free0( pwszInterface );
  1445. }
  1446. if (hServer)
  1447. {
  1448. g_pMprAdminServerDisconnect( hServer );
  1449. }
  1450. }
  1451. return dwErr;
  1452. }//end of EuCredentialsCommitRouterIPSec()
  1453. DWORD
  1454. EuCredentialsCommitRasIPSec(
  1455. IN EINFO* pInfo )
  1456. {
  1457. //Save IPSec Keys through RAS functions
  1458. //
  1459. DWORD dwErr = NO_ERROR;
  1460. RASCREDENTIALS rc;
  1461. TRACE( "EuCredentialsCommitRasIPSec" );
  1462. if ( pInfo->fPSKCached )
  1463. {
  1464. ZeroMemory( &rc, sizeof(rc) );
  1465. rc.dwSize = sizeof(rc);
  1466. rc.dwMask = RASCM_PreSharedKey; //RASCM_Password; //RASCM_UserName;
  1467. // Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
  1468. //
  1469. // Whistler bug 254385 encode password when not being used
  1470. // Assumed password was encoded previously
  1471. //
  1472. DecodePassword( pInfo->szPSK );
  1473. lstrcpyn(
  1474. rc.szPassword,
  1475. pInfo->szPSK,
  1476. sizeof(rc.szPassword) / sizeof(TCHAR) );
  1477. EncodePassword( pInfo->szPSK );
  1478. ASSERT( g_pRasSetCredentials );
  1479. TRACE( "RasSetCredentials(p,TRUE)" );
  1480. dwErr = g_pRasSetCredentials(
  1481. pInfo->pFile->pszPath,
  1482. pInfo->pEntry->pszEntryName,
  1483. &rc,
  1484. FALSE );
  1485. ZeroMemory( rc.szPassword, sizeof(rc.szPassword) );
  1486. TRACE1( "EuCredentialsCommitRasIPSec: RasSetCredentials=%d", dwErr );
  1487. if (dwErr != 0)
  1488. {
  1489. ErrorDlg( pInfo->pApiArgs->hwndOwner, SID_OP_CachePw, dwErr, NULL );
  1490. }
  1491. }
  1492. return dwErr;
  1493. } //end of EuCredentialsCommitRasIPSec()
  1494. // Commits the global ras credentials
  1495. //
  1496. DWORD
  1497. EuCredentialsCommitRasGlobal(
  1498. IN EINFO* pInfo )
  1499. {
  1500. DWORD dwErr = NO_ERROR;
  1501. RASCREDENTIALS rc;
  1502. TRACE( "EuCredentialsCommitRasGlobal" );
  1503. if ( pInfo->pszDefUserName )
  1504. {
  1505. ZeroMemory( &rc, sizeof(rc) );
  1506. rc.dwSize = sizeof(rc);
  1507. rc.dwMask = RASCM_UserName | RASCM_Password;
  1508. //Add this for whistler bug 328673
  1509. //
  1510. if ( pInfo->fGlobalCred )
  1511. {
  1512. rc.dwMask |= RASCM_DefaultCreds;
  1513. }
  1514. // Whistler bug 254385 encode password when not being used
  1515. //
  1516. DecodePassword( pInfo->pszDefPassword );
  1517. lstrcpyn(
  1518. rc.szPassword,
  1519. pInfo->pszDefPassword,
  1520. sizeof(rc.szPassword) / sizeof(TCHAR));
  1521. EncodePassword( pInfo->pszDefPassword );
  1522. lstrcpyn(
  1523. rc.szUserName,
  1524. pInfo->pszDefUserName,
  1525. sizeof(rc.szUserName) / sizeof(TCHAR));
  1526. ASSERT( g_pRasSetCredentials );
  1527. TRACE( "RasSetCredentials(p,TRUE)" );
  1528. dwErr = g_pRasSetCredentials(
  1529. pInfo->pFile->pszPath,
  1530. pInfo->pEntry->pszEntryName,
  1531. &rc,
  1532. FALSE );
  1533. // Whistler bug 254385 encode password when not being used
  1534. //
  1535. ZeroMemory( rc.szPassword, sizeof(rc.szPassword) );
  1536. TRACE1( "EuCredsCommitRasGlobal: RasSetCredentials=%d", dwErr );
  1537. if (dwErr != 0)
  1538. {
  1539. ErrorDlg(
  1540. pInfo->pApiArgs->hwndOwner,
  1541. SID_OP_CachePw,
  1542. dwErr,
  1543. NULL );
  1544. }
  1545. }
  1546. return dwErr;
  1547. }
  1548. DWORD
  1549. EuInternetSettingsCommitDefault(
  1550. IN EINFO* pInfo )
  1551. {
  1552. RASAUTODIALENTRY adEntry;
  1553. DWORD dwErr = NO_ERROR;
  1554. ZeroMemory(&adEntry, sizeof(adEntry));
  1555. adEntry.dwSize = sizeof(adEntry);
  1556. if ( pInfo->fDefInternet )
  1557. {
  1558. lstrcpyn(
  1559. adEntry.szEntry,
  1560. pInfo->pApiArgs->szEntry,
  1561. RAS_MaxEntryName + 1);
  1562. dwErr = RasSetAutodialAddress(
  1563. NULL,
  1564. 0,
  1565. &adEntry,
  1566. sizeof(adEntry),
  1567. 1);
  1568. }
  1569. return dwErr;
  1570. }
  1571. DWORD
  1572. EuHomenetCommitSettings(
  1573. IN EINFO* pInfo)
  1574. {
  1575. DWORD dwErr = NO_ERROR;
  1576. return dwErr;
  1577. }
  1578. DWORD
  1579. EuRouterInterfaceCreate(
  1580. IN EINFO* pInfo )
  1581. // Commits the credentials and user-account for a router interface.
  1582. //
  1583. {
  1584. DWORD dwErr;
  1585. DWORD dwPos, dwSize;
  1586. HANDLE hServer = NULL, hUserServer = NULL, hUser = NULL;
  1587. HANDLE hInterface = NULL;
  1588. WCHAR* pwszInterface = NULL;
  1589. WCHAR pszComputer[512];
  1590. BOOL bComputer, bUserAdded = FALSE;
  1591. RAS_USER_0 ru0;
  1592. USER_INFO_1 ui1;
  1593. MPR_INTERFACE_0 mi0;
  1594. //MPR_CREDENTIALSEX_1 mc1;
  1595. TRACE( "EuRouterInterfaceCreate" );
  1596. // Connect to the router service.
  1597. //
  1598. dwErr = g_pMprAdminServerConnect(pInfo->pszRouter, &hServer);
  1599. if (dwErr != NO_ERROR)
  1600. {
  1601. return dwErr;
  1602. }
  1603. do
  1604. {
  1605. // Initialize the interface-information structure.
  1606. //
  1607. ZeroMemory( &mi0, sizeof(mi0) );
  1608. mi0.dwIfType = ROUTER_IF_TYPE_FULL_ROUTER;
  1609. mi0.fEnabled = TRUE;
  1610. pwszInterface = StrDupWFromT( pInfo->pEntry->pszEntryName );
  1611. if (!pwszInterface)
  1612. {
  1613. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1614. break;
  1615. }
  1616. lstrcpynW(
  1617. mi0.wszInterfaceName,
  1618. pwszInterface,
  1619. MAX_INTERFACE_NAME_LEN+1 );
  1620. // Create the interface.
  1621. //
  1622. dwErr = g_pMprAdminInterfaceCreate(
  1623. hServer,
  1624. 0,
  1625. (BYTE*)&mi0,
  1626. &hInterface );
  1627. if ( dwErr )
  1628. {
  1629. TRACE1( "EuRouterInterfaceCreate: MprAdminInterfaceCreate error %d", dwErr);
  1630. break;
  1631. }
  1632. dwErr = g_pMprAdminInterfaceGetHandle(
  1633. hServer,
  1634. pwszInterface,
  1635. &hInterface,
  1636. FALSE);
  1637. if (dwErr)
  1638. {
  1639. TRACE1( "EuRouterInterfaceCreate: MprAdminInterfaceGetHandle error %d", dwErr);
  1640. break;
  1641. }
  1642. // Add a user if we were instructed to.
  1643. if (pInfo->fAddUser)
  1644. {
  1645. // Initialize user-information structure.
  1646. //
  1647. ZeroMemory( &ui1, sizeof(ui1) );
  1648. ui1.usri1_name = pwszInterface;
  1649. // Whistler bug 254385 encode password when not being used
  1650. // Assumed password was encoded previously
  1651. //
  1652. DecodePassword( pInfo->pszRouterDialInPassword );
  1653. ui1.usri1_password =
  1654. StrDupWFromT( pInfo->pszRouterDialInPassword );
  1655. EncodePassword( pInfo->pszRouterDialInPassword );
  1656. ui1.usri1_priv = USER_PRIV_USER;
  1657. ui1.usri1_comment =
  1658. PszFromId( g_hinstDll, SID_RouterDialInAccount );
  1659. ui1.usri1_flags = UF_SCRIPT |
  1660. UF_NORMAL_ACCOUNT |
  1661. UF_DONT_EXPIRE_PASSWD;
  1662. // Format the server name so that it is
  1663. // in the form '\\<server>' as this is
  1664. // required by the NetUser api's.
  1665. bComputer = FALSE;
  1666. if (pInfo->pszRouter)
  1667. {
  1668. if (*(pInfo->pszRouter) != L'\\')
  1669. {
  1670. dwSize = sizeof(pszComputer) - (2 * sizeof(WCHAR));
  1671. // Whistler bug 224074 use only lstrcpyn's to prevent
  1672. // maliciousness
  1673. //
  1674. lstrcpynW(
  1675. pszComputer,
  1676. L"\\\\",
  1677. sizeof(pszComputer) / sizeof(TCHAR) );
  1678. if (*(pInfo->pszRouter) != 0)
  1679. {
  1680. lstrcatW(pszComputer, pInfo->pszRouter);
  1681. }
  1682. else
  1683. {
  1684. GetComputerName(pszComputer + 2, &dwSize);
  1685. }
  1686. bComputer = TRUE;
  1687. }
  1688. }
  1689. // Add the user-account.
  1690. //
  1691. dwErr = NetUserAdd(
  1692. (bComputer) ? pszComputer : pInfo->pszRouter,
  1693. 1,
  1694. (BYTE*)&ui1,
  1695. &dwPos );
  1696. ZeroMemory(
  1697. ui1.usri1_password,
  1698. lstrlen( ui1.usri1_password ) * sizeof(TCHAR) );
  1699. Free0(ui1.usri1_password);
  1700. Free0(ui1.usri1_comment);
  1701. // pmay: bug 232983. If the user already exists, give the
  1702. // admin the option of continuing with the config or
  1703. // canceling this operation.
  1704. if (dwErr == NERR_UserExists)
  1705. {
  1706. MSGARGS args;
  1707. INT iRet;
  1708. // Initialize the arguments that specify the
  1709. // type of popup we want.
  1710. ZeroMemory(&args, sizeof(args));
  1711. args.dwFlags = MB_YESNO | MB_ICONINFORMATION;
  1712. args.apszArgs[0] = ui1.usri1_name;
  1713. // Popup the confirmation
  1714. iRet = MsgDlg(
  1715. GetActiveWindow(),
  1716. SID_RouterUserExists,
  1717. &args );
  1718. if (iRet == IDNO)
  1719. {
  1720. break;
  1721. }
  1722. }
  1723. // If some other error occurred besides the user already
  1724. // existing, bail out.
  1725. else if (dwErr)
  1726. {
  1727. TRACE1( "EuRouterInterfaceCreate: NetUserAdd error %d", dwErr );
  1728. break;
  1729. }
  1730. // Otherwise, record the fact that a user was added
  1731. // so that we can clean up as appropriate.
  1732. else
  1733. {
  1734. bUserAdded = TRUE;
  1735. }
  1736. // Initialize the RAS user-settings structure.
  1737. //
  1738. ZeroMemory( &ru0, sizeof(ru0) );
  1739. ru0.bfPrivilege = RASPRIV_NoCallback | RASPRIV_DialinPrivilege;
  1740. // Nt4 routers enable local users by setting user parms
  1741. //
  1742. if ( pInfo->fNt4Router )
  1743. {
  1744. dwErr = g_pRasAdminUserSetInfo(
  1745. pInfo->pszRouter,
  1746. pwszInterface,
  1747. 0,
  1748. (BYTE*)&ru0 );
  1749. if(dwErr)
  1750. {
  1751. TRACE1( "EuRouterInterfaceCreate: MprAdminUserSetInfo %d", dwErr );
  1752. break;
  1753. }
  1754. }
  1755. // Nt5 routers enable users for dialin by setting
  1756. // information with sdo's.
  1757. else
  1758. {
  1759. dwErr = g_pMprAdminUserServerConnect(
  1760. (bComputer) ? pszComputer : pInfo->pszRouter,
  1761. TRUE,
  1762. &hUserServer);
  1763. if (dwErr != NO_ERROR)
  1764. {
  1765. TRACE1( "EuRouterInterfaceCreate: UserSvrConnect error %d", dwErr );
  1766. break;
  1767. }
  1768. dwErr = g_pMprAdminUserOpen(
  1769. hUserServer,
  1770. pwszInterface,
  1771. &hUser);
  1772. if (dwErr != NO_ERROR)
  1773. {
  1774. TRACE1( "EuRouterInterfaceCreate: UserOpen error %d", dwErr );
  1775. break;
  1776. }
  1777. dwErr = g_pMprAdminUserWrite(
  1778. hUser,
  1779. 0,
  1780. (LPBYTE)&ru0);
  1781. if (dwErr != NO_ERROR)
  1782. {
  1783. TRACE1( "EuRouterInterfaceCreate: UserWrite error %d", dwErr );
  1784. break;
  1785. }
  1786. }
  1787. }
  1788. }
  1789. while (FALSE);
  1790. // Cleanup
  1791. {
  1792. // If some operation failed, restore the router to the
  1793. // state it was previously in.
  1794. if ( dwErr != NO_ERROR )
  1795. {
  1796. // Cleanup the interface we created...
  1797. if ( hInterface )
  1798. {
  1799. MprAdminInterfaceDelete(hServer, hInterface);
  1800. }
  1801. if ( bUserAdded )
  1802. {
  1803. NetUserDel (
  1804. (bComputer) ? pszComputer : pInfo->pszRouter,
  1805. pwszInterface );
  1806. }
  1807. }
  1808. // Close all handles, free all strings.
  1809. if ( hUser )
  1810. g_pMprAdminUserClose( hUser );
  1811. if ( hUserServer )
  1812. g_pMprAdminUserServerDisconnect( hUserServer );
  1813. if (pwszInterface)
  1814. Free0( pwszInterface );
  1815. if (hServer)
  1816. g_pMprAdminServerDisconnect( hServer );
  1817. }
  1818. return dwErr;
  1819. }
  1820. VOID
  1821. EuFree(
  1822. IN EINFO* pInfo )
  1823. // Releases 'pInfo' and associated resources.
  1824. //
  1825. {
  1826. TCHAR* psz;
  1827. INTERNALARGS* piargs;
  1828. piargs = (INTERNALARGS* )pInfo->pApiArgs->reserved;
  1829. // Don't clean up the phonebook and user preferences if they arrived via
  1830. // the secret hack.
  1831. //
  1832. if (!piargs)
  1833. {
  1834. if (pInfo->pFile)
  1835. {
  1836. ClosePhonebookFile( pInfo->pFile );
  1837. }
  1838. if (pInfo->pUser)
  1839. {
  1840. DestroyUserPreferences( pInfo->pUser );
  1841. }
  1842. }
  1843. if (pInfo->pListPorts)
  1844. {
  1845. DtlDestroyList( pInfo->pListPorts, DestroyPortNode );
  1846. }
  1847. Free0(pInfo->pszCurDevice);
  1848. Free0(pInfo->pszCurPort);
  1849. if (pInfo->pNode)
  1850. {
  1851. DestroyEntryNode( pInfo->pNode );
  1852. }
  1853. // Free router-information
  1854. //
  1855. Free0( pInfo->pszRouter );
  1856. Free0( pInfo->pszRouterUserName );
  1857. Free0( pInfo->pszRouterDomain );
  1858. if (pInfo->pSharedNode)
  1859. {
  1860. DestroyLinkNode( pInfo->pSharedNode );
  1861. }
  1862. psz = pInfo->pszRouterPassword;
  1863. if (psz)
  1864. {
  1865. ZeroMemory( psz, lstrlen( psz ) * sizeof(TCHAR) );
  1866. Free( psz );
  1867. }
  1868. psz = pInfo->pszRouterDialInPassword;
  1869. if (psz)
  1870. {
  1871. ZeroMemory( psz, lstrlen( psz ) * sizeof(TCHAR) );
  1872. Free( psz );
  1873. }
  1874. // Free credentials stuff
  1875. //
  1876. Free0(pInfo->pszDefUserName);
  1877. // Whistler bug 254385 encode password when not being used
  1878. //
  1879. psz = pInfo->pszDefPassword;
  1880. if (psz)
  1881. {
  1882. ZeroMemory( psz, lstrlen( psz ) * sizeof(TCHAR) );
  1883. Free( psz );
  1884. }
  1885. if (pInfo->fComInitialized)
  1886. {
  1887. CoUninitialize();
  1888. }
  1889. Free( pInfo );
  1890. }
  1891. VOID
  1892. EuGetEditFlags(
  1893. IN EINFO* pEinfo,
  1894. OUT BOOL* pfEditMode,
  1895. OUT BOOL* pfChangedNameInEditMode )
  1896. // Sets '*pfEditMode' true if in edit mode, false otherwise. Set
  1897. // '*pfChangedNameInEditMode' true if the entry name was changed while in
  1898. // edit mode, false otherwise. 'PEinfo' is the common entry context.
  1899. //
  1900. {
  1901. if ((pEinfo->pApiArgs->dwFlags & RASEDFLAG_AnyNewEntry)
  1902. || (pEinfo->pApiArgs->dwFlags & RASEDFLAG_CloneEntry))
  1903. {
  1904. *pfEditMode = *pfChangedNameInEditMode = FALSE;
  1905. }
  1906. else
  1907. {
  1908. *pfEditMode = TRUE;
  1909. *pfChangedNameInEditMode =
  1910. (lstrcmpi( pEinfo->szOldEntryName,
  1911. pEinfo->pEntry->pszEntryName ) != 0);
  1912. }
  1913. }
  1914. DWORD
  1915. EuInit(
  1916. IN TCHAR* pszPhonebook,
  1917. IN TCHAR* pszEntry,
  1918. IN RASENTRYDLG* pArgs,
  1919. IN BOOL fRouter,
  1920. OUT EINFO** ppInfo,
  1921. OUT DWORD* pdwOp )
  1922. // Allocates '*ppInfo' data for use by the property sheet or wizard.
  1923. // 'PszPhonebook', 'pszEntry', and 'pArgs', are the arguments passed by
  1924. // user to the API. 'FRouter' is set if running in "router mode", clear
  1925. // for the normal "dial-out" mode. '*pdwOp' is set to the operation code
  1926. // associated with any error.
  1927. //
  1928. // Returns 0 if successful, or an error code. If non-null '*ppInfo' is
  1929. // returned caller must eventually call EuFree to release the returned
  1930. // block.
  1931. //
  1932. {
  1933. DWORD dwErr;
  1934. EINFO* pInfo;
  1935. INTERNALARGS* piargs;
  1936. *ppInfo = NULL;
  1937. *pdwOp = 0;
  1938. pInfo = Malloc( sizeof(EINFO) );
  1939. if (!pInfo)
  1940. {
  1941. return ERROR_NOT_ENOUGH_MEMORY;
  1942. }
  1943. *ppInfo = pInfo;
  1944. ZeroMemory( pInfo, sizeof(*pInfo ) );
  1945. pInfo->pszPhonebook = pszPhonebook;
  1946. pInfo->pszEntry = pszEntry;
  1947. pInfo->pApiArgs = pArgs;
  1948. pInfo->fRouter = fRouter;
  1949. piargs = (INTERNALARGS *)pArgs->reserved;
  1950. if (pInfo->fRouter)
  1951. {
  1952. LPTSTR pszRouter;
  1953. DWORD dwVersion;
  1954. ASSERT(piargs);
  1955. pszRouter = RemoteGetServerName(piargs->hConnection);
  1956. // pmay: 348623
  1957. //
  1958. // Note that RemoteGetServerName is guarenteed to return
  1959. // NULL for local box, non-NULL for remote
  1960. //
  1961. pInfo->fRemote = !!pszRouter;
  1962. if(NULL == pszRouter)
  1963. {
  1964. pszRouter = TEXT("");
  1965. }
  1966. pInfo->pszRouter = StrDupTFromW(pszRouter);
  1967. // Find out if we're focused on an nt4 router
  1968. // pInfo->fNt4Router = FALSE;
  1969. // IsNt40Machine( pszRouter, &(pInfo->fNt4Router) );
  1970. dwVersion = ((RAS_RPC *)(piargs->hConnection))->dwVersion;
  1971. pInfo->fNt4Router = !!(VERSION_40 == dwVersion );
  1972. //Find out if the remote server is a win2k machine
  1973. //
  1974. pInfo->fW2kRouter = !!(VERSION_50 == dwVersion );
  1975. }
  1976. // Load the user preferences, or figure out that caller has already loaded
  1977. // them.
  1978. //
  1979. if (piargs && !piargs->fInvalid)
  1980. {
  1981. // We've received user preferences and the "no user" status via the
  1982. // secret hack.
  1983. //
  1984. pInfo->pUser = piargs->pUser;
  1985. pInfo->fNoUser = piargs->fNoUser;
  1986. pInfo->pFile = piargs->pFile;
  1987. pInfo->fDisableFirstConnect = piargs->fDisableFirstConnect;
  1988. }
  1989. else
  1990. {
  1991. DWORD dwReadPbkFlags = 0;
  1992. // Read user preferences from registry.
  1993. //
  1994. dwErr = g_pGetUserPreferences(
  1995. (piargs) ? piargs->hConnection : NULL,
  1996. &pInfo->user,
  1997. (pInfo->fRouter) ? UPM_Router : UPM_Normal );
  1998. if (dwErr != 0)
  1999. {
  2000. *pdwOp = SID_OP_LoadPrefs;
  2001. return dwErr;
  2002. }
  2003. pInfo->pUser = &pInfo->user;
  2004. if(pInfo->fRouter)
  2005. {
  2006. pInfo->file.hConnection = piargs->hConnection;
  2007. dwReadPbkFlags |= RPBF_Router;
  2008. }
  2009. if(pInfo->fNoUser)
  2010. {
  2011. dwReadPbkFlags |= RPBF_NoUser;
  2012. }
  2013. else
  2014. {
  2015. if (IsConsumerPlatform())
  2016. {
  2017. dwReadPbkFlags |= RPBF_AllUserPbk;
  2018. }
  2019. }
  2020. // Load and parse the phonebook file.
  2021. //
  2022. dwErr = ReadPhonebookFile(
  2023. pInfo->pszPhonebook, &pInfo->user, NULL,
  2024. dwReadPbkFlags,
  2025. &pInfo->file );
  2026. if (dwErr != 0)
  2027. {
  2028. *pdwOp = SID_OP_LoadPhonebook;
  2029. return dwErr;
  2030. }
  2031. pInfo->pFile = &pInfo->file;
  2032. }
  2033. // Determine if strong encryption is supported. Export laws prevent it in
  2034. // some versions of the system.
  2035. //
  2036. {
  2037. ULONG ulCaps;
  2038. RAS_NDISWAN_DRIVER_INFO info;
  2039. ZeroMemory( &info, sizeof(info) );
  2040. ASSERT( g_pRasGetNdiswanDriverCaps );
  2041. dwErr = g_pRasGetNdiswanDriverCaps(
  2042. (piargs) ? piargs->hConnection : NULL, &info );
  2043. if (dwErr == 0)
  2044. {
  2045. pInfo->fStrongEncryption =
  2046. !!(info.DriverCaps & RAS_NDISWAN_128BIT_ENABLED);
  2047. }
  2048. else
  2049. {
  2050. pInfo->fStrongEncryption = FALSE;
  2051. }
  2052. }
  2053. // Load the list of ports.
  2054. //
  2055. dwErr = LoadPortsList2(
  2056. (piargs) ? piargs->hConnection : NULL,
  2057. &pInfo->pListPorts,
  2058. pInfo->fRouter );
  2059. if (dwErr != 0)
  2060. {
  2061. TRACE1( "LoadPortsList=%d", dwErr );
  2062. *pdwOp = SID_OP_RetrievingData;
  2063. return dwErr;
  2064. }
  2065. // Set up work entry node.
  2066. //
  2067. if (pInfo->pApiArgs->dwFlags & RASEDFLAG_AnyNewEntry)
  2068. {
  2069. DTLNODE* pNodeL;
  2070. DTLNODE* pNodeP;
  2071. PBLINK* pLink;
  2072. PBPORT* pPort;
  2073. // New entry mode, so 'pNode' set to default settings.
  2074. //
  2075. pInfo->pNode = CreateEntryNode( TRUE );
  2076. if (!pInfo->pNode)
  2077. {
  2078. TRACE( "CreateEntryNode failed" );
  2079. *pdwOp = SID_OP_RetrievingData;
  2080. return dwErr;
  2081. }
  2082. // Store entry within work node stored in context for convenience
  2083. // elsewhere.
  2084. //
  2085. pInfo->pEntry = (PBENTRY* )DtlGetData( pInfo->pNode );
  2086. ASSERT( pInfo->pEntry );
  2087. if (pInfo->fRouter)
  2088. {
  2089. // Set router specific defaults.
  2090. //
  2091. pInfo->pEntry->dwIpNameSource = ASRC_None;
  2092. pInfo->pEntry->dwRedialAttempts = 0;
  2093. // Since this is a new entry, setup a proposed entry name.
  2094. // This covers the case when the wizard is not used to
  2095. // create the entry and the property sheet has no way to enter
  2096. // the name.
  2097. ASSERT( !pInfo->pEntry->pszEntryName );
  2098. GetDefaultEntryName( pInfo->pFile,
  2099. RASET_Phone,
  2100. pInfo->fRouter,
  2101. &pInfo->pEntry->pszEntryName );
  2102. // Disable MS client and File and Print services by default
  2103. //
  2104. EnableOrDisableNetComponent( pInfo->pEntry, TEXT("ms_msclient"),
  2105. FALSE);
  2106. EnableOrDisableNetComponent( pInfo->pEntry, TEXT("ms_server"),
  2107. FALSE);
  2108. }
  2109. // Use caller's default name, if any.
  2110. //
  2111. if (pInfo->pszEntry)
  2112. {
  2113. pInfo->pEntry->pszEntryName = StrDup( pInfo->pszEntry );
  2114. }
  2115. // Set the default entry type to "phone", i.e. modems, ISDN, X.26 etc.
  2116. // This may be changed to "VPN" or "direct" by the new entry wizard
  2117. // after the initial wizard page.
  2118. //
  2119. EuChangeEntryType( pInfo, RASET_Phone );
  2120. }
  2121. else
  2122. {
  2123. DTLNODE* pNode;
  2124. // Edit or clone entry mode, so 'pNode' set to entry's current
  2125. // settings.
  2126. //
  2127. pInfo->pOldNode = EntryNodeFromName(
  2128. pInfo->pFile->pdtllistEntries, pInfo->pszEntry );
  2129. if ( !pInfo->pOldNode
  2130. && !pInfo->fRouter)
  2131. {
  2132. if(NULL == pInfo->pszPhonebook)
  2133. {
  2134. //
  2135. // Close the phonebook file we opened above.
  2136. // we will try to find the entry name in the
  2137. // per user phonebook file.
  2138. //
  2139. ClosePhonebookFile(&pInfo->file);
  2140. pInfo->pFile = NULL;
  2141. //
  2142. // Attempt to find the file in users profile
  2143. //
  2144. dwErr = GetPbkAndEntryName(
  2145. NULL,
  2146. pInfo->pszEntry,
  2147. 0,
  2148. &pInfo->file,
  2149. &pInfo->pOldNode);
  2150. if(ERROR_SUCCESS != dwErr)
  2151. {
  2152. *pdwOp = SID_OP_RetrievingData;
  2153. return ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  2154. }
  2155. pInfo->pFile = &pInfo->file;
  2156. }
  2157. else
  2158. {
  2159. *pdwOp = SID_OP_RetrievingData;
  2160. return ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  2161. }
  2162. }
  2163. if(NULL != pInfo->pOldNode)
  2164. {
  2165. PBENTRY *pEntry = (PBENTRY *) DtlGetData(pInfo->pOldNode);
  2166. // Before cloning or editing make sure that for dial up
  2167. // connections, share File And Print is disabled.
  2168. //
  2169. if( ((RASET_Phone == pEntry->dwType)
  2170. || (RASET_Broadband == pEntry->dwType))
  2171. && (!pEntry->fShareMsFilePrint))
  2172. {
  2173. EnableOrDisableNetComponent( pEntry, TEXT("ms_server"),
  2174. FALSE);
  2175. }
  2176. }
  2177. if(NULL != pInfo->pOldNode)
  2178. {
  2179. if (pInfo->pApiArgs->dwFlags & RASEDFLAG_CloneEntry)
  2180. {
  2181. pInfo->pNode = CloneEntryNode( pInfo->pOldNode );
  2182. }
  2183. else
  2184. {
  2185. pInfo->pNode = DuplicateEntryNode( pInfo->pOldNode );
  2186. }
  2187. }
  2188. if (!pInfo->pNode)
  2189. {
  2190. TRACE( "DuplicateEntryNode failed" );
  2191. *pdwOp = SID_OP_RetrievingData;
  2192. return ERROR_NOT_ENOUGH_MEMORY;
  2193. }
  2194. // Store entry within work node stored in context for convenience
  2195. // elsewhere.
  2196. //
  2197. pInfo->pEntry = (PBENTRY* )DtlGetData( pInfo->pNode );
  2198. // Save original entry name for comparison later.
  2199. //
  2200. lstrcpyn(
  2201. pInfo->szOldEntryName,
  2202. pInfo->pEntry->pszEntryName,
  2203. RAS_MaxEntryName + 1);
  2204. // For router, want unconfigured ports to show up as "unavailable" so
  2205. // they stand out to user who has been directed to change them.
  2206. //
  2207. if (pInfo->fRouter)
  2208. {
  2209. DTLNODE* pNodeL;
  2210. PBLINK* pLink;
  2211. pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  2212. pLink = (PBLINK* )DtlGetData( pNodeL );
  2213. if (!pLink->pbport.fConfigured)
  2214. {
  2215. Free0( pLink->pbport.pszDevice );
  2216. pLink->pbport.pszDevice = NULL;
  2217. }
  2218. }
  2219. // pmay: 277801
  2220. //
  2221. // Remember the "current" device if this entry was last saved
  2222. // as single link.
  2223. //
  2224. if (DtlGetNodes(pInfo->pEntry->pdtllistLinks) == 1)
  2225. {
  2226. DTLNODE* pNodeL;
  2227. PBLINK* pLink;
  2228. pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  2229. pLink = (PBLINK* )DtlGetData( pNodeL );
  2230. if (pLink->pbport.pszDevice && pLink->pbport.pszPort)
  2231. {
  2232. pInfo->pszCurDevice =
  2233. StrDup(pLink->pbport.pszDevice);
  2234. pInfo->pszCurPort =
  2235. StrDup(pLink->pbport.pszPort);
  2236. }
  2237. }
  2238. // Append all non-configured ports of the entries type to the list of
  2239. // links. This is for the convenience of the UI. The non-configured
  2240. // ports are removed after editing prior to saving.
  2241. //
  2242. AppendDisabledPorts( pInfo, pInfo->pEntry->dwType );
  2243. }
  2244. // Set up the phone number storage for shared phone number mode.
  2245. // Initialize it to a copy of the information from the first link which at
  2246. // startup will always be enabled. Note the Dial case with non-0
  2247. // dwSubEntry is an exception, but in that case the pSharedNode anyway.
  2248. //
  2249. {
  2250. DTLNODE* pNode;
  2251. pInfo->pSharedNode = CreateLinkNode();
  2252. if (!pInfo->pSharedNode)
  2253. {
  2254. *pdwOp = SID_OP_RetrievingData;
  2255. return ERROR_NOT_ENOUGH_MEMORY;
  2256. }
  2257. ASSERT( pInfo->pSharedNode );
  2258. pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  2259. ASSERT( pNode );
  2260. CopyLinkPhoneNumberInfo( pInfo->pSharedNode, pNode );
  2261. }
  2262. if (pInfo->fRouter)
  2263. {
  2264. pInfo->pEntry->dwfExcludedProtocols |= NP_Nbf;
  2265. }
  2266. // AboladeG - capture the security level of the current user.
  2267. //
  2268. pInfo->fIsUserAdminOrPowerUser = FIsUserAdminOrPowerUser();
  2269. return 0;
  2270. }
  2271. BOOL
  2272. EuValidateName(
  2273. IN HWND hwndOwner,
  2274. IN EINFO* pEinfo )
  2275. // Validates the working entry name and pops up a message if invalid.
  2276. // 'HwndOwner' is the window to own the error popup. 'PEinfo' is the
  2277. // common dialog context containing the name to validate.
  2278. //
  2279. // Returns true if the name is valid, false if not.
  2280. //
  2281. {
  2282. PBENTRY* pEntry;
  2283. BOOL fEditMode;
  2284. BOOL fChangedNameInEditMode;
  2285. pEntry = pEinfo->pEntry;
  2286. // Validate the sheet data.
  2287. //
  2288. if (!ValidateEntryName( pEinfo->pEntry->pszEntryName ))
  2289. {
  2290. // Invalid entry name.
  2291. //
  2292. MsgDlg( hwndOwner, SID_BadEntry, NULL );
  2293. return FALSE;
  2294. }
  2295. EuGetEditFlags( pEinfo, &fEditMode, &fChangedNameInEditMode );
  2296. if ((fChangedNameInEditMode || !fEditMode)
  2297. && EntryNodeFromName(
  2298. pEinfo->pFile->pdtllistEntries, pEntry->pszEntryName ))
  2299. {
  2300. // Duplicate entry name.
  2301. //
  2302. MSGARGS msgargs;
  2303. ZeroMemory( &msgargs, sizeof(msgargs) );
  2304. msgargs.apszArgs[ 0 ] = pEntry->pszEntryName;
  2305. MsgDlg( hwndOwner, SID_DuplicateEntry, &msgargs );
  2306. return FALSE;
  2307. }
  2308. return TRUE;
  2309. }
  2310. //----------------------------------------------------------------------------
  2311. // Area-code and Country-code utility routiness (Cu utilities)
  2312. // Listed alphabetically
  2313. //----------------------------------------------------------------------------
  2314. VOID
  2315. CuClearCountryCodeLb(
  2316. IN CUINFO* pCuInfo )
  2317. // Clear the country code dropdown. 'PCuInfo' is the complex phone number
  2318. // context.
  2319. //
  2320. {
  2321. TRACE( "CuClearCountryCodeLb" );
  2322. ComboBox_ResetContent( pCuInfo->hwndLbCountryCodes );
  2323. if (pCuInfo->pCountries)
  2324. {
  2325. FreeCountryInfo( pCuInfo->pCountries, pCuInfo->cCountries );
  2326. pCuInfo->pCountries = NULL;
  2327. }
  2328. pCuInfo->cCountries = 0;
  2329. pCuInfo->fComplete = FALSE;
  2330. }
  2331. BOOL
  2332. CuCountryCodeLbHandler(
  2333. IN CUINFO* pCuInfo,
  2334. IN WORD wNotification )
  2335. // Handles WM_COMMAND notification to the Country Code dropdown.
  2336. // 'PCuInfo' is the complex phone number context. 'WNotification' is the
  2337. // wParam of the WM_COMMAND.
  2338. //
  2339. // Returns true if processed message, false otherwise.
  2340. //
  2341. {
  2342. switch (wNotification)
  2343. {
  2344. case CBN_DROPDOWN:
  2345. {
  2346. CuUpdateCountryCodeLb( pCuInfo, TRUE );
  2347. return TRUE;
  2348. }
  2349. case CBN_SELCHANGE:
  2350. {
  2351. CuCountryCodeLbSelChange( pCuInfo );
  2352. return TRUE;
  2353. }
  2354. }
  2355. return FALSE;
  2356. }
  2357. VOID
  2358. CuCountryCodeLbSelChange(
  2359. IN CUINFO* pCuInfo )
  2360. // Called when the country list selection has changed. 'PCuInfo' is the
  2361. // complex phone number context.
  2362. //
  2363. {
  2364. LONG lSign;
  2365. LONG i;
  2366. TRACE( "CuCountryCodeLbSelChange" );
  2367. // When a partial list (default after setting a new phone number set) is
  2368. // loaded there are dummy entries placed before and after the single
  2369. // country code with contexts of -1 and 1. This allows transparent
  2370. // behavior when user presses left/right arrows to change selection, in
  2371. // which case the full list of countries is loaded behind the scenes, and
  2372. // the selection adjusted to the country before/after the country in the
  2373. // original partial display.
  2374. //
  2375. lSign =
  2376. (LONG )ComboBox_GetItemData( pCuInfo->hwndLbCountryCodes,
  2377. ComboBox_GetCurSel( pCuInfo->hwndLbCountryCodes ) );
  2378. if (lSign == -1 || lSign == 1)
  2379. {
  2380. CuUpdateCountryCodeLb( pCuInfo, TRUE );
  2381. i = (LONG )ComboBox_GetCurSel( pCuInfo->hwndLbCountryCodes );
  2382. if (ComboBox_SetCurSel( pCuInfo->hwndLbCountryCodes, i + lSign ) < 0)
  2383. {
  2384. ComboBox_SetCurSel( pCuInfo->hwndLbCountryCodes, i );
  2385. }
  2386. }
  2387. else
  2388. {
  2389. ASSERT( pCuInfo->fComplete );
  2390. }
  2391. }
  2392. BOOL
  2393. CuDialingRulesCbHandler(
  2394. IN CUINFO* pCuInfo,
  2395. IN WORD wNotification )
  2396. // Handle the WM_COMMAND notification to the "use dialing rules" checkbox
  2397. // control. Updates the the Area Code and Country Code controls to
  2398. // reflect the current state of dialing rules. 'PCuInfo' is the complex
  2399. // phone number context. 'WNotification' is the wparam of the WM_COMMAND
  2400. // notification (though it currently assumes it's a button click).
  2401. //
  2402. // Returns true if processed message, false otherwise.
  2403. {
  2404. BOOL fRules;
  2405. BOOL fEnable;
  2406. TRACE( "CuDialingRulesCbChange" );
  2407. fRules = Button_GetCheck( pCuInfo->hwndCbUseDialingRules );
  2408. // For whistler bug 445424 gangz
  2409. //
  2410. if ( fRules )
  2411. {
  2412. DWORD dwErr = NO_ERROR;
  2413. HLINEAPP hlineapp = (HLINEAPP )0;
  2414. dwErr = TapiNoLocationDlg(
  2415. g_hinstDll,
  2416. &hlineapp,
  2417. pCuInfo->hwndCbUseDialingRules
  2418. );
  2419. if (dwErr != 0)
  2420. {
  2421. // Error here is treated as a "cancel" per bug 288385.
  2422. //
  2423. Button_SetCheck( pCuInfo->hwndCbUseDialingRules, FALSE);
  2424. fRules = FALSE;
  2425. Button_SetCheck( pCuInfo->hwndCbUseDialingRules, FALSE);
  2426. }
  2427. }
  2428. if (fRules)
  2429. {
  2430. CuUpdateCountryCodeLb( pCuInfo, FALSE );
  2431. CuUpdateAreaCodeClb( pCuInfo );
  2432. }
  2433. else
  2434. {
  2435. COUNTRY* pCountry;
  2436. INT iSel;
  2437. iSel = ComboBox_GetCurSel( pCuInfo->hwndLbCountryCodes );
  2438. if (iSel >= 0)
  2439. {
  2440. pCountry = (COUNTRY* )ComboBox_GetItemDataPtr(
  2441. pCuInfo->hwndLbCountryCodes, iSel );
  2442. ASSERT( pCountry );
  2443. if(NULL != pCountry)
  2444. {
  2445. pCuInfo->dwCountryId = pCountry->dwId;
  2446. pCuInfo->dwCountryCode = pCountry->dwCode;
  2447. }
  2448. }
  2449. Free0( pCuInfo->pszAreaCode );
  2450. pCuInfo->pszAreaCode = GetText( pCuInfo->hwndClbAreaCodes );
  2451. ComboBox_ResetContent( pCuInfo->hwndClbAreaCodes );
  2452. CuClearCountryCodeLb( pCuInfo );
  2453. }
  2454. EnableWindow( pCuInfo->hwndStAreaCodes, fRules );
  2455. EnableWindow( pCuInfo->hwndClbAreaCodes, fRules );
  2456. EnableWindow( pCuInfo->hwndStCountryCodes, fRules );
  2457. EnableWindow( pCuInfo->hwndLbCountryCodes, fRules );
  2458. EnableWindow( pCuInfo->hwndPbDialingRules, fRules );
  2459. return TRUE;
  2460. }
  2461. VOID
  2462. CuFree(
  2463. IN CUINFO* pCuInfo )
  2464. // Free resources attached to the 'pCuInfo' context.
  2465. //
  2466. {
  2467. TRACE( "CuFree" );
  2468. if (pCuInfo->pCountries)
  2469. {
  2470. FreeCountryInfo( pCuInfo->pCountries, pCuInfo->cCountries );
  2471. pCuInfo->pCountries = NULL;
  2472. }
  2473. pCuInfo->cCountries = 0;
  2474. pCuInfo->fComplete = FALSE;
  2475. Free0( pCuInfo->pszAreaCode );
  2476. pCuInfo->pszAreaCode = NULL;
  2477. }
  2478. VOID
  2479. CuGetInfo(
  2480. IN CUINFO* pCuInfo,
  2481. OUT DTLNODE* pPhoneNode )
  2482. // Load the phone number set information from the controls into PBPHONE
  2483. // node 'pPhone'. 'PCuInfo' is the complex phone number context.
  2484. //
  2485. {
  2486. PBPHONE* pPhone;
  2487. pPhone = (PBPHONE* )DtlGetData( pPhoneNode );
  2488. ASSERT( pPhone );
  2489. Free0( pPhone->pszPhoneNumber );
  2490. pPhone->pszPhoneNumber = GetText( pCuInfo->hwndEbPhoneNumber );
  2491. if (pCuInfo->hwndEbComment)
  2492. {
  2493. Free0( pPhone->pszComment );
  2494. pPhone->pszComment = GetText( pCuInfo->hwndEbComment );
  2495. }
  2496. pPhone->fUseDialingRules =
  2497. Button_GetCheck( pCuInfo->hwndCbUseDialingRules );
  2498. Free0( pPhone->pszAreaCode );
  2499. if (pPhone->fUseDialingRules)
  2500. {
  2501. COUNTRY* pCountry;
  2502. INT iSel;
  2503. // Get the area and country code selections from the lists.
  2504. //
  2505. pPhone->pszAreaCode = GetText( pCuInfo->hwndClbAreaCodes );
  2506. iSel = ComboBox_GetCurSel( pCuInfo->hwndLbCountryCodes );
  2507. if (iSel >= 0)
  2508. {
  2509. pCountry = (COUNTRY* )ComboBox_GetItemDataPtr(
  2510. pCuInfo->hwndLbCountryCodes, iSel );
  2511. ASSERT( pCountry );
  2512. if(NULL != pCountry)
  2513. {
  2514. pPhone->dwCountryID = pCountry->dwId;
  2515. pPhone->dwCountryCode = pCountry->dwCode;
  2516. }
  2517. }
  2518. }
  2519. else
  2520. {
  2521. // Get the "blanked" values instead.
  2522. //
  2523. pPhone->pszAreaCode = StrDup( pCuInfo->pszAreaCode );
  2524. pPhone->dwCountryID = pCuInfo->dwCountryId;
  2525. pPhone->dwCountryCode = pCuInfo->dwCountryCode;
  2526. }
  2527. if (pPhone->pszAreaCode)
  2528. {
  2529. TCHAR* pIn;
  2530. TCHAR* pOut;
  2531. // Sanitize the area code. See bug 298570.
  2532. //
  2533. for (pIn = pOut = pPhone->pszAreaCode; *pIn; ++pIn)
  2534. {
  2535. if (*pIn != TEXT(' ') && *pIn != TEXT('(') && *pIn != TEXT(')'))
  2536. {
  2537. *pOut++ = *pIn;
  2538. }
  2539. }
  2540. *pOut = TEXT('\0');
  2541. }
  2542. // Add the area code entered to the global list for this user.
  2543. //
  2544. CuSaveToAreaCodeList( pCuInfo, pPhone->pszAreaCode );
  2545. }
  2546. VOID
  2547. CuInit(
  2548. OUT CUINFO* pCuInfo,
  2549. IN HWND hwndStAreaCodes,
  2550. IN HWND hwndClbAreaCodes,
  2551. IN HWND hwndStPhoneNumber,
  2552. IN HWND hwndEbPhoneNumber,
  2553. IN HWND hwndStCountryCodes,
  2554. IN HWND hwndLbCountryCodes,
  2555. IN HWND hwndCbUseDialingRules,
  2556. IN HWND hwndPbDialingRules,
  2557. IN HWND hwndPbAlternates,
  2558. IN HWND hwndStComment,
  2559. IN HWND hwndEbComment,
  2560. IN DTLLIST* pListAreaCodes )
  2561. // Initialize the context '*pCuInfo' in preparation for using other CuXxx
  2562. // calls. The 'hwndStPhoneNumber', 'hwndStComment', 'hwndEbComment',
  2563. // 'hwndPbAlternates', and 'pListAreaCodes' arguments may be NULL. Others
  2564. // are required.
  2565. //
  2566. {
  2567. ZeroMemory( pCuInfo, sizeof(*pCuInfo) );
  2568. pCuInfo->hwndStAreaCodes = hwndStAreaCodes;
  2569. pCuInfo->hwndClbAreaCodes = hwndClbAreaCodes;
  2570. pCuInfo->hwndStPhoneNumber = hwndStPhoneNumber;
  2571. pCuInfo->hwndEbPhoneNumber = hwndEbPhoneNumber;
  2572. pCuInfo->hwndStCountryCodes = hwndStCountryCodes;
  2573. pCuInfo->hwndLbCountryCodes = hwndLbCountryCodes;
  2574. pCuInfo->hwndCbUseDialingRules = hwndCbUseDialingRules;
  2575. pCuInfo->hwndPbDialingRules = hwndPbDialingRules;
  2576. pCuInfo->hwndPbAlternates = hwndPbAlternates;
  2577. pCuInfo->hwndStComment = hwndStComment;
  2578. pCuInfo->hwndEbComment = hwndEbComment;
  2579. pCuInfo->pListAreaCodes = pListAreaCodes;
  2580. // Disaster defaults only. Not used in normal operation.
  2581. //
  2582. pCuInfo->dwCountryId = 1;
  2583. pCuInfo->dwCountryCode = 1;
  2584. Edit_LimitText( pCuInfo->hwndEbPhoneNumber, RAS_MaxPhoneNumber );
  2585. if (pCuInfo->hwndEbComment)
  2586. {
  2587. Edit_LimitText( pCuInfo->hwndEbComment, RAS_MaxDescription );
  2588. }
  2589. }
  2590. VOID
  2591. CuSaveToAreaCodeList(
  2592. IN CUINFO* pCuInfo,
  2593. IN TCHAR* pszAreaCode )
  2594. // Adds 'pszAreaCode' to the top of the list of area codes eliminating any
  2595. // duplicate farther down in the list.
  2596. //
  2597. {
  2598. DTLNODE* pNodeNew;
  2599. DTLNODE* pNode;
  2600. TRACE( "CuSaveToAreaCodeList" );
  2601. if (!pszAreaCode || IsAllWhite( pszAreaCode ) || !pCuInfo->pListAreaCodes)
  2602. {
  2603. return;
  2604. }
  2605. // Create a new node for the current area code and add it to the list
  2606. // head.
  2607. //
  2608. pNodeNew = CreatePszNode( pszAreaCode );
  2609. if (!pNodeNew)
  2610. {
  2611. return;
  2612. }
  2613. DtlAddNodeFirst( pCuInfo->pListAreaCodes, pNodeNew );
  2614. // Delete any other occurrence of the same area code later in the
  2615. // list.
  2616. //
  2617. pNode = DtlGetNextNode( pNodeNew );
  2618. while (pNode)
  2619. {
  2620. TCHAR* psz;
  2621. DTLNODE* pNodeNext;
  2622. pNodeNext = DtlGetNextNode( pNode );
  2623. psz = (TCHAR* )DtlGetData( pNode );
  2624. if (lstrcmp( psz, pszAreaCode ) == 0)
  2625. {
  2626. DtlRemoveNode( pCuInfo->pListAreaCodes, pNode );
  2627. DestroyPszNode( pNode );
  2628. }
  2629. pNode = pNodeNext;
  2630. }
  2631. }
  2632. VOID
  2633. CuSetInfo(
  2634. IN CUINFO* pCuInfo,
  2635. IN DTLNODE* pPhoneNode,
  2636. IN BOOL fDisableAll )
  2637. // Set the controls for context 'pCuInfo' to the PBPHONE node 'pPhoneNode'
  2638. // values. 'FDisableAll' indicates the controls are disabled, meaning a
  2639. // group disable, not a no dialing rules disable.
  2640. //
  2641. {
  2642. PBPHONE* pPhone;
  2643. BOOL fEnableAny;
  2644. BOOL fEnableComplex;
  2645. TRACE( "CuSetInfo" );
  2646. pPhone = (PBPHONE* )DtlGetData( pPhoneNode );
  2647. ASSERT( pPhone );
  2648. // Update "blanked" values.
  2649. //
  2650. Free0( pCuInfo->pszAreaCode );
  2651. pCuInfo->pszAreaCode = StrDup( pPhone->pszAreaCode );
  2652. pCuInfo->dwCountryId = pPhone->dwCountryID;
  2653. pCuInfo->dwCountryCode = pPhone->dwCountryCode;
  2654. SetWindowText(
  2655. pCuInfo->hwndEbPhoneNumber, UnNull( pPhone->pszPhoneNumber ) );
  2656. Button_SetCheck(
  2657. pCuInfo->hwndCbUseDialingRules, pPhone->fUseDialingRules );
  2658. if (pPhone->fUseDialingRules)
  2659. {
  2660. CuUpdateCountryCodeLb( pCuInfo, FALSE );
  2661. CuUpdateAreaCodeClb( pCuInfo );
  2662. }
  2663. else
  2664. {
  2665. ComboBox_ResetContent( pCuInfo->hwndClbAreaCodes );
  2666. CuClearCountryCodeLb( pCuInfo );
  2667. }
  2668. // Enable/disable controls.
  2669. //
  2670. fEnableAny = !fDisableAll;
  2671. fEnableComplex = (pPhone->fUseDialingRules && fEnableAny);
  2672. EnableWindow( pCuInfo->hwndStAreaCodes, fEnableComplex );
  2673. EnableWindow( pCuInfo->hwndClbAreaCodes, fEnableComplex );
  2674. EnableWindow( pCuInfo->hwndEbPhoneNumber, fEnableAny );
  2675. EnableWindow( pCuInfo->hwndStCountryCodes, fEnableComplex );
  2676. EnableWindow( pCuInfo->hwndLbCountryCodes, fEnableComplex );
  2677. EnableWindow( pCuInfo->hwndPbDialingRules, fEnableComplex );
  2678. if (pCuInfo->hwndStPhoneNumber)
  2679. {
  2680. EnableWindow( pCuInfo->hwndStPhoneNumber, fEnableAny );
  2681. }
  2682. if (pCuInfo->hwndPbAlternates)
  2683. {
  2684. EnableWindow( pCuInfo->hwndPbAlternates, fEnableAny );
  2685. }
  2686. if (pCuInfo->hwndEbComment)
  2687. {
  2688. SetWindowText( pCuInfo->hwndEbComment, UnNull( pPhone->pszComment ) );
  2689. EnableWindow( pCuInfo->hwndStComment, fEnableAny );
  2690. EnableWindow( pCuInfo->hwndEbComment, fEnableAny );
  2691. }
  2692. }
  2693. VOID
  2694. CuUpdateAreaCodeClb(
  2695. IN CUINFO* pCuInfo )
  2696. // Fill the area code combo-box-list, if necessary, and set the selection
  2697. // to the one in the context. 'PCuInfo' is the complex phone number
  2698. // context.
  2699. //
  2700. {
  2701. DTLNODE* pNode;
  2702. INT iSel;
  2703. TRACE( "CuUpdateAreaCodeClb" );
  2704. if (!pCuInfo->pListAreaCodes)
  2705. {
  2706. return;
  2707. }
  2708. ComboBox_ResetContent( pCuInfo->hwndClbAreaCodes );
  2709. ComboBox_LimitText( pCuInfo->hwndClbAreaCodes, RAS_MaxAreaCode );
  2710. // Add caller's list of area codes.
  2711. //
  2712. for (pNode = DtlGetFirstNode( pCuInfo->pListAreaCodes );
  2713. pNode;
  2714. pNode = DtlGetNextNode( pNode ))
  2715. {
  2716. TCHAR* pszAreaCode = (TCHAR* )DtlGetData( pNode );
  2717. ComboBox_AddString( pCuInfo->hwndClbAreaCodes, pszAreaCode );
  2718. }
  2719. // Select the last area code set via CuSetInfo, inserting at the top if
  2720. // it's not already in the list.
  2721. //
  2722. if (pCuInfo->pszAreaCode && *(pCuInfo->pszAreaCode))
  2723. {
  2724. iSel = ComboBox_FindStringExact(
  2725. pCuInfo->hwndClbAreaCodes, -1, pCuInfo->pszAreaCode );
  2726. if (iSel < 0)
  2727. {
  2728. ComboBox_InsertString(
  2729. pCuInfo->hwndClbAreaCodes, 0, pCuInfo->pszAreaCode );
  2730. iSel = 0;
  2731. }
  2732. ComboBox_SetCurSel( pCuInfo->hwndClbAreaCodes, iSel );
  2733. }
  2734. ComboBox_AutoSizeDroppedWidth( pCuInfo->hwndClbAreaCodes );
  2735. }
  2736. VOID
  2737. CuUpdateCountryCodeLb(
  2738. IN CUINFO* pCuInfo,
  2739. IN BOOL fComplete )
  2740. // Fill the country code dropdown and set the selection. 'FComplete'
  2741. // indicates the entire list should be loaded, otherwise only the selected
  2742. // item is loaded. 'PCuInfo' is the complex phone number context.
  2743. //
  2744. {
  2745. DWORD dwErr;
  2746. BOOL fSelectionOk;
  2747. COUNTRY* pCountries;
  2748. COUNTRY* pCountry;
  2749. DWORD cCountries;
  2750. DWORD i;
  2751. INT iSel;
  2752. TRACE1( "CuUpdateCountryCodeLb(f=%d)", fComplete );
  2753. // See if the current selection is the one to select. If so, and it's not
  2754. // a partial list when a complete list was requested, there's no need
  2755. // to do anything further.
  2756. //
  2757. iSel = ComboBox_GetCurSel( pCuInfo->hwndLbCountryCodes );
  2758. if (iSel >= 0)
  2759. {
  2760. pCountry = (COUNTRY* )ComboBox_GetItemDataPtr(
  2761. pCuInfo->hwndLbCountryCodes, iSel );
  2762. if (pCountry
  2763. && pCountry != (VOID* )-1
  2764. && pCountry != (VOID* )1
  2765. && (pCountry->dwId == pCuInfo->dwCountryId)
  2766. && (!fComplete || pCuInfo->fComplete))
  2767. {
  2768. return;
  2769. }
  2770. }
  2771. // ...otherwise, clear the list in preparation for reload.
  2772. //
  2773. CuClearCountryCodeLb( pCuInfo );
  2774. pCountries = NULL;
  2775. cCountries = 0;
  2776. dwErr = GetCountryInfo( &pCountries, &cCountries,
  2777. (fComplete) ? 0 : pCuInfo->dwCountryId );
  2778. if (dwErr == 0)
  2779. {
  2780. if (!fComplete)
  2781. {
  2782. // Add dummy item first in partial list so left arrow selection
  2783. // change can be handled correctly. See CBN_SELCHANGE handling.
  2784. //
  2785. ComboBox_AddItem(
  2786. pCuInfo->hwndLbCountryCodes, TEXT("AAAAA"), (VOID* )-1 );
  2787. }
  2788. for (i = 0, pCountry = pCountries;
  2789. i < cCountries;
  2790. ++i, ++pCountry)
  2791. {
  2792. INT iItem;
  2793. TCHAR szBuf[ 512 ];
  2794. wsprintf( szBuf, TEXT("%s (%d)"),
  2795. pCountry->pszName, pCountry->dwCode );
  2796. iItem = ComboBox_AddItem(
  2797. pCuInfo->hwndLbCountryCodes, szBuf, pCountry );
  2798. // If it's the one in the entry, select it.
  2799. //
  2800. if (pCountry->dwId == pCuInfo->dwCountryId)
  2801. {
  2802. ComboBox_SetCurSel( pCuInfo->hwndLbCountryCodes, iItem );
  2803. }
  2804. }
  2805. if (!fComplete)
  2806. {
  2807. // Add dummy item last in partial list so right arrow selection
  2808. // change can be handled correctly. See CBN_SELCHANGE handling.
  2809. //
  2810. ComboBox_AddItem(
  2811. pCuInfo->hwndLbCountryCodes, TEXT("ZZZZZ"), (VOID* )1 );
  2812. }
  2813. ComboBox_AutoSizeDroppedWidth( pCuInfo->hwndLbCountryCodes );
  2814. if (dwErr == 0 && cCountries == 0)
  2815. {
  2816. dwErr = ERROR_TAPI_CONFIGURATION;
  2817. }
  2818. }
  2819. if (dwErr != 0)
  2820. {
  2821. ErrorDlg( GetParent( pCuInfo->hwndLbCountryCodes ),
  2822. SID_OP_LoadTapiInfo, dwErr, NULL );
  2823. return;
  2824. }
  2825. if (ComboBox_GetCurSel( pCuInfo->hwndLbCountryCodes ) < 0)
  2826. {
  2827. // The entry's country code was not added to the list, so as an
  2828. // alternate select the first country in the list, loading the whole
  2829. // list if necessary...should be extremely rare, a diddled phonebook
  2830. // or TAPI country list strangeness.
  2831. //
  2832. if (ComboBox_GetCount( pCuInfo->hwndLbCountryCodes ) > 0)
  2833. {
  2834. ComboBox_SetCurSel( pCuInfo->hwndLbCountryCodes, 0 );
  2835. }
  2836. else
  2837. {
  2838. FreeCountryInfo( pCountries, cCountries );
  2839. CuUpdateCountryCodeLb( pCuInfo, TRUE );
  2840. return;
  2841. }
  2842. }
  2843. // Will be freed by CuFree.
  2844. //
  2845. pCuInfo->pCountries = pCountries;
  2846. pCuInfo->cCountries = cCountries;
  2847. pCuInfo->fComplete = fComplete;
  2848. }
  2849. //----------------------------------------------------------------------------
  2850. // Scripting utility routines (Su utilities)
  2851. // Listed alphabetically
  2852. //----------------------------------------------------------------------------
  2853. BOOL
  2854. SuBrowsePbHandler(
  2855. IN SUINFO* pSuInfo,
  2856. IN WORD wNotification )
  2857. // Handle the WM_COMMAND notification to the "browse" button control.
  2858. // 'PSuInfo' is the script utility context. 'WNotification' is the wparam
  2859. // of the WM_COMMAND notification.
  2860. //
  2861. // 'PSuInfo' is the script utility context.
  2862. //
  2863. {
  2864. OPENFILENAME ofn;
  2865. TCHAR* pszFilterDesc;
  2866. TCHAR* pszFilter;
  2867. TCHAR* pszDefExt;
  2868. TCHAR* pszTitle;
  2869. TCHAR szBuf[ MAX_PATH + 1 ];
  2870. TCHAR szDir[ MAX_PATH + 1 ];
  2871. TCHAR szFilter[ 64 ];
  2872. if (wNotification != BN_CLICKED)
  2873. {
  2874. return FALSE;
  2875. }
  2876. // Fill in FileOpen dialog parameter buffer.
  2877. //
  2878. pszFilterDesc = PszFromId( g_hinstDll, SID_ScpFilterDesc );
  2879. pszFilter = PszFromId( g_hinstDll, SID_ScpFilter );
  2880. if (pszFilterDesc && pszFilter)
  2881. {
  2882. DWORD dwLen = 0, dwSize = sizeof(szFilter) / sizeof(TCHAR);
  2883. ZeroMemory( szFilter, sizeof(szFilter) );
  2884. lstrcpyn( szFilter, pszFilterDesc, dwSize);
  2885. dwLen = lstrlen( szFilter ) + 1;
  2886. lstrcpyn( szFilter + dwLen, pszFilter, dwSize - dwLen );
  2887. }
  2888. Free0( pszFilterDesc );
  2889. Free0( pszFilter );
  2890. pszTitle = PszFromId( g_hinstDll, SID_ScpTitle );
  2891. pszDefExt = PszFromId( g_hinstDll, SID_ScpDefExt );
  2892. szBuf[ 0 ] = TEXT('\0');
  2893. szDir[ 0 ] = TEXT('\0');
  2894. // Saying "Alternate" rather than "System" here gives us the old NT
  2895. // phonebook location rather than the new NT5 location, which for
  2896. // scripts, is what we want.
  2897. //
  2898. GetPhonebookDirectory( PBM_Alternate, szDir );
  2899. ZeroMemory( &ofn, sizeof(ofn) );
  2900. ofn.lStructSize = sizeof(ofn);
  2901. ofn.hwndOwner = GetParent( pSuInfo->hwndLbScripts );
  2902. ofn.hInstance = g_hinstDll;
  2903. ofn.lpstrFilter = szFilter;
  2904. ofn.nFilterIndex = 1;
  2905. ofn.lpstrFile = szBuf;
  2906. ofn.nMaxFile = MAX_PATH;
  2907. ofn.lpstrInitialDir = szDir;
  2908. ofn.lpstrTitle = pszTitle;
  2909. ofn.lpstrDefExt = pszDefExt;
  2910. ofn.Flags = OFN_HIDEREADONLY;
  2911. if (GetOpenFileName (&ofn))
  2912. {
  2913. SetWindowText( pSuInfo->hwndLbScripts, ofn.lpstrFile );
  2914. }
  2915. Free0( pszTitle );
  2916. Free0( pszDefExt );
  2917. return TRUE;
  2918. }
  2919. BOOL
  2920. SuEditPbHandler(
  2921. IN SUINFO* pSuInfo,
  2922. IN WORD wNotification )
  2923. // Handle the WM_COMMAND notification to the "edit" button control.
  2924. // 'PSuInfo' is the script utility context. 'WNotification' is the wparam
  2925. // of the WM_COMMAND notification.
  2926. //
  2927. // 'PSuInfo' is the script utility context.
  2928. //
  2929. {
  2930. TCHAR* psz;
  2931. if (wNotification != BN_CLICKED)
  2932. {
  2933. return FALSE;
  2934. }
  2935. psz = GetText( pSuInfo->hwndLbScripts );
  2936. if (psz)
  2937. {
  2938. HWND hwndDlg = GetParent( pSuInfo->hwndPbEdit );
  2939. if (FFileExists( psz ))
  2940. {
  2941. SuEditScpScript( hwndDlg, psz );
  2942. }
  2943. else
  2944. {
  2945. SuEditSwitchInf( hwndDlg );
  2946. }
  2947. Free( psz );
  2948. }
  2949. return TRUE;
  2950. }
  2951. VOID
  2952. SuEditScpScript(
  2953. IN HWND hwndOwner,
  2954. IN TCHAR* pszScript )
  2955. // Starts notepad.exe on the 'pszScript' script path. 'HwndOwner' is the
  2956. // window to center any error popup on.
  2957. //
  2958. {
  2959. TCHAR szCmd[ (MAX_PATH * 2) + 50 + 1 ];
  2960. STARTUPINFO si;
  2961. PROCESS_INFORMATION pi;
  2962. BOOL f;
  2963. wsprintf( szCmd, TEXT("notepad.exe %s"), pszScript );
  2964. ZeroMemory( &si, sizeof(si) );
  2965. si.cb = sizeof(si);
  2966. TRACEW1( "SuEditScp-cmd=%s", szCmd );
  2967. f = CreateProcess(
  2968. NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
  2969. if (f)
  2970. {
  2971. CloseHandle( pi.hThread );
  2972. CloseHandle( pi.hProcess );
  2973. }
  2974. else
  2975. {
  2976. ErrorDlg( hwndOwner, SID_OP_LoadSwitchEditor, GetLastError(), NULL );
  2977. }
  2978. }
  2979. VOID
  2980. SuEditSwitchInf(
  2981. IN HWND hwndOwner )
  2982. // Starts notepad.exe on the system script file, switch.inf. 'HwndOwner'
  2983. // is the window to center any error popup on.
  2984. //
  2985. {
  2986. TCHAR szCmd[ (MAX_PATH * 2) + 50 + 1 ];
  2987. TCHAR szSysDir[ MAX_PATH + 1 ];
  2988. STARTUPINFO si;
  2989. PROCESS_INFORMATION pi;
  2990. BOOL f;
  2991. szSysDir[ 0 ] = TEXT('\0');
  2992. g_pGetSystemDirectory( NULL, szSysDir, MAX_PATH );
  2993. wsprintf( szCmd, TEXT("notepad.exe %s\\ras\\switch.inf"), szSysDir );
  2994. ZeroMemory( &si, sizeof(si) );
  2995. si.cb = sizeof(si);
  2996. TRACEW1( "SuEditInf-cmd=%s", szCmd );
  2997. f = CreateProcess(
  2998. NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
  2999. if (f)
  3000. {
  3001. CloseHandle( pi.hThread );
  3002. CloseHandle( pi.hProcess );
  3003. }
  3004. else
  3005. {
  3006. ErrorDlg( hwndOwner, SID_OP_LoadSwitchEditor, GetLastError(), NULL );
  3007. }
  3008. }
  3009. VOID
  3010. SuFillDoubleScriptsList(
  3011. IN SUINFO* pSuInfo )
  3012. // Fill scripts list in context 'pSuInfo' with switch.inf entries and .SCP
  3013. // file entries. The old list, if any, is freed. Select the script
  3014. // selection in the context or "(none)" if none. If the name is non-NULL
  3015. // but not found in the list it is appended. Caller must eventually call
  3016. // DtlDestroyList on the returned list.
  3017. //
  3018. {
  3019. DWORD dwErr;
  3020. DTLNODE* pNode;
  3021. INT nIndex;
  3022. DTLLIST* pList;
  3023. DTLLIST* pListScp;
  3024. TRACE( "SuFillDoubleScriptsList" );
  3025. ComboBox_ResetContent( pSuInfo->hwndLbScripts );
  3026. ComboBox_AddItemFromId(
  3027. g_hinstDll, pSuInfo->hwndLbScripts, SID_NoneSelected, NULL );
  3028. ComboBox_SetCurSel( pSuInfo->hwndLbScripts, 0 );
  3029. pList = NULL;
  3030. dwErr = LoadScriptsList( pSuInfo->hConnection, &pList );
  3031. if (dwErr != 0)
  3032. {
  3033. ErrorDlg( GetParent( pSuInfo->hwndLbScripts ),
  3034. SID_OP_LoadScriptInfo, dwErr, NULL );
  3035. return;
  3036. }
  3037. pListScp = NULL;
  3038. dwErr = SuLoadScpScriptsList( &pListScp );
  3039. if (dwErr == 0)
  3040. {
  3041. while (pNode = DtlGetFirstNode( pListScp ))
  3042. {
  3043. DtlRemoveNode( pListScp, pNode );
  3044. DtlAddNodeLast( pList, pNode );
  3045. }
  3046. DtlDestroyList( pListScp, NULL );
  3047. }
  3048. DtlDestroyList( pSuInfo->pList, DestroyPszNode );
  3049. pSuInfo->pList = pList;
  3050. for (pNode = DtlGetFirstNode( pList );
  3051. pNode;
  3052. pNode = DtlGetNextNode( pNode ))
  3053. {
  3054. TCHAR* psz;
  3055. psz = (TCHAR* )DtlGetData( pNode );
  3056. nIndex = ComboBox_AddString( pSuInfo->hwndLbScripts, psz );
  3057. if (pSuInfo->pszSelection
  3058. && lstrcmp( psz, pSuInfo->pszSelection ) == 0)
  3059. {
  3060. ComboBox_SetCurSel( pSuInfo->hwndLbScripts, nIndex );
  3061. }
  3062. }
  3063. if (pSuInfo->pszSelection
  3064. && ComboBox_GetCurSel( pSuInfo->hwndLbScripts ) <= 0
  3065. && lstrcmp( pSuInfo->pszSelection,
  3066. PszLoadString( g_hinstDll, SID_NoneSelected ) ) != 0)
  3067. {
  3068. nIndex = ComboBox_AddString(
  3069. pSuInfo->hwndLbScripts, pSuInfo->pszSelection );
  3070. if (nIndex >= 0)
  3071. {
  3072. ComboBox_SetCurSel( pSuInfo->hwndLbScripts, nIndex );
  3073. }
  3074. }
  3075. ComboBox_AutoSizeDroppedWidth( pSuInfo->hwndLbScripts );
  3076. }
  3077. #if 0
  3078. VOID
  3079. SuFillScriptsList(
  3080. IN EINFO* pEinfo,
  3081. IN HWND hwndLbScripts,
  3082. IN TCHAR* pszSelection )
  3083. // Fill scripts list in working entry of common entry context 'pEinfo'.
  3084. // The old list, if any, is freed. Select the script from user's entry.
  3085. // 'HwndLbScripts' is the script dropdown. 'PszSelection' is the selected
  3086. // name from the phonebook or NULL for "(none)". If the name is non-NULL
  3087. // but not found in the list it is appended.
  3088. //
  3089. {
  3090. DWORD dwErr;
  3091. DTLNODE* pNode;
  3092. INT nIndex;
  3093. DTLLIST* pList;
  3094. TRACE( "SuFillScriptsList" );
  3095. ComboBox_ResetContent( hwndLbScripts );
  3096. ComboBox_AddItemFromId(
  3097. g_hinstDll, hwndLbScripts, SID_NoneSelected, NULL );
  3098. ComboBox_SetCurSel( hwndLbScripts, 0 );
  3099. pList = NULL;
  3100. dwErr = LoadScriptsList( &pList );
  3101. if (dwErr != 0)
  3102. {
  3103. ErrorDlg( GetParent( hwndLbScripts ),
  3104. SID_OP_LoadScriptInfo, dwErr, NULL );
  3105. return;
  3106. }
  3107. DtlDestroyList( pEinfo->pListScripts, DestroyPszNode );
  3108. pEinfo->pListScripts = pList;
  3109. for (pNode = DtlGetFirstNode( pEinfo->pListScripts );
  3110. pNode;
  3111. pNode = DtlGetNextNode( pNode ))
  3112. {
  3113. TCHAR* psz;
  3114. psz = (TCHAR* )DtlGetData( pNode );
  3115. nIndex = ComboBox_AddString( hwndLbScripts, psz );
  3116. if (pszSelection && lstrcmp( psz, pszSelection ) == 0)
  3117. {
  3118. ComboBox_SetCurSel( hwndLbScripts, nIndex );
  3119. }
  3120. }
  3121. if (pszSelection && ComboBox_GetCurSel( hwndLbScripts ) <= 0)
  3122. {
  3123. nIndex = ComboBox_AddString( hwndLbScripts, pszSelection );
  3124. if (nIndex >= 0)
  3125. {
  3126. ComboBox_SetCurSel( hwndLbScripts, nIndex );
  3127. }
  3128. }
  3129. ComboBox_AutoSizeDroppedWidth( hwndLbScripts );
  3130. }
  3131. #endif
  3132. VOID
  3133. SuFree(
  3134. IN SUINFO* pSuInfo )
  3135. // Free resources attached to the 'pSuInfo' context.
  3136. //
  3137. {
  3138. if (pSuInfo->pList)
  3139. {
  3140. DtlDestroyList( pSuInfo->pList, DestroyPszNode );
  3141. pSuInfo->pList = NULL;
  3142. }
  3143. Free0( pSuInfo->pszSelection );
  3144. }
  3145. VOID
  3146. SuGetInfo(
  3147. IN SUINFO* pSuInfo,
  3148. OUT BOOL* pfScript,
  3149. OUT BOOL* pfTerminal,
  3150. OUT TCHAR** ppszScript )
  3151. // Load the scripting information from the controls into caller's output
  3152. // arguments. 'PSuInfo' is the complex phone number context.
  3153. //
  3154. {
  3155. // Whistler 308135 Dialup Scripting: Pre-Dial scripts can be selected but
  3156. // are not executed
  3157. //
  3158. if (pSuInfo->hwndCbTerminal && !(pSuInfo->dwFlags & SU_F_DisableTerminal))
  3159. {
  3160. if (pfTerminal)
  3161. {
  3162. *pfTerminal = Button_GetCheck( pSuInfo->hwndCbTerminal );
  3163. }
  3164. }
  3165. else
  3166. {
  3167. if (pfTerminal)
  3168. {
  3169. *pfTerminal = FALSE;
  3170. }
  3171. }
  3172. if (pSuInfo->dwFlags & SU_F_DisableScripting)
  3173. {
  3174. if (pfScript)
  3175. {
  3176. *pfScript = FALSE;
  3177. }
  3178. if (ppszScript)
  3179. {
  3180. *ppszScript = NULL;
  3181. }
  3182. }
  3183. else
  3184. {
  3185. if (pfScript)
  3186. {
  3187. *pfScript = Button_GetCheck( pSuInfo->hwndCbRunScript );
  3188. }
  3189. if (ppszScript)
  3190. {
  3191. *ppszScript = GetText( pSuInfo->hwndLbScripts );
  3192. }
  3193. }
  3194. // Silently fix up "no script selected" error.
  3195. //
  3196. if (pfScript && *pfScript)
  3197. {
  3198. TCHAR* pszNone;
  3199. pszNone = PszFromId( g_hinstDll, SID_NoneSelected );
  3200. if (!ppszScript || !*ppszScript
  3201. || !pszNone || lstrcmp( pszNone, *ppszScript ) == 0)
  3202. {
  3203. *pfScript = FALSE;
  3204. }
  3205. Free0( pszNone );
  3206. }
  3207. }
  3208. VOID
  3209. SuInit(
  3210. IN SUINFO* pSuInfo,
  3211. IN HWND hwndCbRunScript,
  3212. IN HWND hwndCbTerminal,
  3213. IN HWND hwndLbScripts,
  3214. IN HWND hwndPbEdit,
  3215. IN HWND hwndPbBrowse,
  3216. IN DWORD dwFlags)
  3217. // Initialize the scripting context 'pSuInfo'. The window handles are the
  3218. // controls to be managed. 'PSuInfo' is the script utility context.
  3219. //
  3220. {
  3221. pSuInfo->hwndCbRunScript = hwndCbRunScript;
  3222. pSuInfo->hwndCbTerminal = hwndCbTerminal;
  3223. pSuInfo->hwndLbScripts = hwndLbScripts;
  3224. pSuInfo->hwndPbEdit = hwndPbEdit;
  3225. pSuInfo->hwndPbBrowse = hwndPbBrowse;
  3226. pSuInfo->dwFlags = dwFlags;
  3227. if (pSuInfo->dwFlags & SU_F_DisableTerminal)
  3228. {
  3229. Button_SetCheck(pSuInfo->hwndCbTerminal, FALSE);
  3230. EnableWindow(pSuInfo->hwndCbTerminal, FALSE);
  3231. }
  3232. if (pSuInfo->dwFlags & SU_F_DisableScripting)
  3233. {
  3234. Button_SetCheck(pSuInfo->hwndCbRunScript, FALSE);
  3235. EnableWindow(pSuInfo->hwndCbRunScript, FALSE);
  3236. EnableWindow(pSuInfo->hwndLbScripts, FALSE);
  3237. EnableWindow(pSuInfo->hwndPbEdit, FALSE);
  3238. EnableWindow(pSuInfo->hwndPbBrowse, FALSE);
  3239. }
  3240. pSuInfo->pList = NULL;
  3241. pSuInfo->pszSelection = NULL;
  3242. }
  3243. DWORD
  3244. SuLoadScpScriptsList(
  3245. OUT DTLLIST** ppList )
  3246. // Loads '*ppList' with a list of Psz nodes containing the pathnames of
  3247. // the .SCP files in the RAS directory. It is caller's responsibility to
  3248. // call DtlDestroyList on the returned list.
  3249. //
  3250. // Returns 0 if successful or an error code.
  3251. //
  3252. {
  3253. UINT cch;
  3254. TCHAR szPath[ MAX_PATH ];
  3255. TCHAR* pszFile;
  3256. WIN32_FIND_DATA data;
  3257. HANDLE h;
  3258. DTLLIST* pList;
  3259. cch = g_pGetSystemDirectory( NULL, szPath, MAX_PATH );
  3260. if (cch == 0)
  3261. {
  3262. return GetLastError();
  3263. }
  3264. pList = DtlCreateList( 0L );
  3265. if (!pList)
  3266. {
  3267. return ERROR_NOT_ENOUGH_MEMORY;
  3268. }
  3269. lstrcat( szPath, TEXT("\\ras\\*.scp") );
  3270. h = FindFirstFile( szPath, &data );
  3271. if (h != INVALID_HANDLE_VALUE)
  3272. {
  3273. // Find the address of the file name part of the path since the 'data'
  3274. // provides only the filename and not the rest of the path.
  3275. //
  3276. pszFile = szPath + lstrlen( szPath ) - 5;
  3277. do
  3278. {
  3279. DTLNODE* pNode;
  3280. // Ignore any directories that happen to match.
  3281. //
  3282. if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  3283. {
  3284. continue;
  3285. }
  3286. // Create a Psz node with the path to the found file and append it
  3287. // to the end of the list.
  3288. //
  3289. // Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
  3290. //
  3291. lstrcpyn(
  3292. pszFile,
  3293. data.cFileName,
  3294. MAX_PATH - lstrlen( szPath ) - 5 );
  3295. pNode = CreatePszNode( szPath );
  3296. if (!pNode)
  3297. {
  3298. continue;
  3299. }
  3300. DtlAddNodeLast( pList, pNode );
  3301. }
  3302. while (FindNextFile( h, &data ));
  3303. FindClose( h );
  3304. }
  3305. *ppList = pList;
  3306. return 0;
  3307. }
  3308. BOOL
  3309. SuScriptsCbHandler(
  3310. IN SUINFO* pSuInfo,
  3311. IN WORD wNotification )
  3312. // Handle the WM_COMMAND notification to the "run scripts" checkbox
  3313. // control. 'PSuInfo' is the script utility context. 'WNotification' is
  3314. // the wparam of the WM_COMMAND notification.
  3315. //
  3316. {
  3317. if (wNotification != BN_CLICKED)
  3318. {
  3319. return FALSE;
  3320. }
  3321. SuUpdateScriptControls( pSuInfo );
  3322. return TRUE;
  3323. }
  3324. VOID
  3325. SuSetInfo(
  3326. IN SUINFO* pSuInfo,
  3327. IN BOOL fScript,
  3328. IN BOOL fTerminal,
  3329. IN TCHAR* pszScript )
  3330. // Set the controls for context 'pSuInfo' to the argument values.
  3331. //
  3332. {
  3333. Free0( pSuInfo->pszSelection );
  3334. pSuInfo->pszSelection = StrDup( pszScript );
  3335. if (pSuInfo->hwndCbTerminal && !(pSuInfo->dwFlags & SU_F_DisableTerminal))
  3336. {
  3337. Button_SetCheck( pSuInfo->hwndCbTerminal, fTerminal );
  3338. }
  3339. if (!(pSuInfo->dwFlags & SU_F_DisableScripting))
  3340. {
  3341. Button_SetCheck( pSuInfo->hwndCbRunScript, fScript );
  3342. }
  3343. SuFillDoubleScriptsList( pSuInfo );
  3344. SuUpdateScriptControls( pSuInfo );
  3345. }
  3346. VOID
  3347. SuUpdateScriptControls(
  3348. IN SUINFO* pSuInfo )
  3349. // Update the enable/disable state of the script controls based on the
  3350. // "run script" check box setting. 'PSuInfo' is the script utility
  3351. // context.
  3352. //
  3353. {
  3354. BOOL fCheck;
  3355. fCheck = Button_GetCheck( pSuInfo->hwndCbRunScript );
  3356. if (fCheck)
  3357. {
  3358. if (!pSuInfo->pList)
  3359. {
  3360. // Fill the script list with both SWITCH.INF and .SCP scripts.
  3361. //
  3362. SuFillDoubleScriptsList( pSuInfo );
  3363. }
  3364. }
  3365. else
  3366. {
  3367. // Clear the list contents in addition to disabling, per spec. The
  3368. // current selection is saved off so if user re-checks the box his
  3369. // last selection will show.
  3370. //
  3371. Free0( pSuInfo->pszSelection );
  3372. pSuInfo->pszSelection = GetText( pSuInfo->hwndLbScripts );
  3373. ComboBox_ResetContent( pSuInfo->hwndLbScripts );
  3374. DtlDestroyList( pSuInfo->pList, DestroyPszNode );
  3375. pSuInfo->pList = NULL;
  3376. }
  3377. EnableWindow( pSuInfo->hwndLbScripts, fCheck );
  3378. EnableWindow( pSuInfo->hwndPbEdit, fCheck );
  3379. EnableWindow( pSuInfo->hwndPbBrowse, fCheck );
  3380. }