Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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