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.

1303 lines
35 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 ? S_OK : 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 S_OK;
  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 = S_OK;
  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. StringCchCopy(pNewConnectionObj->pwszConnectionName, cch+1, 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) || pNewConnectionObj->pwszConnectionName) )
  175. {
  176. // put at beginning of list
  177. pNewConnectionObj->pNextConnectionObj = m_pFirstConnectionObj;
  178. m_pFirstConnectionObj = pNewConnectionObj;
  179. *pConnectionObj = pNewConnectionObj;
  180. hr = S_OK;
  181. }
  182. else
  183. {
  184. if (pNewConnectionObj)
  185. {
  186. FreeConnectionObj(pNewConnectionObj);
  187. }
  188. }
  189. }
  190. clockqueue.Leave();
  191. return hr;
  192. }
  193. //+---------------------------------------------------------------------------
  194. //
  195. // Function: CConnectionObj::RemoveConnectionObj, public
  196. //
  197. // Synopsis: Removes the specified connections from the list.
  198. //
  199. // Arguments: [pszConnectionName] - Name of the Connection.
  200. //
  201. // Returns: Appropriate status code
  202. //
  203. // Modifies:
  204. //
  205. // History: 05-Nov-97 rogerg Created.
  206. //
  207. //----------------------------------------------------------------------------
  208. void CConnectionObj::RemoveConnectionObj(CONNECTIONOBJ *pConnectionObj)
  209. {
  210. CONNECTIONOBJ *pCurConnection = m_pFirstConnectionObj;
  211. ASSERT_LOCKHELD(this);
  212. // remove from the list
  213. if (m_pFirstConnectionObj == pConnectionObj)
  214. {
  215. m_pFirstConnectionObj = pConnectionObj->pNextConnectionObj;
  216. }
  217. else
  218. {
  219. while (pCurConnection)
  220. {
  221. if (pCurConnection->pNextConnectionObj == pConnectionObj)
  222. {
  223. pCurConnection->pNextConnectionObj = pConnectionObj->pNextConnectionObj;
  224. break;
  225. }
  226. pCurConnection = pCurConnection->pNextConnectionObj;
  227. }
  228. }
  229. FreeConnectionObj(pConnectionObj);
  230. }
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Function: CConnectionObj::FreeConnectionObj, privte
  234. //
  235. // Synopsis: frees the memory associate with a conneciton Object.
  236. //
  237. // Arguments:
  238. //
  239. // Returns: nada
  240. //
  241. // Modifies:
  242. //
  243. // History: 05-Nov-97 rogerg Created.
  244. //
  245. //----------------------------------------------------------------------------
  246. void CConnectionObj::FreeConnectionObj(CONNECTIONOBJ *pConnectionObj)
  247. {
  248. Assert(pConnectionObj);
  249. if (pConnectionObj)
  250. {
  251. if (pConnectionObj->pwszConnectionName)
  252. {
  253. FREE(pConnectionObj->pwszConnectionName);
  254. }
  255. FREE(pConnectionObj);
  256. }
  257. }
  258. //+---------------------------------------------------------------------------
  259. //
  260. // Member: CConnectionObj::IsConnectionAvailable, public
  261. //
  262. // Synopsis: Given a connection name sees if the connection is open
  263. //
  264. // Arguments:
  265. //
  266. // Returns: S_OK - Connection Open
  267. // S_FALSE - Connection not Open
  268. //
  269. // Modifies:
  270. //
  271. // History: 05-Feb-98 rogerg Created.
  272. //
  273. //----------------------------------------------------------------------------
  274. HRESULT CConnectionObj::IsConnectionAvailable(LPCWSTR pszConnectionName)
  275. {
  276. TCHAR szBuf[MAX_PATH + 1];
  277. DWORD dwConnectionType;
  278. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  279. HRESULT hr = S_FALSE;
  280. if (pNetApi )
  281. {
  282. BOOL fConnected,fCanEstablishConnection;
  283. // for now if the name of the connection is our
  284. // LAN connection name then set the ConnectionType to LAN,
  285. // else set it to WAN. if convert to Connection Manager
  286. // should get type from those interfaces.
  287. LoadString(g_hInst, IDS_LAN_CONNECTION, szBuf, MAX_PATH);
  288. if (NULL == pszConnectionName || 0 == lstrcmp(szBuf,pszConnectionName))
  289. {
  290. dwConnectionType = CNETAPI_CONNECTIONTYPELAN;
  291. }
  292. else
  293. {
  294. dwConnectionType = CNETAPI_CONNECTIONTYPEWAN;
  295. }
  296. pNetApi->GetConnectionStatus(pszConnectionName,dwConnectionType,
  297. &fConnected,&fCanEstablishConnection);
  298. pNetApi->Release();
  299. hr = (fConnected) ? S_OK: S_FALSE;
  300. }
  301. return hr;
  302. }
  303. //+---------------------------------------------------------------------------
  304. //
  305. // Member: CConnectionObj::RestoreWorkOffline, private
  306. //
  307. // Synopsis: If have force an online because of a dial then
  308. // set system state back to Work Offline.
  309. //
  310. // Arguments:
  311. //
  312. // Returns:
  313. //
  314. // Modifies:
  315. //
  316. // History: 05-Apr-99 rogerg Created.
  317. //
  318. //----------------------------------------------------------------------------
  319. void CConnectionObj::RestoreWorkOffline(LPNETAPI pNetApi)
  320. {
  321. if (!pNetApi)
  322. {
  323. Assert(pNetApi);
  324. return;
  325. }
  326. if (m_fForcedOnline)
  327. {
  328. pNetApi->SetOffline(TRUE);
  329. m_fForcedOnline = FALSE;
  330. }
  331. }
  332. //+---------------------------------------------------------------------------
  333. //
  334. // Member: CConnectionObj::TurnOffWorkOffline, private
  335. //
  336. // Synopsis: If System is in WorkOffline state will force
  337. // back to online.
  338. //
  339. // Arguments:
  340. //
  341. // Returns:
  342. //
  343. // Modifies:
  344. //
  345. // History: 05-Apr-99 rogerg Created.
  346. //
  347. //----------------------------------------------------------------------------
  348. void CConnectionObj::TurnOffWorkOffline(LPNETAPI pNetApi)
  349. {
  350. if (!pNetApi)
  351. {
  352. Assert(pNetApi);
  353. return;
  354. }
  355. if (pNetApi->IsGlobalOffline())
  356. {
  357. // if in offline state go ahead and switch to online
  358. if (pNetApi->SetOffline(FALSE))
  359. {
  360. m_fForcedOnline = TRUE;
  361. }
  362. }
  363. }
  364. //+---------------------------------------------------------------------------
  365. //
  366. // Member: CConnectionObj::OpenConnection, public
  367. //
  368. // Synopsis: Given a connection sees if the connection is open
  369. // and if it not and the fMakeConnection is true
  370. // will then attempt to open the connection.
  371. //
  372. // Arguments:
  373. //
  374. // Returns:
  375. //
  376. // Modifies:
  377. //
  378. // History: 05-Feb-98 rogerg Created.
  379. //
  380. //----------------------------------------------------------------------------
  381. HRESULT CConnectionObj::OpenConnection(CONNECTIONOBJ *pConnectionObj, BOOL fMakeConnection, CBaseDlg *pDlg)
  382. {
  383. #ifndef _RASDIAL
  384. DWORD dwConnectionId;
  385. #else
  386. HRASCONN hRasConn;
  387. #endif // _RASDIAL
  388. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  389. BOOL fConnected = FALSE;
  390. BOOL fCanEstablishConnection = FALSE;
  391. if (pNetApi)
  392. {
  393. // See if the specified connection is active and if there is any
  394. // Wan Activity.
  395. Assert(pConnectionObj->dwConnectionType); // should have a connection type setup by now.
  396. if ( S_OK == pNetApi->GetConnectionStatus( pConnectionObj->pwszConnectionName,
  397. pConnectionObj->dwConnectionType,
  398. &fConnected,
  399. &fCanEstablishConnection) )
  400. {
  401. // if there is no Wan Activity and there is not a connection
  402. // then we can go ahead try to dial
  403. if (!fConnected && fCanEstablishConnection
  404. && fMakeConnection && (pConnectionObj->pwszConnectionName))
  405. {
  406. DWORD dwErr;
  407. TurnOffWorkOffline(pNetApi);
  408. dwErr = pNetApi->InternetDialW( (pDlg ? pDlg->GetHwnd() : NULL),
  409. pConnectionObj->pwszConnectionName,
  410. INTERNET_AUTODIAL_FORCE_ONLINE | INTERNET_AUTODIAL_FORCE_UNATTENDED,
  411. &dwConnectionId,
  412. 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 ? S_OK : 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 = S_OK;
  448. DWORD dwErr = -1;
  449. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  450. // only allow one autodial at a time.
  451. if (m_fAutoDialConn)
  452. {
  453. return hr;
  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,
  486. 0 );
  487. if (0 == dwErr)
  488. {
  489. m_fAutoDialConn = TRUE;
  490. m_dwAutoConnID = dwConnectionId;
  491. }
  492. }
  493. // if an error occured then log it.
  494. if (dwErr)
  495. {
  496. if (pDlg)
  497. {
  498. LogError(pNetApi,dwErr,pDlg);
  499. }
  500. }
  501. hr = m_fAutoDialConn ? S_OK : E_UNEXPECTED;
  502. }
  503. if ( pNetApi )
  504. {
  505. pNetApi->Release();
  506. }
  507. return hr;
  508. }
  509. //+---------------------------------------------------------------------------
  510. //
  511. // Member: CConnectionObj::AutoDial
  512. //
  513. // Synopsis: turns on or off work offline
  514. //
  515. // History: 14-April-99 rogerg Created
  516. //
  517. //----------------------------------------------------------------------------
  518. HRESULT CConnectionObj::SetWorkOffline(BOOL fWorkOffline)
  519. {
  520. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  521. if (NULL == pNetApi)
  522. {
  523. return E_OUTOFMEMORY;
  524. }
  525. if (fWorkOffline)
  526. {
  527. RestoreWorkOffline(pNetApi); // Note: only sets back to workOffline if we turned it off.
  528. }
  529. else
  530. {
  531. TurnOffWorkOffline(pNetApi);
  532. }
  533. pNetApi->Release();
  534. return S_OK;
  535. }
  536. //+---------------------------------------------------------------------------
  537. //
  538. // Member: CConnectionObj::LogError, private
  539. //
  540. // Synopsis: Logs the dwErr to the dialog
  541. //
  542. // Arguments:
  543. //
  544. // Returns:
  545. //
  546. // Modifies:
  547. //
  548. // History: 08-Mar-99 rogerg Created.
  549. //
  550. //----------------------------------------------------------------------------
  551. void CConnectionObj::LogError(LPNETAPI pNetApi,DWORD dwErr,CBaseDlg *pDlg)
  552. {
  553. BOOL fErrorString= FALSE;
  554. WCHAR wszErrorString[RASERROR_MAXSTRING];
  555. MSGLogErrors msgLogError;
  556. // don't log if success or no dialog
  557. if (NULL == pDlg || 0 == dwErr)
  558. {
  559. Assert(dwErr);
  560. Assert(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 (S_OK == pNetApi->RasGetErrorStringProc(dwErr, wszErrorString, ARRAYSIZE(wszErrorString)) )
  569. {
  570. fErrorString = TRUE;
  571. }
  572. }
  573. else if (-1 != dwErr) // try formatMessage
  574. {
  575. if (FormatMessageW(
  576. FORMAT_MESSAGE_FROM_SYSTEM,
  577. NULL,
  578. dwErr,
  579. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
  580. wszErrorString,
  581. ARRAYSIZE(wszErrorString),
  582. NULL))
  583. {
  584. fErrorString = TRUE;
  585. }
  586. }
  587. if (FALSE == fErrorString)
  588. {
  589. // just use the generic error.
  590. if (LoadString(g_hInst, IDS_UNDEFINED_ERROR, wszErrorString, ARRAYSIZE(wszErrorString)))
  591. {
  592. fErrorString = TRUE;
  593. }
  594. }
  595. if (fErrorString)
  596. {
  597. msgLogError.mask = 0;
  598. msgLogError.dwErrorLevel = SYNCMGRLOGLEVEL_ERROR;
  599. msgLogError.lpcErrorText = wszErrorString;
  600. msgLogError.ErrorID = GUID_NULL;
  601. msgLogError.fHasErrorJumps = FALSE;
  602. pDlg->HandleLogError(NULL,0,&msgLogError);
  603. }
  604. }
  605. //+---------------------------------------------------------------------------
  606. //
  607. // Member: CConnectionObj::CloseConnection, public
  608. //
  609. // Synopsis: closes the specified connection.
  610. // Not an error if can't find Connection obj since under error
  611. // conditions we still want to call this to clean up, object
  612. // may or may not exist.
  613. //
  614. // Arguments:
  615. //
  616. // Returns:
  617. //
  618. // Modifies:
  619. //
  620. // History: 05-Feb-98 rogerg Created.
  621. //
  622. //----------------------------------------------------------------------------
  623. HRESULT CConnectionObj::CloseConnection(CONNECTIONOBJ *pConnectionObj)
  624. {
  625. CLock clockqueue(this);
  626. CONNECTIONOBJ FirstConnectObj;
  627. CONNECTIONOBJ *pCurConnection = &FirstConnectObj;
  628. clockqueue.Enter();
  629. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  630. pCurConnection->pNextConnectionObj = m_pFirstConnectionObj;
  631. while (pCurConnection->pNextConnectionObj)
  632. {
  633. CONNECTIONOBJ *pConnection = pCurConnection->pNextConnectionObj;
  634. // if the connection is equal to what was passed in, then
  635. // close it out.
  636. if (pConnection == pConnectionObj)
  637. {
  638. // If have a Completion Event to Set then
  639. if (pConnection->hCompletionEvent)
  640. {
  641. SetEvent(pConnection->hCompletionEvent);
  642. CloseHandle(pConnection->hCompletionEvent);
  643. pConnection->hCompletionEvent = NULL;
  644. }
  645. // if have an open ras connection, hang it up.
  646. // only time this should get connected is in the progress
  647. // TODO: make this a class that keeps the netapi loaded
  648. // until all connections have been closed.
  649. #ifndef _RASDIAL
  650. if (pConnection->dwConnectionId)
  651. {
  652. if ( pNetApi )
  653. {
  654. pNetApi->InternetHangUp(pConnection->dwConnectionId,0);
  655. pConnection->dwConnectionId = 0; // even if hangup fails set to null.
  656. }
  657. }
  658. #else
  659. if (pConnection->hRasConn)
  660. {
  661. if ( pNetApi )
  662. {
  663. pNetApi->RasHangup(pConnection->hRasConn);
  664. pConnection->hRasConn = NULL; // even if hangup fails set to null.
  665. }
  666. }
  667. #endif // _RASDIAL
  668. // if no one is holding onto this connection anymore get rid of it.
  669. if (0 == pConnection->cRefs)
  670. {
  671. pCurConnection->pNextConnectionObj = pConnection->pNextConnectionObj;
  672. FreeConnectionObj(pConnection);
  673. }
  674. else
  675. {
  676. pCurConnection = pCurConnection->pNextConnectionObj;
  677. }
  678. break;
  679. }
  680. else
  681. {
  682. pCurConnection = pCurConnection->pNextConnectionObj;
  683. }
  684. }
  685. m_pFirstConnectionObj = FirstConnectObj.pNextConnectionObj;
  686. if ( pNetApi )
  687. pNetApi->Release();
  688. clockqueue.Leave();
  689. return S_OK;
  690. }
  691. //+---------------------------------------------------------------------------
  692. //
  693. // Member: CConnectionObj::CloseConnections, public
  694. //
  695. // Synopsis: Closes any open connections that have a refcount of zero.
  696. //
  697. // Arguments:
  698. //
  699. // Returns:
  700. //
  701. // Modifies:
  702. //
  703. // History: 05-Feb-98 rogerg Created.
  704. //
  705. //----------------------------------------------------------------------------
  706. HRESULT CConnectionObj::CloseConnections()
  707. {
  708. CLock clockqueue(this);
  709. CONNECTIONOBJ FirstConnectObj;
  710. CONNECTIONOBJ *pCurConnection = &FirstConnectObj;
  711. clockqueue.Enter();
  712. pCurConnection->pNextConnectionObj = m_pFirstConnectionObj;
  713. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  714. while (pCurConnection->pNextConnectionObj)
  715. {
  716. CONNECTIONOBJ *pConnection = pCurConnection->pNextConnectionObj;
  717. // If have a Completion Event to Set then
  718. if (pConnection->hCompletionEvent)
  719. {
  720. SetEvent(pConnection->hCompletionEvent);
  721. CloseHandle(pConnection->hCompletionEvent);
  722. pConnection->hCompletionEvent = NULL;
  723. }
  724. // if have an open ras connection, hang it up.
  725. // only time this should get connected is in the progress
  726. // TODO: make this a class that keeps the netapi loaded
  727. // until all connections have been closed.
  728. if (pConnection->dwConnectionId)
  729. {
  730. if ( pNetApi )
  731. {
  732. pNetApi->InternetHangUp(pConnection->dwConnectionId,0);
  733. pConnection->dwConnectionId = 0; // even if hangup fails set to null.
  734. }
  735. }
  736. // if no one is holding onto this connection anymore get rid of it.
  737. if (0 == pConnection->cRefs)
  738. {
  739. pCurConnection->pNextConnectionObj = pConnection->pNextConnectionObj;
  740. FreeConnectionObj(pConnection);
  741. }
  742. else
  743. {
  744. pCurConnection = pCurConnection->pNextConnectionObj;
  745. }
  746. }
  747. m_pFirstConnectionObj = FirstConnectObj.pNextConnectionObj;
  748. //
  749. // Check if auto dial connection needs to be turned off, ignore failure
  750. //
  751. if ( m_fAutoDialConn )
  752. {
  753. if ( pNetApi )
  754. {
  755. if (m_dwAutoConnID)
  756. {
  757. pNetApi->InternetHangUp(m_dwAutoConnID,0);
  758. }
  759. else
  760. {
  761. pNetApi->InternetAutodialHangup( 0 );
  762. }
  763. }
  764. m_dwAutoConnID = FALSE;
  765. m_fAutoDialConn = FALSE;
  766. }
  767. // if we turned off offline then turn it back on
  768. RestoreWorkOffline(pNetApi);
  769. if ( pNetApi )
  770. pNetApi->Release();
  771. clockqueue.Leave();
  772. return S_OK;
  773. }
  774. //+---------------------------------------------------------------------------
  775. //
  776. // Function: CConnectionObj::ReleaseConnectionObj, public
  777. //
  778. // Synopsis: Decrements the specified connectionObj
  779. // If ther reference count goes to zero and there
  780. // is not an open connection we go ahead and
  781. // cleanup immediately.
  782. //
  783. // If there is a dialed connection we wait until
  784. // CloseConnection is explicitly called.
  785. //
  786. // Arguments: [pConnectionObj] - Pointer to the Connection Obj to Release.
  787. //
  788. // Returns: Appropriate status code
  789. //
  790. // Modifies:
  791. //
  792. // History: 05-Nov-97 rogerg Created.
  793. //
  794. //----------------------------------------------------------------------------
  795. DWORD CConnectionObj::ReleaseConnectionObj(CONNECTIONOBJ *pConnectionObj)
  796. {
  797. DWORD cRefs;
  798. BOOL fConnectionOpen = FALSE;
  799. CLock clockqueue(this);
  800. clockqueue.Enter();
  801. --pConnectionObj->cRefs;
  802. cRefs = pConnectionObj->cRefs;
  803. Assert( ((LONG) cRefs) >= 0);
  804. #ifndef _RASDIAL
  805. fConnectionOpen = pConnectionObj->dwConnectionId;
  806. #else
  807. fConnectionOpen = pConnectionObj->hRasConn;
  808. #endif // _RASDIAL
  809. if ( (0 == cRefs) && !fConnectionOpen && (NULL == pConnectionObj->hCompletionEvent) )
  810. {
  811. RemoveConnectionObj(pConnectionObj);
  812. }
  813. clockqueue.Leave();
  814. return cRefs;
  815. }
  816. //+---------------------------------------------------------------------------
  817. //
  818. // Function: CConnectionObj::AddRefConnectionObj, public
  819. //
  820. // Synopsis: Puts an AddRef on the specified connection obj
  821. //
  822. // Arguments: [pConnectionObj] - Pointer to the Connection Obj to Release.
  823. //
  824. // Returns: Appropriate status code
  825. //
  826. // Modifies:
  827. //
  828. // History: 05-Nov-97 rogerg Created.
  829. //
  830. //----------------------------------------------------------------------------
  831. DWORD CConnectionObj::AddRefConnectionObj(CONNECTIONOBJ *pConnectionObj)
  832. {
  833. DWORD cRefs = InterlockedIncrement( (LONG *) &(pConnectionObj->cRefs));
  834. return cRefs;
  835. }
  836. //+---------------------------------------------------------------------------
  837. //
  838. // Member: CConnectionObj::GetConnectionObjCompletionEvent, public
  839. //
  840. // Synopsis: caller has made a request for a completion event to be set up.
  841. // !!! warning, on success the event won't be signalled until CloseConnections is Called.
  842. //
  843. //
  844. // Arguments:
  845. //
  846. // Returns:
  847. //
  848. // Modifies:
  849. //
  850. // History: 05-Feb-98 rogerg Created.
  851. //
  852. //----------------------------------------------------------------------------
  853. HRESULT CConnectionObj::GetConnectionObjCompletionEvent(CONNECTIONOBJ *pConnectionObj,HANDLE *phRasPendingEvent)
  854. {
  855. HRESULT hr = E_UNEXPECTED;
  856. BOOL fFirstCreate = FALSE;
  857. CLock clockqueue(this);
  858. clockqueue.Enter();
  859. if (NULL == pConnectionObj->hCompletionEvent)
  860. {
  861. pConnectionObj->hCompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  862. fFirstCreate = TRUE;
  863. }
  864. if (pConnectionObj->hCompletionEvent)
  865. {
  866. HANDLE hCurThread;
  867. HANDLE hProcess;
  868. // if have a handle, duplicate it hand it out.
  869. hProcess = GetCurrentProcess();
  870. hCurThread = GetCurrentThread();
  871. if ( DuplicateHandle( hProcess,
  872. pConnectionObj->hCompletionEvent,
  873. hProcess,
  874. phRasPendingEvent,
  875. 0,
  876. FALSE,
  877. DUPLICATE_SAME_ACCESS) )
  878. {
  879. hr = S_OK;
  880. }
  881. else
  882. {
  883. *phRasPendingEvent = NULL;
  884. // if event was just created, then also close this one
  885. if (fFirstCreate)
  886. {
  887. CloseHandle(pConnectionObj->hCompletionEvent);
  888. pConnectionObj->hCompletionEvent = NULL;
  889. }
  890. }
  891. }
  892. clockqueue.Leave();
  893. return hr;
  894. }
  895. //+---------------------------------------------------------------------------
  896. //
  897. // Function: ConnectObj_OpenConnection, public
  898. //
  899. // Synopsis: wrapper function
  900. //
  901. // Arguments:
  902. //
  903. // Returns:
  904. //
  905. // Modifies:
  906. //
  907. // History: 05-Feb-98 rogerg Created.
  908. //
  909. //----------------------------------------------------------------------------
  910. HRESULT ConnectObj_OpenConnection(CONNECTIONOBJ *pConnectionObj,BOOL fMakeConnection,CBaseDlg *pDlg)
  911. {
  912. Assert(g_pConnectionObj);
  913. if (NULL == g_pConnectionObj)
  914. return E_UNEXPECTED;
  915. return g_pConnectionObj->OpenConnection(pConnectionObj,fMakeConnection,pDlg);
  916. }
  917. //+---------------------------------------------------------------------------
  918. //
  919. // Function: ConnectObj_CloseConnections, public
  920. //
  921. // Synopsis: wrapper function
  922. //
  923. // Arguments:
  924. //
  925. // Returns:
  926. //
  927. // Modifies:
  928. //
  929. // History: 05-Feb-98 rogerg Created.
  930. //
  931. //----------------------------------------------------------------------------
  932. HRESULT ConnectObj_CloseConnections()
  933. {
  934. Assert(g_pConnectionObj);
  935. if (NULL == g_pConnectionObj)
  936. return E_UNEXPECTED;
  937. return g_pConnectionObj->CloseConnections();
  938. }
  939. //+---------------------------------------------------------------------------
  940. //
  941. // Function: ConnectObj_CloseConnection, public
  942. //
  943. // Synopsis: wrapper function
  944. //
  945. // Arguments:
  946. //
  947. // Returns:
  948. //
  949. // Modifies:
  950. //
  951. // History: 05-Feb-98 rogerg Created.
  952. //
  953. //----------------------------------------------------------------------------
  954. HRESULT ConnectObj_CloseConnection(CONNECTIONOBJ *pConnectionObj)
  955. {
  956. Assert(g_pConnectionObj);
  957. if (NULL == g_pConnectionObj)
  958. return E_UNEXPECTED;
  959. return g_pConnectionObj->CloseConnection(pConnectionObj);
  960. }
  961. //+---------------------------------------------------------------------------
  962. //
  963. // Function: ConnectObj_FindConnectionObj, public
  964. //
  965. // Synopsis: wrapper function
  966. //
  967. // Arguments:
  968. //
  969. // Returns:
  970. //
  971. // Modifies:
  972. //
  973. // History: 05-Feb-98 rogerg Created.
  974. //
  975. //----------------------------------------------------------------------------
  976. HRESULT ConnectObj_FindConnectionObj(LPCWSTR pszConnectionName,BOOL fCreate,CONNECTIONOBJ **pConnectionObj)
  977. {
  978. Assert(g_pConnectionObj);
  979. if (NULL == g_pConnectionObj)
  980. return E_UNEXPECTED;
  981. return g_pConnectionObj->FindConnectionObj(pszConnectionName, fCreate, pConnectionObj);
  982. }
  983. //+---------------------------------------------------------------------------
  984. //
  985. // Function: ConnectObj_AutoDial
  986. //
  987. // Synopsis: Wrapper function for auto dial
  988. //
  989. // History: 28-Jul-98 SitaramR Created
  990. //
  991. //----------------------------------------------------------------------------
  992. HRESULT ConnectObj_AutoDial(DWORD dwFlags,CBaseDlg *pDlg)
  993. {
  994. Assert(g_pConnectionObj);
  995. if (NULL == g_pConnectionObj)
  996. return E_UNEXPECTED;
  997. return g_pConnectionObj->AutoDial(dwFlags,pDlg);
  998. }
  999. //+---------------------------------------------------------------------------
  1000. //
  1001. // Function: ConnectObj_ReleaseConnectionObj, public
  1002. //
  1003. // Synopsis: wrapper function
  1004. //
  1005. // Arguments:
  1006. //
  1007. // Returns:
  1008. //
  1009. // Modifies:
  1010. //
  1011. // History: 05-Feb-98 rogerg Created.
  1012. //
  1013. //----------------------------------------------------------------------------
  1014. DWORD ConnectObj_ReleaseConnectionObj(CONNECTIONOBJ *pConnectionObj)
  1015. {
  1016. Assert(g_pConnectionObj);
  1017. if (NULL == g_pConnectionObj)
  1018. return 0;
  1019. return g_pConnectionObj->ReleaseConnectionObj(pConnectionObj);
  1020. }
  1021. //+---------------------------------------------------------------------------
  1022. //
  1023. // Function: ConnectObj_AddRefConnectionObj, public
  1024. //
  1025. // Synopsis: wrapper function
  1026. //
  1027. // Arguments:
  1028. //
  1029. // Returns:
  1030. //
  1031. // Modifies:
  1032. //
  1033. // History: 05-Feb-98 rogerg Created.
  1034. //
  1035. //----------------------------------------------------------------------------
  1036. DWORD ConnectObj_AddRefConnectionObj(CONNECTIONOBJ *pConnectionObj)
  1037. {
  1038. Assert(g_pConnectionObj);
  1039. if (NULL == g_pConnectionObj)
  1040. return 0;
  1041. return g_pConnectionObj->AddRefConnectionObj(pConnectionObj);
  1042. }
  1043. //+---------------------------------------------------------------------------
  1044. //
  1045. // Function: ConnectObj_GetConnectionObjCompletionEvent, public
  1046. //
  1047. // Synopsis: wrapper function
  1048. //
  1049. // Arguments:
  1050. //
  1051. // Returns:
  1052. //
  1053. // Modifies:
  1054. //
  1055. // History: 05-Feb-98 rogerg Created.
  1056. //
  1057. //----------------------------------------------------------------------------
  1058. HRESULT ConnectObj_GetConnectionObjCompletionEvent(CONNECTIONOBJ *pConnectionObj,HANDLE *phRasPendingEvent)
  1059. {
  1060. Assert(g_pConnectionObj);
  1061. if (NULL == g_pConnectionObj)
  1062. return E_UNEXPECTED;
  1063. return g_pConnectionObj->GetConnectionObjCompletionEvent(pConnectionObj,phRasPendingEvent);
  1064. }
  1065. //+---------------------------------------------------------------------------
  1066. //
  1067. // Function: ConnectObj_IsConnectionAvailable, public
  1068. //
  1069. // Synopsis: wrapper function
  1070. //
  1071. // Arguments:
  1072. //
  1073. // Returns:
  1074. //
  1075. // Modifies:
  1076. //
  1077. // History: 30-Mar-99 rogerg Created.
  1078. //
  1079. //----------------------------------------------------------------------------
  1080. HRESULT ConnectObj_IsConnectionAvailable(LPCWSTR pszConnectionName)
  1081. {
  1082. Assert(g_pConnectionObj);
  1083. if (NULL == g_pConnectionObj)
  1084. return E_UNEXPECTED;
  1085. return g_pConnectionObj->IsConnectionAvailable(pszConnectionName);
  1086. }
  1087. //+---------------------------------------------------------------------------
  1088. //
  1089. // Function: ConnectObj_SetWorkOffline, public
  1090. //
  1091. // Synopsis: wrapper function
  1092. //
  1093. // Arguments:
  1094. //
  1095. // Returns:
  1096. //
  1097. // Modifies:
  1098. //
  1099. // History: 14-Apr-99 rogerg Created.
  1100. //
  1101. //----------------------------------------------------------------------------
  1102. HRESULT ConnectObj_SetWorkOffline(BOOL fWorkOffline)
  1103. {
  1104. Assert(g_pConnectionObj);
  1105. if (NULL == g_pConnectionObj)
  1106. return E_UNEXPECTED;
  1107. return g_pConnectionObj->SetWorkOffline(fWorkOffline);
  1108. }