/* Copyright (c) 1995, Microsoft Corporation, all rights reserved
**
** nwc.c
** Remote Access Common Dialog APIs
** NetWare Compatible warning dialog
**
** 12/06/95 Steve Cobb
*/

#include "rasdlgp.h"


/*----------------------------------------------------------------------------
** Local datatypes
**----------------------------------------------------------------------------
*/

/* NetWare Compatible warning dialog argument block.
*/
#define NWARGS struct tagNWARGS
NWARGS
{
    /* Caller's  arguments to the stub API.
    */
    BOOL     fPosition;
    LONG     xDlg;
    LONG     yDlg;
    PBFILE*  pFile;
    PBENTRY* pEntry;
};


/* Dial status dialog context block.
*/
#define NWINFO struct tagNWINFO
NWINFO
{
    /* Stub API arguments.
    */
    NWARGS* pArgs;

    /* Handle of this dialog and some of it's controls.
    */
    HWND hwndDlg;
    HWND hwndCb;
};


/*----------------------------------------------------------------------------
** Local prototypes (alphabetically)
**----------------------------------------------------------------------------
*/

BOOL
NwConnectionDlg(
    IN HWND     hwndOwner,
    IN BOOL     fPosition,
    IN LONG     xDlg,
    IN LONG     yDlg,
    IN PBFILE*  pFile,
    IN PBENTRY* pEntry );

BOOL CALLBACK
NwDlgProc(
    IN HWND   hwnd,
    IN UINT   unMsg,
    IN WPARAM wparam,
    IN LPARAM lparam );

BOOL
NwCommand(
    IN NWINFO* pInfo,
    IN WORD    wNotification,
    IN WORD    wId,
    IN HWND    hwndCtrl );

BOOL
NwInit(
    IN HWND    hwndDlg,
    IN NWARGS* pArgs );

VOID
NwTerm(
    IN HWND hwndDlg );

TCHAR*
GetNwProviderName(
    void );

BOOL
IsActiveNwLanConnection(
    void );


/*----------------------------------------------------------------------------
** Entry point
**----------------------------------------------------------------------------
*/

BOOL
NwConnectionCheck(
    IN HWND     hwndOwner,
    IN BOOL     fPosition,
    IN LONG     xDlg,
    IN LONG     yDlg,
    IN PBFILE*  pFile,
    IN PBENTRY* pEntry )

    /* Warns about active NetWare LAN connections being blown away, if
    ** indicated.  'HwndOwner' is the owning window if a dialog is necessary.
    ** 'FPosition', 'xDlg', and 'yDlg' are the dialog positioning parameters
    ** as specified to the calling API.  'PFile' and 'pEntry' are the open
    ** phonebook file and entry to check.
    **
    ** Note: This call will write the phonebook file if user checks the "not
    **       in the future" checkbox.
    **
    ** Returns true if warning is not necessary or user pressed OK, false if
    ** user presses cancel.
    */
{
    TRACE("NwConnectionCheck");

    /* Warn about active NetWare LAN connections being blown away, if
    ** indicated.
    */
    if (!pEntry->fSkipNwcWarning
        && pEntry->dwBaseProtocol == BP_Ppp
        && (GetInstalledProtocols() & NP_Ipx)
        && !(pEntry->dwfExcludedProtocols & NP_Ipx)
        && IsActiveNwLanConnection())
    {
        if (!NwConnectionDlg(
                hwndOwner, fPosition, xDlg, yDlg, pFile, pEntry ))
        {
            return FALSE;
        }
    }

    return TRUE;
}


/*----------------------------------------------------------------------------
** Netware dialog routines (alphabetically following stub and DlgProc)
**----------------------------------------------------------------------------
*/

