///////////////////////////////////////////////////////////////////////
//                   Microsoft Windows                               //
//             Copyright(c) Microsoft Corp., 1995                    //
///////////////////////////////////////////////////////////////////////
//
// CONNECTN.C - "Connection" Property Sheet
//
// HISTORY:
//
// 6/22/96  t-gpease    moved to this file
//

#include "inetcplp.h"
#include <inetcpl.h>
#include <rasdlg.h>

#include <mluisupp.h>

HINSTANCE   hInstRNADll = NULL;
DWORD       dwRNARefCount = 0;
BOOL        g_fWin95 = TRUE;
BOOL        g_fMillennium = FALSE;
BOOL        g_fWin2K = FALSE;

static const TCHAR g_szSensPath[]            = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Webcheck");

// clsids used to jit in features
static const CLSID clsidFeatureICW = {      // {5A8D6EE0-3E18-11D0-821E-444553540000}
    0x5A8D6EE0, 0x3E18, 0x11D0, {0x82, 0x1E, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};

static const CLSID clsidFeatureMobile = {   // {3af36230-a269-11d1-b5bf-0000f8051515}
    0x3af36230, 0xa269, 0x11d1, {0xb5, 0xbf, 0x00, 0x00, 0xf8, 0x05, 0x15, 0x15}};

// RNA api function names
static const CHAR szRasEditPhonebookEntryA[]   = "RasEditPhonebookEntryA";
static const CHAR szRasEditPhonebookEntryW[]   = "RasEditPhonebookEntryW";
static const CHAR szRasEnumEntriesA[]          = "RasEnumEntriesA";
static const CHAR szRasEnumEntriesW[]          = "RasEnumEntriesW";
static const CHAR szRasDeleteEntryA[]          = "RasDeleteEntryA";
static const CHAR szRasDeleteEntryW[]          = "RasDeleteEntryW";
static const CHAR szRasGetEntryDialParamsA[]   = "RasGetEntryDialParamsA";
static const CHAR szRasGetEntryDialParamsW[]   = "RasGetEntryDialParamsW";
static const CHAR szRasSetEntryDialParamsA[]   = "RasSetEntryDialParamsA";
static const CHAR szRasSetEntryDialParamsW[]   = "RasSetEntryDialParamsW";
static const CHAR szRasCreatePhonebookEntryA[] = "RasCreatePhonebookEntryA";
static const CHAR szRasGetEntryPropertiesW[]   = "RasGetEntryPropertiesW";
static const CHAR szRnaActivateEngine[]        = "RnaActivateEngine";
static const CHAR szRnaDeactivateEngine[]      = "RnaDeactivateEngine";
static const CHAR szRnaDeleteEntry[]           = "RnaDeleteConnEntry";

RASEDITPHONEBOOKENTRYA   lpRasEditPhonebookEntryA   = NULL;
RASEDITPHONEBOOKENTRYW   lpRasEditPhonebookEntryW   = NULL;
RASENUMENTRIESA          lpRasEnumEntriesA          = NULL;
RASENUMENTRIESW          lpRasEnumEntriesW          = NULL;
RASDELETEENTRYA          lpRasDeleteEntryA          = NULL;
RASDELETEENTRYW          lpRasDeleteEntryW          = NULL;
RASGETENTRYDIALPARAMSA   lpRasGetEntryDialParamsA   = NULL;
RASGETENTRYDIALPARAMSW   lpRasGetEntryDialParamsW   = NULL;
RASSETENTRYDIALPARAMSA   lpRasSetEntryDialParamsA   = NULL;
RASSETENTRYDIALPARAMSW   lpRasSetEntryDialParamsW   = NULL;
RASCREATEPHONEBOOKENTRYA lpRasCreatePhonebookEntryA = NULL;
RASGETENTRYPROPERTIESW   lpRasGetEntryPropertiesW   = NULL;
RNAACTIVATEENGINE        lpRnaActivateEngine        = NULL;
RNADEACTIVATEENGINE      lpRnaDeactivateEngine      = NULL;
RNADELETEENTRY           lpRnaDeleteEntry           = NULL;

#define NUM_RNAAPI_PROCS        15
APIFCN RasApiList[NUM_RNAAPI_PROCS] = {
    { (PVOID *) &lpRasEditPhonebookEntryA,   szRasEditPhonebookEntryA},
    { (PVOID *) &lpRasEditPhonebookEntryW,   szRasEditPhonebookEntryW},
    { (PVOID *) &lpRasEnumEntriesA,          szRasEnumEntriesA},
    { (PVOID *) &lpRasEnumEntriesW,          szRasEnumEntriesW},
    { (PVOID *) &lpRasGetEntryDialParamsA,   szRasGetEntryDialParamsA},
    { (PVOID *) &lpRasGetEntryDialParamsW,   szRasGetEntryDialParamsW},
    { (PVOID *) &lpRasSetEntryDialParamsA,   szRasSetEntryDialParamsA},
    { (PVOID *) &lpRasSetEntryDialParamsW,   szRasSetEntryDialParamsW},
    { (PVOID *) &lpRasDeleteEntryA,          szRasDeleteEntryA},
    { (PVOID *) &lpRasDeleteEntryW,          szRasDeleteEntryW},
    { (PVOID *) &lpRasCreatePhonebookEntryA, szRasCreatePhonebookEntryA},
    { (PVOID *) &lpRasGetEntryPropertiesW,   szRasGetEntryPropertiesW},
    { (PVOID *) &lpRnaActivateEngine,        szRnaActivateEngine},
    { (PVOID *) &lpRnaDeactivateEngine,      szRnaDeactivateEngine},
    { (PVOID *) &lpRnaDeleteEntry,           szRnaDeleteEntry}
};


//
// Connection dialog needs info
//
typedef struct _conninfo {

    HTREEITEM   hDefault;
    TCHAR       szEntryName[RAS_MaxEntryName+1];

} CONNINFO, *PCONNINFO;

//
// dial dialog needs some info asssociated with its window
//
typedef struct _dialinfo {

    PROXYINFO   proxy;              // manual proxy info
    BOOL        fClickedAutodetect; // did the user actually click autodetect?
    LPTSTR      pszConnectoid;
#ifdef UNIX
    TCHAR       szEntryName[RAS_MaxEntryName+1];
#endif

} DIALINFO, *PDIALINFO;

//
// Private Functions
//

BOOL ConnectionDlgInit(HWND hDlg, PCONNINFO pConn);
BOOL ConnectionDlgOK(HWND hDlg, PCONNINFO pConn);
VOID EnableConnectionControls(HWND hDlg, PCONNINFO pConn, BOOL fSetText);
BOOL LoadRNADll(VOID);
VOID UnloadRNADll(VOID);
DWORD PopulateRasEntries(HWND hDlg, PCONNINFO pConn);
BOOL MakeNewConnectoid(HWND hDlg, PCONNINFO pConn);
BOOL EditConnectoid(HWND hDlg);
VOID FixAutodialSettings(HWND hDlg, PCONNINFO pConn);

INT_PTR CALLBACK DialupDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
INT_PTR CALLBACK AdvDialupDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
INT_PTR CALLBACK AdvAutocnfgDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);

// Handy stuff for looking at proxy exceptions (from proxysup.cpp)
BOOL RemoveLocalFromExceptionList(IN LPTSTR lpszExceptionList);

extern const TCHAR cszLocalString[];

// defines for tree view image list
#define BITMAP_WIDTH    16
#define BITMAP_HEIGHT   16
#define CONN_BITMAPS    2
#define IMAGE_LAN       0
#define IMAGE_MODEM     1

