Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1095 lines
32 KiB

// --------------------------------------------------------------------------------
// Ixpras.cpp
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// Steven J. Bailey
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "dllmain.h"
#include "ixpras.h"
#include "strconst.h"
#include "resource.h"
#include "demand.h"
#include "shlwapi.h"
// --------------------------------------------------------------------------------
// RAS API Typedefs
// --------------------------------------------------------------------------------
typedef DWORD (APIENTRY *RASDIALPROC)(LPRASDIALEXTENSIONS, LPTSTR, LPRASDIALPARAMS, DWORD, LPVOID, LPHRASCONN);
typedef DWORD (APIENTRY *RASENUMCONNECTIONSPROC)(LPRASCONN, LPDWORD, LPDWORD);
typedef DWORD (APIENTRY *RASENUMENTRIESPROC)(LPTSTR, LPTSTR, LPRASENTRYNAME, LPDWORD, LPDWORD);
typedef DWORD (APIENTRY *RASGETCONNECTSTATUSPROC)(HRASCONN, LPRASCONNSTATUS);
typedef DWORD (APIENTRY *RASGETERRORSTRINGPROC)(UINT, LPTSTR, DWORD);
typedef DWORD (APIENTRY *RASHANGUPPROC)(HRASCONN);
typedef DWORD (APIENTRY *RASSETENTRYDIALPARAMSPROC)(LPTSTR, LPRASDIALPARAMS, BOOL);
typedef DWORD (APIENTRY *RASGETENTRYDIALPARAMSPROC)(LPTSTR, LPRASDIALPARAMS, BOOL*);
typedef DWORD (APIENTRY *RASCREATEPHONEBOOKENTRYPROC)(HWND, LPTSTR);
typedef DWORD (APIENTRY *RASEDITPHONEBOOKENTRYPROC)(HWND, LPTSTR, LPTSTR);
// --------------------------------------------------------------------------------
// RAS Function Pointers
// --------------------------------------------------------------------------------
static RASDIALPROC g_pRasDial=NULL;
static RASENUMCONNECTIONSPROC g_pRasEnumConnections=NULL;
static RASENUMENTRIESPROC g_pRasEnumEntries=NULL;
static RASGETCONNECTSTATUSPROC g_pRasGetConnectStatus=NULL;
static RASGETERRORSTRINGPROC g_pRasGetErrorString=NULL;
static RASHANGUPPROC g_pRasHangup=NULL;
static RASSETENTRYDIALPARAMSPROC g_pRasSetEntryDialParams=NULL;
static RASGETENTRYDIALPARAMSPROC g_pRasGetEntryDialParams=NULL;
static RASCREATEPHONEBOOKENTRYPROC g_pRasCreatePhonebookEntry=NULL;
static RASEDITPHONEBOOKENTRYPROC g_pRasEditPhonebookEntry=NULL;
#define DEF_HANGUP_WAIT 10 // Seconds
// --------------------------------------------------------------------------------
// Make our code look prettier
// --------------------------------------------------------------------------------
#undef RasDial
#undef RasEnumConnections
#undef RasEnumEntries
#undef RasGetConnectStatus
#undef RasGetErrorString
#undef RasHangup
#undef RasSetEntryDialParams
#undef RasGetEntryDialParams
#undef RasCreatePhonebookEntry
#undef RasEditPhonebookEntry
#define RasDial (*g_pRasDial)
#define RasEnumConnections (*g_pRasEnumConnections)
#define RasEnumEntries (*g_pRasEnumEntries)
#define RasGetConnectStatus (*g_pRasGetConnectStatus)
#define RasGetErrorString (*g_pRasGetErrorString)
#define RasHangup (*g_pRasHangup)
#define RasSetEntryDialParams (*g_pRasSetEntryDialParams)
#define RasGetEntryDialParams (*g_pRasGetEntryDialParams)
#define RasCreatePhonebookEntry (*g_pRasCreatePhonebookEntry)
#define RasEditPhonebookEntry (*g_pRasEditPhonebookEntry)
// --------------------------------------------------------------------------------
// HrLoadRAS
// --------------------------------------------------------------------------------
HRESULT HrLoadRAS(void)
{
// Locals
HRESULT hr=S_OK;
UINT uOldErrorMode;
// Thread Safety
EnterCriticalSection(&g_csRAS);
// If dll is loaded, lets verify all of my function pointers
if (g_hinstRAS)
goto exit;
// 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.
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
HKEY hKey;
const TCHAR c_szRegKeyRAS[] = TEXT("SOFTWARE\\Microsoft\\RAS");
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyRAS, 0, KEY_READ, &hKey))
{
hr = TrapError(IXP_E_RAS_NOT_INSTALLED);
goto exit;
}
RegCloseKey(hKey);
}
// Try loading RAS
uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
g_hinstRAS = LoadLibraryA("RASAPI32.DLL");
SetErrorMode(uOldErrorMode);
// Failure ?
if (NULL == g_hinstRAS)
{
hr = TrapError(IXP_E_RAS_NOT_INSTALLED);
goto exit;
}
// Did we load it
g_pRasDial = (RASDIALPROC)GetProcAddress(g_hinstRAS, c_szRasDial);
g_pRasEnumConnections = (RASENUMCONNECTIONSPROC)GetProcAddress(g_hinstRAS, c_szRasEnumConnections);
g_pRasEnumEntries = (RASENUMENTRIESPROC)GetProcAddress(g_hinstRAS, c_szRasEnumEntries);
g_pRasGetConnectStatus = (RASGETCONNECTSTATUSPROC)GetProcAddress(g_hinstRAS, c_szRasGetConnectStatus);
g_pRasGetErrorString = (RASGETERRORSTRINGPROC)GetProcAddress(g_hinstRAS, c_szRasGetErrorString);
g_pRasHangup = (RASHANGUPPROC)GetProcAddress(g_hinstRAS, c_szRasHangup);
g_pRasSetEntryDialParams = (RASSETENTRYDIALPARAMSPROC)GetProcAddress(g_hinstRAS, c_szRasSetEntryDialParams);
g_pRasGetEntryDialParams = (RASGETENTRYDIALPARAMSPROC)GetProcAddress(g_hinstRAS, c_szRasGetEntryDialParams);
g_pRasCreatePhonebookEntry = (RASCREATEPHONEBOOKENTRYPROC)GetProcAddress(g_hinstRAS, c_szRasCreatePhonebookEntry);
g_pRasEditPhonebookEntry = (RASEDITPHONEBOOKENTRYPROC)GetProcAddress(g_hinstRAS, c_szRasEditPhonebookEntry);
// Make sure all functions have been loaded
if (g_pRasDial &&
g_pRasEnumConnections &&
g_pRasEnumEntries &&
g_pRasGetConnectStatus &&
g_pRasGetErrorString &&
g_pRasHangup &&
g_pRasSetEntryDialParams &&
g_pRasGetEntryDialParams &&
g_pRasCreatePhonebookEntry &&
g_pRasEditPhonebookEntry)
goto exit;
// Failure...
hr = TrapError(IXP_E_RAS_PROCS_NOT_FOUND);
exit:
// Thread Safety
LeaveCriticalSection(&g_csRAS);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::CRASTransport
// --------------------------------------------------------------------------------
CRASTransport::CRASTransport(void)
{
DllAddRef();
m_cRef = 1;
m_pCallback = NULL;
*m_szConnectoid = '\0';
m_hConn = NULL;
m_fConnOwner = FALSE;
m_hwndRAS = NULL;
m_uRASMsg = 0;
ZeroMemory(&m_rServer, sizeof(INETSERVER));
ZeroMemory(&m_rDialParams, sizeof(RASDIALPARAMS));
InitializeCriticalSection(&m_cs);
}
// --------------------------------------------------------------------------------
// CRASTransport::~CRASTransport
// --------------------------------------------------------------------------------
CRASTransport::~CRASTransport(void)
{
EnterCriticalSection(&m_cs);
ZeroMemory(&m_rServer, sizeof(INETSERVER));
SafeRelease(m_pCallback);
*m_szConnectoid = '\0';
m_hConn = NULL;
if (m_hwndRAS)
DestroyWindow(m_hwndRAS);
LeaveCriticalSection(&m_cs);
DeleteCriticalSection(&m_cs);
DllRelease();
}
// --------------------------------------------------------------------------------
// CRASTransport::QueryInterface
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::QueryInterface(REFIID riid, LPVOID *ppv)
{
// Locals
HRESULT hr=S_OK;
// Bad param
if (ppv == NULL)
{
hr = TrapError(E_INVALIDARG);
goto exit;
}
// Init
*ppv=NULL;
// IID_IUnknown
if (IID_IUnknown == riid)
*ppv = ((IUnknown *)this);
// IID_IInternetTransport
else if (IID_IInternetTransport == riid)
*ppv = ((IInternetTransport *)this);
// IID_IRASTransport
else if (IID_IRASTransport == riid)
*ppv = (IRASTransport *)this;
// If not null, addref it and return
if (NULL != *ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
goto exit;
}
// No Interface
hr = TrapError(E_NOINTERFACE);
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::QueryInterface
// --------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CRASTransport::AddRef(void)
{
return ++m_cRef;
}
// --------------------------------------------------------------------------------
// CRASTransport::QueryInterface
// --------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CRASTransport::Release(void)
{
if (0 != --m_cRef)
return m_cRef;
delete this;
return 0;
}
// --------------------------------------------------------------------------------
// CRASTransport::HandsOffCallback
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::HandsOffCallback(void)
{
// Locals
HRESULT hr=S_OK;
// Thread Safety
EnterCriticalSection(&m_cs);
// No current callback
if (NULL == m_pCallback)
{
hr = TrapError(S_FALSE);
goto exit;
}
// Release it
SafeRelease(m_pCallback);
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::InitNew
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::InitNew(IRASCallback *pCallback)
{
// Locals
HRESULT hr=S_OK;
// check params
if (NULL == pCallback)
return TrapError(E_INVALIDARG);
// Thread Safety
EnterCriticalSection(&m_cs);
// Release current callback
SafeRelease(m_pCallback);
// Assume new callback
m_pCallback = pCallback;
m_pCallback->AddRef();
// Have I Create my modeless window for RAS connections yet?
if (NULL == m_hwndRAS)
{
// Create Modeless Window
m_hwndRAS = CreateDialogParam(g_hLocRes, MAKEINTRESOURCE(IDD_RASCONNECT), NULL, RASConnectDlgProc, (LPARAM)this);
if (NULL == m_hwndRAS)
{
hr = TrapError(E_FAIL);
goto exit;
}
// Get registered RAS event message id
m_uRASMsg = RegisterWindowMessageA(RASDIALEVENT);
if (m_uRASMsg == 0)
m_uRASMsg = WM_RASDIALEVENT;
}
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::GetCurrentConnectoid
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::GetCurrentConnectoid(LPSTR pszConnectoid, ULONG cchMax)
{
// Locals
HRESULT hr=S_OK;
LPRASCONN prgConnection=NULL;
DWORD cConnection;
// Invalid Arg
if (NULL == pszConnectoid || cchMax < CCHMAX_CONNECTOID)
return TrapError(E_INVALIDARG);
// Thread Safety
EnterCriticalSection(&m_cs);
// Get Current RAS Connection
if (FEnumerateConnections(&prgConnection, &cConnection) == 0 || 0 == cConnection)
{
hr = IXP_E_NOT_CONNECTED;
goto exit;
}
// Is there at l
StrCpyN(pszConnectoid, prgConnection[0].szEntryName, cchMax);
exit:
// Cleanup
SafeMemFree(prgConnection);
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::Connect
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::Connect(LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
{
// Locals
HRESULT hr=S_OK;
LPRASCONN prgConn=NULL;
DWORD cConn,
dwError;
// check params
if (NULL == pInetServer)
return TrapError(E_INVALIDARG);
// RAS_CONNECT_RAS ?
if (RAS_CONNECT_RAS != pInetServer->rasconntype)
return IXP_S_RAS_NOT_NEEDED;
// Empty Connectoid
if (FIsEmptyA(pInetServer->szConnectoid))
return TrapError(IXP_E_RAS_INVALID_CONNECTOID);
// Thread Safety
EnterCriticalSection(&m_cs);
// Initialized
if (NULL == m_pCallback)
{
hr = TrapError(IXP_E_NOT_INIT);
goto exit;
}
// LoadRAS
CHECKHR(hr = HrLoadRAS());
// Save pInetServer
CopyMemory(&m_rServer, pInetServer, sizeof(INETSERVER));
// No Current Known Connection
if (NULL == m_hConn)
{
// Get Current RAS Connection
if (FEnumerateConnections(&prgConn, &cConn) && cConn > 0)
{
m_fConnOwner = FALSE;
m_hConn = prgConn[0].hrasconn;
StrCpyN(m_szConnectoid, prgConn[0].szEntryName, ARRAYSIZE(m_szConnectoid));
}
}
// Otherwise, verify the connection status
else
{
// Locals
RASCONNSTATUS rcs;
// Get Connection Status
rcs.dwSize = sizeof(RASCONNSTATUS);
dwError = RasGetConnectStatus(m_hConn, &rcs);
if (dwError || rcs.dwError || RASCS_Disconnected == rcs.rasconnstate)
{
m_fConnOwner = FALSE;
m_hConn = NULL;
*m_szConnectoid = '\0';
}
}
// If RAS Connection present, is it equal to suggested
if (m_hConn)
{
// Better have a connectoid
Assert(*m_szConnectoid);
// Current connection is what I want ?
if (lstrcmpi(m_szConnectoid, m_rServer.szConnectoid) == 0)
{
m_pCallback->OnRasDialStatus(RASCS_Connected, 0, this);
hr = IXP_S_RAS_USING_CURRENT;
goto exit;
}
// Otherwise, if we didn't start the RAS connection...
else if (FALSE == m_fConnOwner)
{
// Prompt to Close un-owner current connection...
hr = m_pCallback->OnReconnect(m_szConnectoid, m_rServer.szConnectoid, this);
// Cancel ?
if (IXP_E_USER_CANCEL == hr)
goto exit;
// Use Current Connection...
else if (S_FALSE == hr)
{
hr = IXP_S_RAS_USING_CURRENT;
goto exit;
}
// Close Current ?
else
{
FRasHangupAndWait(DEF_HANGUP_WAIT);
}
}
// Otherwise, I started the connection, so close it
else if (m_fConnOwner == TRUE)
{
FRasHangupAndWait(DEF_HANGUP_WAIT);
}
}
// We probably shouldn't have a connection handle at this point
Assert(m_hConn == NULL);
// Dial the connection
CHECKHR(hr = HrStartRasDial());
// If Synchronous -- Woo - hoo were connected and we started the connection
m_fConnOwner = TRUE;
StrCpyN(m_szConnectoid, m_rServer.szConnectoid, ARRAYSIZE(m_szConnectoid));
exit:
// Cleanup
SafeMemFree(prgConn);
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::HrStartRasDial
// --------------------------------------------------------------------------------
HRESULT CRASTransport::HrStartRasDial(void)
{
// Locals
HRESULT hr=S_OK;
BOOL fRetry=FALSE;
DWORD dwError;
// Prompt for while
while(1)
{
// Logon first ?
hr = HrLogon(fRetry);
if (FAILED(hr))
goto exit;
// If Succeeded
#ifndef WIN16
dwError = RasDial(NULL, NULL, &m_rDialParams, 0xFFFFFFFF, m_hwndRAS, &m_hConn);
#else
dwError = RasDial(NULL, NULL, &m_rDialParams, 0xFFFFFFFF, (LPVOID)m_hwndRAS, &m_hConn);
#endif
if (dwError == 0)
break;
// Lets feed the user the error
m_pCallback->OnRasDialStatus(RASCS_Disconnected, dwError, this);
// Retry Logon
fRetry = TRUE;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::RASConnectDlgProc
// --------------------------------------------------------------------------------
INT_PTR CALLBACK CRASTransport::RASConnectDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Locals
CRASTransport *pTransport=(CRASTransport *)GetWndThisPtr(hwnd);
switch (uMsg)
{
case WM_INITDIALOG:
pTransport = (CRASTransport *)lParam;
Assert(pTransport);
SetWndThisPtr(hwnd, pTransport);
return 0;
case WM_DESTROY:
SetWndThisPtr(hwnd, NULL);
break;
default:
if (NULL != pTransport)
{
// Thread Safety
EnterCriticalSection(&pTransport->m_cs);
// Our Message
if (NULL != pTransport->m_pCallback && uMsg == pTransport->m_uRASMsg)
{
// Handle Error
if (lParam)
{
// Hangup
if (pTransport->m_hConn)
pTransport->FRasHangupAndWait(DEF_HANGUP_WAIT);
}
// Give to callback
pTransport->m_pCallback->OnRasDialStatus((RASCONNSTATE)wParam, (DWORD) lParam, pTransport);
}
// thread Safety
LeaveCriticalSection(&pTransport->m_cs);
}
}
// Done
return 0;
}
// --------------------------------------------------------------------------------
// CRASTransport::HrLogon
// --------------------------------------------------------------------------------
HRESULT CRASTransport::HrLogon(BOOL fForcePrompt)
{
// Locals
HRESULT hr=S_OK;
DWORD dwRasError;
BOOL fSavePassword;
// Do we need to prompt for logon information first ?
ZeroMemory(&m_rDialParams, sizeof(RASDIALPARAMS));
m_rDialParams.dwSize = sizeof(RASDIALPARAMS);
Assert(sizeof(m_rDialParams.szEntryName) >= sizeof(m_rServer.szConnectoid));
StrCpyN(m_rDialParams.szEntryName, m_rServer.szConnectoid, sizeof(m_rDialParams.szEntryName));
// Get params
dwRasError = RasGetEntryDialParams(NULL, &m_rDialParams, &fSavePassword);
if (dwRasError)
{
hr = TrapError(IXP_E_RAS_GET_DIAL_PARAMS);
goto exit;
}
// Do we need to get password / account information
if (fForcePrompt ||
!fSavePassword ||
FIsEmpty(m_rDialParams.szUserName) ||
FIsEmpty(m_rDialParams.szPassword))
{
// Locals
IXPRASLOGON rLogon;
// Init
ZeroMemory(&rLogon, sizeof(IXPRASLOGON));
// Fill Logon Data...
StrCpyN(rLogon.szConnectoid, m_rDialParams.szEntryName, ARRAYSIZE(rLogon.szConnectoid));
StrCpyN(rLogon.szUserName, m_rDialParams.szUserName, ARRAYSIZE(rLogon.szUserName));
StrCpyN(rLogon.szPassword, m_rDialParams.szPassword, ARRAYSIZE(rLogon.szPassword));
StrCpyN(rLogon.szDomain, m_rDialParams.szDomain, ARRAYSIZE(rLogon.szDomain));
StrCpyN(rLogon.szPhoneNumber, m_rDialParams.szPhoneNumber, ARRAYSIZE(rLogon.szPhoneNumber));
rLogon.fSavePassword = fSavePassword;
// Prompt
hr = m_pCallback->OnLogonPrompt(&rLogon, this);
// If OK, lets save the settings
if (S_OK == hr)
{
// Copy parameters back
StrCpyN(m_rDialParams.szUserName, rLogon.szUserName, ARRAYSIZE(m_rDialParams.szUserName));
StrCpyN(m_rDialParams.szPassword, rLogon.szPassword, ARRAYSIZE(m_rDialParams.szPassword));
StrCpyN(m_rDialParams.szDomain, rLogon.szDomain, ARRAYSIZE(m_rDialParams.szDomain));
StrCpyN(m_rDialParams.szPhoneNumber, rLogon.szPhoneNumber, ARRAYSIZE(m_rDialParams.szPhoneNumber));
// Save the dial params
if (RasSetEntryDialParams(NULL, &m_rDialParams, !rLogon.fSavePassword))
{
Assert(FALSE);
TrapError(E_FAIL);
}
}
// RAID-26845 - RAS Transport: Canceling RAS Logon doesn't cancel
else
{
hr = TrapError(IXP_E_USER_CANCEL);
goto exit;
}
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::DropConnection
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::DropConnection(void)
{
// Thread Safety
EnterCriticalSection(&m_cs);
// Hangup
if (m_hConn)
FRasHangupAndWait(DEF_HANGUP_WAIT);
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return S_OK;
}
// --------------------------------------------------------------------------------
// CRASTransport::Disconnect
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::Disconnect(void)
{
// Locals
HRESULT hr=S_OK;
// Thread Safety
EnterCriticalSection(&m_cs);
// If not using RAS, who give a crap
if (RAS_CONNECT_RAS != m_rServer.rasconntype)
{
Assert(m_hConn == NULL);
Assert(m_fConnOwner == FALSE);
goto exit;
}
// Do we have a RAS connection
if (m_hConn)
{
if (m_pCallback->OnDisconnect(m_szConnectoid, (boolean) !!m_fConnOwner, this) == S_OK)
FRasHangupAndWait(DEF_HANGUP_WAIT);
}
// Pretend the connection is owned by the user
m_hConn = NULL;
m_fConnOwner = FALSE;
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::IsState
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::IsState(IXPISSTATE isstate)
{
// Locals
HRESULT hr=S_FALSE;
// Thread Safety
EnterCriticalSection(&m_cs);
// Initialized
if (NULL == m_pCallback)
{
hr = TrapError(IXP_E_NOT_INIT);
goto exit;
}
// Lets validate m_hConn first
if (NULL != m_hConn)
{
// Get Connection Status
RASCONNSTATUS rcs;
DWORD dwError;
// Setup Structure Size
rcs.dwSize = sizeof(RASCONNSTATUS);
// Get Ras Connection Status
dwError = RasGetConnectStatus(m_hConn, &rcs);
// Failure or not connected
if (dwError || rcs.dwError || RASCS_Disconnected == rcs.rasconnstate)
{
m_fConnOwner = FALSE;
m_hConn = NULL;
*m_szConnectoid = '\0';
}
}
// Handle IsType
switch(isstate)
{
// Are we connected
case IXP_IS_CONNECTED:
hr = (m_hConn) ? S_OK : S_FALSE;
break;
// Are we busy
case IXP_IS_BUSY:
if (NULL == m_hConn)
hr = IXP_E_NOT_CONNECTED;
else
hr = S_FALSE;
break;
// Are we busy
case IXP_IS_READY:
if (NULL == m_hConn)
hr = IXP_E_NOT_CONNECTED;
else
hr = S_OK;
break;
// Have we been authenticated yet
case IXP_IS_AUTHENTICATED:
if (NULL == m_hConn)
hr = IXP_E_NOT_CONNECTED;
else
hr = S_OK;
break;
// Unhandled ixpistype
default:
IxpAssert(FALSE);
break;
}
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::GetServerInfo
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::GetServerInfo(LPINETSERVER pInetServer)
{
// check params
if (NULL == pInetServer)
return TrapError(E_INVALIDARG);
// Thread Safety
EnterCriticalSection(&m_cs);
// Copy Server information
CopyMemory(pInetServer, &m_rServer, sizeof(INETSERVER));
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return S_OK;
}
// --------------------------------------------------------------------------------
// CRASTransport::GetIXPType
// --------------------------------------------------------------------------------
STDMETHODIMP_(IXPTYPE) CRASTransport::GetIXPType(void)
{
return IXP_RAS;
}
// --------------------------------------------------------------------------------
// CRASTransport::InetServerFromAccount
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::InetServerFromAccount(IImnAccount *pAccount, LPINETSERVER pInetServer)
{
return E_NOTIMPL;
}
// --------------------------------------------------------------------------------
// CRASTransport::FEnumerateConnections
// --------------------------------------------------------------------------------
BOOL CRASTransport::FEnumerateConnections(LPRASCONN *pprgConn, ULONG *pcConn)
{
// Locals
HRESULT hr=S_OK;
DWORD dw,
dwSize;
BOOL fResult=FALSE;
// Check Params
Assert(pprgConn && pcConn);
// Init
*pprgConn = NULL;
*pcConn = 0;
// Sizeof my buffer
dwSize = sizeof(RASCONN);
// Allocate enough for 1 ras connection info object
CHECKHR(hr = HrAlloc((LPVOID *)pprgConn, dwSize));
// Buffer size
(*pprgConn)->dwSize = dwSize;
// Enumerate ras connections
dw = RasEnumConnections(*pprgConn, &dwSize, pcConn);
// Not enough memory ?
if (dw == ERROR_BUFFER_TOO_SMALL)
{
// Reallocate
CHECKHR(hr = HrRealloc((LPVOID *)pprgConn, dwSize));
*pcConn = 0;
(*pprgConn)->dwSize = sizeof(RASCONN);
dw = RasEnumConnections(*pprgConn, &dwSize, pcConn);
}
// If still failed
if (dw)
{
AssertSz(FALSE, "RasEnumConnections failed");
goto exit;
}
// Success
fResult = TRUE;
exit:
// Done
return fResult;
}
// --------------------------------------------------------------------------------
// CRASTransport::FFindConnection
// --------------------------------------------------------------------------------
BOOL CRASTransport::FFindConnection(LPSTR pszConnectoid, LPHRASCONN phConn)
{
// Locals
ULONG cConn,
i;
LPRASCONN prgConn=NULL;
BOOL fResult=FALSE;
// Check Params
Assert(pszConnectoid && phConn);
// Init
*phConn = NULL;
// Enumerate Connections
if (!FEnumerateConnections(&prgConn, &cConn))
goto exit;
// If still failed
for (i=0; i<cConn; i++)
{
if (lstrcmpi(prgConn[i].szEntryName, pszConnectoid) == 0)
{
*phConn = prgConn[i].hrasconn;
fResult = TRUE;
goto exit;
}
}
exit:
// Cleanup
SafeMemFree(prgConn);
// Done
return fResult;
}
// --------------------------------------------------------------------------------
// CRASTransport::FRasHangupAndWait
// --------------------------------------------------------------------------------
BOOL CRASTransport::FRasHangupAndWait(DWORD dwMaxWaitSeconds)
{
// Locals
RASCONNSTATUS rcs;
DWORD dwTicks=GetTickCount();
// Check Params
Assert(m_hConn);
if (NULL == m_hConn || RasHangup(m_hConn))
{
m_hConn = NULL;
m_fConnOwner = FALSE;
*m_szConnectoid = '\0';
return FALSE;
}
// Wait for connection to really close
ZeroMemory(&rcs, sizeof(RASCONNSTATUS));
rcs.dwSize = sizeof(RASCONNSTATUS);
while (RasGetConnectStatus(m_hConn, &rcs) == 0 && 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);
// Reset
m_hConn = NULL;
m_fConnOwner = FALSE;
*m_szConnectoid = '\0';
// Done
return TRUE;
}
// --------------------------------------------------------------------------------
// CRASTransport::FillConnectoidCombo
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::FillConnectoidCombo(HWND hwndComboBox, boolean fUpdateOnly, DWORD *pdwRASResult)
{
// Locals
HRESULT hr=S_OK;
// check params
if (NULL == hwndComboBox || FALSE == IsWindow(hwndComboBox))
return TrapError(E_INVALIDARG);
// Thread Safety
EnterCriticalSection(&m_cs);
// Call global function
CHECKHR(hr = HrFillRasCombo(hwndComboBox, fUpdateOnly, pdwRASResult));
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::EditConnectoid
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::EditConnectoid(HWND hwndParent, LPSTR pszConnectoid, DWORD *pdwRASResult)
{
// Locals
HRESULT hr=S_OK;
// check params
if (NULL == pszConnectoid)
return TrapError(E_INVALIDARG);
// Thread Safety
EnterCriticalSection(&m_cs);
// Call general function
CHECKHR(hr = HrEditPhonebookEntry(hwndParent, pszConnectoid, pdwRASResult));
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::GetRasErrorString
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::GetRasErrorString(UINT uRasErrorValue, LPSTR pszErrorString, ULONG cchMax, DWORD *pdwRASResult)
{
// Locals
HRESULT hr=S_OK;
// check params
if (NULL == pdwRASResult || 0 == uRasErrorValue || NULL == pszErrorString || cchMax <= 1)
return TrapError(E_INVALIDARG);
// Thread Safety
EnterCriticalSection(&m_cs);
// Make Sure RAS is Loaded
CHECKHR(hr = HrLoadRAS());
// Call RAS Function
*pdwRASResult = RasGetErrorString(uRasErrorValue, pszErrorString, cchMax);
if (*pdwRASResult)
{
hr = TrapError(IXP_E_RAS_ERROR);
goto exit;
}
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CRASTransport::CreateConnectoid
// --------------------------------------------------------------------------------
STDMETHODIMP CRASTransport::CreateConnectoid(HWND hwndParent, DWORD *pdwRASResult)
{
// Locals
HRESULT hr=S_OK;
// Thread Safety
EnterCriticalSection(&m_cs);
// Call General Function
CHECKHR(hr = HrCreatePhonebookEntry(hwndParent, pdwRASResult));
exit:
// Thread Safety
LeaveCriticalSection(&m_cs);
// Done
return hr;
}