|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
autodial.cxx
Abstract:
Contains the implementation of autodial
Contents:
Author:
Darren Mitchell (darrenmi) 22-Apr-1997
Environment:
Win32(s) user-mode DLL
Revision History:
22-Apr-1997 darrenmi Created
--*/
#include "wininetp.h"
#include "autodial.h"
#include "rashelp.h"
#include <sensapi.h>
#include <winsvc.h>
#include <commctrl.h>
#include "millenras.h"
#include <iphlpapi.h>
// Globals.
// In IE4 - there are several situations when these globals are
// accessed simultaneously by different threads and so we need to protect them
// with a mutex
//
// fDontProcessHook - set to TRUE in the following circumstances:
//
// - autodial is not enabled
// - loading the ras dll failed
// - no modem is installed
//
// this flag is only relevant on Win95.
//
BOOL fDontProcessHook = FALSE;
DWORD g_dwLastTickCount = 0;
// g_hwndWebCheck is currently not protected with a mutex
HWND g_hwndWebCheck = NULL; // instead of findwindow every time
// have we already checked out the current connection for proxy change?
BOOL g_fConnChecked = FALSE;
// serialize GetConnectedState
HANDLE g_hConnectionMutex = INVALID_HANDLE_VALUE;
// serialize access to RAS
HANDLE g_hRasMutex = INVALID_HANDLE_VALUE;
// serialize access to proxy reg settings
HANDLE g_hProxyRegMutex = INVALID_HANDLE_VALUE;
// Have we upgraded settings?
BOOL g_fCheckedUpgrade = FALSE;
// should we ask user to go offline if no connect?
BOOL g_fAskOffline = TRUE;
// Don't do any callbacks in rnaapp.exe process
BOOL g_fRNAAppProcess = FALSE;
// We use native font control from comctl so we need to call initcommoncontrols
HMODULE hCommctrl = NULL; typedef BOOL (WINAPI *PFNINITCOMMONCONTROLS)(LPINITCOMMONCONTROLSEX);
// base key for settings, lives in proxreg.cxx
extern CRefdKey* g_prkBase;
//
// Enable sens network checking
//
#ifndef UNIX
/* On Unix we assume we are on a LAN all the time */ #define CHECK_SENS 1
#endif /* UNIX */
#ifdef CHECK_SENS
// prototype for IsNetworkAlive()
typedef BOOL (WINAPI *ISNETWORKALIVE)(LPDWORD);
// handle to sens dll and entry point
BOOL g_fSensInstalled = TRUE; HINSTANCE g_hSens = NULL; ISNETWORKALIVE g_pfnIsNetworkAlive = NULL;
// how often to call sens to check state? Every 15 seconds seems reasonable
#define MIN_SENS_CHECK_INTERVAL 15000
DWORD g_dwLastSensCheck = 0;
// message we send to dialmon to find out if sens is loaded
#define WM_IS_SENSLCE_LOADED (WM_USER+201)
#endif
// registry strings
const CHAR szRegPathRemoteAccess[] = REGSTR_PATH_REMOTEACCESS; const CHAR szRegPathInternetSettings[] = REGSTR_PATH_INTERNET_SETTINGS; const CHAR szRegValEnableAutodial[] = REGSTR_VAL_ENABLEAUTODIAL; const CHAR szRegValInternetEntry[] = REGSTR_VAL_INTERNETPROFILE; const CHAR szRegValUnattended[] = REGSTR_VAL_ENABLEUNATTENDED; static const CHAR szRegPathRNAProfile[] = REGSTR_PATH_REMOTEACCESS "\\Profile"; static const CHAR szRegValAutodialDllName[] = REGSTR_VAL_AUTODIALDLLNAME; static const CHAR szRegValAutodialFcnName[] = REGSTR_VAL_AUTODIALFCNNAME; static const CHAR szRegValAutodialFlags[] = "HandlerFlags"; static const CHAR szRegPathRNAService[] = REGSTR_PATH_SERVICES "\\RemoteAccess"; static const CHAR szRegAddresses[] = "RemoteAccess\\Addresses"; static const CHAR szRegPathTCP[] = REGSTR_PATH_VXD "\\MSTCP"; static const CHAR szRegValRemoteConnection[] = "Remote Connection"; static const CHAR szRegValHostName[] = "HostName"; static const CHAR szInetPerformSecurityCheck[] = "InetPerformSecurityCheck"; static const CHAR szRegValEnableSecurityCheck[] = REGSTR_VAL_ENABLESECURITYCHECK; static const CHAR szAutodialMonitorClass[] = REGSTR_VAL_AUTODIAL_MONITORCLASSNAME; static const CHAR szWebCheckMonitorClass[] = "MS_WebCheckMonitor"; static const CHAR szRegPathComputerName[] = REGSTR_PATH_COMPUTRNAME; static const CHAR szRegValComputerName[] = REGSTR_VAL_COMPUTRNAME; static const CHAR szMigrateProxy[] = "MigrateProxy"; static const CHAR szProxySuspect[] = "ProxySuspect"; static const CHAR szCMDllName[] = "cmdial32.dll";
// wide version of various registry strings
#define TSZMICROSOFTPATHW L"Software\\Microsoft"
#define TSZIEPATHW TSZMICROSOFTPATHW L"\\Internet Explorer"
#define TSZWINCURVERPATHW TSZMICROSOFTPATHW L"\\windows\\CurrentVersion"
#define TSZWININETPATHW TSZWINCURVERPATHW L"\\Internet Settings"
#define REGSTR_PATH_INTERNETSETTINGSW TSZWININETPATHW
#define REGSTR_PATH_INTERNET_LAN_SETTINGSW REGSTR_PATH_INTERNETSETTINGSW L"\\LAN"
#define REGSTR_DIAL_AUTOCONNECTW L"AutoConnect"
#define REGSTR_VAL_COVEREXCLUDEW L"CoverExclude"
#define REGSTR_VAL_REDIALATTEMPTSW L"RedialAttempts"
#define REGSTR_VAL_REDIALINTERVALW L"RedialWait"
#define REGSTR_VAL_INTERNETENTRYW L"InternetProfile"
#define REGSTR_VAL_INTERNETPROFILEW REGSTR_VAL_INTERNETENTRYW
#define REGSTR_PATH_REMOTEACCESSW L"RemoteAccess"
#define REGSTR_VAL_AUTODIALDLLNAMEW L"AutodialDllName"
#define REGSTR_VAL_AUTODIALFCNNAMEW L"AutodialFcnName"
const WCHAR szRegValInternetEntryW[] = REGSTR_VAL_INTERNETPROFILEW; const WCHAR szRegPathRemoteAccessW[] = REGSTR_PATH_REMOTEACCESSW; const WCHAR szRegPathRNAProfileW[] = REGSTR_PATH_REMOTEACCESSW L"\\Profile"; const WCHAR szRegValAutodialDllNameW[] = REGSTR_VAL_AUTODIALDLLNAMEW; const WCHAR szRegValAutodialFcnNameW[] = REGSTR_VAL_AUTODIALFCNNAMEW; const WCHAR szRegValAutodialFlagsW[] = L"HandlerFlags"; const WCHAR szCMDllNameW[] = L"cmdial32.dll";
// NT reg keys for finding ras phonebook file
static const CHAR szNTRasPhonebookKey[] = "Software\\Microsoft\\RAS Phonebook"; static const CHAR szPhonebookMode[] = "PhonebookMode";
// don't check RNA state more than once every 3 seconds
#define MIN_RNA_BUSY_CHECK_INTERVAL 3000
// Name or reg value we save legacy settings for comparison later
#define LEGACY_MIGRATE_FLAGS (PROXY_TYPE_PROXY | PROXY_TYPE_AUTO_PROXY_URL)
//
// Current ras connections - used so we don't poll ras every time we're
// interested - only poll every 3 seconds (const. above)
//
RasEnumConnHelp g_RasCon; DWORD g_dwConnections = 0; BOOL g_fRasInstalled = FALSE; DWORD g_dwLastDialupTicks = 0;
//
// API setting for autodial. Allow individual processes to disable autodial
// using InternetSetOption.
//
// This can override an enabled setting but not a disabled setting.
//
BOOL g_fAutodialEnableAPISetting = TRUE;
//
// Control of autodial initialization
//
BOOL g_fAutodialInitialized = FALSE;
//
// Do we know for sure that winsock is loaded?
//
BOOL g_fWinsockLoaded = FALSE;
HANDLE g_hDialEvent = NULL; //
// Structure used to mess about with proxy settings
//
typedef struct _proxy { DWORD dwEnable; TCHAR szServer[INTERNET_MAX_URL_LENGTH]; TCHAR szOverride[INTERNET_MAX_URL_LENGTH]; DWORD dwSuspect; } PROXY, *PPROXY;
//
// Need GetBestRoute from iphlpapi -- dynaload it, free on ExitAutodialModule
//
typedef DWORD (WINAPI *GETBESTROUTE)(DWORD, DWORD, PMIB_IPFORWARDROW);
static HINSTANCE g_hIphlpapi = NULL; static GETBESTROUTE g_pfnGetBestRoute = NULL;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// RAS dynaload code
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
static HINSTANCE g_hRasLib = NULL; static long g_lRasRefCnt = 0;
static _RASHANGUP pfnRasHangUp = NULL;
static _RASDIALA pfnRasDialA = NULL; static _RASENUMENTRIESA pfnRasEnumEntriesA = NULL; static _RASGETENTRYDIALPARAMSA pfnRasGetEntryDialParamsA = NULL; static _RASSETENTRYDIALPARAMSA pfnRasSetEntryDialParamsA = NULL; static _RASEDITPHONEBOOKENTRYA pfnRasEditPhonebookEntryA = NULL; static _RASCREATEPHONEBOOKENTRYA pfnRasCreatePhonebookEntryA = NULL; static _RASGETERRORSTRINGA pfnRasGetErrorStringA = NULL; static _RASGETCONNECTSTATUSA pfnRasGetConnectStatusA = NULL; static _RASENUMCONNECTIONSA pfnRasEnumConnectionsA = NULL; static _RASGETENTRYPROPERTIESA pfnRasGetEntryPropertiesA = NULL;
static _RASDIALW pfnRasDialW = NULL; static _RASENUMENTRIESW pfnRasEnumEntriesW = NULL; static _RASGETENTRYDIALPARAMSW pfnRasGetEntryDialParamsW = NULL; static _RASSETENTRYDIALPARAMSW pfnRasSetEntryDialParamsW = NULL; static _RASEDITPHONEBOOKENTRYW pfnRasEditPhonebookEntryW = NULL; static _RASCREATEPHONEBOOKENTRYW pfnRasCreatePhonebookEntryW = NULL; static _RASGETERRORSTRINGW pfnRasGetErrorStringW = NULL; static _RASGETCONNECTSTATUSW pfnRasGetConnectStatusW = NULL; static _RASENUMCONNECTIONSW pfnRasEnumConnectionsW = NULL; static _RASGETENTRYPROPERTIESW pfnRasGetEntryPropertiesW = NULL;
// Millennium (DUN 1.4?) RAS exports
static _RASINTERNETDIAL pfnRasInternetDialA = NULL; static _RASINTERNETHANGUP pfnRasInternetHangUpA = NULL; static _RASINTERNETAUTODIAL pfnRasInternetAutodialA = NULL; static _RASINTERNETAUTODIALHANG pfnRasInternetAutodialHangUpA = NULL; static _RASINTERNETCONNSTATE pfnRasInternetGetConnectedStateExA = NULL; static _RNAGETDEFAULTAUTODIAL pfnRnaGetDefaultAutodialConnection = NULL; static _RNASETDEFAULTAUTODIAL pfnRnaSetDefaultAutodialConnection = NULL;
// RAS entry points to sync up autodial connectoid... used on whistler only
static _RASGETAUTODIALADDRESSA pfnRasGetAutodialAddressA = NULL; static _RASSETAUTODIALADDRESSA pfnRasSetAutodialAddressA = NULL;
static _RASGETCREDENTIALSW pfnRasGetCredentialsW = NULL; static _RASSETCREDENTIALSW pfnRasSetCredentialsW = NULL;
typedef struct _tagAPIMAPENTRY { FARPROC* pfn; LPSTR pszProc; } APIMAPENTRY;
APIMAPENTRY rgRasApiMapA[] = { { (FARPROC*) &pfnRasDialA, "RasDialA" }, { (FARPROC*) &pfnRasHangUp, "RasHangUpA" }, { (FARPROC*) &pfnRasEnumEntriesA, "RasEnumEntriesA" }, { (FARPROC*) &pfnRasGetEntryDialParamsA, "RasGetEntryDialParamsA" }, { (FARPROC*) &pfnRasSetEntryDialParamsA, "RasSetEntryDialParamsA" }, { (FARPROC*) &pfnRasEditPhonebookEntryA, "RasEditPhonebookEntryA" }, { (FARPROC*) &pfnRasCreatePhonebookEntryA, "RasCreatePhonebookEntryA" }, { (FARPROC*) &pfnRasGetErrorStringA, "RasGetErrorStringA" }, { (FARPROC*) &pfnRasGetConnectStatusA, "RasGetConnectStatusA" }, { (FARPROC*) &pfnRasEnumConnectionsA, "RasEnumConnectionsA" }, { (FARPROC*) &pfnRasGetEntryPropertiesA, "RasGetEntryPropertiesA"}, { (FARPROC*) &pfnRasInternetDialA, "RasInternetDialA"}, { (FARPROC*) &pfnRasInternetHangUpA, "RasInternetHangUpA"}, { (FARPROC*) &pfnRasInternetAutodialA, "RasInternetAutodialA"}, { (FARPROC*) &pfnRasInternetAutodialHangUpA, "RasInternetAutodialHangUpA"}, { (FARPROC*) &pfnRasInternetGetConnectedStateExA, "RasInternetGetConnectedStateExA"}, { (FARPROC*) &pfnRnaGetDefaultAutodialConnection, "RnaGetDefaultAutodialConnection"}, { (FARPROC*) &pfnRnaSetDefaultAutodialConnection, "RnaSetDefaultAutodialConnection"}, { NULL, NULL }, };
APIMAPENTRY rgRasApiMapW[] = { { (FARPROC*) &pfnRasDialW, "RasDialW" }, { (FARPROC*) &pfnRasHangUp, "RasHangUpW" }, { (FARPROC*) &pfnRasEnumEntriesW, "RasEnumEntriesW" }, { (FARPROC*) &pfnRasGetEntryDialParamsW, "RasGetEntryDialParamsW" }, { (FARPROC*) &pfnRasSetEntryDialParamsW, "RasSetEntryDialParamsW" }, { (FARPROC*) &pfnRasEditPhonebookEntryW, "RasEditPhonebookEntryW" }, { (FARPROC*) &pfnRasCreatePhonebookEntryW, "RasCreatePhonebookEntryW" }, { (FARPROC*) &pfnRasGetErrorStringW, "RasGetErrorStringW" }, { (FARPROC*) &pfnRasGetConnectStatusW, "RasGetConnectStatusW" }, { (FARPROC*) &pfnRasEnumConnectionsW, "RasEnumConnectionsW" }, { (FARPROC*) &pfnRasGetEntryPropertiesW, "RasGetEntryPropertiesW"}, { (FARPROC*) &pfnRasGetCredentialsW, "RasGetCredentialsW"}, { (FARPROC*) &pfnRasSetCredentialsW, "RasSetCredentialsW"},
// following are A in W map on purpose.. used on whistler only, but wininet code has
// the connectoid in multibyte.. may as well let RAS convert it.
{ (FARPROC*) &pfnRasGetAutodialAddressA, "RasGetAutodialAddressA"}, { (FARPROC*) &pfnRasSetAutodialAddressA, "RasSetAutodialAddressA"}, { NULL, NULL }, };
#define RASFCN(_fn, _part, _par, _dbge, _dbgl) \
DWORD _##_fn _part \ { \ DEBUG_ENTER(_dbge); \ \ DWORD dwRet; \ if(NULL == pfn##_fn) \ { \ _dbgl(ERROR_INVALID_FUNCTION); \ return ERROR_INVALID_FUNCTION; \ } \ \ dwRet = (* pfn##_fn) _par; \ \ _dbgl(dwRet); \ return dwRet; \ }
RASFCN(RasDialA, (LPRASDIALEXTENSIONS lpRasDialExtensions, LPSTR lpszPhonebook, LPRASDIALPARAMS lpRasDialParams, DWORD dwNotifierType, LPVOID lpvNotifier, LPHRASCONN lphRasConn), (lpRasDialExtensions, lpszPhonebook, lpRasDialParams, dwNotifierType, lpvNotifier, lphRasConn), (DBG_DIALUP, Dword, "RasDialA", "%#x, %#x (%q), %#x, %d, %#x, %#x", lpRasDialExtensions, lpszPhonebook, lpszPhonebook, lpRasDialParams, dwNotifierType, lpvNotifier, lphRasConn), DEBUG_LEAVE );
RASFCN(RasHangUp, (HRASCONN hRasConn), (hRasConn), (DBG_DIALUP, Dword, "RasHangUp", "%#x", hRasConn), DEBUG_LEAVE );
RASFCN(RasEnumEntriesA, (LPSTR lpszReserved, LPSTR lpszPhonebook, LPRASENTRYNAMEA lprasentryname, LPDWORD lpcb, LPDWORD lpcEntries), (lpszReserved, lpszPhonebook, lprasentryname, lpcb, lpcEntries), (DBG_DIALUP, Dword, "RasEnumEntriesA", "%#x (%q), %#x (%q), %#x, %#x, %#x", lpszReserved, lpszReserved, lpszPhonebook, lpszPhonebook, lprasentryname, lpcb, lpcEntries), DEBUG_LEAVE );
RASFCN(RasGetEntryDialParamsA, (LPCSTR lpszPhonebook, LPRASDIALPARAMS lprasdialparams, LPBOOL lpfPassword), (lpszPhonebook, lprasdialparams, lpfPassword), (DBG_DIALUP, Dword, "RasGetEntryDialParamsA", "%#x (%q), %#x, %#x", lpszPhonebook, lpszPhonebook, lprasdialparams, lpfPassword), DEBUG_LEAVE );
RASFCN(RasSetEntryDialParamsA, (LPCSTR lpszPhonebook,LPRASDIALPARAMS lprasdialparams, BOOL fRemovePassword), (lpszPhonebook,lprasdialparams, fRemovePassword), (DBG_DIALUP, Dword, "RasSetEntryDialParamsA", "%#x (%q), %#x, %d", lpszPhonebook, lpszPhonebook, lprasdialparams, fRemovePassword), DEBUG_LEAVE );
RASFCN(RasGetErrorStringA, (UINT uError, LPSTR pszBuf, DWORD cBufSize), (uError, pszBuf, cBufSize), (DBG_DIALUP, Dword, "RasGetErrorStringA", "%d, %#x (%q), %d", uError, pszBuf, cBufSize), DEBUG_LEAVE );
RASFCN(RasEditPhonebookEntryA, (HWND hwnd, LPSTR lpszBook, LPSTR lpszEntry), (hwnd, lpszBook, lpszEntry), (DBG_DIALUP, Dword, "RasEditPhonebookEntryA", "%#x, %#x (%q), %#x (%q)", hwnd, lpszBook, lpszBook, lpszEntry, lpszEntry), DEBUG_LEAVE );
RASFCN(RasCreatePhonebookEntryA, (HWND hwnd, LPSTR pszBook), (hwnd, pszBook), (DBG_DIALUP, Dword, "RasCreatePhonebookEntryA", "%#x, %#x (%q)", hwnd, pszBook, pszBook), DEBUG_LEAVE );
RASFCN(RasGetConnectStatusA, (HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus), (hrasconn, lprasconnstatus), (DBG_DIALUP, Dword, "RasGetConnectStatusA", "%#x, %#x", hrasconn, lprasconnstatus), DEBUG_LEAVE );
RASFCN(RasGetEntryPropertiesA, (LPSTR lpszPhonebook, LPSTR lpszEntry, LPRASENTRY lpRasEntry, LPDWORD lpdwEntryInfoSize, LPBYTE lpbDeviceInfo, LPDWORD lpdwDeviceInfoSize), (lpszPhonebook, lpszEntry, lpRasEntry, lpdwEntryInfoSize, lpbDeviceInfo, lpdwDeviceInfoSize), (DBG_DIALUP, Dword, "RasGetEntryPropertiesA", "%#x (%q), %#x (%q), %#x, %#x, %#x %#x", lpszPhonebook, lpszPhonebook, lpszEntry, lpszEntry, lpRasEntry, lpdwEntryInfoSize, lpbDeviceInfo, lpdwDeviceInfoSize), DEBUG_LEAVE );
RASFCN(RasEnumConnectionsA, (LPRASCONN lpRasConn, LPDWORD lpdwSize, LPDWORD lpdwConn), (lpRasConn, lpdwSize, lpdwConn), (DBG_DIALUP, Dword, "RasEnumConnectionsA", "%#x, %#x, %#x", lpRasConn, lpdwSize, lpdwConn), DEBUG_LEAVE );
RASFCN(RasInternetDialA, (HWND hwndParent, LPSTR pszEntryName, DWORD dwFlags, DWORD_PTR *lpdwConnection, DWORD dwReserved), (hwndParent, pszEntryName, dwFlags, lpdwConnection, dwReserved), (DBG_DIALUP, Dword, "RasInternetDialA", "#x, #x (%q), %x, %x, %x", hwndParent, pszEntryName, pszEntryName, dwFlags, lpdwConnection, dwReserved), DEBUG_LEAVE );
RASFCN(RasInternetHangUpA, (DWORD_PTR dwConnection, DWORD dwReserved), (dwConnection, dwReserved), (DBG_DIALUP, Dword, "RasInternetHangUpA", "#x, #x", dwConnection, dwReserved), DEBUG_LEAVE );
RASFCN(RasInternetAutodialA, (DWORD dwFlags, HWND hwndParent), (dwFlags, hwndParent), (DBG_DIALUP, Dword, "RasInterenetAutodialA", "#x, #x", dwFlags, hwndParent), DEBUG_LEAVE );
RASFCN(RasInternetAutodialHangUpA, (DWORD dwReserved), (dwReserved), (DBG_DIALUP, Dword, "RasInternetAutodialHangUpA", "#x", dwReserved), DEBUG_LEAVE );
RASFCN(RasInternetGetConnectedStateExA, (LPDWORD lpdwFlags, LPSTR lpszConnectionName, DWORD dwBufLen, DWORD dwReserved), (lpdwFlags, lpszConnectionName, dwBufLen, dwReserved), (DBG_DIALUP, Bool, "RasInternetGetConnectedStateExA", "%x, %x, %x, %x", lpdwFlags, lpszConnectionName, dwBufLen, dwReserved), DEBUG_LEAVE );
RASFCN(RnaGetDefaultAutodialConnection, (LPSTR pszEntry, DWORD dwLen, LPDWORD lpdwFlags), (pszEntry, dwLen, lpdwFlags), (DBG_DIALUP, Dword, "RnaGetDefaultAutodialConnection", "%#x, %#x, %#x", pszEntry, dwLen, lpdwFlags), DEBUG_LEAVE );
RASFCN(RnaSetDefaultAutodialConnection, (LPSTR pszEntry, DWORD dwFlags), (pszEntry, dwFlags), (DBG_DIALUP, Dword, "RnaSetDefaultAutodialConnection", "%#x (%q), %#x", pszEntry, pszEntry, dwFlags), DEBUG_LEAVE );
////////////////////////////////////////////////////
// Wide versions
RASFCN(RasDialW, (LPRASDIALEXTENSIONS lpRasDialExtensions, LPWSTR lpszPhonebook, LPRASDIALPARAMSW lpRasDialParams, DWORD dwNotifierType, LPVOID lpvNotifier, LPHRASCONN lphRasConn), (lpRasDialExtensions, lpszPhonebook, lpRasDialParams, dwNotifierType, lpvNotifier, lphRasConn), (DBG_DIALUP, Dword, "RasDialW", "%#x, %#x (%Q), %#x, %d, %#x, %#x", lpRasDialExtensions, lpszPhonebook, lpszPhonebook, lpRasDialParams, dwNotifierType, lpvNotifier, lphRasConn), DEBUG_LEAVE );
RASFCN(RasEnumEntriesW, (LPWSTR lpszReserved, LPWSTR lpszPhonebook, LPRASENTRYNAMEW lprasentryname, LPDWORD lpcb, LPDWORD lpcEntries), (lpszReserved, lpszPhonebook, lprasentryname, lpcb, lpcEntries), (DBG_DIALUP, Dword, "RasEnumEntriesW", "%#x (%Q), %#x (%Q), %#x, %#x %#x", lpszReserved, lpszReserved, lpszPhonebook, lpszPhonebook, lprasentryname, lpcb, lpcEntries), DEBUG_LEAVE );
RASFCN(RasGetEntryDialParamsW, (LPCWSTR lpszPhonebook, LPRASDIALPARAMSW lprasdialparams, LPBOOL lpfPassword), (lpszPhonebook, lprasdialparams, lpfPassword), (DBG_DIALUP, Dword, "RasGetEntryDialParamsW", "%#x (%Q), %#x, %#x", lpszPhonebook, lpszPhonebook, lprasdialparams, lpfPassword), DEBUG_LEAVE );
RASFCN(RasSetEntryDialParamsW, (LPCWSTR lpszPhonebook, LPRASDIALPARAMSW lprasdialparams, BOOL fRemovePassword), (lpszPhonebook,lprasdialparams, fRemovePassword), (DBG_DIALUP, Dword, "RasSetEntryDialParamsW", "%#x (%Q), %#x, %d", lpszPhonebook, lpszPhonebook, lprasdialparams, fRemovePassword), DEBUG_LEAVE );
RASFCN(RasGetErrorStringW, (UINT uError, LPWSTR pszBuf, DWORD cBufSize), (uError, pszBuf, cBufSize), (DBG_DIALUP, Dword, "RasGetErrorStringW", "%d, %#x (%Q), %d", uError, pszBuf, cBufSize), DEBUG_LEAVE );
RASFCN(RasEditPhonebookEntryW, (HWND hwnd, LPWSTR lpszBook, LPWSTR lpszEntry), (hwnd, lpszBook, lpszEntry), (DBG_DIALUP, Dword, "RasEditPhonebookEntryW", "%#x, %#x (%Q), %#x (%Q)", hwnd, lpszBook, lpszBook, lpszEntry, lpszEntry), DEBUG_LEAVE );
RASFCN(RasCreatePhonebookEntryW, (HWND hwnd, LPWSTR pszBook), (hwnd, pszBook), (DBG_DIALUP, Dword, "RasCreatePhonebookEntryW", "%#x, %#x (%Q)", hwnd, pszBook, pszBook), DEBUG_LEAVE );
RASFCN(RasGetConnectStatusW, (HRASCONN hrasconn, LPRASCONNSTATUSW lprasconnstatus), (hrasconn, lprasconnstatus), (DBG_DIALUP, Dword, "RasGetConnectStatusW", "%#x, %#x", hrasconn, lprasconnstatus), DEBUG_LEAVE );
RASFCN(RasGetEntryPropertiesW, (LPWSTR lpszPhonebook, LPWSTR lpszEntry, LPRASENTRYW lpRasEntry, LPDWORD lpdwEntryInfoSize, LPBYTE lpbDeviceInfo, LPDWORD lpdwDeviceInfoSize), (lpszPhonebook, lpszEntry, lpRasEntry, lpdwEntryInfoSize, lpbDeviceInfo, lpdwDeviceInfoSize), (DBG_DIALUP, Dword, "RasGetEntryPropertiesW", "%#x (%Q), %#x (%Q), %#x, %#x, %#x %#x", lpszPhonebook, lpszPhonebook, lpszEntry, lpszEntry, lpRasEntry, lpdwEntryInfoSize, lpbDeviceInfo, lpdwDeviceInfoSize), DEBUG_LEAVE );
RASFCN(RasEnumConnectionsW, (LPRASCONNW lpRasConn, LPDWORD lpdwSize, LPDWORD lpdwConn), (lpRasConn, lpdwSize, lpdwConn), (DBG_DIALUP, Dword, "RasEnumConnectionsW", "%#x, %#x, %#x", lpRasConn, lpdwSize, lpdwConn), DEBUG_LEAVE );
RASFCN(RasGetAutodialAddressA, (LPCSTR lpszAddress, LPDWORD lpdwReserved, LPRASAUTODIALENTRYA lpEntries, LPDWORD lpdwBytes, LPDWORD lpdwEntries), (lpszAddress, lpdwReserved, lpEntries, lpdwBytes, lpdwEntries), (DBG_DIALUP, Dword, "RasGetAutodialAddressA", "%#x (%Q), %#x, %#x, %#x, %#x", lpszAddress, lpszAddress, lpdwReserved, lpEntries, lpdwBytes, lpdwEntries), DEBUG_LEAVE );
RASFCN(RasSetAutodialAddressA, (LPCSTR lpszAddress, DWORD dwReserved, LPRASAUTODIALENTRYA lpEntries, DWORD dwBytes, DWORD dwEntries), (lpszAddress, dwReserved, lpEntries, dwBytes, dwEntries), (DBG_DIALUP, Dword, "RasSetAutodialAddressA", "%#x (%q), %#x, %#x, %#x, %#x", lpszAddress, lpszAddress, dwReserved, lpEntries, dwBytes, dwEntries), DEBUG_LEAVE );
RASFCN(RasGetCredentialsW, (LPCWSTR pszPhonebook, LPCWSTR pszEntry, LPRASCREDENTIALSW pCreds), (pszPhonebook, pszEntry, pCreds), (DBG_DIALUP, Dword, "RasGetCredentialsW", "%#x (%Q), %#x (%Q), %#x", pszPhonebook, pszPhonebook, pszEntry, pszEntry, pCreds), DEBUG_LEAVE );
RASFCN(RasSetCredentialsW, (LPCWSTR pszPhonebook, LPCWSTR pszEntry, LPRASCREDENTIALSW pCreds, BOOL fNuke), (pszPhonebook, pszEntry, pCreds, fNuke), (DBG_DIALUP, Dword, "RasSetCredentialsW", "%#x (%Q), %#x (%Q), %#x, %#x", pszPhonebook, pszPhonebook, pszEntry, pszEntry, pCreds, fNuke), DEBUG_LEAVE );
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
BOOL EnsureRasLoaded( VOID )
/*++
Routine Description:
Dynaload ras apis
Arguments:
pfInstalled - return installed state of ras
Return Value:
BOOL TRUE - Ras loaded FALSE - Ras not loaded
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "EnsureRasLoaded", NULL ));
//
// Looks like RAS is installed - try and load it up!
//
if(NULL == g_hRasLib) { g_hRasLib = LoadLibrary("RASAPI32.DLL");
if(NULL == g_hRasLib) { DEBUG_LEAVE(FALSE); return FALSE; }
APIMAPENTRY *prgRasApiMap; if(PLATFORM_TYPE_WIN95 == GlobalPlatformType) prgRasApiMap = rgRasApiMapA; else prgRasApiMap = rgRasApiMapW;
int nIndex = 0; while ((prgRasApiMap+nIndex)->pszProc != NULL) { // Some functions are only present on some platforms. Don't
// assume this succeeds for all functions.
*(prgRasApiMap+nIndex)->pfn = GetProcAddress(g_hRasLib, (prgRasApiMap+nIndex)->pszProc); nIndex++; } }
if(g_hRasLib) { g_lRasRefCnt++; DEBUG_LEAVE(TRUE); return TRUE; }
DEBUG_LEAVE(FALSE); return FALSE; }
BOOL IsServiceRunning( LPSTR pszServiceName, DWORD dwRequiredState )
/*++
Routine Description:
Determines whether a specified service is running on NT
Arguments:
pszServiceName - service to find dwRequiredState - state the service has to be in to consider it found
Return Value:
BOOL TRUE - Service is in required state
FALSE - not
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsServiceRunning", "%#x (%q), %#x", pszServiceName, pszServiceName, dwRequiredState ));
SC_HANDLE hscm; BOOL fFoundService = FALSE;
//
// Sanity check - can only do this on NT
//
if(PLATFORM_TYPE_WIN95 == GlobalPlatformType) { DEBUG_LEAVE(FALSE); return FALSE; }
//
// Ask service manager to enumerate all running services
//
hscm = OpenSCManager(NULL, NULL, GENERIC_READ); if(hscm) { SC_HANDLE hras; ENUM_SERVICE_STATUS essServices[16]; DWORD dwError, dwResume = 0, i; DWORD cbNeeded = 1, csReturned;
while(FALSE == fFoundService && cbNeeded > 0) { // Get the next chunk of services
dwError = 0; if(FALSE == EnumServicesStatus(hscm, SERVICE_WIN32, dwRequiredState, essServices, sizeof(essServices), &cbNeeded, &csReturned, &dwResume)) { dwError = GetLastError(); }
if(dwError && dwError != ERROR_MORE_DATA) { // unknown error - bail
break; }
for(i=0; i<csReturned; i++) { if(0 == lstrcmpi(essServices[i].lpServiceName, pszServiceName)) { // found it!
fFoundService = TRUE; break; } } }
CloseServiceHandle(hscm); }
DEBUG_LEAVE(fFoundService); return fFoundService; }
BOOL IsRasInstalled( VOID )
/*++
Routine Description:
Determines whether ras is installed on this machine
Arguments:
none
Return Value:
BOOL TRUE - Ras is installed
FALSE - Ras is not installed
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "IsRasInstalled", NULL ));
static fChecked = FALSE;
//
// If RAS is already loaded, don't bother doing any work.
//
if(g_hRasLib) { DEBUG_LEAVE_API(TRUE); return TRUE; }
//
// if we've already done the check, don't do it again
//
if(fChecked) { DEBUG_LEAVE_API(g_fRasInstalled); return g_fRasInstalled; }
if(PLATFORM_TYPE_WIN95 == GlobalPlatformType) { //
// Check Win9x key
//
char szSmall[3]; // there should be a "1" or a "0" only
DWORD cb; HKEY hkey; long lRes;
lRes = REGOPENKEYEX(HKEY_LOCAL_MACHINE, REGSTR_PATH_RNACOMPONENT, NULL, KEY_READ, &hkey); if(ERROR_SUCCESS == lRes) { cb = sizeof(szSmall); // REGSTR_VAL_RNAINSTALLED is defined with TEXT() macro so
// if wininet is ever compiled unicode this will be a compile
// error.
lRes = RegQueryValueExA(hkey, REGSTR_VAL_RNAINSTALLED, NULL, NULL, (LPBYTE)szSmall, &cb); if(ERROR_SUCCESS == lRes) { if((szSmall[0] == '1') && (szSmall[1] == 0)) { // 1 means ras installed
g_fRasInstalled = TRUE; } } REGCLOSEKEY(hkey); } } else { OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi);
if (osvi.dwMajorVersion < 5) { // on NT4, make sure ras man service is installed
g_fRasInstalled = IsServiceRunning("RasMan", SERVICE_STATE_ALL);
if(g_fRasInstalled) { if(EnsureRasLoaded() && FALSE == GlobalDisableNT4RasCheck) { RasEnumHelp *pRasEnum = NULL; __try { // call rasenumentries - if it faults, we're in that
// NT4 busted case so return not installed.
pRasEnum = new RasEnumHelp; } __except(EXCEPTION_EXECUTE_HANDLER) { // if it faults, don't use ras any more
g_fRasInstalled = FALSE; } ENDEXCEPT
if (pRasEnum) delete pRasEnum; } } } else { // NT5 and presumably beyond, ras is always installed
g_fRasInstalled = TRUE; } }
fChecked = TRUE;
DEBUG_LEAVE_API(g_fRasInstalled); return g_fRasInstalled; }
BOOL DoConnectoidsExist( VOID )
/*++
Routine Description:
Determines whether any ras connectoids exist
Arguments:
none
Return Value:
BOOL TRUE - Connectoids exist
FALSE - No connectoids exist
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "DoConnectoidsExist", NULL ));
static BOOL fExist = FALSE;
//
// If we found connectoids before, don't bother looking again
//
if(fExist) { DEBUG_LEAVE_API(TRUE); return TRUE; }
//
// If RAS is already loaded, ask it
//
if(g_hRasLib && FALSE == GlobalDisableNT4RasCheck) { DWORD dwRet, dwEntries;
RasEnumHelp *pRasEnum = new RasEnumHelp;
if (pRasEnum) { dwRet = pRasEnum->GetError(); dwEntries = pRasEnum->GetEntryCount(); delete pRasEnum; } else { dwRet = ERROR_NOT_ENOUGH_MEMORY; }
// If ras tells us there are none, return none
if(ERROR_SUCCESS == dwRet && 0 == dwEntries) { DEBUG_LEAVE_API(FALSE); return FALSE; } // couldn't determine that there aren't any so assume there are.
fExist = TRUE; DEBUG_LEAVE_API(TRUE); return TRUE; }
//
// if ras isn't installed, say no connectoids
//
if(FALSE == IsRasInstalled()) { DEBUG_LEAVE_API(FALSE); return FALSE; }
if(PLATFORM_TYPE_WIN95 == GlobalPlatformType) { // On win95, check for any value in RemoteAccess\Addresses reg key
HKEY hkey; TCHAR szName[RAS_MaxEntryName+1]; DWORD cbName = RAS_MaxEntryName+1; long lRes;
if(ERROR_SUCCESS == REGOPENKEYEX(HKEY_CURRENT_USER, szRegAddresses, 0, KEY_READ, &hkey)) {
lRes = RegEnumValue(hkey, 0, szName, &cbName, NULL, NULL, NULL, NULL); if(ERROR_SUCCESS == lRes) { // we managed to get info on a connectoid.
fExist = TRUE; }
REGCLOSEKEY(hkey); } } else { OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi);
// assume connectoids exist
fExist = TRUE;
if (osvi.dwMajorVersion < 5) { // On NT4, check for rasphone.pbk size > 0
TCHAR szPhonebook[MAX_PATH + 128]; ULONG uLen, ulMode, cb; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwSize, dwBigSize; HKEY hkey;
// Ensure system phonebook is the one in use. If user has switched
// to another phonebook, don't bother doing anything else and assume
// connectoids exist. It's not our job to grope the world trying to
// find custom phonebooks.
if(ERROR_SUCCESS == REGOPENKEYEX(HKEY_CURRENT_USER, szNTRasPhonebookKey, 0, KEY_READ, &hkey)) { *szPhonebook = 0; cb = sizeof(ULONG); if(ERROR_SUCCESS == RegQueryValueEx(hkey, szPhonebookMode, NULL, NULL, (LPBYTE)&ulMode, &cb) && 0 == ulMode) { // system phonebook - rasphone.pbk in ras directory
uLen = GetSystemDirectory(szPhonebook, MAX_PATH); if(uLen) { // append \ras\rasphone.pbk
LoadString(GlobalDllHandle, IDS_RASPHONEBOOK, szPhonebook + uLen, 128); hFile = CreateFile(szPhonebook, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(INVALID_HANDLE_VALUE == hFile) { // file doesn't exist - no connectoids
fExist = FALSE; } else { dwSize = GetFileSize(hFile, &dwBigSize); if(0 == dwSize && 0 == dwBigSize) // zero size system phonebook - no connectoids
fExist = FALSE; CloseHandle(hFile); } } } REGCLOSEKEY(hkey); } } }
DEBUG_LEAVE_API(fExist); return fExist; }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Helper Functions
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
BOOL InitCommCtrl( VOID )
/*++
Routine Description:
Initializes common controls for native font control
Called from InternetDialA which is serialized.
Arguments:
None
Return Value:
BOOL TRUE - successly called InitCommonControlsEx FALSE - failed
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "InitCommCtrl", NULL ));
BOOL fSuccess = FALSE;
hCommctrl = LoadLibrary("comctl32.dll"); if(hCommctrl) { PFNINITCOMMONCONTROLS pfnInit;
pfnInit = (PFNINITCOMMONCONTROLS)GetProcAddress(hCommctrl, "InitCommonControlsEx"); if(pfnInit) { INITCOMMONCONTROLSEX ex;
ex.dwSize = sizeof(ex); ex.dwICC = ICC_NATIVEFNTCTL_CLASS; pfnInit(&ex); fSuccess = TRUE; } }
DEBUG_LEAVE(fSuccess); return fSuccess; }
VOID ExitCommCtrl( VOID )
/*++
Routine Description:
Unloads commctrl library
Called from InternetDialA which is serialized.
Arguments:
None
Return Value:
None
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "ExitCommCtrl", NULL ));
if(hCommctrl) { FreeLibrary(hCommctrl); hCommctrl = NULL; }
DEBUG_LEAVE(0); }
BOOL IsGlobalOffline( VOID )
/*++
Routine Description:
Determines whether wininet is in global offline mode
Arguments:
None
Return Value:
BOOL TRUE - offline FALSE - online
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsGlobalOffline", NULL ));
DWORD dwState = 0, dwSize = sizeof(DWORD); BOOL fRet = FALSE;
if(InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize)) { if(dwState & INTERNET_STATE_DISCONNECTED_BY_USER) fRet = TRUE; }
DEBUG_LEAVE(fRet); return fRet; }
VOID SetOffline( IN BOOL fOffline )
/*++
Routine Description:
Sets wininet's offline mode
Arguments:
fOffline - online or offline
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "SetOffline", "%B", fOffline ));
INTERNET_CONNECTED_INFO ci;
memset(&ci, 0, sizeof(ci)); if(fOffline) { ci.dwConnectedState = INTERNET_STATE_DISCONNECTED_BY_USER; ci.dwFlags = ISO_FORCE_DISCONNECTED; } else { ci.dwConnectedState = INTERNET_STATE_CONNECTED; }
InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
DEBUG_LEAVE(0); }
VOID GetConnKeyW( IN LPWSTR pszConn, IN LPWSTR pszKey, IN int iLen )
/*++
Routine Description:
Get registry key for a specific connection
Arguments:
pszConn - connection for which key is required pszKey - buffer to put key iLen - buffer size
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "GetConnKeyW", "%#x (%Q), %#x, %d", pszConn, pszConn, pszKey, iLen ));
if(NULL == pszConn || 0 == *pszConn) { // lan setting
StrCpyNW(pszKey, REGSTR_PATH_INTERNET_LAN_SETTINGSW, iLen); } else { // connectoid settings
wnsprintfW(pszKey, iLen, L"%ws\\%ws", szRegPathRNAProfileW, pszConn); }
DEBUG_LEAVE(0); }
VOID GetConnKeyA( IN LPSTR pszConn, IN LPSTR pszKey, IN int iLen )
/*++
Routine Description:
Get registry key for a specific connection
Arguments:
pszConn - connection for which key is required pszKey - buffer to put key iLen - buffer size
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "GetConnKeyA", "%#x (%q), %#x, %d", pszConn, pszConn, pszKey, iLen ));
if(NULL == pszConn || 0 == *pszConn) { // lan setting
lstrcpynA(pszKey, REGSTR_PATH_INTERNET_LAN_SETTINGS, iLen); } else { // connectoid settings
wnsprintfA(pszKey, iLen, "%s\\%s", szRegPathRNAProfile, pszConn); }
DEBUG_LEAVE(0); }
VOID SetAutodialEnable( IN BOOL fEnable )
/*++
Routine Description:
Sets the API setting for controlling autodial. Called from InternetSetOption.
Arguments:
fEnable - FALSE means don't autodial for this process TRUE means autodial if configured by the user
Return Value:
none.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "SetAutodialEnable", "%B", fEnable ));
g_fAutodialEnableAPISetting = fEnable;
DEBUG_LEAVE(0); }
DWORD GetAutodialMode( )
{ DEBUG_ENTER((DBG_DIALUP, Dword, "GetAutodialMode", NULL ));
DWORD dwMode = AUTODIAL_MODE_NO_NETWORK_PRESENT, dwError, dwData;
// make sure RAS and Wininet flags match up
INET_ASSERT(RAS_AUTODIAL_OPT_NEVER == AUTODIAL_MODE_NEVER); INET_ASSERT(RAS_AUTODIAL_OPT_ALWAYS == AUTODIAL_MODE_ALWAYS); INET_ASSERT(RAS_AUTODIAL_OPT_DEMAND == AUTODIAL_MODE_NO_NETWORK_PRESENT);
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRnaGetDefaultAutodialConnection) { dwError = _RnaGetDefaultAutodialConnection(NULL, 0, &dwMode);
if(dwError) { DEBUG_ERROR(DIALUP, dwError); dwMode = AUTODIAL_MODE_NEVER; }
dwMode &= (RAS_AUTODIAL_OPT_NEVER | RAS_AUTODIAL_OPT_ALWAYS | RAS_AUTODIAL_OPT_DEMAND);
DEBUG_LEAVE(dwMode); return dwMode; }
if(InternetReadRegistryDword(REGSTR_VAL_ENABLEAUTODIAL, &dwData) || 0 == dwData) { dwMode = AUTODIAL_MODE_NEVER; }
if(AUTODIAL_MODE_NO_NETWORK_PRESENT == dwMode) { if(InternetReadRegistryDword(REGSTR_VAL_NONETAUTODIAL, &dwData) || 0 == dwData) { dwMode = AUTODIAL_MODE_ALWAYS; } }
DEBUG_LEAVE(dwMode); return dwMode; }
DWORD SetAutodialMode( IN DWORD dwMode )
{ DEBUG_ENTER((DBG_DIALUP, Dword, "SetAutodialMode", "%#x", dwMode ));
DWORD dwEnable = 0, dwNonet = 0, dwError = 0;
// make sure RAS and Wininet flags match up
INET_ASSERT(RAS_AUTODIAL_OPT_NEVER == AUTODIAL_MODE_NEVER); INET_ASSERT(RAS_AUTODIAL_OPT_ALWAYS == AUTODIAL_MODE_ALWAYS); INET_ASSERT(RAS_AUTODIAL_OPT_DEMAND == AUTODIAL_MODE_NO_NETWORK_PRESENT);
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRnaSetDefaultAutodialConnection && pfnRnaGetDefaultAutodialConnection) { CHAR szOldName[RAS_MaxEntryName+1]; DWORD dwOldMode;
// Have to set both name and mode at the same time, so read existing values and change
// what we need.
dwError = _RnaGetDefaultAutodialConnection(szOldName, ARRAYSIZE(szOldName), &dwOldMode); if(0 == dwError) { dwError = _RnaSetDefaultAutodialConnection(szOldName, dwMode); }
DEBUG_LEAVE(dwError); return dwError; }
switch(dwMode) { case AUTODIAL_MODE_NEVER: break; case AUTODIAL_MODE_NO_NETWORK_PRESENT: dwNonet = 1; // fall through to always
case AUTODIAL_MODE_ALWAYS: dwEnable = 1; break; default: dwError = ERROR_INVALID_PARAMETER; }
if(ERROR_SUCCESS == dwError) { InternetWriteRegistryDword(REGSTR_VAL_ENABLEAUTODIAL, dwEnable); InternetWriteRegistryDword(REGSTR_VAL_NONETAUTODIAL, dwNonet); }
DEBUG_LEAVE(dwError); return dwError; }
DWORD GetAutodialConnection( CHAR *pszBuffer, DWORD dwBufferLength ) { DEBUG_ENTER((DBG_DIALUP, Dword, "GetAutodialConnection", "%#x, %#x", pszBuffer, dwBufferLength ));
DWORD dwType, dwHasEntry = FALSE, dwMode, dwError = ERROR_INVALID_NAME;
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRnaGetDefaultAutodialConnection) { dwError = _RnaGetDefaultAutodialConnection(pszBuffer, dwBufferLength, &dwMode);
if(0 == dwError) { DEBUG_PRINT(DIALUP, INFO, ("Entry=%s, Mode=%x", pszBuffer, dwMode)); }
DEBUG_LEAVE(dwError); return dwError; }
if(GlobalPlatformWhistler && EnsureRasLoaded() && pfnRasGetAutodialAddressA) { RASAUTODIALENTRYA adEntry; DWORD dwBytes, dwEntries; ZeroMemory(&adEntry, sizeof(adEntry)); adEntry.dwSize = sizeof(adEntry); dwBytes = sizeof(adEntry); dwEntries = 1; dwError = _RasGetAutodialAddressA( NULL, NULL, &adEntry, &dwBytes, &dwEntries);
if(NO_ERROR == dwError && dwEntries) { lstrcpyn(pszBuffer, adEntry.szEntry, dwBufferLength); } else { *pszBuffer = 0; }
DEBUG_LEAVE(dwError); return dwError; }
if(ERROR_SUCCESS == SHGetValueA(HKEY_CURRENT_USER, szRegPathRemoteAccess, szRegValInternetEntry, &dwType, pszBuffer, &dwBufferLength) && lstrlen(pszBuffer)) { dwError = 0; // success
}
DEBUG_LEAVE(dwError); return dwError; }
DWORD SetAutodialConnection( CHAR *pszConnection ) { DEBUG_ENTER((DBG_DIALUP, Dword, "SetAutodialConnection", "%#x (%q)", pszConnection, pszConnection ));
DWORD dwError;
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRnaSetDefaultAutodialConnection && pfnRnaGetDefaultAutodialConnection) { CHAR szOldName[RAS_MaxEntryName+1]; DWORD dwOldMode;
// Have to set both name and mode at the same time, so read existing values and change
// what we need.
dwError = _RnaGetDefaultAutodialConnection(szOldName, ARRAYSIZE(szOldName), &dwOldMode); if(0 == dwError) { dwError = _RnaSetDefaultAutodialConnection(pszConnection, dwOldMode); }
DEBUG_LEAVE(dwError); return dwError; }
if(GlobalPlatformWhistler && EnsureRasLoaded() && pfnRasSetAutodialAddressA) { RASAUTODIALENTRYA adEntry; ZeroMemory(&adEntry, sizeof(adEntry)); adEntry.dwSize = sizeof(adEntry); lstrcpyn(adEntry.szEntry, pszConnection, sizeof(adEntry.szEntry) / sizeof(TCHAR)); dwError = _RasSetAutodialAddressA( NULL, NULL, &adEntry, sizeof(adEntry), 1);
DEBUG_LEAVE(dwError); return dwError; }
SHSetValue(HKEY_CURRENT_USER, szRegPathRemoteAccess, szRegValInternetEntry, REG_SZ, pszConnection, lstrlen(pszConnection));
DEBUG_LEAVE(0); return 0; }
BOOL IsAutodialEnabled( OUT BOOL *pfForceDial, IN AUTODIAL *pConfig )
/*++
Routine Description:
Read flags used to control autodial. Also honors SetOption setting to override and not autodial.
Note: if autodial isn't enabled, the rest of the structure isn't read.
Arguments:
pConfig - AUTODIAL struct to store info. NULL is valid if info isn't required.
Return Value:
BOOL TRUE - Autodial is enabled FALSE - Autodial is not enabled
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsAutodialEnabled", "%#x, %#x", pfForceDial, pConfig ));
HKEY hKey; DWORD dwRes, dwData = 0, dwSize, dwType; BOOL fConfigured, fEnabled;
//
// Init out parameter
//
if(pfForceDial) { *pfForceDial = FALSE; }
if(pConfig) { memset(pConfig, 0, sizeof(AUTODIAL)); }
//
// Get autodial enabled
//
fConfigured = fEnabled = TRUE;
// check registry setting
if(InternetReadRegistryDword(REGSTR_VAL_ENABLEAUTODIAL, &dwData) || 0 == dwData) { fEnabled = fConfigured = FALSE; }
if(fEnabled) { if(InternetReadRegistryDword(REGSTR_VAL_NONETAUTODIAL, &dwData) || 0 == dwData) { // don't use sens -- imitate IE4 and before behavior
if(pConfig) { pConfig->fForceDial = TRUE; } if(pfForceDial) { *pfForceDial = TRUE; } }
// update fEnabled based on api setting
fEnabled = g_fAutodialEnableAPISetting; }
if(NULL == pConfig) { DEBUG_LEAVE(fEnabled); return fEnabled; }
//
// save enabled to pconfig struct
//
pConfig->fEnabled = fEnabled;
pConfig->fConfigured = fConfigured;
//
// read security check
//
dwSize = sizeof(dwData); if( GlobalPlatformType == PLATFORM_TYPE_WIN95 && InternetReadRegistryDword(szRegValEnableSecurityCheck, &dwData) == ERROR_SUCCESS && dwData) { pConfig->fSecurity = TRUE; }
if(FALSE == fEnabled) { // if autodial isn't enabled, no point in reading the rest of the
// info because it isn't used
DEBUG_LEAVE(fEnabled); return fEnabled; }
//
// read connectoid name
//
CHAR szConnectoidName[RAS_MaxEntryName + 1]; if(ERROR_SUCCESS == GetAutodialConnection(szConnectoidName, RAS_MaxEntryName)) { MultiByteToWideChar(CP_ACP, 0, szConnectoidName, -1, pConfig->pszEntryName, RAS_MaxEntryName); } else { pConfig->pszEntryName[0] = 0; }
if(lstrlenW(pConfig->pszEntryName)) { pConfig->fHasEntry = TRUE;
// if possible, verify that autodial entry actually exists
RasEntryPropHelp *pRasProp = new RasEntryPropHelp;
if (pRasProp) { if(pRasProp->GetError() == 0) { DWORD dwRet = pRasProp->GetW(pConfig->pszEntryName); if((ERROR_SUCCESS != dwRet) && (ERROR_INVALID_FUNCTION != dwRet)) { // ras doesn't know about this - blow it away
pConfig->fHasEntry = FALSE; *pConfig->pszEntryName = 0; } } delete pRasProp; } }
if(FALSE == pConfig->fHasEntry && (FALSE == DoConnectoidsExist())) { // We expect an entry at this point. If we don't and none exist at
// this point, autodial isn't, in fact, enabled.
pConfig->fEnabled = FALSE; pConfig->fForceDial = FALSE;
if(pfForceDial) { *pfForceDial = FALSE; } }
//
// read autoconnect for the specified entry
//
if(pConfig->fHasEntry) { WCHAR szKey[MAX_PATH];
GetConnKeyW(pConfig->pszEntryName, szKey, ARRAYSIZE(szKey)); dwSize = sizeof(DWORD); if(ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey, REGSTR_DIAL_AUTOCONNECTW, &dwType, &dwData, &dwSize) && dwData) { pConfig->fUnattended = TRUE; } }
DEBUG_LEAVE(pConfig->fEnabled); return pConfig->fEnabled; }
UINT_PTR SendDialmonMessage( UINT uMessage, BOOL fPost )
/*++
Routine Description:
Send a message to dialmon
Arguments:
uMessage - message to send fPost - post or send
Return Value:
Return of send or 0 if post
--*/
{ DEBUG_ENTER((DBG_DIALUP, Dword, "SendDialmonMessage", "%x, %B", uMessage, fPost ));
UINT_PTR uRet = 0;
// Send a message to dialmon's monitor window to start monitoring this
// connectoid
if(NULL == g_hwndWebCheck) { g_hwndWebCheck = FindWindow(szWebCheckMonitorClass,NULL); } if(g_hwndWebCheck) { if(fPost) { PostMessage(g_hwndWebCheck, uMessage, 0, 0); } else { uRet = SendMessage(g_hwndWebCheck, uMessage, 0, 0); } }
DEBUG_LEAVE(uRet); return uRet; }
BOOL GetRedialParameters( IN LPWSTR pszConn, OUT LPDWORD pdwDialAttempts, OUT LPDWORD pdwDialInterval )
/*++
Routine Description:
Get redial information for a specific connectoid
Arguments:
pszConn - connection name pdwDialAttempts - location to store dial attempts pdwDialInterval - location to store dial interval
Return Value:
BOOL TRUE - success FALSE - failure
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "GetRedialParameters", "%#x (%Q), %x, %x", pszConn, pszConn, pdwDialAttempts, pdwDialInterval ));
WCHAR szKey[MAX_PATH]; DWORD dwValue, dwSize; HKEY hkey;
//
// validate and clear out variables
//
if(NULL == pdwDialAttempts || NULL == pdwDialInterval) { DEBUG_LEAVE(FALSE); return FALSE; }
//
// set to defaults
//
*pdwDialAttempts = DEFAULT_DIAL_ATTEMPTS; *pdwDialInterval = DEFAULT_DIAL_INTERVAL;
//
// read values from registry
//
GetConnKeyW(pszConn, szKey, ARRAYSIZE(szKey)); dwSize = sizeof(DWORD); if(ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey, REGSTR_VAL_REDIALATTEMPTSW, NULL, &dwValue, &dwSize) && dwValue) { *pdwDialAttempts = dwValue; }
dwSize = sizeof(DWORD); if(ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey, REGSTR_VAL_REDIALINTERVALW, NULL, &dwValue, &dwSize) && dwValue) { *pdwDialInterval = dwValue; }
DEBUG_LEAVE(TRUE); return TRUE; }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Win9x security check
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// stolen from ICW's wizglob.h -- BUGBUG - add to our tree
#define INSTANCE_PPPDRIVER 0x0002
typedef DWORD (WINAPI * ICFGISFILESHARINGTURNEDON ) (DWORD dwfDriverType, LPBOOL lpfSharingOn);
BOOL IsSharingEnabled( VOID )
/*++
Routine Description:
Silently determine whether sharing is turned on on PPP devices on Win9x
Arguments:
none
Return Value:
BOOL TRUE - sharing on FALSE - sharing off (or NT)
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsSharingEnabled", NULL ));
ICFGISFILESHARINGTURNEDON lpIcfgIsFileSharingTurnedOn=NULL; HINSTANCE hICFGInst = NULL; BOOL fSharingIsOn = FALSE;
//
// Bail out on NT
//
if(PLATFORM_TYPE_WINNT == GlobalPlatformType) { DEBUG_LEAVE(FALSE); return FALSE; } else { hICFGInst = LoadLibraryA("icfg95.dll"); }
//
// Try and get entry point in icfg95.dll to check
//
if(hICFGInst) { DWORD dwRet; lpIcfgIsFileSharingTurnedOn = (ICFGISFILESHARINGTURNEDON)GetProcAddress( hICFGInst, "IcfgIsFileSharingTurnedOn"); if(lpIcfgIsFileSharingTurnedOn) dwRet = lpIcfgIsFileSharingTurnedOn(INSTANCE_PPPDRIVER, &fSharingIsOn);
FreeLibrary(hICFGInst); }
DEBUG_LEAVE(fSharingIsOn); return fSharingIsOn; }
DWORD PerformSecurityCheck( IN HWND hwndParent, IN DWORD dwFlags )
/*++
Routine Description:
Prompt user to fix sharing on PPP device on Win9x. Reboot if necessary.
Arguments:
hwndParent - parent window for any UI dwFlags - flags possibly containing INTERNET_AUTODIAL_FAILIFSECURITYCHECK
Return Value:
BOOL TRUE - failed test, may be rebooting FALSE - passed test
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "PerformSecurityCheck", "%#x, %#x", hwndParent, dwFlags ));
static BOOL fDoneCheckOnce = FALSE; BOOL fNeedRestart = FALSE; HINSTANCE hinstInetWiz; INETPERFORMSECURITYCHECK lpInetPerformSecurityCheck; CHAR szFilename[SMALLBUFLEN+1]="";
// only do this once per session, never on NT
if(PLATFORM_TYPE_WINNT == GlobalPlatformType || fDoneCheckOnce) { DEBUG_LEAVE(FALSE); return FALSE; } fDoneCheckOnce = TRUE;
if(dwFlags & (INTERNET_AUTODIAL_FAILIFSECURITYCHECK | INTERNET_DIAL_UNATTENDED | INTERNET_AUTODIAL_FORCE_UNATTENDED)) { if(IsSharingEnabled()) { // silent check failed
DEBUG_LEAVE(TRUE); return TRUE; } }
// get filename out of resource
LoadString(GlobalDllHandle,IDS_INETCFG_FILENAME,szFilename, sizeof(szFilename));
// load the inetcfg dll
hinstInetWiz = LoadLibrary(szFilename); INET_ASSERT(hinstInetWiz); if (hinstInetWiz) {
// get the proc address
lpInetPerformSecurityCheck = (INETPERFORMSECURITYCHECK) GetProcAddress(hinstInetWiz,szInetPerformSecurityCheck); INET_ASSERT(lpInetPerformSecurityCheck); if (lpInetPerformSecurityCheck) { // call the function to do system security check
(lpInetPerformSecurityCheck) (hwndParent, &fNeedRestart); }
FreeLibrary(hinstInetWiz);
if(fNeedRestart) { // call RestartDialog in shell32
HINSTANCE hShell = LoadLibrary("shell32.dll"); _RESTARTDIALOG pfnRestart = NULL;
if(hShell) { pfnRestart = (_RESTARTDIALOG)GetProcAddress(hShell, (LPTSTR)59); if(pfnRestart) (*pfnRestart)(NULL, NULL, EWX_REBOOT); FreeLibrary(hShell); } } }
DEBUG_LEAVE(fNeedRestart); return fNeedRestart; }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Custom Dial Handler code
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
BOOL IsCDH( IN LPWSTR pszEntryName, IN CDHINFO *pcdh )
/*++
Routine Description:
Determine whether a connection uses a custom dial handler
Arguments:
pszEntryName - connection name pcdh - pointer to structure to hold cdh info
Return Value:
BOOL TRUE - connection uses custom dial handler FALSE - doesn't
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsCDH", "%#x (%Q), %#x", pszEntryName, pszEntryName, pcdh ));
//
// clear out cdhinfo
//
memset(pcdh, 0, sizeof(CDHINFO));
if(PLATFORM_TYPE_WIN95 == GlobalPlatformType) { //
// Check registry settings on Win9x
//
WCHAR szKey[MAX_PATH]; DWORD dwType; DWORD cbDllName = sizeof(pcdh->pszDllName); DWORD cbFcnName = sizeof(pcdh->pszFcnName); wnsprintfW(szKey, MAX_PATH, L"%ws\\%ws", szRegPathRNAProfileW, pszEntryName);
if((ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey, szRegValAutodialDllNameW, &dwType, (LPBYTE) pcdh->pszDllName, &cbDllName)) && (ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey, szRegValAutodialFcnNameW, &dwType, (LPBYTE) pcdh->pszFcnName, &cbFcnName))) { // try to read flags - not critical if can't find it
DWORD cbFlags = sizeof(DWORD); SHGetValueW(HKEY_CURRENT_USER, szKey, szRegValAutodialFlagsW, &dwType, (LPBYTE) &(pcdh->dwHandlerFlags), &cbFlags); if(0 == cbFlags) pcdh->dwHandlerFlags = 0;
// if we got dll / fcn, we have a handler
pcdh->fHasHandler = TRUE;
// ICW's isign32.dll registers itself as a CDH but does no useful work. Ignore it.
// Note this could distinguish isign32.dll a little better -- right now it will
// incorectly find "aolisign32.dll" if such a thing were to exist.
if( StrStrIW(pcdh->pszDllName, L"isign32.dll") && StrStrIW(pcdh->pszFcnName, L"AutodialLogon")) { // nuke it
memset(pcdh, 0, sizeof(CDHINFO)); } } } else { //
// No such this as a "CDH" on Win2k as defined by this mechanism.
// On Win2K, there's a new field in the rasentry struct specifically
// for this. See the function DialIfWin2KCDH.
//
// Always return FALSE for CDH on Win2K.
//
if(FALSE == GlobalPlatformVersion5) { //
// NT4 - this is broken -- we look in the RASENTRY struct for autodial
// function and dll but these fields are intended for use by NT's
// autodial code, NOT IE's. Prototypes are different and we only
// get by by luck - if NT finds these entries, it tries to find an
// A or W version of the exported function. CM is the only guy that
// does this and they don't export decorated A or W versions. Since
// NT can't find the function, it ignores the entries.
//
// This problem disappears on NT5 -- CM has thier own connectoid
// type. (Custom dial handlers in general won't be supported)
//
RasEntryPropHelp *pRasProp = new RasEntryPropHelp;
if (pRasProp) { if((0 == pRasProp->GetError()) && (0 == pRasProp->GetW(pszEntryName))) { // got entry, if there is custom dial fields, copy them to our
// struct
if(pRasProp->GetAutodiallDllW() && pRasProp->GetAutodialFuncW()) { StrCpyNW(pcdh->pszDllName, pRasProp->GetAutodiallDllW(), sizeof(pcdh->pszDllName)); StrCpyNW(pcdh->pszFcnName, pRasProp->GetAutodialFuncW(), sizeof(pcdh->pszFcnName)); pcdh->fHasHandler = TRUE; } } delete pRasProp; } } }
DEBUG_LEAVE(pcdh->fHasHandler); return pcdh->fHasHandler; }
BOOL CallCDH( IN HWND hwndParent, IN LPWSTR pszEntryName, IN CDHINFO *pcdh, IN DWORD dwOperation, OUT LPDWORD lpdwResult )
/*++
Routine Description:
Call a custom dial handler to perform an operation
Arguments:
hwndParent - parent window for any ui pszEntryName - connection name pcdh - pointer to structure to hold cdh info dwOperation - a CDH operation to perform, one of the INTERNET_CUSTOMDIAL_* operations. lpdwResult - result of CDH operation
ERROR_SUCCESS - operation completed ERROR_ALREADY_EXISTS - connection already exists (CM only) ERROR_USER_DISCONNECTION - user cancelled operation ERROR_INVALID_PARAMETER - CDH failed to load or service request
Returns Value:
BOOL TRUE - CDH handled operation FALSE - didn't
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "CallCDH", "%#x, %#x (%Q), %#x, %#x, %#x", hwndParent, pszEntryName, pszEntryName, pcdh, dwOperation, lpdwResult ));
BOOL fRet = FALSE;
if(pcdh->fHasHandler) { // FIXME - verify handler supports requested operation by checking
// it's flags. Connection Manager has been known to assert if it's
// called to do something it doesn't understand.
HINSTANCE hinstDialerDll = LoadLibraryWrapW(pcdh->pszDllName); if (hinstDialerDll) { PFN_DIAL_HANDLER lpInetDialHandler; CHAR szFcnName[MAX_PATH + 1];
WideCharToMultiByte(CP_ACP, 0, pcdh->pszFcnName, -1, szFcnName, MAX_PATH, NULL, NULL); lpInetDialHandler = (PFN_DIAL_HANDLER)GetProcAddress(hinstDialerDll, szFcnName); if (lpInetDialHandler) { #ifdef _X86_
// IBM Global Network is busted in that it expects to be called
// as cdecl when all other CDHs are stdcall. To get around
// this bustitude somewhat, restore esp after the call to get
// our stack frame back to a point where we won't fault.
DWORD dwSavedEsp; _asm { mov [dwSavedEsp], esp } #endif
// Thunk entry name to ansi
CHAR szEntryName[RAS_MaxEntryName + 1]; WideCharToMultiByte(CP_ACP, 0, pszEntryName, -1, szEntryName, RAS_MaxEntryName, NULL, NULL); fRet = (lpInetDialHandler)(hwndParent, szEntryName, dwOperation, lpdwResult);
#ifdef _X86_
_asm { mov esp, [dwSavedEsp] } #endif
}
FreeLibrary(hinstDialerDll); } }
DEBUG_LEAVE(fRet); return fRet; }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Initialization
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
VOID InitAutodialModule( BOOL fGlobalDataNeeded )
/*++
Routine Description:
Initialize autodial code
Arguments:
None.
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "InitAutodialModule", "%B", fGlobalDataNeeded ));
// check for global data first - will only ever happen once
if(fGlobalDataNeeded && !GlobalDataInitialized) { GlobalDataInitialize(); }
// only do this once...
if(g_fAutodialInitialized) { DEBUG_LEAVE(0); return; }
// make sure internet settings key is open
EnsureInternetSettingsKeyCached();
// There is really no reason to acquire a crosprocess mutex
// We are going to creat a perprocess mutex when services are running. SPP
// wininet folks will explore whether this has to be expanded to include all processes
// (Shishir Pardikar)
if (FALSE == GlobalIsProcessNtService) { // create connection mutex
g_hConnectionMutex = OpenMutex(SYNCHRONIZE, FALSE, CONNECTION_MUTEX); if (g_hConnectionMutex == NULL && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME)) { SECURITY_ATTRIBUTES* psa = SHGetAllAccessSA(); if (psa) { g_hConnectionMutex = CreateMutex(psa, FALSE, CONNECTION_MUTEX); } } } else { g_hConnectionMutex = CreateMutex(NULL, FALSE, NULL); } INET_ASSERT(g_hConnectionMutex != INVALID_HANDLE_VALUE);
// create dial mutex to serialize access to RAS (per process)
g_hRasMutex = CreateMutex(NULL, FALSE, NULL); INET_ASSERT(g_hRasMutex != INVALID_HANDLE_VALUE);
// create proxy registry mutex to serialize access to registry settings across processes
g_hProxyRegMutex = OpenMutex(SYNCHRONIZE, FALSE, PROXY_REG_MUTEX); if (g_hProxyRegMutex == NULL && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME)) { SECURITY_ATTRIBUTES* psa = SHGetAllAccessSA(); if (psa) { g_hProxyRegMutex = CreateMutex(psa, FALSE, PROXY_REG_MUTEX); } }
INET_ASSERT(g_hProxyRegMutex != INVALID_HANDLE_VALUE);
if(FALSE == IsAutodialEnabled(NULL, NULL)) { // if autodial not enabled, then set the fDontProcessHook flag so we
// exit our hook proc very quickly and don't interfere with Winsock
fDontProcessHook = TRUE; }
if(GetModuleHandle("rnaapp.exe")) { // We're in rnaapp! Bail all winsock callbacks
g_fRNAAppProcess = TRUE; } DEBUG_PRINT(DIALUP, INFO, ("g_fRNAAppProcess = %B\n", g_fRNAAppProcess));
g_fAutodialInitialized = TRUE;
DEBUG_LEAVE(0); }
VOID ExitAutodialModule( VOID )
/*++
Routine Description:
Clean up autodial code
Arguments:
None.
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "ExitAutodialModule", NULL ));
// don't do anything if not initialized
if(FALSE == g_fAutodialInitialized) { DEBUG_LEAVE(0); return; }
#ifdef CHECK_SENS
if(g_hSens) { FreeLibrary(g_hSens); g_hSens = NULL; g_pfnIsNetworkAlive = NULL; } #endif
// close connection mutex
if(INVALID_HANDLE_VALUE != g_hConnectionMutex) { CloseHandle(g_hConnectionMutex); g_hConnectionMutex = INVALID_HANDLE_VALUE; }
// close RAS mutex
if(INVALID_HANDLE_VALUE != g_hRasMutex) { CloseHandle(g_hRasMutex); g_hRasMutex = INVALID_HANDLE_VALUE; }
// close proxy registry mutex
if(INVALID_HANDLE_VALUE != g_hProxyRegMutex) { CloseHandle(g_hProxyRegMutex); g_hProxyRegMutex = INVALID_HANDLE_VALUE; }
// close user's reg key
CRefdKey* prk = (CRefdKey*)InterlockedExchangePointer((PVOID*)&g_prkBase, NULL); CloseBaseProxyKey(prk);
if (g_hRasLib) { FreeLibrary(g_hRasLib); g_hRasLib = NULL; }
if(g_hIphlpapi) { FreeLibrary(g_hIphlpapi); g_hIphlpapi = NULL; g_pfnGetBestRoute = NULL; }
g_fAutodialInitialized = FALSE;
DEBUG_LEAVE(0); }
VOID ResetAutodialModule( VOID )
/*++
Routine Description:
Reset certain state when a global reset is called. Causes settings to be reread and some one-time operations to be redone.
Arguments:
None.
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "ResetAutodialModule", NULL ));
// global settings have changed - reset hook to look again
fDontProcessHook = FALSE;
// refresh proxy info and next connection
g_fConnChecked = FALSE;
#ifdef CHECK_SENS
// refresh our sens state
g_fSensInstalled = TRUE; #endif
// beta 1 hack
g_fCheckedUpgrade = FALSE;
// check security context again for HKCU settings
CRefdKey* prk = (CRefdKey*)InterlockedExchangePointer((PVOID*)&g_prkBase, NULL); CloseBaseProxyKey(prk);
DEBUG_LEAVE(0); }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Connection management code
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
#ifdef CHECK_SENS
BOOL GetSensLanState( OUT LPDWORD pdwFlags )
/*++
Routine Description:
Load and query sens to see if any packets have moved on the lan. Beware of service not started and/or api dll not present.
Arguments:
None
Return Value:
BOOL TRUE - Lan is active FALSE - Lan is not active
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "GetSensLanState", "%#x", pdwFlags ));
BOOL fConnected = TRUE;
// initialize out flags parameter to default - lan connectivity
*pdwFlags = NETWORK_ALIVE_LAN;
// If sens isn't around to ask, we have to assume the lan is connected
if(FALSE == g_fSensInstalled) { DEBUG_LEAVE(TRUE); return TRUE; }
//
// Try to load SENS and get our entry point
//
if(NULL == g_hSens) {
INT_PTR fSensRunning;
if(PLATFORM_TYPE_WINNT == GlobalPlatformType) { // check for running service on NT
fSensRunning = IsServiceRunning("Sens", SERVICE_ACTIVE); } else { // check for dialmon loaded bits on Win9x
//
// Webcheck creates this named event to track the lifetime of Sens.
// It's created with CreateEventA so we need to open with with
// OpenEventA.
//
HANDLE hEvent;
fSensRunning = FALSE;
hEvent = OpenEventA(SYNCHRONIZE, FALSE, "MS_WebcheckExternalsTerminateEvent"); if(hEvent) { fSensRunning = TRUE; CloseHandle(hEvent); } }
// On win9x check with dialmon to see if sens is running before
// calling it. If we call it and it isn't loaded, it'll load itself
// and defeat the purpose of not loading it.
if(fSensRunning) { g_hSens = LoadLibrary("sensapi.dll"); if(g_hSens) { g_pfnIsNetworkAlive = (ISNETWORKALIVE)GetProcAddress(g_hSens, "IsNetworkAlive"); } } }
//
// Call sens to get its state
//
if(g_pfnIsNetworkAlive) { fConnected = g_pfnIsNetworkAlive(pdwFlags); g_fSensInstalled = TRUE; if(fConnected) { if(ERROR_SUCCESS != GetLastError()) { // sens service not running - must assume lan is available
g_fSensInstalled = FALSE; } if(0 == (*pdwFlags & (NETWORK_ALIVE_LAN | NETWORK_ALIVE_AOL))) { // no AOL or LAN flag, so return no lan connectivity
fConnected = FALSE; } } }
DEBUG_PRINT(DIALUP, INFO, ("g_fSensInstalled = %B\n", g_fSensInstalled));
//
// If sens isn't alive but we managed to load the dll, unload it
// now as it's useless. Otherwise, hang on to the dll. No need to
// load and unload it all the time.
//
if(FALSE == g_fSensInstalled && g_hSens) { FreeLibrary(g_hSens); g_hSens = NULL; g_pfnIsNetworkAlive = NULL; }
DEBUG_LEAVE(fConnected); return fConnected; }
#endif // CHECK_SENS
BOOL IsDialUpConnection( IN BOOL fForceRefresh, OUT LPDWORD lpdwConnectionNum )
/*++
Routine Description:
Determines whether there's a dial-up connection. Refreshes information periodically.
Arguments:
None
Return Value:
BOOL TRUE - A dial-up connection exists FALSE - No dial-up connection
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsDialUpConnection", "%B, %x", fForceRefresh, lpdwConnectionNum ));
static BOOL fRasLoaded = FALSE; DWORD dwNewTickCount, dwElapsed, dwBytes, dwRes, dwConNum = 0; BOOL fProcessedRecently = FALSE, fRet;
//
// Initialize out parameter
//
if(lpdwConnectionNum) { *lpdwConnectionNum = 0; }
//
// serialize
//
WaitForSingleObject(g_hRasMutex, INFINITE);
//
// Check out how recently we polled ras
//
dwNewTickCount = GetTickCountWrap(); dwElapsed = dwNewTickCount - g_dwLastDialupTicks;
//
// Only refresh if more than MIN... ticks has passed
//
if((dwElapsed >= MIN_RNA_BUSY_CHECK_INTERVAL) || fForceRefresh) { g_dwLastDialupTicks = dwNewTickCount; if(DoConnectoidsExist()) { if(FALSE == fRasLoaded) fRasLoaded = EnsureRasLoaded();
if(fRasLoaded) { g_RasCon.Enum(); if(g_RasCon.GetError() == 0) g_dwConnections = g_RasCon.GetConnectionsCount(); else g_dwConnections = 0; } } else { g_dwConnections = 0; } }
DEBUG_PRINT(DIALUP, INFO, ("Found %d connections\n", g_dwConnections));
if(g_dwConnections > 1 && lpdwConnectionNum) { //
// We have more than one connection and caller wants to know which one
// is the interesting one. Try to find a VPN connectoid.
//
// Note: RasGetEntryPropertiesA doesn't exist on Win95 Gold. However,
// you need RAS 1.2 (which has it) for the VPN device so we're ok
// using it. If we can't dynaload it for some inexplicable reason,
// we'll just end up not finding a VPN entry and setting proxy
// settings to the first connection.
//
// Note we use an array of 2 rasentry structures because NT wants to
// a phone number list after the actual struct and we need space for it.
// An extra RASENTRY struct is 1700+ bytes so it should be sufficient.
//
RasEntryPropHelp *pRasProp = new RasEntryPropHelp;
if (pRasProp) { for(dwConNum = 0; dwConNum < g_dwConnections; dwConNum++) { if(0 == pRasProp->GetW(g_RasCon.GetEntryW(dwConNum))) { if(0 == lstrcmpiA(pRasProp->GetDeviceTypeA(), RASDT_Vpn)) { DEBUG_PRINT(DIALUP, INFO, ("Found VPN entry: %ws\n", g_RasCon.GetEntryW(dwConNum))); *lpdwConnectionNum = dwConNum; break; } } } delete pRasProp; } }
fRet = (BOOL)(g_dwConnections != 0);
//
// verify status of connection we're interested in is RASCS_Connected.
//
if(fRet) { RasGetConnectStatusHelp RasGetConnectStatus(g_RasCon.GetHandle(dwConNum)); dwRes = RasGetConnectStatus.GetError(); if(dwRes || (RasGetConnectStatus.ConnState() != RASCS_Connected)) { fRet = FALSE; }
DEBUG_PRINT(DIALUP, INFO, ("Connect Status: dwRet=%x, connstate=%x\n", dwRes, RasGetConnectStatus.ConnState())); }
ReleaseMutex(g_hRasMutex);
DEBUG_LEAVE(fRet); return fRet; }
BOOL IsLanConnection( OUT LPDWORD pdwFlags )
/*++
Routine Description:
Determines whether there's a lan connection. Refreshes information periodically.
When Sens is present, AOL functionality is retuned as TRUE with *pdwFlags = NETWORK_ALIVE_AOL.
Arguments:
None
Return Value:
BOOL TRUE - A lan connection exists FALSE - No lan connection
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "IsLanConnection", "%#x", pdwFlags ));
static DWORD dwLastSensTicks = 0; static BOOL fSensState = TRUE; static DWORD dwSensFlags = 0; DWORD dwNewTickCount, dwElapsed; BOOL fRet = TRUE;
// init out parameter
INET_ASSERT(pdwFlags); *pdwFlags = 0;
#ifdef CHECK_SENS
//
// Check connectivity apis to see if lan is really present
//
if(fRet) { dwNewTickCount = GetTickCountWrap(); dwElapsed = dwNewTickCount - dwLastSensTicks; if(dwElapsed >= MIN_SENS_CHECK_INTERVAL) { fSensState = GetSensLanState(&dwSensFlags); dwLastSensTicks = dwNewTickCount; } fRet = fSensState; *pdwFlags = dwSensFlags; } #endif
DEBUG_LEAVE(fRet); return fRet; }
VOID CheckForUpgrade( VOID )
/*++
Routine Description:
Performs processing that needs to happen when we upgrade to IE5.
- Migrate proxy and dial settings on upgrade - Migrate legacy proxy settings when they change
Arguments:
None
Return Value:
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "CheckForUpgrade", NULL ));
DWORD dwMigrateState = 1, dwRet, dwEntries = 0; char szUserName[10]; DWORD cbUserNameSize = ARRAYSIZE(szUserName); CRefdKey* prkBase = FindBaseProxyKey();
//
// Bail out right away if we've already done this
// Or if we are running in an NT service such as the usermode portion of webdav redir
// in order to avoid deadlocks
// Also check to make sure we're not running as .default or SYSTEM
if(prkBase && (FALSE == g_fCheckedUpgrade) && (FALSE == GlobalIsProcessNtService) && !IsInGUIModeSetup() && !(GlobalPlatformWhistler && GlobalUserName.Get(szUserName,&cbUserNameSize) && (0 == lstrcmpi(szUserName, ".Default") || 0 == lstrcmpi(szUserName, "SYSTEM")))) { LONG lResult; DWORD dwType, dwExclude, dwSize = sizeof(DWORD), dwDisp; RasEnumHelp *pRasEnum = NULL; //
// Check to see if proxy settings have been migrated
//
if(ERROR_SUCCESS != SHGetValue(prkBase->GetKey(), REGSTR_PATH_INTERNET_SETTINGS, szMigrateProxy, &dwType, &dwMigrateState, &dwSize)) { dwMigrateState = 0; }
DEBUG_PRINT(DIALUP, INFO, ("dwMigrateState=%d\n", dwMigrateState));
//
// set up list of connectoids
//
if(DoConnectoidsExist() && EnsureRasLoaded() && FALSE == GlobalDisableNT4RasCheck) { pRasEnum = new RasEnumHelp; if(pRasEnum != NULL) { dwRet = pRasEnum->GetError(); dwEntries = pRasEnum->GetEntryCount(); } }
//
// Migrate legacy proxy settings to all connections
//
if(0 == dwMigrateState) { INTERNET_PROXY_INFO_EX info;
// start off with clean proxy struct
memset(&info, 0, sizeof(info)); info.dwStructSize = sizeof(INTERNET_PROXY_INFO_EX);
// need to migrate settings
if(ReadLegacyProxyInfo(szRegPathInternetSettings, &info)) { #ifndef UNIX
// make sure autodiscovery is on
info.dwFlags |= PROXY_TYPE_AUTO_DETECT; #endif /* !UNIX */
// Save proxy settings to for lan
info.lpszConnectionName = NULL; WriteProxySettings(&info, TRUE);
// Save legacy settings to special location so we can check
// for change later
info.lpszConnectionName = LEGACY_SAVE_NAME; WriteProxySettings(&info, TRUE);
//
// If we're not turning on autodiscovery for dialup connections
// by default, get rid of it at this point
//
if(FALSE == EnableAutodiscoverForDialup()) { info.dwFlags &= ~PROXY_TYPE_AUTO_DETECT; }
// Save settings for each connectoid
DWORD i; for(i=0; i<dwEntries; i++) { info.lpszConnectionName = pRasEnum->GetEntryA(i); WriteProxySettings(&info, TRUE); }
// clean memory possibly allocated by ReadLegacyProxyInfo
info.lpszConnectionName = NULL; // not allocated, don't free
CleanProxyStruct(&info); } }
//
// Check to see if other dial-up settings have been migrated
//
if(0 == dwMigrateState && dwEntries) { CHAR szKey[MAX_PATH]; DWORD dwMinutes, dwAttempts, dwInterval, dwWait, i; DWORD dwEnable;
// read dial attempts and wait
if(InternetReadRegistryDword(REGSTR_VAL_REDIALATTEMPTS, &dwAttempts)) dwAttempts = DEFAULT_DIAL_ATTEMPTS; if(InternetReadRegistryDword(REGSTR_VAL_REDIALINTERVAL, &dwInterval)) dwInterval = DEFAULT_DIAL_INTERVAL;
// Get idle enable
if(InternetReadRegistryDword(REGSTR_VAL_ENABLEAUTODISCONNECT, &dwEnable) || 0 == dwEnable) { dwEnable = 0; dwMinutes = 20; }
// if enabled, get minutes
if(dwEnable && InternetReadRegistryDword(REGSTR_VAL_DISCONNECTIDLETIME, &dwMinutes)) { dwEnable = 0; dwMinutes = 20; }
// enumerate ras entries
for(i=0; i<dwEntries; i++) { DWORD dwDisposition; HKEY hkey; long lRes;
// migrate settings for this connectoid
GetConnKeyA(pRasEnum->GetEntryA(i), szKey, ARRAYSIZE(szKey)); SHSetValueA(HKEY_CURRENT_USER, szKey, REGSTR_VAL_ENABLEAUTODISCONNECT, REG_DWORD, (BYTE *)&dwEnable, sizeof(DWORD)); SHSetValueA(HKEY_CURRENT_USER, szKey, REGSTR_VAL_DISCONNECTIDLETIME, REG_DWORD, (BYTE *)&dwMinutes, sizeof(DWORD)); SHSetValueA(HKEY_CURRENT_USER, szKey, REGSTR_VAL_ENABLEEXITDISCONNECT, REG_DWORD, (BYTE *)&dwEnable, sizeof(DWORD)); SHSetValueA(HKEY_CURRENT_USER, szKey, REGSTR_VAL_REDIALATTEMPTS, REG_DWORD, (BYTE *)&dwAttempts, sizeof(DWORD)); SHSetValueA(HKEY_CURRENT_USER, szKey, REGSTR_VAL_REDIALINTERVAL, REG_DWORD, (BYTE *)&dwInterval, sizeof(DWORD)); } }
if(pRasEnum) delete pRasEnum;
//
// mark setings as migrated so we don't do this again next time
//
dwDisp = 1; SHSetValueA(prkBase->GetKey(), REGSTR_PATH_INTERNET_SETTINGS, szMigrateProxy, REG_DWORD, &dwDisp, sizeof(DWORD));
if(dwMigrateState) { // We have already migrated settings. If legacy settings have
// changed, update current connection.
INTERNET_PROXY_INFO_EX saved, current, destination;
memset(&saved, 0, sizeof(saved)); saved.dwStructSize = sizeof(INTERNET_PROXY_INFO_EX); saved.lpszConnectionName = LEGACY_SAVE_NAME;
memset(¤t, 0, sizeof(current)); current.dwStructSize = sizeof(INTERNET_PROXY_INFO_EX);
memset(&destination, 0, sizeof(destination)); destination.dwStructSize = sizeof(INTERNET_PROXY_INFO_EX);
if( ReadLegacyProxyInfo(szRegPathInternetSettings, ¤t) && ERROR_SUCCESS == ReadProxySettings(&saved)) { BOOL fChanged = FALSE;
//
// see if they've changed
//
if((saved.dwFlags & LEGACY_MIGRATE_FLAGS) != (current.dwFlags & LEGACY_MIGRATE_FLAGS)) { fChanged = TRUE; } else { // Only check for autoconfig url match if setting is the same and on because
// legacy saved for no autoconfig url is to delete the url.
if((saved.dwFlags & PROXY_TYPE_AUTO_PROXY_URL) && (FALSE == IsConnectionMatch(saved.lpszAutoconfigUrl, current.lpszAutoconfigUrl))) { fChanged = TRUE; } } if(FALSE == IsConnectionMatch(saved.lpszProxy, current.lpszProxy)) { fChanged = TRUE; } if(FALSE == IsConnectionMatch(saved.lpszProxyBypass, current.lpszProxyBypass)) { fChanged = TRUE; }
// if they have, save to current connection
if(fChanged) { DWORD dwIndex; LPCSTR lpszTemp;
// save new legacy settings to check again later
current.lpszConnectionName = LEGACY_SAVE_NAME; WriteProxySettings(¤t, TRUE);
// read existing lan settings
destination.lpszConnectionName = NULL; ReadProxySettings(&destination);
// fix flags
destination.dwFlags = (destination.dwFlags & ~LEGACY_MIGRATE_FLAGS) | (current.dwFlags & LEGACY_MIGRATE_FLAGS);
// fix proxy server / override
lpszTemp = destination.lpszProxy; destination.lpszProxy = current.lpszProxy; current.lpszProxy = lpszTemp;
lpszTemp = destination.lpszProxyBypass; destination.lpszProxyBypass = current.lpszProxyBypass; current.lpszProxyBypass = lpszTemp;
// fix autoconfig url
lpszTemp = destination.lpszAutoconfigUrl; destination.lpszAutoconfigUrl = current.lpszAutoconfigUrl; current.lpszAutoconfigUrl = lpszTemp;
// save it
WriteProxySettings(&destination, TRUE); } }
saved.lpszConnectionName = NULL; current.lpszConnectionName = NULL; destination.lpszConnectionName = NULL; CleanProxyStruct(&saved); CleanProxyStruct(¤t); CleanProxyStruct(&destination); }
// don't run this code again
g_fCheckedUpgrade = TRUE; }
CloseBaseProxyKey(prkBase);
DEBUG_LEAVE(0); }
DWORD FixProxySettings( IN LPWSTR pszConnW, IN BOOL fForceUpdate, IN DWORD dwLanFlags )
/*++
Routine Description:
Copy lan or dial-up proxy settings to generic key and tell proxy code new proxy information
Arguments:
pszConn - connection name to switch to fForceUpdate - set regardless of having set before dwLanFlags - distinguish between LAN and AOL connection
Return Value:
DWORD 0 - no proxy for this connection 1 - proxy exists for this connection
--*/
{ DEBUG_ENTER((DBG_DIALUP, Int, "FixProxySettings", "%#x (%Q), %B, %#x", pszConnW, pszConnW, fForceUpdate, dwLanFlags ));
static TCHAR pszLastConn[RAS_MaxEntryName+1]; static DWORD dwEnable = 0; CHAR szConn[RAS_MaxEntryName + 1]; LPSTR pszConn = NULL;
if(pszConnW != NULL) { *szConn = '\0'; pszConn = szConn; WideCharToMultiByte(CP_ACP, 0, pszConnW, -1, pszConn, RAS_MaxEntryName, NULL, NULL); }
//
// Make sure we've listened to any global settings changed that happened
// in other processes
//
if (InternetSettingsChanged()) { ChangeGlobalSettings(); }
//
// Ensure upgrade stuff is done
//
CheckForUpgrade();
//
// Is this connection already fixed?
//
if(g_fConnChecked && (FALSE == fForceUpdate)) { if((NULL == pszConn && 0 == *pszLastConn) || 0 == lstrcmp(pszConn, pszLastConn)) { // already fixed this connection
DEBUG_LEAVE(dwEnable); return dwEnable; } }
//
// Get proxy struct for proxy object
//
INTERNET_PROXY_INFO_EX info; memset(&info, 0, sizeof(info)); info.dwStructSize = sizeof(info); info.lpszConnectionName = pszConn;
//
// Read proxy settings for this connection unless it's LAN/AOL
// in which case we want no proxy
//
if(pszConn || 0 == (dwLanFlags & NETWORK_ALIVE_AOL)) { if (ReadProxySettings(&info) != ERROR_SUCCESS) { DEBUG_LEAVE(dwEnable); return dwEnable; } }
//
// Save connection we fixed
//
if(NULL == pszConn) { // lan
*pszLastConn = 0; } else { // connectoid
lstrcpyn(pszLastConn, pszConn, RAS_MaxEntryName + 1); }
// tell caller if proxy is enabled
if(info.dwFlags & PROXY_TYPE_PROXY) { dwEnable = 1; } else { dwEnable = 0; }
GlobalProxyInfo.SetProxySettings(&info, FALSE);
//GlobalProxyInfo.RefreshProxySettings(FALSE);
//
// Copy current settings to the legacy reg locations so legacy
// apps can find them.
//
info.lpszConnectionName = LEGACY_SAVE_NAME; WriteLegacyProxyInfo(szRegPathInternetSettings, &info, TRUE); WriteProxySettings(&info, TRUE);
// free up memory allocated by ReadProxySettings
info.lpszConnectionName = NULL; // not allocated, don't free
CleanProxyStruct(&info);
//
// Flag we've checked this at least once so in future we can bail out early
//
g_fConnChecked = TRUE;
DEBUG_LEAVE(dwEnable); return dwEnable; }
BOOL FixProxySettingsForCurrentConnection( IN BOOL fForceUpdate )
/*++
Routine Description:
Figure out the current connection and fix proxy settings for it. Basically a cheap, return-no-info version of GetConnectedStateEx used by the winsock callback.
Arguments:
none
Return Value:
BOOL TRUE - connected FALSE - not connected
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "FixProxySettingsForCurrentConnection", "%B", fForceUpdate ));
BOOL fRet, fForceDial; DWORD dwFixEntry;
//
// Make sure everything's initialized
//
InitAutodialModule(TRUE);
// serialize connection type stuff
WaitForSingleObject(g_hConnectionMutex, INFINITE);
//
// Check to see if we have a dialup connection
//
fRet = IsDialUpConnection(FALSE, &dwFixEntry); if(fRet) { FixProxySettings(g_RasCon.GetEntryW(dwFixEntry), fForceUpdate, 0); }
//
// If dial always isn't set, check lan setting
//
IsAutodialEnabled(&fForceDial, NULL);
if(FALSE == fRet && FALSE == fForceDial) { //
// no ras connections - ensure LAN proxy settings are correct
//
DWORD dwFlags; fRet = IsLanConnection(&dwFlags);
//
// Whether we have a lan connection or not, prop lan proxy settings.
// This allows unknown connections to use lan settings.
//
FixProxySettings(NULL, fForceUpdate, dwFlags); }
ReleaseMutex(g_hConnectionMutex);
DEBUG_LEAVE(fRet); return fRet; }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Win2K Helper Functions
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
BOOL DialIfWin2KCDH( IN LPWSTR pszEntry, IN HWND hwndParent, IN BOOL fHideParent, OUT DWORD *lpdwResult, OUT DWORD_PTR *lpdwConnection )
/*++
Routine Description:
Check a connectoid to see if it has a Win2K custom dial handler and if so, do the voodoo magic to dial it
Arguments:
lpParams - dial params hwndParent - parent window fHideParent - if true, hide this window if dialing this connectoid lpdwResult - result of dial (set if return is TRUE)
Return Value:
BOOL TRUE - Attempted to dial Win2K CDH FALSE - didn't
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "DialIfWin2KCDH", "%x (%Q), %x, %B, %x, %x", pszEntry, pszEntry, hwndParent, fHideParent, lpdwResult, lpdwConnection ));
DWORD dwRet; RasEntryPropHelp *pRasProp = new RasEntryPropHelp; BOOL fResult = FALSE;
if (pRasProp == NULL) { goto Cleanup; }
if(FALSE == GlobalPlatformVersion5) { // not on win2k, bag
goto Cleanup; }
// get props for this connectoid and see if it has a custom dial dll
if(ERROR_SUCCESS != (dwRet = pRasProp->GetW(pszEntry))) { // error getting rasentry struct
goto Cleanup; }
if(NULL == pRasProp->GetCustomDialDllW()) { // no custom dial dll
goto Cleanup; }
// hide parent window if necessary
if(fHideParent) { ShowWindow(hwndParent, SW_HIDE); }
// call rasdialdlg to dial the custom dude
HMODULE hLib; RASDIALDLG rdd; _RASDIALDLGW pfnRdd;
hLib = LoadLibrary("rasdlg.dll"); if(hLib) { pfnRdd = (_RASDIALDLGW)GetProcAddress(hLib, "RasDialDlgW"); if(pfnRdd) { memset(&rdd, 0, sizeof(rdd)); rdd.dwSize = sizeof(RASDIALDLG); rdd.hwndOwner = hwndParent; dwRet = (*pfnRdd)(NULL, pszEntry, NULL, &rdd); } FreeLibrary(hLib); } else { // really bad...
goto Cleanup; }
// figure out how we did
if(dwRet) { DWORD dwEntry;
// success
*lpdwResult = ERROR_SUCCESS;
// find hconn for the thing we just dialed
if(lpdwConnection) { if(IsDialUpConnection(TRUE, &dwEntry)) { *lpdwConnection = (DWORD_PTR) g_RasCon.GetHandle(dwEntry); } } } else { // error or cancel
*lpdwResult = ERROR_USER_DISCONNECTION;
if(rdd.dwError) { *lpdwResult = rdd.dwError; } }
fResult = TRUE;
Cleanup: if (pRasProp) { delete pRasProp; }
DEBUG_LEAVE(fResult); return fResult; }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Winsock callback handler
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
DWORD CheckForNoNetOverride( LPSTR pszHostName ) { DEBUG_ENTER((DBG_DIALUP, Bool, "CheckForNoNetOverride", "%#x (%q)", pszHostName, pszHostName ));
DWORD dwAutodialFlags = 0; DWORD dwFlags;
if(IsOS(OS_WHISTLERORGREATER) && IsLanConnection(&dwFlags) && ERROR_SUCCESS == LoadWinsock()) { DWORD dwIpAddress; DWORD dwError;
// assume no route and we want to override
dwAutodialFlags = INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT;
// First check to see if we have an ip address.
ADDRINFO Hints; LPADDRINFO lpAddrInfo;
memset(&Hints, 0, sizeof(struct addrinfo)); Hints.ai_flags = AI_NUMERICHOST; // Only check for address literals.
Hints.ai_family = PF_UNSPEC; // Accept any protocol family.
Hints.ai_socktype = SOCK_STREAM; // Constrain results to stream socket.
Hints.ai_protocol = IPPROTO_TCP; // Constrain results to TCP.
dwError = _I_getaddrinfo(pszHostName, NULL, &Hints, &lpAddrInfo);
if(ERROR_SUCCESS != dwError) { // not an ip address, try to resolve name
Hints.ai_flags = AI_CANONNAME; dwError = _I_getaddrinfo(pszHostName, NULL, &Hints, &lpAddrInfo); }
//
// If we got an IP4 address, check to see if we have a route for it
//
if(ERROR_SUCCESS == dwError && (AF_INET == lpAddrInfo->ai_family)) { MIB_IPFORWARDROW bestRoute; DWORD dwError = 0;
if(NULL == g_hIphlpapi) { g_hIphlpapi = LoadLibrary("iphlpapi.dll"); if(g_hIphlpapi) { g_pfnGetBestRoute = (GETBESTROUTE)GetProcAddress(g_hIphlpapi, "GetBestRoute"); } }
// snag ip address from lpaddr
SOCKADDR_IN *paddr = (SOCKADDR_IN *)(lpAddrInfo->ai_addr); dwIpAddress = *((unsigned long *)(&paddr->sin_addr));
if(g_pfnGetBestRoute && (ERROR_SUCCESS == g_pfnGetBestRoute(dwIpAddress, 0, &bestRoute))) { // got a route, no need to override dial semantics
DEBUG_PRINT(DIALUP, INFO, ("Found a route to %s, no need to override dial\n", pszHostName)); dwAutodialFlags = 0; } }
UnloadWinsock(); }
DEBUG_LEAVE(dwAutodialFlags); return dwAutodialFlags; }
BOOL InternetAutodialIfNotLocalHost( IN LPSTR OPTIONAL pszURL, IN LPSTR OPTIONAL pszHostName )
/*++
Routine Description:
Dial so long as we're configured for it and the name passed isn't a local host alias.
Finds: 'localhost' '127.0.0.1' and its aliases local machine name from registry or winsock
If a URL is specified, it's cracked to get the host name.
Arguments:
pszURL - url to check for pszHostName - hostname to check for
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_DIALUP, Bool, "InternetAutodialIfNotLocalHost", "%#x (%q), %#x (%q)", pszURL, pszURL, pszHostName, pszHostName ));
CHAR *pszURLCopy = NULL, *pszLocalHostname; BOOL fLocalHost = FALSE; BOOL fAllocatedBuffer = FALSE; BOOL fRet = TRUE; BOOL fNeedToFix = TRUE; DWORD dwAutodialFlags = 0;
//
// Make sure we're all initialized
//
InitAutodialModule(TRUE);
// we bypass this activity in an NT service has disabled autodialing. This special cases
// this behaviour for the webdav redir.
// In future wininet folks will look to see whether this shouldn't be done for all
// apps disabling autodialing. For now we just avoid the testing hit for the
// browser folks (Shishir Pardikar)
if((FALSE == fDontProcessHook) && !(GlobalIsProcessNtService && !IsAutodialEnabled(NULL, NULL)))
{ //
// If we were passed a URL, crack it to get host name
//
if(NULL == pszHostName && pszURL) { DWORD dwHostNameLength; long error;
// make a copy of url to crack
pszURLCopy = new (CHAR[INTERNET_MAX_URL_LENGTH+1]); if(NULL == pszURLCopy) { goto quit; } fAllocatedBuffer = TRUE; lstrcpyn(pszURLCopy, pszURL, INTERNET_MAX_URL_LENGTH);
// crack it
error = CrackUrl(pszURLCopy, 0, FALSE, // don't escape URL-path
NULL, // don't care about scheme
NULL, // don't care about Scheme Name
NULL, &pszHostName, &dwHostNameLength, NULL, // don't care about port
NULL, // don't care about user name
NULL, NULL, // or password
NULL, NULL, // or object
NULL, NULL, // no extra
NULL, NULL );
if ((error != ERROR_SUCCESS) || (pszHostName == NULL)) { goto quit; }
// null-terminate host name (stomps pszURLCopy buffer)
pszHostName[dwHostNameLength] = 0; }
//
// We'd better have a host name by now...
//
INET_ASSERT(pszHostName); if(NULL == pszHostName) { goto quit; }
//
// Check for 'localhost'
//
if( 0 == lstrcmpi(pszHostName, "localhost")) { DEBUG_PRINT(DIALUP, INFO, ("Found localhost\n")); fLocalHost = TRUE; goto quit; }
//
// check for 127.0.0.1 or its variants -- use inet_addr if winsock loaded
//
if(g_fWinsockLoaded || _I_inet_addr) { if(ERROR_SUCCESS == LoadWinsock()) { if(0x0100007f == _I_inet_addr(pszHostName)) { fLocalHost = TRUE; } UnloadWinsock(); } } else { // winsock not loaded, do the best we can
if(0 == lstrcmpi(pszHostName, "127.0.0.1")) { fLocalHost = TRUE; } }
if(fLocalHost) { DEBUG_PRINT(DIALUP, INFO, ("Found 127.0.0.1 alias\n")); goto quit; }
//
// check local machine name
//
pszLocalHostname = new (CHAR[INTERNET_MAX_HOST_NAME_LENGTH+1]); INET_ASSERT(pszLocalHostname); if(pszLocalHostname) { DWORD dwSize = INTERNET_MAX_HOST_NAME_LENGTH; DWORD dwValType;
// check fully qualified name (only if we know winsock is loaded)
if(g_fWinsockLoaded || _I_gethostname) { if(ERROR_SUCCESS == LoadWinsock()) { if(0 == _I_gethostname(pszLocalHostname, INTERNET_MAX_HOST_NAME_LENGTH)) { if(0 == lstrcmpi(pszLocalHostname, pszHostName)) fLocalHost = TRUE; } UnloadWinsock(); } }
if (!fLocalHost && SHGetValue(HKEY_LOCAL_MACHINE,szRegPathTCP, szRegValHostName,&dwValType,pszLocalHostname,&dwSize) == ERROR_SUCCESS) { if(0 == lstrcmpi(pszLocalHostname, pszHostName)) fLocalHost = TRUE; }
// also against check computer name in registry, RPC
// will use this if there's no DNS hostname set
dwSize = INTERNET_MAX_HOST_NAME_LENGTH; if (!fLocalHost && SHGetValue(HKEY_LOCAL_MACHINE, szRegPathComputerName, szRegValComputerName,&dwValType,pszLocalHostname,&dwSize) == ERROR_SUCCESS) { if(0 == lstrcmpi(pszLocalHostname, pszHostName)) fLocalHost = TRUE; }
delete pszLocalHostname; }
if(fLocalHost) { DEBUG_PRINT(DIALUP, INFO, ("Found local machine name\n")); goto quit; }
// Check for override of "dial if no net" (ICS host is prime example)
dwAutodialFlags = CheckForNoNetOverride(pszHostName);
// not localhost, so need to autodial
fRet = InternetAutodial(dwAutodialFlags, 0); fNeedToFix = FALSE; }
quit: if(fNeedToFix) { // Since we're not dialing, ensure correct settings
FixProxySettingsForCurrentConnection(FALSE); }
if(fAllocatedBuffer) { delete pszURLCopy; }
DEBUG_LEAVE(fRet); return fRet; }
extern "C" VOID InternetAutodialCallback( IN DWORD dwOpCode, IN LPCVOID lpParam )
/*++
Routine Description:
Possibly establish a connection prior to a winsock operation. Called by winsock before each operation.
Arguments:
dwOpCode - Winsock operation about to be done lpParam - Information about operation
Return Value:
None.
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, None, "InternetAutodialCallback", "%s (%#x), %#x", InternetMapWinsockCallbackType(dwOpCode), dwOpCode, lpParam ));
//
// Make sure we're initialized and have done the process check!
//
InitAutodialModule(FALSE);
//
// If we're in rnaapp.exe process, bail out now!
//
if(g_fRNAAppProcess) { DEBUG_PRINT(DIALUP, INFO, ("Process is rnaapp.exe! Bailing out!\n")); DEBUG_LEAVE_API(0); return; }
// return as soon as possible if we know there's nothing for us to do here...
// keep track of the last time we sent winsock activity messages or
// checked for RNA activity. We won't do these things more than once
// every MIN_RNA_BUSY_CHECK_INTERVAL seconds. Getting the tick count
// is extremely cheap so this is a worthwhile optimization.
BOOL fProcessedRecently = FALSE; DWORD dwNewTickCount = GetTickCountWrap(); DWORD dwElapsed = dwNewTickCount - g_dwLastTickCount; if (dwElapsed < MIN_RNA_BUSY_CHECK_INTERVAL) { fProcessedRecently = TRUE; } else { g_dwLastTickCount = dwNewTickCount; }
// we're in the winsock callback so it's safe (ie. cheap) to call winsock
g_fWinsockLoaded = TRUE;
if (!fProcessedRecently) { // if hidden autodisconnect monitor window is around, send it a message to
// notify it of winsock activity so it knows we're not idle.
HWND hwndMonitorApp = FindWindow(szAutodialMonitorClass,NULL); if (hwndMonitorApp) { PostMessage(hwndMonitorApp,WM_WINSOCK_ACTIVITY,0,0); } if(NULL == g_hwndWebCheck) { g_hwndWebCheck = FindWindow(szWebCheckMonitorClass,NULL); } if(g_hwndWebCheck) { PostMessage(g_hwndWebCheck,WM_WINSOCK_ACTIVITY,0,0); } }
//
// Only continue if we have a callback type that we actually do something
// with
//
switch(dwOpCode) { case WINSOCK_CALLBACK_CONNECT: case WINSOCK_CALLBACK_RECVFROM: // we do stuff with these so continue...
break; case WINSOCK_CALLBACK_GETHOSTBYNAME: // bail out now for gethostbyname(NULL) else do normal
// gethostbyname processing.
if(NULL == lpParam) { DEBUG_PRINT(DIALUP, INFO, ("Not dialing for gethostbyname(NULL)\n")); DEBUG_LEAVE_API(0); return; } break; default: DEBUG_LEAVE_API(0); return; }
//
// if we're EXPLORER or IEXPLORE and in global offline mode, don't dial
//
if (GlobalIsProcessExplorer && IsGlobalOffline()) { DEBUG_LEAVE_API(0); return; }
//
// verify proxy settings are correct for current connection and if
// we're already connected, bail out!
//
if(FixProxySettingsForCurrentConnection(FALSE) || fDontProcessHook) { DEBUG_LEAVE_API(0); return; }
//
// Look at the specific winsock operation we're doing and bail out if
// we don't want to dial
//
switch (dwOpCode) { case WINSOCK_CALLBACK_CONNECT: case WINSOCK_CALLBACK_RECVFROM: // these APIs all have a sockaddr struct as the API-specific
// parameter, look in struct to find address family. Don't
// respond if it's non-TCP.
INET_ASSERT(lpParam);
if (lpParam) { struct sockaddr_in * psa = (struct sockaddr_in *) lpParam;
if (AF_INET != psa->sin_family) { // not TCP, don't respond
DEBUG_PRINT(DIALUP, INFO, ("Not dialing for non TCP connect\n")); DEBUG_LEAVE_API(0); return; }
#if defined(UNIX) && defined(ux10)
DEBUG_PRINT(DIALUP, INFO, ("IP address: %d.%d.%d.%d\n", ((LPBYTE)&(psa->sin_addr))[0], ((LPBYTE)&(psa->sin_addr))[1], ((LPBYTE)&(psa->sin_addr))[2], ((LPBYTE)&(psa->sin_addr))[3])); #else
DEBUG_PRINT(DIALUP, INFO, ("IP address: %d.%d.%d.%d\n", psa->sin_addr.S_un.S_un_b.s_b1, psa->sin_addr.S_un.S_un_b.s_b2, psa->sin_addr.S_un.S_un_b.s_b3, psa->sin_addr.S_un.S_un_b.s_b4)); #endif
if (0x0100007f == psa->sin_addr.s_addr) { // loop back address, don't respond
DEBUG_PRINT(DIALUP, INFO, ("Not dialing for 127.0.0.1\n")); DEBUG_LEAVE_API(0); return; }
//
// Check to make sure this isn't our local address if possible
//
// This is a very rare code path and won't be hit in normal
// browsing. Also, winsock is already loaded in this process
// so LoadWinsock is reasonably cheap.
//
// This code is here to fix FrontPage and WinCE. Those are
// pretty much the only guys that will ever hit it.
//
// [darrenmi] don't attempt to do this if we're on the
// netware client because gethostbyname(NULL) will fault.
//
// how many IPs can the local host have? 16 seems like an
// excessive amount.
#define MAX_IP_COUNT 16
if (FALSE == GlobalRunningNovellClient32 && FALSE == g_fGetHostByNameNULLFails && ERROR_SUCCESS == LoadWinsock()) { // get real ip addresses for this host
HOSTENT *ph;
__try { ph = _I_gethostbyname(NULL); } __except(EXCEPTION_EXECUTE_HANDLER) { g_fGetHostByNameNULLFails = TRUE; ph = NULL; } ENDEXCEPT
if(ph) { int iCount = 0; DWORD dwAddress[MAX_IP_COUNT];
while((LPDWORD)(ph->h_addr_list[iCount]) && iCount < MAX_IP_COUNT) { dwAddress[iCount] = *((LPDWORD)(ph->h_addr_list[iCount]));
//
// don't dial if connecting to this host's ip address
//
// FrontPage does this.
//
if(dwAddress[iCount] == psa->sin_addr.s_addr) { DEBUG_PRINT(DIALUP, INFO, ("Not dialing for local host IP address\n")); DEBUG_LEAVE_API(0); return; }
iCount++; }
//
// RFC1918 lists 192.168.x.x as 256 class C networks
// for use as non-global addresses. If this address
// is one of these guys and we already have an ip on the
// same subnet, don't dial
//
// WinCE device does this.
//
if((psa->sin_addr.s_addr & 0x0000FFFF) == 0x0000A8C0) { int i;
for(i=0; i<iCount; i++) { if((psa->sin_addr.s_addr & 0x00FFFFFF) == (dwAddress[i] & 0x00FFFFFF)) { // connect to a local subnet we're alreay on. Don't dial.
DEBUG_PRINT(DIALUP, INFO, ("Not dialing for local 192.168.x.x subnet\n")); DEBUG_LEAVE_API(0); return; } } } } UnloadWinsock(); } } break;
case WINSOCK_CALLBACK_GETHOSTBYNAME: // a lot of apps do a GetHostByName(<local host name>) first
// thing to get their hands on a hostent struct, this doesn't
// constitute wanting to hit the net. If we get a GetHostByName,
// compare the host name to the local host name in the registry,
// and if they match then don't respond to this.
if (lpParam) { InternetAutodialIfNotLocalHost(NULL, (LPSTR)lpParam); DEBUG_LEAVE_API(0); return; } }
//
// Dial...
//
InternetAutodial(0, 0);
DEBUG_LEAVE_API(0); }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// Public APIs
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
VOID AUTO_PROXY_DLLS::SaveDetectedProxySettings( IN LPINTERNET_PROXY_INFO_EX lpProxySettings, IN BOOL fNeedHostIPChk ) { BOOL fRet; BOOL fDialupRet; BOOL fConnectionMatch = FALSE;
//
// Ensure we're initialized
//
InitAutodialModule(TRUE);
WaitForSingleObject(g_hConnectionMutex, INFINITE);
// remove settting from last time...
lpProxySettings->dwAutoDiscoveryFlags &= ~(AUTO_PROXY_FLAG_DETECTION_SUSPECT);
//
// Check to see if we have a dialup connection
//
DWORD dwFixEntry; fRet = IsDialUpConnection(TRUE, &dwFixEntry);
if(fRet) { // check for match
if(lpProxySettings->lpszConnectionName && lstrcmpiA(lpProxySettings->lpszConnectionName, g_RasCon.GetEntryA(dwFixEntry)) == 0) { fConnectionMatch = TRUE; } }
fDialupRet = fRet;
DWORD dwFlags;
//
// no ras connections - ensure LAN proxy settings are correct
//
fRet = IsLanConnection(&dwFlags);
if(fRet) { if (lpProxySettings->lpszConnectionName == NULL) { fConnectionMatch = TRUE; } else if (fDialupRet && (dwFlags & NETWORK_ALIVE_LAN) && (lpProxySettings->dwDetectedInterfaceIpCount == 1) && g_fSensInstalled ) { //
// At this point our detection results are suspect,
// because we are claiming to have a DialUp Adapter,
// Net Adapter, and only One IP address for the whole
// system.
//
lpProxySettings->dwAutoDiscoveryFlags |= AUTO_PROXY_FLAG_DETECTION_SUSPECT; } }
if ( fConnectionMatch && !(IsGlobalOffline())) { LockAutoProxy();
fRet = TRUE;
//
// Do Host IP check to confirm we're still ok, ie on the same connection,
// that we began on.
//
if ( fNeedHostIPChk ) { DWORD error; DWORD * pdwDetectedInterfaceIp = NULL; DWORD dwDetectedInterfaceIpCount;
fRet = FALSE;
error = GetHostAddresses(&pdwDetectedInterfaceIp, &dwDetectedInterfaceIpCount); // will this cause problems with auto-dial?
if ( error == ERROR_SUCCESS && dwDetectedInterfaceIpCount == lpProxySettings->dwDetectedInterfaceIpCount) { fRet = TRUE; for (DWORD i = 0; i < dwDetectedInterfaceIpCount; i++) { if (pdwDetectedInterfaceIp[i] != lpProxySettings->pdwDetectedInterfaceIp[i] ) { fRet = FALSE; break; } } }
if ( pdwDetectedInterfaceIp != NULL) { FREE_MEMORY(pdwDetectedInterfaceIp); } }
//
// Now save out all our settings, if we can.
//
if (fRet) { SetProxySettings(lpProxySettings, IsModifiedInProcess(), FALSE /*no overwrite*/);
if ( ! IsModifiedInProcess() ) { // Need to save results to registry, if we succeed,
// then make sure to transfer new version stamp
if ( WriteProxySettings(lpProxySettings, FALSE) == ERROR_SUCCESS ) { _ProxySettings.dwCurrentSettingsVersion = lpProxySettings->dwCurrentSettingsVersion; } }
// stamp version, so we know we've been updated.
_dwUpdatedProxySettingsVersion = lpProxySettings->dwCurrentSettingsVersion; }
UnlockAutoProxy(); }
ReleaseMutex(g_hConnectionMutex); return; }
INTERNETAPI_(BOOL) InternetGetConnectedStateExW( OUT LPDWORD lpdwFlags, OUT LPWSTR lpszConnectionName, IN DWORD dwBufLen, IN DWORD dwReserved )
/*++
Routine Description:
Determine whether any useful connections exist
On FALSE, will return information about autodial connection if any
Arguments:
lpdwFlags - Location to store flags about current connection INTERNET_CONNECTION_MODEM Modem connection INTERNET_CONNECTION_LAN Network connection INTERNET_CONNECTION_PROXY Proxy in use INTERNET_RAS_INSTALLED Ras is installed on machine lpszConnectionName - name of current connection dwBufLen - length of name buffer dwReserved - Must be 0
Return Value:
BOOL TRUE - connection exists FALSE - no connection exists
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetGetConnectedStateExW", "%#x, %#x, %#x, %#x", lpdwFlags, lpszConnectionName, dwBufLen, dwReserved ));
BOOL fRet = FALSE, fProcessedRecently = FALSE, fConfigured = FALSE; DWORD dwFlags = 0; DWORD dwRes = 0, dwBytes, dwEnable = 0; AUTODIAL ad; BOOL fAutodialEnabled; static BOOL fSensState = TRUE;
//
// Ensure we're initialized
//
InitAutodialModule(TRUE);
//
// Verify parameters
//
if((lpdwFlags && ERROR_SUCCESS != ProbeWriteBuffer(lpdwFlags, sizeof(DWORD))) || (lpszConnectionName && ERROR_SUCCESS != ProbeWriteBuffer(lpszConnectionName, dwBufLen)) || dwReserved) { SetLastError(ERROR_INVALID_PARAMETER); DEBUG_ERROR(DIALUP, ERROR_INVALID_PARAMETER); DEBUG_LEAVE_API(FALSE); return FALSE; }
//
// If on Millennium, forward calls to RAS
//
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRasInternetGetConnectedStateExA) { CHAR szAnsiName[RAS_MaxEntryName + 1]; DWORD dwConnFlags = 0;
//
// call RAS one first...
//
fRet = _RasInternetGetConnectedStateExA(&dwConnFlags, szAnsiName, RAS_MaxEntryName, dwReserved);
if(lpszConnectionName) { MultiByteToWideChar(CP_ACP, 0, szAnsiName, -1, lpszConnectionName, dwBufLen); }
//
// RAS one fills in everything except PROXY and OFFLINE flags.
//
if(dwConnFlags & INTERNET_CONNECTION_MODEM) { dwEnable = FixProxySettings(lpszConnectionName, FALSE, 0); } else if(dwConnFlags & INTERNET_CONNECTION_LAN) { dwEnable = FixProxySettings(NULL, FALSE, 0); }
if(dwEnable) { dwConnFlags |= INTERNET_CONNECTION_PROXY | INTERNET_CONNECTION_CONFIGURED; }
if(IsGlobalOffline()) { dwConnFlags |= INTERNET_CONNECTION_OFFLINE; }
if(fRet) { // we now have a connection - if we get into a state where we don't,
// ask user to go offline
g_fAskOffline = TRUE; }
// set out flags if caller requested it
if(lpdwFlags) { *lpdwFlags = dwConnFlags; }
DEBUG_LEAVE_API(fRet); return fRet; }
//
// Initialize out variables
//
if(lpdwFlags) *lpdwFlags = 0;
if(lpszConnectionName) *lpszConnectionName = 0;
WaitForSingleObject(g_hConnectionMutex, INFINITE);
//
// Check to see if we have a dialup connection
//
DWORD dwFixEntry; fRet = IsDialUpConnection(FALSE, &dwFixEntry);
//
// Tell caller if RAS is installed
//
if(g_fRasInstalled) { dwFlags |= INTERNET_RAS_INSTALLED; }
if(fRet) { // this connectoid is connected
dwFlags |= INTERNET_CONNECTION_MODEM; fConfigured = TRUE;
dwEnable = FixProxySettings(g_RasCon.GetEntryW(dwFixEntry), FALSE, 0);
// copy name for caller
if(lpszConnectionName && dwBufLen) { StrCpyNW(lpszConnectionName, g_RasCon.GetEntryW(dwFixEntry), dwBufLen); } }
//
// autodial configuration is relevant for finding out if lan is present.
// if autodial.force is set, consider lan NOT present since we're going
// to dial anyway.
//
fAutodialEnabled = IsAutodialEnabled(NULL, &ad);
if((FALSE == fRet) && (FALSE == ad.fForceDial)) { //
// no ras connections - ensure LAN proxy settings are correct
//
DWORD dwLanFlags; fRet = IsLanConnection(&dwLanFlags);
if(fRet) { // lan connection is configured and present
dwFlags |= INTERNET_CONNECTION_LAN; dwEnable = FixProxySettings(NULL, FALSE, dwLanFlags); // if call wants name, fill in "lan connection"
if(lpszConnectionName && dwBufLen) LoadStringWrapW(GlobalDllHandle, IDS_LAN_CONNECTION, lpszConnectionName, dwBufLen); } }
//
// turn on proxy flag if necessary
//
if(dwEnable) { dwFlags |= INTERNET_CONNECTION_PROXY;
// we have some kind of configured connection
fConfigured = TRUE; }
//
// If no connection found, tell caller about autodial entry
//
if(FALSE == fConfigured || 0 == (dwFlags & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_MODEM))) { if(ad.fConfigured) { // we have an autodial connection
fConfigured = TRUE;
if(0 == (dwFlags & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_MODEM))) { // autodial is enabled
// If the caller cares about entry name, find them one
if(ad.fHasEntry) { // use specified one
dwFlags |= INTERNET_CONNECTION_MODEM; if(lpszConnectionName && dwBufLen) { StrCpyNW(lpszConnectionName, ad.pszEntryName, dwBufLen); } } else { // None set as default, pick one and set it
RasEnumHelp * pre = new RasEnumHelp;
if(pre) { if (pre->GetEntryCount()) { LPWSTR pwzName = pre->GetEntryW(0);
// set this entry to the default
SHSetValueW(HKEY_CURRENT_USER, szRegPathRemoteAccessW, szRegValInternetEntryW, REG_SZ, (BYTE *)pwzName, lstrlenW(pwzName));
// return to caller
dwFlags |= INTERNET_CONNECTION_MODEM; if(lpszConnectionName && dwBufLen) { StrCpyNW(lpszConnectionName, pwzName, dwBufLen); } } delete pre; } } } } }
//
// Tell caller if we have a connection configured
//
if(fConfigured) { dwFlags |= INTERNET_CONNECTION_CONFIGURED; }
//
// Tell caller if we're offline
//
if(IsGlobalOffline()) { dwFlags |= INTERNET_CONNECTION_OFFLINE; }
if(lpdwFlags) *lpdwFlags = dwFlags;
#if defined(SITARA)
//
// IF we're configured to use a modem,
// then go ahead an turn on Sitara
//
if (fRet && (dwFlags & INTERNET_CONNECTION_MODEM)) { GlobalHasSitaraModemConn = TRUE; } else { GlobalHasSitaraModemConn = FALSE; }
#endif // SITARA
if(fRet) // we now have a connection - if we get into a state where we don't,
// ask user to go offline
g_fAskOffline = TRUE;
ReleaseMutex(g_hConnectionMutex);
DEBUG_LEAVE_API(fRet); SetLastError(ERROR_SUCCESS); return fRet; }
INTERNETAPI_(BOOL) InternetGetConnectedStateExA( OUT LPDWORD lpdwFlags, OUT LPSTR lpszConnectionName, IN DWORD dwBufLen, IN DWORD dwReserved )
/*++
Routine Description:
Ansi version of InternetGetConnectedStateExW
Arguments:
Same as InternetGetConnectedStateExW
Return Value:
Same as InternetGetConnectedStateExW
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetGetConnectedStateExA", "%#x, %#x, %#x, %#x", lpdwFlags, lpszConnectionName, dwBufLen, dwReserved ));
WCHAR szWideName[RAS_MaxEntryName + 1]; BOOL fRet;
//
// call wide version
//
*szWideName = 0; fRet = InternetGetConnectedStateExW(lpdwFlags, szWideName, RAS_MaxEntryName, dwReserved);
//
// convert wide name to ansi
//
if(lpszConnectionName) { if(ERROR_SUCCESS == ProbeWriteBuffer(lpszConnectionName, dwBufLen)) { int i; i = WideCharToMultiByte(CP_ACP, 0, szWideName, -1, lpszConnectionName, dwBufLen, NULL, NULL); if(0 == i) { // truncated - null terminate
lpszConnectionName[dwBufLen - 1] = 0; } } else { SetLastError(ERROR_INVALID_PARAMETER); DEBUG_ERROR(DIALUP, ERROR_INVALID_PARAMETER); fRet = FALSE; } }
DEBUG_LEAVE_API(fRet); return fRet; }
INTERNETAPI_(BOOL) InternetGetConnectedState( OUT LPDWORD lpdwFlags, IN DWORD dwReserved )
/*++
Routine Description:
Get simple information about connected state
Arguments:
lpdwFlags - Location to store connection flags
xxx
dwReserved - must be 0
Return Value:
BOOL Connected - TRUE
Not - FALSE
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetGetConnectedState", "%#x, %#x", lpdwFlags, dwReserved ));
BOOL fRet = InternetGetConnectedStateExW(lpdwFlags, NULL, 0, dwReserved);
DEBUG_LEAVE_API(fRet); return fRet; }
BOOL HandleFlagsForRas( IN HWND hwndParent, IN BOOL fAutodialing, IN DWORD dwFlags, OUT DWORD *pdwRasFlags )
/*++
Routine Description:
Convert InternetDial flags to RasInternetDial flags. Also directly handle any flags that Ras doesn't know about.
Only ever called on Millennium
Arguments:
hwndParent Parent window for any UI fAutodialing We're called from InternetAutodial vs. InternetDial dwFlags InternetDial flags dwRasFlags RasInternetDial flags
Return values:
TRUE Success
FALSE Abort operation
--*/ { DEBUG_ENTER((DBG_DIALUP, Dword, "HandleFlagsForRas", "%#x, %B, %#x, %#x", hwndParent, fAutodialing, dwFlags, pdwRasFlags ));
DWORD dwResult = ERROR_SUCCESS;
*pdwRasFlags = 0;
//
// Convert flags for directly supported options
//
if((dwFlags & INTERNET_DIAL_SHOW_OFFLINE) || (GlobalIsProcessExplorer)) *pdwRasFlags |= RAS_INTERNET_AUTODIAL_ALLOW_OFFLINE; if((dwFlags & INTERNET_DIAL_UNATTENDED) || (dwFlags & INTERNET_AUTODIAL_FORCE_UNATTENDED)) *pdwRasFlags |= RAS_INTERNET_AUTODIAL_UNATTENDED;
// if(dwFlags & INTERNET_DIAL_FORCE_PROMPT) not supported
//
// Handle offline mode
//
if(dwFlags & INTERNET_AUTODIAL_FORCE_ONLINE) { SetOffline(FALSE); }
//
// Handle security check -- only if not connected and autodial and check is enabled.
//
AUTODIAL ad; DWORD dwState;
if(!IsDialUpConnection(FALSE, NULL)) { //
// Perform check if:
//
// - Autodial is enabled OR we're not autodialing
// - and Security check is enabled
//
IsAutodialEnabled(NULL, &ad);
if((ad.fEnabled || !fAutodialing) && ad.fSecurity) { if(PerformSecurityCheck(hwndParent, dwFlags)) { // non-silent check failed
dwResult = ERROR_INTERNET_FAILED_DUETOSECURITYCHECK; } } }
DEBUG_PRINT(DIALUP, INFO, ("Ras Flags=0x%x\n", *pdwRasFlags));
DEBUG_LEAVE(dwResult); return dwResult; }
VOID HandleUserCancel( IN DWORD dwResult, IN DWORD dwFlags )
/*++
Routine Description:
Check to see if user cancelled dial and fix appropriate states
Arguments:
dwResult - Result of dialing operation -- only care about USER_DISCONNECTION dwFlags - Dialing flags, only care about SHOW_OFFLINE
Return Value:
None
--*/
{ DEBUG_ENTER((DBG_DIALUP, None, "HandleUserCancel", "%#x, %#x", dwResult, dwFlags ));
if(ERROR_USER_DISCONNECTION == dwResult) { if(GlobalIsProcessExplorer || (dwFlags & INTERNET_DIAL_SHOW_OFFLINE)) { // offline semantics - set offline mode
SetOffline(TRUE); } else { // Normal cancel. Prevent more dialing attempts.
fDontProcessHook = TRUE; } }
DEBUG_LEAVE(0); }
DWORD InternetDialW( IN HWND hwndParent, IN LPWSTR pszEntryName, IN DWORD dwFlags, OUT DWORD_PTR *lpdwConnection, IN DWORD dwReserved )
/*++
Routine Description:
Connect to a specified connectoid
Arguments:
hwndParent - parent window for dialing ui
pszEntryName - string => connectoid to connect to - empty string ("") => let user choose - NULL => connect to autodial connectoid
dwFlags - flags controlling operation:
xxx
lpdwConnection - location to store connection handle
dwReserved - must be 0
Return Value:
DWORD Success - 0
Failure - Ras or windows error code
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Dword, "InternetDialW", "%#x, %#x (%Q), %#x, %#x, %#x", hwndParent, pszEntryName, pszEntryName, dwFlags, lpdwConnection, dwReserved ));
DIALSTATE data; BOOL fConn = FALSE; DWORD dwRet = ERROR_SUCCESS, dwTemp; WCHAR szKey[MAX_PATH]; AUTODIAL ad;
//
// Ensure we're initialized
//
InitAutodialModule(TRUE);
//
// ensure reserved field is 0
//
if(dwReserved) { dwRet = ERROR_INVALID_PARAMETER; goto quit; }
//
// ensure we have a lpdwConnection pointer and initialize it
//
if(NULL == lpdwConnection || ERROR_SUCCESS != ProbeWriteBuffer(lpdwConnection, sizeof(DWORD))) { dwRet = ERROR_INVALID_PARAMETER; goto quit; } *lpdwConnection = 0;
//
// ensure we have a valid pszEntryName (NULL is valid - see below)
//
if(pszEntryName && ERROR_SUCCESS != ProbeStringW(pszEntryName, &dwTemp)) { dwRet = ERROR_INVALID_PARAMETER; goto quit; }
//
// On Millennium, forward calls to RAS
//
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRasInternetDialA) { DWORD dwRasFlags;
dwRet = HandleFlagsForRas(hwndParent, FALSE, dwFlags, &dwRasFlags); if(dwRet) { // error, need to bail out
DEBUG_LEAVE_API(dwRet); return dwRet; }
CHAR szAnsiName[RAS_MaxEntryName+1]; CHAR *pszNameToUse = NULL;
if(pszEntryName) { WideCharToMultiByte(CP_ACP, 0, pszEntryName, -1, szAnsiName, RAS_MaxEntryName, NULL, NULL); pszNameToUse = szAnsiName; }
dwRet = _RasInternetDialA(hwndParent, pszNameToUse, dwRasFlags, lpdwConnection, dwReserved);
//
// Switch to offline mode if necessary
//
HandleUserCancel(dwRet, dwFlags);
//
// If connected, send message to dialmon
//
CDHINFO cdh; DWORD dwEntry = 0; if(IsDialUpConnection(TRUE, &dwEntry) && !IsCDH(g_RasCon.GetEntryW(dwEntry), &cdh)) { SendDialmonMessage(WM_SET_CONNECTOID_NAME, TRUE); }
//
// fix proxy information for new connection
//
FixProxySettingsForCurrentConnection(FALSE);
DEBUG_LEAVE_API(dwRet); return dwRet; }
//
// Check config state
//
IsAutodialEnabled(NULL, &ad);
if(ad.fSecurity) { if(PerformSecurityCheck(hwndParent, dwFlags)) { DEBUG_LEAVE_API(ERROR_INTERNET_FAILED_DUETOSECURITYCHECK); return ERROR_INTERNET_FAILED_DUETOSECURITYCHECK; } }
//
// Save connectoid name
//
memset(&data, 0, sizeof(DIALSTATE)); data.params.dwSize = sizeof(RASDIALPARAMSW); if(pszEntryName && *pszEntryName) { // use passed connection name as one to dial
StrCpyNW(data.params.szEntryName, pszEntryName, RAS_MaxEntryName + 1); } else { // NULL name passed, use autodial entry if any. If not, use first
// one in list (data.params.szEntryName == "")
if(ad.fEnabled && ad.fHasEntry) { StrCpyNW(data.params.szEntryName, ad.pszEntryName, RAS_MaxEntryName + 1); } }
//
// Check to see if already have a ras connection
//
fConn = IsDialUpConnection(FALSE, NULL);
//
// Check to see if there's a custom dial handler
//
if(FALSE == fConn) { CDHINFO cdh;
memset(&cdh, 0, sizeof(CDHINFO)); if(IsCDH(data.params.szEntryName, &cdh)) { DWORD dwTmpRetVal;
if(CallCDH(hwndParent, data.params.szEntryName, &cdh, INTERNET_CUSTOMDIAL_CONNECT, &dwTmpRetVal)) { dwRet = dwTmpRetVal; if(ERROR_SUCCESS == dwRet || ERROR_ALREADY_EXISTS == dwRet) { // successfully connected
dwRet = ERROR_SUCCESS;
if(lpdwConnection) *lpdwConnection = (DWORD)CDH_HCONN;
// reset last ras poll time to force a check next time
g_dwLastDialupTicks = 0;
// fix proxy information for new connection
WaitForSingleObject(g_hConnectionMutex, INFINITE); FixProxySettings(data.params.szEntryName, FALSE, 0); ReleaseMutex(g_hConnectionMutex); } else { // check to see if user cancelled and go to offline if necessary
HandleUserCancel(dwRet, dwFlags); } dwRet = ERROR_SUCCESS; goto quit; }
// else CDH didn't actually do anything - fall through
} }
if(GlobalPlatformVersion5 && *data.params.szEntryName) { // check to see if it's a win2k CDH
if(DialIfWin2KCDH(data.params.szEntryName, hwndParent, FALSE, &dwRet, lpdwConnection)) { // check for cancel and offline mode
HandleUserCancel(dwRet, dwFlags);
goto quit; } }
//
// If we still don't have a connection, show our UI to make one
//
if(FALSE == fConn) { DWORD dwType, dwTemp, dwSize; BOOL fDialedCDH = FALSE;
//
// serialize access to our UI
//
// If we already are displaying the UI, bring it to the foreground
// get mutex and check connection again - may have to wait for it and
// connection status could change
INET_ASSERT(g_hAutodialMutex); WaitForSingleObject(g_hAutodialMutex, INFINITE);
if(IsDialUpConnection(FALSE, NULL)) { // got a connection in the mean time - bail out
ReleaseMutex(g_hAutodialMutex); DEBUG_LEAVE_API(ERROR_SUCCESS); return ERROR_SUCCESS; }
if(IsGlobalOffline()) { // we went offline, then bail out without UI
ReleaseMutex(g_hAutodialMutex); DEBUG_LEAVE_API(ERROR_SUCCESS); return ERROR_SUCCESS; }
//
// Make sure ras is happy
//
if(FALSE == EnsureRasLoaded()) { ReleaseMutex(g_hAutodialMutex); DEBUG_LEAVE_API(ERROR_NO_CONNECTION); return ERROR_NO_CONNECTION; }
//
// Fire up commctrl
//
InitCommCtrl(); if(!g_hDialEvent) { g_hDialEvent = CreateEvent(NULL, FALSE, FALSE, NULL); }
if(!g_hDialEvent) { return E_FAIL; } //
// Dial it
//
CDialUI *pdui = new CDialUI(hwndParent);
if(pdui) { // make sure we have a reference
pdui->AddRef(); dwRet = pdui->StartDial(&data, dwFlags); fDialedCDH = pdui->DialedCDH(); pdui->Release(); }
//
// Shut down commtrl
//
ExitCommCtrl();
//
// Switch to offline mode if necessary
//
HandleUserCancel(data.dwResult, dwFlags);
//
// reset last ras poll time to force a check next time and release
// mutex
//
g_dwLastDialupTicks = 0; ReleaseMutex(g_hAutodialMutex);
if(!fDialedCDH) { //
// Save connect automatically if it wasn't overridden
//
if(0 == (dwFlags & INTERNET_DIAL_FORCE_PROMPT)) { GetConnKeyW(data.params.szEntryName, szKey, ARRAYSIZE(szKey)); dwTemp = (data.dwFlags & CI_AUTO_CONNECT) ? 1 : 0; SHSetValueW(HKEY_CURRENT_USER, szKey, REGSTR_DIAL_AUTOCONNECTW, REG_DWORD, &dwTemp, sizeof(DWORD)); } //
// check to see if we're really connected or not
//
if(data.dwResult || NULL == data.hConn) { if(data.hConn) _RasHangUp(data.hConn); dwRet = data.dwResult; goto quit; } RasGetConnectStatusHelp RasGetConnectStatus(data.hConn); dwRet = RasGetConnectStatus.GetError(); if(dwRet) { _RasHangUp(data.hConn); goto quit; } if(RasGetConnectStatus.ConnState() != RASCS_Connected) { _RasHangUp(data.hConn); dwRet = ERROR_NO_CONNECTION; goto quit; } } }
//
// fix proxy information for new connection
//
WaitForSingleObject(g_hConnectionMutex, INFINITE); FixProxySettings(data.params.szEntryName, FALSE, 0); ReleaseMutex(g_hConnectionMutex);
//
// reset last ras poll time to force a check next time
//
g_dwLastDialupTicks = 0;
//
// start disconnect monitoring
//
SendDialmonMessage(WM_SET_CONNECTOID_NAME, TRUE);
//
// return handle to caller if required
//
if(lpdwConnection) *lpdwConnection = (DWORD_PTR) data.hConn;
quit: SetEvent(g_hDialEvent); DEBUG_LEAVE_API(dwRet); return dwRet; }
DWORD InternetDialA( IN HWND hwndParent, IN LPSTR pszEntryName, IN DWORD dwFlags, OUT DWORD_PTR *lpdwConnection, IN DWORD dwReserved )
/*++
Routine Description:
Wide version of InternetDialA
Arguments:
Same as InternetDialA
Return Value:
Same as InternetDialA
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Dword, "InternetDialA", "%#x, %#x (%q), %#x, %#x, %#x", hwndParent, pszEntryName, pszEntryName, dwFlags, lpdwConnection, dwReserved ));
DWORD dwErr = ERROR_SUCCESS; WCHAR szWideEntryName[RAS_MaxEntryName + 1]; WCHAR *pwzNameToUse = NULL;
if (pszEntryName) { if (IsBadStringPtr(pszEntryName, RAS_MaxEntryName + 1)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } else { int i; i = MultiByteToWideChar(CP_ACP, 0, pszEntryName, -1, szWideEntryName, RAS_MaxEntryName); if(0 == i) { // truncated - null terminate
szWideEntryName[RAS_MaxEntryName] = 0; } pwzNameToUse = szWideEntryName; } } dwErr = InternetDialW(hwndParent, pwzNameToUse, dwFlags, lpdwConnection, dwReserved);
cleanup: DEBUG_LEAVE_API(dwErr); return dwErr; }
DWORD InternetHangUp( IN DWORD_PTR dwConnection, IN DWORD dwReserved )
/*++
Routine Description:
Hangs up a connection established by InternetDial
Arguments:
dwConnection - connection obtained from InternetDial
dwReserved - must be 0
Return Value:
DWORD Success - 0
Failure - Ras or windows error code
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Dword, "InternetHangUp", "%#x, %#x", dwConnection, dwReserved ));
DWORD dwRet;
//
// If on Millennium, forward calls to RAS
//
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRasInternetHangUpA) { dwRet = _RasInternetHangUpA(dwConnection, dwReserved);
DEBUG_LEAVE_API(dwRet); return dwRet; }
// ensure reserved is 0
if(dwReserved) { DEBUG_LEAVE_API(ERROR_INVALID_PARAMETER); return ERROR_INVALID_PARAMETER; }
//
// Ensure we're initialized
//
if(FALSE == g_fAutodialInitialized) { InitAutodialModule(FALSE); }
//
// Best we can do for CDH's is post message to the disconnect monitor.
// Hopefully it'll do the right thing and disconnect. Works for MSN
// at least.
//
if(CDH_HCONN == dwConnection) { //
// Try to find a CM connection to hang up
//
if(IsDialUpConnection(FALSE, NULL)) { CDHINFO cdh; DWORD i, dwError;
for(i=0; i < g_dwConnections; i++) { if(IsCDH(g_RasCon.GetEntryW(i), &cdh)) { if(StrStrIW(cdh.pszDllName, szCMDllNameW)) { DEBUG_PRINT(DIALUP, INFO, ("Found CM connection to hang up\n")); dwError = _RasHangUp(g_RasCon.GetHandle(i)); DEBUG_LEAVE_API(dwError); return dwError; } } } }
HWND hwndMonitorWnd = FindWindow(TEXT("MS_AutodialMonitor"),NULL); if (hwndMonitorWnd) { PostMessage(hwndMonitorWnd,WM_IEXPLORER_EXITING,0,0); }
DEBUG_LEAVE_API(0); return 0; }
//
// Load ras
//
if(FALSE == EnsureRasLoaded()) { DEBUG_LEAVE_API(ERROR_UNKNOWN); return ERROR_UNKNOWN; }
//
// hang up the connection
//
dwRet = _RasHangUp((HRASCONN)dwConnection);
DEBUG_LEAVE_API(dwRet); return dwRet; }
BOOLAPI InternetSetDialStateA( IN LPCSTR lpszEntryName, IN DWORD dwState, IN DWORD dwReserved )
/*++
Routine Description:
Sets current state for a custom dial handler.
This was broken in IE4 and didn't actually do anything. Rather than leave it in this state, the notion of custom dial state has been removed. [darrenmi]
Arguments:
lpszEntryName - connectiod to set state for
dwState - new connection state
dwReserved - must be 0
Return Value:
BOOL Success - TRUE
Failure - FALSE, GetLastError for more information
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetSetDialStateA", "%#x (%q), %#x, %#x", lpszEntryName, lpszEntryName, dwState, dwReserved ));
// NOTE: When this starts using lpszEntryName, remember to define USES_STRING to activate
// unicode conversions for InternetSetDialStateW.
if(dwReserved) { SetLastError(ERROR_INVALID_PARAMETER); DEBUG_ERROR(DIALUP, ERROR_INVALID_PARAMETER);
DEBUG_LEAVE_API(FALSE); return FALSE; }
// [darrenmi] I do not expect any client to ever call this api - I don't
// think any were ever written. Only possible exception may be CM.
// If it does call it, I want to know.
#ifdef DEBUG
OutputDebugString("Wininet.DLL: Unexpected use of dead api, contact darrenmi [x34231]\n"); OutputDebugString("Wininet.DLL: It is safe to continue past this DebugBreak()\n"); DebugBreak(); #endif
DEBUG_LEAVE_API(TRUE); return TRUE; }
BOOLAPI InternetSetDialStateW( IN LPCWSTR lpszEntryName, IN DWORD dwState, IN DWORD dwReserved )
/*++
Routine Description:
Wide version of InternetSetDialStateA
Arguments:
Same as InternetSetDialStateA
Return Value:
Same as InternetSetDialStateA
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetSetDialStateW", "%#x (%Q), %#x, %#x", lpszEntryName, lpszEntryName, dwState, dwReserved ));
BOOL fRet;
//
// Convert and call multibyte version
//
#ifdef INTERNETSETDIALSTATE_USES_CONNECTOID
DWORD dwErr = ERROR_SUCCESS; MEMORYPACKET mpConnectoid;
if (lpszEntryName) { ALLOC_MB(lpszEntryName, 0, mpConnectoid); if (!mpConnectoid.psStr) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } UNICODE_TO_ANSI(lpszEntryName, mpConnectoid); } fRet = InternetSetDialStateA(mpConnectoid.psStr, dwState, dwReserved);
cleanup: if (dwErr!=ERROR_SUCCESS) { SetLastError(dwErr); DEBUG_ERROR(DIALUP, dwErr); } #else
fRet = InternetSetDialStateA(NULL, dwState, dwReserved); #endif
DEBUG_LEAVE_API(fRet); return fRet; }
BOOLAPI InternetGoOnlineW( IN LPWSTR lpszURL, IN HWND hwndParent, IN DWORD dwFlags )
/*++
Routine Description:
Show UI to ask user whether they wish to go back online. This is triggered by clicking a link that isn't available offline.
Arguments:
lpszURL - url that triggered switch (currently not used)
hwndParent - parent window for dialog
dwFlags - operation control flags (currently not used) INTERENT_GOONLINE_REFRESH This was caused by a refresh rather than a click on an unavailable link
Return Value:
BOOL Success - TRUE
Failure - FALSE, GetLastError for more information
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetGoOnlineW", "%#x (%Q), %#x, %#x", lpszURL, lpszURL, hwndParent, dwFlags ));
INT_PTR fRet = TRUE;
//
// validate flags
//
if(dwFlags & ~INTERENT_GOONLINE_REFRESH) { SetLastError(ERROR_INVALID_PARAMETER); DEBUG_ERROR(DIALUP, ERROR_INVALID_PARAMETER);
DEBUG_LEAVE_API(FALSE); return FALSE; }
//
// if already online, we're done
//
if(IsGlobalOffline()) { ULONG_PTR uCookie = 0; SHActivateContext(&uCookie); //
// Show ui to ask user to go online
//
fRet = DialogBoxParamWrapW(GlobalDllHandle, MAKEINTRESOURCEW(IDD_GOONLINE), hwndParent, OnlineDlgProc, 0);
if (uCookie) { SHDeactivateContext(uCookie); } }
if(fRet) { //
// Make sure we're connected.
//
SetOffline(FALSE);
MEMORYPACKET mpUrl; if (lpszURL) { ALLOC_MB(lpszURL, 0, mpUrl); if (mpUrl.psStr) { UNICODE_TO_ANSI(lpszURL, mpUrl); fRet = InternetAutodialIfNotLocalHost(mpUrl.psStr, NULL); } else { fRet = FALSE; } } }
DEBUG_LEAVE_API(fRet != 0); return (fRet != 0); }
BOOLAPI InternetGoOnlineA( IN LPSTR lpszURL, IN HWND hwndParent, IN DWORD dwFlags )
/*++
Routine Description:
Wide version of InternetGoOnlineA
Arguments:
Same as InternetGoOnlineA
Return Value:
Same as InternetGoOnlineA
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetGoOnlineA", "%#x (%q), %#x, %#x", lpszURL, lpszURL, hwndParent, dwFlags ));
BOOL fRet = FALSE;
//
// Convert and call multibyte version
//
DWORD dwErr = ERROR_SUCCESS; BOOL fResult = FALSE; LPWSTR lpszWideURL = NULL;
if (lpszURL) { int i; DWORD dwLen = lstrlenA(lpszURL); if((lpszWideURL = (LPWSTR)LocalAlloc(LPTR, (dwLen+1) * sizeof(WCHAR))) != NULL) { i = MultiByteToWideChar(CP_ACP, 0, lpszURL, -1, lpszWideURL, dwLen); if(0 == i) lpszWideURL[dwLen] = 0; // truncated - null terminate
} }
fRet = InternetGoOnlineW(lpszWideURL, hwndParent, dwFlags);
if(lpszWideURL) { LocalFree(lpszWideURL); }
DEBUG_LEAVE_API(fRet); return fRet; }
BOOL InternetAutodial( IN DWORD dwFlags, IN HWND hwndParent )
/*++
Routine Description:
Dials the internet connectoid
Arguments:
dwFlags - flags to control operation
xxx
hwndParent - parent window for any ui that's displayed
Return Value:
BOOL Success - TRUE
Failure - FALSE, GetLastError for more info
--*/
{ DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetAutodial", "%#x, %#x", dwFlags, hwndParent ));
AUTODIAL config; DWORD dwErrorCode = ERROR_INTERNET_INTERNAL_ERROR; DWORD dwRet = ERROR_SUCCESS, dwLanFlags; HWND hwnd = GetDesktopWindow();
//
// On Millennium, forward calls to RAS
//
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRasInternetAutodialA) { DWORD dwRasFlags;
dwRet = HandleFlagsForRas(hwndParent, TRUE, dwFlags, &dwRasFlags); if(dwRet) { // error, need to bail out
DEBUG_LEAVE_API(dwRet); return dwRet; }
dwRet = _RasInternetAutodialA(dwRasFlags, hwndParent);
//
// Switch to offline mode if necessary
//
HandleUserCancel(dwRet, dwFlags);
//
// If connected, send message to dialmon
//
CDHINFO cdh; DWORD dwEntry = 0; if(IsDialUpConnection(TRUE, &dwEntry) && !IsCDH(g_RasCon.GetEntryW(dwEntry), &cdh)) { SendDialmonMessage(WM_SET_CONNECTOID_NAME, TRUE); }
//
// fix proxy information for new connection
//
FixProxySettingsForCurrentConnection(FALSE);
//
// Prop return code
//
if(dwRet) { DEBUG_ERROR(DIALUP, dwRet); SetLastError(dwRet); }
DEBUG_LEAVE_API(0 == dwRet); return (0 == dwRet); }
// dwFlags - only valid flag is INTERNET_AUTODIAL_FORCE_UNATTENDED
// Keep ISVs honest about this
if(dwFlags & ~(INTERNET_AUTODIAL_FLAGS_MASK)) { dwErrorCode = ERROR_INVALID_PARAMETER; goto quit; }
if(FALSE == g_fAutodialInitialized) { InitAutodialModule(TRUE); }
// if no parent window was passed, use desktop window
if(NULL == hwndParent) { hwndParent = GetDesktopWindow(); }
//
// need connection mutex for FixProxySettings and IsLanConnection
//
WaitForSingleObject(g_hConnectionMutex, INFINITE);
//
// check to see if we're already connected
//
if(IsDialUpConnection(FALSE, &dwRet)) { // make sure proxy settings are correct
FixProxySettings(g_RasCon.GetEntryW(dwRet), FALSE, 0); ReleaseMutex(g_hConnectionMutex);
// If we're connected by modem, ensure online if necessary
if(dwFlags & INTERNET_AUTODIAL_FORCE_ONLINE) { SetOffline(FALSE); }
dwErrorCode = ERROR_SUCCESS; goto quit; }
// Check config and make sure we have connectoids if we're supposed to
// dial one
if(IsAutodialEnabled(NULL, &config)) { if(FALSE == EnsureRasLoaded()) { config.fEnabled = config.fForceDial = FALSE; } else { RasEnumHelp *pRasEnum = new RasEnumHelp;
if (pRasEnum) { if (pRasEnum->GetEntryCount() == 0) { config.fEnabled = config.fForceDial = FALSE; } delete pRasEnum; } } }
if(IsLanConnection(&dwLanFlags) && (FALSE == config.fForceDial)) { if(!config.fEnabled || !(dwFlags & INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT)) { // make sure proxy settings are correct
FixProxySettings(NULL, FALSE, dwLanFlags); ReleaseMutex(g_hConnectionMutex);
// autodial not necessary
dwErrorCode = ERROR_SUCCESS; goto quit; } }
//
// check if offline and can't go online...
//
if( GlobalIsProcessExplorer && IsGlobalOffline() && 0 == (dwFlags & INTERNET_AUTODIAL_FORCE_ONLINE)) {
ReleaseMutex(g_hConnectionMutex); dwErrorCode = ERROR_INTERNET_OFFLINE; goto quit; }
// make sure we're online
SetOffline(FALSE);
// make sure we're supposed to dial
if(FALSE == config.fEnabled) { fDontProcessHook = TRUE; dwErrorCode = ERROR_SUCCESS;
DEBUG_PRINT(DIALUP, INFO, ("Unable to find a connection\n"));
// no connections and can't dial. Prompt to go offline.
if(g_fAskOffline) { // IE5 Beta 1 Hack - Throw up this dialog for explorer or IE
// Only for now. However, we should introduce an API that
// allows any app to say that it wants to participate in
// IE's Offline Mode stuff and all such apps would then
// get this dialog
if(GlobalIsProcessExplorer) { ULONG_PTR uCookie = 0; SHActivateContext(&uCookie); // Throw up this dialog for explorer.exe or iexplore.exe only
if(DialogBoxParamWrapW(GlobalDllHandle, MAKEINTRESOURCEW(IDD_GOOFFLINE), hwndParent, GoOfflinePromptDlgProc,(LPARAM) 0)) { SetOffline(TRUE); } else { g_fAskOffline = FALSE; } if (uCookie) { SHDeactivateContext(uCookie); } } }
//
// If we try to hit the net at this point, we want to use the lan
// settings whatever they are.
//
// This is the only place settings get propagated when no connection
// can be found.
//
FixProxySettings(NULL, FALSE, 0); ReleaseMutex(g_hConnectionMutex);
goto quit; }
// if no entry, fill in a bogus one - dialing UI will pick the first
// one
if(FALSE == config.fHasEntry) { config.pszEntryName[0] = 0; config.fHasEntry = TRUE; }
ReleaseMutex(g_hConnectionMutex);
// Load Ras
if(FALSE == EnsureRasLoaded()) { // Load of ras failed - probably not installed
fDontProcessHook = TRUE; dwErrorCode = ERROR_SERVICE_DOES_NOT_EXIST; goto quit; }
//
// Fix dial flags
//
if((dwFlags & INTERNET_AUTODIAL_FORCE_UNATTENDED) && (config.fUnattended)) dwFlags |= INTERNET_DIAL_UNATTENDED;
//
// Dial it
//
DWORD_PTR dwHandle; dwErrorCode = InternetDialW(hwndParent, config.pszEntryName, dwFlags, &dwHandle, 0);
quit: if(dwErrorCode != ERROR_SUCCESS) { SetLastError(dwErrorCode); DEBUG_ERROR(DIALUP, dwErrorCode); } DEBUG_LEAVE_API(dwErrorCode == ERROR_SUCCESS);
return((dwErrorCode == ERROR_SUCCESS)); }
BOOLAPI InternetAutodialHangup( IN DWORD dwReserved )
/*++
Routine Description:
Finds and hangs up the autodial connection
If the autodial connection is a CDH, call the CDH to hang it up. This may or may not work depending on whether the CDH supports hanging up.
Arguments:
dwReserved - must be 0
Return Value:
BOOL Success - TRUE
Failure - FALSE, GetLastError for more information
--*/
{ AUTODIAL config; CDHINFO cdh;
DEBUG_ENTER_API((DBG_DIALUP, Bool, "InternetAutodialHangup", "%#x", dwReserved ));
DWORD dwErr = ERROR_SUCCESS; int j = 0;
// ensure reserved is 0
if(dwReserved) { SetLastError(ERROR_INVALID_PARAMETER); DEBUG_ERROR(DIALUP, ERROR_INVALID_PARAMETER); DEBUG_LEAVE_API(FALSE); return FALSE; }
//
// On Millennium, forward calls to RAS
//
if(GlobalPlatformMillennium && EnsureRasLoaded() && pfnRasInternetAutodialHangUpA) { dwErr = _RasInternetAutodialHangUpA(dwReserved);
DEBUG_LEAVE_API(TRUE); return TRUE; }
if(FALSE == g_fAutodialInitialized) { InitAutodialModule(FALSE); }
// read connectoid - if none or autodial not enabled, bail
if(FALSE == IsAutodialEnabled(NULL, &config) || FALSE == config.fHasEntry) goto quit;
if(IsCDH(config.pszEntryName, &cdh)) { //
// If this CDH is CM, bail out here so the RasHangup below happens
//
if(NULL == StrStrIW(cdh.pszDllName, szCMDllNameW)) { // ask it to hang up - may or may not do it depending on what it
// supports
//
// This isn't going to work. CM doesn't like getting commands it
// doesn't understand. For now, CDHs don't hang up. Tough.
//
// CallCDH(NULL, config.pszEntryName, &cdh, INTERNET_CUSTOMDIAL_DISCONNECT);
//
// Actually, post message to CDH's disconnect monitor. Works for
// MSN at least.
HWND hwndMonitorWnd = FindWindow(TEXT("MS_AutodialMonitor"),NULL); if (hwndMonitorWnd) { PostMessage(hwndMonitorWnd,WM_IEXPLORER_EXITING,0,0); }
goto quit; } }
//
// See if a ras connection matches the autodial connectoid
//
if(IsDialUpConnection(FALSE, NULL)) { //
// See if any current connections match autodial connection
//
DWORD i;
for(i = 0; i < g_dwConnections; i++) { if(0 == StrCmpIW(g_RasCon.GetEntryW(i), config.pszEntryName)) { _RasHangUp(g_RasCon.GetHandle(i)); break; } } }
quit: DEBUG_LEAVE_API(TRUE); return TRUE; }
|