void GetConnKey(LPTSTR pszConn, LPTSTR pszBuffer, int iBuffLen)
{
    if(NULL == pszConn || 0 == *pszConn) {
        // use lan reg location
        StrCpyN(pszBuffer, REGSTR_PATH_INTERNET_LAN_SETTINGS, iBuffLen);
    } else {
        // use connectoid reg location
        wnsprintf(pszBuffer, iBuffLen, TEXT("%s\\Profile\\%s"), REGSTR_PATH_REMOTEACCESS, pszConn);
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// JitFeature - decide if a feature is present, not present but
//              jitable, or not present and not jitable.  Actually JIT it
//              in if requested
//
/////////////////////////////////////////////////////////////////////////////
#define JIT_PRESENT         0           // Installed
#define JIT_AVAILABLE       1           // Can be JIT'ed
#define JIT_NOT_AVAILABLE   2           // You're in trouble - can't be JIT'ed

DWORD JitFeature(HWND hwnd, REFCLSID clsidFeature, BOOL fCheckOnly)
{
    HRESULT     hr  = REGDB_E_CLASSNOTREG;
    uCLSSPEC    classpec;
    DWORD       dwFlags = 0;

    // figure out struct and flags
    classpec.tyspec = TYSPEC_CLSID;
    classpec.tagged_union.clsid = clsidFeature;

    if(fCheckOnly)
        dwFlags = FIEF_FLAG_PEEK;

    //
    // since we only come to install of JIT features
    // only via a UI code path in inetcpl, we want to
    // simply ignore any previous UI action
    //
    dwFlags |= FIEF_FLAG_FORCE_JITUI;
    // call jit code
    hr = FaultInIEFeature(hwnd, &classpec, NULL, dwFlags);

    if(S_OK == hr) {
        // feature present
        return JIT_PRESENT;
    }

    if(S_FALSE == hr || E_ACCESSDENIED == hr) {
        // jit doesn't know about this feature.  Assume it's present.
        return JIT_PRESENT;
    }

    if(HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) {
        // user didn't want it - may try again sometime, however
        return JIT_AVAILABLE;
    }

    if(fCheckOnly) {
        if(HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED) == hr) {
            // not present but can get it
            return JIT_AVAILABLE;
        }
    }

    //
    // Actually tried to get it but didn't - return not available
    //
    return JIT_NOT_AVAILABLE;
}


/////////////////////////////////////////////////////////////////////////////
//
// RasEnumHelp
//
// Abstract grusome details of getting a correct enumeration of entries 
// from RAS.  Works on all 9x and NT platforms correctly, maintaining unicode
// whenever possible.
//
/////////////////////////////////////////////////////////////////////////////

class RasEnumHelp
{
private:
    
    //
    // Win2k version of RASENTRYNAMEW struct
    //
    #define W2KRASENTRYNAMEW struct tagW2KRASENTRYNAMEW
    W2KRASENTRYNAMEW
    {
        DWORD dwSize;
        WCHAR szEntryName[ RAS_MaxEntryName + 1 ];
        DWORD dwFlags;
        WCHAR szPhonebookPath[MAX_PATH + 1];
    };
    #define LPW2KRASENTRYNAMEW W2KRASENTRYNAMEW*

    //
    // Possible ways we got info from RAS
    //
    typedef enum {
        ENUM_MULTIBYTE,             // Win9x
        ENUM_UNICODE,               // NT4
        ENUM_WIN2K                  // Win2K
    } ENUM_TYPE;

    //
    // How we got the info
    //
    ENUM_TYPE       _EnumType;     

    //
    // Any error we got during enumeration
    //
    DWORD           _dwLastError;

    //
    // Number of entries we got
    //
    DWORD           _dwEntries;

    //
    // Pointer to info retrieved from RAS
    //
    RASENTRYNAMEA * _preList;

    //
    // Last entry returned as multibyte or unicode when conversion required
    //
    WCHAR           _szCurrentEntryW[RAS_MaxEntryName + 1];


public:
    RasEnumHelp();
    ~RasEnumHelp();

    DWORD   GetError();
    DWORD   GetEntryCount();
    LPWSTR  GetEntryW(DWORD dwEntry);
};



RasEnumHelp::RasEnumHelp()
{
    DWORD           dwBufSize, dwStructSize;
    OSVERSIONINFO   ver;

    // init
    _dwEntries = 0;
    _dwLastError = 0;

    // figure out which kind of enumeration we're doing - start with multibyte
    _EnumType = ENUM_MULTIBYTE;
    dwStructSize = sizeof(RASENTRYNAMEA);

    ver.dwOSVersionInfoSize = sizeof(ver);
    if(GetVersionEx(&ver))
    {
        if(VER_PLATFORM_WIN32_NT == ver.dwPlatformId)
        {
            _EnumType = ENUM_UNICODE;
            dwStructSize = sizeof(RASENTRYNAMEW);

            if(ver.dwMajorVersion >= 5)
            {
                _EnumType = ENUM_WIN2K;
                dwStructSize = sizeof(W2KRASENTRYNAMEW);
            }
        }
    }

    // allocate space for 16 entries
    dwBufSize = 16 * dwStructSize;
    _preList = (LPRASENTRYNAMEA)GlobalAlloc(LMEM_FIXED, dwBufSize);
    if(_preList)
    {
        do
        {
            // set up list
            _preList[0].dwSize = dwStructSize;

            // call ras to enumerate
            _dwLastError = ERROR_UNKNOWN;
            if(ENUM_MULTIBYTE == _EnumType)
            {
                if(lpRasEnumEntriesA)
                {
                    _dwLastError = lpRasEnumEntriesA(
                                    NULL,
                                    NULL,
                                    (LPRASENTRYNAMEA)_preList,
                                    &dwBufSize,
                                    &_dwEntries
                                    );
                }
            }
            else
            {
                if(lpRasEnumEntriesW)
                {
                    _dwLastError = lpRasEnumEntriesW(
                                    NULL,
                                    NULL,
                                    (LPRASENTRYNAMEW)_preList,
                                    &dwBufSize,
                                    &_dwEntries
                                    );
                }
            }
       
            // reallocate buffer if necessary
            if(ERROR_BUFFER_TOO_SMALL == _dwLastError)
            {
                GlobalFree(_preList);
                _preList = (LPRASENTRYNAMEA)GlobalAlloc(LMEM_FIXED, dwBufSize);
                if(NULL == _preList)
                {
                    _dwLastError = ERROR_NOT_ENOUGH_MEMORY;
                    break;
                }
            }
            else
            {
                break;
            }

        } while(TRUE);
    }
    else
    {
        _dwLastError = ERROR_NOT_ENOUGH_MEMORY;
    }

    if(_preList && (ERROR_SUCCESS != _dwLastError))
    {
        GlobalFree(_preList);
        _preList = NULL;
        _dwEntries = 0;
    }

    return;
}

RasEnumHelp::~RasEnumHelp()
{
    if(_preList)
    {
        GlobalFree(_preList);
    }
}

DWORD
RasEnumHelp::GetError()
{
    return _dwLastError;
}

DWORD
RasEnumHelp::GetEntryCount()
{
    return _dwEntries;
}

LPWSTR
RasEnumHelp::GetEntryW(
    DWORD dwEntryNum
    )
{
    LPWSTR  pwszName = NULL;

    if(dwEntryNum >= _dwEntries)
    {
        return NULL;
    }

    switch(_EnumType)
    {
    case ENUM_MULTIBYTE:
        MultiByteToWideChar(CP_ACP, 0, _preList[dwEntryNum].szEntryName,
            -1, _szCurrentEntryW, RAS_MaxEntryName + 1);
        pwszName = _szCurrentEntryW;
        break;
    case ENUM_UNICODE:
        {
        LPRASENTRYNAMEW lpTemp = (LPRASENTRYNAMEW)_preList;
        pwszName = lpTemp[dwEntryNum].szEntryName;
        break;
        }
    case ENUM_WIN2K:
        {
        LPW2KRASENTRYNAMEW lpTemp = (LPW2KRASENTRYNAMEW)_preList;
        pwszName = lpTemp[dwEntryNum].szEntryName;
        break;
        }
    }

    return pwszName;
}

/////////////////////////////////////////////////////////////////////////////
//
//        NAME:           MakeNewConnectoid
//
//        SYNOPSIS:       Launches RNA new connectoid wizard; selects newly
//                                created connectoid (if any) in combo box
//
/////////////////////////////////////////////////////////////////////////////

typedef BOOL (*PFRED)(LPTSTR, LPTSTR, LPRASENTRYDLG);

BOOL MakeNewConnectoid(HWND hDlg, PCONNINFO pConn)
{
    BOOL fRet = FALSE, fDone = FALSE;
    DWORD dwRes = 0;

    ASSERT(lpRasCreatePhonebookEntryA);

    if(FALSE == g_fWin95) {
        // on NT, use RasEntryDlg so we know who we created and can edit
        // proxy info for that connectoid
        HMODULE hRasDlg = LoadLibrary(TEXT("rasdlg.dll"));
        if(hRasDlg) {
#ifdef UNICODE
            PFRED pfred = (PFRED)GetProcAddress(hRasDlg, "RasEntryDlgW");
#else
            PFRED pfred = (PFRED)GetProcAddress(hRasDlg, "RasEntryDlgA");
#endif
            if(pfred) {
                RASENTRYDLG info;

                memset(&info, 0, sizeof(RASENTRYDLG));
                info.dwSize = sizeof(RASENTRYDLG);
                info.hwndOwner = hDlg;
                info.dwFlags = RASEDFLAG_NewEntry;

                dwRes = (pfred)(NULL, NULL, &info);
                if(dwRes) {
                    DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_DIALUP), hDlg,
                        DialupDlgProc, (LPARAM)info.szEntry);
                    dwRes = ERROR_SUCCESS;

                    // save name as default
                    lstrcpyn(pConn->szEntryName, info.szEntry, RAS_MaxEntryName);
                } else {
                    dwRes = info.dwError;
                }
                fDone = TRUE;
            }

            FreeLibrary(hRasDlg);
        }
    }

    if(FALSE == fDone) {
        // on win95, show the ui to make new entry
        if(lpRasCreatePhonebookEntryA)
        {
            dwRes = (lpRasCreatePhonebookEntryA)(hDlg,NULL);
        }

        // if we're on millennium, refresh default
        if(g_fMillennium)
        {
            FixAutodialSettings(hDlg, pConn);
        }
    }

    if(ERROR_SUCCESS == dwRes) {
        // make sure dial default is turned on.  If this is NT, default entry
        // is set above to new entry.
        if(IsDlgButtonChecked(hDlg, IDC_DIALUP_NEVER))
        {
            CheckRadioButton(hDlg, IDC_DIALUP_NEVER, IDC_DIALUP, IDC_DIALUP);
        }
        PopulateRasEntries(hDlg, pConn);
        EnableConnectionControls(hDlg, pConn, FALSE);
        fRet = TRUE;
    }

    return fRet;
}

///////////////////////////////////////////////////////////////////////////
//
//        NAME:           PopulateRasEntries
//
//        ENTRY:          hwndDlg - dlg box window handle
//
//        SYNOPSIS:       Fills specified combo box with list of existing RNA
//                                connectoids
//
///////////////////////////////////////////////////////////////////////////

#define DEF_ENTRY_BUF_SIZE      8192

DWORD PopulateRasEntries(HWND hDlg, PCONNINFO pConn)
{
    HWND hwndTree = GetDlgItem(hDlg, IDC_CONN_LIST);
    DWORD i;
    DWORD dwBufSize = 16 * sizeof(RASENTRYNAMEA);
    DWORD dwEntries = 0;
    TVITEM tvi;
    TVINSERTSTRUCT tvins;
    HTREEITEM hFirst = NULL;

    ASSERT(hwndTree);

    // init tvi and tvins
    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
    tvi.lParam = 0;
    tvins.hInsertAfter = (HTREEITEM)TVI_SORT;
    tvins.hParent = TVI_ROOT;

    // clear list
    TreeView_DeleteAllItems(hwndTree);

    // any old htree is now bogus - we'll get a new one
    pConn->hDefault = NULL;

    // enumerate
    RasEnumHelp reh;

    if(ERROR_SUCCESS == reh.GetError())
    {
        TCHAR szTemp[RAS_MaxEntryName + 64];
        BOOL fDefault, fFoundDefault = FALSE;
        LPTSTR pszEntryName;

        // insert connectoid names from buffer into combo box
        for(i=0; i<reh.GetEntryCount(); i++)
        {
            pszEntryName = reh.GetEntryW(i);
            fDefault = FALSE;

            // if there's only one entry, force it to be the default
            if(1 == dwEntries)
            {
                StrCpyN(pConn->szEntryName, pszEntryName, RAS_MaxEntryName);
            }

            if(*pConn->szEntryName && 0 == StrCmp(pszEntryName, pConn->szEntryName)) {
                // this is the default entry - stick it in the default
                // text control and append (Default) to it
                SetWindowText(GetDlgItem(hDlg, IDC_DIAL_DEF_ISP), pConn->szEntryName);
                StrCpyN(szTemp, pszEntryName, RAS_MaxEntryName);
                MLLoadString(IDS_DEFAULT_TEXT, szTemp + lstrlen(szTemp), 64);
                tvi.pszText = szTemp;
                fDefault = TRUE;
                fFoundDefault = TRUE;
            } else {
                tvi.pszText = pszEntryName;
            }
            tvi.iImage = IMAGE_MODEM;
            tvi.iSelectedImage = IMAGE_MODEM;
            tvi.lParam = i;
            tvins.item = tvi;
            HTREEITEM hItem = TreeView_InsertItem(hwndTree, &tvins);
            if(NULL == hFirst)
                hFirst = hItem;
            if(fDefault)
                pConn->hDefault = hItem;
        }

        // if we didn't match our default with a connectoid, kill it
        if(FALSE == fFoundDefault)
        {
            *pConn->szEntryName = 0;
            MLLoadString(IDS_NONE, szTemp, 64);
            SetWindowText(GetDlgItem(hDlg, IDC_DIAL_DEF_ISP), szTemp);
        }
    }

    // select default or first entry if there is one
    if(pConn->hDefault)
    {
        TreeView_Select(hwndTree, pConn->hDefault, TVGN_CARET);
    }
    else if(hFirst)
    {
        TreeView_Select(hwndTree, hFirst, TVGN_CARET);
    }

    return reh.GetEntryCount();
}

