Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1349 lines
34 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: connobj.cpp
  7. //
  8. // Contents: ConnectionObject Implementation
  9. //
  10. // Classes: CCConnectObj
  11. //
  12. // Notes: Purpose is to globally keep track of Connections
  13. // for a SyncMgr instance. and Open and Close Connections
  14. // abstracted from LAN or RAS.
  15. //
  16. // History: 10-Feb-98 rogerg Created.
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "precomp.h"
  20. extern HINSTANCE g_hInst; // current instance
  21. CConnectionObj *g_pConnectionObj = NULL; // global pointer to ConnectionObject.
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: InitConnectionObjects, public
  25. //
  26. // Synopsis: Must be called to initialize the ConnectionObjects
  27. // before any other functions are called.
  28. //
  29. // Arguments:
  30. //
  31. // Returns:
  32. //
  33. // Modifies:
  34. //
  35. // History: 05-Feb-98 rogerg Created.
  36. //
  37. //----------------------------------------------------------------------------
  38. HRESULT InitConnectionObjects()
  39. {
  40. g_pConnectionObj = new CConnectionObj;
  41. return g_pConnectionObj ? NOERROR : S_FALSE;
  42. }
  43. //+---------------------------------------------------------------------------
  44. //
  45. // Member: ReleaseConnectionObjects, public
  46. //
  47. // Synopsis: Called to Release the Connection Objects
  48. //
  49. // Arguments:
  50. //
  51. // Returns:
  52. //
  53. // Modifies:
  54. //
  55. // History: 05-Feb-98 rogerg Created.
  56. //
  57. //----------------------------------------------------------------------------
  58. HRESULT ReleaseConnectionObjects()
  59. {
  60. if (g_pConnectionObj)
  61. {
  62. delete g_pConnectionObj;
  63. g_pConnectionObj = NULL;
  64. }
  65. return NOERROR;
  66. }
  67. //+---------------------------------------------------------------------------
  68. //
  69. // Member: CConnectionObj::CConnectionObj, public
  70. //
  71. // Synopsis: Constructor
  72. //
  73. // Arguments:
  74. //
  75. // Returns:
  76. //
  77. // Modifies:
  78. //
  79. // History: 05-Feb-98 rogerg Created.
  80. //
  81. //----------------------------------------------------------------------------
  82. CConnectionObj::CConnectionObj()
  83. : m_pFirstConnectionObj(NULL),
  84. m_fAutoDialConn(FALSE),
  85. m_fForcedOnline(FALSE)
  86. {
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // Function: CConnectionObj::FindConnectionObj, public
  91. //
  92. // Synopsis: Sees if there is an existing Connection object for this
  93. // Item and if there is incremements the refcount. If one
  94. // isn't found and fCreate is true a new one is allocated
  95. // and added to the list.
  96. //
  97. // Arguments: [pszConnectionName] - Name of the Connection.
  98. // [fCreate] - Create a New Connection if one doesn't already exist
  99. /// [pConnectionOb] - OutParam pointer to newly created connectionObj
  100. //
  101. // Returns: Appropriate status code
  102. //
  103. // Modifies:
  104. //
  105. // History: 05-Nov-97 rogerg Created.
  106. //
  107. //----------------------------------------------------------------------------
  108. HRESULT CConnectionObj::FindConnectionObj(LPCWSTR pszConnectionName,
  109. BOOL fCreate,CONNECTIONOBJ **pConnectionObj)
  110. {
  111. HRESULT hr = S_FALSE;
  112. CONNECTIONOBJ *pCurConnectionObj;
  113. BOOL fFoundMatch = FALSE;
  114. CLock clockqueue(this);
  115. TCHAR szBuf[MAX_PATH + 1];
  116. *pConnectionObj = NULL;
  117. Assert(pszConnectionName);
  118. clockqueue.Enter();
  119. // look for an existing match
  120. pCurConnectionObj = m_pFirstConnectionObj;
  121. while (pCurConnectionObj)
  122. {
  123. if (0 == lstrcmp(pszConnectionName,pCurConnectionObj->pwszConnectionName))
  124. {
  125. fFoundMatch = TRUE;
  126. break;
  127. }
  128. pCurConnectionObj = pCurConnectionObj->pNextConnectionObj;
  129. }
  130. if (fFoundMatch)
  131. {
  132. ++(pCurConnectionObj->cRefs);
  133. *pConnectionObj = pCurConnectionObj;
  134. hr = NOERROR;
  135. }
  136. else if (fCreate)
  137. {
  138. CONNECTIONOBJ *pNewConnectionObj;
  139. // if we need to create a new connectionObj then
  140. pNewConnectionObj = (CONNECTIONOBJ *) ALLOC(sizeof(CONNECTIONOBJ));
  141. if (pNewConnectionObj)
  142. {
  143. memset(pNewConnectionObj,0,sizeof(CONNECTIONOBJ));
  144. pNewConnectionObj->cRefs = 1;
  145. Assert(pszConnectionName);
  146. // setup the Connectoin Name
  147. if (pszConnectionName)
  148. {
  149. DWORD cch = lstrlen(pszConnectionName);
  150. DWORD cbAlloc = (cch + 1)*ARRAY_ELEMENT_SIZE(pNewConnectionObj->pwszConnectionName);
  151. pNewConnectionObj->pwszConnectionName = (LPWSTR) ALLOC(cbAlloc);
  152. if (pNewConnectionObj->pwszConnectionName)
  153. {
  154. lstrcpy(pNewConnectionObj->pwszConnectionName,pszConnectionName);
  155. }
  156. }
  157. // for now if the name of the connection is our
  158. // LAN connection name then set the ConnectionType to LAN,
  159. // else set it to WAN. if convert to using hte connection
  160. // manager should get from that.
  161. LoadString(g_hInst, IDS_LAN_CONNECTION, szBuf, MAX_PATH);
  162. if (NULL == pszConnectionName || 0 == lstrcmp(szBuf,pszConnectionName))
  163. {
  164. pNewConnectionObj->dwConnectionType = CNETAPI_CONNECTIONTYPELAN;
  165. }
  166. else
  167. {
  168. pNewConnectionObj->dwConnectionType = CNETAPI_CONNECTIONTYPEWAN;
  169. }
  170. }
  171. // if everything went okay, add it to the list.
  172. // must have a new connection obj and either not connection name
  173. // was passed in or we successfully added a connection name.
  174. if (pNewConnectionObj && (NULL == pszConnectionName
  175. || pNewConnectionObj->pwszConnectionName) )
  176. {
  177. // put at beginning of list
  178. pNewConnectionObj->pNextConnectionObj = m_pFirstConnectionObj;
  179. m_pFirstConnectionObj = pNewConnectionObj;
  180. *pConnectionObj = pNewConnectionObj;
  181. hr = NOERROR;
  182. }
  183. else
  184. {
  185. if (pNewConnectionObj)
  186. {
  187. FreeConnectionObj(pNewConnectionObj);
  188. }
  189. }
  190. }
  191. clockqueue.Leave();
  192. return hr;
  193. }
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Function: CConnectionObj::RemoveConnectionObj, public
  197. //
  198. // Synopsis: Removes the specified connections from the list.
  199. //
  200. // Arguments: [pszConnectionName] - Name of the Connection.
  201. //
  202. // Returns: Appropriate status code
  203. //
  204. // Modifies:
  205. //
  206. // History: 05-Nov-97 rogerg Created.
  207. //
  208. //----------------------------------------------------------------------------
  209. void CConnectionObj::RemoveConnectionObj(CONNECTIONOBJ *pConnectionObj)
  210. {
  211. CONNECTIONOBJ *pCurConnection = m_pFirstConnectionObj;
  212. ASSERT_LOCKHELD(this);
  213. // remove from the list
  214. if (m_pFirstConnectionObj == pConnectionObj)
  215. {
  216. m_pFirstConnectionObj = pConnectionObj->pNextConnectionObj;
  217. }
  218. else
  219. {
  220. while (pCurConnection)
  221. {
  222. if (pCurConnection->pNextConnectionObj == pConnectionObj)
  223. {
  224. pCurConnection->pNextConnectionObj = pConnectionObj->pNextConnectionObj;
  225. break;
  226. }
  227. pCurConnection = pCurConnection->pNextConnectionObj;
  228. }
  229. }
  230. FreeConnectionObj(pConnectionObj);
  231. }
  232. //+---------------------------------------------------------------------------
  233. //
  234. // Function: CConnectionObj::FreeConnectionObj, privte
  235. //
  236. // Synopsis: frees the memory associate with a conneciton Object.
  237. //
  238. // Arguments:
  239. //
  240. // Returns: nada
  241. //
  242. // Modifies:
  243. //
  244. // History: 05-Nov-97 rogerg Created.
  245. //
  246. //----------------------------------------------------------------------------
  247. void CConnectionObj::FreeConnectionObj(CONNECTIONOBJ *pConnectionObj)
  248. {
  249. Assert(pConnectionObj);
  250. if (pConnectionObj)
  251. {
  252. if (pConnectionObj->pwszConnectionName)
  253. {
  254. FREE(pConnectionObj->pwszConnectionName);
  255. }
  256. FREE(pConnectionObj);
  257. }
  258. }
  259. //+---------------------------------------------------------------------------
  260. //
  261. // Member: CConnectionObj::IsConnectionAvailable, public
  262. //
  263. // Synopsis: Given a connection name sees if the connection is open
  264. //
  265. // Arguments:
  266. //
  267. // Returns: S_OK - Connection Open
  268. // S_FALSE - Connection not Open
  269. //
  270. // Modifies:
  271. //
  272. // History: 05-Feb-98 rogerg Created.
  273. //
  274. //----------------------------------------------------------------------------
  275. HRESULT CConnectionObj::IsConnectionAvailable(LPCWSTR pszConnectionName)
  276. {
  277. TCHAR szBuf[MAX_PATH + 1];
  278. DWORD dwConnectionType;
  279. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  280. HRESULT hr = S_FALSE;
  281. if (NULL != pNetApi )
  282. {
  283. BOOL fConnected,fCanEstablishConnection;
  284. // for now if the name of the connection is our
  285. // LAN connection name then set the ConnectionType to LAN,
  286. // else set it to WAN. if convert to Connection Manager
  287. // should get type from those interfaces.
  288. LoadString(g_hInst, IDS_LAN_CONNECTION, szBuf, MAX_PATH);
  289. if (NULL == pszConnectionName || 0 == lstrcmp(szBuf,pszConnectionName))
  290. {
  291. dwConnectionType = CNETAPI_CONNECTIONTYPELAN;
  292. }
  293. else
  294. {
  295. dwConnectionType = CNETAPI_CONNECTIONTYPEWAN;
  296. }
  297. pNetApi->GetConnectionStatus(pszConnectionName,dwConnectionType,
  298. &fConnected,&fCanEstablishConnection);
  299. pNetApi->Release();
  300. hr = (fConnected) ? S_OK: S_FALSE;
  301. }
  302. return hr;
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Member: CConnectionObj::RestoreWorkOffline, private
  307. //
  308. // Synopsis: If have force an online because of a dial then
  309. // set system state back to Work Offline.
  310. //
  311. // Arguments:
  312. //
  313. // Returns:
  314. //
  315. // Modifies:
  316. //
  317. // History: 05-Apr-99 rogerg Created.
  318. //
  319. //----------------------------------------------------------------------------
  320. void CConnectionObj::RestoreWorkOffline(LPNETAPI pNetApi)
  321. {
  322. if (!pNetApi)
  323. {
  324. Assert(pNetApi);
  325. return;
  326. }
  327. if (m_fForcedOnline)
  328. {
  329. pNetApi->SetOffline(TRUE);
  330. m_fForcedOnline = FALSE;
  331. }
  332. }
  333. //+---------------------------------------------------------------------------
  334. //
  335. // Member: CConnectionObj::TurnOffWorkOffline, private
  336. //
  337. // Synopsis: If System is in WorkOffline state will force
  338. // back to online.
  339. //
  340. // Arguments:
  341. //
  342. // Returns:
  343. //
  344. // Modifies:
  345. //
  346. // History: 05-Apr-99 rogerg Created.
  347. //
  348. //----------------------------------------------------------------------------
  349. void CConnectionObj::TurnOffWorkOffline(LPNETAPI pNetApi)
  350. {
  351. if (!pNetApi)
  352. {
  353. Assert(pNetApi);
  354. return;
  355. }
  356. if (pNetApi->IsGlobalOffline())
  357. {
  358. // if in offline state go ahead and switch to online
  359. if (pNetApi->SetOffline(FALSE))
  360. {
  361. m_fForcedOnline = TRUE;
  362. }
  363. }
  364. }
  365. //+---------------------------------------------------------------------------
  366. //
  367. // Member: CConnectionObj::OpenConnection, public
  368. //
  369. // Synopsis: Given a connection sees if the connection is open
  370. // and if it not and the fMakeConnection is true
  371. // will then attempt to open the connection.
  372. //
  373. // Arguments:
  374. //
  375. // Returns:
  376. //
  377. // Modifies:
  378. //
  379. // History: 05-Feb-98 rogerg Created.
  380. //
  381. //----------------------------------------------------------------------------
  382. HRESULT CConnectionObj::OpenConnection(CONNECTIONOBJ *pConnectionObj,BOOL fMakeConnection,CBaseDlg *pDlg)
  383. {
  384. #ifndef _RASDIAL
  385. DWORD dwConnectionId;
  386. #else
  387. HRASCONN hRasConn;
  388. #endif // _RASDIAL
  389. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  390. BOOL fConnected = FALSE;
  391. BOOL fCanEstablishConnection = FALSE;
  392. if (NULL != pNetApi )
  393. {
  394. // See if the specified connection is active and if there is any
  395. // Wan Activity.
  396. Assert(pConnectionObj->dwConnectionType); // should have a connection type setup by now.
  397. if (NOERROR == pNetApi->GetConnectionStatus(pConnectionObj->pwszConnectionName,
  398. pConnectionObj->dwConnectionType,
  399. &fConnected,
  400. &fCanEstablishConnection))
  401. {
  402. // if there is no Wan Activity and there is not a connection
  403. // then we can go ahead try to dial
  404. if (!fConnected && fCanEstablishConnection
  405. && fMakeConnection && (pConnectionObj->pwszConnectionName))
  406. {
  407. DWORD dwErr;
  408. TurnOffWorkOffline(pNetApi);
  409. dwErr = pNetApi->InternetDialW(pDlg ? pDlg->GetHwnd() : NULL,
  410. pConnectionObj->pwszConnectionName,
  411. INTERNET_AUTODIAL_FORCE_ONLINE |INTERNET_AUTODIAL_FORCE_UNATTENDED,
  412. &dwConnectionId,0);
  413. if (0 == dwErr)
  414. {
  415. fConnected = TRUE;
  416. pConnectionObj->dwConnectionId = dwConnectionId;
  417. }
  418. else
  419. {
  420. dwConnectionId = 0;
  421. if (pDlg)
  422. {
  423. LogError(pNetApi,dwErr,pDlg);
  424. }
  425. }
  426. }
  427. }
  428. }
  429. if (pNetApi)
  430. pNetApi->Release();
  431. // review, don't handle all failure cases for Scheduling such as LAN connection
  432. // not available or not allowed to make connection on RAS.
  433. pConnectionObj->fConnectionOpen = fConnected;
  434. return pConnectionObj->fConnectionOpen ? NOERROR : S_FALSE;
  435. }
  436. //+---------------------------------------------------------------------------
  437. //
  438. // Member: CConnectionObj::AutoDial
  439. //
  440. // Synopsis: Dials the default auto dial connection
  441. //
  442. // History: 28-Jul-98 SitaramR Created
  443. //
  444. //----------------------------------------------------------------------------
  445. HRESULT CConnectionObj::AutoDial(DWORD dwFlags,CBaseDlg *pDlg)
  446. {
  447. HRESULT hr = NOERROR;
  448. DWORD dwErr = -1;
  449. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  450. // only allow one autodial at a time.
  451. if (m_fAutoDialConn)
  452. {
  453. return NOERROR;
  454. }
  455. if ( NULL == pNetApi )
  456. {
  457. hr = E_OUTOFMEMORY;
  458. }
  459. else
  460. {
  461. TurnOffWorkOffline(pNetApi);
  462. // if flags are force unattended then call InternetAutoDial
  463. // if should prompt user call InternetDial without
  464. // a connectoid to bringup choice
  465. if (dwFlags & INTERNET_AUTODIAL_FORCE_UNATTENDED)
  466. {
  467. BOOL fOk = pNetApi->InternetAutodial(dwFlags,0);
  468. if ( fOk )
  469. {
  470. m_fAutoDialConn = TRUE;
  471. m_dwAutoConnID = 0;
  472. dwErr = 0;
  473. }
  474. else
  475. {
  476. dwErr = GetLastError();
  477. }
  478. }
  479. else
  480. {
  481. DWORD dwConnectionId;
  482. dwErr = pNetApi->InternetDialW(pDlg ? pDlg->GetHwnd() : NULL,
  483. NULL,
  484. INTERNET_AUTODIAL_FORCE_ONLINE,
  485. &dwConnectionId,0);
  486. if (0 == dwErr)
  487. {
  488. m_fAutoDialConn = TRUE;
  489. m_dwAutoConnID = dwConnectionId;
  490. }
  491. }
  492. // if an error occured then log it.
  493. if (0 != dwErr)
  494. {
  495. if (pDlg)
  496. {
  497. LogError(pNetApi,dwErr,pDlg);
  498. }
  499. }
  500. hr = m_fAutoDialConn ? NOERROR : E_UNEXPECTED;
  501. }
  502. if ( pNetApi != NULL )
  503. {
  504. pNetApi->Release();
  505. }
  506. return hr;
  507. }
  508. //+---------------------------------------------------------------------------
  509. //
  510. // Member: CConnectionObj::AutoDial
  511. //
  512. // Synopsis: turns on or off work offline
  513. //
  514. // History: 14-April-99 rogerg Created
  515. //
  516. //----------------------------------------------------------------------------
  517. HRESULT CConnectionObj::SetWorkOffline(BOOL fWorkOffline)
  518. {
  519. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  520. if (NULL == pNetApi)
  521. {
  522. return E_OUTOFMEMORY;
  523. }
  524. if (fWorkOffline)
  525. {
  526. RestoreWorkOffline(pNetApi); // Note: only sets back to workOffline if we turned it off.
  527. }
  528. else
  529. {
  530. TurnOffWorkOffline(pNetApi);
  531. }
  532. pNetApi->Release();
  533. return NOERROR;
  534. }
  535. //+---------------------------------------------------------------------------
  536. //
  537. // Member: CConnectionObj::LogError, private
  538. //
  539. // Synopsis: Logs the dwErr to the dialog
  540. //
  541. // Arguments:
  542. //
  543. // Returns:
  544. //
  545. // Modifies:
  546. //
  547. // History: 08-Mar-99 rogerg Created.
  548. //
  549. //----------------------------------------------------------------------------
  550. void CConnectionObj::LogError(LPNETAPI pNetApi,DWORD dwErr,CBaseDlg *pDlg)
  551. {
  552. BOOL fErrorString= FALSE;
  553. WCHAR wszErrorString[RASERROR_MAXSTRING];
  554. DWORD dwErrorStringLen = sizeof(wszErrorString)/sizeof(WCHAR);
  555. MSGLogErrors msgLogError;
  556. // don't log if success or no dialog
  557. if (NULL == pDlg || 0 == dwErr)
  558. {
  559. Assert(0 != dwErr);
  560. Assert(NULL != pDlg);
  561. return;
  562. }
  563. // print out an error message if it falls within the range of RAS then
  564. // get the raserror, else if a Win32 message get that, if -1 means the dll
  565. // failed to load so use the unknown error.
  566. if (dwErr >= RASBASE && dwErr <= RASBASEEND)
  567. {
  568. if (NOERROR ==
  569. pNetApi->RasGetErrorStringProc(dwErr,wszErrorString,dwErrorStringLen) )
  570. {
  571. fErrorString = TRUE;
  572. }
  573. }
  574. else if (-1 != dwErr) // try formatMessage
  575. {
  576. if (FormatMessage(
  577. FORMAT_MESSAGE_FROM_SYSTEM,
  578. NULL,
  579. dwErr,
  580. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
  581. wszErrorString,
  582. dwErrorStringLen,
  583. NULL))
  584. {
  585. fErrorString = TRUE;
  586. }
  587. }
  588. if (FALSE == fErrorString)
  589. {
  590. // just use the generic error.
  591. if (LoadString(g_hInst, IDS_UNDEFINED_ERROR,wszErrorString,dwErrorStringLen))
  592. {
  593. fErrorString = TRUE;
  594. }
  595. }
  596. if (fErrorString)
  597. {
  598. msgLogError.mask = 0;
  599. msgLogError.dwErrorLevel = SYNCMGRLOGLEVEL_ERROR;
  600. msgLogError.lpcErrorText = wszErrorString;
  601. msgLogError.ErrorID = GUID_NULL;
  602. msgLogError.fHasErrorJumps = FALSE;
  603. pDlg->HandleLogError(NULL,0,&msgLogError);
  604. }
  605. }
  606. //+---------------------------------------------------------------------------
  607. //
  608. // Member: CConnectionObj::CloseConnection, public
  609. //
  610. // Synopsis: closes the specified connection.
  611. // Not an error if can't find Connection obj since under error
  612. // conditions we still want to call this to clean up, object
  613. // may or may not exist.
  614. //
  615. // Arguments:
  616. //
  617. // Returns:
  618. //
  619. // Modifies:
  620. //
  621. // History: 05-Feb-98 rogerg Created.
  622. //
  623. //----------------------------------------------------------------------------
  624. HRESULT CConnectionObj::CloseConnection(CONNECTIONOBJ *pConnectionObj)
  625. {
  626. CLock clockqueue(this);
  627. CONNECTIONOBJ FirstConnectObj;
  628. CONNECTIONOBJ *pCurConnection = &FirstConnectObj;
  629. clockqueue.Enter();
  630. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  631. pCurConnection->pNextConnectionObj = m_pFirstConnectionObj;
  632. while (pCurConnection->pNextConnectionObj)
  633. {
  634. CONNECTIONOBJ *pConnection = pCurConnection->pNextConnectionObj;
  635. // if the connection is equal to what was passed in, then
  636. // close it out.
  637. if (pConnection
  638. == pConnectionObj)
  639. {
  640. // If have a Completion Event to Set then
  641. if (pConnection->hCompletionEvent)
  642. {
  643. SetEvent(pConnection->hCompletionEvent);
  644. CloseHandle(pConnection->hCompletionEvent);
  645. pConnection->hCompletionEvent = NULL;
  646. }
  647. // if have an open ras connection, hang it up.
  648. // only time this should get connected is in the progress
  649. // TODO: make this a class that keeps the netapi loaded
  650. // until all connectoins have been closed.
  651. #ifndef _RASDIAL
  652. if (pConnection->dwConnectionId)
  653. {
  654. if ( NULL != pNetApi )
  655. {
  656. pNetApi->InternetHangUp(pConnection->dwConnectionId,0);
  657. pConnection->dwConnectionId = 0; // even if hangup fails set to null.
  658. }
  659. }
  660. #else
  661. if (pConnection->hRasConn)
  662. {
  663. if ( NULL != pNetApi )
  664. {
  665. pNetApi->RasHangup(pConnection->hRasConn);
  666. pConnection->hRasConn = NULL; // even if hangup fails set to null.
  667. }
  668. }
  669. #endif // _RASDIAL
  670. // if noone is holding onto this connection anymore get rid of it.
  671. if (0 == pConnection->cRefs)
  672. {
  673. pCurConnection->pNextConnectionObj
  674. = pConnection->pNextConnectionObj;
  675. FreeConnectionObj(pConnection);
  676. }
  677. else
  678. {
  679. pCurConnection = pCurConnection->pNextConnectionObj;
  680. }
  681. break;
  682. }
  683. else
  684. {
  685. pCurConnection = pCurConnection->pNextConnectionObj;
  686. }
  687. }
  688. m_pFirstConnectionObj = FirstConnectObj.pNextConnectionObj;
  689. if ( pNetApi != NULL )
  690. pNetApi->Release();
  691. clockqueue.Leave();
  692. return NOERROR;
  693. }
  694. //+---------------------------------------------------------------------------
  695. //
  696. // Member: CConnectionObj::CloseConnections, public
  697. //
  698. // Synopsis: Closes any open connections that have a refcount of zero.
  699. //
  700. // Arguments:
  701. //
  702. // Returns:
  703. //
  704. // Modifies:
  705. //
  706. // History: 05-Feb-98 rogerg Created.
  707. //
  708. //----------------------------------------------------------------------------
  709. HRESULT CConnectionObj::CloseConnections()
  710. {
  711. CLock clockqueue(this);
  712. CONNECTIONOBJ FirstConnectObj;
  713. CONNECTIONOBJ *pCurConnection = &FirstConnectObj;
  714. clockqueue.Enter();
  715. pCurConnection->pNextConnectionObj = m_pFirstConnectionObj;
  716. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  717. while (pCurConnection->pNextConnectionObj)
  718. {
  719. CONNECTIONOBJ *pConnection = pCurConnection->pNextConnectionObj;
  720. // If have a Completion Event to Set then
  721. if (pConnection->hCompletionEvent)
  722. {
  723. SetEvent(pConnection->hCompletionEvent);
  724. CloseHandle(pConnection->hCompletionEvent);
  725. pConnection->hCompletionEvent = NULL;
  726. }
  727. // if have an open ras connection, hang it up.
  728. // only time this should get connected is in the progress
  729. // TODO: make this a class that keeps the netapi loaded
  730. // until all connectoins have been closed.
  731. if (pConnection->dwConnectionId)
  732. {
  733. if ( NULL != pNetApi )
  734. {
  735. pNetApi->InternetHangUp(pConnection->dwConnectionId,0);
  736. pConnection->dwConnectionId = 0; // even if hangup fails set to null.
  737. }
  738. }
  739. // if noone is holding onto this connection anymore get rid of it.
  740. if (0 == pConnection->cRefs)
  741. {
  742. pCurConnection->pNextConnectionObj
  743. = pConnection->pNextConnectionObj;
  744. FreeConnectionObj(pConnection);
  745. }
  746. else
  747. {
  748. pCurConnection = pCurConnection->pNextConnectionObj;
  749. }
  750. }
  751. m_pFirstConnectionObj = FirstConnectObj.pNextConnectionObj;
  752. //
  753. // Check if auto dial connection needs to be turned off, ignore failure
  754. //
  755. if ( m_fAutoDialConn )
  756. {
  757. if ( NULL != pNetApi )
  758. {
  759. if (m_dwAutoConnID)
  760. {
  761. pNetApi->InternetHangUp(m_dwAutoConnID,0);
  762. }
  763. else
  764. {
  765. pNetApi->InternetAutodialHangup( 0 );
  766. }
  767. }
  768. m_dwAutoConnID = FALSE;
  769. m_fAutoDialConn = FALSE;
  770. }
  771. // if we turned off offline then turn it back on
  772. RestoreWorkOffline(pNetApi);
  773. if ( pNetApi != NULL )
  774. pNetApi->Release();
  775. clockqueue.Leave();
  776. return NOERROR;
  777. }
  778. //+---------------------------------------------------------------------------
  779. //
  780. // Function: CConnectionObj::ReleaseConnectionObj, public
  781. //
  782. // Synopsis: Decrements the specified connectionObj
  783. // If ther reference count goes to zero and there
  784. // is not an open connection we go ahead and
  785. // cleanup immediately.
  786. //
  787. // If there is a dialed connection we wait until
  788. // CloseConnection is explicitly called.
  789. //
  790. // Arguments: [pConnectionObj] - Pointer to the Connection Obj to Release.
  791. //
  792. // Returns: Appropriate status code
  793. //
  794. // Modifies:
  795. //
  796. // History: 05-Nov-97 rogerg Created.
  797. //
  798. //----------------------------------------------------------------------------
  799. DWORD CConnectionObj::ReleaseConnectionObj(CONNECTIONOBJ *pConnectionObj)
  800. {
  801. DWORD cRefs;
  802. BOOL fConnectionOpen = FALSE;
  803. CLock clockqueue(this);
  804. clockqueue.Enter();
  805. --pConnectionObj->cRefs;
  806. cRefs = pConnectionObj->cRefs;
  807. Assert( ((LONG) cRefs) >= 0);
  808. #ifndef _RASDIAL
  809. fConnectionOpen = pConnectionObj->dwConnectionId;
  810. #else
  811. fConnectionOpen = pConnectionObj->hRasConn;
  812. #endif // _RASDIAL
  813. if (0 == cRefs && !fConnectionOpen
  814. && NULL == pConnectionObj->hCompletionEvent)
  815. {
  816. RemoveConnectionObj(pConnectionObj);
  817. }
  818. clockqueue.Leave();
  819. return cRefs;
  820. }
  821. //+---------------------------------------------------------------------------
  822. //
  823. // Function: CConnectionObj::AddRefConnectionObj, public
  824. //
  825. // Synopsis: Puts an AddRef on the specified connection obj
  826. //
  827. // Arguments: [pConnectionObj] - Pointer to the Connection Obj to Release.
  828. //
  829. // Returns: Appropriate status code
  830. //
  831. // Modifies:
  832. //
  833. // History: 05-Nov-97 rogerg Created.
  834. //
  835. //----------------------------------------------------------------------------
  836. DWORD CConnectionObj::AddRefConnectionObj(CONNECTIONOBJ *pConnectionObj)
  837. {
  838. DWORD cRefs;
  839. cRefs = InterlockedIncrement( (LONG *) &(pConnectionObj->cRefs));
  840. return cRefs;
  841. }
  842. //+---------------------------------------------------------------------------
  843. //
  844. // Member: CConnectionObj::GetConnectionObjCompletionEvent, public
  845. //
  846. // Synopsis: caller has made a request for a completion event to be set up.
  847. // !!! warning, on success the event won't be signalled until CloseConnections is Called.
  848. //
  849. //
  850. // Arguments:
  851. //
  852. // Returns:
  853. //
  854. // Modifies:
  855. //
  856. // History: 05-Feb-98 rogerg Created.
  857. //
  858. //----------------------------------------------------------------------------
  859. HRESULT CConnectionObj::GetConnectionObjCompletionEvent(CONNECTIONOBJ *pConnectionObj,HANDLE *phRasPendingEvent)
  860. {
  861. HRESULT hr = E_UNEXPECTED;
  862. BOOL fFirstCreate = FALSE;
  863. CLock clockqueue(this);
  864. clockqueue.Enter();
  865. if (NULL == pConnectionObj->hCompletionEvent)
  866. {
  867. pConnectionObj->hCompletionEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  868. fFirstCreate = TRUE;
  869. }
  870. if (pConnectionObj->hCompletionEvent)
  871. {
  872. HANDLE hCurThread;
  873. HANDLE hProcess;
  874. // if have a handle, duplicate it hand it out.
  875. hCurThread = GetCurrentThread();
  876. hProcess = GetCurrentProcess();
  877. if (DuplicateHandle(hProcess,pConnectionObj->hCompletionEvent,hProcess,
  878. phRasPendingEvent,
  879. 0,FALSE,DUPLICATE_SAME_ACCESS) )
  880. {
  881. hr = NOERROR;
  882. }
  883. else
  884. {
  885. *phRasPendingEvent = NULL;
  886. // if event was just created, then also close this one
  887. if (fFirstCreate)
  888. {
  889. CloseHandle(pConnectionObj->hCompletionEvent);
  890. pConnectionObj->hCompletionEvent = NULL;
  891. }
  892. }
  893. }
  894. clockqueue.Leave();
  895. return hr;
  896. }
  897. //+---------------------------------------------------------------------------
  898. //
  899. // Function: ConnectObj_OpenConnection, public
  900. //
  901. // Synopsis: wrapper function
  902. //
  903. // Arguments:
  904. //
  905. // Returns:
  906. //
  907. // Modifies:
  908. //
  909. // History: 05-Feb-98 rogerg Created.
  910. //
  911. //----------------------------------------------------------------------------
  912. HRESULT ConnectObj_OpenConnection(CONNECTIONOBJ *pConnectionObj,BOOL fMakeConnection,CBaseDlg *pDlg)
  913. {
  914. Assert(g_pConnectionObj);
  915. if (NULL == g_pConnectionObj)
  916. return E_UNEXPECTED;
  917. return g_pConnectionObj->OpenConnection(pConnectionObj,fMakeConnection,pDlg);
  918. }
  919. //+---------------------------------------------------------------------------
  920. //
  921. // Function: ConnectObj_CloseConnections, public
  922. //
  923. // Synopsis: wrapper function
  924. //
  925. // Arguments:
  926. //
  927. // Returns:
  928. //
  929. // Modifies:
  930. //
  931. // History: 05-Feb-98 rogerg Created.
  932. //
  933. //----------------------------------------------------------------------------
  934. HRESULT ConnectObj_CloseConnections()
  935. {
  936. Assert(g_pConnectionObj);
  937. if (NULL == g_pConnectionObj)
  938. return E_UNEXPECTED;
  939. return g_pConnectionObj->CloseConnections();
  940. }
  941. //+---------------------------------------------------------------------------
  942. //
  943. // Function: ConnectObj_CloseConnection, public
  944. //
  945. // Synopsis: wrapper function
  946. //
  947. // Arguments:
  948. //
  949. // Returns:
  950. //
  951. // Modifies:
  952. //
  953. // History: 05-Feb-98 rogerg Created.
  954. //
  955. //----------------------------------------------------------------------------
  956. HRESULT ConnectObj_CloseConnection(CONNECTIONOBJ *pConnectionObj)
  957. {
  958. Assert(g_pConnectionObj);
  959. if (NULL == g_pConnectionObj)
  960. return E_UNEXPECTED;
  961. return g_pConnectionObj->CloseConnection(pConnectionObj);
  962. }
  963. //+---------------------------------------------------------------------------
  964. //
  965. // Function: ConnectObj_FindConnectionObj, public
  966. //
  967. // Synopsis: wrapper function
  968. //
  969. // Arguments:
  970. //
  971. // Returns:
  972. //
  973. // Modifies:
  974. //
  975. // History: 05-Feb-98 rogerg Created.
  976. //
  977. //----------------------------------------------------------------------------
  978. HRESULT ConnectObj_FindConnectionObj(LPCWSTR pszConnectionName,BOOL fCreate,CONNECTIONOBJ **pConnectionObj)
  979. {
  980. Assert(g_pConnectionObj);
  981. if (NULL == g_pConnectionObj)
  982. return E_UNEXPECTED;
  983. return g_pConnectionObj->FindConnectionObj(pszConnectionName,
  984. fCreate,pConnectionObj);
  985. }
  986. //+---------------------------------------------------------------------------
  987. //
  988. // Function: ConnectObj_AutoDial
  989. //
  990. // Synopsis: Wrapper function for auto dial
  991. //
  992. // History: 28-Jul-98 SitaramR Created
  993. //
  994. //----------------------------------------------------------------------------
  995. HRESULT ConnectObj_AutoDial(DWORD dwFlags,CBaseDlg *pDlg)
  996. {
  997. Assert(g_pConnectionObj);
  998. if (NULL == g_pConnectionObj)
  999. return E_UNEXPECTED;
  1000. return g_pConnectionObj->AutoDial(dwFlags,pDlg);
  1001. }
  1002. //+---------------------------------------------------------------------------
  1003. //
  1004. // Function: ConnectObj_ReleaseConnectionObj, public
  1005. //
  1006. // Synopsis: wrapper function
  1007. //
  1008. // Arguments:
  1009. //
  1010. // Returns:
  1011. //
  1012. // Modifies:
  1013. //
  1014. // History: 05-Feb-98 rogerg Created.
  1015. //
  1016. //----------------------------------------------------------------------------
  1017. DWORD ConnectObj_ReleaseConnectionObj(CONNECTIONOBJ *pConnectionObj)
  1018. {
  1019. Assert(g_pConnectionObj);
  1020. if (NULL == g_pConnectionObj)
  1021. return 0;
  1022. return g_pConnectionObj->ReleaseConnectionObj(pConnectionObj);
  1023. }
  1024. //+---------------------------------------------------------------------------
  1025. //
  1026. // Function: ConnectObj_AddRefConnectionObj, public
  1027. //
  1028. // Synopsis: wrapper function
  1029. //
  1030. // Arguments:
  1031. //
  1032. // Returns:
  1033. //
  1034. // Modifies:
  1035. //
  1036. // History: 05-Feb-98 rogerg Created.
  1037. //
  1038. //----------------------------------------------------------------------------
  1039. DWORD ConnectObj_AddRefConnectionObj(CONNECTIONOBJ *pConnectionObj)
  1040. {
  1041. Assert(g_pConnectionObj);
  1042. if (NULL == g_pConnectionObj)
  1043. return 0;
  1044. return g_pConnectionObj->AddRefConnectionObj(pConnectionObj);
  1045. }
  1046. //+---------------------------------------------------------------------------
  1047. //
  1048. // Function: ConnectObj_GetConnectionObjCompletionEvent, public
  1049. //
  1050. // Synopsis: wrapper function
  1051. //
  1052. // Arguments:
  1053. //
  1054. // Returns:
  1055. //
  1056. // Modifies:
  1057. //
  1058. // History: 05-Feb-98 rogerg Created.
  1059. //
  1060. //----------------------------------------------------------------------------
  1061. HRESULT ConnectObj_GetConnectionObjCompletionEvent(CONNECTIONOBJ *pConnectionObj,HANDLE *phRasPendingEvent)
  1062. {
  1063. Assert(g_pConnectionObj);
  1064. if (NULL == g_pConnectionObj)
  1065. return E_UNEXPECTED;
  1066. return g_pConnectionObj->GetConnectionObjCompletionEvent(
  1067. pConnectionObj,phRasPendingEvent);
  1068. }
  1069. //+---------------------------------------------------------------------------
  1070. //
  1071. // Function: ConnectObj_IsConnectionAvailable, public
  1072. //
  1073. // Synopsis: wrapper function
  1074. //
  1075. // Arguments:
  1076. //
  1077. // Returns:
  1078. //
  1079. // Modifies:
  1080. //
  1081. // History: 30-Mar-99 rogerg Created.
  1082. //
  1083. //----------------------------------------------------------------------------
  1084. HRESULT ConnectObj_IsConnectionAvailable(LPCWSTR pszConnectionName)
  1085. {
  1086. Assert(g_pConnectionObj);
  1087. if (NULL == g_pConnectionObj)
  1088. return E_UNEXPECTED;
  1089. return g_pConnectionObj->IsConnectionAvailable(pszConnectionName);
  1090. }
  1091. //+---------------------------------------------------------------------------
  1092. //
  1093. // Function: ConnectObj_SetWorkOffline, public
  1094. //
  1095. // Synopsis: wrapper function
  1096. //
  1097. // Arguments:
  1098. //
  1099. // Returns:
  1100. //
  1101. // Modifies:
  1102. //
  1103. // History: 14-Apr-99 rogerg Created.
  1104. //
  1105. //----------------------------------------------------------------------------
  1106. HRESULT ConnectObj_SetWorkOffline(BOOL fWorkOffline)
  1107. {
  1108. Assert(g_pConnectionObj);
  1109. if (NULL == g_pConnectionObj)
  1110. return E_UNEXPECTED;
  1111. return g_pConnectionObj->SetWorkOffline(fWorkOffline);
  1112. }