1346 lines
36 KiB
C++
1346 lines
36 KiB
C++
|
#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("<unknown>");
|
||
|
|
||
|
// 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; i<iCurReport; i++) {
|
||
|
pClient = (CLIENTINFO *)(DPA_GetPtr(m_hdpaClient, i));
|
||
|
if(pClient)
|
||
|
delete pClient;
|
||
|
}
|
||
|
DPA_Destroy(m_hdpaClient);
|
||
|
m_hdpaClient = NULL;
|
||
|
}
|
||
|
|
||
|
// release our strong registration
|
||
|
DBG("CConnectionAgent::Clean revoking connection agent object");
|
||
|
m_dwRegisterHandle = 0;
|
||
|
RevokeActiveObject(dwHandle, NULL);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//
|
||
|
// Connect - entry point to connect
|
||
|
//
|
||
|
void
|
||
|
CConnectionAgent::Connect(void)
|
||
|
{
|
||
|
BOOL fDone = FALSE;
|
||
|
TCHAR pszText[TEXT_LENGTH];
|
||
|
|
||
|
//
|
||
|
// increment connection count
|
||
|
//
|
||
|
m_lConnectionCount ++;
|
||
|
TraceMsg(TF_THISMODULE, "CConnectionAgent::Connect ref count now %d", m_lConnectionCount);
|
||
|
|
||
|
//
|
||
|
// Store offline state if we haven't already and go online
|
||
|
//
|
||
|
if(FALSE == IsFlagSet(m_dwFlags, CA_OFFLINE_STATE_READ)) {
|
||
|
|
||
|
if(IsGlobalOffline())
|
||
|
SetFlag(m_dwFlags, CA_OFFLINE);
|
||
|
|
||
|
// make sure we're online
|
||
|
SetGlobalOffline(FALSE);
|
||
|
|
||
|
SetFlag(m_dwFlags, CA_OFFLINE_STATE_READ);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check for pending dialup connection
|
||
|
//
|
||
|
if(IsFlagSet(m_dwFlags, CA_CONNECTING_NOW)) {
|
||
|
// already working on a connection
|
||
|
DBG("CConnectionAgent::Connect already trying to connect");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check to see if we can dial to get a connection
|
||
|
//
|
||
|
if(FALSE == IsDialPossible()) {
|
||
|
|
||
|
//
|
||
|
// can't dial - better have a direct connection
|
||
|
//
|
||
|
DBG("CConnectionAgent::Connect guessing connected");
|
||
|
if(!MLLoadString(IDS_DIAL_DIRECT, pszText, TEXT_LENGTH))
|
||
|
lstrcpy(pszText, "direct");
|
||
|
Notify(S_OK, pszText);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check for an existing dialup connection
|
||
|
//
|
||
|
|
||
|
if(FALSE == IsFlagSet(m_dwFlags, CA_LOADED_RAS)) {
|
||
|
SetFlag(m_dwFlags, CA_LOADED_RAS);
|
||
|
LoadRasDLL();
|
||
|
}
|
||
|
|
||
|
if(IsDialExisting()) {
|
||
|
DBG("CConnectionAgent::Connect already connected");
|
||
|
if(!MLLoadString(IDS_DIAL_ALREADY_CONNECTED, pszText, TEXT_LENGTH))
|
||
|
lstrcpy(pszText, "success");
|
||
|
Notify(S_OK, pszText);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#ifdef COOL_MODEM_ACTION
|
||
|
// since we assume connected for direct connect, no proxy check is
|
||
|
// necessary. If this check is put in, cool behavior results: It uses
|
||
|
// the proxy server if it can find it, otherwise it autodials.
|
||
|
|
||
|
// Autodial needs to be made consistant with this before it gets turned
|
||
|
// on
|
||
|
|
||
|
//
|
||
|
// check for a proxy connection
|
||
|
//
|
||
|
if(PingProxy(5)) {
|
||
|
// Dial is possible but proxy is available! Turn off autodial and
|
||
|
// flag to turn it back on when we're done
|
||
|
CPing::EnableAutodial(FALSE);
|
||
|
SetFlag(m_dwFlags, CA_AUTODIAL_OFF);
|
||
|
|
||
|
// Using proxy
|
||
|
DBG("CConnectionAgent::Connect using proxy");
|
||
|
if(!MLLoadString(IDS_DIAL_PROXY, pszText, TEXT_LENGTH))
|
||
|
lstrcpy(pszText, "proxy");
|
||
|
Notify(S_OK, pszText);
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//
|
||
|
// Ensure we can dial without user intervention
|
||
|
//
|
||
|
BOOL fContinue = TRUE;
|
||
|
|
||
|
if(SHRestricted2W(REST_NoUnattendedDialing, NULL, 0))
|
||
|
// dialing restricted
|
||
|
fContinue = FALSE;
|
||
|
|
||
|
//
|
||
|
// No existing connection but we can dial. do it now.
|
||
|
//
|
||
|
SetFlag(m_dwFlags, CA_CONNECTING_NOW);
|
||
|
|
||
|
|
||
|
DWORD dwRetCode;
|
||
|
if(fContinue)
|
||
|
{
|
||
|
dwRetCode = ERROR_SUCCESS;
|
||
|
if(!InternetAutodial((INTERNET_AUTODIAL_FORCE_ONLINE |
|
||
|
INTERNET_AUTODIAL_FORCE_UNATTENDED |
|
||
|
INTERNET_AUTODIAL_FAILIFSECURITYCHECK), 0))
|
||
|
{
|
||
|
dwRetCode = GetLastError();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (fContinue && (ERROR_SUCCESS == dwRetCode)) {
|
||
|
// successful connection made
|
||
|
SetFlag(m_dwFlags, CA_DIALED);
|
||
|
if(!MLLoadString(IDS_DIAL_SUCCESS, pszText, TEXT_LENGTH))
|
||
|
lstrcpy(pszText, "success");
|
||
|
Notify(S_OK, pszText);
|
||
|
} else {
|
||
|
//UINT uID;
|
||
|
HRESULT hrDialResult;
|
||
|
// unable to dial
|
||
|
if(ERROR_INTERNET_FAILED_DUETOSECURITYCHECK == dwRetCode)
|
||
|
{
|
||
|
hrDialResult = E_ABORT;
|
||
|
// uID = IDS_STRING_E_SECURITYCHECK; not needed - since MLLoadString below is commented out
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hrDialResult = E_INVALIDARG;
|
||
|
// uID = IDS_STRING_E_CONFIG;not needed - since MLLoadString below is commented out
|
||
|
}
|
||
|
|
||
|
// if(!MLLoadString(uID, pszText, TEXT_LENGTH)) // Don't bother : This is ignored anyway
|
||
|
lstrcpy(pszText, "Connection Not Made");
|
||
|
Notify(hrDialResult, pszText);
|
||
|
}
|
||
|
|
||
|
ClearFlag(m_dwFlags, CA_CONNECTING_NOW);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Disconnect - entry point to disconnect
|
||
|
//
|
||
|
void
|
||
|
CConnectionAgent::Disconnect(void)
|
||
|
{
|
||
|
// If we're the last connection, hang up
|
||
|
m_lConnectionCount --;
|
||
|
TraceMsg(TF_THISMODULE, "CConnectionAgent::Disconnect ref count now %d", m_lConnectionCount);
|
||
|
|
||
|
if(0 == m_lConnectionCount) {
|
||
|
|
||
|
// If we dialed this connection, hang it up
|
||
|
if(IsFlagSet(m_dwFlags, CA_DIALED)) {
|
||
|
LogEvent(TEXT("EVT: Hanging up"));
|
||
|
InternetAutodialHangup(0);
|
||
|
}
|
||
|
|
||
|
#ifdef COOL_MODEM_ACTION
|
||
|
if(IsFlagSet(m_dwFlags, CA_AUTODIAL_OFF)) {
|
||
|
// we turned autodial off - turn it back on
|
||
|
CPing::EnableAutodial(TRUE);
|
||
|
|
||
|
// tell wininet we've changed it
|
||
|
InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// restore original offline state
|
||
|
SetGlobalOffline(IsFlagSet(m_dwFlags, CA_OFFLINE));
|
||
|
|
||
|
// revoke our object
|
||
|
Clean();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//
|
||
|
// IsDialPossible - search around and make sure all necessary info
|
||
|
// is available to connect. If fQuiet is false, may bring up dialogs
|
||
|
// to get necessary info
|
||
|
//
|
||
|
BOOL
|
||
|
CConnectionAgent::IsDialPossible()
|
||
|
{
|
||
|
BOOL fPossible = TRUE;
|
||
|
|
||
|
// Refresh data in case properties has been up and changed it
|
||
|
if(m_pData)
|
||
|
MemFree(m_pData);
|
||
|
m_pData = InitDialData();
|
||
|
|
||
|
if(NULL == m_pData)
|
||
|
return FALSE;
|
||
|
|
||
|
if(FALSE == m_pData->fEnabled)
|
||
|
// 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; dwCur<dwConn; dwCur++) {
|
||
|
if(0 == lstrcmp(pszConn, pRasCon[dwCur].szEntryName))
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//
|
||
|
// IUnknown members
|
||
|
//
|
||
|
STDMETHODIMP CConnectionAgent::QueryInterface(REFIID riid, void ** ppv)
|
||
|
{
|
||
|
*ppv=NULL;
|
||
|
|
||
|
// Validate requested interface
|
||
|
if ((IID_IUnknown == riid) ||
|
||
|
(IID_IOleCommandTarget == riid))
|
||
|
{
|
||
|
*ppv=(IOleCommandTarget*)this;
|
||
|
} else {
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
((LPUNKNOWN)*ppv)->AddRef();
|
||
|
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; i<iCurReport; i++) {
|
||
|
pClient = (CLIENTINFO *)(DPA_GetPtr(m_hdpaClient, i));
|
||
|
if(pClient && 0 == pClient->dwFlags) {
|
||
|
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;
|
||
|
}
|