void PopulateProxyControls(HWND hDlg, LPPROXYINFO pInfo, BOOL fSetText)
{
    BOOL fManual = FALSE, fScript = FALSE, fDisable, fTemp;

    // decide if everything is disabled
    fDisable = IsDlgButtonChecked(hDlg, IDC_DONT_USE_CONNECTION);

    //
    // disable proxy enable check box if proxy restricted
    //
    fTemp = fDisable || g_restrict.fProxy;
    EnableDlgItem(hDlg, IDC_MANUAL, !fTemp);
    if(FALSE == g_restrict.fProxy)
    {
        fManual = !fDisable && pInfo->fEnable;
    }

    //
    // Disable autoconfig if restricted
    //
    fScript = !fDisable && IsDlgButtonChecked(hDlg, IDC_CONFIGSCRIPT);

    fTemp = fDisable || g_restrict.fAutoConfig;
    EnableDlgItem(hDlg, IDC_CONFIGSCRIPT, !fTemp);
    EnableDlgItem(hDlg, IDC_AUTODISCOVER, !fTemp);
    if(fTemp)
    {
        fScript = FALSE;
    }

    // enable config script controls
    EnableDlgItem(hDlg, IDC_CONFIG_ADDR, fScript);
    EnableDlgItem(hDlg, IDC_CONFIGADDR_TX, fScript);
    EnableDlgItem(hDlg, IDC_AUTOCNFG_ADVANCED, fScript);

    // Button is always on and omit local addresses is available if proxy is checked
    EnableDlgItem(hDlg, IDC_PROXY_ADVANCED, fManual);
    EnableDlgItem(hDlg, IDC_PROXY_OMIT_LOCAL_ADDRESSES, fManual);

    // Enable dial controls as necessary
    EnableDlgItem(hDlg, IDC_USER, !fDisable && !pInfo->fCustomHandler);
    EnableDlgItem(hDlg, IDC_PASSWORD, !fDisable && !pInfo->fCustomHandler);
    EnableDlgItem(hDlg, IDC_DOMAIN, !fDisable && !pInfo->fCustomHandler);
    EnableDlgItem(hDlg, IDC_TX_USER, !fDisable && !pInfo->fCustomHandler);
    EnableDlgItem(hDlg, IDC_TX_PASSWORD, !fDisable && !pInfo->fCustomHandler);
    EnableDlgItem(hDlg, IDC_TX_DOMAIN, !fDisable && !pInfo->fCustomHandler);
    EnableDlgItem(hDlg, IDC_RAS_SETTINGS, !fDisable);
    EnableDlgItem(hDlg, IDC_DIAL_ADVANCED, !fDisable && !pInfo->fCustomHandler);

    // settings changed in here are enabled/disabled based on the actual proxy settings
    if(StrChr(pInfo->szProxy, TEXT('=')))
    {
        // different servers for each - disable fields on this dialog
        fManual = FALSE;
        if (fSetText)
        {
            SetWindowText(GetDlgItem(hDlg, IDC_PROXY_ADDR), TEXT(""));
            SetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), TEXT(""));
        }
    }
    else if (fSetText)
    {
        TCHAR       *pszColon, *pszColon2;
        //Is there a : in the proxy string ?
        pszColon = StrChr(pInfo->szProxy, TEXT(':'));
        if(pszColon)
        {
            //Yes, Find if we have another ':'
            pszColon2 = StrChr(pszColon + 1, TEXT(':'));
            if(pszColon2)
            {
                //Yes, so we have strig like http://itgproxy:80
                pszColon = pszColon2;
                SetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), pszColon + 1);
                *pszColon = 0;
            }
            else
            {
                //No, We dont have a second ':'

                int ilength =  (int) (pszColon - pInfo->szProxy);
                //Are there atleast two characters  left beyond the first ':'
                if (lstrlen(pInfo->szProxy) - ilength >= 2 )
                {
                    //Yes, Are Those characters equal //
                    if((pInfo->szProxy[++ilength] == TEXT('/')) &&
                        (pInfo->szProxy[++ilength] == TEXT('/')))
                    {
                        //Yes then we have string like http://itgproxy
                        //make the whole thing as the server and make port fiel empty
                       SetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), TEXT(""));
                    }
                    else
                    {
                        //No, so we have string like itgproxy:80.
                        SetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), pszColon + 1);
                        *pszColon = 0;
                    }
                }
                else
                {
                  //No We dont have atleast two character so lets parse this as server and port
                  // Assuming this strign to be something like itgproxy:8
                  SetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), pszColon + 1);
                  *pszColon = 0;
                }

            }
        }
        else
        {
            //No we dont have a : so treat the string as just the proxy server.
            //Case itgproxy
            SetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), TEXT(""));
        }
        SetWindowText(GetDlgItem(hDlg, IDC_PROXY_ADDR), pInfo->szProxy);
    }


    EnableDlgItem(hDlg, IDC_ADDRESS_TEXT,   fManual);
    EnableDlgItem(hDlg, IDC_PORT_TEXT,      fManual);
    EnableDlgItem(hDlg, IDC_PROXY_ADDR,     fManual);
    EnableDlgItem(hDlg, IDC_PROXY_PORT,     fManual);
}

void GetProxyInfo(HWND hDlg, PDIALINFO pDI)
{
    pDI->proxy.fEnable = IsDlgButtonChecked(hDlg, IDC_MANUAL);

    if(NULL == StrChr(pDI->proxy.szProxy, TEXT('=')))
    {
        //
        // not per-protocol, so read edit boxes
        //
        TCHAR szProxy[MAX_URL_STRING];
        TCHAR szPort[INTERNET_MAX_PORT_NUMBER_LENGTH + 1];

        GetWindowText(GetDlgItem(hDlg, IDC_PROXY_ADDR), szProxy, ARRAYSIZE(szProxy) );
        GetWindowText(GetDlgItem(hDlg, IDC_PROXY_PORT), szPort, ARRAYSIZE(szPort) );

        // if we got a proxy and a port, combine in to one string
        if(*szProxy && *szPort)
            wnsprintf(pDI->proxy.szProxy, ARRAYSIZE(pDI->proxy.szProxy), TEXT("%s:%s"), szProxy, szPort);
        else
            StrCpyN(pDI->proxy.szProxy, szProxy, ARRAYSIZE(pDI->proxy.szProxy));
    }

    //
    // fix manual settings override
    //
    pDI->proxy.fOverrideLocal = IsDlgButtonChecked(hDlg, IDC_PROXY_OMIT_LOCAL_ADDRESSES);

    if(pDI->proxy.fOverrideLocal) {
        RemoveLocalFromExceptionList(pDI->proxy.szOverride);
        if(*pDI->proxy.szOverride)
            wnsprintf(pDI->proxy.szOverride, ARRAYSIZE(pDI->proxy.szOverride), TEXT("%s;%s"), pDI->proxy.szOverride, cszLocalString);
        else
            StrCpyN(pDI->proxy.szOverride, cszLocalString, ARRAYSIZE(pDI->proxy.szOverride));
    }
}

//////////////////////////////////////////////////////////////////////
//
//        NAME:       DeleteRasEntry
//
//        SYNOPSIS:   Delete a connectoid
//
//////////////////////////////////////////////////////////////////////
void DeleteRasEntry(LPTSTR pszEntry)
{
    // Use RasDeleteEntryW if possible
    if(lpRasDeleteEntryW)
    {
        (lpRasDeleteEntryW)(NULL, pszEntry);
    }
    else
    {
        CHAR szEntryA[MAX_PATH];
        SHUnicodeToAnsi(pszEntry, szEntryA, ARRAYSIZE(szEntryA));

        // Use RasDeleteEntryA if possible
        if(lpRasDeleteEntryA)
        {
            (lpRasDeleteEntryA)(NULL, szEntryA);
        }
        else
        {
            // no RasDeleteEntry - must by Win95 gold machine.  Use RNA. Ick.
            if( lpRnaActivateEngine &&
                lpRnaDeleteEntry &&
                lpRnaDeactivateEngine &&
                ERROR_SUCCESS == (lpRnaActivateEngine)())
            {
                (lpRnaDeleteEntry)(szEntryA);
                (lpRnaDeactivateEngine)();
            }
        }
    }
}

//////////////////////////////////////////////////////////////////////
//
//        NAME:       ChangeDefault
//
//        SYNOPSIS:   Change default connectoid to currently selected one
//
//////////////////////////////////////////////////////////////////////
void ChangeDefault(HWND hDlg, PCONNINFO pConn)
{
    TVITEM tvi;
    HWND hwndTree = GetDlgItem(hDlg, IDC_CONN_LIST);
    HTREEITEM hCur;

    memset(&tvi, 0, sizeof(TVITEM));

    // find current selection - if there isn't one, bail
    hCur = TreeView_GetSelection(hwndTree);
    if(NULL == hCur)
        return;

    // remove (default) from current default
    if(pConn->hDefault) {
        tvi.mask = TVIF_HANDLE | TVIF_TEXT;
        tvi.hItem = pConn->hDefault;
        tvi.pszText = pConn->szEntryName;
        tvi.cchTextMax = RAS_MaxEntryName;
        TreeView_SetItem(hwndTree, &tvi);
    }

    // get text for current item
    tvi.mask = TVIF_HANDLE | TVIF_TEXT;
    tvi.hItem = hCur;
    tvi.pszText = pConn->szEntryName;
    tvi.cchTextMax = RAS_MaxEntryName;
    TreeView_GetItem(hwndTree, &tvi);

    // fill in default text field
    SetWindowText(GetDlgItem(hDlg, IDC_DIAL_DEF_ISP), pConn->szEntryName);

    // add (default) to current selection
    TCHAR szTemp[RAS_MaxEntryName + 64];

    StrCpyN(szTemp, pConn->szEntryName, RAS_MaxEntryName);
    MLLoadString(IDS_DEFAULT_TEXT, szTemp + lstrlen(szTemp), 64);

    // stick it back in the tree
    tvi.mask = TVIF_HANDLE | TVIF_TEXT;
    tvi.hItem = hCur;
    tvi.pszText = szTemp;
    tvi.cchTextMax = RAS_MaxEntryName;
    TreeView_SetItem(hwndTree, &tvi);

    // save htree
    pConn->hDefault = hCur;
}

//////////////////////////////////////////////////////////////////////
//
//        NAME:       ShowConnProps
//
//        SYNOPSIS:   Show properties for selected connection
//
//////////////////////////////////////////////////////////////////////

HTREEITEM GetCurSel(PCONNINFO pConn, HWND hDlg, LPTSTR pszBuffer, int iLen, BOOL *pfChecked)
{
    HWND    hwndTree = GetDlgItem(hDlg, IDC_CONN_LIST);
    TVITEM  tvi;

    tvi.hItem = TreeView_GetSelection(hwndTree);

    if(tvi.hItem) {
        tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
        tvi.stateMask = TVIS_STATEIMAGEMASK;

        // get test if needed
        if(pszBuffer) {
            tvi.mask |= TVIF_TEXT;
            tvi.pszText = pszBuffer;
            tvi.cchTextMax = iLen;
        }
        TreeView_GetItem(hwndTree, &tvi);

        if(pfChecked)
            *pfChecked = (BOOL)(tvi.state >> 12) - 1;
    }

    // if this is the default connectiod, return name without (default) part
    if(pszBuffer && tvi.hItem == pConn->hDefault) {
        StrCpyN(pszBuffer, pConn->szEntryName, iLen);
    }

    return tvi.hItem;
}

void ShowConnProps(HWND hDlg, PCONNINFO pConn, BOOL fLan)
{
    HTREEITEM   hItem = NULL;
    TCHAR       szEntryName[RAS_MaxEntryName+1];
    BOOL        fChecked = FALSE;

    // if not lan, apply current selections
    if(g_fMillennium && !fLan)
    {
        ConnectionDlgOK(hDlg, pConn);
    }

    // default to lan
    *szEntryName = 0;

    // find item of interest
    if(FALSE == fLan)
        hItem = GetCurSel(pConn, hDlg, szEntryName, RAS_MaxEntryName, &fChecked);

    if(hItem || fLan) {
        // show settings
        DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_DIALUP), hDlg,
            DialupDlgProc, (LPARAM)szEntryName);
    }

    // if not lan, some settings may have been changed by RAS UI -- refresh
    if(g_fMillennium && !fLan )
    {
        FixAutodialSettings(hDlg, pConn);
    }
}

BOOL GetConnSharingDll(LPTSTR pszPath)
{
    DWORD cb = SIZEOF(TCHAR) * MAX_PATH;
    return SHGetValue(HKEY_LOCAL_MACHINE, 
                TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
                TEXT("SharingDLL"), NULL, pszPath, &cb) == ERROR_SUCCESS;
}

BOOL IsConnSharingAvail()
{
    TCHAR szPath[MAX_PATH];
    return GetConnSharingDll(szPath);
}

typedef HRESULT (WINAPI *PFNCONNECTIONSHARING)(HWND hwnd, DWORD dwFlags);

void ShowConnSharing(HWND hDlg)
{
    TCHAR szPath[MAX_PATH];
    if (GetConnSharingDll(szPath))
    {
        HMODULE hmod = LoadLibrary(szPath);
        if (hmod)
        {
            PFNCONNECTIONSHARING pfn = (PFNCONNECTIONSHARING)GetProcAddress(hmod, "InternetConnectionSharing");
            if (pfn)
                pfn(hDlg, 0);
            FreeLibrary(hmod);
        }
    }
}

//////////////////////////////////////////////////////////////////////
//
//        NAME:       ConnectionDlgProc
//
//        SYNOPSIS:   Connection property sheet dialog proc.
//
//////////////////////////////////////////////////////////////////////


