#include "private.h" #include "offline.h" #undef TF_THISMODULE #define TF_THISMODULE TF_DIALMON // prototypes DIALPROPDATA * InitDialData(void); // // uuid for our command target // const UUID CGID_ConnCmdGrp = { 0x1dc1fd0, 0xdc49, 0x11d0, {0xaf, 0x95, 0x00, 0xc0, 0x4f, 0xd9, 0x40, 0xbe} }; // // Registry keys we use to get autodial information // // Key name const TCHAR c_szAutodial[] = TEXT("EnableAutodial"); const TCHAR c_szProxy[] = TEXT("ProxyServer"); const TCHAR c_szUnknown[] = TEXT(""); // from schedule.cpp extern TCHAR szInternetSettings[]; extern TCHAR szProxyEnable[]; // length of general text strings #define TEXT_LENGTH 200 // our connection agent instance CConnectionAgent *pAgent = NULL; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Connection Agent class factory helper // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// HRESULT CConnectionAgent_CreateInstance(LPUNKNOWN pUnkOuter, IUnknown **ppunk) { IUnknown *punk, *punkClient = NULL; HRESULT hr; CConnClient *pClient; *ppunk = NULL; // create new con client instance pClient = new CConnClient; if(NULL == pClient) return E_OUTOFMEMORY; // Look for CConnectionAgent in ROT hr = GetActiveObject(CLSID_ConnectionAgent, NULL, &punk); if (NULL == punk) { // Not there - create one ASSERT(NULL == pAgent); pAgent = new CConnectionAgent; if(NULL == pAgent) { pClient->Release(); return E_OUTOFMEMORY; } // Get an IUnknown on new object hr = pAgent->QueryInterface(IID_IUnknown, (LPVOID *)&punk); if (FAILED(hr) || NULL == punk) { SAFERELEASE(pAgent); pClient->Release(); return E_FAIL; } // Register new connection agent hr = RegisterActiveObject(punk, CLSID_ConnectionAgent, ACTIVEOBJECT_STRONG, &pAgent->m_dwRegisterHandle); SAFERELEASE(pAgent); if (FAILED(hr)) { DBG_WARN("CConnectionAgentClassFactory RegisterActiveObject failed."); pClient->Release(); punk->Release(); return hr; } DBG("New connection agent object created."); } #ifdef DEBUG else { DBG("Using existing connection agent object."); } #endif // Now we have pClient and punk. Tell client who the boss is hr = pClient->SetConnAgent(punk); punk->Release(); if(FAILED(hr)) { pClient->Release(); return E_FAIL; } *ppunk = (IOleCommandTarget *)pClient; return hr; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Helper functions // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Ping Class // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // helper stuff // #define IS_DIGIT(ch) InRange(ch, TEXT('0'), TEXT('9')) void UnloadICMP(void); long g_lPingWndReg = 0; const TCHAR c_szPingWndClass[] = TEXT("PingClass"); #define WM_NAME (WM_USER) #define WM_STOP (WM_USER+1) class CPing { protected: HANDLE _hPing; HANDLE _hAsync; HWND _hwnd; UINT _uTimerID; BOOL _fResult; UINT _uTimeoutSec; BOOL EnableAutodial(BOOL fEnable); public: CPing(); ~CPing(); BOOL Init(UINT uTimeoutSec); BOOL PingSite(LPTSTR pszSite); static LRESULT CPing::WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); }; CPing::CPing() { _hPing = INVALID_HANDLE_VALUE; _hwnd = NULL; _hAsync = NULL; _uTimeoutSec = 10; } CPing::~CPing() { if(_hwnd) DestroyWindow(_hwnd); if(_hPing) IcmpCloseHandle(_hPing); UnloadICMP(); } BOOL CPing::Init(UINT uTimeoutSec) { // save timeout _uTimeoutSec = uTimeoutSec; // load ICMP.DLL and get a ping handle _hPing = IcmpCreateFile(); if(INVALID_HANDLE_VALUE == _hPing) return FALSE; // register window class if necessary if(!g_lPingWndReg) { g_lPingWndReg++; WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = CPing::WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInst; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)NULL; wc.lpszMenuName = NULL; wc.lpszClassName = c_szPingWndClass; RegisterClass(&wc); } if(NULL == _hwnd) _hwnd = CreateWindow(c_szPingWndClass, NULL, WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInst, (LPVOID)this); if(NULL == _hwnd) return FALSE; return TRUE; } LRESULT CPing::WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { CPing *pping = (CPing *)GetWindowLong(hWnd, GWL_USERDATA); LPCREATESTRUCT pcs = NULL; switch(Msg) { case WM_CREATE: pcs = (LPCREATESTRUCT)lParam; SetWindowLong(hWnd, GWL_USERDATA, ((LONG) (pcs->lpCreateParams))); break; case WM_NAME: // gethostbyname completed if(0 == WSAGETASYNCERROR(lParam)) pping->_fResult = TRUE; // fall through to WM_TIMER case WM_TIMER: // we ran out of time PostMessage(hWnd, WM_STOP, 0, 0); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; } BOOL CPing::EnableAutodial(BOOL fEnable) { DWORD dwNewState = 0, dwOldState = 0, dwSize = sizeof(DWORD); BOOL fOldEnable = FALSE; if(g_fIsWinNT) { // // In NT land, 1 means disabled, 0 means enabled // // Get WinNT autodial state _RasGetAutodialParam(RASADP_LoginSessionDisable, &dwOldState, &dwSize); if(0 == dwOldState) fOldEnable = TRUE; // set new state if(FALSE == fEnable) dwNewState = 1; _RasSetAutodialParam(RASADP_LoginSessionDisable, &dwNewState, sizeof(DWORD)); } else { // // In Win95 land, 1 means enabled, 0 means disabled // // Get Win95 autodial state if(!ReadRegValue(HKEY_CURRENT_USER, szInternetSettings, c_szAutodial, &dwOldState, sizeof(DWORD))) dwOldState = 0; if(dwOldState) fOldEnable = TRUE; // set new state if(fEnable) dwNewState = 1; WriteRegValue(HKEY_CURRENT_USER, szInternetSettings, c_szAutodial, &dwNewState, sizeof(DWORD), REG_BINARY); } return fOldEnable; } BOOL CPing::PingSite(LPTSTR pszHost) { IPAddr ipAddress = INADDR_NONE; DWORD dwPingSend = 0xdeadbeef, dwCount; WSADATA wsaData; BOOL fOldState; TCHAR pszWork[1024], *pEnd; BYTE pGetHostBuff[MAXGETHOSTSTRUCT]; int iErr; // assume failure _fResult = FALSE; if(INVALID_HANDLE_VALUE == _hPing) { DBG("CPing::PingSite no ICMP handle"); return FALSE; } // fire up winsock if(iErr = WSAStartup(0x0101, &wsaData)) { TraceMsg(TF_THISMODULE,"CPing::PingSite WSAStartup failed, iErr=%d", iErr); return FALSE; } if(IS_DIGIT(*pszHost)) { // try to convert ip address ipAddress = inet_addr(pszHost); } // turn off autodial fOldState = EnableAutodial(FALSE); if(INADDR_NONE == ipAddress) { // strip port (if any) from host name lstrcpyn(pszWork, pszHost, ARRAYSIZE(pszWork)); pEnd = StrChr(pszWork, TEXT(':')); if(pEnd) *pEnd = 0; // start async gethostbyname _uTimerID = SetTimer(_hwnd, 1, _uTimeoutSec * 1000, NULL); _hAsync = WSAAsyncGetHostByName(_hwnd, WM_NAME, pszWork, (char *)pGetHostBuff, MAXGETHOSTSTRUCT); if(_hAsync) { // operation started... wait for completion or time out MSG msg; while(1) { GetMessage(&msg, _hwnd, 0, 0); if(msg.message == WM_STOP) break; TranslateMessage(&msg); DispatchMessage(&msg); } /* while */ if(_fResult) { // it worked, snarf address struct hostent *phe; phe = (struct hostent *)pGetHostBuff; memcpy(&ipAddress, phe->h_addr, sizeof(IPAddr)); } else { // If we timed out, clean up pending request WSACancelAsyncRequest(_hAsync); } #ifdef DEBUG } else { // operation failed to start iErr = WSAGetLastError(); TraceMsg(TF_THISMODULE, "CPing::PingSite WSAAsyncGetHostByName failed, error=%d", iErr); #endif } // kill the timer if(_uTimerID) { KillTimer(_hwnd, _uTimerID); _uTimerID = 0; } } // assume the ping will fail _fResult = FALSE; if(INADDR_NONE != ipAddress) { // try to ping that address dwCount = IcmpSendEcho( _hPing, ipAddress, &dwPingSend, sizeof(DWORD), NULL, pszWork, sizeof(pszWork), _uTimeoutSec * 1000); if(dwCount) { // ping succeeded!! _fResult = TRUE; #ifdef DEBUG } else { // didn't work - spew iErr = GetLastError(); TraceMsg(TF_THISMODULE, "CPing::PingSite IcmpSendEcho failed, error=%x", iErr); #endif } } // restore autodial EnableAutodial(fOldState); #ifdef DEBUG if(_fResult) TraceMsg(TF_THISMODULE, "CPing::PingSite ping <%s> success", pszHost); else TraceMsg(TF_THISMODULE, "CPing::PingSite ping <%s> FAILURE", pszHost); #endif WSACleanup(); return _fResult; } // // PingProxy - exported function to decide if the proxy is available or not // BOOL PingProxy(UINT uTimeoutSec) { BOOL fRet = FALSE; TCHAR pszProxy[TEXT_LENGTH], *pszHttp, *pszSemi; DWORD dwValue; // check for proxy enabled if(ReadRegValue(HKEY_CURRENT_USER, szInternetSettings, szProxyEnable, &dwValue, sizeof(DWORD))) { if(0 == dwValue) return FALSE; } // proxy is enabled in registry. Ping it to see if it's around. if(ReadRegValue(HKEY_CURRENT_USER, szInternetSettings, c_szProxy, pszProxy, TEXT_LENGTH)) { // if there's an '=' in the proxy string, we'll look for the http= proxy if(NULL != StrChr(pszProxy, '=')) { pszHttp = StrStrI(pszProxy, TEXT("http=")); if(NULL == pszHttp) // don't understand proxy string return FALSE; pszHttp += 5; // 5 chars in "http=" // remove following entries - they're separated by ; pszSemi = StrChr(pszHttp, ';'); if(pszSemi) *pszSemi = 0; } else { pszHttp = pszProxy; } // got a proxy, crack the host name out of it TCHAR *pszPingSite; URL_COMPONENTS comp; ZeroMemory(&comp, sizeof(comp)); comp.dwStructSize = sizeof(comp); comp.dwHostNameLength = 1; if(InternetCrackUrlA(pszHttp, 0, 0, &comp) && (comp.nScheme != INTERNET_SCHEME_UNKNOWN)) { pszPingSite = comp.lpszHostName; pszPingSite[comp.dwHostNameLength] = 0; } else { pszPingSite = pszHttp; } // ping it CPing ping; if(ping.Init(uTimeoutSec)) fRet = ping.PingSite(pszPingSite); } return fRet; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Connection Client object // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Constructor / Destructor // CConnClient::CConnClient() { m_cRef = 1; m_poctAgent = NULL; m_pReport = NULL; m_State = CLIENT_NEW; m_bstrURL = NULL; } ////////////////////////////////////////////////////////////////////////// // // IUnknown members // STDMETHODIMP CConnClient::QueryInterface(REFIID riid, void ** ppv) { *ppv=NULL; // Validate requested interface if ((IID_IUnknown == riid) || (IID_INotificationSink == riid)) { *ppv=(INotificationSink*)this; } else if(IID_IOleCommandTarget == riid) { *ppv=(IOleCommandTarget*)this; } else { return E_NOINTERFACE; } ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } STDMETHODIMP_(ULONG) CConnClient::AddRef(void) { TraceMsg(TF_THISMODULE, "CConnClient::Addref (%08x) m_cRef=%d", this, m_cRef+1); return ++m_cRef; } STDMETHODIMP_(ULONG) CConnClient::Release(void) { TraceMsg(TF_THISMODULE, "CConnClient::Release (%08x) m_cRef=%d", this, m_cRef-1); if( 0L != --m_cRef ) return m_cRef; DBG("CConClient::Release Bye Bye"); // Make sure we're disconnected Disconnect(); m_poctAgent->Release(); if(m_bstrURL) SysFreeString(m_bstrURL); delete this; return 0L; } ////////////////////////////////////////////////////////////////////////// // // CConClient helper functions // HRESULT CConnClient::SetConnAgent(IUnknown *punk) { return punk->QueryInterface(IID_IOleCommandTarget, (void **)&m_poctAgent); } HRESULT CConnClient::Connect() { HRESULT hr; VARIANTARG vin, vout; m_State = CLIENT_CONNECTING; // tell agent we want to connect vin.vt = VT_UNKNOWN; vin.punkVal = (IOleCommandTarget *)this; VariantInit(&vout); hr = m_poctAgent->Exec(&CGID_ConnCmdGrp, AGENT_CONNECT, 0, &vin, &vout); if(SUCCEEDED(hr)) { ASSERT(vout.vt == VT_I4); m_iCookie = vout.lVal; } return hr; } HRESULT CConnClient::Disconnect() { HRESULT hr; VARIANTARG vin; if(CLIENT_DISCONNECTED == m_State) return S_OK; m_State = CLIENT_DISCONNECTED; // tell agent we want to disconnect vin.vt = VT_I4; vin.ulVal = m_iCookie; hr = m_poctAgent->Exec(&CGID_ConnCmdGrp, AGENT_DISCONNECT, 0, &vin, NULL); // done with report pointer SAFERELEASE(m_pReport); return hr; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // INotificationSink members // STDMETHODIMP CConnClient::OnNotification( LPNOTIFICATION pNotification, LPNOTIFICATIONREPORT pNotificationReport, DWORD dwReserved ) { NOTIFICATIONTYPE nt; HRESULT hr = S_OK; hr = pNotification->GetNotificationInfo(&nt, NULL,NULL,NULL,0); if(FAILED(hr)) { DBG_WARN("CConnClient::OnNotification failed to get not type!"); return E_INVALIDARG; } if(IsEqualGUID(nt, NOTIFICATIONTYPE_AGENT_START)) { DBG("CConnClient::OnNotification AGENT_START"); if(CLIENT_NEW == m_State) { // Must have a report pointer! if(NULL == pNotificationReport) { DBG("CConnClient::OnNotification no report on START!"); return E_UNEXPECTED; } // save report pointer TraceMsg(TF_THISMODULE, "CConClient::OnNotification (%08x) addreffing report pointer", this); m_pReport = pNotificationReport; m_pReport->AddRef(); // get the URL hr = ReadBSTR(pNotification, NULL, c_szPropURL, &m_bstrURL); // convert to ansi and log url connection request TCHAR pszURL[INTERNET_MAX_URL_LENGTH]; MyOleStrToStrN(pszURL, INTERNET_MAX_URL_LENGTH, m_bstrURL); LogEvent("Connecting for <%s>", pszURL); // Tell agent to connect Connect(); } else { DBG("CConnClient::OnNotification unexpected connect"); return E_UNEXPECTED; } } else if(IsEqualGUID(nt, NOTIFICATIONTYPE_TASKS_COMPLETED)) { DBG("CConnClient::OnNotification TASKS_COMPLETED"); // convert url to ansi TCHAR pszURL[INTERNET_MAX_URL_LENGTH]; MyOleStrToStrN(pszURL, INTERNET_MAX_URL_LENGTH, m_bstrURL); switch(m_State) { case CLIENT_CONNECTING: m_State = CLIENT_ABORT; // log connection abort LogEvent("Aborting connection for <%s>", pszURL); break; case CLIENT_CONNECTED: // log disconnect LogEvent("Disconnecting for <%s>", pszURL); Disconnect(); break; default: DBG("CConnClient::OnNotification unexpected disconnect"); return E_UNEXPECTED; } } else { DBG("CConnClient::OnNotification unknown type"); } return S_OK; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // IOleCommandTarget members // STDMETHODIMP CConnClient::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) { if (IsEqualGUID(*pguidCmdGroup, CGID_ConnCmdGrp)) { return S_OK; } return OLECMDERR_E_UNKNOWNGROUP; } STDMETHODIMP CConnClient::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvaIn, VARIANTARG *pvaOut) { HRESULT hr = E_NOTIMPL; if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_ConnCmdGrp)) { switch(nCmdID) { case AGENT_NOTIFY: if(VT_ERROR == pvaIn->vt) { hr = DeliverProgressReport(pvaIn->scode, NULL); } else { hr = E_INVALIDARG; } break; } } return hr; } ////////////////////////////////////////////////////////////////////////// // // Other methods // HRESULT CConnClient::DeliverProgressReport(SCODE scode, BSTR bstrErrorText) { HRESULT hr = S_OK; INotificationMgr *pMgr; INotification *pStatus; switch(m_State) { case CLIENT_CONNECTING: // Get Notification manager hr = CoCreateInstance(CLSID_StdNotificationMgr, NULL, CLSCTX_INPROC_SERVER, IID_INotificationMgr, (void**)&pMgr); if(FAILED(hr)) return hr; // create notification to deliver hr = pMgr->CreateNotification(NOTIFICATIONTYPE_PROGRESS_REPORT, (NOTIFICATIONFLAGS)0, NULL, &pStatus, 0); pMgr->Release(); if(FAILED(hr)) return hr; // stick result and string in progress report // WriteOLESTR(pStatus, NULL, c_szPropStatusString, bstrErrorText); WriteSCODE(pStatus, NULL, c_szPropStatusCode, scode); // deliver notification hr = m_pReport->DeliverUpdate(pStatus, 0, 0); pStatus->Release(); if(SUCCEEDED(scode)) { m_State = CLIENT_CONNECTED; } else { Disconnect(); } break; case CLIENT_ABORT: Disconnect(); break; } return hr; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Connection agent // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Constructor and destructor // CConnectionAgent::CConnectionAgent() { m_pData = NULL; m_cRef = 1; m_dwRegisterHandle = 0; m_lConnectionCount = 0; m_dwFlags = 0; m_hdpaClient = NULL; // Get the notification manager m_pMgr = NULL; CoCreateInstance(CLSID_StdNotificationMgr, NULL, CLSCTX_INPROC_SERVER, IID_INotificationMgr, (void**)&m_pMgr); } CConnectionAgent::~CConnectionAgent() { SAFERELEASE(m_pMgr); SAFELOCALFREE(m_pData); if(IsFlagSet(m_dwFlags, CA_LOADED_RAS)) UnloadRasDLL(); } // // Clean - clean up strong lock and ref count // void CConnectionAgent::Clean(void) { DWORD dwHandle = m_dwRegisterHandle; int iCurReport, i; CLIENTINFO *pClient; // don't do anything if there are outstanding connections if(m_lConnectionCount) return; // clean up client dpa if(m_hdpaClient) { iCurReport = DPA_GetPtrCount(m_hdpaClient); for(i=0; ifEnabled) // not enabled fPossible = FALSE; if(!m_pData->pszConnection[0]) // no connection fPossible = FALSE; return fPossible; } // // IsDialExisting - check to see if there's an existing dialup connection // that we didn't do // #define MAX_CONNECTION 8 BOOL CConnectionAgent::IsDialExisting(void) { TCHAR pszConn[RAS_MaxEntryName+1]; RASCONN pRasCon[MAX_CONNECTION]; DWORD dwSize = MAX_CONNECTION * sizeof(RASCONN), dwConn, dwCur; HKEY hkeyRoot = HKEY_CURRENT_USER; // read internet connectoid from registry if(!ReadRegValue(hkeyRoot, c_szRASKey, c_szProfile, pszConn, RAS_MaxEntryName+1)) { DBG("CConnectionAgent::IsDialExisting unable to read internet connectoid"); return FALSE; } // have Ras enumerate existing connections pRasCon[0].dwSize = sizeof(RASCONN); if(_RasEnumConnections(pRasCon, &dwSize, &dwConn)) { DBG("CConnectionAgent::IsDialExisting RasEnumConnections failed"); return FALSE; } // do any of them match our internet connectoid? for(dwCur=0; dwCurAddRef(); return NOERROR; } STDMETHODIMP_(ULONG) CConnectionAgent::AddRef(void) { TraceMsg(TF_THISMODULE, "CConnectionAgent::Addref m_cRef=%d", m_cRef+1); return ++m_cRef; } STDMETHODIMP_(ULONG) CConnectionAgent::Release(void) { TraceMsg(TF_THISMODULE, "CConnectionAgent::Release m_cRef=%d", m_cRef-1); if( 0L != --m_cRef ) return m_cRef; DBG("CConnectionAgent::Release Bye Bye"); delete this; return 0L; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // IOleCommandTarget members // STDMETHODIMP CConnectionAgent::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) { if (IsEqualGUID(*pguidCmdGroup, CGID_ConnCmdGrp)) { // We like connection agent commands return S_OK; } return OLECMDERR_E_UNKNOWNGROUP; } STDMETHODIMP CConnectionAgent::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvaIn, VARIANTARG *pvaOut) { HRESULT hr; CLIENTINFO *pInfo; int iIndex; if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_ConnCmdGrp)) { switch(nCmdID) { case AGENT_CONNECT: // validate input arguments if(VT_UNKNOWN != pvaIn->vt || NULL == pvaOut) return E_INVALIDARG; // create dpa if necessary if(NULL == m_hdpaClient) m_hdpaClient = DPA_Create(0); if(NULL == m_hdpaClient) return E_OUTOFMEMORY; // create and initialize new clientinfo struct pInfo = new CLIENTINFO; if(NULL == pInfo) return E_OUTOFMEMORY; pInfo->dwFlags = 0; hr = pvaIn->punkVal->QueryInterface(IID_IOleCommandTarget, (void **)&pInfo->poctClient); if(FAILED(hr)) return hr; // insert struct into dpa and return index iIndex = DPA_InsertPtr(m_hdpaClient, DPA_APPEND, pInfo); if(iIndex < 0) { delete pInfo; return E_OUTOFMEMORY; } else { pvaOut->vt = VT_I4; pvaOut->ulVal = iIndex; } // connect Connect(); return S_OK; case AGENT_DISCONNECT: // validate input parameters if(VT_I4 != pvaIn->vt) return E_INVALIDARG; // mark client record as disconnected pInfo = (CLIENTINFO *)DPA_GetPtr(m_hdpaClient, pvaIn->lVal); if(pInfo) { pInfo->dwFlags |= CLIENT_DISCONNECT; SAFERELEASE(pInfo->poctClient); } // disconnect Disconnect(); return S_OK; } } return E_NOTIMPL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // Notify all waiting agents of success or failure of dial attempt // void CConnectionAgent::Notify(HRESULT hrDialResult, TCHAR *pszErrorText) { CLIENTINFO *pClient; int i, iCurReport; //WCHAR pwszStatus[TEXT_LENGTH]; VARIANTARG vin; // We're done connecting ClearFlag(m_dwFlags, CA_CONNECTING_NOW); // Create the notifications to send if(S_OK == hrDialResult) { DBG("CConnectionAgent::Notify sending ONLINE"); LogEvent(TEXT("EVT: Successful connection")); } else { DBG("CConnectionAgent::Notify sending OFFLINE"); LogEvent(TEXT("EVT: Unsuccessful connection - hr=%08x"), hrDialResult); } // convert string to bstr // MyStrToOleStrN(pwszStatus, TEXT_LENGTH, pszErrorText); // build exec paramaters vin.vt = VT_ERROR; vin.scode = hrDialResult; // Send it to all the clients iCurReport = DPA_GetPtrCount(m_hdpaClient); for(i=0; idwFlags) { pClient->poctClient->Exec(&CGID_ConnCmdGrp, AGENT_NOTIFY, 0, &vin, NULL); // This can get blown away out from under us. if (m_hdpaClient) { pClient->dwFlags |= CLIENT_NOTIFIED; SAFERELEASE(pClient->poctClient); } } } // if we're disconnected, clean ourselves up Clean(); } BOOL GetLogonInfo(DIALPROPDATA *pData) { RASDIALPARAMS dp; DWORD dwRes; BOOL fPassword = FALSE; // initially set name/password/domain to null pData->pszUsername[0] = 0; pData->pszPassword[0] = 0; pData->pszDomain[0] = 0; // if there's no connection, we're done if(0 == pData->pszConnection[0]) return FALSE; // Try and get name/password/domain from Ras memset(&dp, 0, sizeof(RASDIALPARAMS)); dp.dwSize = sizeof(RASDIALPARAMS); lstrcpyn(dp.szEntryName, pData->pszConnection, ARRAYSIZE(dp.szEntryName)); dwRes = _RasGetEntryDialParams(NULL, &dp, &fPassword); if(fPassword && 0 == dwRes) { // Copy ras information to pData. lstrcpyn(pData->pszUsername, dp.szUserName, ARRAYSIZE(pData->pszUsername)); lstrcpyn(pData->pszPassword, dp.szPassword, ARRAYSIZE(pData->pszPassword)); lstrcpyn(pData->pszDomain, dp.szDomain, ARRAYSIZE(pData->pszDomain)); } return fPassword; } DIALPROPDATA * InitDialData(void) { DIALPROPDATA * pData = (DIALPROPDATA *)MemAlloc(LPTR, sizeof(DIALPROPDATA)); HKEY hkeyRoot = HKEY_CURRENT_USER; BOOL fGotInfo = FALSE; DWORD dwValue; if(NULL == pData) return NULL; // Fix fEnabled from registry HKCU\...\Internet Settings\EnableAutodial ReadRegValue(hkeyRoot, szInternetSettings, c_szAutodial, &dwValue, sizeof(DWORD)); if(dwValue == 1) { pData->fEnabled = TRUE; } // Fix fUnattended from registry HKCU\...\Internet Settings\EnableUnattended ReadRegValue(hkeyRoot, szInternetSettings, c_szEnable, &dwValue, sizeof(DWORD)); if(dwValue == 1) { pData->fUnattended = TRUE; } // Try to find a connection HKCU\Remote Access\Internet Profile if(ReadRegValue(hkeyRoot, c_szRASKey, c_szProfile, pData->pszConnection, RAS_MaxEntryName+1)) { GetLogonInfo(pData); } return pData; }