BOOL
NwConnectionDlg(
    IN HWND     hwndOwner,
    IN BOOL     fPosition,
    IN LONG     xDlg,
    IN LONG     yDlg,
    IN PBFILE*  pFile,
    IN PBENTRY* pEntry )

    /* Pops up a warning about active NWC LAN connections being blown away.
    ** 'HwndOwner' is the owning window if a dialog is necessary.
    ** 'FPosition', 'xDlg', and 'yDlg' are the dialog positioning parameters
    ** as specified to the calling API.  'PFile' and 'pEntry' are the open
    ** phonebook file and entry to check.
    **
    ** Note: This call will write the phonebook file if user checks the "not
    **       in the future" checkbox.
    **
    ** Returns true if user pressed OK, false if user presses cancel.
    */
{
    int    nStatus;
    NWARGS args;

    TRACE("NwConnectionDlg");

    /* Initialize dialog argument block.
    */
    args.fPosition = fPosition;
    args.xDlg = xDlg;
    args.yDlg = yDlg;
    args.pFile = pFile;
    args.pEntry = pEntry;

    /* Run the dialog.
    */
    nStatus =
        (BOOL )DialogBoxParam(
            g_hinstDll,
            MAKEINTRESOURCE( DID_NW_NwcConnections ),
            hwndOwner,
            NwDlgProc,
            (LPARAM )&args );

    if (nStatus == -1)
    {
        ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
        nStatus = FALSE;
    }

    return (BOOL )nStatus;
}