INT_PTR CALLBACK ConnectionDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
                                LPARAM lParam)
{
    PCONNINFO pConn = (PCONNINFO)GetWindowLongPtr(hDlg, GWLP_USERDATA);
    if (NULL == pConn && uMsg != WM_INITDIALOG)
    {
        return FALSE;
    }

    switch (uMsg)
    {
        case WM_INITDIALOG:
            // build and save conninfo struct
            pConn = new CONNINFO;
            if(NULL == pConn)
                return FALSE;
            SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)pConn);
            memset(pConn, 0, sizeof(CONNINFO));

            return ConnectionDlgInit(hDlg, pConn);

        case WM_DESTROY:
        {
            UnloadRNADll();

            // Free the image list used by the connection list
            HWND hwndConnList = GetDlgItem(hDlg, IDC_CONN_LIST);
            HIMAGELIST himl = TreeView_SetImageList(hwndConnList, NULL, TVSIL_NORMAL);
            if (himl)
            {
                ImageList_Destroy(himl);
            }

            SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)NULL);
            delete pConn;
            return TRUE;
        }
        case WM_NOTIFY:
        {
            NMHDR * lpnm = (NMHDR *) lParam;
            switch (lpnm->code)
            {
                case TVN_KEYDOWN:
                {
                    TV_KEYDOWN *pkey = (TV_KEYDOWN*)lpnm;
                    if(pkey->wVKey == VK_SPACE)
                    {
                        ENABLEAPPLY(hDlg);
                        SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // eat the key
                        return TRUE;
                    }
                    break;
                }

                case NM_CLICK:
                case NM_DBLCLK:
                {   // is this click in our tree?
                    if(lpnm->idFrom == IDC_CONN_LIST)
                    {   
                        HWND            hwndTree = GetDlgItem(hDlg, IDC_CONN_LIST);
                        TV_HITTESTINFO  ht;
                        HTREEITEM       hItem;

                        GetCursorPos(&ht.pt);
                        ScreenToClient(hwndTree, &ht.pt);
                        hItem = TreeView_HitTest(hwndTree, &ht);
                        if(hItem)
                        {
                            TreeView_SelectItem(hwndTree, hItem);

                            // If it's a double click, show settings
                            if(NM_DBLCLK == lpnm->code)
                            {
                                PostMessage(hDlg, WM_COMMAND, IDC_MODEM_SETTINGS, 0);
                            }
                        }
                    }
                    EnableConnectionControls(hDlg, pConn, FALSE);
                    break;
                }

                case TVN_SELCHANGEDA:
                case TVN_SELCHANGEDW:
                    EnableConnectionControls(hDlg, pConn, FALSE);
                    break;

                case PSN_QUERYCANCEL:
                case PSN_KILLACTIVE:
                case PSN_RESET:
                    SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
                    return TRUE;

                case PSN_APPLY:
                {
                    BOOL fRet = ConnectionDlgOK(hDlg, pConn);
                    SetPropSheetResult(hDlg,!fRet);
                    return !fRet;
                    break;
                }
            }
            break;
        }

        case WM_COMMAND:
            switch  (LOWORD(wParam))
            {
                case IDC_LAN_SETTINGS:
                    ShowConnProps(hDlg, pConn, TRUE);
                    break;

                case IDC_CON_SHARING:
                    ShowConnSharing(hDlg);
                    break;

                case IDC_DIALUP_ADD:
                    MakeNewConnectoid(hDlg, pConn);
                    break;

                case IDC_DIALUP_REMOVE:
                {
                    TCHAR   szEntryName[RAS_MaxEntryName+1];

                    if (GetCurSel(pConn, hDlg, szEntryName, RAS_MaxEntryName, NULL) &&
                        *szEntryName) {
                        if(IDOK == MsgBox(hDlg, IDS_DELETECONNECTOID, MB_ICONWARNING, MB_OKCANCEL)) {
                            DeleteRasEntry(szEntryName);
                            PopulateRasEntries(hDlg, pConn);

                            // fix controls
                            EnableConnectionControls(hDlg, pConn, FALSE);
                        }
                    }
                    break;
                }


                case IDC_DIALUP:
                case IDC_DIALUP_ON_NONET:
                case IDC_DIALUP_NEVER:

                    // fix radio buttons
                    CheckRadioButton(hDlg, IDC_DIALUP_NEVER, IDC_DIALUP, LOWORD(wParam));

                    // enable/disable other controls appropriately
                    EnableConnectionControls(hDlg, pConn, FALSE);
                    ENABLEAPPLY(hDlg);
                    break;

                case IDC_ENABLE_SECURITY:
                    ENABLEAPPLY(hDlg);
                    break;

                case IDC_SET_DEFAULT:
                    ChangeDefault(hDlg, pConn);
                    if(GetFocus() == GetDlgItem(hDlg, IDC_SET_DEFAULT))
                    {
                        // focus is currently on the button and it's about to be disabled
                        SetFocus(GetDlgItem(hDlg, IDC_CONN_LIST));
                    }
                    EnableConnectionControls(hDlg, pConn, FALSE);
                    ENABLEAPPLY(hDlg);
                    break;

                case IDC_MODEM_SETTINGS:
                    ShowConnProps(hDlg, pConn, FALSE);
                    break;

                case IDC_CONNECTION_WIZARD:
                    TCHAR       szICWReg[MAX_PATH];
                    TCHAR       szICWPath[MAX_PATH + 1];
                    DWORD       cbSize = MAX_PATH, dwType;

                    if (IsOS(OS_WHISTLERORGREATER))
                    {
                        // This is the invocation path for the New Connection Wizard in Whistler
                        StrCpy(szICWPath, TEXT("rundll32.exe netshell.dll,StartNCW"));
                    }
                    else
                    {
                        // Try and get ICW from IOD.  If it fails, try to run
                        // ICW anyway.  We may luck out and get an old one.
                        DWORD dwRes = JitFeature(hDlg, clsidFeatureICW, FALSE);

                        // find path of ICW
                        MLLoadString(IDS_ICW_NAME, szICWPath, MAX_PATH);
                        wnsprintf(szICWReg, ARRAYSIZE(szICWReg), TEXT("%s\\%s"), REGSTR_PATH_APPPATHS, szICWPath);

                        // read app paths key
                        if(ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, szICWReg, NULL, &dwType, szICWPath, &cbSize))
                            break;
                    }

                    // run connection wizard
                    STARTUPINFO si;
                    PROCESS_INFORMATION pi;
                    memset(&si, 0, sizeof(si));
                    si.cb = sizeof(si);

                    if(CreateProcess(NULL, szICWPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
                    {
                        // successfully ran ICW - get rid of this dialog
                        CloseHandle(pi.hProcess);
                        CloseHandle(pi.hThread);
                        PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
                    }
                    break;
            }
            break;

        case WM_HELP:      // F1
            ResWinHelp((HWND) ((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
                       HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;

        case WM_CONTEXTMENU:      // right mouse click
            ResWinHelp((HWND)wParam, IDS_HELPFILE,
                       HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;

        default:
            return FALSE;
    }

    return TRUE;
}

/*******************************************************************

NAME:           ConnectionDlgOK

SYNOPSIS:       OK button handler for connection prop page

********************************************************************/

// prototype for IsNetworkAlive()
typedef BOOL (WINAPI *ISNETWORKALIVE)(LPDWORD);

BOOL ConnectionDlgOK(HWND hDlg, PCONNINFO pConn)
{
    DWORD   dwAutodial;

    RegEntry re(REGSTR_PATH_INTERNETSETTINGS,HKEY_CURRENT_USER);
    if(ERROR_SUCCESS == re.GetError()) {

        // autodial
        dwAutodial = AUTODIAL_MODE_NEVER;
        if(IsDlgButtonChecked(hDlg, IDC_DIALUP))
        {
            dwAutodial = AUTODIAL_MODE_ALWAYS;
        }
        else if(IsDlgButtonChecked(hDlg, IDC_DIALUP_ON_NONET))
        {
            dwAutodial = AUTODIAL_MODE_NO_NETWORK_PRESENT;

            DWORD dwRes = JitFeature(hDlg, clsidFeatureMobile, FALSE);
            if(JIT_PRESENT != dwRes) {
                // user doesn't want MOP, change to dial always.
                dwAutodial = AUTODIAL_MODE_ALWAYS;
            }
            else
            {
                // Call IsNetworkAlive.  This will start sens service
                // and next instance of wininet will use it.
                HINSTANCE hSens;
                ISNETWORKALIVE pfnIsNetworkAlive;
                DWORD dwFlags;

                hSens = LoadLibrary(TEXT("sensapi.dll"));
                if(hSens)
                {
                    pfnIsNetworkAlive = (ISNETWORKALIVE)GetProcAddress(hSens, "IsNetworkAlive");
                    if(pfnIsNetworkAlive)
                    {
                        // Call it.  Don't really care about the result.
                        pfnIsNetworkAlive(&dwFlags);
                    }
                    FreeLibrary(hSens);
                }
            }
        }

        // save autodial mode
        InternetSetOption(NULL, INTERNET_OPTION_AUTODIAL_MODE, &dwAutodial, sizeof(dwAutodial));

        // save default connectoid
        if(*pConn->szEntryName)
        {
            InternetSetOption(NULL, INTERNET_OPTION_AUTODIAL_CONNECTION, pConn->szEntryName, lstrlen(pConn->szEntryName));
        }
    }

    // save security check state on win95
    if(g_fWin95)
    {
        DWORD dwValue = 0;
        if(IsDlgButtonChecked(hDlg, IDC_ENABLE_SECURITY))
        {
            dwValue = 1;
        }
        re.SetValue(REGSTR_VAL_ENABLESECURITYCHECK, dwValue);
    }

    //
    // Have wininet refresh it's connection settings
    //
    InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);

    UpdateAllWindows();

    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//        NAME:           EnableConnectionControls
//
//        SYNOPSIS:       Enables controls appropriately depending on what
//                                checkboxes are checked.
//
/////////////////////////////////////////////////////////////////////////////

VOID EnableConnectionControls(HWND hDlg, PCONNINFO pConn, BOOL fSetText)
{
    TCHAR   szEntryName[RAS_MaxEntryName + 1];
    BOOL    fList = FALSE, fDial = FALSE, fAutodial = FALSE;
    BOOL    fAdd = FALSE, fSettings = FALSE, fLan = TRUE, fSetDefault = TRUE;
    BOOL    fDialDefault = FALSE, fNT4SP3;
    HTREEITEM   hItem;
    int     iCount;

    fNT4SP3 = IsNTSPx(FALSE, 4, 3);

    if(fNT4SP3)
    {
        // no sens stuff on NT4SP3, so make sure on no net isn't picked
        if(IsDlgButtonChecked(hDlg, IDC_DIALUP_ON_NONET))
        {
            CheckRadioButton(hDlg, IDC_DIALUP_NEVER, IDC_DIALUP, IDC_DIALUP);
        }
    }

    //
    // Check out how much stuff is in the tree view and what's selected
    //
    iCount = TreeView_GetCount(GetDlgItem(hDlg, IDC_CONN_LIST));
    hItem = GetCurSel(pConn, hDlg, szEntryName, RAS_MaxEntryName, NULL);

    if(dwRNARefCount) {
        // Ras is loaded so enable list control
        fList = TRUE;

        // if anything is selected, turn on settings button
        if(hItem)
        {
            fSettings = TRUE;
            if(hItem == pConn->hDefault)
            {
                fSetDefault = FALSE;
            }
        }

        // Ensure ras is loaded
        if(iCount > 0)
            fDial = TRUE;
    }

    // check to see if dial default is checked
    if(fDial)
        fDialDefault = !IsDlgButtonChecked(hDlg, IDC_DIALUP_NEVER);

    if(fList && lpRasCreatePhonebookEntryA)
        fAdd = TRUE;

    // if dialing restriction is present, make sure user can't do nothing.
    if(g_restrict.fDialing)
        fAdd = fList = fDial = fDialDefault = fAutodial = fSettings = fLan = fSetDefault = FALSE;

    // enable list controls
    EnableDlgItem(hDlg, IDC_CONN_LIST,       fList);
    EnableDlgItem(hDlg, IDC_DIALUP_ADD,      fAdd);
    EnableDlgItem(hDlg, IDC_DIALUP_REMOVE,   fSettings);
    EnableDlgItem(hDlg, IDC_MODEM_SETTINGS,  fSettings);

    // enable lan controls
    EnableDlgItem(hDlg, IDC_LAN_SETTINGS,    fLan);

    // enable default controls
    EnableDlgItem(hDlg, IDC_DIALUP_NEVER,    fDial);
    EnableDlgItem(hDlg, IDC_DIALUP_ON_NONET, fDial && !fNT4SP3);
    EnableDlgItem(hDlg, IDC_DIALUP,          fDial);
    EnableDlgItem(hDlg, IDC_DIAL_DEF_TXT,    fDialDefault);
    EnableDlgItem(hDlg, IDC_DIAL_DEF_ISP,    fDialDefault);
    EnableDlgItem(hDlg, IDC_ENABLE_SECURITY, fDialDefault);
    EnableDlgItem(hDlg, IDC_SET_DEFAULT,     fDialDefault && fSetDefault);

    // if autodialing is disabled (no connectoids) make sure it's not checked
    if(FALSE == fDial)
        CheckRadioButton(hDlg, IDC_DIALUP_NEVER, IDC_DIALUP, IDC_DIALUP_NEVER);

    //
    // Fix connection wizard
    //
    if (g_restrict.fConnectionWizard)
    {
        EnableDlgItem(hDlg, IDC_CONNECTION_WIZARD, FALSE);
    }
}

VOID FixAutodialSettings(HWND hDlg, PCONNINFO pConn)
{
    // Find default connectoid
    DWORD dwSize = RAS_MaxEntryName + 1;
    if(FALSE == InternetQueryOption(NULL, INTERNET_OPTION_AUTODIAL_CONNECTION, pConn->szEntryName, &dwSize))
    {
        *pConn->szEntryName = 0;
    }

    // populate connectoids, will do the right thing with the default read above
    PopulateRasEntries(hDlg, pConn);

    // fix autodial radio buttons
    int iSel;
    DWORD dwAutodial;

    dwSize = sizeof(DWORD);
    if(FALSE == InternetQueryOption(NULL, INTERNET_OPTION_AUTODIAL_MODE, &dwAutodial, &dwSize))
    {
        dwAutodial = AUTODIAL_MODE_NEVER;
    }

    switch(dwAutodial)
    {
    case AUTODIAL_MODE_ALWAYS:
        iSel = IDC_DIALUP;
        break;
    case AUTODIAL_MODE_NO_NETWORK_PRESENT:
        iSel = IDC_DIALUP_ON_NONET;
        break;
    default :
        iSel = IDC_DIALUP_NEVER;
        break;
    } /* switch */
    CheckRadioButton(hDlg, IDC_DIALUP_NEVER, IDC_DIALUP, iSel);

    // enable appropriate controls
    EnableConnectionControls(hDlg, pConn, TRUE);
}


BOOL ConnectionDlgInit(HWND hDlg, PCONNINFO pConn)
{
    BOOL        fProxy = FALSE;
    BOOL        fDial = FALSE;
    HIMAGELIST  himl;
    HICON       hIcon;

    // Get platform - we need this as there's no security check on NT.
    OSVERSIONINFOA osvi;
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    GetVersionExA(&osvi);

    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) 
    {
        g_fWin95 = FALSE;

        if(osvi.dwMajorVersion > 4)
        {
            g_fWin2K = TRUE;
        }
    }
    else
    {
        if(osvi.dwMinorVersion >= 90)
        {
            g_fMillennium = TRUE;
        }
    }

    // load ras (success checked later - see dwRNARefCount in EnableConnectionControls
    LoadRNADll();

    // create image list for tree view
    himl = ImageList_Create(BITMAP_WIDTH, BITMAP_HEIGHT, ILC_COLOR | ILC_MASK, CONN_BITMAPS, 4 );
    hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_LAN));
    ImageList_AddIcon(himl, hIcon);
    hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_PHONE));
    ImageList_AddIcon(himl, hIcon);

    TreeView_SetImageList(GetDlgItem(hDlg, IDC_CONN_LIST), himl, TVSIL_NORMAL);

    // populate and configure autodial settings
    FixAutodialSettings(hDlg, pConn);

    // fix security check
    if(g_fWin95)
    {
        RegEntry re(REGSTR_PATH_INTERNETSETTINGS,HKEY_CURRENT_USER);
        if (re.GetError() == ERROR_SUCCESS)
        {
            if(re.GetNumber(REGSTR_VAL_ENABLESECURITYCHECK,0))
            {
                CheckDlgButton(hDlg, IDC_ENABLE_SECURITY, TRUE);
            }
        }
    }
    else
    {
        // no security check on NT so hide check box
        ShowWindow(GetDlgItem(hDlg, IDC_ENABLE_SECURITY), SW_HIDE);
    }

    if (!IsConnSharingAvail())
        ShowWindow(GetDlgItem(hDlg, IDC_CON_SHARING), SW_HIDE);

    // disable wizard button if for some reason ICW cannot be JITed in
    DWORD dwRes = JitFeature(hDlg, clsidFeatureICW, TRUE);
    if(JIT_NOT_AVAILABLE == dwRes) {
        // can never get ICW so grey button
        EnableWindow(GetDlgItem(hDlg, IDC_CONNECTION_WIZARD), FALSE);
    }

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////
//
//        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;
    }

    // Ask wininet if Ras is installed.  Always make this call even if ras
    // dll doesn't load since it also forces wininet to migrate proxy
    // settings if necessary.
    DWORD dwFlags;
    InternetGetConnectedStateExA(&dwFlags, NULL, 0, 0);
    if(0 == (dwFlags & INTERNET_RAS_INSTALLED)) {
        // not installed - none of the functions will work so bail
        dwRNARefCount--;
        return FALSE;
    }

    // get the file name from resource
    TCHAR szDllFilename[SMALL_BUF_LEN+1];
    if (!MLLoadString(IDS_RNADLL_FILENAME,szDllFilename,ARRAYSIZE(szDllFilename))) {
        dwRNARefCount--;
        return FALSE;
    }

    // load the DLL
    hInstRNADll = LoadLibrary(szDllFilename);
    if (!hInstRNADll) {
        dwRNARefCount--;
        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 (!(*RasApiList[nIndex].ppFcnPtr = (PVOID) GetProcAddress(hInstRNADll,
            RasApiList[nIndex].pszName)))
        {
            // no longer fatal - no RasDeleteEntry on Win95 gold.
            TraceMsg(TF_GENERAL, "Unable to get address of function %s", RasApiList[nIndex].pszName);

//          UnloadRNADll();
//          return FALSE;
        }
    }

    if(g_fWin95)
    {
        // make sure we don't use any W versions that may be around on Win9x.
        // They'll almost certainly be stubs.
        lpRasEditPhonebookEntryW   = NULL;
        lpRasEnumEntriesW          = NULL;
        lpRasDeleteEntryW          = NULL;
        lpRasGetEntryDialParamsW   = NULL;
        lpRasSetEntryDialParamsW   = NULL;
        lpRasGetEntryPropertiesW   = NULL;
    }

    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++)
            *RasApiList[nIndex].ppFcnPtr = NULL;

        // free the library
        FreeLibrary(hInstRNADll);
        hInstRNADll = NULL;
    }
}


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//                           Dialup Dialog ie modem settings
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

