mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1436 lines
43 KiB
1436 lines
43 KiB
/*****************************************************************/
|
|
/** Microsoft Windows **/
|
|
/** Copyright (C) Microsoft Corp., 1995 **/
|
|
/*****************************************************************/
|
|
|
|
//
|
|
// AUTODIAL.CPP - winsock autodial hook code
|
|
//
|
|
|
|
// HISTORY:
|
|
//
|
|
// 3/22/95 jeremys Created.
|
|
//
|
|
|
|
#include "project.hpp"
|
|
#pragma hdrstop
|
|
|
|
#include <winsock.h>
|
|
#include <oharestr.h>
|
|
#include <regstr.h>
|
|
#include <dialmsg.h>
|
|
|
|
#include "resource.h"
|
|
#include "autodial.hpp"
|
|
|
|
extern "C" {
|
|
VOID AutodialHookCallback(DWORD dwOpCode,LPCVOID lpParam);
|
|
BOOL AutodialInit(VOID);
|
|
VOID AutodialDeInit(VOID);
|
|
#include "connapi.h"
|
|
#include "windowsx.h"
|
|
}
|
|
|
|
// Globals
|
|
BOOL fModemInUse = FALSE;
|
|
BOOL fDontProcessHook = FALSE;
|
|
BOOL fUserCancelled = FALSE;
|
|
DWORD dwLastTickCount = 0;
|
|
|
|
// Function prototypes
|
|
BOOL LoadRNADll(VOID);
|
|
VOID UnloadRNADll(VOID);
|
|
BOOL IsModemPresent(VOID);
|
|
BOOL ChooseInternetConnectoid(HWND hwndOwner,LPSTR pszConnectoidName,
|
|
DWORD cbConnectoidName);
|
|
BOOL CALLBACK ChooseConnectoidDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
|
|
LPARAM lParam);
|
|
BOOL ChooseConnectoidDlgInit(HWND hDlg);
|
|
BOOL ChooseConnectoidDlgOK(HWND hDlg,BOOL * pfRetCode);
|
|
VOID EnableConnectionCtrls(HWND hDlg,BOOL fEnable);
|
|
BOOL CenterWindow (HWND hwndChild, HWND hwndParent);
|
|
BOOL MakeNewConnectoid(HWND hDlg);
|
|
BOOL EditConnectoid(HWND hDlg);
|
|
BOOL FillConnectoidComboBox(HWND hwndCombo, BOOL fUpdateOnly);
|
|
VOID MinimizeRNAWindow(CHAR * pszConnectoidName);
|
|
BOOL StartAutodisconnectMonitoring(CHAR * pszConnectoidName);
|
|
BOOL PerformSecurityCheck(BOOL * pfNeedRestart);
|
|
BOOL CallInstallableDialHandler(HWND hwndParent,LPSTR pszEntryName,DWORD * pdwRet);
|
|
|
|
#pragma data_seg(DATA_SEG_READ_ONLY)
|
|
// registry strings
|
|
static const CHAR szRegPathRemoteAccess[] = REGSTR_PATH_REMOTEACCESS;
|
|
static const CHAR szRegPathRNAProfile[] = REGSTR_PATH_REMOTEACCESS "\\Profile";
|
|
static const CHAR szRegPathInternetSettings[] = REGSTR_PATH_INTERNET_SETTINGS;
|
|
static const CHAR szRegValInternetEntry[] = REGSTR_VAL_INTERNETPROFILE;
|
|
static const CHAR szRegValDefaultEntry[] = "Default";
|
|
static const CHAR szRegValAutodialDllName[] = REGSTR_VAL_AUTODIALDLLNAME;
|
|
static const CHAR szRegValAutodialFcnName[] = REGSTR_VAL_AUTODIALFCNNAME;
|
|
static const CHAR szRegPathRNAService[] = REGSTR_PATH_SERVICES "\\RemoteAccess";
|
|
static const CHAR szRegPathTCP[] = REGSTR_PATH_VXD "\\MSTCP";
|
|
static const CHAR szRegValRemoteConnection[] = "Remote Connection";
|
|
static const CHAR szRegValHostName[] = "HostName";
|
|
static const CHAR szRnaEnumDevices[] = "RnaEnumDevices";
|
|
static const CHAR szRnaEnumConnEntries[] = "RnaEnumConnEntries";
|
|
static const CHAR szRnaImplicitDial[] = "RnaImplicitDial";
|
|
static const CHAR szRnaActivateEngine[] = "RnaActivateEngine";
|
|
static const CHAR szRnaDeactivateEngine[] = "RnaDeactivateEngine";
|
|
static const CHAR szRasCreatePhonebookEntry[] = "RasCreatePhonebookEntryA";
|
|
static const CHAR szRasEditPhonebookEntry[] = "RasEditPhonebookEntryA";
|
|
static const CHAR szInetPerformSecurityCheck[] = "InetPerformSecurityCheck";
|
|
static const CHAR szRnaAppWindowClass[] = "#32770"; // hard coded dialog class name
|
|
static const CHAR szRegValEnableAutodial[] = REGSTR_VAL_ENABLEAUTODIAL;
|
|
static const CHAR szRegValEnableAutoDisconnect[] = REGSTR_VAL_ENABLEAUTODISCONNECT;
|
|
static const CHAR szRegValEnableSecurityCheck[] = REGSTR_VAL_ENABLESECURITYCHECK;
|
|
static const CHAR szAutodialMonitorClass[] = AUTODIAL_MONITOR_CLASS_NAME;
|
|
static const CHAR szRegPathComputerName[] = REGSTR_PATH_COMPUTRNAME;
|
|
static const CHAR szRegValComputerName[] = REGSTR_VAL_COMPUTRNAME;
|
|
#pragma data_seg()
|
|
|
|
#pragma data_seg(DATA_SEG_PER_INSTANCE)
|
|
RNAENUMDEVICES lpRnaEnumDevices = NULL;
|
|
RNAIMPLICITDIAL lpRnaImplicitDial = NULL;
|
|
RNAACTIVATEENGINE lpRnaActivateEngine = NULL;
|
|
RNADEACTIVATEENGINE lpRnaDeactivateEngine = NULL;
|
|
RNAENUMCONNENTRIES lpRnaEnumConnEntries = NULL;
|
|
RASCREATEPHONEBOOKENTRY lpRasCreatePhonebookEntry = NULL;
|
|
RASEDITPHONEBOOKENTRY lpRasEditPhonebookEntry = NULL;
|
|
|
|
|
|
#define NUM_RNAAPI_PROCS 7
|
|
APIFCN RnaApiList[NUM_RNAAPI_PROCS] = {
|
|
{ (PVOID *) &lpRnaEnumDevices,szRnaEnumDevices},
|
|
{ (PVOID *) &lpRnaImplicitDial,szRnaImplicitDial},
|
|
{ (PVOID *) &lpRnaActivateEngine,szRnaActivateEngine},
|
|
{ (PVOID *) &lpRnaDeactivateEngine,szRnaDeactivateEngine},
|
|
{ (PVOID *) &lpRnaEnumConnEntries,szRnaEnumConnEntries},
|
|
{ (PVOID *) &lpRasCreatePhonebookEntry,szRasCreatePhonebookEntry},
|
|
{ (PVOID *) &lpRasEditPhonebookEntry,szRasEditPhonebookEntry}
|
|
};
|
|
|
|
HKEY hKeyRNA = NULL;
|
|
HINSTANCE hInstRNADll=NULL;
|
|
DWORD dwRNARefCount = 0;
|
|
|
|
#pragma data_seg()
|
|
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
|
|
|
|
// don't check RNA state more than once every 3 seconds
|
|
#define MIN_RNA_BUSY_CHECK_INTERVAL 3000
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: AutodialHookCallback
|
|
|
|
SYNOPSIS: This function is called by the Winsock DLL when one of
|
|
a number of Winsock APIs is called. This function will
|
|
offer to establish an RNA connection to the Internet
|
|
if a connection isn't already made.
|
|
|
|
ENTRY: dwOpCode - an ordinal indicating which Winsock API was
|
|
called
|
|
lpParam - API-specific data
|
|
|
|
NOTES: This function is called FREQUENTLY, by common Winsock
|
|
APIs such as gethostbyname(), connect() and sendto(). This
|
|
function needs to return *very quickly* (except when actually
|
|
dialing) to avoid degrading Winsock app performance.
|
|
|
|
********************************************************************/
|
|
VOID AutodialHookCallback(DWORD dwOpCode,LPCVOID lpParam)
|
|
{
|
|
// return as soon as possible if we know there's nothing for us to do here...
|
|
|
|
// check the fDontProcessHook flag so we return immediately if autodialing
|
|
// is disabled, the user has already said 'no' to autodialing, or the like.
|
|
// Also, if we couldn't open RNA services key (hKeyRNA is NULL) then
|
|
// most likely RNA is not installed, and we have no way of (easily) finding
|
|
// out if RNA is busy, so drop out.
|
|
if (fDontProcessHook || !hKeyRNA)
|
|
return;
|
|
|
|
// 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 = GetTickCount();
|
|
DWORD dwElapsed = dwNewTickCount - dwLastTickCount;
|
|
if (dwElapsed < MIN_RNA_BUSY_CHECK_INTERVAL) {
|
|
fProcessedRecently = TRUE;
|
|
} else {
|
|
dwLastTickCount = GetTickCount();
|
|
}
|
|
|
|
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) {
|
|
SendMessage(hwndMonitorApp,WM_WINSOCK_ACTIVITY,0,0);
|
|
}
|
|
}
|
|
|
|
switch (dwOpCode) {
|
|
|
|
case AUTODIAL_LISTEN:
|
|
case AUTODIAL_SENDTO:
|
|
// don't respond to listen() or sendto()
|
|
return;
|
|
break;
|
|
|
|
case AUTODIAL_CONNECT:
|
|
case AUTODIAL_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.
|
|
ASSERT(lpParam);
|
|
if (lpParam) {
|
|
if ((((struct sockaddr *) lpParam)->sa_family) !=
|
|
AF_INET) {
|
|
// not TCP, don't respond
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AUTODIAL_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) {
|
|
BOOL fDontProcess=FALSE; // assume we will process this
|
|
// allocate memory to hold hostname
|
|
CHAR * pszLocalHostname = new (CHAR[MAX_LOCAL_HOST+1]);
|
|
ASSERT(pszLocalHostname);
|
|
if (pszLocalHostname) {
|
|
DWORD dwSize = MAX_LOCAL_HOST+1;
|
|
DWORD dwValType;
|
|
|
|
if (GetRegKeyValue(HKEY_LOCAL_MACHINE,szRegPathTCP,
|
|
szRegValHostName,&dwValType,(BYTE *) pszLocalHostname,&dwSize) ==
|
|
ERROR_SUCCESS) {
|
|
if (!lstrcmpi(pszLocalHostname,(LPSTR) lpParam))
|
|
fDontProcess = TRUE;
|
|
}
|
|
|
|
// also against check computer name in registry, RPC
|
|
// will use this if there's no DNS hostname set
|
|
if (!fDontProcess && GetRegKeyValue(HKEY_LOCAL_MACHINE,
|
|
szRegPathComputerName,
|
|
szRegValComputerName,&dwValType,(BYTE *) pszLocalHostname,&dwSize) ==
|
|
ERROR_SUCCESS) {
|
|
if (!lstrcmpi(pszLocalHostname,(LPSTR) lpParam))
|
|
fDontProcess = TRUE;
|
|
}
|
|
|
|
|
|
delete pszLocalHostname;
|
|
}
|
|
|
|
if (fDontProcess)
|
|
return;
|
|
}
|
|
|
|
default:
|
|
// proceed...
|
|
break;
|
|
}
|
|
|
|
// check to see if RNA connection is in use. We check a registry value
|
|
// which RNA dynamically updates because that is the cheapest way to
|
|
// find out if RNA is using the modem. (Alternatives include: CreateFile
|
|
// on the modem, polling RasEnumConnections, launching a separate process
|
|
// to be a TAPI app. All pretty ugly.) As a further optimization, since
|
|
// this hook can potentially get called a number of times in rapid succession,
|
|
// check the registry no more than once every MIN_RNA_BUSY_CHECK_INTERVAL
|
|
// milliseconds. (A little measurement determined that checking the tick
|
|
// count is at least 50x faster than reading the registry value, so the
|
|
// optimization is worthwhile.) Note that we need to check the RNA state
|
|
// periodically, even if we know we dialed, because the user can shut down
|
|
// the RNA connection without us knowing.
|
|
|
|
|
|
if (fModemInUse && fProcessedRecently) {
|
|
// we've checked too recently, just bag out
|
|
return;
|
|
}
|
|
|
|
// call InetEnsureConnected to do last checks and do autodialing. If this
|
|
// returns FALSE, then user has declined dialing, so set fDontProcessHook
|
|
// so we don't do this again.
|
|
if (!InetEnsureConnected(NULL,0))
|
|
fDontProcessHook = TRUE;
|
|
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: InetEnsureConnected
|
|
|
|
SYNOPSIS: Dials to the Internet if not already connected
|
|
|
|
ENTRY: hwndParent - parent window
|
|
dwFlags - reserved for future use. This parameter must be
|
|
zero.
|
|
|
|
EXIT: returns TRUE if a connection is made, or a connection already
|
|
exists, or autodialing is not enabled. Returns FALSE if a
|
|
connection was not made or the user cancelled.
|
|
|
|
NOTES: If a LAN is present and user has set preference to use LAN,
|
|
then no dialing is done.
|
|
|
|
Note that this API does not guarantee or verify that the Internet
|
|
is on the other end of the connection -- it merely assures that
|
|
an RNA or LAN connection is present.
|
|
|
|
This function may be exposed to ISVs.
|
|
|
|
********************************************************************/
|
|
BOOL WINAPI InetEnsureConnected(HWND hwndParent,DWORD dwFlags)
|
|
{
|
|
// dwFlags must be zero. Enforce it to keep ISVs honest so we can
|
|
// use this parameter later if we want.
|
|
ASSERT(!dwFlags);
|
|
if (dwFlags)
|
|
return FALSE;
|
|
|
|
HKEY hKey;
|
|
BOOL fAutodialEnabled=FALSE,fAutoDisconnectEnabled=FALSE;
|
|
BOOL fSecurityCheckEnabled=FALSE;
|
|
|
|
// read registry setting for enabling autodialing
|
|
if (RegOpenKey(HKEY_CURRENT_USER,szRegPathInternetSettings,&hKey) == ERROR_SUCCESS) {
|
|
DWORD dwData,dwSize;
|
|
|
|
dwSize = sizeof(dwData);
|
|
if (RegQueryValueEx(hKey,szRegValEnableAutodial,NULL,NULL,
|
|
(LPBYTE) &dwData,&dwSize) == ERROR_SUCCESS && dwData) {
|
|
fAutodialEnabled = TRUE;
|
|
}
|
|
|
|
if (fAutodialEnabled) {
|
|
// while we're here, let's find out if autodisconnect and
|
|
// dial-time security check are enabled
|
|
dwSize = sizeof(dwData);
|
|
if (RegQueryValueEx(hKey,szRegValEnableAutoDisconnect,NULL,NULL,
|
|
(LPBYTE) &dwData,&dwSize) == ERROR_SUCCESS && dwData) {
|
|
fAutoDisconnectEnabled = TRUE;
|
|
}
|
|
|
|
dwSize = sizeof(dwData);
|
|
if (RegQueryValueEx(hKey,szRegValEnableSecurityCheck,NULL,NULL,
|
|
(LPBYTE) &dwData,&dwSize) == ERROR_SUCCESS && dwData) {
|
|
fSecurityCheckEnabled = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// no RNA connection. If autodialing is not turned on then there's nothing
|
|
// we can do, return FALSE
|
|
if (!fAutodialEnabled) {
|
|
fDontProcessHook = TRUE; // don't process winsock hook
|
|
return TRUE;
|
|
}
|
|
|
|
// check the registry to determine RNA state
|
|
DWORD dwVal=0,dwSize=sizeof(dwVal);
|
|
if ((RegQueryValueEx(hKeyRNA,szRegValRemoteConnection,NULL,NULL,
|
|
(LPBYTE) &dwVal,&dwSize) == ERROR_SUCCESS) && dwVal) {
|
|
|
|
// RNA connection is already established
|
|
fModemInUse = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
// autodialing enabled, try to dial...
|
|
|
|
fModemInUse = FALSE;
|
|
|
|
// load RNA for RnaImplicitDial, and make sure modem is present.
|
|
if (!LoadRNADll()) {
|
|
// loading RNA dll failed (most likely means RNA not installed)
|
|
fDontProcessHook = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
if (!IsModemPresent()) {
|
|
// modem not present.
|
|
// Don't try it any more, and set fDontProcessHook flag so we return
|
|
// very quickly on subsequent calls
|
|
fDontProcessHook = TRUE;
|
|
UnloadRNADll();
|
|
return FALSE;
|
|
}
|
|
|
|
// perform dial-time security check if enabled
|
|
if (fSecurityCheckEnabled) {
|
|
BOOL fNeedRestart=FALSE;
|
|
if (PerformSecurityCheck(&fNeedRestart)) {
|
|
// offer to restart machine if appropriate
|
|
if (fNeedRestart) {
|
|
RestartDialog(NULL,NULL,EW_RESTARTWINDOWS);
|
|
UnloadRNADll();
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// get the name of the internet RNA entry from the registry
|
|
CHAR szEntryName[RAS_MaxEntryName + 1]="";
|
|
BOOL fHaveEntryName=FALSE;
|
|
dwSize = sizeof(szEntryName);
|
|
if (RegOpenKey(HKEY_CURRENT_USER,szRegPathRemoteAccess,&hKey) == ERROR_SUCCESS) {
|
|
if ((RegQueryValueEx(hKey,szRegValInternetEntry,NULL,NULL,
|
|
(LPBYTE) szEntryName,&dwSize) == ERROR_SUCCESS) && lstrlen(szEntryName)) {
|
|
fHaveEntryName = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// if autodial is turned on but no internet entry set, prompt user for name
|
|
if (!fHaveEntryName) {
|
|
if (!ChooseInternetConnectoid(hwndParent,szEntryName,sizeof(szEntryName))) {
|
|
|
|
// no internet entry established, so no way we can dial.
|
|
UnloadRNADll();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL fResult = FALSE;
|
|
BOOL fOtherDialerUsed = FALSE;
|
|
DWORD dwRet=ERROR_SUCCESS;
|
|
|
|
|
|
// if an autodial handler is installed for this connectoid, then call it
|
|
if (CallInstallableDialHandler(hwndParent,szEntryName,&dwRet)) {
|
|
fOtherDialerUsed = TRUE; // don't dial ourselves now
|
|
|
|
if (dwRet == ERROR_USER_DISCONNECTION) {
|
|
// remember that user cancelled
|
|
fUserCancelled = TRUE;
|
|
}
|
|
|
|
fResult = (dwRet == ERROR_SUCCESS);
|
|
}
|
|
|
|
// if there is not an autodial handler installed or it didn't want to
|
|
// process this call, then dial ourselves
|
|
|
|
// should have proc address now
|
|
ASSERT(lpRnaImplicitDial);
|
|
if (!fOtherDialerUsed && lpRnaImplicitDial != NULL) {
|
|
|
|
//call RnaImplicitDial, which will bring up a dialog box with a "connect"
|
|
//button. If the user chooses 'cancel', then we'll take that as a 'no'
|
|
//and won't ask again.
|
|
dwRet = (lpRnaImplicitDial)(hwndParent,szEntryName);
|
|
|
|
// if we couldn't find the connectoid specified for the internet
|
|
// (most likely, the connectoid has been deleted), prompt the user
|
|
// to choose or create another
|
|
if (dwRet == ERROR_CANNOT_FIND_PHONEBOOK_ENTRY) {
|
|
if (ChooseInternetConnectoid(hwndParent,szEntryName,sizeof(szEntryName))) {
|
|
// try dialing again
|
|
dwRet = (lpRnaImplicitDial)(hwndParent,szEntryName);
|
|
}
|
|
}
|
|
|
|
if (dwRet == ERROR_SUCCESS) {
|
|
|
|
fResult = TRUE;
|
|
|
|
// try to find the RNAAPP window and minimize the sucker
|
|
MinimizeRNAWindow(szEntryName);
|
|
|
|
// start autodisconnect monitoring, if appropriate
|
|
if (fAutoDisconnectEnabled) {
|
|
StartAutodisconnectMonitoring(szEntryName);
|
|
}
|
|
} else if (dwRet == ERROR_USER_DISCONNECTION) {
|
|
|
|
// remember that user cancelled
|
|
fUserCancelled = TRUE;
|
|
}
|
|
}
|
|
|
|
// done with RNA dll, we can unload it
|
|
UnloadRNADll();
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: InetIsOffline
|
|
|
|
SYNOPSIS: Determines if user wants to be "offline" (get all information
|
|
from cache)
|
|
|
|
ENTRY: dwFlags - reserved for future use. This parameter must be
|
|
zero.
|
|
|
|
EXIT: returns TRUE if app should be offline, FALSE if app should
|
|
be online (continue to hit the wire)
|
|
|
|
NOTES: Offline mode begins if the user is prompted to dial, and
|
|
cancels.
|
|
|
|
********************************************************************/
|
|
INTSHCUTAPI BOOL WINAPI InetIsOffline(DWORD dwFlags)
|
|
{
|
|
BOOL fRet = FALSE; // assume not offline
|
|
|
|
// dwFlags must be zero. Enforce it to keep ISVs honest so we can
|
|
// use this parameter later if we want.
|
|
ASSERT(!dwFlags);
|
|
if (dwFlags)
|
|
return FALSE;
|
|
|
|
// we are offline if user was prompted to dial and cancelled,
|
|
// and there are no current RNA connections
|
|
|
|
if (fUserCancelled) {
|
|
|
|
// check the registry to determine RNA state.
|
|
DWORD dwVal=0,dwSize=sizeof(dwVal);
|
|
if (hKeyRNA && (RegQueryValueEx(hKeyRNA,szRegValRemoteConnection,NULL,
|
|
NULL,(LPBYTE) &dwVal,&dwSize) == ERROR_SUCCESS) && dwVal) {
|
|
|
|
fRet = FALSE; // RNA connection is active, not offline
|
|
|
|
} else {
|
|
|
|
fRet = TRUE; // no RNA connection, we're offline
|
|
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: CallInstallableDialHander
|
|
|
|
SYNOPSIS: Checks the registry to see if a dial handler is installed
|
|
for the specified RNA entry (connectoid). If so, loads the
|
|
dll and calls the function.
|
|
|
|
ENTRY: hwndParent - parent window
|
|
pszEntryName - name of RNA entry
|
|
pdwRet - pointer to DWORD filled in at exit with RNA error
|
|
code. This return code only valid if function returns
|
|
TRUE.
|
|
|
|
EXIT: returns TRUE if the dll is registered, we called its function
|
|
and the dll processed the dialing. Returns FALSE if a
|
|
dll was not registered or did not want to process the dialing.
|
|
|
|
NOTES: Note that a TRUE return value does not necessarily mean that
|
|
we are connected; for instance, the dialer could have dialed
|
|
but the number might have been busy. Caller meeds to check
|
|
code pdwRet to determine if connection succeeded.
|
|
|
|
********************************************************************/
|
|
BOOL CallInstallableDialHandler(HWND hwndParent,LPSTR pszEntryName,DWORD *
|
|
pdwRet)
|
|
{
|
|
ASSERT(pszEntryName);
|
|
ASSERT(pdwRet);
|
|
|
|
*pdwRet = ERROR_SUCCESS;
|
|
BOOL fRet = FALSE;
|
|
|
|
// look in registry for this RNA entry and see if an autodial handler is
|
|
// installed for this entry.
|
|
HKEY hkeyProfile;
|
|
if (RegOpenKey(HKEY_CURRENT_USER,szRegPathRNAProfile,&hkeyProfile) ==
|
|
ERROR_SUCCESS) {
|
|
HKEY hkeyEntry;
|
|
if (RegOpenKey(hkeyProfile,pszEntryName,&hkeyEntry) == ERROR_SUCCESS) {
|
|
CHAR szDllName[MAX_PATH+1]="";
|
|
CHAR szFcnName[MAX_AUTODIAL_FCNNAME+1]="";
|
|
DWORD cbDllName=sizeof(szDllName),cbFcnName=sizeof(szFcnName);
|
|
if ((RegQueryValueEx(hkeyEntry,szRegValAutodialDllName,NULL,NULL,
|
|
(LPBYTE) szDllName,&cbDllName) == ERROR_SUCCESS) &&
|
|
(RegQueryValueEx(hkeyEntry,szRegValAutodialFcnName,NULL,NULL,
|
|
(LPBYTE) szFcnName,&cbFcnName) == ERROR_SUCCESS) &&
|
|
cbDllName && cbFcnName) {
|
|
|
|
// there is a dll and function name specified for this RNA
|
|
// entry. Try to load the dll and get the proc address.
|
|
|
|
HINSTANCE hinstDialerDll = LoadLibrary(szDllName);
|
|
if (hinstDialerDll) {
|
|
INETDIALHANDLER lpInetDialHandler;
|
|
|
|
lpInetDialHandler=(INETDIALHANDLER)
|
|
GetProcAddress(hinstDialerDll,szFcnName);
|
|
|
|
if (lpInetDialHandler) {
|
|
fRet = (lpInetDialHandler)(hwndParent,
|
|
pszEntryName,0,pdwRet);
|
|
}
|
|
|
|
FreeLibrary(hinstDialerDll);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyEntry);
|
|
}
|
|
|
|
RegCloseKey(hkeyProfile);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: InitAutodialModule
|
|
|
|
SYNOPSIS: Called when the DLL is loaded by a process.
|
|
|
|
NOTES: Checks the registry to see if autodialing is enabled.
|
|
If so, opens a handle to the RNA services registry key
|
|
and keeps it around for use by the hook proc.
|
|
|
|
********************************************************************/
|
|
BOOL InitAutodialModule(void)
|
|
{
|
|
// open the Internet Settings key in registry and examine settings
|
|
HKEY hKeyTmp;
|
|
BOOL fAutodialEnabled=FALSE;
|
|
UINT uErr = RegCreateKey(HKEY_CURRENT_USER,szRegPathInternetSettings,&hKeyTmp);
|
|
if (uErr == ERROR_SUCCESS) {
|
|
DWORD dwVal,dwSize;
|
|
|
|
// is autodial enabled?
|
|
dwSize = sizeof(dwVal);
|
|
if (RegQueryValueEx(hKeyTmp,szRegValEnableAutodial,NULL,NULL,(LPBYTE)
|
|
&dwVal,&dwSize) == ERROR_SUCCESS) {
|
|
|
|
// autodial is enabled, but need to check the following: if LAN
|
|
// is present and user has indicated she wants to use LAN if present,
|
|
// then don't autodial.
|
|
|
|
fAutodialEnabled = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hKeyTmp);
|
|
}
|
|
|
|
if (fAutodialEnabled) {
|
|
// open a registry key to the RNA service key and keep it around
|
|
uErr=RegCreateKey(HKEY_LOCAL_MACHINE,szRegPathRNAService,&hKeyRNA);
|
|
ASSERT(uErr == ERROR_SUCCESS);
|
|
} else {
|
|
// if autodial not enabled, then set the fDontProcessHook flag so we
|
|
// exit our hook proc very quickly and don't interfere with Winsock
|
|
if (!fAutodialEnabled)
|
|
fDontProcessHook = TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ExitAutodialModule
|
|
|
|
SYNOPSIS: Called when the DLL is freed by a process.
|
|
|
|
********************************************************************/
|
|
void ExitAutodialModule(void)
|
|
{
|
|
// close RNA service registry key
|
|
if (hKeyRNA) {
|
|
RegCloseKey(hKeyRNA);
|
|
hKeyRNA = NULL;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: LoadRNADll
|
|
|
|
SYNOPSIS: Loads RNA dll if not already loaded and obtains pointers
|
|
for function addresses.
|
|
|
|
NOTES: Maintains a reference count so we know when to unload
|
|
|
|
********************************************************************/
|
|
BOOL LoadRNADll(VOID)
|
|
{
|
|
// increase reference count
|
|
dwRNARefCount++;
|
|
|
|
if (hInstRNADll) {
|
|
// already loaded, nothing to do
|
|
return TRUE;
|
|
}
|
|
|
|
// get the file name from resource
|
|
CHAR szDllFilename[SMALLBUFLEN+1];
|
|
if (!LoadString(GetThisModulesHandle(),IDS_RNADLL_FILENAME,
|
|
szDllFilename,sizeof(szDllFilename)))
|
|
return FALSE;
|
|
|
|
// load the DLL
|
|
hInstRNADll = LoadLibrary(szDllFilename);
|
|
if (!hInstRNADll)
|
|
return FALSE;
|
|
|
|
// cycle through the API table and get proc addresses for all the APIs we
|
|
// need
|
|
UINT nIndex;
|
|
for (nIndex = 0;nIndex < NUM_RNAAPI_PROCS;nIndex++) {
|
|
if (!(*RnaApiList[nIndex].ppFcnPtr = (PVOID) GetProcAddress(hInstRNADll,
|
|
RnaApiList[nIndex].pszName))) {
|
|
TRACE_OUT(("Unable to get address of function %s",
|
|
RnaApiList[nIndex].pszName));
|
|
|
|
UnloadRNADll();
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: UnloadRNADll
|
|
|
|
SYNOPSIS: Decrements RNA dll reference count and unloads it if
|
|
zero
|
|
|
|
********************************************************************/
|
|
VOID UnloadRNADll(VOID)
|
|
{
|
|
// decrease reference count
|
|
if (dwRNARefCount)
|
|
dwRNARefCount --;
|
|
|
|
// unload DLL if reference count hits zero
|
|
if (!dwRNARefCount && hInstRNADll) {
|
|
|
|
// set function pointers to NULL
|
|
UINT nIndex;
|
|
for (nIndex = 0;nIndex < NUM_RNAAPI_PROCS;nIndex++)
|
|
*RnaApiList[nIndex].ppFcnPtr = NULL;
|
|
|
|
// free the library
|
|
FreeLibrary(hInstRNADll);
|
|
hInstRNADll = NULL;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: IsModemPresent
|
|
|
|
SYNOPSIS: Determines if a modem is present
|
|
|
|
EXIT: returns TRUE if one or more modems is present
|
|
|
|
NOTES: Side effect: RNA dll is loaded.
|
|
RNA files must be installed, otherwise this function
|
|
will always return FALSE.
|
|
|
|
********************************************************************/
|
|
BOOL IsModemPresent(VOID)
|
|
{
|
|
// load RNA dll if not already loaded
|
|
if (!LoadRNADll()) {
|
|
return FALSE;
|
|
}
|
|
|
|
ASSERT(lpRnaEnumDevices); // should have proc addresses now
|
|
ASSERT(lpRnaActivateEngine);
|
|
ASSERT(lpRnaDeactivateEngine);
|
|
if (!lpRnaEnumDevices || !lpRnaActivateEngine || !lpRnaDeactivateEngine)
|
|
return FALSE;
|
|
|
|
// activate RNA engine
|
|
DWORD dwRet = (lpRnaActivateEngine)();
|
|
ASSERT(dwRet == ERROR_SUCCESS);
|
|
if (dwRet != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
// call RnaEnumDevices with NULL buffer to get the number of devices
|
|
DWORD cbSize=0,nEntries=0;
|
|
dwRet = (lpRnaEnumDevices)(NULL,&cbSize,&nEntries);
|
|
ASSERT(dwRet == ERROR_BUFFER_TOO_SMALL);
|
|
|
|
// deactivate the RNA engine
|
|
dwRet = (lpRnaDeactivateEngine)();
|
|
ASSERT(dwRet == ERROR_SUCCESS);
|
|
|
|
// return TRUE if one more more modems present
|
|
return (nEntries > 0);
|
|
}
|
|
|
|
HWND hwndFound = NULL;
|
|
|
|
BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lparam)
|
|
{
|
|
char szTemp[SMALLBUFLEN+2];
|
|
PSTR pszTitle;
|
|
UINT uLen1, uLen2;
|
|
|
|
if(!IsWindowVisible(hwnd))
|
|
return TRUE;
|
|
if(GetClassName(hwnd, szTemp, SMALLBUFLEN)==0)
|
|
return TRUE; // continue enumerating
|
|
if(strcmp(szTemp, szRnaAppWindowClass)!=0)
|
|
return TRUE;
|
|
if(GetWindowText(hwnd, szTemp, SMALLBUFLEN)==0)
|
|
return TRUE;
|
|
szTemp[SMALLBUFLEN] = 0;
|
|
uLen1 = lstrlen(szTemp);
|
|
if (uLen1 > 5)
|
|
uLen1 -= 5; // skip last 5 chars of title (avoid "...")
|
|
pszTitle = (PSTR)lparam;
|
|
ASSERT(pszTitle);
|
|
uLen2 = lstrlen(pszTitle);
|
|
TRACE_OUT(("Title=(%s), len=%d, Window=(%s), len=%d\r\n", pszTitle, uLen2, szTemp, uLen1));
|
|
if(uLen2 < uLen1)
|
|
return TRUE;
|
|
if(_memicmp(pszTitle, szTemp, uLen1)!=0)
|
|
return TRUE;
|
|
hwndFound = hwnd;
|
|
return FALSE;
|
|
}
|
|
|
|
HWND MyFindRNAWindow(PSTR pszTitle)
|
|
{
|
|
DWORD dwRet;
|
|
hwndFound = NULL;
|
|
dwRet = EnumWindows((WNDENUMPROC)(&MyEnumWindowsProc), (LPARAM)pszTitle);
|
|
TRACE_OUT(("EnumWindows returned %d\r\n", dwRet));
|
|
return hwndFound;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: WaitAndMinimizeRNAWindow
|
|
|
|
SYNOPSIS: Finds and minimizes the annoying RNA window
|
|
|
|
ENTRY: pTitle - title of window to look for
|
|
|
|
NOTES: This runs on its own thread.
|
|
This function must free the memory pointed to by pTitle.
|
|
|
|
********************************************************************/
|
|
DWORD WINAPI WaitAndMinimizeRNAWindow(PVOID pTitle)
|
|
{
|
|
// starts as a separate thread
|
|
HWND hwndRNAApp;
|
|
|
|
ASSERT(pTitle);
|
|
|
|
hwndRNAApp=MyFindRNAWindow((PSTR)pTitle);
|
|
|
|
TRACE_OUT(("FindWindow (%s)(%s) returned %d\r\n", szRnaAppWindowClass, pTitle, hwndRNAApp));
|
|
|
|
if(hwndRNAApp)
|
|
{
|
|
// minimize the RNA window
|
|
ShowWindow(hwndRNAApp,SW_MINIMIZE);
|
|
}
|
|
|
|
LocalFree(pTitle);
|
|
// exit function and thread
|
|
return (DWORD)hwndRNAApp;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: MinimizeRNAWindow
|
|
|
|
SYNOPSIS: Finds and minimizes the annoying RNA window
|
|
|
|
ENTRY: pszConnectoidName - name of connectoid launched
|
|
|
|
********************************************************************/
|
|
VOID MinimizeRNAWindow(CHAR * pszConnectoidName)
|
|
{
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
|
|
Assert(pszConnectoidName);
|
|
|
|
// alloc strings for title and format
|
|
CHAR * pFmt = (CHAR*)LocalAlloc(LPTR, (SMALLBUFLEN+1));
|
|
CHAR * pTitle = (CHAR*)LocalAlloc(LPTR, (RAS_MaxEntryName + SMALLBUFLEN + 1));
|
|
if (!pFmt || !pTitle)
|
|
goto error;
|
|
|
|
// load the title format ("connected to <connectoid name>" from resource
|
|
LoadString(GetThisModulesHandle(), IDS_CONNECTED_TO, pFmt, SMALLBUFLEN);
|
|
// build the title
|
|
wsprintf(pTitle, pFmt, pszConnectoidName);
|
|
|
|
// start a thread to find RNA window. Since we have to enum windows,
|
|
// this could potentially take a while (in a really extreme case), ao
|
|
// spin a thread to do it and return to caller right away.
|
|
hThread = CreateThread(0, 0, &WaitAndMinimizeRNAWindow, pTitle, 0, &dwThreadId);
|
|
ASSERT(hThread!=INVALID_HANDLE_VALUE && dwThreadId);
|
|
// dont free pTitle. The child thread needs it!
|
|
LocalFree(pFmt);
|
|
// free the thread handle or the threads stack is leaked!
|
|
CloseHandle(hThread);
|
|
return;
|
|
|
|
error:
|
|
if(pFmt) LocalFree(pFmt);
|
|
if(pTitle) LocalFree(pTitle);
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: StartAutodisconnectMonitoring
|
|
|
|
SYNOPSIS: Launches autodisconnect monitoring app
|
|
|
|
ENTRY: pszConnectoidName - name of connectoid to monitor
|
|
|
|
NOTES: Assumes autodisconnect is enabled, calling routine
|
|
should check this. (If autodisconnect is not enabled,
|
|
app will just exit immediately, but it would be a shame
|
|
to waste cycles starting the process...)
|
|
|
|
********************************************************************/
|
|
BOOL StartAutodisconnectMonitoring(CHAR * pszConnectoidName)
|
|
{
|
|
// should have a valid, non-zero length connectoid name
|
|
ASSERT(pszConnectoidName);
|
|
ASSERT(*pszConnectoidName);
|
|
|
|
BOOL fSuccess=FALSE;
|
|
|
|
// the autodial monitor app may already be running. If it is,
|
|
// find the hidden window that it creates and send it a message
|
|
// to start monitoring this connectoid
|
|
HWND hwndMonitorApp = FindWindow(szAutodialMonitorClass,NULL);
|
|
if (hwndMonitorApp) {
|
|
SendMessage(hwndMonitorApp,WM_SET_CONNECTOID_NAME,0,
|
|
(LPARAM) pszConnectoidName);
|
|
fSuccess = TRUE;
|
|
} else {
|
|
// autodial monitor app is not running, launch it.
|
|
// pass connectoid name on command line
|
|
CHAR szDialmonFilename[SMALLBUFLEN+1]="";
|
|
CHAR szCommandLine[RAS_MaxEntryName+SMALLBUFLEN+1];
|
|
|
|
// load app filename out of resource
|
|
if (LoadString(GetThisModulesHandle(),IDS_DIALMON_FILENAME,
|
|
szDialmonFilename,sizeof(szDialmonFilename))) {
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO sti;
|
|
memset(&sti,0,sizeof(sti));
|
|
sti.cb = sizeof(STARTUPINFO);
|
|
|
|
// build the command line: "DIALMON.EXE <connectoid name>"
|
|
wsprintf(szCommandLine,"%s %s",szDialmonFilename,pszConnectoidName);
|
|
|
|
// launch disconnect monitoring app as a process
|
|
fSuccess = CreateProcess(NULL,szCommandLine,
|
|
NULL, NULL, FALSE, 0, NULL, NULL,&sti, &pi);
|
|
ASSERT(fSuccess);
|
|
|
|
if (fSuccess) {
|
|
CloseHandle(pi.hThread);
|
|
}
|
|
}
|
|
}
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: PerformSecurityCheck
|
|
|
|
SYNOPSIS: Checks to make sure win 95 file/print sharing is not
|
|
bound to TCP/IP used for the internet
|
|
|
|
ENTRY: pfNeedRestart - on exit, set to TRUE if restart is needed.
|
|
|
|
NOTES: If we warn user about file/print sharing and user tells us
|
|
to fix, then a reboot is necessary. Caller is responsible
|
|
for checking *pfNeedRestart on return and restarting system
|
|
if necessary.
|
|
|
|
This function is a wrapper that loads Internet wizard DLL,
|
|
calls function in it, and unloads it.
|
|
|
|
********************************************************************/
|
|
BOOL PerformSecurityCheck(BOOL * pfNeedRestart)
|
|
{
|
|
ASSERT(pfNeedRestart);
|
|
|
|
*pfNeedRestart = FALSE;
|
|
|
|
HINSTANCE hinstInetWiz;
|
|
INETPERFORMSECURITYCHECK lpInetPerformSecurityCheck;
|
|
CHAR szFilename[SMALLBUFLEN+1]="";
|
|
|
|
// get filename out of resource
|
|
LoadString(GetThisModulesHandle(),IDS_INETCFG_FILENAME,szFilename,
|
|
sizeof(szFilename));
|
|
|
|
// load the inetcfg dll
|
|
hinstInetWiz = LoadLibrary(szFilename);
|
|
ASSERT(hinstInetWiz);
|
|
if (hinstInetWiz) {
|
|
|
|
// get the proc address
|
|
lpInetPerformSecurityCheck = (INETPERFORMSECURITYCHECK)
|
|
GetProcAddress(hinstInetWiz,szInetPerformSecurityCheck);
|
|
ASSERT(lpInetPerformSecurityCheck);
|
|
if (lpInetPerformSecurityCheck) {
|
|
|
|
// call the function to do system security check
|
|
(lpInetPerformSecurityCheck) (NULL,pfNeedRestart);
|
|
|
|
}
|
|
|
|
FreeLibrary(hinstInetWiz);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ChooseInternetConnectoid
|
|
|
|
SYNOPSIS: Displays UI to select connectoid to be used to dial the
|
|
Internet
|
|
|
|
ENTRY: hwndOwner - parent window
|
|
pszConnectoidName - return buffer to receive name. Caller
|
|
can set this to NULL if not interested in name.
|
|
cbConnectoidName - size of pszConnectoidName buffer
|
|
|
|
NOTES: If a new connectoid is selected, the name is set in the
|
|
registry, and also returned to the caller if a pszConnectoidName
|
|
buffer is passed.
|
|
|
|
********************************************************************/
|
|
BOOL ChooseInternetConnectoid(HWND hwndOwner,LPSTR pszConnectoidName,
|
|
DWORD cbConnectoidName)
|
|
{
|
|
BOOL fRet;
|
|
|
|
// make sure RNA dll is loaded
|
|
if (!LoadRNADll())
|
|
return FALSE;
|
|
|
|
// launch the dialog box for user to choose connectoid
|
|
fRet=DialogBoxParam(GetThisModulesHandle(),MAKEINTRESOURCE(DLG_INTERNET_AUTODIAL),
|
|
hwndOwner,ChooseConnectoidDlgProc,(LPARAM) pszConnectoidName);
|
|
|
|
UnloadRNADll();
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ChooseConnectoidDlgProc
|
|
|
|
SYNOPSIS: Dialog proc for connectoid-choosing UI
|
|
|
|
********************************************************************/
|
|
BOOL CALLBACK ChooseConnectoidDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg) {
|
|
|
|
case WM_INITDIALOG:
|
|
// lParam contains optional pointer to return buffer, set it
|
|
// in our window data
|
|
SetWindowLong(hDlg,DWL_USER,lParam);
|
|
return ChooseConnectoidDlgInit(hDlg);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
{
|
|
BOOL fRetCode;
|
|
if (ChooseConnectoidDlgOK(hDlg,&fRetCode));
|
|
EndDialog(hDlg,fRetCode);
|
|
}
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hDlg,FALSE);
|
|
break;
|
|
|
|
case IDD_DISABLEAUTODIAL:
|
|
// enable/disable other dialog controls
|
|
// according to if 'don't use' checkbox is checked
|
|
EnableConnectionCtrls(hDlg,!IsDlgButtonChecked(hDlg,
|
|
IDD_DISABLEAUTODIAL));
|
|
break;
|
|
|
|
case IDD_CHOOSE_CONNECTION:
|
|
// enable OK button if there is a selection in combo box
|
|
EnableConnectionCtrls(hDlg,TRUE);
|
|
break;
|
|
|
|
case IDD_NEW:
|
|
MakeNewConnectoid(hDlg);
|
|
break;
|
|
|
|
case IDD_EDIT:
|
|
EditConnectoid(hDlg);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ChooseConnectoidDlgInit
|
|
|
|
SYNOPSIS: Called when dialog to choose Internet connectoid inits
|
|
|
|
NOTES: Populates combo box with list of existing connectoids
|
|
|
|
********************************************************************/
|
|
BOOL ChooseConnectoidDlgInit(HWND hDlg)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
|
|
// we should have proc addresses at this point
|
|
ASSERT(lpRnaActivateEngine);
|
|
ASSERT(lpRnaEnumConnEntries);
|
|
ASSERT(lpRnaDeactivateEngine);
|
|
|
|
if (!lpRnaActivateEngine || !lpRnaEnumConnEntries ||
|
|
!lpRnaDeactivateEngine)
|
|
return FALSE;
|
|
|
|
// center the dialog over the parent app or the desktop
|
|
HWND hParent = GetParent(hDlg);
|
|
CenterWindow(hDlg,hParent ? hParent : GetDesktopWindow());
|
|
|
|
HWND hwndCB = GetDlgItem(hDlg,IDD_CHOOSE_CONNECTION);
|
|
FillConnectoidComboBox(hwndCB,FALSE);
|
|
|
|
HKEY hKey;
|
|
// get default connectoid name, set it as default in combo box if possible
|
|
if (RegOpenKey(HKEY_CURRENT_USER,szRegPathRemoteAccess,&hKey)
|
|
== ERROR_SUCCESS) {
|
|
CHAR szEntryName[RAS_MaxEntryName + 1]="";
|
|
DWORD dwSize=sizeof(szEntryName);
|
|
if ((RegQueryValueEx(hKey,szRegValDefaultEntry,NULL,NULL,
|
|
(LPBYTE) szEntryName,&dwSize) == ERROR_SUCCESS) &&
|
|
lstrlen(szEntryName)) {
|
|
int iSel = ComboBox_FindString(hwndCB,0,szEntryName);
|
|
if (iSel >= 0)
|
|
ComboBox_SetCurSel(hwndCB,iSel);
|
|
}
|
|
}
|
|
|
|
// enable 'OK' and 'Edit' button depending on if there's a selection in combo box or not
|
|
EnableConnectionCtrls(hDlg,TRUE);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ChooseConnectoidDlgOK
|
|
|
|
SYNOPSIS: Called when OK is pressed on dialog to choose
|
|
Internet connectoid
|
|
|
|
********************************************************************/
|
|
BOOL ChooseConnectoidDlgOK(HWND hDlg,BOOL * pfRetCode)
|
|
{
|
|
ASSERT(pfRetCode);
|
|
|
|
HKEY hKey;
|
|
|
|
if (IsDlgButtonChecked(hDlg,IDD_DISABLEAUTODIAL)) {
|
|
// user wants to disable autodial, disable it in registry
|
|
|
|
if (RegCreateKey(HKEY_CURRENT_USER,szRegPathInternetSettings,&hKey)
|
|
== ERROR_SUCCESS) {
|
|
DWORD dwVal = 0;
|
|
RegSetValueEx(hKey,szRegValEnableAutodial,0,REG_BINARY,
|
|
(LPBYTE) &dwVal,sizeof(dwVal));
|
|
RegCloseKey(hKey);
|
|
}
|
|
*pfRetCode = FALSE; // return FALSE to caller
|
|
|
|
} else {
|
|
HWND hwndCB = GetDlgItem(hDlg,IDD_CHOOSE_CONNECTION);
|
|
|
|
// should have a selection if we get here
|
|
ASSERT(ComboBox_GetCurSel(hwndCB) >= 0 );
|
|
|
|
CHAR szEntryName[RAS_MaxEntryName+1];
|
|
if (ComboBox_GetText(hwndCB,szEntryName,sizeof(szEntryName))) {
|
|
|
|
if (RegCreateKey(HKEY_CURRENT_USER,szRegPathRemoteAccess,&hKey)
|
|
== ERROR_SUCCESS) {
|
|
RegSetValueEx(hKey,szRegValInternetEntry,0,REG_SZ,(LPBYTE) szEntryName,
|
|
lstrlen(szEntryName)+1);
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// get pointer to return buffer from our window data - this
|
|
// is optional, can be NULL if caller doesn't want data returned
|
|
LPSTR pszReturnBuf = (LPSTR) GetWindowLong(hDlg,DWL_USER);
|
|
if (pszReturnBuf) {
|
|
lstrcpy(pszReturnBuf,szEntryName);
|
|
}
|
|
|
|
*pfRetCode = TRUE; // return TRUE to caller
|
|
} else {
|
|
*pfRetCode = FALSE; // return FALSE to caller
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID EnableConnectionCtrls(HWND hDlg,BOOL fEnable)
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg,IDD_TX_CHOOSE_CONNECTION),fEnable);
|
|
EnableWindow(GetDlgItem(hDlg,IDD_CHOOSE_CONNECTION),fEnable);
|
|
EnableWindow(GetDlgItem(hDlg,IDD_NEW),fEnable);
|
|
|
|
BOOL fComboboxHasSelection = (ComboBox_GetCurSel(GetDlgItem(hDlg,
|
|
IDD_CHOOSE_CONNECTION)) >= 0);
|
|
|
|
// for edit button, only enable if there is a selection in connectoid
|
|
// combo box
|
|
BOOL fEnableEdit = fEnable && fComboboxHasSelection;
|
|
EnableWindow(GetDlgItem(hDlg,IDD_EDIT),fEnableEdit);
|
|
|
|
// for OK button, only enable if there is a selection in connectoid
|
|
// combo box or we are disabling other controls (e.g. "don't use
|
|
// autodial" is checked, in which case we need OK button to be enabled)
|
|
BOOL fEnableOK = (!fEnable) || fComboboxHasSelection;
|
|
EnableWindow(GetDlgItem(hDlg,IDOK),fEnableOK);
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: MakeNewConnectoid
|
|
|
|
SYNOPSIS: Launches RNA new connectoid wizard; selects newly
|
|
created connectoid (if any) in combo box
|
|
|
|
********************************************************************/
|
|
BOOL MakeNewConnectoid(HWND hDlg)
|
|
{
|
|
BOOL fRet=FALSE;
|
|
|
|
ASSERT(lpRasCreatePhonebookEntry);
|
|
|
|
// call RAS to launch connectoid wizard
|
|
if ((lpRasCreatePhonebookEntry)(hDlg,NULL) == ERROR_SUCCESS) {
|
|
HWND hwndCombo = GetDlgItem(hDlg,IDD_CHOOSE_CONNECTION);
|
|
ASSERT(hwndCombo);
|
|
|
|
FillConnectoidComboBox(hwndCombo,TRUE); // refresh combo box
|
|
|
|
fRet = TRUE;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: EditConnectoid
|
|
|
|
SYNOPSIS: Brings up RNA dialog for connectoid properties for
|
|
selected connectoid
|
|
|
|
********************************************************************/
|
|
BOOL EditConnectoid(HWND hDlg)
|
|
{
|
|
BOOL fRet=FALSE;
|
|
HWND hwndCombo = GetDlgItem(hDlg,IDD_CHOOSE_CONNECTION);
|
|
ASSERT(hwndCombo);
|
|
|
|
// shouldn't get here unless there is selection in combo box
|
|
ASSERT(ComboBox_GetCurSel(hwndCombo) >= 0);
|
|
|
|
CHAR szEntryName[RAS_MaxEntryName+1]="";
|
|
ComboBox_GetText(hwndCombo,szEntryName,sizeof(szEntryName));
|
|
|
|
if (lstrlen(szEntryName)) {
|
|
|
|
// call RAS to do connectoid editing (including UI)
|
|
ASSERT(lpRasEditPhonebookEntry);
|
|
if ((lpRasEditPhonebookEntry)(hDlg,NULL,szEntryName) == ERROR_SUCCESS) {
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: FillConnectoidComboBox
|
|
|
|
ENTRY: hwndCombo - handle of combo box
|
|
fUpdateOnly - if FALSE, then the combo box is filled with
|
|
all RNA connectoids. If TRUE, then only connectoids
|
|
that aren't already in the combo box are added,
|
|
and the selection is set to a new connectoid if there are
|
|
any. This parameter is set to TRUE when called immediately
|
|
after a new connectoid is created.
|
|
|
|
SYNOPSIS: Fills specified combo box with list of existing RNA
|
|
connectoids
|
|
|
|
********************************************************************/
|
|
#define DEF_ENTRY_BUF_SIZE 8192
|
|
BOOL FillConnectoidComboBox(HWND hwndCombo,BOOL fUpdateOnly)
|
|
{
|
|
ASSERT(hwndCombo);
|
|
BOOL fSuccess = FALSE;
|
|
|
|
if (!fUpdateOnly)
|
|
ComboBox_ResetContent(hwndCombo); // clear combo box
|
|
|
|
// activate RNA engine
|
|
DWORD dwRet = (lpRnaActivateEngine)();
|
|
ASSERT(dwRet == ERROR_SUCCESS);
|
|
if (dwRet != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
DWORD dwBufSize = DEF_ENTRY_BUF_SIZE;
|
|
DWORD dwEntries = 0;
|
|
LPSTR pBuf = (LPSTR) new (CHAR[dwBufSize]);
|
|
if (pBuf) {
|
|
dwRet = (lpRnaEnumConnEntries)(pBuf,dwBufSize,&dwEntries);
|
|
if (dwRet == ERROR_BUFFER_TOO_SMALL) {
|
|
// reallocate buffer if necessary
|
|
delete pBuf;
|
|
pBuf = NULL;
|
|
dwBufSize = dwEntries * (RAS_MaxEntryName+1);
|
|
pBuf = (LPSTR) new (CHAR[dwBufSize]);
|
|
if (pBuf) {
|
|
dwRet = (lpRnaEnumConnEntries)(pBuf,dwBufSize,&dwEntries);
|
|
}
|
|
}
|
|
|
|
if (dwRet == ERROR_SUCCESS && pBuf) {
|
|
fSuccess = TRUE;
|
|
|
|
// insert connectoid names from buffer into combo box
|
|
CHAR * pszConn = pBuf;
|
|
while (*pszConn && dwEntries) {
|
|
if (!fUpdateOnly) {
|
|
// we're refreshing content, add every connectoid in list
|
|
ComboBox_AddString(hwndCombo,pszConn);
|
|
} else {
|
|
// only add connectoids not already in combo box
|
|
if (ComboBox_FindStringExact(hwndCombo,0,pszConn) < 0) {
|
|
int iSel;
|
|
iSel = ComboBox_AddString(hwndCombo,pszConn);
|
|
ComboBox_SetCurSel(hwndCombo,iSel);
|
|
}
|
|
}
|
|
pszConn += lstrlen(pszConn) + 1;
|
|
dwEntries--;
|
|
}
|
|
}
|
|
|
|
if (pBuf)
|
|
delete pBuf;
|
|
}
|
|
|
|
// deactivate RNA engine
|
|
(lpRnaDeactivateEngine)();
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
FUNCTION: CenterWindow (HWND, HWND)
|
|
|
|
PURPOSE: Center one window over another
|
|
|
|
COMMENTS:
|
|
|
|
Dialog boxes take on the screen position that they were designed at,
|
|
which is not always appropriate. Centering the dialog over a particular
|
|
window usually results in a better position.
|
|
|
|
****************************************************************************/
|
|
BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
|
|
{
|
|
RECT rChild, rParent;
|
|
int wChild, hChild, wParent, hParent;
|
|
int wScreen, hScreen, xNew, yNew;
|
|
HDC hdc;
|
|
|
|
// Get the Height and Width of the child window
|
|
GetWindowRect (hwndChild, &rChild);
|
|
wChild = rChild.right - rChild.left;
|
|
hChild = rChild.bottom - rChild.top;
|
|
|
|
// Get the Height and Width of the parent window
|
|
GetWindowRect (hwndParent, &rParent);
|
|
wParent = rParent.right - rParent.left;
|
|
hParent = rParent.bottom - rParent.top;
|
|
|
|
// Get the display limits
|
|
hdc = GetDC (hwndChild);
|
|
wScreen = GetDeviceCaps (hdc, HORZRES);
|
|
hScreen = GetDeviceCaps (hdc, VERTRES);
|
|
ReleaseDC (hwndChild, hdc);
|
|
|
|
// Calculate new X position, then adjust for screen
|
|
xNew = rParent.left + ((wParent - wChild) /2);
|
|
if (xNew < 0) {
|
|
xNew = 0;
|
|
} else if ((xNew+wChild) > wScreen) {
|
|
xNew = wScreen - wChild;
|
|
}
|
|
|
|
// Calculate new Y position, then adjust for screen
|
|
yNew = rParent.top + ((hParent - hChild) /2);
|
|
if (yNew < 0) {
|
|
yNew = 0;
|
|
} else if ((yNew+hChild) > hScreen) {
|
|
yNew = hScreen - hChild;
|
|
}
|
|
|
|
// Set it, and return
|
|
return SetWindowPos (hwndChild, NULL,
|
|
xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
|