BOOL CALLBACK
NwDlgProc(
    IN HWND   hwnd,
    IN UINT   unMsg,
    IN WPARAM wparam,
    IN LPARAM lparam )

    /* DialogProc callback for the Netware warning dialog.  Parameters and
    ** return value are as described for standard windows 'DialogProc's.
    */
{
#if 0
    TRACE4("NwDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
           (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
#endif

    switch (unMsg)
    {
        case WM_INITDIALOG:
            return NwInit( hwnd, (NWARGS* )lparam );

        case WM_COMMAND:
        {
            NWINFO* pInfo = (NWINFO* )GetWindowLong( hwnd, DWL_USER );
            ASSERT(pInfo);

            return NwCommand(
                pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
        }

        case WM_DESTROY:
        {
            NwTerm( hwnd );
            break;
        }
    }

    return FALSE;
}


BOOL
NwCommand(
    IN NWINFO* pInfo,
    IN WORD    wNotification,
    IN WORD    wId,
    IN HWND    hwndCtrl )

    /* Called on WM_COMMAND.  'PInfo' is the dialog context.  'WNotification'
    ** is the notification code of the command.  'wId' is the control/menu
    ** identifier of the command.  'HwndCtrl' is the control window handle of
    ** the command.
    **
    ** Returns true if processed message, false otherwise.
    */
{
    TRACE3("NwCommand(n=%d,i=%d,c=$%x)",
        (DWORD)wNotification,(DWORD)wId,(DWORD)hwndCtrl);

    switch (wId)
    {
        case IDOK:
        {
            TRACE("OK pressed");
            if (Button_GetCheck( pInfo->hwndCb ))
            {
                DWORD dwErr;

                /* Save user's preference to skip this warning popup in the
                ** phonebook.
                */
                pInfo->pArgs->pEntry->fSkipNwcWarning = TRUE;
                pInfo->pArgs->pEntry->fDirty = TRUE;
                dwErr = WritePhonebookFile( pInfo->pArgs->pFile, NULL );
                if (dwErr != 0)
                {
                    ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook,
                        dwErr, NULL );
                }
            }

            EndDialog( pInfo->hwndDlg, TRUE );
            return TRUE;
        }

        case IDCANCEL:
        {
            TRACE("Cancel pressed");
            EndDialog( pInfo->hwndDlg, FALSE );
            return TRUE;
        }
    }

    return FALSE;
}


BOOL
NwInit(
    IN HWND    hwndDlg,
    IN NWARGS* pArgs )

    /* Called on WM_INITDIALOG.  'hwndDlg' is the handle of the owning window.
    ** 'PArgs' is caller's arguments as passed to the stub API.
    **
    ** Return false if focus was set, true otherwise, i.e. as defined for
    ** WM_INITDIALOG.
    */
{
    DWORD   dwErr;
    TCHAR*  psz;
    NWINFO* pInfo;

    TRACE("NwInit");

    /* Allocate the dialog context block.  Initialize minimally for proper
    ** cleanup, then attach to the dialog window.
    */
    {
        pInfo = Malloc( sizeof(*pInfo) );
        if (!pInfo)
        {
            ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
            EndDialog( hwndDlg, FALSE );
            return TRUE;
        }

        ZeroMemory( pInfo, sizeof(*pInfo) );
        pInfo->pArgs = pArgs;
        pInfo->hwndDlg = hwndDlg;

        SetWindowLong( hwndDlg, DWL_USER, (LONG )pInfo );
        TRACE("Context set");
    }

    pInfo->hwndCb = GetDlgItem( hwndDlg, CID_NW_CB_SkipPopup );
    ASSERT(pInfo->hwndCb);

    /* Position the dialog per caller's instructions.
    */
    PositionDlg( hwndDlg, pArgs->fPosition, pArgs->xDlg, pArgs->yDlg );
    SetForegroundWindow( hwndDlg );

    /* Add context help button to title bar.  Dlgedit.exe doesn't currently
    ** support this at resource edit time.  When that's fixed set
    ** DS_CONTEXTHELP there and remove this call.
    */
    AddContextHelpButton( hwndDlg );

    /* Add context help button to title bar.  Dlgedit.exe doesn't currently
    ** support this at resource edit time.  When that's fixed set
    ** DS_CONTEXTHELP there and remove this call.
    */
    AddContextHelpButton( hwndDlg );

    return TRUE;
}


VOID
NwTerm(
    IN HWND hwndDlg )

    /* Called on WM_DESTROY.  'HwndDlg' is that handle of the dialog window.
    */
{
    NWINFO* pInfo = (NWINFO* )GetWindowLong( hwndDlg, DWL_USER );

    TRACE("NwTerm");

    if (pInfo)
        Free( pInfo );
}


/*----------------------------------------------------------------------------
** Utility routines
**----------------------------------------------------------------------------
*/


TCHAR*
GetNwProviderName(
    void )

    /* Returns the NWC provider name from the registry or NULL if none.  It's
    ** caller's responsibility to Free the returned string.
    */
{
#define REGKEY_Nwc  TEXT("SYSTEM\\CurrentControlSet\\Services\\NWCWorkstation\\networkprovider")
#define REGVAL_Name TEXT("Name")

    HKEY   hkey;
    DWORD  dwErr;
    DWORD  cb;
    TCHAR* psz = NULL;
    DWORD  dwType = REG_SZ;

    dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Nwc, &hkey );

    if (dwErr == 0)
    {
        dwErr = RegQueryValueEx(
            hkey, REGVAL_Name, NULL, &dwType, NULL, &cb );
        if (dwErr == 0)
        {
            psz = (TCHAR* )Malloc( cb );
            if (psz)
            {
                dwErr = RegQueryValueEx(
                    hkey, REGVAL_Name, NULL, &dwType, (LPBYTE )psz, &cb );
            }
        }

        RegCloseKey( hkey );
    }

    if (!psz || dwErr != 0 || dwType != REG_SZ)
    {
        if (psz)
            Free( psz );
        return NULL;
    }

    return psz;
}


BOOL
IsActiveNwLanConnection(
    void )

    /* Returns true if NWC is installed and there are redirected  drive or UNC
    ** connections using NWC provider, false otherwise.
    */
{
    DWORD  dwErr;
    DWORD  cEntries;
    DWORD  cb;
    TCHAR* pszProvider;
    BYTE   ab[ 1024 ];
    HANDLE hEnum = INVALID_HANDLE_VALUE;
    BOOL   fStatus = FALSE;

    do
    {
        pszProvider = GetNwProviderName();
        if (!pszProvider)
            break;

        dwErr = WNetOpenEnum(
            RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL, &hEnum );
        if (dwErr != NO_ERROR)
            break;

        for (;;)
        {
            NETRESOURCE* pnr;

            cEntries = 0xFFFFFFFF;
            cb = sizeof(ab);
            dwErr = WNetEnumResource( hEnum, &cEntries, ab, &cb );
            if (!cEntries || dwErr != NO_ERROR)
                break;

            for (pnr = (NETRESOURCE* )ab; cEntries--; ++pnr)
            {
                if (pnr->lpProvider
                    && lstrcmp( pnr->lpProvider, pszProvider ) == 0)
                {
                    fStatus = TRUE;
                    break;
                }
            }
        }
    }
    while (FALSE);

    if (hEnum != INVALID_HANDLE_VALUE)
        WNetCloseEnum( hEnum );

    if (pszProvider)
        Free( pszProvider );

    return fStatus;
}