#define W2KRASENTRYW struct tagW2KRASENTRYW
W2KRASENTRYW
{
    DWORD       dwSize;
    DWORD       dwfOptions;
    DWORD       dwCountryID;
    DWORD       dwCountryCode;
    WCHAR       szAreaCode[ RAS_MaxAreaCode + 1 ];
    WCHAR       szLocalPhoneNumber[ RAS_MaxPhoneNumber + 1 ];
    DWORD       dwAlternateOffset;
    RASIPADDR   ipaddr;
    RASIPADDR   ipaddrDns;
    RASIPADDR   ipaddrDnsAlt;
    RASIPADDR   ipaddrWins;
    RASIPADDR   ipaddrWinsAlt;
    DWORD       dwFrameSize;
    DWORD       dwfNetProtocols;
    DWORD       dwFramingProtocol;
    WCHAR       szScript[ MAX_PATH ];
    WCHAR       szAutodialDll[ MAX_PATH ];
    WCHAR       szAutodialFunc[ MAX_PATH ];
    WCHAR       szDeviceType[ RAS_MaxDeviceType + 1 ];
    WCHAR       szDeviceName[ RAS_MaxDeviceName + 1 ];
    WCHAR       szX25PadType[ RAS_MaxPadType + 1 ];
    WCHAR       szX25Address[ RAS_MaxX25Address + 1 ];
    WCHAR       szX25Facilities[ RAS_MaxFacilities + 1 ];
    WCHAR       szX25UserData[ RAS_MaxUserData + 1 ];
    DWORD       dwChannels;
    DWORD       dwReserved1;
    DWORD       dwReserved2;
    DWORD       dwSubEntries;
    DWORD       dwDialMode;
    DWORD       dwDialExtraPercent;
    DWORD       dwDialExtraSampleSeconds;
    DWORD       dwHangUpExtraPercent;
    DWORD       dwHangUpExtraSampleSeconds;
    DWORD       dwIdleDisconnectSeconds;
    DWORD       dwType;
    DWORD       dwEncryptionType;
    DWORD       dwCustomAuthKey;
    GUID        guidId;
    WCHAR       szCustomDialDll[MAX_PATH];
    DWORD       dwVpnStrategy;
};


BOOL GetConnectoidInfo(HWND hDlg, LPTSTR pszEntryName)
{
    BOOL    fPassword = FALSE;

    if(g_fWin2K && lpRasGetEntryPropertiesW)
    {
        W2KRASENTRYW    re[2];
        DWORD           dwSize;

        // get props for this connectoid and see if it has a custom dial dll
        re[0].dwSize = sizeof(W2KRASENTRYW);
        dwSize = sizeof(re);
        if(ERROR_SUCCESS == (lpRasGetEntryPropertiesW)(NULL, pszEntryName,
                    (LPRASENTRYW)re, &dwSize, NULL, NULL))
        {
            if(0 != re[0].szCustomDialDll[0])
            {
                // Win2K handler exists - flag that we need to grey out
                // credential fields
                return TRUE;
            }
        }
    }
    else
    {
        // on down level platforms, check registry for cdh
        TCHAR   szTemp[MAX_PATH];

        GetConnKey(pszEntryName, szTemp, MAX_PATH);
        RegEntry re(szTemp, HKEY_CURRENT_USER);
        if(ERROR_SUCCESS == re.GetError())
        {
            if(re.GetString(REGSTR_VAL_AUTODIALDLLNAME, szTemp, MAX_PATH) && *szTemp)
            {
                // CDH exists - flag that we need to grey credentials
                return TRUE;
            }
        }
    }

    if(lpRasGetEntryDialParamsW)
    {
        RASDIALPARAMSW params;
        WCHAR  *pszUser = L"", *pszPassword = L"", *pszDomain = L"";

        memset(&params, 0, sizeof(params));
        params.dwSize = sizeof(params);

        StrCpyN(params.szEntryName, pszEntryName, RAS_MaxEntryName);
        if(ERROR_SUCCESS == (lpRasGetEntryDialParamsW)(NULL, (LPRASDIALPARAMSW)&params, &fPassword))
        {
            pszUser = params.szUserName;
            if(' ' != params.szDomain[0] || IsNTSPx(TRUE, 4, 6))  // NT4SP6 or greater?
                pszDomain = params.szDomain;
            if(fPassword)
                pszPassword = params.szPassword;
        }

        SetWindowText(GetDlgItem(hDlg, IDC_USER), pszUser);
        SetWindowText(GetDlgItem(hDlg, IDC_DOMAIN), pszDomain);
        SetWindowText(GetDlgItem(hDlg, IDC_PASSWORD), pszPassword);
    }
    else if(lpRasGetEntryDialParamsA)
    {
        RASDIALPARAMSA  params;
        CHAR            *pszUser = "", *pszPassword = "", *pszDomain = "";

        memset(&params, 0, sizeof(params));
        params.dwSize = sizeof(params);
        SHUnicodeToAnsi(pszEntryName, params.szEntryName, ARRAYSIZE(params.szEntryName));

        if(ERROR_SUCCESS == (lpRasGetEntryDialParamsA)(NULL, &params, &fPassword))
        {
            pszUser = params.szUserName;
            if(' ' != params.szDomain[0] || IsNTSPx(TRUE, 4, 6))  // NT4SP6 or greater?
                pszDomain = params.szDomain;
            if(fPassword)
                pszPassword = params.szPassword;
        }

        SetWindowTextA(GetDlgItem(hDlg, IDC_USER), pszUser);
        SetWindowTextA(GetDlgItem(hDlg, IDC_DOMAIN), pszDomain);
        SetWindowTextA(GetDlgItem(hDlg, IDC_PASSWORD), pszPassword);
    }

    return FALSE;
}

#ifndef WS_EX_LAYOUTRTL
#define WS_EX_LAYOUTRTL                 0x00400000L // Right to left mirroring
#else
#error "WS_EX_LAYOUTRTL is already defined in winuser.h"
#endif // WS_EX_LAYOUTRTL

