Windows2003-3790/inetcore/wininet/dll/iedial.cxx
2020-09-30 16:53:55 +02:00

1993 lines
48 KiB
C++

#include "wininetp.h"
#include "autodial.h"
#include "rashelp.h"
#define TAPI_CURRENT_VERSION 0x00010004
#include <tapi.h>
void PostString(HWND hDlg, LPWSTR pszString);
void GetDialErrorString(DWORD dwError, LPWSTR pszBuffer, DWORD dwLength);
void SetDialError(HWND hDlg, DWORD dwError);
UINT_PTR
SendDialmonMessage(
UINT uMessage,
BOOL fPost
);
// function prototype in inetcpl to launch connections tab
typedef BOOL (WINAPI *LAUNCHCPL)(HWND);
//
// Globals
//
BOOL g_fRegisterWndProc = FALSE;
#define REGSTR_DIAL_AUTOCONNECTW L"AutoConnect"
typedef struct _tagRASCONNSTATEMAP {
RASCONNSTATE rascs;
UINT uResourceID;
} RASCONNSTATEMAP;
RASCONNSTATEMAP rgRasStates[] = {
{ RASCS_OpenPort, IDS_DIALING },
{ RASCS_AllDevicesConnected, IDS_CONNECTED },
{ RASCS_Authenticate, IDS_AUTHENTICATE },
{ RASCS_Disconnected, IDS_DISCONNECTED },
{ (RASCONNSTATE)0, 0 }
};
PROPMAP g_PropertyMap[] = {
{DIALPROP_USERNAME, PropUserName },
{DIALPROP_PASSWORD, PropPassword },
{DIALPROP_DOMAIN, PropDomain },
{DIALPROP_SAVEPASSWORD, PropSavePassword },
{DIALPROP_PHONENUMBER, PropPhoneNumber },
{DIALPROP_REDIALCOUNT, PropRedialCount },
{DIALPROP_REDIALINTERVAL, PropRedialInterval },
{DIALPROP_LASTERROR, PropLastError },
{DIALPROP_RESOLVEDPHONE, PropResolvedPhone }
};
#define NUM_DIALPROPS (sizeof(g_PropertyMap) / sizeof(PROPMAP))
//////////////////////////////////////////////////////////////////////////////
//
// CDialEngine implementation
//
//////////////////////////////////////////////////////////////////////////////
CDialEngine::CDialEngine()
{
m_cRef = 0;
m_pdes = NULL;
m_rcs = RASCS_Disconnected;
m_fCurrentlyDialing = FALSE;
memset(&m_rdp, 0, sizeof(m_rdp));
memset(&m_rcred, 0, sizeof(m_rcred));
m_fPassword = FALSE;
m_fSavePassword = FALSE;
m_dwError = 0;
// must be initialized to zero -- RasDial will fail (!) if this is anything
// other than 0 when passed in to receive conn handle!!
m_hConn = NULL;
m_rdp.dwSize = sizeof(m_rdp);
EnsureRasLoaded();
if(FALSE == g_fRegisterWndProc)
{
// register window class for dialing engine
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = CDialEngine::EngineWndProc;
wc.hInstance = GlobalDllHandle;
wc.lpszClassName = "DialEngine";
RegisterClass(&wc);
g_fRegisterWndProc = TRUE;
}
}
CDialEngine::~CDialEngine()
{
SAFE_RELEASE(m_pdes);
if(m_hwnd)
{
DestroyWindow(m_hwnd);
}
}
//
// IUnknown members
//
STDMETHODIMP_(ULONG) CDialEngine::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CDialEngine::Release(void)
{
if( 0L != --m_cRef )
return m_cRef;
delete this;
return 0L;
}
STDMETHODIMP CDialEngine::QueryInterface(REFIID riid, void ** ppv)
{
*ppv = NULL;
// Validate requested interface
if ((IID_IUnknown == riid) ||
(IID_IDialEngine == riid))
{
*ppv = (IDialEngine *)this;
}
else
{
return E_NOINTERFACE;
}
// Addref through the interface
((LPUNKNOWN)*ppv)->AddRef();
return S_OK;
}
//
// IDialEngine members
//
STDMETHODIMP
CDialEngine::Initialize(
LPCWSTR pwzConnectoid,
IDialEventSink *pIDES
)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::Initialize",
"%#x (%Q), %#x",
pwzConnectoid,
pwzConnectoid,
pIDES
));
// save off stuff
m_pdes = pIDES;
m_pdes->AddRef();
StrCpyW(m_rdp.szEntryName, pwzConnectoid);
m_rdp.dwSize = sizeof(m_rdp);
// get stats from RAS
RasEntryDialParamsHelp re;
if(re.GetW(NULL, &m_rdp, &m_fPassword))
{
DEBUG_LEAVE(E_INVALIDARG);
return E_INVALIDARG;
}
if(IsOS(OS_WHISTLERORGREATER))
{
// on whistler, use RasGetCredentials instead to preserve settings
m_rcred.dwSize = sizeof(m_rcred);
m_rcred.dwMask = RASCM_UserName | RASCM_Password;
if(_RasGetCredentialsW(NULL, pwzConnectoid, &m_rcred))
{
DEBUG_LEAVE(E_INVALIDARG);
return E_INVALIDARG;
}
DEBUG_PRINT(DIALUP, INFO, ("Name=<%ws>, PW=<%ws>, dwMask=%x\n", m_rcred.szUserName, m_rcred.szPassword, m_rcred.dwMask));
m_fPassword = (m_rcred.dwMask & RASCM_Password) ? TRUE : FALSE;
}
// read redial properties
GetRedialParameters((LPWSTR)pwzConnectoid, &m_dwTryTotal, &m_dwWaitTotal);
m_dwTryCurrent = 0;
m_dwWaitCurrent = 0;
// register the ras message
m_uRasMsg = RegisterWindowMessageA(RASDIALEVENT);
if(0 == m_uRasMsg)
m_uRasMsg = WM_RASDIALEVENT;
// create the window to get ras callbacks.
m_hwnd = CreateWindowA(
"DialEngine",
"DialEngine",
WS_OVERLAPPED,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
GlobalDllHandle,
NULL
);
if(NULL == m_hwnd)
{
DEBUG_LEAVE(E_OUTOFMEMORY);
return E_OUTOFMEMORY;
}
// tell window our this pointer
SendMessage(m_hwnd, WM_USER, 0, (LPARAM)this);
// get current connected state from RAS
UpdateRasState();
DEBUG_LEAVE(S_OK);
return S_OK;
}
STDMETHODIMP
CDialEngine::GetProperty(
LPCWSTR pwzProperty,
LPWSTR pwzValue,
DWORD dwBufSize
)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::GetProperty",
"%#x (%Q), %#x, %#x",
pwzProperty,
pwzProperty,
pwzValue,
dwBufSize
));
HRESULT hr = E_INVALIDARG;
WCHAR * pwzSrc = NULL;
RasEntryPropHelp *pre = new RasEntryPropHelp;
switch(PropertyToOrdinal(pwzProperty))
{
case PropUserName:
pwzSrc = m_rdp.szUserName;
break;
case PropPassword:
if(m_fPassword)
{
pwzSrc = m_rdp.szPassword;
}
else
{
hr = S_FALSE;
}
break;
case PropDomain:
pwzSrc = m_rdp.szDomain;
break;
case PropSavePassword:
if(m_fSavePassword)
{
pwzSrc = L"TRUE";
}
else
{
pwzSrc = L"FALSE";
}
break;
case PropResolvedPhone:
if(ResolvePhoneNumber(pwzValue, dwBufSize))
{
hr = S_OK;
break;
}
//
// failed to get nicely formatted phone number, fall through to basic one
//
case PropPhoneNumber:
if (pre == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
pre->GetW(m_rdp.szEntryName);
pwzSrc = pre->GetPhoneNumberW();
}
break;
case PropRedialCount:
DEBUG_PRINT(DIALUP, INFO, ("Prop value = %d\n", m_dwTryTotal));
wnsprintfW(pwzValue, dwBufSize, L"%d", m_dwTryTotal);
hr = S_OK;
break;
case PropRedialInterval:
DEBUG_PRINT(DIALUP, INFO, ("Prop value = %d\n", m_dwWaitTotal));
wnsprintfW(pwzValue, dwBufSize, L"%d", m_dwWaitTotal);
hr = S_OK;
break;
case PropLastError:
GetDialErrorString(m_dwError, pwzValue, dwBufSize);
DEBUG_PRINT(DIALUP, INFO, ("Prop value = %ws\n", pwzValue));
hr = S_OK;
break;
}
if(pwzSrc)
{
DEBUG_PRINT(DIALUP, INFO, ("Prop value = %ws\n", pwzSrc));
StrCpyNW(pwzValue, pwzSrc, dwBufSize);
hr = S_OK;
}
if (pre)
delete pre;
DEBUG_LEAVE(hr);
return hr;
}
STDMETHODIMP
CDialEngine::SetProperty(
LPCWSTR pwzProperty,
LPCWSTR pwzValue
)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::SetProperty",
"%#x (%Q), %#x (%Q)",
pwzProperty,
pwzProperty,
pwzValue,
pwzValue
));
HRESULT hr = E_INVALIDARG;
WCHAR * pwzDest = NULL;
DWORD dwMaxLength = 0;
WCHAR wcNull = 0;
// treat NULL values as emtpy values
if(NULL == pwzValue)
{
pwzValue = &wcNull;
}
switch(PropertyToOrdinal(pwzProperty))
{
case PropUserName:
pwzDest = m_rdp.szUserName;
dwMaxLength = UNLEN;
if(IsOS(OS_WHISTLERORGREATER))
{
StrCpyNW(m_rcred.szUserName, pwzValue, dwMaxLength);
}
break;
case PropPassword:
pwzDest = m_rdp.szPassword;
dwMaxLength = PWLEN;
m_fPassword = TRUE;
if(IsOS(OS_WHISTLERORGREATER))
{
StrCpyNW(m_rcred.szPassword, pwzValue, dwMaxLength);
}
break;
case PropDomain:
pwzDest = m_rdp.szDomain;
dwMaxLength = DNLEN;
break;
case PropSavePassword:
if(!StrCmpIW(pwzValue, L"TRUE"))
{
m_fSavePassword = TRUE;
}
else
{
m_fSavePassword = FALSE;
}
if(FALSE == m_fSavePassword)
{
m_fPassword = FALSE;
}
hr = S_OK;
break;
case PropPhoneNumber:
pwzDest = m_rdp.szPhoneNumber;
dwMaxLength = RAS_MaxPhoneNumber;
break;
case PropRedialCount:
m_dwTryTotal = StrToIntW(pwzValue);
if(0 == m_dwTryTotal)
{
m_dwTryTotal = DEFAULT_DIAL_ATTEMPTS;
}
hr = S_OK;
break;
case PropRedialInterval:
m_dwWaitTotal = StrToIntW(pwzValue);
if(0 == m_dwWaitTotal)
{
m_dwWaitTotal = DEFAULT_DIAL_INTERVAL;
}
hr = S_OK;
break;
default:
hr = E_UNEXPECTED;
break;
}
if(pwzDest)
{
StrCpyNW(pwzDest, pwzValue, dwMaxLength);
hr = S_OK;
}
DEBUG_LEAVE(hr);
return hr;
}
STDMETHODIMP
CDialEngine::StartConnection()
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::StartConnection",
NULL
));
m_dwTryCurrent++;
m_pdes->OnEvent(DIALENG_RedialAttempt, m_dwTryCurrent);
RasDialHelp RasDial(NULL, NULL, &m_rdp, 0xFFFFFFFF, m_hwnd, &m_hConn);
if(0 != RasDial.GetError()) {
// Clean up since RAS may return a connection anyway...
CleanConnection();
m_dwError = ERROR_NO_CONNECTION;
EndOfOperation();
DEBUG_PRINT(DIALUP, INFO, ("Bailing - RasDial error\n"));
DEBUG_LEAVE(E_FAIL);
return E_FAIL;
}
DEBUG_LEAVE(S_OK);
return S_OK;
}
STDMETHODIMP
CDialEngine::Dial()
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::Dial",
NULL
));
HRESULT hr;
if(m_fCurrentlyDialing)
{
DEBUG_PRINT(DIALUP, INFO, ("Bailing - m_fCurentlyDialing\n"));
DEBUG_LEAVE(S_FALSE);
return S_FALSE;
}
// find out if our connection state has changed in the mean time
UpdateRasState();
// we have begun...
m_fCurrentlyDialing = TRUE;
if(m_rcs == RASCS_Connected)
{
DEBUG_PRINT(DIALUP, INFO, ("Bailing - already connected\n"));
m_dwError = ERROR_SUCCESS;
EndOfOperation();
DEBUG_LEAVE(S_FALSE);
return S_FALSE;
}
m_dwError = 0;
m_dwTryCurrent = 0;
hr = StartConnection();
DEBUG_LEAVE(hr);
return hr;
}
STDMETHODIMP
CDialEngine::CleanConnection()
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::CleanConnection",
NULL
));
HRESULT hr = S_FALSE;
// make sure we see if we've connected in the mean time
UpdateRasState();
DEBUG_PRINT(DIALUP, INFO, ("m_hConn=%x\n", m_hConn));
// hang up connection if we got one
if(m_hConn)
{
HRASCONN hConn = m_hConn;
m_hConn = NULL;
_RasHangUp(hConn);
hr = S_OK;
}
DEBUG_LEAVE(hr);
return hr;
}
STDMETHODIMP
CDialEngine::HangUp()
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::HangUp",
NULL
));
HRESULT hr;
// hang up or abort any pending dials
hr = CleanConnection();
// make sure no pending timers
if(m_uTimerId)
{
KillTimer(m_hwnd, m_uTimerId);
m_uTimerId = 0;
}
// calling hangup causes ras events to end
if(0 == m_dwError)
{
m_dwError = ERROR_USER_DISCONNECTION;
}
EndOfOperation();
DEBUG_LEAVE(hr);
return hr;
}
STDMETHODIMP
CDialEngine::GetConnectedState(
DWORD *pdwState)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::GetConnectedState",
NULL
));
*pdwState = MapRCS(m_rcs);
DEBUG_LEAVE(S_OK);
return S_OK;
}
STDMETHODIMP
CDialEngine::GetConnectHandle(
DWORD_PTR *pdwHandle
)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::GetConnectHandle",
NULL
));
if(RASCS_Connected == m_rcs)
{
*pdwHandle = (DWORD_PTR)m_hConn;
DEBUG_LEAVE(S_OK);
return S_OK;
}
else
{
*pdwHandle = 0;
DEBUG_LEAVE(S_FALSE);
return S_FALSE;
}
}
//
// private members
//
LONG_PTR CALLBACK
CDialEngine::EngineWndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::EngineWndProc",
"%#x, %#x, %#x, %#x",
hwnd,
uMsg,
wParam,
lParam
));
CDialEngine * peng = (CDialEngine *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(uMsg == WM_USER)
{
peng = (CDialEngine *)lParam;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (DWORD_PTR)peng);
}
else if(peng && uMsg == peng->m_uRasMsg)
{
peng->OnRasEvent((RASCONNSTATE)wParam, (DWORD)lParam);
}
else if(peng && uMsg == WM_TIMER)
{
peng->OnTimer();
}
DEBUG_LEAVE(0);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
VOID
CDialEngine::OnTimer()
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialEngine::OnTimer",
NULL
));
if(0 == m_dwError)
{
m_dwWaitCurrent--;
if(0 == m_dwWaitCurrent)
{
// kick off dial
KillTimer(m_hwnd, m_uTimerId);
m_uTimerId = 0;
StartConnection();
}
else
{
// update sink
// m_pdes->OnEvent(DIALENG_RedialWait, m_dwWaitCurrent);
}
}
DEBUG_LEAVE(0);
}
VOID
CDialEngine::OnRasEvent(
RASCONNSTATE rcs,
DWORD dwError
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialEngine::OnRasEvent",
"%#x, %#x",
(DWORD)rcs,
dwError
));
// save rasconnstate
m_rcs = rcs;
// forward event to UI object
m_pdes->OnEvent(MapRCS(rcs), dwError);
// handle the dial state
if(dwError != SUCCESS) {
// win95 returns this error if authentication failed.
if(ERROR_UNKNOWN == dwError)
dwError = ERROR_AUTHENTICATION_FAILURE;
// save error if we don't already have one
if(0 == m_dwError && dwError)
{
m_dwError = dwError;
}
// clean up connection
CleanConnection();
switch(dwError) {
case ERROR_AUTHENTICATION_FAILURE:
memset(m_rdp.szPassword, 0, ARRAYSIZE(m_rdp.szPassword));
EndOfOperation();
break;
case ERROR_USER_DISCONNECTION:
// we hit cancel and called RasHangUp. Nothing to do here -
// cancel code has cleaned up as necessary.
EndOfOperation();
break;
case ERROR_LINE_BUSY:
case ERROR_NO_ANSWER:
case ERROR_NO_CARRIER:
if(m_dwTryCurrent < m_dwTryTotal)
{
m_dwError = 0;
m_dwWaitCurrent = m_dwWaitTotal;
m_uTimerId = SetTimer(m_hwnd, 1, 1000, NULL);
m_pdes->OnEvent(DIALENG_RedialWait, m_dwWaitCurrent);
break;
}
// fall through
default:
EndOfOperation();
}
} else {
// we're getting status
if(rcs == RASCS_Connected)
{
// we're done
m_dwError = ERROR_SUCCESS;
EndOfOperation();
DEBUG_PRINT(DIALUP, INFO, ("Connected: m_fPassword=%B, m_fSavePassword=%B\n", m_fPassword, m_fSavePassword));
if(IsOS(OS_WHISTLERORGREATER))
{
// delete/write/leave alone semantics
//
// m_fPassword m_fSavePassword result
// T T Write password
// F F Delete password
// T F Leave password alone
// F T Never happens
if(!m_fPassword && !m_fSavePassword)
{
// delete case, only want password mask
m_rcred.dwMask = 0;
}
if(m_fPassword == m_fSavePassword)
{
// write or delete case
// always need password flag
m_rcred.dwMask |= RASCM_Password;
// write or delete, depend on m_fSavePassword
DEBUG_PRINT(DIALUP, INFO, ("Name=<%ws>, PW=<%ws>, dwMask=%x\n", m_rcred.szUserName, m_rcred.szPassword, m_rcred.dwMask));
_RasSetCredentialsW(NULL, m_rdp.szEntryName, &m_rcred, !m_fSavePassword);
}
}
else
{
if(m_fPassword == m_fSavePassword)
{
// save or delete password
RasEntryDialParamsHelp re;
re.SetW(NULL, &m_rdp, !m_fSavePassword);
}
}
// inform dialmon that we've dialed
SendDialmonMessage(WM_SET_CONNECTOID_NAME, TRUE);
}
}
DEBUG_LEAVE(0);
}
DWORD
CDialEngine::MapRCS(RASCONNSTATE rcs)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialEngine::MapRCS",
"%#x",
(DWORD)rcs
));
DEBUG_LEAVE((DWORD)rcs);
return (DWORD)rcs;
}
DIALPROP
CDialEngine::PropertyToOrdinal(LPCWSTR pwzProperty)
{
long i;
for(i=0; i<NUM_DIALPROPS; i++)
{
if(!StrCmpIW(g_PropertyMap[i].pwzProperty, pwzProperty))
{
return g_PropertyMap[i].Prop;
}
}
return PropInvalid;
}
VOID
CDialEngine::UpdateRasState()
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialEngine::UpdateRasState",
NULL
));
DEBUG_PRINT(DIALUP, INFO, ("m_fCurrentlyDialing = %B\n", m_fCurrentlyDialing));
//
// only do this if not dialing. If we are, OnRasEvent will update
// state appropriately.
//
if(FALSE == m_fCurrentlyDialing)
{
RasEnumConnHelp re;
re.Enum();
DEBUG_PRINT(DIALUP, INFO, ("Checking for connections\n"));
// set state to disconnected and try to find a connection
m_rcs = RASCS_Disconnected;
if(0 == re.GetError())
{
DWORD dwCount;
for(dwCount = 0; dwCount < re.GetConnectionsCount(); dwCount++)
{
if(0 == StrCmpW(re.GetEntryW(dwCount), m_rdp.szEntryName))
{
DEBUG_PRINT(DIALUP, INFO, ("Found connection\n"));
m_hConn = re.GetHandle(dwCount);
m_rcs = RASCS_Connected;
}
}
}
}
DEBUG_LEAVE(0);
}
VOID
CDialEngine::EndOfOperation()
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialEngine::EndOfOperation",
NULL
));
if(m_fCurrentlyDialing)
{
// called when a dialing operation is done
m_fCurrentlyDialing = FALSE;
m_dwTryCurrent = 0;
// notify sink that no more events are forthcoming
m_pdes->OnEvent(DIALENG_OperationComplete, m_dwError);
}
DEBUG_LEAVE(0);
}
VOID FAR CALLBACK TapiCallback(
DWORD hDevice,
DWORD dwMsg,
DWORD_PTR dwCallbackInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2,
DWORD_PTR dwParam3
)
{
}
BOOL
CDialEngine::ResolvePhoneNumber(LPWSTR pwzBuffer, DWORD dwLen)
{
char *pszTemp = NULL;
WCHAR szCanonical[128];
CHAR szAnsiCanonical[128];
CHAR *pszResolved;
long lErr, i;
BOOL fResult = FALSE;
RasEntryPropHelp *pre = new RasEntryPropHelp;
if (pre == NULL)
{
goto Cleanup;
}
pszTemp = (char *) ALLOCATE_FIXED_MEMORY(4096);
if (pszTemp == NULL)
{
goto Cleanup;
}
// look up RAS entry
pre->GetW(m_rdp.szEntryName);
if(pre->GetError())
{
goto Cleanup;
}
if(pre->GetOptions() & RASEO_UseCountryAndAreaCodes)
{
PWSTR pszAreaCode = pre->GetAreaCodeW();
HLINEAPP hApp;
DWORD dwNumDevs;
// make TAPI canonical phone number
wnsprintfW(szCanonical, 128, L"+%d (%ws) %ws", pre->GetCountryCode(), pszAreaCode ? pszAreaCode : L"", pre->GetPhoneNumberW());
// ask TAPI to translate it
LPLINETRANSLATEOUTPUT lpOut = (LPLINETRANSLATEOUTPUT)pszTemp;
lpOut->dwTotalSize = 4096;
lErr = lineInitialize(&hApp, GlobalDllHandle, TapiCallback, "Wininet", &dwNumDevs);
if(lErr)
{
goto Cleanup;
}
WideCharToMultiByte(CP_ACP, 0, szCanonical, -1, szAnsiCanonical, 128, NULL, NULL);
lErr = lineTranslateAddress(hApp, 0, TAPI_CURRENT_VERSION, szAnsiCanonical, 0, 0, lpOut);
if(lErr)
{
goto Cleanup;
}
pszResolved = (CHAR *)((char *)lpOut + lpOut->dwDisplayableStringOffset);
i = MultiByteToWideChar(CP_ACP, 0, pszResolved, -1, pwzBuffer, dwLen);
if(0 == i)
{
pwzBuffer[dwLen] = 0; // truncated - null terminate
}
}
else
{
// TAPI resolution not turned on, just return straight phone number
StrCpyNW(pwzBuffer, pre->GetPhoneNumberW(), dwLen);
}
fResult = TRUE;
Cleanup:
if (pre)
delete pre;
if (pszTemp)
FREE_MEMORY(pszTemp);
return fResult;
}
//////////////////////////////////////////////////////////////////////////////
//
// CDialUI implementation
//
//////////////////////////////////////////////////////////////////////////////
CDialUI::CDialUI(HWND hwndParent)
{
m_cRef = 0;
m_pEng = NULL;
m_pdb = NULL;
m_State = UISTATE_Interactive;
m_fOfflineSemantics = FALSE;
m_fSavePassword = FALSE;
m_fPasswordChanged = FALSE;
m_fAutoConnect = FALSE;
m_fCDH = FALSE;
m_fDialedCDH = FALSE;
memset(&m_cdh, 0, sizeof(m_cdh));
if(hwndParent)
{
m_hwndParent = hwndParent;
}
else
{
m_hwndParent = GetDesktopWindow();
}
}
CDialUI::~CDialUI()
{
SAFE_RELEASE(m_pEng);
SAFE_RELEASE(m_pdb);
}
//
// IUnknown members
//
STDMETHODIMP_(ULONG) CDialUI::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CDialUI::Release(void)
{
if( 0L != --m_cRef )
return m_cRef;
delete this;
return 0L;
}
STDMETHODIMP CDialUI::QueryInterface(REFIID riid, void ** ppv)
{
*ppv=NULL;
// Validate requested interface
if ((IID_IUnknown == riid) ||
(IID_IDialEventSink == riid))
{
*ppv = (IDialEventSink *)this;
}
else
{
return E_NOINTERFACE;
}
// Addref through the interface
((LPUNKNOWN)*ppv)->AddRef();
return S_OK;
}
//
// IDialUI members
//
DWORD
CDialUI::StartDial(
IN DIALSTATE *pDial,
IN DWORD dwFlags
)
//
//
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialUI::StartDial",
"%#x, %#x",
pDial,
dwFlags
));
DWORD dwSize, dwTemp, dwType;
WCHAR szKey[MAX_PATH];
// save passed info
m_dwFlags = dwFlags;
m_pDial = pDial;
m_pDial->dwResult = 0;
// check for connect automatically
dwSize = sizeof(DWORD);
dwTemp = 0;
GetConnKeyW(pDial->params.szEntryName, szKey, ARRAYSIZE(szKey));
if(0 == (dwFlags & INTERNET_DIAL_FORCE_PROMPT) &&
ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey,
REGSTR_DIAL_AUTOCONNECTW, &dwType, &dwTemp, &dwSize) && dwTemp)
{
m_fAutoConnect = TRUE;
}
//
// Get some UI going
//
ULONG_PTR uCookie = 0;
SHActivateContext(&uCookie);
if(-1 == DialogBoxParamWrapW(GlobalDllHandle, MAKEINTRESOURCEW(IDD_CONNECT_TO),
m_hwndParent, CDialUI::DialogProc, (LPARAM)this))
{
// couldn't create dialog for some reason - no mem?
m_pDial->dwResult = ERROR_OUTOFMEMORY;
}
if (uCookie)
{
SHDeactivateContext(uCookie);
}
// prop odds and ends back to data so caller is happy
if(!m_fCDH)
{
m_pDial->dwFlags = 0;
if(m_fAutoConnect)
{
m_pDial->dwFlags |= CI_AUTO_CONNECT;
}
if(m_pEng)
{
m_pEng->GetConnectHandle((DWORD_PTR *)&m_pDial->hConn);
}
}
else
{
m_pDial->hConn = (HRASCONN)CDH_HCONN;
}
//
// Clean up
//
SAFE_RELEASE(m_pEng);
DEBUG_LEAVE(m_pDial->dwResult);
return m_pDial->dwResult;
}
STDMETHODIMP
CDialUI::OnEvent(
DWORD dwEvent,
DWORD dwStatus
)
{
DEBUG_ENTER((DBG_DIALUP,
Dword,
"CDialUI::OnEvent",
"%#x, %#x",
dwEvent,
dwStatus
));
WCHAR pszText[128], pszTemplate[128];
INT idRes;
// find string for this state (if any)
for (int nIndex = 0; rgRasStates[nIndex].uResourceID != 0; nIndex++)
{
if ((RASCONNSTATE)dwEvent == rgRasStates[nIndex].rascs) {
LoadStringWrapW(GlobalDllHandle, rgRasStates[nIndex].uResourceID,
pszText, 128);
PostString(m_hwnd, pszText);
}
}
switch(dwEvent)
{
case DIALENG_RedialAttempt:
case DIALENG_RedialWait:
idRes = IDS_REDIAL_ATTEMPT;
if(dwEvent == DIALENG_RedialWait)
{
idRes = IDS_REDIAL_WAIT;
}
LoadStringWrapW(GlobalDllHandle, idRes, pszTemplate, 128);
wnsprintfW(pszText, ARRAYSIZE(pszText), pszTemplate, dwStatus);
PostString(m_hwnd, pszText);
break;
case DIALENG_OperationComplete:
m_pDial->dwResult = dwStatus;
if(0 == dwStatus || m_State == UISTATE_Unattended)
{
EndDialog(m_hwnd, 0);
}
else
{
if(dwStatus)
{
// get an error - display it
SetDialError(m_hwnd, dwStatus);
}
m_State = UISTATE_Interactive;
FixUIComponents();
}
break;
}
DEBUG_LEAVE(0);
return NOERROR;
}
VOID
CDialUI::FixUIComponents(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::FixUIComponents",
NULL
));
WCHAR pszTemp[64];
int i;
BOOL fActive = TRUE, fCanSave, fCDHActive = TRUE;
TCHAR szUser[UNLEN+1];
DWORD dwLen = UNLEN;
UINT uIDs[] = {IDC_CONN_TXT, IDC_CONN_LIST, ID_CONNECT, IDC_SETTINGS};
UINT uCDHIDs[] = {IDC_NAME_TXT, IDC_USER_NAME, IDC_PASSWORD_TXT, IDC_PASSWORD};
#define NUM_IDS (sizeof(uIDs) / sizeof(UINT))
#define NUM_CDH_IDS (sizeof(uCDHIDs) / sizeof(UINT))
//
// fix cancel button
//
if(UISTATE_Dialing == m_State || UISTATE_Unattended == m_State || FALSE == m_fOfflineSemantics)
{
i = IDS_CANCEL;
}
else
{
i = IDS_WORK_OFFLINE;
}
LoadStringWrapW(GlobalDllHandle, i, pszTemp, MAX_PATH);
SetWindowTextWrapW(GetDlgItem(m_hwnd, IDCANCEL), pszTemp);
//
// Fix focus
//
if(UISTATE_Dialing == m_State || UISTATE_Unattended == m_State)
{
SetFocus(GetDlgItem(m_hwnd, IDCANCEL));
fActive = FALSE;
}
//
// Grey out appropriate stuff
//
for(i=0; i<NUM_IDS; i++)
{
EnableWindow(GetDlgItem(m_hwnd, uIDs[i]), fActive);
}
for(i=0; i<NUM_CDH_IDS; i++)
{
EnableWindow(GetDlgItem(m_hwnd, uCDHIDs[i]), fActive && !m_fCDH);
}
//
// fix password and auto check boxes
//
fCanSave = (0 != GetUserName(szUser, &dwLen));
EnableWindow(GetDlgItem(m_hwnd, IDC_SAVE_PASSWORD), fActive && fCanSave);
//
// special case - Autoconnect is disabled if save password not checked
// or password cannot be saved
//
EnableWindow(
GetDlgItem(m_hwnd, IDC_AUTOCONNECT),
fCanSave && fActive && IsDlgButtonChecked(m_hwnd, IDC_SAVE_PASSWORD));
DEBUG_LEAVE(0);
}
//
// Other members
//
VOID
CDialUI::OnInitDialog(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::OnInitDialog",
NULL
));
TCHAR szUser[UNLEN+1];
DWORD dwLen = UNLEN;
BOOL fCanSave;
// Fill in the connectoid list
EnumerateConnectoids();
// Get the engine for this connectoid and get relevant properties
GetProps();
// check flags for unattended, etc.
if(GlobalIsProcessExplorer || (m_dwFlags & INTERNET_DIAL_SHOW_OFFLINE))
{
m_fOfflineSemantics = TRUE;
}
if(m_dwFlags & (INTERNET_DIAL_UNATTENDED|INTERNET_AUTODIAL_FORCE_UNATTENDED))
{
// want unattended dial.. do it if we can, else bail out
m_State = UISTATE_Unattended;
if(m_pEng)
{
m_pEng->Dial();
}
else
{
OnCancel();
}
}
// make sure cancel button is correct
FixUIComponents();
// Handle autoconnect
if(m_fAutoConnect)
{
CheckDlgButton(m_hwnd, IDC_AUTOCONNECT, BST_CHECKED);
OnConnect();
}
DEBUG_LEAVE(0);
}
VOID
CDialUI::OnSelChange()
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::OnSelChange",
NULL
));
int iSel;
HWND hwndList = GetDlgItem(m_hwnd, IDC_CONN_LIST);
// yank out new name
iSel = ComboBox_GetCurSel(hwndList);
if(CB_ERR == iSel)
iSel = 0;
SendMessageWrapW(hwndList, CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)m_pDial->params.szEntryName);
// Fill in props for new connection (will get new engine)
GetProps();
DEBUG_LEAVE(0);
}
VOID
CDialUI::OnConnect(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::OnConnect",
NULL
));
// If we have a CDH, call it
if(m_fCDH)
{
if(!CallCDH(m_hwnd, m_pDial->params.szEntryName, &m_cdh, 0, &(m_pDial->dwResult)))
{
// custom dial handler failed to handle dial request, bail out
m_pDial->dwResult = ERROR_USER_DISCONNECTION;
}
m_fDialedCDH = TRUE;
EndDialog(m_hwnd, 0);
DEBUG_LEAVE(0);
return;
}
else
{
// If we don't have an engine, repop conn list (may have been deleted)
// and bail out of dial operation
if(!m_pEng)
{
EnumerateConnectoids();
DEBUG_LEAVE(0);
return;
}
// Save off properties
SaveProps();
}
// TODO grey stuff
m_State = UISTATE_Dialing;
FixUIComponents();
// Stick phone number in progress box
WCHAR szString[256], szPhone[128];
LoadStringWrapW(GlobalDllHandle, IDS_DIALING, szString, 128);
if(SUCCEEDED(m_pEng->GetProperty(DIALPROP_RESOLVEDPHONE, szPhone, 128)))
{
StrNCatW(szString, szPhone, 128);
PostString(m_hwnd, szString);
}
// Start the dialing operation
m_pEng->Dial();
DEBUG_LEAVE(0);
}
VOID
CDialUI::OnCancel(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::OnCancel",
NULL
));
switch(m_State)
{
case UISTATE_Interactive:
//
// exit the dialog box
//
m_pDial->dwResult = ERROR_USER_DISCONNECTION;
EndDialog(m_hwnd, 0);
break;
case UISTATE_Unattended:
case UISTATE_Dialing:
//
// cancel current dialing operation
//
if(m_pEng)
{
m_pEng->HangUp();
}
m_pDial->dwResult = ERROR_USER_DISCONNECTION;
//
// If we were previous "unattended" we aren't any more
//
CheckDlgButton(m_hwnd, IDC_AUTOCONNECT, BST_UNCHECKED);
m_fAutoConnect = FALSE;
//
// fix grey stuff
//
FixUIComponents();
break;
}
DEBUG_LEAVE(0);
}
INT_PTR CALLBACK
CDialUI::DialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
CDialUI * pui = (CDialUI *)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch(uMsg)
{
case WM_INITDIALOG:
SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
pui = (CDialUI *)lParam;
pui->m_hwnd = hwndDlg;
pui->OnInitDialog();
return TRUE;
case WM_COMMAND:
// handle combo box messages
if(HIWORD(wParam) == CBN_SELCHANGE) {
pui->OnSelChange();
break;
}
switch (LOWORD(wParam))
{
case ID_CONNECT:
pui->OnConnect();
break;
case IDCANCEL:
pui->OnCancel();
break;
case IDC_SETTINGS:
{
HMODULE hInetcpl = LoadLibrary("inetcpl.cpl");
if(hInetcpl)
{
LAUNCHCPL cpl = (LAUNCHCPL)GetProcAddress(hInetcpl, "LaunchConnectionDialog");
if(cpl)
{
cpl(hwndDlg);
// refresh to new default if any
AUTODIAL config;
memset(&config, 0, sizeof(config));
IsAutodialEnabled(NULL, &config);
if(config.fEnabled)
{
if(config.fHasEntry)
{
StrCpyW(pui->m_pDial->params.szEntryName, config.pszEntryName);
}
// refresh settings
pui->EnumerateConnectoids();
pui->GetProps();
}
else
{
// nothing to dial... bail out right away.
pui->OnCancel();
}
}
FreeLibrary(hInetcpl);
}
}
break;
case IDC_SAVE_PASSWORD:
EnableWindow(
GetDlgItem(hwndDlg, IDC_AUTOCONNECT),
IsDlgButtonChecked(hwndDlg, IDC_SAVE_PASSWORD));
break;
case IDC_PASSWORD:
if(HIWORD(wParam) == EN_CHANGE)
{
pui->m_fPasswordChanged = TRUE;
}
break;
}
break;
}
return FALSE;
}
VOID
CDialUI::EnumerateConnectoids(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::EnumerateConnectoids",
NULL
));
HWND hwndCombo = GetDlgItem(m_hwnd, IDC_CONN_LIST);
INET_ASSERT(hwndCombo);
ComboBox_ResetContent(hwndCombo);
EnsureRasLoaded();
DWORD dwEntries, dwRet;
RasEnumHelp RasEnum;
dwRet = RasEnum.GetError();
dwEntries = RasEnum.GetEntryCount();
if(ERROR_SUCCESS == dwRet)
{
// insert connectoid names from buffer into combo box
DWORD i;
for(i=0; i<dwEntries; i++)
{
SendMessageWrapW(hwndCombo, CB_ADDSTRING, 0, (LPARAM)RasEnum.GetEntryW(i));
}
// try to find connectoid from pinfo
int iSel = (int)SendMessageWrapW(hwndCombo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)m_pDial->params.szEntryName);
if(CB_ERR == iSel)
{
iSel = 0;
SendMessageWrapW(hwndCombo, CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)m_pDial->params.szEntryName);
}
ComboBox_SetCurSel(hwndCombo, iSel);
}
DEBUG_LEAVE(0);
}
VOID
CDialUI::GetProps(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::GetProps",
NULL
));
WCHAR wzBuffer[256];
HRESULT hr;
CDHINFO cdh;
SAFE_RELEASE(m_pEng);
//
// Find out if new selection is a CDH
//
m_fCDH = IsCDH(m_pDial->params.szEntryName, &m_cdh);
//
// Query for properties for non-CDH connections
//
if(!m_fCDH && SUCCEEDED(InternetGetDialEngineW(m_pDial->params.szEntryName, (IDialEventSink *)this, &m_pEng)))
{
if(FAILED(m_pEng->GetProperty(DIALPROP_USERNAME, wzBuffer, 256)))
{
*wzBuffer = 0;
}
SetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_USER_NAME), wzBuffer);
m_fSavePassword = FALSE;
hr = m_pEng->GetProperty(DIALPROP_PASSWORD, wzBuffer, 256);
if(S_OK == hr)
{
m_fSavePassword = TRUE;
}
else // S_FALSE - no saved password, or error
{
*wzBuffer = 0;
}
SetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_PASSWORD), wzBuffer);
CheckDlgButton(m_hwnd, IDC_SAVE_PASSWORD, m_fSavePassword ? BST_CHECKED : BST_UNCHECKED);
if(FAILED(m_pEng->GetProperty(DIALPROP_DOMAIN, wzBuffer, 256)))
{
*wzBuffer = 0;
}
SetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_DOMAIN), wzBuffer);
}
//
// fix UI based on connectoid type
//
FixUIComponents();
// reset password changed as setting it above will cause the window message
m_fPasswordChanged = FALSE;
DEBUG_LEAVE(0);
}
VOID
CDialUI::SaveProps(
)
{
DEBUG_ENTER((DBG_DIALUP,
None,
"CDialUI::SaveProps",
NULL
));
WCHAR wzBuffer[256];
GetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_USER_NAME), wzBuffer, 256);
m_pEng->SetProperty(DIALPROP_USERNAME, wzBuffer);
GetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_DOMAIN), wzBuffer, 256);
m_pEng->SetProperty(DIALPROP_DOMAIN, wzBuffer);
m_fSavePassword = FALSE;
if(BST_CHECKED == IsDlgButtonChecked(m_hwnd, IDC_SAVE_PASSWORD))
m_fSavePassword = TRUE;
if(m_fPasswordChanged || FALSE == m_fSavePassword)
{
GetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_PASSWORD), wzBuffer, 256);
m_pEng->SetProperty(DIALPROP_PASSWORD, wzBuffer);
m_pEng->SetProperty(DIALPROP_SAVEPASSWORD, m_fSavePassword ? L"TRUE" : L"FALSE");
m_fPasswordChanged = FALSE;
}
m_fAutoConnect = FALSE;
if(BST_CHECKED == IsDlgButtonChecked(m_hwnd, IDC_AUTOCONNECT))
m_fAutoConnect = TRUE;
DEBUG_LEAVE(0);
}
//////////////////////////////////////////////////////////////////////////////
//
// Helper functions
//
//////////////////////////////////////////////////////////////////////////////
//
// Add a string to the details edit box
//
void PostString(HWND hDlg, LPWSTR pszString)
{
HWND hwndEdit = GetDlgItem(hDlg, IDC_DETAILS_LIST);
WCHAR szCR[] = L"\r\n";
// move caret to end
SendMessageWrapW(hwndEdit, EM_SETSEL, 0, -1);
SendMessageWrapW(hwndEdit, EM_SETSEL, -1, -1);
// replace selection (nothing) with new string
SendMessageWrapW(hwndEdit, EM_REPLACESEL, 0, (LPARAM)pszString);
// move caret to end
SendMessageWrapW(hwndEdit, EM_SETSEL, 0, -1);
SendMessageWrapW(hwndEdit, EM_SETSEL, -1, -1);
// replace selection (nothing) with CR
SendMessageWrapW(hwndEdit, EM_REPLACESEL, 0, (LPARAM)szCR);
// scroll to end
SendMessageWrapW(hwndEdit, EM_SCROLLCARET, 0, 0);
}
#define RAS_BOGUS_AUTHFAILCODE_1 84
#define RAS_BOGUS_AUTHFAILCODE_2 74389484
DWORD RasErrorToIDS(DWORD dwErr)
{
if(dwErr==RAS_BOGUS_AUTHFAILCODE_1 || dwErr==RAS_BOGUS_AUTHFAILCODE_2)
{
return IDS_PPPRANDOMFAILURE;
}
if((dwErr>=653 && dwErr<=663) || (dwErr==667) || (dwErr>=669 && dwErr<=675))
{
return IDS_MEDIAINIERROR;
}
switch(dwErr)
{
default:
return IDS_PPPRANDOMFAILURE;
case ERROR_LINE_BUSY:
return IDS_PHONEBUSY;
case ERROR_NO_ANSWER:
return IDS_NOANSWER;
case ERROR_NO_DIALTONE:
return IDS_NODIALTONE;
case ERROR_HARDWARE_FAILURE: // modem turned off
case ERROR_PORT_ALREADY_OPEN: // procomm/hypertrm/RAS has COM port
case ERROR_PORT_OR_DEVICE: // got this when hypertrm had the device open -- jmazner
return IDS_NODEVICE;
case ERROR_BUFFER_INVALID: // bad/empty rasdilap struct
case ERROR_BUFFER_TOO_SMALL: // ditto?
case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY: // if connectoid name in registry is wrong
case ERROR_INTERACTIVE_MODE:
return IDS_TCPINSTALLERROR;
case ERROR_AUTHENTICATION_FAILURE: // get this on actual CHAP reject
return IDS_AUTHFAILURE;
case ERROR_VOICE_ANSWER:
case ERROR_NO_CARRIER:
case ERROR_PPP_TIMEOUT: // get this on CHAP timeout
case ERROR_REMOTE_DISCONNECTION: // Ascend drops connection on auth-fail
case ERROR_AUTH_INTERNAL: // got this on random POP failure
case ERROR_PROTOCOL_NOT_CONFIGURED: // get this if LCP fails
case ERROR_PPP_NO_PROTOCOLS_CONFIGURED: // get this if IPCP addr download gives garbage
return IDS_PPPRANDOMFAILURE;
}
return 0;
}
void GetDialErrorString(DWORD dwError, LPWSTR pszBuffer, DWORD dwLength)
{
DWORD dwRes;
dwRes = RasErrorToIDS(dwError);
if(dwRes) {
// we have a resource - use it
LoadStringWrapW(GlobalDllHandle, dwRes, pszBuffer, dwLength);
} else {
// couldn't get ras error, try system error
if(0 == FormatMessageWrapW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, pszBuffer, dwLength, NULL)) {
// couldn't get system error, get system error E_FAIL == Unknown error
FormatMessageWrapW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, E_FAIL, 0, pszBuffer, dwLength, NULL);
}
}
}
void SetDialError(HWND hDlg, DWORD dwError)
{
WCHAR szBuf[200];
GetDialErrorString(dwError, szBuf, 200);
PostString(hDlg, szBuf);
}
BOOL
FindDialProvider(
IN LPWSTR pwzConnectoid,
IN LPWSTR pwzProviderType,
OUT CLSID * pclsid
)
//
// FindDialProvider - find an engine, UI, or branding provider for a
// specific connectoid
//
{
DEBUG_ENTER((DBG_DIALUP,
Bool,
"FindDialProvider",
"%#x (%Q), %#x (%Q), %#x",
pwzConnectoid,
pwzConnectoid,
pwzProviderType,
pwzProviderType,
pclsid
));
WCHAR szKey[MAX_PATH];
WCHAR szClsid[64];
DWORD dwSize;
// get the key for the connectoid
GetConnKeyW(pwzConnectoid, szKey, ARRAYSIZE(szKey));
// read the CLSID string
dwSize = sizeof(szClsid);
if(ERROR_SUCCESS != SHGetValueW(
HKEY_CURRENT_USER,
szKey,
pwzProviderType,
NULL,
szClsid,
&dwSize))
{
// no provider specified
DEBUG_PRINT(DIALUP, INFO, ("No provider found.\n"));
DEBUG_LEAVE(FALSE);
return FALSE;
}
// covert string to clsid
if(FAILED(CLSIDFromString(szClsid, pclsid)))
{
DEBUG_PRINT(DIALUP, INFO, ("Unable to convert clsid.\n"));
DEBUG_LEAVE(FALSE);
return FALSE;
}
DEBUG_LEAVE(TRUE);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
//
// Public APIs
//
//////////////////////////////////////////////////////////////////////////////
INTERNETAPI InternetGetDialEngineW(
IN LPWSTR pwzConnectoid,
IN IDialEventSink * pdes,
OUT IDialEngine ** ppde
)
{
DEBUG_ENTER_API((DBG_DIALUP,
Dword,
"InternetGetDialEngineW",
"%#x (%Q), %#x, %#x",
pwzConnectoid,
pwzConnectoid,
pdes,
ppde
));
HRESULT hr;
CLSID clsid;
*ppde = NULL;
//
// find engine we're going to use
//
if(FindDialProvider(pwzConnectoid, L"DialEngine", &clsid))
{
// engine specified, try to create it
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
IID_IDialEngine, (void **)ppde);
}
if(NULL == *ppde)
{
// use default engine
CDialEngine * pEngine = new CDialEngine();
if(pEngine)
{
hr = pEngine->QueryInterface(IID_IDialEngine, (void **)ppde);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if(SUCCEEDED(hr))
{
hr = (*ppde)->Initialize(pwzConnectoid, pdes);
if(FAILED(hr))
{
(*ppde)->Release();
*ppde = NULL;
}
}
DEBUG_LEAVE_API(hr);
return hr;
}
#if 0
//
// [darrenmi 4/14/00] cleaning up exports of incomplete feature
//
INTERNETAPI InternetGetDialBrandingW(
IN LPWSTR pwzConnectoid,
OUT IDialBranding ** ppdb
)
{
DEBUG_ENTER_API((DBG_DIALUP,
Dword,
"InternetGetDialBrandingW",
"%#x (%Q), %#x",
pwzConnectoid,
pwzConnectoid,
ppdb
));
HRESULT hr = S_FALSE;
CLSID clsid;
*ppdb = NULL;
//
// find engine we're going to use
//
if(FindDialProvider(pwzConnectoid, L"DialBranding", &clsid))
{
// engine specified, try to create it
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
IID_IDialBranding, (void **)ppdb);
}
if(SUCCEEDED(hr))
{
hr = (*ppdb)->Initialize(pwzConnectoid);
if(FAILED(hr))
{
(*ppdb)->Release();
*ppdb = NULL;
}
}
DEBUG_LEAVE_API(hr);
return hr;
}
#endif