|
|
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
//
// MODULE: conman.cpp
//
// PURPOSE: Defines the CConnectionManager object for Athena.
//
#include "pch.hxx"
#include "conman.h"
#include "error.h"
#include "strconst.h"
#include "rasdlgsp.h"
#include "resource.h"
#include "xpcomm.h"
#include "goptions.h"
#include "thormsgs.h"
#include "wininet.h"
#include "shlwapip.h"
#include "demand.h"
#include "dllmain.h"
#include "browser.h"
#include <urlmon.h>
#include "menures.h"
#include "workoff.h"
#include <sync.h>
ASSERTDATA
#define DEF_HANGUP_WAIT 10 // Seconds
static const TCHAR s_szRasDlgDll[] = "RASDLG.DLL"; #ifdef UNICODE
static const TCHAR s_szRasDialDlg[] = "RasDialDlgW"; static const TCHAR s_szRasEntryDlg[] = "RasEntryDlgW"; #else
static const TCHAR s_szRasDialDlg[] = "RasDialDlgA"; static const TCHAR s_szRasEntryDlg[] = "RasEntryDlgA"; #endif
BOOL FIsPlatformWinNT();
//
// FUNCTION: CConnectionManager::CConnectionManager()
//
// PURPOSE: Constructor
//
CConnectionManager::CConnectionManager() { m_cRef = 1; // Synchronization Objects
InitializeCriticalSection(&m_cs); m_hMutexDial = INVALID_HANDLE_VALUE; m_pAcctMan = 0; m_fSavePassword = 0; m_fRASLoadFailed = 0; m_fOffline = 0;
m_dwConnId = 0; ZeroMemory(&m_rConnInfo, sizeof(CONNINFO)); m_rConnInfo.state = CIS_REFRESH;
*m_szConnectName = 0; ZeroMemory(&m_rdp, sizeof(RASDIALPARAMS)); m_hInstRas = NULL; m_hInstRasDlg = NULL;
m_pNotifyList = NULL; m_pConnListHead = NULL;
m_hInstSensDll = NULL; m_fMobilityPackFailed = FALSE; m_pIsDestinationReachable = NULL; m_pIsNetworkAlive = NULL; m_fTryAgain = FALSE; m_fDialerUI = FALSE; }
//
// FUNCTION: CConnectionManager::~CConnectionManager()
//
// PURPOSE: Destructor
//
CConnectionManager::~CConnectionManager() { SafeRelease(m_pAcctMan);
FreeNotifyList();
EnterCriticalSection(&m_cs);
if (m_hInstRas) FreeLibrary(m_hInstRas);
if (m_hInstRasDlg) FreeLibrary(m_hInstRasDlg);
if (m_hInstSensDll) FreeLibrary(m_hInstSensDll);
CloseHandle(m_hMutexDial);
LeaveCriticalSection(&m_cs); DeleteCriticalSection(&m_cs);
EmptyConnList();
}
//
// FUNCTION: CConnectionManager::HrInit()
//
// PURPOSE: Initalizes the connection manager by attempting to load RAS
// and storing a pointer to the Account Manager object that is
// passed in.
//
// PARAMETERS:
// <in> pAcctMan - Pointer to the account manager object that we will
// use to retrieve account information and register for
// account changes.
//
// RETURN VALUE:
// S_OK Everything is hunky-dorie
// HR_E_ALREADYEXISTS We already exist, can't do it twice.
// HR_S_RASNOTLOADED The system doesn't have RAS installed.
//
HRESULT CConnectionManager::HrInit(IImnAccountManager *pAcctMan) { HRESULT hr = S_OK;
// Make a copy of the account manager pointer
if (NULL == pAcctMan) { AssertSz(pAcctMan, _T("CConnectionManager::HrInit() - Requires an IAccountManager pointer.")); return (E_INVALIDARG); }
m_pAcctMan = pAcctMan; m_pAcctMan->AddRef(); // Register a window class for our advise handling
WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = NotifyWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInst; wc.hIcon = 0; wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = 0; wc.lpszClassName = NOTIFY_HWND;
RegisterClass(&wc);
m_hMutexDial = CreateMutex(NULL, FALSE, NULL); if (NULL == m_hMutexDial) return (E_FAIL);
return (S_OK); }
HRESULT STDMETHODCALLTYPE CConnectionManager::QueryInterface(REFIID riid, LPVOID *ppvObject) { if (!ppvObject) return E_INVALIDARG;
if (IsEqualIID(riid, IID_IUnknown)) *ppvObject = (LPVOID) (IUnknown*) this; else if (IsEqualIID(riid, IID_IImnAdviseAccount)) *ppvObject = (LPVOID) (IImnAdviseAccount*) this; else *ppvObject = NULL;
if (*ppvObject) { AddRef(); return (S_OK); } else return (E_NOINTERFACE); }
ULONG STDMETHODCALLTYPE CConnectionManager::AddRef(void) { return (++m_cRef); }
ULONG STDMETHODCALLTYPE CConnectionManager::Release(void) { ULONG cRef = --m_cRef; if (m_cRef == 0) { delete this; return (0); }
return (cRef); }
HRESULT STDMETHODCALLTYPE CConnectionManager::AdviseAccount(DWORD dwAdviseType, ACTX *pactx) { IImnAccount *pAccount; DWORD dwConnection;
// SendAdvise(CONNNOTIFY_RASACCOUNTSCHANGED, 0);
switch (dwAdviseType) { case AN_ACCOUNT_DELETED: { if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pactx->pszAccountID, &pAccount))) { if (SUCCEEDED(pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection))) { if (dwConnection == CONNECTION_TYPE_RAS) { TCHAR szConnection[CCHMAX_CONNECTOID]; *szConnection = '\0'; if (SUCCEEDED(pAccount->GetPropSz(AP_RAS_CONNECTOID, szConnection, ARRAYSIZE(szConnection))) && *szConnection) { RemoveFromConnList(szConnection); } } } } break; } }
return (S_OK); }
void CConnectionManager::EmptyConnList() { ConnListNode *pCur;
//Delete all the nodes
while (m_pConnListHead != NULL) { pCur = m_pConnListHead; m_pConnListHead = m_pConnListHead->pNext; delete pCur; } m_pConnListHead = NULL; }
void CConnectionManager::RemoveFromConnList(LPTSTR pszRasConn) { ConnListNode *prev = NULL, *Cur = m_pConnListHead; LPTSTR pRasConn;
while (Cur != NULL) { if (0 == lstrcmpi(pszRasConn, Cur->pszRasConn)) { if (prev == NULL) { m_pConnListHead = Cur->pNext; } else { prev->pNext = Cur->pNext; } delete Cur; } else { prev = Cur; Cur = Cur->pNext; } } }
HRESULT CConnectionManager::AddToConnList(LPTSTR pszRasConn) { //We don't have to make sure that this is not already in the list because once
//it is in the list, that means its already connected and so we don't land up in this
//situation after that
ConnListNode *pnext; HRESULT hres; IImnAccount *pAccount;
pnext = m_pConnListHead; m_pConnListHead = new ConnListNode; if (m_pConnListHead != NULL) { m_pConnListHead->pNext = pnext; StrCpyN(m_pConnListHead->pszRasConn, pszRasConn, ARRAYSIZE(m_pConnListHead->pszRasConn)); hres = S_OK; } else hres = E_FAIL;
return hres; }
HRESULT CConnectionManager::SearchConnList(LPTSTR pszRasConn) { ConnListNode *pCur = m_pConnListHead; while (pCur != NULL) { if (0 == lstrcmpi(pszRasConn, pCur->pszRasConn)) return S_OK; pCur = pCur->pNext; } return E_FAIL; }
//
// FUNCTION: CConnectionManager::CanConnect()
//
// PURPOSE: Determines if the caller can connect to the given account
// using the existing connection.
//
// PARAMETERS:
// <in> pAccount - Pointer to the account object the caller wants to
// connect to.
//
// RETURN VALUE:
// S_OK - The caller can connect using the existing connection
// S_FALSE - There is no existing connection, so there is no reason the
// caller can't connect.
// E_FAIL - The existing connection is different from the account's
// connection. The user must hang up and dial again to connect
//
HRESULT CConnectionManager::CanConnect(IImnAccount *pAccount) { HRESULT hr; DWORD dwConnection; IImnAccount *pDefault = 0; LPRASCONN pConnections = NULL; ULONG cConnections = 0; BOOL fFound = 0;
// Check to see if we're working offline
if (IsGlobalOffline()) return (HR_E_OFFLINE); // If the connection the user is looking for is not RAS, then we just
// return success.
if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection))) { // If we didn't get the connection information, then we look for the
// connection from the default server of this type
if (FAILED(hr = GetDefaultConnection(pAccount, &pDefault))) { // Bug #36071 - If we haven't set up any accounts of this type yet,
// we'd fail. As a result, if you fire a URL to a server
// we'd never try to connect and download. I'm going
// to change this to succeed and we'll see what type
// of bugs that creates.
return (S_OK); } // We're going to use the default from now on
pAccount = pDefault; if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection))) { // Bug #36071 - If we haven't set up any accounts of this type yet,
// we'd fail. As a result, if you fire a URL to a server
// we'd never try to connect and download. I'm going
// to change this to succeed and we'll see what type
// of bugs that creates.
return (S_OK); } }
hr = OEIsDestinationReachable(pAccount, dwConnection);
//I don't think we should be doing this here. Review again
/*
if ((hr == S_OK) && (dwConnection == CONNECTION_TYPE_RAS || dwConnection == CONNECTION_TYPE_INETSETTINGS)) { m_rConnInfo.fConnected = TRUE; } */
//exit:
SafeRelease(pDefault); return (hr); }
//
// FUNCTION: CConnectionManager::CanConnect()
//
// PURPOSE: Determines if the caller can connect to the given account
// using the existing connection.
//
// PARAMETERS:
// <in> pszAccount - Pointer to the name of the account the caller wants
// to connect to.
//
// RETURN VALUE:
// S_OK - The caller can connect using the existing connection
// S_FALSE - There is no existing connection, so there is no reason the
// caller can't connect.
// E_FAIL - The existing connection is different from the account's
// connection. The user must hang up and dial again to connect
// E_INVALIDARG - The account doesn't exist
//
HRESULT CConnectionManager::CanConnect(LPTSTR pszAccount) { IImnAccount *pAccount = NULL; HRESULT hr; // Check to see if we're working offline
if (IsGlobalOffline()) return (HR_E_OFFLINE);
// Look up the account name in the account manager to get the account
// object.
Assert(m_pAcctMan);
if (lstrcmpi(pszAccount, STR_LOCALSTORE) == 0) return(S_OK); if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccount, &pAccount))) { // Call through to the polymorphic version of us
hr = CanConnect(pAccount); pAccount->Release(); } else { // Bug #36071 - If we haven't set up any accounts of this type yet,
// we'd fail. As a result, if you fire a URL to a server
// we'd never try to connect and download. I'm going
// to change this to succeed and we'll see what type
// of bugs that creates.
hr = S_OK; } return (hr); }
BOOL CConnectionManager::IsAccountDisabled(LPTSTR pszAccount) { IImnAccount *pAccount = NULL; DWORD dw; // Look up the account name in the account manager to get the account
// object.
Assert(m_pAcctMan);
if (lstrcmpi(pszAccount, STR_LOCALSTORE) == 0) return(FALSE); if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccount, &pAccount))) { if (SUCCEEDED(pAccount->GetPropDw(AP_HTTPMAIL_DOMAIN_MSN, &dw)) && dw) { if(HideHotmail()) return(TRUE); } return(FALSE); } return(TRUE); }
//
// FUNCTION: CConnectionManager::Connect()
//
// PURPOSE: Attempts to establish a connection for the account specified.
//
// PARAMETERS:
// <in> pAccount - Pointer to the account object to connect to.
// <in> hwnd - Handle of the window to show UI over. Only needed if
// fShowUI is TRUE.
// <in> fShowUI - TRUE if the functions are allowed to display UI.
//
// RETURN VALUE:
// S_OK - We're connected
// E_UNEXPECTED - There wasn't enough information in pAccount to figure
// figure out which connection to use.
//
HRESULT CConnectionManager::Connect(IImnAccount *pAccount, HWND hwnd, BOOL fShowUI) { HRESULT hr = S_OK; DWORD dwConnection; IImnAccount *pDefault = 0;
if (!m_fDialerUI) { m_fDialerUI = TRUE; // Check to see if we're working offline
if (IsGlobalOffline()) { if (fShowUI) { if (IDNO == AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline), 0, MB_YESNO | MB_ICONEXCLAMATION )) { m_fDialerUI = FALSE; return (HR_E_OFFLINE); } else g_pConMan->SetGlobalOffline(FALSE); } else { m_fDialerUI = FALSE; return (HR_E_OFFLINE); } } m_fDialerUI = FALSE; }
if (CanConnect(pAccount) == S_OK) { return S_OK; }
// If the connection the user is looking for is not RAS, then we just
// return success.
if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection))) { // If we didn't get the connection information, then we look for the
// connection from the default server of this type
if (FAILED(hr = GetDefaultConnection(pAccount, &pDefault))) { // Bug #36071 - If we haven't set up any accounts of this type yet,
// we'd fail. As a result, if you fire a URL to a server
// we'd never try to connect and download. I'm going
// to change this to succeed and we'll see what type
// of bugs that creates.
return (S_OK); } // We're going to use the default from now on
pAccount = pDefault; if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection))) { // Bug #36071 - If we haven't set up any accounts of this type yet,
// we'd fail. As a result, if you fire a URL to a server
// we'd never try to connect and download. I'm going
// to change this to succeed and we'll see what type
// of bugs that creates.
hr = S_OK; goto exit; } }
if (dwConnection == CONNECTION_TYPE_INETSETTINGS) { hr = ConnectUsingIESettings(hwnd, fShowUI); goto exit; }
if (dwConnection == CONNECTION_TYPE_LAN) { //CanConnect already told us that Lan is not present
hr = E_FAIL; goto exit; }
if (dwConnection != CONNECTION_TYPE_RAS) { hr = S_OK; goto exit; }
// Get the name of the connection while we're at it.
TCHAR szConnection[CCHMAX_CONNECTOID]; if (FAILED(hr = pAccount->GetPropSz(AP_RAS_CONNECTOID, szConnection, ARRAYSIZE(szConnection)))) { AssertSz(FALSE, _T("CConnectionManager::Connect() - No connection name.")); hr = E_UNEXPECTED; goto exit; }
hr = ConnectActual(szConnection, hwnd, fShowUI);
exit: SafeRelease(pDefault);
return (hr); }
//
// FUNCTION: CConnectionManager::Connect()
//
// PURPOSE: Attempts to establish a connection for the account specified.
//
// PARAMETERS:
// <in> pszAccount - Name of the account to connect to.
// <in> hwnd - Handle of the window to show UI over. Only needed if
// fShowUI is TRUE.
// <in> fShowUI - TRUE if the functions are allowed to display UI.
//
// RETURN VALUE:
// <???>
//
HRESULT CConnectionManager::Connect(LPTSTR pszAccount, HWND hwnd, BOOL fShowUI) { IImnAccount *pAccount = NULL; HRESULT hr; // Check to see if we're working offline
if (!m_fDialerUI) { m_fDialerUI = TRUE; // Check to see if we're working offline
if (IsGlobalOffline()) { if (fShowUI) { if (IDNO == AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline), 0, MB_YESNO | MB_ICONEXCLAMATION )) { m_fDialerUI = FALSE; return (HR_E_OFFLINE); } else g_pConMan->SetGlobalOffline(FALSE); } else { m_fDialerUI = FALSE; return (HR_E_OFFLINE); } }
m_fDialerUI = FALSE; }
// Look up the account name in the account manager to get the account
// object.
Assert(m_pAcctMan); // if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_NAME, pszAccount, &pAccount)))
if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccount, &pAccount))) { // Call through to the polymorphic version of us
hr = Connect(pAccount, hwnd, fShowUI); pAccount->Release(); } else { // Bug #36071 - If we haven't set up any accounts of this type yet,
// we'd fail. As a result, if you fire a URL to a server
// we'd never try to connect and download. I'm going
// to change this to succeed and we'll see what type
// of bugs that creates.
hr = S_OK; } return (hr); }
//
// FUNCTION: CConnectionManager::Connect()
//
// PURPOSE: Attempts to establish a connection for the account specified.
//
// PARAMETERS:
// <in> hMenu - Handle of the menu that was used to select the account
// to connect to.
// <in> cmd - Cmd ID from the menu that says which account to use.
// <in> hwnd - Handle to display UI over.
//
// RETURN VALUE:
// <???>
//
HRESULT CConnectionManager::Connect(HMENU hMenu, DWORD cmd, HWND hwnd) { MENUITEMINFO mii;
Assert(hMenu && cmd); Assert(cmd >= (DWORD) ID_CONNECT_FIRST && cmd < ((DWORD) ID_CONNECT_FIRST + GetMenuItemCount(hMenu)));
// Get the account pointer from the menu item
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA; mii.dwItemData = 0;
if (GetMenuItemInfo(hMenu, cmd, FALSE, &mii)) { Assert(mii.dwItemData); if (mii.dwItemData) { return (Connect((IImnAccount *) mii.dwItemData, hwnd, TRUE)); } }
return (E_UNEXPECTED); }
HRESULT CConnectionManager::ConnectDefault(HWND hwnd, BOOL fShowUI) { IImnEnumAccounts *pEnum = NULL; IImnAccount *pAcct = NULL; DWORD dwConn = 0; TCHAR szAcct[CCHMAX_ACCOUNT_NAME]; TCHAR szConn[CCHMAX_CONNECTOID]; HRESULT hr = E_UNEXPECTED;
// Get the enumerator from the account manager
if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum))) { pEnum->Reset();
// Walk through all the accounts
while (SUCCEEDED(pEnum->GetNext(&pAcct))) { // Get the connection type for this account
if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn))) { // If the account is a RAS account, ask for the connectoid name
// and the account name.
if (dwConn == CONNECTION_TYPE_RAS || dwConn == CONNECTION_TYPE_INETSETTINGS) { break; } } SafeRelease(pAcct); } SafeRelease(pEnum); }
if (pAcct) { hr = Connect(pAcct, hwnd, fShowUI); SafeRelease(pAcct); }
return (hr); }
//
// FUNCTION: CConnectionManager::Disconnect()
//
// PURPOSE: Brings down the current RAS connection.
//
// PARAMETERS:
// <in> hwnd - Handle of the window to display UI over.
// <in> fShowUI - Allows to caller to determine if UI will be displayed
// while disconnecting.
// <in> fForce - Forces the connection down even if we didn't create it.
// <in> fShutdown - TRUE if we're dropping because we're shutting down.
//
// RETURN VALUE:
// S_OK - Everything worked.
// E_FAIL - We didn't create it
//
HRESULT CConnectionManager::Disconnect(HWND hwnd, BOOL fShowUI, BOOL fForce, BOOL fShutdown) { HRESULT hr; TCHAR szRes[CCHMAX_STRINGRES]; TCHAR szBuf[CCHMAX_STRINGRES]; int idAnswer = IDYES;
// RefreshConnInfo
hr = RefreshConnInfo(FALSE); if (FAILED(hr)) return hr; // See if we even have a RAS connection active
if (!m_rConnInfo.hRasConn) return (S_OK); /*
if (!(*m_rConnInfo.szCurrentConnectionName)) return S_OK; */
// The autodialer has it's own shutdown prompt.
if (fShutdown && m_rConnInfo.fAutoDial) return (S_OK);
if (fShutdown && !m_rConnInfo.fIStartedRas) return (S_OK);
if (fShutdown) { AthLoadString(idsRasPromptDisconnect, szRes, ARRAYSIZE(szRes)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, m_rConnInfo.szCurrentConnectionName); idAnswer = AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), szBuf, 0, MB_YESNO | MB_ICONEXCLAMATION ); } // Hang up
if (idAnswer == IDYES) { SendAdvise(CONNNOTIFY_DISCONNECTING, NULL);
if (S_FALSE == DoAutoDial(hwnd, m_rConnInfo.szCurrentConnectionName, FALSE)) { InternetHangUpAndWait(m_dwConnId, DEF_HANGUP_WAIT); /*
RasHangupAndWait(m_rConnInfo.hRasConn, DEF_HANGUP_WAIT); */ }
EnterCriticalSection(&m_cs);
ZeroMemory(&m_rConnInfo, sizeof(CONNINFO)); m_rConnInfo.state = CIS_CLEAN; m_dwConnId = 0;
LeaveCriticalSection(&m_cs); EmptyConnList();
SendAdvise(CONNNOTIFY_DISCONNECTED, NULL); return (S_OK); } return (E_FAIL); }
//
// FUNCTION: CConnectionManager::IsConnected()
//
// PURPOSE: Allows the client to query whether or not there is an active
// RAS connection that we established.
//
// RETURN VALUE:
// TRUE - We're connected, FALSE - we're not.
//
BOOL CConnectionManager::IsConnected(void) { BOOL f=FALSE;
EnterCriticalSection(&m_cs);
RefreshConnInfo();
if (m_rConnInfo.hRasConn) { f = (NULL == m_rConnInfo.hRasConn) ? FALSE : TRUE; }
LeaveCriticalSection(&m_cs); return f; }
//
// FUNCTION: CConnectionManager::Advise()
//
// PURPOSE: Allows the user to register to be notified whenever connection
// status changes.
//
// PARAMETERS:
// <in> pNotify - Pointer to the IConnectionNotify interface the client
// would like called when events happen.
//
// RETURN VALUE:
// S_OK - Added ok.
// E_OUTOFMEMORY - Couldn't realloc the array
//
HRESULT CConnectionManager::Advise(IConnectionNotify *pNotify) { HRESULT hr = S_OK;
if (!pNotify) return (E_INVALIDARG);
EnterCriticalSection(&m_cs);
// Check to see if we already have a notify window for this thread
NOTIFYHWND *pTemp = m_pNotifyList; DWORD dwThread = GetCurrentThreadId();
while (pTemp) { if (pTemp->dwThreadId == dwThread) break;
pTemp = pTemp->pNext; }
// If we didn't find a notify window for this thread, create one
if (NULL == pTemp) { HWND hwndTemp = CreateWindow(NOTIFY_HWND, NULL, WS_OVERLAPPED, 10, 10, 10, 10, NULL, (HMENU) 0, g_hInst, (LPVOID) this); if (!hwndTemp) { hr = E_OUTOFMEMORY; goto exit; }
if (!MemAlloc((LPVOID*) &pTemp, sizeof(NOTIFYHWND))) { RemoveProp(hwndTemp, NOTIFY_HWND); DestroyWindow(hwndTemp); hr = E_OUTOFMEMORY; goto exit; }
pTemp->dwThreadId = dwThread; pTemp->hwnd = hwndTemp; pTemp->pNext = m_pNotifyList; m_pNotifyList = pTemp; }
// Allocate a NOTIFYLIST node for this caller
NOTIFYLIST *pListTemp; if (!MemAlloc((LPVOID*) &pListTemp, sizeof(NOTIFYLIST))) { hr = E_OUTOFMEMORY; goto exit; }
pListTemp->pNotify = pNotify;
// Get the current list for this thread and insert this node at the
// beginning
pListTemp->pNext = (NOTIFYLIST *) GetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA);
// Set this new list to the window
SetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA, (LONG_PTR)pListTemp);
exit: LeaveCriticalSection(&m_cs); return (hr); }
//
// FUNCTION: CConnectionManager::Unadvise()
//
// PURPOSE: Allows a client that has previously registered for notifications
// to unregister itself.
//
// PARAMETERS:
// <in> pNotify - Pointer to the interface that is being called upon
// notifications.
//
// RETURN VALUE:
// E_INVALIDARG - pNotify was not found in the list
// S_OK - Everything's OK
//
HRESULT CConnectionManager::Unadvise(IConnectionNotify *pNotify) { DWORD index = 0; HRESULT hr = S_OK; EnterCriticalSection(&m_cs);
// Loop through the notify windows we own
NOTIFYHWND *pTemp = m_pNotifyList; NOTIFYHWND *pHwndPrev = NULL; while (pTemp) { // Get the list of notify callbacks for this window
NOTIFYLIST *pList = (NOTIFYLIST *)GetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA); if (pList) { // Loop through the callbacks looking for this one
NOTIFYLIST *pListT = pList; NOTIFYLIST *pPrev; // Check to see if it's the first one
if (pListT->pNotify == pNotify) { pList = pListT->pNext; if (pList) { SetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA, (LONG_PTR)pList); } else { Assert(GetCurrentThreadId() == GetWindowThreadProcessId(pTemp->hwnd, NULL)); RemoveProp(pTemp->hwnd, NOTIFY_HWND); DestroyWindow(pTemp->hwnd); if (pHwndPrev) pHwndPrev->pNext = pTemp->pNext; else m_pNotifyList = pTemp->pNext; MemFree(pTemp); } SafeMemFree(pListT); hr = S_OK; goto exit; } else { pPrev = pList; pListT = pList->pNext;
while (pListT) { if (pListT->pNotify == pNotify) { pPrev->pNext = pListT->pNext; SafeMemFree(pListT); hr = S_OK; goto exit; }
pListT = pListT->pNext; pPrev = pPrev->pNext; } } }
pHwndPrev = pTemp; pTemp = pTemp->pNext; }
exit: LeaveCriticalSection(&m_cs); return (hr); } //
// FUNCTION: CConnectionManager::RasAccountsExist()
//
// PURPOSE: Allows the client to ask whether or not we have any accounts
// configured that require a RAS connection.
//
// RETURN VALUE:
// S_OK - Accounts exist that require RAS
// S_FALSE - No accounts exist that require RAS
//
HRESULT CConnectionManager::RasAccountsExist(void) { IImnEnumAccounts *pEnum = NULL; IImnAccount *pAcct = NULL; DWORD dwConn; BOOL fFound = FALSE;
// If no RAS, no accounts
#ifdef SLOWDOWN_STARTUP_TIME
if (FAILED(VerifyRasLoaded())) return (S_FALSE); #endif
// We need to walk through the accounts in the Account Manager to see if
// any of them have a connect type of RAS. As soon as we find one, we can
// return success.
Assert(m_pAcctMan);
if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum))) { pEnum->Reset();
while (!fFound && SUCCEEDED(pEnum->GetNext(&pAcct))) { if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn))) { if (dwConn == CONNECTION_TYPE_RAS) { fFound = TRUE; } } SafeRelease(pAcct); }
SafeRelease(pEnum); }
return (fFound ? S_OK : S_FALSE); }
//
// FUNCTION: CConnectionManager::GetConnectMenu()
//
// PURPOSE: Returns a menu that has all the accounts that require RAS
// connections listed. A pointer to the IImnAccount for each
// account is stored in the menu item's dwItemData parameter.
// As a result, the client MUST call FreeConnectMenu() when then
// menu is no longer being used.
//
// PARAMETERS:
// <out> phMenu - Returns the menu handle
//
// RETURN VALUE:
// S_OK - phMenu contains the menu
// E_FAIL - Something unfortunate happend.
//
HRESULT CConnectionManager::GetConnectMenu(HMENU *phMenu) { HMENU hMenu = NULL; IImnEnumAccounts *pEnum = NULL; IImnAccount *pAcct = NULL; DWORD dwConn = 0; TCHAR szAcct[CCHMAX_ACCOUNT_NAME]; TCHAR szConn[CCHMAX_CONNECTOID]; TCHAR szConnQuoted[CCHMAX_CONNECTOID + 2], szBuf[CCHMAX_CONNECTOID + 2]; TCHAR szMenu[CCHMAX_ACCOUNT_NAME + CCHMAX_CONNECTOID]; MENUITEMINFO mii; DWORD cAcct = 0; // Create a menu and add all the RAS based accounts to it
Assert(m_pAcctMan); hMenu = CreatePopupMenu(); // Get the enumerator from the account manager
if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum))) { pEnum->Reset();
// Walk through all the accounts
while (SUCCEEDED(pEnum->GetNext(&pAcct))) { // Get the connection type for this account
if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn))) { // If the account is a RAS account, ask for the connectoid name
// and the account name.
if (dwConn == CONNECTION_TYPE_RAS) { pAcct->GetPropSz(AP_RAS_CONNECTOID, szConn, ARRAYSIZE(szConn)); pAcct->GetPropSz(AP_ACCOUNT_NAME, szAcct, ARRAYSIZE(szAcct)); wnsprintf(szMenu, ARRAYSIZE(szMenu), _T("%s (%s)"), PszEscapeMenuStringA(szAcct, szBuf, sizeof(szBuf) / sizeof(TCHAR)), PszEscapeMenuStringA(szConn, szConnQuoted, sizeof(szConnQuoted) / sizeof(TCHAR))); // Insert the menu item into the menu
ZeroMemory(&mii, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_TYPE; mii.fType = MFT_STRING | MFT_RADIOCHECK; mii.fState = MFS_ENABLED; mii.wID = ID_CONNECT_FIRST + cAcct; mii.dwItemData = (DWORD_PTR) pAcct; mii.dwTypeData = szMenu; pAcct->AddRef();
SideAssert(InsertMenuItem(hMenu, cAcct, TRUE, &mii)); cAcct++; } } SafeRelease(pAcct); }
SafeRelease(pEnum); }
if (hMenu) if(GetMenuItemCount(hMenu)) { *phMenu = hMenu; return (S_OK); } else { DestroyMenu(hMenu); return (E_FAIL); } else return (E_FAIL); }
//
// FUNCTION: CConnectionManager::FreeConnectMenu()
//
// PURPOSE: Frees the item data stored with the menu returned from
// GetConnectMenu().
//
// PARAMETERS:
// <in> hMenu - Handle of the menu to free.
//
void CConnectionManager::FreeConnectMenu(HMENU hMenu) { // Walk through the items on this menu and free the pointers stored in
// the item data.
MENUITEMINFO mii; int cItems = 0;
Assert(hMenu);
cItems = GetMenuItemCount(hMenu); for (int i = 0; i < cItems; i++) { mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA; mii.dwItemData = 0;
if (GetMenuItemInfo(hMenu, i, TRUE, &mii)) { Assert(mii.dwItemData);
if (mii.dwItemData) ((IImnAccount *) mii.dwItemData)->Release(); } }
DestroyMenu(hMenu); }
//
// FUNCTION: CConnectionManager::OnActivate()
//
// PURPOSE: Called whenever the browser receives a WM_ACTIVATE message.
// In response, we check the current state of our RAS connection
// to see if we are still connected / disconnected.
void CConnectionManager::OnActivate(BOOL fActive) { BOOL fOfflineChanged = FALSE; BOOL fOffline = FALSE;
if (fActive) { EnterCriticalSection(&m_cs); m_rConnInfo.state = CIS_REFRESH;
// Check to see if we've gone offline
if (m_fOffline != IsGlobalOffline()) { fOffline = m_fOffline = (!m_fOffline); fOfflineChanged = TRUE; }
LeaveCriticalSection(&m_cs);
// Do this outside of the critsec
if (fOfflineChanged) SendAdvise(CONNNOTIFY_WORKOFFLINE, (LPVOID) IntToPtr(fOffline)); } }
//
// FUNCTION: CConnectionManager::FillRasCombo()
//
// PURPOSE: This function enumerates the accounts in the account manager
// and builds a list of the RAS connections those accounts use.
// The function then inserts those connections in to the provided
// combobox.
//
// PARAMETERS:
// <in> hwndCombo - Handle of the combobox to fill
// <in> fIncludeNone - Inserts a string at the top "Don't dial a connection"
//
// RETURN VALUE:
// BOOL
//
BOOL CConnectionManager::FillRasCombo(HWND hwndCombo, BOOL fIncludeNone) { IImnEnumAccounts *pEnum = NULL; IImnAccount *pAcct = NULL; DWORD dwConn = 0; LPTSTR *rgszConn = NULL; TCHAR szConn[CCHMAX_CONNECTOID]; ULONG cAcct = 0; ULONG cConn = 0; BOOL fSucceeded = FALSE; ULONG ul;
LPRASENTRYNAME pEntry=NULL; DWORD dwSize, cEntries, dwError;
HRESULT hr = S_OK; int i;
EnterCriticalSection(&m_cs); #ifdef NEVER
// Find out how many accounts exist
m_pAcctMan->GetAccountCount(ACCT_NEWS, &cAcct); m_pAcctMan->GetAccountCount(ACCT_MAIL, &ul); cAcct += ul; m_pAcctMan->GetAccountCount(ACCT_DIR_SERV, &ul); cAcct += ul; if (cAcct == 0) { fSucceeded = TRUE; goto exit; }
// Allocate an array to hold the connection list
if (!MemAlloc((LPVOID*) &rgszConn, cAcct * sizeof(LPTSTR))) goto exit; ZeroMemory(rgszConn, cAcct * sizeof(LPTSTR)); // Get the enumerator from the account manager
if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum))) { pEnum->Reset();
// Walk through all the accounts
while (SUCCEEDED(pEnum->GetNext(&pAcct))) { // Get the connection type for this account
if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn))) { // If the account is a RAS account, ask for the connectoid name
// and the account name.
if (dwConn == CONNECTION_TYPE_RAS) { pAcct->GetPropSz(AP_RAS_CONNECTOID, szConn, ARRAYSIZE(szConn));
// Check to see if this connection has already been inserted into
// our list
for (ULONG k = 0; k < cConn; k++) { if (0 == lstrcmpi(szConn, rgszConn[k])) break; }
// If we didn't find it, we insert it
if (k >= cConn) { rgszConn[cConn] = StringDup(szConn); cConn++; } } } SafeRelease(pAcct); }
SafeRelease(pEnum); }
// Sort the list
int i, j, min; LPTSTR pszT; for (i = 0; i < (int) cConn; i++) { min = i; for (j = i + 1; j < (int) cConn; j++) if (0 > lstrcmpi(rgszConn[j], rgszConn[min])) min = j;
pszT = rgszConn[min]; rgszConn[min] = rgszConn[i]; rgszConn[i] = pszT; }
// Insert the items into the combo box
if (fIncludeNone) { AthLoadString(idsConnNoDial, szConn, ARRAYSIZE(szConn)); ComboBox_AddString(hwndCombo, szConn); }
for (i = 0; i < (int) cConn; i++) ComboBox_AddString(hwndCombo, rgszConn[i]);
#endif NEVER
// Make sure the RAS DLL is loaded before we try this
CHECKHR(hr = VerifyRasLoaded());
// Allocate RASENTRYNAME
dwSize = sizeof(RASENTRYNAME); CHECKHR(hr = HrAlloc((LPVOID*)&pEntry, dwSize)); // Ver stamp the entry
pEntry->dwSize = sizeof(RASENTRYNAME); cEntries = 0; dwError = RasEnumEntries(NULL, NULL, pEntry, &dwSize, &cEntries); if (dwError == ERROR_BUFFER_TOO_SMALL) { SafeMemFree(pEntry); CHECKHR(hr = HrAlloc((LPVOID *)&pEntry, dwSize)); pEntry->dwSize = sizeof(RASENTRYNAME); cEntries = 0; dwError = RasEnumEntries(NULL, NULL, pEntry, &dwSize, &cEntries); }
// Error ?
if (dwError) { hr = TrapError(IXP_E_RAS_ERROR); goto exit; }
// Insert the items into the combo box
if (fIncludeNone) { AthLoadString(idsConnNoDial, szConn, ARRAYSIZE(szConn)); ComboBox_AddString(hwndCombo, szConn); }
for (i = 0; i < (int) cEntries; i++) ComboBox_AddString(hwndCombo, pEntry[i].szEntryName);
fSucceeded = TRUE;
exit: if (rgszConn) { for (i = 0; i < (int) cConn; i++) SafeMemFree(rgszConn[i]); MemFree(rgszConn); }
SafeMemFree(pEntry);
LeaveCriticalSection(&m_cs); return (fSucceeded); }
//
// FUNCTION: CConnectionManager::DoStartupDial()
//
// PURPOSE: This function checks to see what the user's startup options
// are with respect to RAS and performs the actions required
// (dial, dialog, nada)
// PARAMETERS:
// <in> hwndParent - Handle to parent a dialog to
//
void CConnectionManager::DoStartupDial(HWND hwndParent) { DWORD dwStart; DWORD dw; DWORD dwReturn; TCHAR szConn[CCHMAX_CONNECTOID]; LPRASCONN pConnections = NULL; ULONG cConnections = 0; DWORD dwDialFlags = 0; DWORD dwLanFlags = 0;
// The first thing to do is figure out what the user's startup option if
dw = DwGetOption(OPT_DIALUP_START);
// If the user want's to do nothing, we're done
if (dw == START_NO_CONNECT) return;
//ConnectUsingIESettings(hwndParent, TRUE);
if (!m_fDialerUI) { m_fDialerUI = TRUE; // Check to see if we're working offline
if (IsGlobalOffline()) { if (IDYES == AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline), 0, MB_YESNO | MB_ICONEXCLAMATION )) { g_pConMan->SetGlobalOffline(FALSE); } else { goto DialerExit; } }
//We do not dial if there is an active connection already existing. Even if it is not the connection
//InternetDial would have dialed, if we had called. Heres why:
//1)We don't want to look into the registry to get the default connectoid.
//Thats why we call InternetDial with NULL and it dials the def connectoid if there is one set
//Otherwise it dials the first connectoid in the list.
//Since InternetDial figures out which connectoid to dial, we don't want to do all the work of figuring
//out if we are already connected to the connectoid we are going to dial.
//So we just do not dial even if there is one active connection.
if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections))) { if (cConnections > 0) goto DialerExit; }
dwDialFlags = INTERNET_AUTODIAL_FORCE_ONLINE;
if (VerifyMobilityPackLoaded() == S_OK) { if (!IsNetworkAlive(&dwLanFlags) || (!(dwLanFlags & NETWORK_ALIVE_LAN))) dwDialFlags |= INTERNET_DIAL_SHOW_OFFLINE; }
// Only one caller can be dialing the phone at a time.
if (WAIT_TIMEOUT == WaitForSingleObject(m_hMutexDial, 0)) { goto DialerExit; }
dwReturn = InternetDialA(hwndParent, NULL, dwDialFlags, &m_dwConnId, 0); if (dwReturn == 0) { m_rConnInfo.fConnected = TRUE; m_rConnInfo.fIStartedRas = TRUE; m_rConnInfo.fAutoDial = FALSE; m_rConnInfo.hRasConn = (HRASCONN)m_dwConnId; SendAdvise(CONNNOTIFY_CONNECTED, NULL); } else { if (dwReturn == ERROR_USER_DISCONNECTION) { SendAdvise(CONNNOTIFY_USER_CANCELLED, NULL); if (!!(dwDialFlags & INTERNET_DIAL_SHOW_OFFLINE)) SetGlobalOffline(TRUE); } else { DebugTrace("Error dialing: %d\n", GetLastError()); DebugTrace("InternetDial returned: %d\n", dwReturn); } }
DialerExit: m_fDialerUI = FALSE; SafeMemFree(pConnections); }
ReleaseMutex(m_hMutexDial); }
HRESULT CConnectionManager::GetDefConnectoid(LPTSTR szConn, DWORD dwSize) { HRESULT hr = E_FAIL; DWORD dwType; DWORD dwerr;
*szConn = '\0';
if ((dwerr = SHGetValue(HKEY_CURRENT_USER, c_szDefConnPath, c_szRegDefaultConnection, &dwType, szConn, &dwSize)) == ERROR_SUCCESS) { hr = S_OK; } return hr; }
//
// FUNCTION: CConnectionManager::VerifyRasLoaded()
//
// PURPOSE: Checks to see if this object has already loaded the RAS DLL.
// If not, then the DLL is loaded and the function pointers are
// fixed up.
//
// RETURN VALUE:
// S_OK - Loaded and ready, sir.
// hrRasInitFailure - Failed to load.
//
HRESULT CConnectionManager::VerifyRasLoaded(void) { // Locals
UINT uOldErrorMode;
// Protected
EnterCriticalSection(&m_cs);
// Check to see if we've tried this before
if (m_fRASLoadFailed) goto failure;
// Bug #20573 - Let's do a little voodoo here. On NT, it appears that they
// have a key in the registry to show which protocols are
// supported by RAS service. AKA - if this key doesn't exist,
// then RAS isn't installed. This may enable us to avoid some
// special bugs when RAS get's uninstalled on NT.
if (g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { HKEY hKey; const TCHAR c_szRegKeyRAS[] = _T("SOFTWARE\\Microsoft\\RAS");
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyRAS, 0, KEY_READ, &hKey)) { goto failure; }
RegCloseKey(hKey); }
// If dll is loaded, lets verify all of my function pointers
if (!m_hInstRas) { // Try loading Ras.
uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX); m_hInstRas = LoadLibrary(szRasDll); SetErrorMode(uOldErrorMode);
// Failure ?
if (!m_hInstRas) goto failure;
// Did we load it
m_pRasDial = (RASDIALPROC)GetProcAddress(m_hInstRas, szRasDial); m_pRasEnumConnections = (RASENUMCONNECTIONSPROC)GetProcAddress(m_hInstRas, szRasEnumConnections); m_pRasEnumEntries = (RASENUMENTRIESPROC)GetProcAddress(m_hInstRas, szRasEnumEntries); m_pRasGetConnectStatus = (RASGETCONNECTSTATUSPROC)GetProcAddress(m_hInstRas, szRasGetConnectStatus); m_pRasGetErrorString = (RASGETERRORSTRINGPROC)GetProcAddress(m_hInstRas, szRasGetErrorString); m_pRasHangup = (RASHANGUPPROC)GetProcAddress(m_hInstRas, szRasHangup); m_pRasSetEntryDialParams = (RASSETENTRYDIALPARAMSPROC)GetProcAddress(m_hInstRas, szRasSetEntryDialParams); m_pRasGetEntryDialParams = (RASGETENTRYDIALPARAMSPROC)GetProcAddress(m_hInstRas, szRasGetEntryDialParams); m_pRasEditPhonebookEntry = (RASEDITPHONEBOOKENTRYPROC)GetProcAddress(m_hInstRas, szRasEditPhonebookEntry); m_pRasGetEntryProperties = (RASGETENTRYPROPERTIES) GetProcAddress(m_hInstRas, szRasGetEntryProperties); }
if (!m_hInstRasDlg && FIsPlatformWinNT()) { // Try loading Ras.
uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX); m_hInstRasDlg = LoadLibrary(s_szRasDlgDll); SetErrorMode(uOldErrorMode);
// Failure ?
if (!m_hInstRasDlg) goto failure;
m_pRasDialDlg = (RASDIALDLGPROC)GetProcAddress(m_hInstRasDlg, s_szRasDialDlg); m_pRasEntryDlg = (RASENTRYDLGPROC)GetProcAddress(m_hInstRasDlg, s_szRasEntryDlg);
if (!m_pRasDialDlg || !m_pRasEntryDlg) goto failure; }
// Make sure all functions have been loaded
if (m_pRasDial && m_pRasEnumConnections && m_pRasEnumEntries && m_pRasGetConnectStatus && m_pRasGetErrorString && m_pRasHangup && m_pRasSetEntryDialParams && m_pRasGetEntryDialParams && m_pRasEditPhonebookEntry) { // Protected
LeaveCriticalSection(&m_cs);
// Success
return S_OK; }
failure: m_fRASLoadFailed = TRUE;
// Protected
LeaveCriticalSection(&m_cs);
// Otherwise, were hosed
return (hrRasInitFailure); }
//
// FUNCTION: CConnectionManager::EnumerateConnections()
//
// PURPOSE: Asks RAS for the list of active RAS connections.
//
// PARAMETERS:
// <out> ppRasConn - Returns an array of RASCONN structures for the
// list of active connections.
// <out> pcConnections - Number of structures in ppRasCon.
//
// RETURN VALUE:
// S_OK - The data in ppRasConn and pcConnections is valid
//
HRESULT CConnectionManager::EnumerateConnections(LPRASCONN *ppRasConn, ULONG *pcConnections) { // Locals
DWORD dw, dwSize; BOOL fResult=FALSE; HRESULT hr;
// Check Params
Assert(ppRasConn && pcConnections);
// Make sure RAS is loaded
if (FAILED(hr = VerifyRasLoaded())) return (hr);
// Init
*ppRasConn = NULL; *pcConnections = 0;
// Sizeof my buffer
dwSize = sizeof(RASCONN) * 2;
// Allocate enough for 1 ras connection info object
if (!MemAlloc((LPVOID *)ppRasConn, dwSize)) { TRAPHR(hrMemory); return (E_OUTOFMEMORY); }
ZeroMemory(*ppRasConn, dwSize);
// Buffer size
//(*ppRasConn)->dwSize = dwSize;
(*ppRasConn)->dwSize = sizeof(RASCONN);
// Enumerate ras connections
dw = RasEnumConnections(*ppRasConn, &dwSize, pcConnections);
// Not enough memory ?
if ((dw == ERROR_BUFFER_TOO_SMALL) || (dw == ERROR_NOT_ENOUGH_MEMORY)) { // Reallocate
if (!MemRealloc((LPVOID *)ppRasConn, dwSize)) { TRAPHR(hrMemory); goto exit; }
// Call enumerate again
*pcConnections = 0; (*ppRasConn)->dwSize = sizeof(RASCONN); dw = RasEnumConnections(*ppRasConn, &dwSize, pcConnections); }
// If still failed
if (dw) { AssertSz(FALSE, "RasEnumConnections failed"); return E_FAIL; } // Success
hr = S_OK; exit: // Done
return S_OK; }
//
// FUNCTION: CConnectionManager::StartRasDial()
//
// PURPOSE: Called when the client actually wants to establish a RAS
// connection.
//
// PARAMETERS:
// <in> hwndParent - Handle of the window to parent any UI
// <in> pszConnection - Name of the connection to establish
//
// RETURN VALUE:
// HRESULT
//
HRESULT CConnectionManager::StartRasDial(HWND hwndParent, LPTSTR pszConnection) { HRESULT hr = S_OK;
// Refresh ConnInfo
CHECKHR(hr = RefreshConnInfo()); // Check to see if we need to ask the user for information or credentials
// before we attempt to dial
CHECKHR (hr = RasLogon(hwndParent, pszConnection, FALSE));
// If we can use a system dialog for this, do so.
if (m_pRasDialDlg) { RASDIALDLG rdd = {0}; BOOL fRet;
rdd.dwSize = sizeof(rdd); rdd.hwndOwner = hwndParent;
#if (WINVER >= 0x401)
rdd.dwSubEntry = m_rdp.dwSubEntry; #else
rdd.dwSubEntry = 0; #endif
fRet = RasDialDlg(NULL, m_rdp.szEntryName, lstrlen(m_rdp.szPhoneNumber) ? m_rdp.szPhoneNumber : NULL, &rdd); if (fRet) { // Need to get the current connection handle
LPRASCONN pConnections = NULL; ULONG cConnections = 0;
if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections))) { for (UINT i = 0; i < cConnections; i++) { if (0 == lstrcmpi(pConnections[i].szEntryName, m_rdp.szEntryName)) { EnterCriticalSection(&m_cs); m_rConnInfo.hRasConn = pConnections[i].hrasconn; LeaveCriticalSection(&m_cs); break; } }
SafeMemFree(pConnections); }
hr = S_OK; } else hr = E_FAIL; } else { // We need to use our own RAS UI.
hr = (HRESULT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRasProgress), hwndParent, RasProgressDlgProc, (LPARAM) this); }
exit: // Done
return hr; }
//
// FUNCTION: CConnectionManager::RasLogon()
//
// PURPOSE: Attempts to load the RAS phonebook entry for the requested
// connection. If it doesn't exist or there isn't enough info,
// we present UI to the user to request that information.
//
// PARAMETERS:
// <in> hwnd - Handle to display UI over.
// <in> pszConnection - Name of the connection to load info for.
// <in> fForcePrompt - Forces the UI to be displayed.
//
// RETURN VALUE:
// S_OK - prdp contains the requested information
// hrGetDialParmasFailed - Couldn't get the phonebook entry from RAS
// hrUserCancel - User canceled
//
//
HRESULT CConnectionManager::RasLogon(HWND hwnd, LPTSTR pszConnection, BOOL fForcePrompt) { // Locals
HRESULT hr = S_OK; DWORD dwRasError;
// Do we need to prompt for logon information first ?
ZeroMemory(&m_rdp, sizeof(RASDIALPARAMS)); m_rdp.dwSize = sizeof(RASDIALPARAMS); StrCpyN(m_rdp.szEntryName, pszConnection, ARRAYSIZE(m_rdp.szEntryName));
// See if we can get the information from RAS
dwRasError = RasGetEntryDialParams(NULL, &m_rdp, &m_fSavePassword); if (dwRasError) { TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES]; AthLoadString(idshrGetDialParamsFailed, szRes, ARRAYSIZE(szRes)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, pszConnection); AthMessageBox(hwnd, MAKEINTRESOURCE(idsRasError), szBuf, 0, MB_OK | MB_ICONSTOP); hr = TRAPHR(hrGetDialParamsFailed); goto exit; }
// NT Supports the UI we need to display. If this exists, then
// RasDialDlg will take it from here
if (m_pRasDialDlg) { goto exit; }
// Do we need to get password / account information?
if (fForcePrompt || m_fSavePassword == FALSE || FIsStringEmpty(m_rdp.szUserName) || FIsStringEmpty(m_rdp.szPassword)) { // RAS Logon
hr = (HRESULT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRasLogon), hwnd, RasLogonDlgProc, (LPARAM) this); if (hr == hrUserCancel) { DisplayRasError(hwnd, hrUserCancel, 0); hr = hrUserCancel; goto exit; } }
exit: // Done
return hr; }
//
// FUNCTION: CConnectionManager::DisplayRasError()
//
// PURPOSE: Displays a message box describing the error that occured while
// dealing with connections etc.
//
// PARAMETERS:
// <in> hwnd - Handle of the window to display UI over
// <in> hrRasError - HRESULT to display the error for
// <in> dwRasError - Error code returned from RAS to display the error for
//
void CConnectionManager::DisplayRasError(HWND hwnd, HRESULT hrRasError, DWORD dwRasError) { // Locals
TCHAR szRasError[256]; BOOL fRasError = FALSE;
// No Error
if (SUCCEEDED(hrRasError)) return;
// Look up RAS error
if (dwRasError) { if (RasGetErrorString(dwRasError, szRasError, sizeof(szRasError)) == 0) fRasError = TRUE; else *szRasError = _T('\0'); }
// General Error
switch (hrRasError) { case hrUserCancel: break;
case hrMemory: AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(idsMemory), 0, MB_OK | MB_ICONSTOP); break;
case hrRasInitFailure: AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrRasInitFailure), 0, MB_OK | MB_ICONSTOP); break;
case hrRasDialFailure: if (fRasError) CombinedRasError(hwnd, HR_CODE(hrRasDialFailure), szRasError, dwRasError); else AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrRasDialFailure), 0, MB_OK | MB_ICONSTOP); break;
case hrRasServerNotFound: AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrRasServerNotFound), 0, MB_OK | MB_ICONSTOP); break;
case hrGetDialParamsFailed: AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrGetDialParamsFailed), 0, MB_OK | MB_ICONSTOP); break;
case E_FAIL: default: AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(idsRasErrorGeneral), 0, MB_OK | MB_ICONSTOP); break; }
}
//
// FUNCTION: CConnectionManager::PromptCloseConn()
//
// PURPOSE: Asks the user if they want to close the current connection or
// try to use it.
//
// PARAMETERS:
// <in> hwnd - Parent for the dialog
//
// RETURN VALUE:
// Returns the button that closed the dialog
//
UINT CConnectionManager::PromptCloseConnection(HWND hwnd) { RefreshConnInfo();
if (DwGetOption(OPT_DIALUP_WARN_SWITCH)) { if (0 == lstrcmpi(m_rConnInfo.szCurrentConnectionName, m_szConnectName)) return (idrgUseCurrent); else return (UINT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRasCloseConn), hwnd, RasCloseConnDlgProc, (LPARAM) this); } else return (idrgDialNew); } INT_PTR CALLBACK CConnectionManager::RasCloseConnDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Locals
CConnectionManager *pThis = NULL; TCHAR szRes[255], szMsg[255+RAS_MaxEntryName+1]; TCHAR szConn[CCHMAX_CONNECTOID + 2];
switch(uMsg) { case WM_INITDIALOG: // The LPARAM contains our this pointer
pThis = (CConnectionManager*) lParam; if (!pThis) { Assert(pThis); EndDialog(hwnd, E_FAIL); return (TRUE); }
// Center
CenterDialog(hwnd);
// Refresh Connection Info
pThis->RefreshConnInfo();
// Set Text
GetWindowText(GetDlgItem(hwnd, idcCurrentMsg), szRes, sizeof(szRes)/sizeof(TCHAR)); wnsprintf(szMsg, ARRAYSIZE(szMsg), szRes, PszEscapeMenuStringA(pThis->m_rConnInfo.szCurrentConnectionName, szConn, sizeof(szConn) / sizeof(TCHAR))); SetWindowText(GetDlgItem(hwnd, idcCurrentMsg), szMsg);
// Set control
GetWindowText(GetDlgItem(hwnd, idrgDialNew), szRes, sizeof(szRes)/sizeof(TCHAR)); wnsprintf(szMsg, ARRAYSIZE(szMsg), szRes, PszEscapeMenuStringA(pThis->m_szConnectName, szConn, sizeof(szConn) / sizeof(TCHAR))); SetWindowText(GetDlgItem(hwnd, idrgDialNew), szMsg);
// Set Default
CheckDlgButton(hwnd, idrgDialNew, TRUE); return (TRUE);
case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: { if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, idcDontWarnCheck))) { // If the user has this checked, we reset the "Warn before..." option
SetDwOption(OPT_DIALUP_WARN_SWITCH, 0, NULL, 0); } EndDialog(hwnd, IsDlgButtonChecked(hwnd, idrgDialNew) ? idrgDialNew : idrgUseCurrent); return (TRUE); }
case IDCANCEL: EndDialog(hwnd, IDCANCEL); return (TRUE); } return (TRUE); } return (FALSE); }
//
// FUNCTION: CConnectionMAanger::CombinedRasError()
//
// PURPOSE: <???>
//
// PARAMETERS:
// <???>
//
void CConnectionManager::CombinedRasError(HWND hwnd, UINT unids, LPTSTR pszRasError, DWORD dwRasError) { // Locals
TCHAR szRes[255], sz[30]; LPTSTR pszError=NULL;
// Load string
AthLoadString(unids, szRes, sizeof(szRes));
// Allocate memory for errors
DWORD cc = lstrlen(szRes) + lstrlen(pszRasError) + 100; pszError = SzStrAlloc(cc);
// Out of Memory ?
if (!pszError) AthMessageBox(hwnd, MAKEINTRESOURCE(idsRasError), szRes, 0, MB_OK | MB_ICONSTOP);
// Build Error message
else { AthLoadString(idsErrorText, sz, sizeof(sz)); wnsprintf(pszError, cc, "%s\n\n%s %d: %s", szRes, sz, dwRasError, pszRasError); AthMessageBox(hwnd, MAKEINTRESOURCE(idsRasError), pszError, 0, MB_OK | MB_ICONSTOP); MemFree(pszError); } }
//
// FUNCTION: CConnectionManager::RasHangupAndWait()
//
// PURPOSE: Hangs up on a RAS connection and waits for it to finish before
// returning.
//
// PARAMETERS:
// <in> hRasConn - Handle of the connection to hang up.
// <in> dwMaxWaitSeconds - Amount of time to wait.
//
// RETURN VALUE:
// TRUE if we disconnected, FALSE otherwise.
//
BOOL CConnectionManager::RasHangupAndWait(HRASCONN hRasConn, DWORD dwMaxWaitSeconds) { // Locals
RASCONNSTATUS rcs; DWORD dwTicks=GetTickCount();
// Check Params
if (!hRasConn) return 0;
// Make sure RAS is loaded
if (FAILED (VerifyRasLoaded())) return FALSE;
// Call Ras hangup
if (RasHangup(hRasConn)) return FALSE;
// Wait for connection to really close
ZeroMemory(&rcs, sizeof(RASCONNSTATUS)); rcs.dwSize = sizeof(RASCONNSTATUS); while (RasGetConnectStatus(hRasConn, &rcs) != ERROR_INVALID_HANDLE && rcs.rasconnstate != RASCS_Disconnected) { // Wait timeout
if (GetTickCount() - dwTicks >= dwMaxWaitSeconds * 1000) break;
// Sleep and yields
Sleep(0); }
// Wait 2 seconds for modem to reset
Sleep(2000);
// Done
return TRUE; } DWORD CConnectionManager::InternetHangUpAndWait(DWORD_PTR hRasConn, DWORD dwMaxWaitSeconds) { // Locals
RASCONNSTATUS rcs; DWORD dwTicks=GetTickCount(); DWORD dwret;
// Check Params
if (!hRasConn) return 0;
// Make sure RAS is loaded
if (FAILED (VerifyRasLoaded())) return FALSE;
dwret = InternetHangUp(m_dwConnId, 0); if (dwret) { DebugTrace("InternetHangup failed: %d\n", dwret); goto exit; }
// Wait for connection to really close
ZeroMemory(&rcs, sizeof(RASCONNSTATUS)); rcs.dwSize = sizeof(RASCONNSTATUS); while (RasGetConnectStatus((HRASCONN)hRasConn, &rcs) != ERROR_INVALID_HANDLE && rcs.rasconnstate != RASCS_Disconnected) { // Wait timeout
if (GetTickCount() - dwTicks >= dwMaxWaitSeconds * 1000) break;
// Sleep and yields
Sleep(0); }
// Wait 2 seconds for modem to reset
Sleep(2000);
exit: return dwret; }
INT_PTR CALLBACK CConnectionManager::RasLogonDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Locals
TCHAR sz[255], szText[255 + RAS_MaxEntryName + 1]; DWORD dwRasError; CConnectionManager *pThis = (CConnectionManager *)GetWndThisPtr(hwnd);
switch (uMsg) { case WM_INITDIALOG: // Get lparam
pThis = (CConnectionManager *)lParam; if (!pThis) { Assert (FALSE); EndDialog(hwnd, E_FAIL); return (TRUE); }
// Center the window
CenterDialog(hwnd);
// Get Window Title
GetWindowText(hwnd, sz, sizeof(sz)); wnsprintf(szText, ARRAYSIZE(szText), sz, pThis->m_szConnectName); SetWindowText(hwnd, szText);
// Word Default
AthLoadString(idsDefault, sz, sizeof(sz)); // Set Fields
Edit_LimitText(GetDlgItem(hwnd, ideUserName), UNLEN); Edit_LimitText(GetDlgItem(hwnd, idePassword), PWLEN); Edit_LimitText(GetDlgItem(hwnd, idePhone), RAS_MaxPhoneNumber); SetDlgItemText(hwnd, ideUserName, pThis->m_rdp.szUserName); SetDlgItemText(hwnd, idePassword, pThis->m_rdp.szPassword);
if (FIsStringEmpty(pThis->m_rdp.szPhoneNumber)) SetDlgItemText(hwnd, idePhone, sz); else SetDlgItemText(hwnd, idePhone, pThis->m_rdp.szPhoneNumber);
CheckDlgButton(hwnd, idchSavePassword, pThis->m_fSavePassword);
// Save pRas
SetWndThisPtr(hwnd, pThis); return 1;
case WM_COMMAND: switch(GET_WM_COMMAND_ID(wParam, lParam)) { case idbEditConnection: pThis->EditPhonebookEntry(hwnd, (pThis->m_szConnectName)); return 1;
case IDCANCEL: EndDialog(hwnd, hrUserCancel); return 1;
case IDOK: AthLoadString(idsDefault, sz, sizeof(sz));
// Set Fields
GetDlgItemText(hwnd, ideUserName, pThis->m_rdp.szUserName, UNLEN+1); GetDlgItemText(hwnd, idePassword, pThis->m_rdp.szPassword, PWLEN+1);
GetDlgItemText(hwnd, idePhone, pThis->m_rdp.szPhoneNumber, RAS_MaxPhoneNumber+1); if (lstrcmp(pThis->m_rdp.szPhoneNumber, sz) == 0) *pThis->m_rdp.szPhoneNumber = _T('\0'); pThis->m_fSavePassword = IsDlgButtonChecked(hwnd, idchSavePassword);
// Save Dial Parameters
dwRasError = (pThis->m_pRasSetEntryDialParams)(NULL, &(pThis->m_rdp), !(pThis->m_fSavePassword)); if (dwRasError) { pThis->DisplayRasError(hwnd, hrSetDialParamsFailed, dwRasError); return 1; } EndDialog(hwnd, S_OK); return 1; } break;
case WM_DESTROY: SetWndThisPtr (hwnd, NULL); break; } return 0; }
INT_PTR CALLBACK CConnectionManager::RasProgressDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Locals
CConnectionManager *pThis = (CConnectionManager *) GetWndThisPtr(hwnd); TCHAR szText[255+RAS_MaxEntryName+1], sz[255]; static TCHAR s_szCancel[40]; static UINT s_unRasEventMsg=0; static BOOL s_fDetails=FALSE; static RECT s_rcDialog; static BOOL s_fAuthStarted=FALSE; DWORD dwRasError, cyDetails; RASCONNSTATUS rcs; RECT rcDetails, rcDlg; switch (uMsg) { case WM_INITDIALOG: // Get lparam
pThis = (CConnectionManager *)lParam; if (!pThis) { Assert (FALSE); EndDialog(hwnd, E_FAIL); return 1; }
// Save this pointer
SetWndThisPtr (hwnd, pThis);
// Save Original Size of the dialog
GetWindowRect (hwnd, &s_rcDialog);
// Refresh Connection Info
pThis->RefreshConnInfo();
// Details enabled
s_fDetails = DwGetOption(OPT_RASCONNDETAILS);
// Hide details drop down
if (s_fDetails == FALSE) { // Hid
GetWindowRect (GetDlgItem (hwnd, idcSplitter), &rcDetails);
// Height of details
cyDetails = s_rcDialog.bottom - rcDetails.top; // Re-size
MoveWindow (hwnd, s_rcDialog.left, s_rcDialog.top, s_rcDialog.right - s_rcDialog.left, s_rcDialog.bottom - s_rcDialog.top - cyDetails - 1, FALSE); } else { AthLoadString (idsHideDetails, sz, sizeof (sz)); SetWindowText (GetDlgItem (hwnd, idbDet), sz); }
// Get registered RAS event message id
s_unRasEventMsg = RegisterWindowMessageA(RASDIALEVENT); if (s_unRasEventMsg == 0) s_unRasEventMsg = WM_RASDIALEVENT;
// Center the window
CenterDialog (hwnd); SetForegroundWindow(hwnd);
// Get Window Title
GetWindowText(hwnd, sz, sizeof(sz)); wnsprintf(szText, ARRAYSIZE(szText), sz, pThis->m_szConnectName); SetWindowText(hwnd, szText);
// Dialog Xxxxxxx.....
if (pThis->m_rdp.szPhoneNumber[0]) { AthLoadString(idsRas_Dialing_Param, sz, sizeof(sz)/sizeof(TCHAR)); wnsprintf(szText, ARRAYSIZE(szText), sz, pThis->m_rdp.szPhoneNumber); } else AthLoadString(idsRas_Dialing, szText, ARRAYSIZE(szText));
SetWindowText(GetDlgItem(hwnd, ideProgress), szText);
// Get Cancel Text
GetWindowText(GetDlgItem(hwnd, IDCANCEL), s_szCancel, sizeof(s_szCancel));
// Give the list box and hscroll
SendMessage(GetDlgItem(hwnd, idlbDetails), LB_SETHORIZONTALEXTENT, 600, 0);
// Dial the connection
pThis->m_rConnInfo.hRasConn = NULL; dwRasError = (pThis->m_pRasDial)(NULL, NULL, &(pThis->m_rdp), 0xFFFFFFFF, hwnd, &(pThis->m_rConnInfo.hRasConn)); if (dwRasError) { pThis->FailedRasDial(hwnd, hrRasDialFailure, dwRasError); if (!pThis->LogonRetry(hwnd, s_szCancel)) { SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,IDCANCEL), NULL); return 1; } } return 1;
case WM_COMMAND: switch(GET_WM_COMMAND_ID(wParam,lParam)) { case IDCANCEL: SetDwOption(OPT_RASCONNDETAILS, s_fDetails, NULL, 0); EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE); if (pThis) pThis->FailedRasDial(hwnd, hrUserCancel, 0); EndDialog(hwnd, hrUserCancel); return 1;
case idbDet: // Get current location of the dialog
GetWindowRect (hwnd, &rcDlg);
// If currently hidden
if (s_fDetails == FALSE) { // Re-size
MoveWindow (hwnd, rcDlg.left, rcDlg.top, s_rcDialog.right - s_rcDialog.left, s_rcDialog.bottom - s_rcDialog.top, TRUE);
AthLoadString (idsHideDetails, sz, sizeof (sz)); SetWindowText (GetDlgItem (hwnd, idbDet), sz); s_fDetails = TRUE; }
else { // Size of details
GetWindowRect (GetDlgItem (hwnd, idcSplitter), &rcDetails); cyDetails = rcDlg.bottom - rcDetails.top; MoveWindow (hwnd, rcDlg.left, rcDlg.top, s_rcDialog.right - s_rcDialog.left, s_rcDialog.bottom - s_rcDialog.top - cyDetails - 1, TRUE);
AthLoadString (idsShowDetails, sz, sizeof (sz)); SetWindowText (GetDlgItem (hwnd, idbDet), sz); s_fDetails = FALSE; } break; } break;
case WM_DESTROY: SetWndThisPtr (hwnd, NULL); break;
case CM_INTERNALRECONNECT: if (!pThis->LogonRetry(hwnd, s_szCancel)) { SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,IDCANCEL), NULL); return 1; } break;
default: if (!pThis) break;
pThis->RefreshConnInfo();
if (uMsg == s_unRasEventMsg) { HWND hwndLB = GetDlgItem(hwnd, idlbDetails);
// Error ?
if (lParam) { // Disconnected
AthLoadString(idsRASCS_Disconnected, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz);
// Log Error
TCHAR szRasError[512]; if ((pThis->m_pRasGetErrorString)((UINT) lParam, szRasError, sizeof(szRasError)) == 0) { TCHAR szError[512 + 255]; AthLoadString(idsErrorText, sz, sizeof(sz)); wnsprintf(szError, ARRAYSIZE(szError), "%s %d: %s", sz, lParam, szRasError); ListBox_AddString(hwndLB, szError); }
// Select last item
SendMessage(hwndLB, LB_SETCURSEL, ListBox_GetCount(hwndLB)-1, 0);
// Show Error
pThis->FailedRasDial(hwnd, hrRasDialFailure, (DWORD) lParam);
// Re logon
PostMessage(hwnd, CM_INTERNALRECONNECT, 0, 0);
}
// Otherwise, process RAS event
else { switch(wParam) { case RASCS_OpenPort: AthLoadString(idsRASCS_OpenPort, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_PortOpened: AthLoadString(idsRASCS_PortOpened, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_ConnectDevice: rcs.dwSize = sizeof(RASCONNSTATUS); if (pThis->m_rConnInfo.hRasConn && (pThis->m_pRasGetConnectStatus)(pThis->m_rConnInfo.hRasConn, &rcs) == 0) { AthLoadString(idsRASCS_ConnectDevice, sz, sizeof(sz)/sizeof(TCHAR)); wnsprintf(szText, ARRAYSIZE(szText), sz, rcs.szDeviceName, rcs.szDeviceType); ListBox_AddString(hwndLB, szText); } break;
case RASCS_DeviceConnected: rcs.dwSize = sizeof(RASCONNSTATUS); if (pThis->m_rConnInfo.hRasConn && (pThis->m_pRasGetConnectStatus)(pThis->m_rConnInfo.hRasConn, &rcs) == 0) { AthLoadString(idsRASCS_DeviceConnected, sz, sizeof(sz)/sizeof(TCHAR)); wnsprintf(szText, ARRAYSIZE(szText), sz, rcs.szDeviceName, rcs.szDeviceType); ListBox_AddString(hwndLB, szText); } break;
case RASCS_AllDevicesConnected: AthLoadString(idsRASCS_AllDevicesConnected, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_Authenticate: if (s_fAuthStarted == FALSE) { AthLoadString(idsRas_Authentication, sz, sizeof(sz)/sizeof(TCHAR)); SetWindowText(GetDlgItem(hwnd, ideProgress), sz); ListBox_AddString(hwndLB, sz); s_fAuthStarted = TRUE; } break;
case RASCS_AuthNotify: rcs.dwSize = sizeof(RASCONNSTATUS); if (pThis->m_rConnInfo.hRasConn && (pThis->m_pRasGetConnectStatus)(pThis->m_rConnInfo.hRasConn, &rcs) == 0) { AthLoadString(idsRASCS_AuthNotify, sz, sizeof(sz)/sizeof(TCHAR)); wnsprintf(szText, ARRAYSIZE(szText), sz, rcs.dwError); ListBox_AddString(hwndLB, szText); if (rcs.dwError) { pThis->FailedRasDial(hwnd, hrRasDialFailure, rcs.dwError); PostMessage(hwnd, CM_INTERNALRECONNECT, 0, 0); } } break;
case RASCS_AuthRetry: AthLoadString(idsRASCS_AuthRetry, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_AuthCallback: AthLoadString(idsRASCS_AuthCallback, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_AuthChangePassword: AthLoadString(idsRASCS_AuthChangePassword, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_AuthProject: AthLoadString(idsRASCS_AuthProject, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_AuthLinkSpeed: AthLoadString(idsRASCS_AuthLinkSpeed, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_AuthAck: AthLoadString(idsRASCS_AuthAck, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_ReAuthenticate: AthLoadString(idsRas_Authenticated, sz, sizeof(sz)/sizeof(TCHAR)); SetWindowText(GetDlgItem(hwnd, ideProgress), sz); AthLoadString(idsRASCS_Authenticated, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_PrepareForCallback: AthLoadString(idsRASCS_PrepareForCallback, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_WaitForModemReset: AthLoadString(idsRASCS_WaitForModemReset, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_WaitForCallback: AthLoadString(idsRASCS_WaitForCallback, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_Projected: AthLoadString(idsRASCS_Projected, sz, sizeof(sz)/sizeof(TCHAR)); ListBox_AddString(hwndLB, sz); break;
case RASCS_Disconnected: AthLoadString(idsRASCS_Disconnected, sz, sizeof(sz)/sizeof(TCHAR)); SetWindowText(GetDlgItem(hwnd, ideProgress), sz); ListBox_AddString(hwndLB, sz); pThis->FailedRasDial(hwnd, hrRasDialFailure, 0); PostMessage(hwnd, CM_INTERNALRECONNECT, 0, 0); break;
case RASCS_Connected: SetDwOption(OPT_RASCONNDETAILS, s_fDetails, NULL, 0); AthLoadString(idsRASCS_Connected, sz, sizeof(sz)/sizeof(TCHAR)); SetWindowText(GetDlgItem(hwnd, ideProgress), sz); ListBox_AddString(hwndLB, sz); EndDialog(hwnd, S_OK); break; }
// Select last lb item
SendMessage(hwndLB, LB_SETCURSEL, ListBox_GetCount(hwndLB)-1, 0); } return 1; } break; }
// Done
return 0; }
BOOL CConnectionManager::LogonRetry(HWND hwnd, LPTSTR pszCancel) { // Locals
DWORD dwRasError;
// Refresh
RefreshConnInfo();
// Reset Cancel button
SetWindowText(GetDlgItem(hwnd, IDCANCEL), pszCancel);
// Empty the listbox
ListBox_ResetContent(GetDlgItem(hwnd, idlbDetails));
while(1) { // If failed...
if (FAILED(RasLogon(hwnd, m_szConnectName, TRUE))) return FALSE;
// Dial the connection
m_rConnInfo.hRasConn = NULL; dwRasError = RasDial(NULL, NULL, &m_rdp, 0xFFFFFFFF, hwnd, &m_rConnInfo.hRasConn); if (dwRasError) { FailedRasDial(hwnd, hrRasDialFailure, dwRasError); continue; }
// Success
break; }
// Done
return TRUE; }
// =====================================================================================
// CConnectionManager::FailedRasDial
// =====================================================================================
VOID CConnectionManager::FailedRasDial(HWND hwnd, HRESULT hrRasError, DWORD dwRasError) { // Locals
TCHAR sz[255];
// Refresh
RefreshConnInfo();
// Hangup the connection
if (m_rConnInfo.hRasConn) RasHangupAndWait(m_rConnInfo.hRasConn, DEF_HANGUP_WAIT);
// Disconnected
AthLoadString(idsRASCS_Disconnected, sz, sizeof(sz)/sizeof(TCHAR)); SetWindowText(GetDlgItem(hwnd, ideProgress), sz);
// Save dwRasError
DisplayRasError(hwnd, hrRasError, dwRasError);
// NULL it
m_rConnInfo.hRasConn = NULL;
// Change dialog button to OK
AthLoadString(idsOK, sz, sizeof(sz)/sizeof(TCHAR)); SetWindowText(GetDlgItem(hwnd, IDCANCEL), sz); }
DWORD CConnectionManager::EditPhonebookEntry(HWND hwnd, LPTSTR pszEntryName) { if (FAILED(VerifyRasLoaded())) return (DWORD)E_FAIL;
if (FIsPlatformWinNT() && m_hInstRasDlg && m_pRasEntryDlg) { RASENTRYDLG info;
ZeroMemory(&info, sizeof(RASENTRYDLG)); info.dwSize = sizeof(RASENTRYDLG); info.hwndOwner = hwnd;
m_pRasEntryDlg(NULL, pszEntryName, &info); return info.dwError; } else { return RasEditPhonebookEntry(hwnd, NULL, pszEntryName); } }
//
// FUNCTION: CConnectionNotify::SendAdvise()
//
// PURPOSE: Sends the specified notification to all the clients that have
// requested notifications.
//
// PARAMETERS:
// <in> nCode - Notification code to send.
// <in> pvData - Data to send with the notificaiton. Can be NULL.
//
void CConnectionManager::SendAdvise(CONNNOTIFY nCode, LPVOID pvData) { if (nCode == CONNNOTIFY_CONNECTED) DoOfflineTransactions();
// Loop through each interface and send the notification
EnterCriticalSection(&m_cs);
NOTIFYHWND *pTemp = m_pNotifyList; while (pTemp) { Assert(IsWindow(pTemp->hwnd)); DWORD dwThread = GetCurrentThreadId(); PostMessage(pTemp->hwnd, CM_NOTIFY, (WPARAM) nCode, (LPARAM) pvData); pTemp = pTemp->pNext; }
LeaveCriticalSection(&m_cs); }
void CConnectionManager::FreeNotifyList(void) { // Loop through the notify windows we own
NOTIFYHWND *pTemp;
while (m_pNotifyList) { // Get the list of notify callbacks for this window
if (IsWindow(m_pNotifyList->hwnd)) { NOTIFYLIST *pList = (NOTIFYLIST *) GetWindowLongPtr(m_pNotifyList->hwnd, GWLP_USERDATA); NOTIFYLIST *pListT;
// Loop through the callbacks freeing each one
while (pList) { pListT = pList->pNext; SafeMemFree(pList); pList = pListT; }
SetWindowLong(m_pNotifyList->hwnd, GWLP_USERDATA, NULL);
RemoveProp(m_pNotifyList->hwnd, NOTIFY_HWND); if (GetCurrentThreadId() == GetWindowThreadProcessId(m_pNotifyList->hwnd, NULL)) { DestroyWindow(m_pNotifyList->hwnd); } else PostMessage(m_pNotifyList->hwnd, WM_CLOSE, 0, 0L); }
pTemp = m_pNotifyList; m_pNotifyList = m_pNotifyList->pNext; SafeMemFree(pTemp); } }
LRESULT CALLBACK CConnectionManager::NotifyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { //CConnectionManager *pThis = (CConnectionManager *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
CConnectionManager *pThis = (CConnectionManager *)GetProp(hwnd, NOTIFY_HWND);
// If we're idle, then we should not process any notifications
if (uMsg != WM_NCCREATE && !pThis) return (DefWindowProc(hwnd, uMsg, wParam, lParam));
switch (uMsg) { case WM_NCCREATE: pThis = (CConnectionManager *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
//SetWindowLong(hwnd, GWLP_USERDATA, (LONG) pThis);
SetProp(hwnd, NOTIFY_HWND, (HANDLE)pThis); return (TRUE); case CM_NOTIFY: // This doesn't need to be critsec'd since the message is sent from
// within a critsec.
NOTIFYLIST *pList = (NOTIFYLIST *)GetWindowLongPtr(hwnd, GWLP_USERDATA); while (pList) { pList->pNotify->OnConnectionNotify((CONNNOTIFY) wParam, (LPVOID) lParam, pThis); pList = pList->pNext; }
return (0); }
return DefWindowProc(hwnd, uMsg, wParam, lParam); }
HRESULT CConnectionManager::GetDefaultConnection(IImnAccount *pAccount, IImnAccount **ppDefault) { TCHAR szDefault[CCHMAX_ACCOUNT_NAME]; ACCTTYPE acctType; HRESULT hr = S_OK;
// Get the type of account from the original account
if (FAILED(hr = pAccount->GetAccountType(&acctType))) { // How can an account have no account type?
Assert(FALSE); return (hr); }
// Ask the account manager for the default account of this type
if (FAILED(hr = g_pAcctMan->GetDefaultAccount(acctType, ppDefault))) { // No default account of this type?
Assert(FALSE); return (hr); }
return (S_OK); }
BOOL CConnectionManager::IsConnectionUsed(LPTSTR pszConn) { IImnEnumAccounts *pEnum = NULL; IImnAccount *pAcct = NULL; DWORD dwConn = 0; TCHAR szConn[CCHMAX_CONNECTOID]; BOOL fFound = FALSE;
// Get the enumerator from the account manager
if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum))) { pEnum->Reset();
// Walk through all the accounts
while (!fFound && SUCCEEDED(pEnum->GetNext(&pAcct))) { // Get the connection type for this account
if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn))) { // If the account is a RAS account, ask for the connectoid name
// and the account name.
if (dwConn == CONNECTION_TYPE_RAS) { pAcct->GetPropSz(AP_RAS_CONNECTOID, szConn, ARRAYSIZE(szConn));
// Check to see if this connection matches
if (0 == lstrcmpi(szConn, pszConn)) { fFound = TRUE; } } } SafeRelease(pAcct); } SafeRelease(pEnum); }
return (fFound); }
HRESULT CConnectionManager::ConnectActual(LPTSTR pszRasConn, HWND hwndParent, BOOL fShowUI) { HRESULT hr;
StrCpyN(m_szConnectName, pszRasConn, ARRAYSIZE(m_szConnectName));
// RefreshConnInfo
CHECKHR(hr = RefreshConnInfo()); // Make sure the RAS DLL is loaded before we try this
if (FAILED(VerifyRasLoaded())) { hr = HR_E_UNINITIALIZED; goto exit; } // Check to see if we even can connect
hr = CanConnectActual(pszRasConn); // If we can connect using the current connection, return success
if (S_OK == hr) { m_rConnInfo.fConnected = TRUE; hr = S_OK; goto exit; }
// There is another connection already established ask the user if they
// want to change.
if (!m_fDialerUI) { m_fDialerUI = TRUE;
if (E_FAIL == hr) { UINT uAnswer;
uAnswer = idrgUseCurrent;
// Check to see if this a voodoo Connection Manager autodialer thing
if (!ConnectionManagerVoodoo(pszRasConn)) { if (fShowUI) uAnswer = PromptCloseConnection(hwndParent); // The user canceled from the dialog. Therefore we give up.
if (IDCANCEL == uAnswer || IDNO == uAnswer) { hr = hrUserCancel; goto exit; } // The user said they wanted to hang up and dial a new connection.
else if (idrgDialNew == uAnswer || IDYES == uAnswer) { Disconnect(hwndParent, fShowUI, TRUE, FALSE); } // The user said to try to use the current connection.
else if (idrgUseCurrent == uAnswer) { // Who are we to tell the user what to do...
//Save the conn info so we can return true for this connection in CanConnectActual
AddToConnList(pszRasConn);
// Send a connect notification since we are getting connected and then return
hr = S_OK; goto NotifyAndExit; } } } else { //I don't see any reason as to why this is there.
// If we started RAS, then we can close it on a whim.
Disconnect(hwndParent, fShowUI, FALSE, FALSE); }
// Only one caller can be dialing the phone at a time.
if (WAIT_TIMEOUT == WaitForSingleObject(m_hMutexDial, 0)) { hr = HR_E_DIALING_INPROGRESS; goto exit; }
if (S_FALSE == (hr = DoAutoDial(hwndParent, pszRasConn, TRUE))) { DWORD dwReturn; DWORD dwLanFlags = 0; DWORD dwDialFlags = 0;
dwDialFlags = INTERNET_AUTODIAL_FORCE_ONLINE;
if (VerifyMobilityPackLoaded() == S_OK) { if (!IsNetworkAlive(&dwLanFlags) || (!(dwLanFlags & NETWORK_ALIVE_LAN))) dwDialFlags |= INTERNET_DIAL_SHOW_OFFLINE; }
dwReturn = InternetDialA(hwndParent, pszRasConn, dwDialFlags, &m_dwConnId, 0); /*
// Dial the new connection
if (SUCCEEDED(hr = StartRasDial(hwndParent, pszRasConn))) */ if (dwReturn == 0) { m_rConnInfo.fConnected = TRUE; m_rConnInfo.fIStartedRas = TRUE; m_rConnInfo.fAutoDial = FALSE; m_rConnInfo.hRasConn = (HRASCONN)m_dwConnId; StrCpyN(m_rConnInfo.szCurrentConnectionName, pszRasConn, ARRAYSIZE(m_rConnInfo.szCurrentConnectionName)); hr = S_OK; } else { if (dwReturn == ERROR_USER_DISCONNECTION) { hr = HR_E_USER_CANCEL_CONNECT; if (!!(dwDialFlags & INTERNET_DIAL_SHOW_OFFLINE)) SetGlobalOffline(TRUE); } else { DebugTrace("Error dialing: %d\n", GetLastError()); hr = E_FAIL; } } }
ReleaseMutex(m_hMutexDial);
NotifyAndExit: // Send the advise after we leave the critsec to make sure we don't deadlock
if (hr == S_OK) { SendAdvise(CONNNOTIFY_CONNECTED, NULL); } exit: m_fDialerUI = FALSE; }
return (hr); }
HRESULT CConnectionManager::CanConnectActual(LPTSTR pszRasConn) { LPRASCONN pConnections = NULL; ULONG cConnections = 0; BOOL fFound = 0; HRESULT hr = E_FAIL; TCHAR pszCurConn[CCHMAX_CONNECTOID]; DWORD dwFlags; //Look in our Conection list first
hr = SearchConnList(pszRasConn); if (hr == S_OK) return hr; // Make sure the RAS DLL is loaded before we try this
if (FAILED(VerifyRasLoaded())) { hr = HR_E_UNINITIALIZED; goto exit; }
// Find out what we're currently connected to
if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections))) { // If no connections exist, then just exit
if (0 == cConnections) { SafeMemFree(pConnections); hr = S_FALSE; goto exit; } // Walk through the existing connections and see if we can find the
// one we're looking for.
for (ULONG i = 0; i < cConnections; i++) { if (0 == lstrcmpi(pszRasConn, pConnections[i].szEntryName)) { // Found it. Return success.
fFound = TRUE; break; } } // Free the list of connections returned from the enumerator
SafeMemFree(pConnections); hr = (fFound ? S_OK : E_FAIL); goto exit; } exit:
if ((hr != S_OK) && (m_fDialerUI)) hr = HR_E_DIALING_INPROGRESS;
return (hr); }
INT_PTR CALLBACK CConnectionManager::RasStartupDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Locals
CConnectionManager *pThis = (CConnectionManager *) GetWndThisPtr(hwnd); TCHAR szConn[CCHMAX_CONNECTOID]; DWORD dwOpt = OPT_DIALUP_LAST_START; switch (uMsg) { case WM_INITDIALOG: pThis = (CConnectionManager *)lParam; if (!pThis) { Assert (FALSE); EndDialog(hwnd, E_FAIL); return 1; }
// Save this pointer
SetWndThisPtr (hwnd, pThis);
// Fill in the combo box
pThis->FillRasCombo(GetDlgItem(hwnd, idcDialupCombo), TRUE);
// If there are no RAS connections, then don't show the dialog
if (ComboBox_GetCount(GetDlgItem(hwnd, idcDialupCombo)) <= 1) { EndDialog(hwnd, 0); return (TRUE); }
// If the reason that we're in this dialog is because the user usually autodial's
// on startup but is now offline, then we should display the normal autodial
// connectoid
if (START_CONNECT == DwGetOption(OPT_DIALUP_START)) dwOpt = OPT_DIALUP_CONNECTION;
// Initialize the combo box to the last connection
*szConn = 0; GetOption(dwOpt, szConn, ARRAYSIZE(szConn)); if (0 != *szConn) { // If we can't find it any longer, then according to the spec, we're
// supposed to default to the "Ask me" option
if (CB_ERR == ComboBox_SelectString(GetDlgItem(hwnd, idcDialupCombo), -1, szConn)) { ComboBox_SetCurSel(GetDlgItem(hwnd, idcDialupCombo), 0); } } else ComboBox_SetCurSel(GetDlgItem(hwnd, idcDialupCombo), 0); CenterDialog(hwnd); return (TRUE);
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: // Get the connection name from the combo box
ComboBox_GetText(GetDlgItem(hwnd, idcDialupCombo), szConn, ARRAYSIZE(szConn)); // Check to see if it's the "Don't dial..." string
TCHAR szRes[CCHMAX_STRINGRES]; AthLoadString(idsConnNoDial, szRes, ARRAYSIZE(szRes));
if (0 == lstrcmp(szRes, szConn)) { // It's the don't dial string, so clear the history in the registry
SetOption(OPT_DIALUP_LAST_START, _T(""), sizeof(TCHAR), NULL, 0);
// See if the user checked the "Set as default..."
if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, idcDefaultCheck))) { // If don't dial is set as default, we clear the startup prompt option
SetDwOption(OPT_DIALUP_START, START_NO_CONNECT, NULL, 0); } } else { // Save this connection in the history
SetOption(OPT_DIALUP_LAST_START, szConn, lstrlen(szConn) + 1, NULL, 0); if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, idcDefaultCheck))) { // If the user want's this as default, then we change the startup
// option to auto connect to this connection.
SetDwOption(OPT_DIALUP_START, START_CONNECT, NULL, 0); SetOption(OPT_DIALUP_CONNECTION, szConn, lstrlen(szConn) + 1, NULL, 0); }
// Dial the phone
pThis->ConnectActual(szConn, hwnd, FALSE); }
EndDialog(hwnd, 0); return (TRUE);
case IDCANCEL: EndDialog(hwnd, 0); return (TRUE); } break; case WM_CLOSE: SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0); return (TRUE); }
return (FALSE); }
//-------------------------------------------------------------------------------------------
// Function: FIsPlatformWinNT() - checks if we are running on NT or Win95
//-------------------------------------------------------------------------------------------
BOOL FIsPlatformWinNT() { return (g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); }
HRESULT CConnectionManager::RefreshConnInfo(BOOL fSendAdvise) { // Locals
HRESULT hr=S_OK; LPRASCONN pConnections=NULL; ULONG cConnections=0; BOOL fFound=FALSE; ULONG i;
// Thread Safety
EnterCriticalSection(&m_cs);
// No Refresh needed
if (CIS_REFRESH != m_rConnInfo.state) goto exit;
// Set this here to prevent an infinite loop and thus a stack fault.
m_rConnInfo.state = CIS_CLEAN;
// Make sure the RAS DLL is loaded before we try this
CHECKHR(hr = VerifyRasLoaded());
// Find out what we're currently connected to
CHECKHR(hr = EnumerateConnections(&pConnections, &cConnections));
// Walk through the existing connections and see if we can find the
// one we're looking for.
for (i = 0; i < cConnections; i++) { // if (m_rConnInfo.hRasConn == pConnections[i].hrasconn)
//To get around a problem in ConnectActual when we dial using InternetDial
if (lstrcmp(m_rConnInfo.szCurrentConnectionName, pConnections[i].szEntryName) == 0) { // Found it. Return success.
fFound = TRUE; m_rConnInfo.fConnected = TRUE; m_rConnInfo.fIStartedRas = TRUE; m_rConnInfo.hRasConn = pConnections[0].hrasconn; m_dwConnId = (DWORD_PTR) m_rConnInfo.hRasConn;
break; } }
// If we didn't find our connection
if (!fFound) { // The user hung up. We need to put ourselves in a disconnected
// state.
if (cConnections == 0) { Disconnect(NULL, FALSE, TRUE, FALSE); } else { StrCpyN(m_rConnInfo.szCurrentConnectionName, pConnections[0].szEntryName, ARRAYSIZE(m_rConnInfo.szCurrentConnectionName)); m_rConnInfo.fConnected = TRUE; m_rConnInfo.fIStartedRas = FALSE; m_rConnInfo.hRasConn = pConnections[0].hrasconn; m_dwConnId = (DWORD_PTR) m_rConnInfo.hRasConn;
if (fSendAdvise) SendAdvise(CONNNOTIFY_CONNECTED, NULL); } } exit: // Thread Safety
LeaveCriticalSection(&m_cs);
// Free the list of connections returned from the enumerator
SafeMemFree(pConnections);
// Done
return hr; }
//
// FUNCTION: CConnectionManager::IsGlobalOffline()
//
// PURPOSE: Checks the state of the WININET global offline setting.
// Note - this is copied from shdocvw
//
// PARAMETERS:
// void
//
// RETURN VALUE:
// BOOL
//
BOOL CConnectionManager::IsGlobalOffline(void) { DWORD dwState = 0, dwSize = sizeof(DWORD); BOOL fRet = FALSE;
if (InternetQueryOptionA(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize)) { if (dwState & INTERNET_STATE_DISCONNECTED_BY_USER) fRet = TRUE; } return (fRet); }
//
// FUNCTION: CConnectionManager::SetGlobalOffline()
//
// PURPOSE: Sets the global offline state for Athena and IE. Note - this
// function is copied from shdocvw.
//
// PARAMETERS:
// <in> fOffline - TRUE to disconnect, FALSE to allow connections.
//
// RETURN VALUE:
// void
//
void CConnectionManager::SetGlobalOffline(BOOL fOffline, HWND hwndParent) { DWORD dwReturn;
if (fOffline) { if (hwndParent) { //Offer to hangup
RefreshConnInfo(FALSE); if (m_rConnInfo.hRasConn) { dwReturn = AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsWorkOfflineHangup), 0, MB_YESNOCANCEL);
if (dwReturn == IDCANCEL) return;
if (dwReturn == IDYES) { Disconnect(hwndParent, FALSE, TRUE, FALSE); } } } } SetShellOfflineState(fOffline);
m_fOffline = fOffline;
if (!m_fOffline) DoOfflineTransactions();
SendAdvise(CONNNOTIFY_WORKOFFLINE, (LPVOID) IntToPtr(fOffline)); }
typedef BOOL (WINAPI *PFNINETDIALHANDLER)(HWND,LPCSTR, DWORD, LPDWORD);
HRESULT CConnectionManager::DoAutoDial(HWND hwndParent, LPTSTR pszConnectoid, BOOL fDial) { TCHAR szAutodialDllName[MAX_PATH]; TCHAR szAutodialFcnName[MAX_PATH]; HRESULT hr = S_FALSE; UINT uError; HINSTANCE hInstDialer = 0; PFNINETDIALHANDLER pfnDialHandler = NULL; DWORD dwRasError = 0; BOOL f = 0; TCHAR szRegPath[MAX_PATH]; LPRASCONN pConnections = NULL; ULONG cConnections = 0; DWORD dwDialFlags = fDial ? INTERNET_CUSTOMDIAL_CONNECT : INTERNET_CUSTOMDIAL_DISCONNECT;
// Check to see if this connectoid has the autodial values
if (FAILED(LookupAutoDialHandler(pszConnectoid, szAutodialDllName, szAutodialFcnName))) goto exit;
// If we were able to load those two values, then we're going to let the
// autodialer take care of dialing the phone.
uError = SetErrorMode(SEM_NOOPENFILEERRORBOX);
// Try to load the library that contains the autodialer
hInstDialer = LoadLibrary(szAutodialDllName); SetErrorMode(uError);
if (!hInstDialer) { goto exit; }
// Try to load the function address
pfnDialHandler = (PFNINETDIALHANDLER) GetProcAddress(hInstDialer, szAutodialFcnName); if (!pfnDialHandler) goto exit;
// Call the dialer
f = (*pfnDialHandler)(hwndParent, pszConnectoid, dwDialFlags, &dwRasError);
hr = f ? S_OK : E_FAIL; m_rConnInfo.fConnected = fDial && f; m_rConnInfo.fIStartedRas = TRUE; m_rConnInfo.fAutoDial = TRUE;
if (f && fDial) { // Need to get the current connection handle
if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections))) { for (UINT i = 0; i < cConnections; i++) { if (0 == lstrcmpi(pConnections[i].szEntryName, pszConnectoid)) { EnterCriticalSection(&m_cs); m_rConnInfo.hRasConn = pConnections[i].hrasconn; m_rConnInfo.state = CIS_REFRESH; // new connection, must refresh conn info
LeaveCriticalSection(&m_cs); break; } }
SafeMemFree(pConnections); } }
exit: if (hInstDialer) FreeLibrary(hInstDialer);
return (hr); }
HRESULT CConnectionManager::LookupAutoDialHandler(LPTSTR pszConnectoid, LPTSTR pszAutodialDllName, LPTSTR pszAutodialFcnName) { HRESULT hr = E_FAIL; DWORD dwEntryInfoSize = 0; LPRASENTRY pRasEntry = NULL;
*pszAutodialDllName = 0; *pszAutodialFcnName = 0;
if (m_pRasGetEntryProperties) { // Find out how big the struct we need to pass in should be
RasGetEntryProperties(NULL, pszConnectoid, NULL, &dwEntryInfoSize, NULL, NULL); if (dwEntryInfoSize) { // Allocate a buffer big enough for this structure
if (!MemAlloc((LPVOID*) &pRasEntry, dwEntryInfoSize)) return (E_OUTOFMEMORY);
// Request the RASENTRY properties
pRasEntry->dwSize = sizeof(RASENTRY); if (0 != RasGetEntryProperties(NULL, pszConnectoid, pRasEntry, &dwEntryInfoSize, NULL, NULL)) goto exit;
// Copy the autodial info to the provided buffers
if (pRasEntry->szAutodialDll[0]) StrCpyN(pszAutodialDllName, pRasEntry->szAutodialDll, MAX_PATH);
if (pRasEntry->szAutodialFunc[0]) StrCpyN(pszAutodialFcnName, pRasEntry->szAutodialFunc, MAX_PATH);
// If we got here, we have all the data we need
if (*pszAutodialDllName && *pszAutodialFcnName) hr = S_OK; } } exit: SafeMemFree(pRasEntry); return (hr); }
// If the current connection is a CM connection, and the target connection is
// a CM connection, then we let the CM do whatever it is that they do.
BOOL CConnectionManager::ConnectionManagerVoodoo(LPTSTR pszConnection) { TCHAR szAutodialDllName[MAX_PATH]; TCHAR szAutodialFcnName[MAX_PATH];
// Check to see if the target is a CM connectoid
if (FAILED(LookupAutoDialHandler(pszConnection, szAutodialDllName, szAutodialFcnName))) return (FALSE);
// Find out if the current connection is a CM connectoid
if (FAILED(LookupAutoDialHandler(m_rConnInfo.szCurrentConnectionName, szAutodialDllName, szAutodialFcnName))) return (FALSE);
return (TRUE); }
HRESULT CConnectionManager::OEIsDestinationReachable(IImnAccount *pAccount, DWORD dwConnType) { char szServerName[256]; HRESULT hr = S_FALSE;
/*
if ((VerifyMobilityPackLoaded() == S_OK) && (GetServerName(pAccount, szServerName, ARRAYSIZE(szServerName)) == S_OK)) { if (IsDestinationReachable(szServerName, NULL) && (GetLastError() == 0)) { hr = S_OK; } } else { */ DWORD dw; if (SUCCEEDED(pAccount->GetPropDw(AP_HTTPMAIL_DOMAIN_MSN, &dw)) && dw) { if(HideHotmail()) return(hr); }
hr = IsInternetReachable(pAccount, dwConnType); /*
} */ return hr; }
HRESULT CConnectionManager::IsInternetReachable(IImnAccount *pAccount, DWORD dwConnType) {
TCHAR szConnectionName[CCHMAX_CONNECTOID]; HRESULT hr = S_FALSE; DWORD dwFlags;
switch (dwConnType) { case CONNECTION_TYPE_RAS: { if (FAILED(hr = pAccount->GetPropSz(AP_RAS_CONNECTOID, szConnectionName, ARRAYSIZE(szConnectionName)))) { AssertSz(FALSE, _T("CConnectionManager::Connect() - No connection name.")); break; }
hr = CanConnectActual(szConnectionName); break; }
case CONNECTION_TYPE_LAN: { if (VerifyMobilityPackLoaded() == S_OK) { if (IsNetworkAlive(&dwFlags) && (!!(dwFlags & NETWORK_ALIVE_LAN))) { hr = S_OK; } } else { //If Mobility pack is not loaded we can't figure out if lan indeed present, so like
//everywhere else we just assume that lan is present
hr = S_OK; } break; }
case CONNECTION_TYPE_INETSETTINGS: default: { if (InternetGetConnectedStateExA(&dwFlags, szConnectionName, ARRAYSIZE(szConnectionName), 0)) hr = S_OK;
break; } }
return hr; }
HRESULT CConnectionManager::GetServerName(IImnAccount *pAcct, LPSTR pServerName, DWORD size) { HRESULT hr = E_FAIL; DWORD dwSrvrType; ACCTTYPE accttype;
//This function will be called only for LAN accounts to avoid confusion with POP accounts having two servers
// an incoming and an outgoing.
if (SUCCEEDED(pAcct->GetAccountType(&accttype))) { switch (accttype) { case ACCT_MAIL: dwSrvrType = AP_IMAP_SERVER; break;
case ACCT_NEWS: dwSrvrType = AP_NNTP_SERVER; break;
case ACCT_DIR_SERV: dwSrvrType = AP_LDAP_SERVER; break;
default: Assert(FALSE); goto exit; }
if ((hr = pAcct->GetPropSz(dwSrvrType, pServerName, size)) != S_OK) { //If the account type is MAIL, we try to get the name of POP server
//For POP accounts we just try to ping the POP3 server as in most of the cases
//POP server and SMTP servers are the same. Even if they are not, we assume that if
//one is reachable the connection is dialed and ISPs network is reachable and hence the other
//server is reachable too.
if (accttype == ACCT_MAIL) { hr = pAcct->GetPropSz(AP_POP3_SERVER, pServerName, size); // look for an httpmail server
if (FAILED(hr)) hr = pAcct->GetPropSz(AP_HTTPMAIL_SERVER, pServerName, size); } } }
exit: return hr; }
BOOLEAN CConnectionManager::IsSameDestination(LPSTR pszConnectionName, LPSTR pszServerName) { //We need to find an account with pszConnectionName as the connectoid and pszServerName
//Return TRUE if we find one FALSE otherwise
IImnAccount *pAcct; BOOLEAN fret = FALSE;
if (g_pAcctMan && (g_pAcctMan->FindAccount(AP_RAS_CONNECTOID, pszConnectionName, &pAcct) == S_OK)) { //Now check if its server name is what we want.
//Althoug findAccount finds first account that satisfies the searchdata, this should work fine for a
//typical OE user. Even if there are two accounts with same connectoids and different servers and if
//we miss to find the one we want,at the most we will be putting up a connect dialog.
char myServerName[MAX_PATH]; if (SUCCEEDED(GetServerName(pAcct, myServerName, sizeof(myServerName)))) { if (lstrcmp(myServerName, pszServerName) == 0) { fret = TRUE; } } }
return fret; }
HRESULT CConnectionManager::VerifyMobilityPackLoaded() { HRESULT hr = REGDB_E_CLASSNOTREG; uCLSSPEC classpec;
if (!m_fMobilityPackFailed) { HWND hwnd; if (!m_hInstSensDll) { // figure out struct and flags
classpec.tyspec = TYSPEC_CLSID; classpec.tagged_union.clsid = CLSID_MobilityFeature; // call jit code
if (!g_pBrowser) { goto exit; } IOleWindow *pOleWnd; if (FAILED(g_pBrowser->QueryInterface(IID_IAthenaBrowser, (LPVOID*)&pOleWnd))) { goto exit; } pOleWnd->GetWindow(&hwnd);
hr = FaultInIEFeature(hwnd, &classpec, NULL, FIEF_FLAG_PEEK); pOleWnd->Release();
if(S_OK == hr) { // Mobile pack is installed
m_hInstSensDll = LoadLibrary(szSensApiDll); if (m_hInstSensDll) { m_pIsDestinationReachable = (ISDESTINATIONREACHABLE)GetProcAddress(m_hInstSensDll, szIsDestinationReachable); m_pIsNetworkAlive = (ISNETWORKALIVE)GetProcAddress(m_hInstSensDll, szIsNetworkAlive); }
if (!m_hInstSensDll || !m_pIsDestinationReachable || !m_pIsNetworkAlive) { m_fMobilityPackFailed = TRUE; } else { m_fMobilityPackFailed = FALSE; hr = S_OK; } } } else hr = S_OK; } return hr; exit: m_fMobilityPackFailed = TRUE; return hr; }
void CConnectionManager::DoOfflineTransactions() { char szId[CCHMAX_ACCOUNT_NAME]; IImnEnumAccounts *pEnum; HRESULT hr; FOLDERID id, *pid; ULONG iAcct, cAcct; IImnAccount *pAccount; DWORD dwConnection; HWND hwnd; DWORD cRecords;
pid = NULL; iAcct = 0;
// If this is getting hit through a news article URL, we won't have a browser and
// should not play back.
if (!g_pBrowser || !g_pSync) return;
// Get Record Count
g_pSync->GetRecordCount(&cRecords);
// sbailey: perf. fix. - prevent doing that expensive stuff below if there are no transactions.
if (0 == cRecords) return;
hr = g_pAcctMan->Enumerate(SRV_NNTP | SRV_IMAP | SRV_HTTPMAIL, &pEnum); if (SUCCEEDED(hr)) { hr = pEnum->GetCount(&cAcct); if (SUCCEEDED(hr) && cAcct > 0 && MemAlloc((void **)&pid, cAcct * sizeof(FOLDERID))) { while (SUCCEEDED(pEnum->GetNext(&pAccount))) { hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection); if (SUCCEEDED(hr)) { hr = OEIsDestinationReachable(pAccount, dwConnection); if (hr == S_OK) { hr = pAccount->GetPropSz(AP_ACCOUNT_ID, szId, ARRAYSIZE(szId)); if (SUCCEEDED(hr)) { hr = g_pStore->FindServerId(szId, &id); if (SUCCEEDED(hr)) { pid[iAcct] = id; iAcct++; } } } }
pAccount->Release(); } }
pEnum->Release(); }
if (iAcct > 0) { g_pBrowser->GetWindow(&hwnd); g_pBrowser->GetCurrentFolder(&id); g_pSync->DoPlayback(hwnd, pid, iAcct, id); }
if (pid != NULL) MemFree(pid); }
HRESULT CConnectionManager::ConnectUsingIESettings(HWND hwndParent, BOOL fShowUI) { TCHAR lpConnection[CCHMAX_CONNECTOID]; DWORD dwFlags = 0; DWORD dwReturn; HRESULT hr = E_FAIL;
if (InternetGetConnectedStateExA(&dwFlags, lpConnection, ARRAYSIZE(lpConnection), 0)) { m_fTryAgain = FALSE; return S_OK; }
// Only one caller can be dialing the phone at a time.
if (WAIT_TIMEOUT == WaitForSingleObject(m_hMutexDial, 0)) { return (HR_E_DIALING_INPROGRESS); }
if (!!(dwFlags & INTERNET_CONNECTION_MODEM) && (*lpConnection)) { if (!m_fDialerUI) { m_fDialerUI = TRUE; //A DEF CONNECTOID IS SET. Dial that one
if (IsGlobalOffline()) { if (fShowUI) { if (IDNO == AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline), 0, MB_YESNO | MB_ICONEXCLAMATION )) { hr = HR_E_OFFLINE; goto DialExit; } else g_pConMan->SetGlobalOffline(FALSE); } else { hr = HR_E_OFFLINE; //m_fDialerUI = FALSE;
goto DialExit; } }
if ((hr = PromptCloseConnection(lpConnection, fShowUI, hwndParent)) != S_FALSE) goto DialExit;
{ DWORD dwDialFlags = 0; DWORD dwLanFlags = 0;
dwDialFlags = INTERNET_AUTODIAL_FORCE_ONLINE;
if (VerifyMobilityPackLoaded() == S_OK) { if (!IsNetworkAlive(&dwLanFlags) || (!(dwLanFlags & NETWORK_ALIVE_LAN))) dwDialFlags |= INTERNET_DIAL_SHOW_OFFLINE; }
dwReturn = InternetDialA(hwndParent, lpConnection, dwDialFlags, &m_dwConnId, 0); if (dwReturn == 0) { m_rConnInfo.fConnected = TRUE; m_rConnInfo.fIStartedRas = TRUE; m_rConnInfo.fAutoDial = FALSE; m_rConnInfo.hRasConn = (HRASCONN)m_dwConnId; StrCpyN(m_rConnInfo.szCurrentConnectionName, lpConnection, ARRAYSIZE(m_rConnInfo.szCurrentConnectionName)); SendAdvise(CONNNOTIFY_CONNECTED, NULL); hr = S_OK; } else { if (dwReturn == ERROR_USER_DISCONNECTION) { hr = HR_E_USER_CANCEL_CONNECT; if (!!(dwDialFlags & INTERNET_DIAL_SHOW_OFFLINE)) { SetGlobalOffline(TRUE); } } else { hr = E_FAIL; DebugTrace("Error dialing: %d\n", GetLastError()); } } } DialExit: m_fDialerUI = FALSE; } else { hr = HR_E_USER_CANCEL_CONNECT; } } else { if (!m_fTryAgain) { int err = (int) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddOfferOffline), hwndParent, OfferOfflineDlgProc, (LPARAM)this); if (err == -1) { DWORD dwerr = GetLastError(); hr = S_OK; } if (!IsGlobalOffline()) hr = S_OK; else hr = HR_E_OFFLINE; } else hr = S_OK; } ReleaseMutex(m_hMutexDial);
return hr; }
void CConnectionManager::SetTryAgain(BOOL bval) { m_fTryAgain = bval; }
INT_PTR CALLBACK CConnectionManager::OfferOfflineDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { BOOL retval = 1; CConnectionManager *pThis = (CConnectionManager*)GetWndThisPtr(hwnd);
switch (uMsg) { case WM_INITDIALOG: { // Get lparam
pThis = (CConnectionManager *)lParam; if (!pThis) { Assert (FALSE); EndDialog(hwnd, E_FAIL); goto exit; } // Save this pointer
SetWndThisPtr (hwnd, pThis); break; }
case WM_COMMAND: { switch(GET_WM_COMMAND_ID(wParam, lParam)) { case IDWorkOffline: pThis->SetGlobalOffline(TRUE, NULL); break;
case IDTryAgain: pThis->SetGlobalOffline(FALSE); pThis->SetTryAgain(TRUE); break; } EndDialog(hwnd, S_OK); break; }
case WM_CLOSE: pThis->SetGlobalOffline(TRUE, NULL); EndDialog(hwnd, S_OK); break;
case WM_DESTROY: SetWndThisPtr(hwnd, NULL); break;
default: retval = 0; break; }
exit: return retval; }
HRESULT CConnectionManager::PromptCloseConnection(LPTSTR pszRasConn, BOOL fShowUI, HWND hwndParent) { HRESULT hr = S_FALSE; UINT uAnswer; LPRASCONN pConnections = NULL; ULONG cConnections = 0; uAnswer = idrgDialNew;
// Make sure the RAS DLL is loaded before we try this
if (FAILED(VerifyRasLoaded())) { hr = HR_E_UNINITIALIZED; goto exit; }
StrCpyN(m_szConnectName, pszRasConn, ARRAYSIZE(m_szConnectName));
// RefreshConnInfo
CHECKHR(hr = RefreshConnInfo());
if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections)) && (cConnections > 0)) { if (fShowUI) uAnswer = PromptCloseConnection(hwndParent);
// The user canceled from the dialog. Therefore we give up.
if (IDCANCEL == uAnswer || IDNO == uAnswer) { hr = HR_E_USER_CANCEL_CONNECT; goto exit; }
// The user said they wanted to hang up and dial a new connection.
else if (idrgDialNew == uAnswer || IDYES == uAnswer) { Disconnect(hwndParent, fShowUI, TRUE, FALSE); hr = S_FALSE; goto exit; }
// The user said to try to use the current connection.
else if (idrgUseCurrent == uAnswer) { //Save the conn info so we can return true for this connection in CanConnectActual
AddToConnList(pszRasConn);
hr = S_OK; SendAdvise(CONNNOTIFY_CONNECTED, NULL); goto exit; } } else { Disconnect(NULL, FALSE, TRUE, FALSE); hr = S_FALSE; } exit: SafeMemFree(pConnections); return hr; }
|