///////////////////////////////////////////////////////////////////
//
// NAME:       FixDialogForLan
//
// SYNOPSIS:   Remove dialing section of dialog box
//
///////////////////////////////////////////////////////////////////
void FixDialogForLan(HWND hDlg)
{
    RECT rectParent, rectDial, rectNet, rectCur;
    POINT pt;
    int i;

    static int iHideIDs[] = {
        IDC_GRP_DIAL, IDC_RAS_SETTINGS, IDC_TX_USER, IDC_USER, IDC_TX_PASSWORD,
        IDC_PASSWORD, IDC_TX_DOMAIN, IDC_DOMAIN, IDC_DIAL_ADVANCED,
        IDC_DONT_USE_CONNECTION
      };
#define NUM_HIDE (sizeof(iHideIDs) / sizeof(int))

    static int iMoveIDs[] = {
        IDCANCEL, IDOK
      };
#define NUM_MOVE (sizeof(iMoveIDs) / sizeof(int))

    // hide relevant windows
    for(i=0; i<NUM_HIDE; i++) {
        ShowWindow(GetDlgItem(hDlg, iHideIDs[i]), SW_HIDE);
    }

    // move relevant windows (yuck)
    GetWindowRect(hDlg, &rectParent);
    GetWindowRect(GetDlgItem(hDlg, IDC_GRP_DIAL), &rectDial);
    GetWindowRect(GetDlgItem(hDlg, IDC_GRP_PROXY), &rectNet);

    for(i=0; i<NUM_MOVE; i++) {
        GetWindowRect(GetDlgItem(hDlg, iMoveIDs[i]), &rectCur);
        pt.x = (GetWindowLong(hDlg, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ? rectCur.right : rectCur.left;
        pt.y = rectCur.top;
        ScreenToClient(hDlg, &pt);
        MoveWindow(GetDlgItem(hDlg, iMoveIDs[i]), pt.x,
            pt.y - (rectDial.bottom - rectNet.bottom),
            rectCur.right - rectCur.left,
            rectCur.bottom - rectCur.top,
            TRUE);
    }

    // adjust dialog box size
    MoveWindow(hDlg, rectParent.left, rectParent.top,
        rectParent.right - rectParent.left,
        rectParent.bottom - rectParent.top - (rectDial.bottom - rectNet.bottom),
        TRUE);
}

///////////////////////////////////////////////////////////////////
//
// NAME:       DialupDlgInit
//
// SYNOPSIS:   Does initalization for dialup dialog
//
////////////////////////////////////////////////////////////////////

BOOL DialupDlgInit(HWND hDlg, LPTSTR pszConnectoid)
{
    PDIALINFO pDI;
    TCHAR   szTemp[MAX_PATH], szSettings[64];
    DWORD   dwIEAK = 0, cb;

    // set up dailinfo struct
    pDI = new DIALINFO;
    if(NULL == pDI)
        return FALSE;
    memset(pDI, 0, sizeof(DIALINFO));  // new already zero init?
#ifndef UNIX
    pDI->pszConnectoid = pszConnectoid;
#else
    // Can't pass lparam from PSheet because we put dialup dialog directly
    // on the tab.
    pszConnectoid = TEXT("");
    pDI->pszConnectoid = pDI->szEntryName;

#endif
    SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)pDI);

    // Fix window title
    if(0 == *(pDI->pszConnectoid)) {
        if (MLLoadString(IDS_LAN_SETTINGSPROXY, szTemp, MAX_PATH))
        {
            SetDlgItemText(hDlg, IDC_MANUAL, szTemp);
        }
        MLLoadString(IDS_LAN_SETTINGS, szTemp, MAX_PATH);
    } else {
        MLLoadString(IDS_SETTINGS, szSettings, 64);
        wnsprintf(szTemp, ARRAYSIZE(szTemp), TEXT("%s %s"), pDI->pszConnectoid, szSettings);
    }
    SetWindowText(hDlg, szTemp);

#ifndef UNIX
    // Different stuff if we're editing a connectoid vs. lan settings
    if(NULL == pszConnectoid || 0 == *pszConnectoid) {
        // remove dialing goo from dialog
        FixDialogForLan(hDlg);
    } else {
        // fill in username/password/domain
        pDI->proxy.fCustomHandler = GetConnectoidInfo(hDlg, pszConnectoid);
    }
#endif

    // hide advanced button for autoconfig info if IEAK restriction is not set

    cb = sizeof(dwIEAK);
    if ((SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_INETCPL_RESTRICTIONS, REGSTR_VAL_INETCPL_IEAK,
        NULL, (LPVOID)&dwIEAK, &cb) != ERROR_SUCCESS) || !dwIEAK)
        ShowWindow(GetDlgItem(hDlg, IDC_AUTOCNFG_ADVANCED), SW_HIDE);

    // hide advanced button on millennium
    if(g_fMillennium)
    {
        ShowWindow(GetDlgItem(hDlg, IDC_DIAL_ADVANCED), SW_HIDE);
        EnableWindow(GetDlgItem(hDlg, IDC_DIAL_ADVANCED), FALSE);
    }

    //
    // Read proxy and autoconfig settings for this connection
    //
    INTERNET_PER_CONN_OPTION_LIST list;
    DWORD dwBufSize = sizeof(list);

    list.pszConnection = (pszConnectoid && *pszConnectoid) ? pszConnectoid : NULL;
    list.dwSize = sizeof(list);
    list.dwOptionCount = 4;
    list.pOptions = new INTERNET_PER_CONN_OPTION[4];
    if(NULL == list.pOptions)
    {
        return FALSE;
    }

    list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
    list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
    list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
    list.pOptions[3].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;

    if(FALSE == InternetQueryOption(NULL,
            INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwBufSize))
    {
        delete [] list.pOptions;
        return FALSE;
    }

    //
    // move options to pDI struct
    //
    pDI->proxy.fEnable = (list.pOptions[0].Value.dwValue & PROXY_TYPE_PROXY);
    if(list.pOptions[1].Value.pszValue)
    {
        StrCpyN(pDI->proxy.szProxy, list.pOptions[1].Value.pszValue, MAX_URL_STRING);
        GlobalFree(list.pOptions[1].Value.pszValue);
        list.pOptions[1].Value.pszValue = NULL;
    }
    if(list.pOptions[2].Value.pszValue)
    {
        StrCpyN(pDI->proxy.szOverride, list.pOptions[2].Value.pszValue, MAX_URL_STRING);
        GlobalFree(list.pOptions[2].Value.pszValue);
        list.pOptions[2].Value.pszValue = NULL;
    }

    //
    // fill in dialog fields
    //

    // proxy enable
    if(pDI->proxy.fEnable)
    {
        CheckDlgButton(hDlg, IDC_MANUAL, TRUE);
    }

    // autoconfig enable and url
    if(list.pOptions[0].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL)
    {
        CheckDlgButton(hDlg, IDC_CONFIGSCRIPT, TRUE);
    }
    if(list.pOptions[3].Value.pszValue)
    {
        SetWindowText(GetDlgItem(hDlg, IDC_CONFIG_ADDR), list.pOptions[3].Value.pszValue);
        GlobalFree(list.pOptions[3].Value.pszValue);
        list.pOptions[3].Value.pszValue = NULL;
    }

    // autodiscovery enable
    if(list.pOptions[0].Value.dwValue & PROXY_TYPE_AUTO_DETECT)
    {
        CheckDlgButton(hDlg, IDC_AUTODISCOVER, TRUE);
    }

    // all done with options list
    delete [] list.pOptions;

    // check enable and override and parse out server and port
    pDI->proxy.fOverrideLocal = RemoveLocalFromExceptionList(pDI->proxy.szOverride);
    CheckDlgButton(hDlg, IDC_PROXY_ENABLE, pDI->proxy.fEnable);
    CheckDlgButton(hDlg, IDC_PROXY_OMIT_LOCAL_ADDRESSES, pDI->proxy.fOverrideLocal);
    PopulateProxyControls(hDlg, &pDI->proxy, TRUE);

    return TRUE;
}

///////////////////////////////////////////////////////////////////
//
// NAME:       DialupDlgOk
//
// SYNOPSIS:   Apply settings for dial up dialog box
//
////////////////////////////////////////////////////////////////////

BOOL DialupDlgOk(HWND hDlg, PDIALINFO pDI)
{
    DWORD   dwValue = 0;

    //
    // Save proxy settings
    //
    INTERNET_PER_CONN_OPTION_LIST list;
    DWORD   dwBufSize = sizeof(list);
    DWORD   dwOptions = 2;              // always save FLAGS & DISCOVERY_FLAGS
    TCHAR   szAutoConfig[MAX_URL_STRING];
    
    list.pszConnection = (pDI->pszConnectoid && *pDI->pszConnectoid) ? pDI->pszConnectoid : NULL;
    list.dwSize = sizeof(list);
    list.dwOptionCount = 1;
    list.pOptions = new INTERNET_PER_CONN_OPTION[5];
    if(NULL == list.pOptions)
    {
        return FALSE;
    }

    list.pOptions[0].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;

    //
    // Query autodiscover flags - we just need to set one bit in there
    //
    if(FALSE == InternetQueryOption(NULL,
            INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwBufSize))
    {
        delete [] list.pOptions;
        return FALSE;
    }

    //
    // save off all other options
    //
    list.pOptions[1].dwOption = INTERNET_PER_CONN_FLAGS;
    list.pOptions[1].Value.dwValue = PROXY_TYPE_DIRECT;

    //
    // save proxy settings
    //
    GetProxyInfo(hDlg, pDI);

    if(pDI->proxy.fEnable)
    {
        list.pOptions[1].Value.dwValue |= PROXY_TYPE_PROXY;
    }

    list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
    list.pOptions[2].Value.pszValue = pDI->proxy.szProxy;
    list.pOptions[3].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
    list.pOptions[3].Value.pszValue = pDI->proxy.szOverride;

    dwOptions += 2;

    //
    // save autodetect
    //
    if(IsDlgButtonChecked(hDlg, IDC_AUTODISCOVER))
    {
        list.pOptions[1].Value.dwValue |= PROXY_TYPE_AUTO_DETECT;
        if(pDI->fClickedAutodetect)
        {
            list.pOptions[0].Value.dwValue |= AUTO_PROXY_FLAG_USER_SET;
        }
    }
    else
    {
        list.pOptions[0].Value.dwValue &= ~AUTO_PROXY_FLAG_DETECTION_RUN;
    }

    //
    // save autoconfig
    //
    if(IsDlgButtonChecked(hDlg, IDC_CONFIGSCRIPT) &&
       GetWindowText(GetDlgItem(hDlg, IDC_CONFIG_ADDR), szAutoConfig, MAX_URL_STRING))
    {
        list.pOptions[1].Value.dwValue |= PROXY_TYPE_AUTO_PROXY_URL;
        list.pOptions[dwOptions].Value.pszValue = szAutoConfig;
        list.pOptions[dwOptions].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
        dwOptions++;
    }

    // update wininet
    list.dwOptionCount = dwOptions;
    InternetSetOption(NULL,
            INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);

    // tell wininet that the proxy info has changed
    InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);

    // all done with options list
    delete [] list.pOptions;

    // all done if we're editing lan settings
    if(NULL == pDI->pszConnectoid || 0 == *pDI->pszConnectoid)
        return TRUE;

    // no credentials to store if we have a w2k custom handler
    if(pDI->proxy.fCustomHandler)
    {
        return TRUE;
    }

    //
    // save connectoid information - use wide version if possible
    //
    BOOL            fDeletePassword = FALSE;

    if(lpRasSetEntryDialParamsW)
    {
        RASDIALPARAMSW  params;

        memset(&params, 0, sizeof(RASDIALPARAMSW));
        params.dwSize = sizeof(RASDIALPARAMSW);
        StrCpyN(params.szEntryName, pDI->pszConnectoid, RAS_MaxEntryName+1);
        GetWindowText(GetDlgItem(hDlg, IDC_USER), params.szUserName, UNLEN);
        GetWindowText(GetDlgItem(hDlg, IDC_PASSWORD), params.szPassword, PWLEN);
        if(0 == params.szPassword[0])
            fDeletePassword = TRUE;
        GetWindowText(GetDlgItem(hDlg, IDC_DOMAIN), params.szDomain, DNLEN);
        if(0 == params.szDomain[0] && !IsNTSPx(TRUE, 4, 6)) {    // NT4SP6 or greater?
            // user wants empty domain
            params.szDomain[0] = TEXT(' ');
        }
        (lpRasSetEntryDialParamsW)(NULL, &params, fDeletePassword);

    }
    else if(lpRasSetEntryDialParamsA)
    {
        RASDIALPARAMSA  params;

        memset(&params, 0, sizeof(RASDIALPARAMSA));
        params.dwSize = sizeof(RASDIALPARAMSA);
        SHUnicodeToAnsi(pDI->pszConnectoid, params.szEntryName, ARRAYSIZE(params.szEntryName));
        GetWindowTextA(GetDlgItem(hDlg, IDC_USER), params.szUserName, UNLEN);
        GetWindowTextA(GetDlgItem(hDlg, IDC_PASSWORD), params.szPassword, PWLEN);
        if(0 == params.szPassword[0])
            fDeletePassword = TRUE;
        GetWindowTextA(GetDlgItem(hDlg, IDC_DOMAIN), params.szDomain, DNLEN);
        if(0 == params.szDomain[0] && !IsNTSPx(TRUE, 4, 6)) {      // NT4SP6 or greater?
            // user wants empty domain
            params.szDomain[0] = TEXT(' ');
        }
        (lpRasSetEntryDialParamsA)(NULL, &params, fDeletePassword);
    }

    return TRUE;
}

///////////////////////////////////////////////////////////////////
//
// NAME:       DialupDlgProc
//
// SYNOPSIS:   Dialog proc for dial up dialog
//
////////////////////////////////////////////////////////////////////

INT_PTR CALLBACK DialupDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    PDIALINFO pDI = (PDIALINFO)GetWindowLongPtr(hDlg, GWLP_USERDATA);

    switch (uMsg) {

        case WM_INITDIALOG:
            ASSERT(lParam);
            DialupDlgInit(hDlg, (LPTSTR)lParam);
            return FALSE;

        case WM_DESTROY:
            delete pDI;
            break;

        case WM_COMMAND:
            switch (GET_WM_COMMAND_ID(wParam, lParam)) {
            case IDC_AUTODISCOVER:
                pDI->fClickedAutodetect = TRUE;
                break;
            case IDC_AUTOCNFG_ADVANCED:
                if(GET_WM_COMMAND_CMD(wParam, lParam) != BN_CLICKED)
                    break;
                // show advanced dialog box
                DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_AUTOCNFG_SETTINGS), hDlg,
                    AdvAutocnfgDlgProc, (LPARAM) pDI->pszConnectoid);
                break;

            case IDC_PROXY_ADVANCED:
                if(GET_WM_COMMAND_CMD(wParam, lParam) != BN_CLICKED)
                    break;

                GetProxyInfo(hDlg, pDI);

                // remove local so it doesn't show up in advanced dialog
                RemoveLocalFromExceptionList(pDI->proxy.szOverride);

                // show advanced dialog box
                if (DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_PROXY_SETTINGS), hDlg,
                                ProxyDlgProc, (LPARAM) &pDI->proxy) == IDOK)
                {
                    if(FALSE == pDI->proxy.fEnable)
                    {
                        // user disabled proxy in advanced dialog
                        CheckDlgButton(hDlg, IDC_MANUAL, FALSE);
                    }
                    PopulateProxyControls(hDlg, &pDI->proxy, TRUE);
                }
                break;

            case IDC_RAS_SETTINGS:
                if (g_fWin95) //jeffsi
                {
                    if(lpRasEditPhonebookEntryW)
                    {
                        (lpRasEditPhonebookEntryW)(hDlg, NULL, pDI->pszConnectoid);
                    }
                    else if(lpRasEditPhonebookEntryA)
                    {
                        CHAR  szConnectoid[MAX_PATH];
                        SHUnicodeToAnsi(pDI->pszConnectoid, szConnectoid, ARRAYSIZE(szConnectoid));
                        (lpRasEditPhonebookEntryA)(hDlg, NULL, szConnectoid);
                    }  
                }
                else
                {
                    PFRED pfred = NULL;
                    HMODULE hRasDlg = LoadLibrary(TEXT("rasdlg.dll"));
                    RASENTRYDLG info;

                    if (!hRasDlg)
                    {
                        break;
                    }
#ifdef UNICODE
                    pfred = (PFRED)GetProcAddress(hRasDlg, "RasEntryDlgW");
#else
                    pfred = (PFRED)GetProcAddress(hRasDlg, "RasEntryDlgA");
#endif
                    if (!pfred)
                    {
                        FreeLibrary(hRasDlg);
                        break;
                    }

                    memset(&info, 0, sizeof(RASENTRYDLG));
                    info.dwSize = sizeof(RASENTRYDLG);
                    info.hwndOwner = hDlg;

#ifdef UNICODE
                    (pfred)(NULL, pDI->pszConnectoid, &info);
#else
                    CHAR szConnectoid[MAX_PATH];
                    SHUnicodeToAnsi(pDI->pszConnectoid, szConnectoid, ARRAYSIZE(szConnectoid));
                    (pfred)(NULL, szConnectoid, &info);
#endif

                    FreeLibrary(hRasDlg);
                }
                break;
                
            case IDC_DIAL_ADVANCED:
                DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_DIALUP_ADVANCED), hDlg,
                    AdvDialupDlgProc, (LPARAM) pDI->pszConnectoid);
                break;

            case IDC_MANUAL:
                if(IsDlgButtonChecked(hDlg, IDC_MANUAL))
                {
                    pDI->proxy.fEnable = TRUE;
                    SetFocus(GetDlgItem(hDlg, IDC_PROXY_ADDR));
                    SendMessage(GetDlgItem(hDlg, IDC_PROXY_ADDR), EM_SETSEL, 0, -1);
                }
                else
                {
                    pDI->proxy.fEnable = FALSE;
                }
                PopulateProxyControls(hDlg, &pDI->proxy, FALSE);
#ifdef UNIX
                ENABLEAPPLY(hDlg);
#endif
                break;

            case IDC_CONFIGSCRIPT:
                if(IsDlgButtonChecked(hDlg, IDC_CONFIGSCRIPT))
                {
                    // set focus to config script url
                    SetFocus(GetDlgItem(hDlg, IDC_CONFIG_ADDR));
                    SendMessage(GetDlgItem(hDlg, IDC_CONFIG_ADDR), EM_SETSEL, 0, -1);
                }
                PopulateProxyControls(hDlg, &pDI->proxy, FALSE);
#ifdef UNIX
                ENABLEAPPLY(hDlg);
#endif
                break;


#ifdef UNIX
            case IDC_AUTODISCOVER:
            case IDC_PROXY_OMIT_LOCAL_ADDRESSES:
                ENABLEAPPLY(hDlg);
                break;
            case IDC_PROXY_PORT:
            case IDC_PROXY_ADDR:
            case IDC_CONFIG_ADDR:
                switch (HIWORD(wParam))
                {
                    case EN_CHANGE:
                        ENABLEAPPLY(hDlg);
                        break;
                }
                break;
#endif
            case IDC_DONT_USE_CONNECTION:
                PopulateProxyControls(hDlg, &pDI->proxy, FALSE);
                break;

            case IDOK:
                if(FALSE == DialupDlgOk(hDlg, pDI))
                    // something is wrong... don't exit yet
                    break;

                // fall through
            case IDCANCEL:
                return EndDialog(hDlg, 0);
            }
            break;

        case WM_HELP:      // F1
            ResWinHelp((HWND) ((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
                       HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;

        case WM_CONTEXTMENU:      // right mouse click
            ResWinHelp((HWND)wParam, IDS_HELPFILE,
                       HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;
#ifdef UNIX
        case WM_NOTIFY:
        {
            NMHDR * lpnm = (NMHDR *) lParam;
            switch (lpnm->code)
            {
                case PSN_APPLY:
                {
            if(FALSE == DialupDlgOk(hDlg, pDI))
                // something is wrong... don't exit yet
                break;
                // fall through
                }
        }
    }
#endif
    }

    return FALSE;
}


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//                  Advanced dial-up settings dialog
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
//
// NAME:       AdvDialupDlgProc
//
// SYNOPSIS:   Dialog proc for dial up dialog
//
////////////////////////////////////////////////////////////////////

void EnableAdvDialControls(HWND hDlg)
{
    BOOL fIdle      = IsDlgButtonChecked(hDlg, IDC_ENABLE_AUTODISCONNECT);

    // on if we have idle disconnect...
    EnableDlgItem(hDlg, IDC_IDLE_TIMEOUT, fIdle);
    EnableDlgItem(hDlg, IDC_IDLE_SPIN, fIdle);
}

BOOL AdvDialupDlgInit(HWND hDlg, LPTSTR pszConnectoid)
{
    TCHAR szTemp[MAX_PATH];
    DWORD dwRedialAttempts, dwRedialInterval, dwAutodisconnectTime;
    BOOL fExit, fDisconnect;

    // save connectoid name
    SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)pszConnectoid);

    // figure out our registry key
    GetConnKey(pszConnectoid, szTemp, MAX_PATH);

    // open connectoid or lan settings
    RegEntry reCon(szTemp, HKEY_CURRENT_USER);
    if(ERROR_SUCCESS != reCon.GetError())
        return FALSE;

    //
    // Read autodial / redial stuff
    //
    // We get this stuff from the connectoid if possible.  We assume it's all
    // saved to the connectoid together so if EnableAutodial is present there,
    // read everything from there else read everything from the IE4 settings.
    //
    dwRedialInterval = reCon.GetNumber(REGSTR_VAL_REDIALINTERVAL, DEF_REDIAL_WAIT);
    dwRedialAttempts = reCon.GetNumber(REGSTR_VAL_REDIALATTEMPTS, DEF_REDIAL_TRIES);

    // autodisconnect
    fDisconnect = (BOOL)reCon.GetNumber(REGSTR_VAL_ENABLEAUTODIALDISCONNECT, 0);
    dwAutodisconnectTime = reCon.GetNumber(REGSTR_VAL_DISCONNECTIDLETIME, DEF_AUTODISCONNECT_TIME);
    fExit = (BOOL)reCon.GetNumber(REGSTR_VAL_ENABLEEXITDISCONNECT, 0);

    //
    // Check if the mobile pack is installed and if it is not - then do not have it checked
    //
    DWORD dwRes = JitFeature(hDlg, clsidFeatureMobile, TRUE);
    if(JIT_PRESENT != dwRes)
    {
        fDisconnect = FALSE;
        fExit = FALSE;
        // check to see if offline pack is installed and disable the disconnect
        // options if user has bailed on it
        if(JIT_NOT_AVAILABLE == dwRes) {
            // can't get offline pack so disable options
            CheckDlgButton(hDlg, IDC_ENABLE_AUTODISCONNECT, FALSE);
            CheckDlgButton(hDlg, IDC_EXIT_DISCONNECT, FALSE);
            EnableWindow(GetDlgItem(hDlg, IDC_ENABLE_AUTODISCONNECT), FALSE);
            EnableWindow(GetDlgItem(hDlg, IDC_TX_AUTODISCONNECT), FALSE);
            EnableWindow(GetDlgItem(hDlg, IDC_EXIT_DISCONNECT), FALSE);
        }
    }

    //
    // Populate controls
    //
    CheckDlgButton(hDlg, IDC_ENABLE_AUTODISCONNECT, fDisconnect);
    CheckDlgButton(hDlg, IDC_EXIT_DISCONNECT, fExit);

    SendDlgItemMessage(hDlg, IDC_IDLE_SPIN, UDM_SETPOS, 0, dwAutodisconnectTime);
    SendDlgItemMessage(hDlg, IDC_CONNECT_SPIN,UDM_SETPOS, 0, dwRedialAttempts);
    SendDlgItemMessage(hDlg, IDC_INTERVAL_SPIN,UDM_SETPOS, 0, dwRedialInterval);

    //
    // Set control limits
    //
    Edit_LimitText(GetDlgItem(hDlg,IDC_IDLE_TIMEOUT), 2);    // limit edit ctrl to 2 chars
    Edit_LimitText(GetDlgItem(hDlg,IDC_IDLE_SPIN), 2);
    Edit_LimitText(GetDlgItem(hDlg,IDC_CONNECT_SPIN), 2);

    // set spin control min/max
    SendDlgItemMessage(hDlg,IDC_IDLE_SPIN,UDM_SETRANGE,0,
                    MAKELPARAM(MAX_AUTODISCONNECT_TIME,MIN_AUTODISCONNECT_TIME));
    SendDlgItemMessage(hDlg,IDC_CONNECT_SPIN,UDM_SETRANGE,0,
                    MAKELPARAM(MAX_REDIAL_TRIES,MIN_REDIAL_TRIES));
    SendDlgItemMessage(hDlg,IDC_INTERVAL_SPIN,UDM_SETRANGE,0,
                    MAKELPARAM(MAX_REDIAL_WAIT,MIN_REDIAL_WAIT));

    // enable controls
    EnableAdvDialControls(hDlg);

    return TRUE;
}

BOOL AdvDialupDlgOk(HWND hDlg, LPTSTR pszConnectoid)
{
    TCHAR szTemp[MAX_PATH];

    GetConnKey(pszConnectoid, szTemp, MAX_PATH);

    // open connectoid or lan settings
    RegEntry reCon(szTemp, HKEY_CURRENT_USER);
    if(ERROR_SUCCESS != reCon.GetError())
        return FALSE;

    // Save autodisconnect values
    BOOL fExit = IsDlgButtonChecked(hDlg,IDC_EXIT_DISCONNECT);
    BOOL fDisconnect = IsDlgButtonChecked(hDlg,IDC_ENABLE_AUTODISCONNECT);

    if(fExit || fDisconnect) {
        // make sure offline pack is installed or this feature won't work.
        DWORD dwRes = JitFeature(hDlg, clsidFeatureMobile, FALSE);
        if(JIT_PRESENT != dwRes) {
            // user doesn't want to download it so turn off autodisconnect
            fExit = FALSE;
            fDisconnect = FALSE;
        }
    }

    reCon.SetValue(REGSTR_VAL_ENABLEAUTODIALDISCONNECT, (DWORD)fDisconnect);
    reCon.SetValue(REGSTR_VAL_ENABLEEXITDISCONNECT, (DWORD)fExit);

    if(fDisconnect)
    {
        // get autodisconnect time from edit control
        // Sundown: coercion to 32b since values are range checked
        DWORD dwAutoDisconnectTime = (DWORD) SendDlgItemMessage(hDlg, IDC_IDLE_SPIN,
                                                                UDM_GETPOS,0,0);

        if(HIWORD(dwAutoDisconnectTime)) {
            MsgBox(hDlg, IDS_INVALID_AUTODISCONNECT_TIME, 0, MB_OK);

            // decide if it's too big or too small and fix it appropriately
            if(GetDlgItemInt(hDlg, IDC_IDLE_TIMEOUT, NULL, FALSE) < MIN_AUTODISCONNECT_TIME)
                dwAutoDisconnectTime = MIN_AUTODISCONNECT_TIME;
            else
                dwAutoDisconnectTime = MAX_AUTODISCONNECT_TIME;
            SendDlgItemMessage(hDlg, IDC_IDLE_SPIN, UDM_SETPOS, 0, dwAutoDisconnectTime);
            SetFocus(GetDlgItem(hDlg, IDC_IDLE_TIMEOUT));
            return FALSE;
        }

        // save it to registry
        reCon.SetValue(REGSTR_VAL_DISCONNECTIDLETIME, dwAutoDisconnectTime);

        // also save this value to MSN autodisconnect value, to
        // avoid confusion.  At some point in the future we'll
        // combine our UI...
        RegEntry reMSN(REGSTR_PATH_MOSDISCONNECT,HKEY_CURRENT_USER);
        if (reMSN.GetError() == ERROR_SUCCESS)
        {
            reMSN.SetValue(REGSTR_VAL_MOSDISCONNECT,dwAutoDisconnectTime);
        }
    }

    // save redial info
    DWORD_PTR dwRedialTry = SendDlgItemMessage(hDlg, IDC_CONNECT_SPIN, UDM_GETPOS, 0, 0);
    DWORD_PTR dwRedialWait = SendDlgItemMessage(hDlg, IDC_INTERVAL_SPIN, UDM_GETPOS, 0, 0);

    if(HIWORD(dwRedialTry)) {
        MsgBox(hDlg, IDS_INVALID_REDIAL_ATTEMPTS, 0, MB_OK);
        if(GetDlgItemInt(hDlg, IDC_CONNECT, NULL, FALSE) < MIN_REDIAL_TRIES)
            dwRedialTry = MIN_REDIAL_TRIES;
        else
            dwRedialTry = MAX_REDIAL_TRIES;
        SendDlgItemMessage(hDlg, IDC_CONNECT_SPIN, UDM_SETPOS, 0, dwRedialTry);
        SetFocus(GetDlgItem(hDlg, IDC_CONNECT));
        return FALSE;
    }

    if(HIWORD(dwRedialWait)) {
        MsgBox(hDlg, IDS_INVALID_REDIAL_WAIT, 0, MB_OK);
        if(GetDlgItemInt(hDlg, IDC_INTERVAL, NULL, FALSE) < MIN_REDIAL_WAIT)
            dwRedialWait = MIN_REDIAL_WAIT;
        else
            dwRedialWait = MAX_REDIAL_WAIT;
        SendDlgItemMessage(hDlg, IDC_INTERVAL_SPIN, UDM_SETPOS, 0, dwRedialWait);
        SetFocus(GetDlgItem(hDlg, IDC_INTERVAL));
        return FALSE;
    }

    reCon.SetValue(REGSTR_VAL_REDIALATTEMPTS, (DWORD) dwRedialTry);
    reCon.SetValue(REGSTR_VAL_REDIALINTERVAL, (DWORD) dwRedialWait);

    return TRUE;
}

INT_PTR CALLBACK AdvDialupDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    LPTSTR pszConn = (LPTSTR) GetWindowLongPtr(hDlg, GWLP_USERDATA);

    switch (uMsg) {

        case WM_INITDIALOG:
            ASSERT(lParam);
            AdvDialupDlgInit(hDlg, (LPTSTR)lParam);
            return FALSE;

        case WM_COMMAND:
            switch (GET_WM_COMMAND_ID(wParam, lParam)) {
            case IDC_ENABLE_AUTODISCONNECT:
                EnableAdvDialControls(hDlg);
                break;

            case IDOK:
                if(FALSE == AdvDialupDlgOk(hDlg, pszConn))
                    // something is wrong... don't exit yet
                    break;

                // fall through
            case IDCANCEL:
                return EndDialog(hDlg, 0);
            }
            break;

        case WM_HELP:      // F1
            ResWinHelp((HWND) ((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
                       HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;

        case WM_CONTEXTMENU:      // right mouse click
            ResWinHelp((HWND)wParam, IDS_HELPFILE,
                       HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;
    }

    return FALSE;
}


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//                  Advanced autoconfig settings dialog (only used by IEAK)
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

BOOL AdvAutocnfgDlgInit(HWND hDlg, LPTSTR pszConnectoid)
{
    INTERNET_PER_CONN_OPTION_LIST list;
    DWORD dwBufSize = sizeof(list);

    // save connectoid name
    SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)pszConnectoid);

    list.pszConnection = (pszConnectoid && *pszConnectoid) ? pszConnectoid : NULL;
    list.dwSize = sizeof(list);
    list.dwOptionCount = 3;
    list.pOptions = new INTERNET_PER_CONN_OPTION[3];
    if(NULL == list.pOptions)
    {
        return FALSE;
    }

    list.pOptions[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL;
    list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS;
    list.pOptions[2].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;

    if(FALSE == InternetQueryOption(NULL,
            INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwBufSize))
    {
        delete [] list.pOptions;
        return FALSE;
    }

    // autoproxy url (js)
    if(list.pOptions[0].Value.pszValue)
    {
        SetWindowText(GetDlgItem(hDlg, IDC_CONFIGJS_ADDR), list.pOptions[0].Value.pszValue);
    }

    
    // autoconfig timer interval
    if(list.pOptions[1].Value.dwValue)
    {
        TCHAR szTimerInterval[16];

        wsprintf(szTimerInterval, TEXT("%d"), list.pOptions[1].Value.dwValue);
        SetWindowText(GetDlgItem(hDlg, IDC_CONFIGTIMER), szTimerInterval);
    }

    // autoconfig optimization
    CheckDlgButton(hDlg, IDC_CONFIGOPTIMIZE, 
        (list.pOptions[2].Value.dwValue & AUTO_PROXY_FLAG_CACHE_INIT_RUN ) ? BST_CHECKED : BST_UNCHECKED);

    // all done with options list
    if (list.pOptions[0].Value.pszValue)
    {
        GlobalFree(list.pOptions[0].Value.pszValue);
    }
    delete [] list.pOptions;

    return TRUE;
}

BOOL AdvAutocnfgDlgOk(HWND hDlg, LPTSTR pszConnectoid)
{
    INTERNET_PER_CONN_OPTION_LIST list;
    DWORD   dwBufSize = sizeof(list);
    TCHAR    szAutoconfig[MAX_URL_STRING];
    TCHAR   szTimerInterval[16];

    list.pszConnection = (pszConnectoid && *pszConnectoid) ? pszConnectoid : NULL;
    list.dwSize = sizeof(list);
    list.dwOptionCount = 1;
    list.pOptions = new INTERNET_PER_CONN_OPTION[3];
    if(NULL == list.pOptions)
    {
        return FALSE;
    }

    list.pOptions[0].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
    //
    // Query autodiscover flags - we just need to set one bit in there
    //
    if(FALSE == InternetQueryOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwBufSize))
    {
        delete [] list.pOptions;
        return FALSE;
    }

    // save autoconfiguration optimization field

    if (IsDlgButtonChecked(hDlg, IDC_CONFIGOPTIMIZE) == BST_CHECKED)
        list.pOptions[0].Value.dwValue |= AUTO_PROXY_FLAG_CACHE_INIT_RUN ;
    else
        list.pOptions[0].Value.dwValue &= ~AUTO_PROXY_FLAG_CACHE_INIT_RUN ;

    //
    // save autoproxy url
    //
    list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL;
    GetWindowText(GetDlgItem(hDlg, IDC_CONFIGJS_ADDR), szAutoconfig, sizeof(szAutoconfig));
    list.pOptions[1].Value.pszValue = szAutoconfig;

    //
    // save autoconfig timer
    //
    list.pOptions[2].dwOption = INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS;
    list.pOptions[2].Value.dwValue = 0;
        
    if(GetWindowText(GetDlgItem(hDlg, IDC_CONFIGTIMER), szTimerInterval, sizeof(szTimerInterval)))
        list.pOptions[2].Value.dwValue = StrToInt(szTimerInterval);
    
    // update wininet
    list.dwOptionCount = 3;
    InternetSetOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);

    // tell wininet that the proxy info has changed
    InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);

    delete [] list.pOptions;

    return TRUE;
}

///////////////////////////////////////////////////////////////////
//
// NAME:       AdvAutocnfgProc
//
// SYNOPSIS:   Dialog proc for autoconfig dialog
//
////////////////////////////////////////////////////////////////////

INT_PTR CALLBACK AdvAutocnfgDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    LPTSTR pszConn = (LPTSTR) GetWindowLongPtr(hDlg, GWLP_USERDATA);

    switch (uMsg) {

        case WM_INITDIALOG:
            AdvAutocnfgDlgInit(hDlg, (LPTSTR)lParam);
            return FALSE;

        case WM_COMMAND:
            switch (GET_WM_COMMAND_ID(wParam, lParam)) {
            case IDOK:
                if(FALSE == AdvAutocnfgDlgOk(hDlg, pszConn))
                    // something is wrong... don't exit yet
                    break;

                // fall through
            case IDCANCEL:
                return EndDialog(hDlg, 0);
            }
            break;

        case WM_HELP:      // F1
            ResWinHelp((HWND) ((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
                       HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;

        case WM_CONTEXTMENU:      // right mouse click
            ResWinHelp((HWND)wParam, IDS_HELPFILE,
                       HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
            break;
    }

    return FALSE;
}
