1799 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1799 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Copyright (c) 1995, Microsoft Corporation, all rights reserved
 | 
						|
**
 | 
						|
** entry.c
 | 
						|
** Remote Access Common Dialog APIs
 | 
						|
** RasPhonebookEntryDlg APIs
 | 
						|
**
 | 
						|
** 06/20/95 Steve Cobb
 | 
						|
*/
 | 
						|
 | 
						|
#include "rasdlgp.h"
 | 
						|
#include "entry.h"
 | 
						|
#include <serial.h>     // for SERIAL_TXT
 | 
						|
#include <mprapi.h>     // for MprAdmin API declarations
 | 
						|
#include <lmaccess.h>   // for NetUserAdd declarations
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
** Local prototypes (alphabetically)
 | 
						|
**----------------------------------------------------------------------------
 | 
						|
*/
 | 
						|
 | 
						|
BOOL
 | 
						|
EuCommit(
 | 
						|
    IN EINFO* pInfo );
 | 
						|
 | 
						|
DWORD
 | 
						|
EuCommitCredentials(
 | 
						|
    IN  EINFO*  pInfo );
 | 
						|
 | 
						|
DWORD
 | 
						|
EuLoadScpScriptsList(
 | 
						|
    OUT DTLLIST** ppList );
 | 
						|
 | 
						|
/* Target machine for RouterEntryDlg{A,W}
 | 
						|
*/
 | 
						|
static WCHAR g_wszServer[ MAX_COMPUTERNAME_LENGTH + 3] = L"";
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
** External entry points
 | 
						|
**----------------------------------------------------------------------------
 | 
						|
*/
 | 
						|
 | 
						|
BOOL APIENTRY
 | 
						|
RasEntryDlgA(
 | 
						|
    IN     LPSTR          lpszPhonebook,
 | 
						|
    IN     LPSTR          lpszEntry,
 | 
						|
    IN OUT LPRASENTRYDLGA lpInfo )
 | 
						|
 | 
						|
    /* Win32 ANSI entrypoint that displays the modal Phonebook Entry property
 | 
						|
    ** sheet.  'LpszPhonebook' is the full path to the phonebook file or NULL
 | 
						|
    ** to use the default phonebook.  'LpszEntry' is the entry to edit or the
 | 
						|
    ** default name of the new entry.  'LpInfo' is caller's additional
 | 
						|
    ** input/output parameters.
 | 
						|
    **
 | 
						|
    ** Returns true if user presses OK and succeeds, false on error or Cancel.
 | 
						|
    */
 | 
						|
{
 | 
						|
    WCHAR*       pszPhonebookW;
 | 
						|
    WCHAR*       pszEntryW;
 | 
						|
    RASENTRYDLGW infoW;
 | 
						|
    BOOL         fStatus;
 | 
						|
 | 
						|
    TRACE("RasEntryDlgA");
 | 
						|
 | 
						|
    if (!lpInfo)
 | 
						|
    {
 | 
						|
        SetLastError( ERROR_INVALID_PARAMETER );
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (lpInfo->dwSize != sizeof(RASENTRYDLGA))
 | 
						|
    {
 | 
						|
        lpInfo->dwError = ERROR_INVALID_SIZE;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Thunk "A" arguments to "W" arguments.
 | 
						|
    */
 | 
						|
    if (lpszPhonebook)
 | 
						|
    {
 | 
						|
        pszPhonebookW = StrDupTFromA( lpszPhonebook );
 | 
						|
        if (!pszPhonebookW)
 | 
						|
        {
 | 
						|
            lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
        pszPhonebookW = NULL;
 | 
						|
 | 
						|
    if (lpszEntry)
 | 
						|
    {
 | 
						|
        pszEntryW = StrDupTFromA( lpszEntry );
 | 
						|
        if (!pszEntryW)
 | 
						|
        {
 | 
						|
            Free0( pszPhonebookW );
 | 
						|
            {
 | 
						|
                lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
                return FALSE;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
        pszEntryW = NULL;
 | 
						|
 | 
						|
    ZeroMemory( &infoW, sizeof(infoW) );
 | 
						|
    infoW.dwSize = sizeof(infoW);
 | 
						|
    infoW.hwndOwner = lpInfo->hwndOwner;
 | 
						|
    infoW.dwFlags = lpInfo->dwFlags;
 | 
						|
    infoW.xDlg = lpInfo->xDlg;
 | 
						|
    infoW.yDlg = lpInfo->yDlg;
 | 
						|
    infoW.reserved = lpInfo->reserved;
 | 
						|
    infoW.reserved2 = lpInfo->reserved2;
 | 
						|
 | 
						|
    /* Thunk to the equivalent "W" API.
 | 
						|
    */
 | 
						|
    fStatus = RasEntryDlgW( pszPhonebookW, pszEntryW, &infoW );
 | 
						|
 | 
						|
    Free0( pszPhonebookW );
 | 
						|
    Free0( pszEntryW );
 | 
						|
 | 
						|
    /* Thunk "W" results to "A" results.
 | 
						|
    */
 | 
						|
    WideCharToMultiByte(
 | 
						|
        CP_ACP, 0, infoW.szEntry, -1, lpInfo->szEntry,
 | 
						|
        RAS_MaxEntryName + 1, NULL, NULL );
 | 
						|
    lpInfo->dwError = infoW.dwError;
 | 
						|
 | 
						|
    return fStatus;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
BOOL APIENTRY
 | 
						|
RasEntryDlgW(
 | 
						|
    IN     LPWSTR         lpszPhonebook,
 | 
						|
    IN     LPWSTR         lpszEntry,
 | 
						|
    IN OUT LPRASENTRYDLGW lpInfo )
 | 
						|
 | 
						|
    /* Win32 Unicode entrypoint that displays the modal Phonebook Entry
 | 
						|
    ** property sheet.  'LpszPhonebook' is the full path to the phonebook file
 | 
						|
    ** or NULL to use the default phonebook.  'LpszEntry' is the entry to edit
 | 
						|
    ** or the default name of the new entry.  'LpInfo' is caller's additional
 | 
						|
    ** input/output parameters.
 | 
						|
    **
 | 
						|
    ** Returns true if user presses OK and succeeds, false on error or Cancel.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD dwErr;
 | 
						|
    EINFO einfo;
 | 
						|
    BOOL  fStatus;
 | 
						|
    HWND  hwndOwner;
 | 
						|
    DWORD dwOp;
 | 
						|
 | 
						|
    TRACE("RasEntryDlgW");
 | 
						|
 | 
						|
    if (!lpInfo)
 | 
						|
    {
 | 
						|
        SetLastError( ERROR_INVALID_PARAMETER );
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (lpInfo->dwSize != sizeof(RASENTRYDLGW))
 | 
						|
    {
 | 
						|
        lpInfo->dwError = ERROR_INVALID_SIZE;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Eliminate some invalid flag combinations up front.
 | 
						|
    */
 | 
						|
    if (lpInfo->dwFlags & RASEDFLAG_CloneEntry)
 | 
						|
        lpInfo->dwFlags &= ~(RASEDFLAG_NewEntry | RASEDFLAG_NoRename);
 | 
						|
 | 
						|
    /* Pre-initialize the entry common context block.  The initialization is
 | 
						|
    ** completed later after the property sheet or wizard has been positioned
 | 
						|
    ** so that "waiting for services" can be centered.
 | 
						|
    */
 | 
						|
    dwErr = EuInit0( lpszPhonebook, lpszEntry, lpInfo, &einfo, &dwOp );
 | 
						|
    if (dwErr == 0)
 | 
						|
    {
 | 
						|
        if ((lpInfo->dwFlags & RASEDFLAG_NewEntry)
 | 
						|
            && einfo.pUser->fNewEntryWizard)
 | 
						|
        {
 | 
						|
            if (!einfo.fRouter)
 | 
						|
                AeWizard( &einfo );
 | 
						|
            else
 | 
						|
                AiWizard( &einfo );
 | 
						|
            if (einfo.fPadSelected)
 | 
						|
            {
 | 
						|
                /* Explain to the user that an address must be entered,
 | 
						|
                */
 | 
						|
                MsgDlg( lpInfo->hwndOwner, SID_EnterX25Address, NULL );
 | 
						|
                einfo.fChainPropertySheet = TRUE;
 | 
						|
            }
 | 
						|
            if (einfo.fChainPropertySheet && lpInfo->dwError == 0)
 | 
						|
                PePropertySheet( &einfo );
 | 
						|
            if (einfo.fPadSelected)
 | 
						|
            {
 | 
						|
                /* Now we clear 'fChainPropertySheet' if we only set it
 | 
						|
                ** because an X25 pad was selected.
 | 
						|
                ** This way, the user credentials are committed as required
 | 
						|
                ** in EuCommit below.
 | 
						|
                */
 | 
						|
                einfo.fChainPropertySheet = FALSE;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            PePropertySheet( &einfo );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        ErrorDlg( lpInfo->hwndOwner, dwOp, dwErr, NULL );
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
    }
 | 
						|
 | 
						|
    fStatus = (einfo.fCommit && EuCommit( &einfo ));
 | 
						|
    EuFree( &einfo );
 | 
						|
    return fStatus;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
BOOL APIENTRY
 | 
						|
RouterEntryDlgA(
 | 
						|
    IN     LPSTR          lpszServer,
 | 
						|
    IN     LPSTR          lpszPhonebook,
 | 
						|
    IN     LPSTR          lpszEntry,
 | 
						|
    IN OUT LPRASENTRYDLGA lpInfo )
 | 
						|
{
 | 
						|
    BOOL fSuccess;
 | 
						|
    DWORD dwErr;
 | 
						|
    PWCHAR pszServerW = NULL;
 | 
						|
 | 
						|
    TRACE("RouterEntryDlgA");
 | 
						|
 | 
						|
    //
 | 
						|
    // Set the RPC server.
 | 
						|
    //
 | 
						|
    if (!lpszServer)
 | 
						|
        g_wszServer[0] = L'\0';
 | 
						|
    else
 | 
						|
    {
 | 
						|
        MultiByteToWideChar(
 | 
						|
            CP_ACP, 0, lpszServer, -1, g_wszServer, MAX_COMPUTERNAME_LENGTH+3 );
 | 
						|
    }
 | 
						|
    dwErr = LoadRasRpcDll(g_wszServer);
 | 
						|
    if (dwErr) {
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Load MprApi entrypoints
 | 
						|
    //
 | 
						|
    dwErr = LoadMpradminDll();
 | 
						|
    if (dwErr) {
 | 
						|
        LoadRasRpcDll(NULL);
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Call the existing UI.
 | 
						|
    //
 | 
						|
    fSuccess = RasEntryDlgA(lpszPhonebook, lpszEntry, lpInfo);
 | 
						|
    //
 | 
						|
    // Unload MprApi entrypoints
 | 
						|
    //
 | 
						|
    UnloadMpradminDll();
 | 
						|
    //
 | 
						|
    // Unset the RPC server.
 | 
						|
    //
 | 
						|
    dwErr = LoadRasRpcDll(NULL);
 | 
						|
    if (dwErr) {
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    
 | 
						|
    return fSuccess;
 | 
						|
}
 | 
						|
 | 
						|
WCHAR pszRemoteHelpFmt[] = L"\\\\%s\\admin$\\system32\\%s";
 | 
						|
 | 
						|
DWORD 
 | 
						|
UpdateRemoteHelpFile(
 | 
						|
    IN PWCHAR lpszServer,
 | 
						|
    IN DWORD dwSid,
 | 
						|
    OUT PWCHAR* ppszFile)
 | 
						|
{
 | 
						|
    PWCHAR pszFile = NULL, pszMachine = NULL;
 | 
						|
    DWORD dwSize = 0;
 | 
						|
 | 
						|
    pszFile = PszFromId( g_hinstDll, dwSid );
 | 
						|
    if (pszFile == NULL)
 | 
						|
    {
 | 
						|
        return ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((*lpszServer) && (*lpszServer == L'\\'))
 | 
						|
    {
 | 
						|
        pszMachine = lpszServer + 2;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        pszMachine = lpszServer;
 | 
						|
    }
 | 
						|
 | 
						|
    dwSize = lstrlen(pszRemoteHelpFmt)  + 
 | 
						|
             lstrlen(pszMachine)        + 
 | 
						|
             lstrlen(pszFile)           +
 | 
						|
             1;
 | 
						|
    dwSize *= 2;
 | 
						|
 | 
						|
    // Free the previous setting
 | 
						|
    //
 | 
						|
    Free0(*ppszFile);
 | 
						|
    *ppszFile = (PWCHAR) Malloc(dwSize);
 | 
						|
    if (*ppszFile == NULL)
 | 
						|
    {
 | 
						|
        Free0(pszFile);
 | 
						|
        return ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
    }
 | 
						|
 | 
						|
    wsprintfW(*ppszFile, pszRemoteHelpFmt, pszMachine, pszFile);
 | 
						|
    
 | 
						|
    Free0(pszFile);
 | 
						|
 | 
						|
    return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
BOOL APIENTRY
 | 
						|
RouterEntryDlgW(
 | 
						|
    IN     LPWSTR         lpszServer,
 | 
						|
    IN     LPWSTR         lpszPhonebook,
 | 
						|
    IN     LPWSTR         lpszEntry,
 | 
						|
    IN OUT LPRASENTRYDLGW lpInfo )
 | 
						|
{
 | 
						|
    BOOL fSuccess;
 | 
						|
    DWORD dwErr;
 | 
						|
 | 
						|
    TRACE("RouterEntryDlgW");
 | 
						|
    TRACEW1("  s=%s",(lpszServer)?lpszServer:TEXT(""));
 | 
						|
    TRACEW1("  p=%s",(lpszPhonebook)?lpszPhonebook:TEXT(""));
 | 
						|
    TRACEW1("  e=%s",(lpszEntry)?lpszEntry:TEXT(""));
 | 
						|
 | 
						|
    if (!lpszServer)
 | 
						|
        g_wszServer[0] = L'\0';
 | 
						|
    else
 | 
						|
        lstrcpyW(g_wszServer, lpszServer);
 | 
						|
 | 
						|
    // 
 | 
						|
    // Reset the global router help file to be the one
 | 
						|
    // already installed on the nt4 machine.
 | 
						|
    //
 | 
						|
    if (lpszServer)
 | 
						|
    {
 | 
						|
        dwErr = UpdateRemoteHelpFile(
 | 
						|
                    lpszServer, 
 | 
						|
                    SID_HelpFile, 
 | 
						|
                    &g_pszHelpFile);
 | 
						|
        if (dwErr != NO_ERROR)
 | 
						|
        {
 | 
						|
            return dwErr;
 | 
						|
        }
 | 
						|
        
 | 
						|
        dwErr = UpdateRemoteHelpFile(
 | 
						|
                    lpszServer, 
 | 
						|
                    SID_RouterHelpFile, 
 | 
						|
                    &g_pszRouterHelpFile);
 | 
						|
        if (dwErr != NO_ERROR)
 | 
						|
        {
 | 
						|
            return dwErr;
 | 
						|
        }
 | 
						|
    }
 | 
						|
        
 | 
						|
    //
 | 
						|
    // Set the RPC server before calling RasEntryDlg.
 | 
						|
    //
 | 
						|
    dwErr = LoadRasRpcDll(lpszServer);
 | 
						|
    if (dwErr) {
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Load MprApi entrypoints
 | 
						|
    //
 | 
						|
    dwErr = LoadMpradminDll();
 | 
						|
    if (dwErr) {
 | 
						|
        LoadRasRpcDll(NULL);
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Call the existing UI.
 | 
						|
    //
 | 
						|
    fSuccess = RasEntryDlgW(lpszPhonebook, lpszEntry, lpInfo);
 | 
						|
    //
 | 
						|
    // Unload MprApi entrypoints
 | 
						|
    //
 | 
						|
    UnloadMpradminDll();
 | 
						|
    //
 | 
						|
    // Unset the RPC server.
 | 
						|
    //
 | 
						|
    dwErr = LoadRasRpcDll(NULL);
 | 
						|
    if (dwErr) {
 | 
						|
        lpInfo->dwError = dwErr;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return fSuccess;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
** Phonebook Entry common routines
 | 
						|
** Listed alphabetically
 | 
						|
**----------------------------------------------------------------------------
 | 
						|
*/
 | 
						|
 | 
						|
BOOL
 | 
						|
EuCommit(
 | 
						|
    IN EINFO* pInfo )
 | 
						|
 | 
						|
    /* Commits the new or changed entry node to the phonebook file and list.
 | 
						|
    ** Also adds the area code to the per-user list, if indicated.  'PInfo' is
 | 
						|
    ** the common entry information block.
 | 
						|
    **
 | 
						|
    ** Returns true if successful, false otherwise.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD dwErr;
 | 
						|
    BOOL  fEditMode;
 | 
						|
    BOOL  fChangedNameInEditMode;
 | 
						|
 | 
						|
    /* Delete all disabled link nodes.
 | 
						|
    */
 | 
						|
    if (DtlGetNodes( pInfo->pEntry->pdtllistLinks ) > 1)
 | 
						|
    {
 | 
						|
        DTLNODE* pNode;
 | 
						|
 | 
						|
        pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
 | 
						|
        while (pNode)
 | 
						|
        {
 | 
						|
            PBLINK*  pLink = (PBLINK* )DtlGetData( pNode );
 | 
						|
            DTLNODE* pNextNode = DtlGetNextNode( pNode );
 | 
						|
 | 
						|
            if (!pLink->fEnabled)
 | 
						|
            {
 | 
						|
                DtlRemoveNode( pInfo->pEntry->pdtllistLinks, pNode );
 | 
						|
                DestroyLinkNode( pNode );
 | 
						|
            }
 | 
						|
 | 
						|
            pNode = pNextNode;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Add the area code to the per-user list.
 | 
						|
    */
 | 
						|
    if (pInfo->pEntry->pszAreaCode)
 | 
						|
    {
 | 
						|
        TCHAR*   pszNewAreaCode = NULL;
 | 
						|
        DTLNODE* pNodeNew;
 | 
						|
        DTLNODE* pNode;
 | 
						|
 | 
						|
        /* Create a new node for the current area code and add it to the list
 | 
						|
        ** head.
 | 
						|
        */
 | 
						|
        pszNewAreaCode = StrDup( pInfo->pEntry->pszAreaCode );
 | 
						|
        if (!pszNewAreaCode)
 | 
						|
            return FALSE;
 | 
						|
 | 
						|
        pNodeNew = DtlCreateNode( pszNewAreaCode, 0 );
 | 
						|
        if (!pNodeNew)
 | 
						|
        {
 | 
						|
            Free( pszNewAreaCode );
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        DtlAddNodeFirst( pInfo->pUser->pdtllistAreaCodes, pNodeNew );
 | 
						|
 | 
						|
        /* Delete any other occurrence of the same area code later in the
 | 
						|
        ** list.
 | 
						|
        */
 | 
						|
        pNode = DtlGetNextNode( pNodeNew );
 | 
						|
 | 
						|
        while (pNode)
 | 
						|
        {
 | 
						|
            TCHAR*   pszAreaCode;
 | 
						|
            DTLNODE* pNodeNext;
 | 
						|
 | 
						|
            pNodeNext = DtlGetNextNode( pNode );
 | 
						|
 | 
						|
            pszAreaCode = (TCHAR* )DtlGetData( pNode );
 | 
						|
            if (lstrcmp( pszAreaCode, pszNewAreaCode ) == 0)
 | 
						|
            {
 | 
						|
                DtlRemoveNode( pInfo->pUser->pdtllistAreaCodes, pNode );
 | 
						|
                DestroyPszNode( pNode );
 | 
						|
            }
 | 
						|
 | 
						|
            pNode = pNodeNext;
 | 
						|
        }
 | 
						|
 | 
						|
        Free0( pszNewAreaCode );
 | 
						|
        pInfo->pUser->fDirty = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Notice if user changed his area-code/country-code preference.
 | 
						|
    */
 | 
						|
    if ((pInfo->pApiArgs->dwFlags & RASEDFLAG_NewEntry)
 | 
						|
        && pInfo->pUser->fUseAreaAndCountry
 | 
						|
              != pInfo->pEntry->fUseCountryAndAreaCode)
 | 
						|
    {
 | 
						|
        pInfo->pUser->fUseAreaAndCountry =
 | 
						|
            pInfo->pEntry->fUseCountryAndAreaCode;
 | 
						|
 | 
						|
        pInfo->pUser->fDirty = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Save preferences if they've changed.
 | 
						|
    */
 | 
						|
    if (pInfo->pUser->fDirty)
 | 
						|
    {
 | 
						|
        if (g_pSetUserPreferences(
 | 
						|
                pInfo->pUser,
 | 
						|
                (pInfo->fRouter) ? UPM_Router : UPM_Normal ) != 0)
 | 
						|
        {
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Save the changed phonebook entry.
 | 
						|
    */
 | 
						|
    pInfo->pEntry->fDirty = TRUE;
 | 
						|
 | 
						|
    /* The final name of the entry is output to caller via API structure.
 | 
						|
    */
 | 
						|
    lstrcpy( pInfo->pApiArgs->szEntry, pInfo->pEntry->pszEntryName );
 | 
						|
 | 
						|
    /* Delete the old node if in edit mode, then add the new node.
 | 
						|
    */
 | 
						|
    EuGetEditFlags( pInfo, &fEditMode, &fChangedNameInEditMode );
 | 
						|
 | 
						|
    if (fEditMode)
 | 
						|
        DtlDeleteNode( pInfo->pFile->pdtllistEntries, pInfo->pOldNode );
 | 
						|
 | 
						|
    DtlAddNodeLast( pInfo->pFile->pdtllistEntries, pInfo->pNode );
 | 
						|
    pInfo->pNode = NULL;
 | 
						|
 | 
						|
    /* Write the change to the phone book file.
 | 
						|
    */
 | 
						|
    dwErr = WritePhonebookFile( pInfo->pFile,
 | 
						|
                (fChangedNameInEditMode) ? pInfo->szOldEntryName : NULL );
 | 
						|
 | 
						|
    if (dwErr != 0)
 | 
						|
    {
 | 
						|
        ErrorDlg( pInfo->pApiArgs->hwndOwner, SID_OP_WritePhonebook, dwErr,
 | 
						|
            NULL );
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* If the user is creating a new router-phonebook entry,
 | 
						|
    ** and the user is using the router wizard to create it,
 | 
						|
    ** and the user did not edit properties directly,
 | 
						|
    ** save the dial-out credentials, and optionally, the dial-in credentials.
 | 
						|
    */
 | 
						|
    if ((pInfo->pApiArgs->dwFlags & RASEDFLAG_NewEntry)
 | 
						|
        && pInfo->fRouter
 | 
						|
        && pInfo->pUser->fNewEntryWizard
 | 
						|
        && !pInfo->fChainPropertySheet)
 | 
						|
    {
 | 
						|
        dwErr = EuCommitCredentials(pInfo);
 | 
						|
    }
 | 
						|
 | 
						|
    /* If the user edited/created a router-phonebook entry,
 | 
						|
    ** store the bitmask of selected network-protocols in 'reserved2'.
 | 
						|
    */
 | 
						|
    if (pInfo->fRouter)
 | 
						|
        pInfo->pApiArgs->reserved2 =
 | 
						|
            ((NP_Ip|NP_Ipx) & ~pInfo->pEntry->dwfExcludedProtocols);
 | 
						|
 | 
						|
    pInfo->pApiArgs->dwError = 0;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
DWORD
 | 
						|
EuCommitCredentials(
 | 
						|
    IN  EINFO*  pInfo )
 | 
						|
 | 
						|
    /* Commits the credentials and user-account for a router interface.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD   dwErr;
 | 
						|
    DWORD   dwPos;
 | 
						|
    HANDLE  hServer;
 | 
						|
    HANDLE  hInterface;
 | 
						|
    WCHAR*  pwszInterface = NULL;
 | 
						|
 | 
						|
    TRACE("EuCommitCredentials");
 | 
						|
    /* Connect to the router service
 | 
						|
    */
 | 
						|
    dwErr = g_pMprAdminServerConnect(g_wszServer, &hServer);
 | 
						|
    if (dwErr != NO_ERROR)
 | 
						|
        return dwErr;
 | 
						|
 | 
						|
    do
 | 
						|
    {
 | 
						|
        RAS_USER_0 ru0;
 | 
						|
        USER_INFO_1 ui1;
 | 
						|
        MPR_INTERFACE_0 mi0;
 | 
						|
 | 
						|
        /* Initialize the interface-information structure.
 | 
						|
        */
 | 
						|
        ZeroMemory(&mi0, sizeof(mi0));
 | 
						|
 | 
						|
        mi0.dwIfType = ROUTER_IF_TYPE_FULL_ROUTER;
 | 
						|
        mi0.fEnabled = TRUE;
 | 
						|
        pwszInterface = StrDupWFromT(pInfo->pEntry->pszEntryName);
 | 
						|
        if (!pwszInterface)
 | 
						|
        {
 | 
						|
            dwErr = ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        lstrcpyW(mi0.wszInterfaceName, pwszInterface);
 | 
						|
 | 
						|
        /* Create the interface.
 | 
						|
        */
 | 
						|
        dwErr = g_pMprAdminInterfaceCreate(
 | 
						|
                    hServer, 0, (BYTE*)&mi0, &hInterface );
 | 
						|
        if (dwErr) {
 | 
						|
            TRACE1("EuCommitCredentials: MprAdminInterfaceCreate error %d", dwErr);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /* Set the dial-out credentials for the interface.
 | 
						|
        ** Stop after this if an error occurs, or if we don't need
 | 
						|
        ** to add a user-account.
 | 
						|
        */
 | 
						|
        dwErr = g_pMprAdminInterfaceSetCredentials(
 | 
						|
                    g_wszServer, pwszInterface, pInfo->pszRouterUserName,
 | 
						|
                    pInfo->pszRouterDomain, pInfo->pszRouterPassword );
 | 
						|
        if (dwErr || !pInfo->fAddUser)
 | 
						|
        {
 | 
						|
            if(dwErr)
 | 
						|
                TRACE1("EuCommitCredentials: MprAdminInterfaceSetCredentials error %d", dwErr);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Initialize user-information structure.
 | 
						|
        */
 | 
						|
        ZeroMemory(&ui1, sizeof(ui1));
 | 
						|
 | 
						|
        ui1.usri1_name = pwszInterface;
 | 
						|
        ui1.usri1_password = StrDupWFromT(pInfo->pszRouterDialInPassword);
 | 
						|
        ui1.usri1_priv = USER_PRIV_USER;
 | 
						|
        ui1.usri1_comment = PszFromId(g_hinstDll, SID_RouterDialInAccount);
 | 
						|
        ui1.usri1_flags = UF_SCRIPT|UF_NORMAL_ACCOUNT|UF_DONT_EXPIRE_PASSWD;
 | 
						|
 | 
						|
 | 
						|
        /* Add the user-account.
 | 
						|
        */
 | 
						|
        {
 | 
						|
            WCHAR pszComputer[256], *pszMachine = NULL;
 | 
						|
 | 
						|
            if (g_wszServer == NULL)
 | 
						|
            {
 | 
						|
                pszMachine = NULL;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                pszMachine = pszComputer;
 | 
						|
 | 
						|
                if (*g_wszServer == L'\\')
 | 
						|
                {
 | 
						|
                    wcscpy(pszMachine, g_wszServer);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    wcscpy(pszMachine, L"\\\\");
 | 
						|
                    wcscpy(pszMachine + 2, g_wszServer);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            dwErr = NetUserAdd(pszMachine, 1, (BYTE*)&ui1, &dwPos);
 | 
						|
 | 
						|
            ZeroMemory(
 | 
						|
                ui1.usri1_password, lstrlen(ui1.usri1_password) * sizeof(TCHAR));
 | 
						|
            Free0(ui1.usri1_password);
 | 
						|
            Free0(ui1.usri1_comment);
 | 
						|
 | 
						|
            if (dwErr) {
 | 
						|
                TRACE1("EuCommitCredentials: NetUserAdd error %d", dwErr);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }            
 | 
						|
 | 
						|
        /* Initialize the RAS user-settings structure.
 | 
						|
        */
 | 
						|
        ZeroMemory(&ru0, sizeof(ru0));
 | 
						|
 | 
						|
        ru0.bfPrivilege = RASPRIV_NoCallback|RASPRIV_DialinPrivilege;
 | 
						|
 | 
						|
 | 
						|
        /* Enable dial-in access for the user-account.
 | 
						|
        */
 | 
						|
        dwErr = g_pRasAdminUserSetInfo(
 | 
						|
                    g_wszServer, pwszInterface, 0, (BYTE*)&ru0);
 | 
						|
        if(dwErr)
 | 
						|
            TRACE1("EuCommitCredentials: RasAdminUserSetInfo error %d", dwErr);
 | 
						|
 | 
						|
    } while(FALSE);
 | 
						|
 | 
						|
    if (pwszInterface)
 | 
						|
        Free(pwszInterface);
 | 
						|
 | 
						|
    g_pMprAdminServerDisconnect(hServer);
 | 
						|
 | 
						|
    return dwErr;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuEditScpScript(
 | 
						|
    IN HWND   hwndOwner,
 | 
						|
    IN TCHAR* pszScript )
 | 
						|
 | 
						|
    /* Starts notepad.exe on the 'pszScript' script path.  'HwndOwner' is the
 | 
						|
    ** window to center any error popup on.  'PEinfo' is the common entry
 | 
						|
    ** context.
 | 
						|
    */
 | 
						|
{
 | 
						|
    TCHAR               szCmd[ (MAX_PATH * 2) + 50 + 1 ];
 | 
						|
    STARTUPINFO         si;
 | 
						|
    PROCESS_INFORMATION pi;
 | 
						|
    BOOL                f;
 | 
						|
 | 
						|
    wsprintf( szCmd, TEXT("notepad.exe %s"), pszScript );
 | 
						|
 | 
						|
    ZeroMemory( &si, sizeof(si) );
 | 
						|
    si.cb = sizeof(si);
 | 
						|
 | 
						|
    TRACEW1("EuEditScp-cmd=%s",szCmd);
 | 
						|
 | 
						|
    f = CreateProcess(
 | 
						|
            NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
 | 
						|
 | 
						|
    if (f)
 | 
						|
    {
 | 
						|
        CloseHandle( pi.hThread );
 | 
						|
        CloseHandle( pi.hProcess );
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        ErrorDlg( hwndOwner, SID_OP_LoadSwitchEditor, GetLastError(), NULL );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuEditSwitchInf(
 | 
						|
    IN HWND hwndOwner )
 | 
						|
 | 
						|
    /* Starts notepad.exe on the system script file, switch.inf.  'HwndOwner'
 | 
						|
    ** is the window to center any error popup on.
 | 
						|
    */
 | 
						|
{
 | 
						|
    TCHAR               szCmd[ (MAX_PATH * 2) + 50 + 1 ];
 | 
						|
    TCHAR               szSysDir[ MAX_PATH + 1 ];
 | 
						|
    STARTUPINFO         si;
 | 
						|
    PROCESS_INFORMATION pi;
 | 
						|
    BOOL                f;
 | 
						|
 | 
						|
    szSysDir[ 0 ] = TEXT('\0');
 | 
						|
    g_pGetSystemDirectory( szSysDir, MAX_PATH );
 | 
						|
 | 
						|
    wsprintf( szCmd, TEXT("notepad.exe %s\\ras\\switch.inf"), szSysDir );
 | 
						|
 | 
						|
    ZeroMemory( &si, sizeof(si) );
 | 
						|
    si.cb = sizeof(si);
 | 
						|
 | 
						|
    TRACEW1("EuEditInf-cmd=%s",szCmd);
 | 
						|
 | 
						|
    f = CreateProcess(
 | 
						|
            NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
 | 
						|
 | 
						|
    if (f)
 | 
						|
    {
 | 
						|
        CloseHandle( pi.hThread );
 | 
						|
        CloseHandle( pi.hProcess );
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        ErrorDlg( hwndOwner, SID_OP_LoadSwitchEditor, GetLastError(), NULL );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuFillAreaCodeList(
 | 
						|
    IN EINFO* pEinfo,
 | 
						|
    IN HWND   hwndClbAreaCodes )
 | 
						|
 | 
						|
    /* Fill the area code list 'hwndClbAreaCodes' and set the selection to the
 | 
						|
    ** area code in the entry, unless it's already been filled.  'PEinfo' is
 | 
						|
    ** the common entry context.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DTLLIST* pList;
 | 
						|
    DTLNODE* pNode;
 | 
						|
    PBENTRY* pEntry;
 | 
						|
 | 
						|
    TRACE("EuFillAreaCodeList");
 | 
						|
 | 
						|
    if (ComboBox_GetCount( hwndClbAreaCodes ) > 0)
 | 
						|
        return;
 | 
						|
 | 
						|
    pList = pEinfo->pUser->pdtllistAreaCodes;
 | 
						|
    ASSERT(pList);
 | 
						|
    pEntry = pEinfo->pEntry;
 | 
						|
    ASSERT(pEntry);
 | 
						|
 | 
						|
    ComboBox_LimitText( hwndClbAreaCodes, RAS_MaxAreaCode );
 | 
						|
 | 
						|
    /* Add this entry's area code first.
 | 
						|
    */
 | 
						|
    if (pEntry->pszAreaCode)
 | 
						|
        ComboBox_AddString( hwndClbAreaCodes, pEntry->pszAreaCode );
 | 
						|
 | 
						|
    /* Append the per-user list of area codes, skipping the one we already
 | 
						|
    ** added.
 | 
						|
    */
 | 
						|
    for (pNode = DtlGetFirstNode( pList );
 | 
						|
         pNode;
 | 
						|
         pNode = DtlGetNextNode( pNode ))
 | 
						|
    {
 | 
						|
        TCHAR* pszAreaCode = (TCHAR* )DtlGetData( pNode );
 | 
						|
 | 
						|
        if (!pEntry->pszAreaCode
 | 
						|
            || lstrcmp( pszAreaCode, pEntry->pszAreaCode ) != 0)
 | 
						|
        {
 | 
						|
            ComboBox_AddString( hwndClbAreaCodes, pszAreaCode );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ComboBox_AutoSizeDroppedWidth( hwndClbAreaCodes );
 | 
						|
 | 
						|
    /* Select the first item, which will be this entry's code, if any.
 | 
						|
    */
 | 
						|
    if (ComboBox_GetCount( hwndClbAreaCodes ) > 0)
 | 
						|
        ComboBox_SetCurSel( hwndClbAreaCodes, 0 );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuFillCountryCodeList(
 | 
						|
    IN EINFO* pEinfo,
 | 
						|
    IN HWND   hwndLbCountryCodes,
 | 
						|
    IN BOOL   fComplete )
 | 
						|
 | 
						|
    /* Fill the country code list 'hwndLbCountryCodes' and set the selection
 | 
						|
    ** to the one in the entry, unless it's filled already.  If 'fComplete' is
 | 
						|
    ** set the list is completedly filled, otherwise only the current entry's
 | 
						|
    ** country code is loaded.  'PEinfo' is the common entry context.  'HwndDlg' is
 | 
						|
    ** the dialog owning the
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD    dwErr;
 | 
						|
    COUNTRY* pCountries;
 | 
						|
    COUNTRY* pCountry;
 | 
						|
    DWORD    cCountries;
 | 
						|
    DWORD    i;
 | 
						|
 | 
						|
    TRACE1("EuFillCountryCodeList(f=%d)",fComplete);
 | 
						|
 | 
						|
    /* There are 3 items in a partial list, the single visible country code
 | 
						|
    ** and the dummy items before and after used to give correct behavior when
 | 
						|
    ** left/right arrows are pressed.
 | 
						|
    */
 | 
						|
    cCountries = ComboBox_GetCount( hwndLbCountryCodes );
 | 
						|
    if (cCountries > 3 || (!fComplete && cCountries == 3))
 | 
						|
        return;
 | 
						|
 | 
						|
    /* Release old data buffer if already partially loaded.
 | 
						|
    */
 | 
						|
    if (pEinfo->pCountries)
 | 
						|
        FreeCountryInfo( pEinfo->pCountries, pEinfo->cCountries );
 | 
						|
 | 
						|
    pCountries = NULL;
 | 
						|
    cCountries = 0;
 | 
						|
 | 
						|
    dwErr = GetCountryInfo( &pCountries, &cCountries,
 | 
						|
                (fComplete) ? 0 : pEinfo->pEntry->dwCountryID );
 | 
						|
    if (dwErr == 0)
 | 
						|
    {
 | 
						|
        ComboBox_ResetContent( hwndLbCountryCodes );
 | 
						|
 | 
						|
        if (!fComplete)
 | 
						|
        {
 | 
						|
            /* Add dummy item first in partial list so left arrow selection
 | 
						|
            ** change can be handled correctly.  See CBN_SELCHANGE handling.
 | 
						|
            */
 | 
						|
            ComboBox_AddItem(
 | 
						|
                hwndLbCountryCodes, TEXT("AAAAA"), (VOID* )-1 );
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 0, pCountry = pCountries;
 | 
						|
             i < cCountries;
 | 
						|
             ++i, ++pCountry)
 | 
						|
        {
 | 
						|
            INT   iItem;
 | 
						|
            TCHAR szBuf[ 512 ];
 | 
						|
 | 
						|
            wsprintf( szBuf, TEXT("%s (%d)"),
 | 
						|
                pCountry->pszName, pCountry->dwCode );
 | 
						|
 | 
						|
            iItem = ComboBox_AddItem(
 | 
						|
                hwndLbCountryCodes, szBuf, pCountry );
 | 
						|
 | 
						|
            /* If it's the one in the entry, select it.
 | 
						|
            */
 | 
						|
            if (pCountry->dwId == pEinfo->pEntry->dwCountryID)
 | 
						|
                ComboBox_SetCurSel( hwndLbCountryCodes, iItem );
 | 
						|
        }
 | 
						|
 | 
						|
        if (!fComplete)
 | 
						|
        {
 | 
						|
            /* Add dummy item last in partial list so right arrow selection
 | 
						|
            ** change can be handled correctly.  See CBN_SELCHANGE handling.
 | 
						|
            */
 | 
						|
            ComboBox_AddItem(
 | 
						|
                hwndLbCountryCodes, TEXT("ZZZZZ"), (VOID* )1 );
 | 
						|
        }
 | 
						|
 | 
						|
        ComboBox_AutoSizeDroppedWidth( hwndLbCountryCodes );
 | 
						|
 | 
						|
        if (dwErr == 0 && cCountries == 0)
 | 
						|
            dwErr = ERROR_TAPI_CONFIGURATION;
 | 
						|
    }
 | 
						|
 | 
						|
    if (dwErr != 0)
 | 
						|
    {
 | 
						|
        ErrorDlg( GetParent( hwndLbCountryCodes ),
 | 
						|
            SID_OP_LoadTapiInfo, dwErr, NULL );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ComboBox_GetCurSel( hwndLbCountryCodes ) < 0)
 | 
						|
    {
 | 
						|
        /* The entry's country code was not added to the list, so as an
 | 
						|
        ** alternate select the first country in the list, loading the whole
 | 
						|
        ** list if necessary...should be extremely rare, a diddled phonebook
 | 
						|
        ** or TAPI country list strangeness.
 | 
						|
        */
 | 
						|
        if (ComboBox_GetCount( hwndLbCountryCodes ) > 0)
 | 
						|
            ComboBox_SetCurSel( hwndLbCountryCodes, 0 );
 | 
						|
        else
 | 
						|
        {
 | 
						|
            FreeCountryInfo( pCountries, cCountries );
 | 
						|
            EuFillCountryCodeList( pEinfo, hwndLbCountryCodes, TRUE );
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Will be freed by EuFree.
 | 
						|
    */
 | 
						|
    pEinfo->pCountries = pCountries;
 | 
						|
    pEinfo->cCountries = cCountries;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuFillScriptsList(
 | 
						|
    IN EINFO* pEinfo,
 | 
						|
    IN HWND   hwndLbScripts,
 | 
						|
    IN TCHAR* pszSelection )
 | 
						|
 | 
						|
    /* Fill scripts list in working entry of common entry context 'pEinfo'.
 | 
						|
    ** The old list, if any, is freed.  Select the script from user's entry.
 | 
						|
    ** 'HwndLbScripts' is the script dropdown.  'PszSelection' is the selected
 | 
						|
    ** name from the phonebook or NULL for "(none)".  If the name is non-NULL
 | 
						|
    ** but not found in the list it is appended.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD    dwErr;
 | 
						|
    DTLNODE* pNode;
 | 
						|
    INT      nIndex;
 | 
						|
    DTLLIST* pList;
 | 
						|
 | 
						|
    TRACE("EuFillScriptsList");
 | 
						|
 | 
						|
    ComboBox_ResetContent( hwndLbScripts );
 | 
						|
    ComboBox_AddItemFromId(
 | 
						|
        g_hinstDll, hwndLbScripts, SID_NoneSelected, NULL );
 | 
						|
    ComboBox_SetCurSel( hwndLbScripts, 0 );
 | 
						|
 | 
						|
    pList = NULL;
 | 
						|
    dwErr = LoadScriptsList( &pList );
 | 
						|
    if (dwErr != 0)
 | 
						|
    {
 | 
						|
        ErrorDlg( GetParent( hwndLbScripts ),
 | 
						|
            SID_OP_LoadScriptInfo, dwErr, NULL );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    DtlDestroyList( pEinfo->pListScripts, DestroyPszNode );
 | 
						|
    pEinfo->pListScripts = pList;
 | 
						|
 | 
						|
    for (pNode = DtlGetFirstNode( pEinfo->pListScripts );
 | 
						|
         pNode;
 | 
						|
         pNode = DtlGetNextNode( pNode ))
 | 
						|
    {
 | 
						|
        TCHAR* psz;
 | 
						|
 | 
						|
        psz = (TCHAR* )DtlGetData( pNode );
 | 
						|
        nIndex = ComboBox_AddString( hwndLbScripts, psz );
 | 
						|
 | 
						|
        if (pszSelection && lstrcmp( psz, pszSelection ) == 0)
 | 
						|
            ComboBox_SetCurSel( hwndLbScripts, nIndex );
 | 
						|
    }
 | 
						|
 | 
						|
    if (pszSelection && ComboBox_GetCurSel( hwndLbScripts ) <= 0)
 | 
						|
    {
 | 
						|
        nIndex = ComboBox_AddString( hwndLbScripts, pszSelection );
 | 
						|
        if (nIndex >= 0)
 | 
						|
            ComboBox_SetCurSel( hwndLbScripts, nIndex );
 | 
						|
    }
 | 
						|
 | 
						|
    ComboBox_AutoSizeDroppedWidth( hwndLbScripts );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuFillDoubleScriptsList(
 | 
						|
    IN EINFO* pEinfo,
 | 
						|
    IN HWND   hwndLbScripts,
 | 
						|
    IN TCHAR* pszSelection )
 | 
						|
 | 
						|
    /* Fill double scripts list (switch.inf entries and .SCP files) in working
 | 
						|
    ** entry of common entry context 'pEinfo'.  The old list, if any, is
 | 
						|
    ** freed.  Select the script from user's entry.  'HwndLbScripts' is the
 | 
						|
    ** script combobox.  'PszSelection' is the selected name from the
 | 
						|
    ** phonebook or NULL for "(none)".  If the name is non-NULL but not found
 | 
						|
    ** in the list it is appended.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD    dwErr;
 | 
						|
    DTLNODE* pNode;
 | 
						|
    INT      nIndex;
 | 
						|
    DTLLIST* pList;
 | 
						|
    DTLLIST* pListScp;
 | 
						|
 | 
						|
    TRACE("EuFillDoubleScriptsList");
 | 
						|
 | 
						|
    ComboBox_ResetContent( hwndLbScripts );
 | 
						|
    ComboBox_AddItemFromId(
 | 
						|
        g_hinstDll, hwndLbScripts, SID_NoneSelected, NULL );
 | 
						|
    ComboBox_SetCurSel( hwndLbScripts, 0 );
 | 
						|
 | 
						|
    pList = NULL;
 | 
						|
    dwErr = LoadScriptsList( &pList );
 | 
						|
    if (dwErr != 0)
 | 
						|
    {
 | 
						|
        ErrorDlg( GetParent( hwndLbScripts ),
 | 
						|
            SID_OP_LoadScriptInfo, dwErr, NULL );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    pListScp = NULL;
 | 
						|
    dwErr = EuLoadScpScriptsList( &pListScp );
 | 
						|
    if (dwErr == 0)
 | 
						|
    {
 | 
						|
        while (pNode = DtlGetFirstNode( pListScp ))
 | 
						|
        {
 | 
						|
            DtlRemoveNode( pListScp, pNode );
 | 
						|
            DtlAddNodeLast( pList, pNode );
 | 
						|
        }
 | 
						|
 | 
						|
        DtlDestroyList( pListScp, NULL );
 | 
						|
    }
 | 
						|
 | 
						|
    DtlDestroyList( pEinfo->pListDoubleScripts, DestroyPszNode );
 | 
						|
    pEinfo->pListDoubleScripts = pList;
 | 
						|
 | 
						|
    for (pNode = DtlGetFirstNode( pEinfo->pListDoubleScripts );
 | 
						|
         pNode;
 | 
						|
         pNode = DtlGetNextNode( pNode ))
 | 
						|
    {
 | 
						|
        TCHAR* psz;
 | 
						|
 | 
						|
        psz = (TCHAR* )DtlGetData( pNode );
 | 
						|
        nIndex = ComboBox_AddString( hwndLbScripts, psz );
 | 
						|
 | 
						|
        if (pszSelection && lstrcmp( psz, pszSelection ) == 0)
 | 
						|
            ComboBox_SetCurSel( hwndLbScripts, nIndex );
 | 
						|
    }
 | 
						|
 | 
						|
    if (pszSelection && ComboBox_GetCurSel( hwndLbScripts ) <= 0)
 | 
						|
    {
 | 
						|
        nIndex = ComboBox_AddString( hwndLbScripts, pszSelection );
 | 
						|
        if (nIndex >= 0)
 | 
						|
            ComboBox_SetCurSel( hwndLbScripts, nIndex );
 | 
						|
    }
 | 
						|
 | 
						|
    ComboBox_AutoSizeDroppedWidth( hwndLbScripts );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuFree(
 | 
						|
    IN EINFO* pInfo )
 | 
						|
 | 
						|
    /* Releases memory associated with 'pInfo'.
 | 
						|
    */
 | 
						|
{
 | 
						|
    TCHAR* psz;
 | 
						|
    INTERNALARGS* piargs;
 | 
						|
 | 
						|
    piargs = (INTERNALARGS* )pInfo->pApiArgs->reserved;
 | 
						|
 | 
						|
    /* Don't clean up the phonebook and user preferences if they arrived
 | 
						|
    ** via the secret hack.
 | 
						|
    */
 | 
						|
    if (!piargs)
 | 
						|
    {
 | 
						|
        if (pInfo->pFile)
 | 
						|
            ClosePhonebookFile( pInfo->pFile );
 | 
						|
 | 
						|
        if (pInfo->pUser)
 | 
						|
            DestroyUserPreferences( pInfo->pUser );
 | 
						|
    }
 | 
						|
 | 
						|
    DtlDestroyList( pInfo->pListScripts, DestroyPszNode );
 | 
						|
    DtlDestroyList( pInfo->pListDoubleScripts, DestroyPszNode );
 | 
						|
 | 
						|
    if (pInfo->pNode)
 | 
						|
        DestroyEntryNode( pInfo->pNode );
 | 
						|
 | 
						|
    if (pInfo->pCountries)
 | 
						|
        FreeCountryInfo( pInfo->pCountries, pInfo->cCountries );
 | 
						|
 | 
						|
    /* Free router-information
 | 
						|
    */
 | 
						|
    Free0(pInfo->pszRouter);
 | 
						|
    Free0(pInfo->pszRouterUserName);
 | 
						|
    Free0(pInfo->pszRouterDomain);
 | 
						|
    if (psz = pInfo->pszRouterPassword)
 | 
						|
    {
 | 
						|
        ZeroMemory(psz, lstrlen(psz) * sizeof(TCHAR));
 | 
						|
        Free(psz);
 | 
						|
    }
 | 
						|
    if (psz = pInfo->pszRouterDialInPassword)
 | 
						|
    {
 | 
						|
        ZeroMemory(psz, lstrlen(psz) * sizeof(TCHAR));
 | 
						|
        Free(psz);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuGetEditFlags(
 | 
						|
    IN  EINFO* pEinfo,
 | 
						|
    OUT BOOL*  pfEditMode,
 | 
						|
    OUT BOOL*  pfChangedNameInEditMode )
 | 
						|
 | 
						|
    /* Sets '*pfEditMode' true if in edit mode, false otherwise.  Set
 | 
						|
    ** '*pfChangedNameInEditMode' true if the entry name was changed while in
 | 
						|
    ** edit mode, false otherwise.  'PEinfo' is the common entry context.
 | 
						|
    */
 | 
						|
{
 | 
						|
    if ((pEinfo->pApiArgs->dwFlags & RASEDFLAG_NewEntry)
 | 
						|
        || (pEinfo->pApiArgs->dwFlags & RASEDFLAG_CloneEntry))
 | 
						|
    {
 | 
						|
        *pfEditMode = *pfChangedNameInEditMode = FALSE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        *pfEditMode = TRUE;
 | 
						|
        *pfChangedNameInEditMode =
 | 
						|
            (lstrcmpi( pEinfo->szOldEntryName,
 | 
						|
                pEinfo->pEntry->pszEntryName ) != 0);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
DWORD
 | 
						|
EuInit0(
 | 
						|
    IN  TCHAR*       pszPhonebook,
 | 
						|
    IN  TCHAR*       pszEntry,
 | 
						|
    IN  RASENTRYDLG* pArgs,
 | 
						|
    OUT EINFO*       pInfo,
 | 
						|
    OUT DWORD*       pdwOp )
 | 
						|
 | 
						|
    /* Initializes 'pInfo' data just enough so the user preferences are
 | 
						|
    ** available and it can be safely EuFree()ed, for use by the property
 | 
						|
    ** sheet or wizard.  'PszPhonebook', 'pszEntry', and 'pArgs', are the
 | 
						|
    ** arguments passed by user to the API.  '*pdwOp' is set to the operation
 | 
						|
    ** code associated with any error.
 | 
						|
    **
 | 
						|
    ** See EuInit.
 | 
						|
    **
 | 
						|
    ** Returns 0 if successful or an error code.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD dwErr;
 | 
						|
 | 
						|
    *pdwOp = 0;
 | 
						|
 | 
						|
    ZeroMemory( pInfo, sizeof(*pInfo ) );
 | 
						|
    pInfo->pszPhonebook = pszPhonebook;
 | 
						|
    pInfo->pszEntry = pszEntry;
 | 
						|
    pInfo->pApiArgs = pArgs;
 | 
						|
    pInfo->fRouter = RasRpcDllLoaded();
 | 
						|
    if (pInfo->fRouter)
 | 
						|
        pInfo->pszRouter = StrDupTFromW(g_wszServer);
 | 
						|
 | 
						|
    /* Load the user preferences, or figure out that caller has already loaded
 | 
						|
    ** them.
 | 
						|
    */
 | 
						|
    if (pArgs->reserved)
 | 
						|
    {
 | 
						|
        INTERNALARGS* piargs;
 | 
						|
 | 
						|
        /* We've received user preferences and the "no user" status via the
 | 
						|
        ** secret hack.
 | 
						|
        */
 | 
						|
        piargs = (INTERNALARGS* )pArgs->reserved;
 | 
						|
        pInfo->pUser = piargs->pUser;
 | 
						|
        pInfo->fNoUser = piargs->fNoUser;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        /* Read user preferences from registry.
 | 
						|
        */
 | 
						|
        dwErr = g_pGetUserPreferences(
 | 
						|
            &pInfo->user, (pInfo->fRouter) ? UPM_Router : UPM_Normal );
 | 
						|
        if (dwErr != 0)
 | 
						|
        {
 | 
						|
            *pdwOp = SID_OP_LoadPrefs;
 | 
						|
            return dwErr;
 | 
						|
        }
 | 
						|
 | 
						|
        pInfo->pUser = &pInfo->user;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
DWORD
 | 
						|
EuInit(
 | 
						|
    OUT EINFO* pInfo,
 | 
						|
    OUT DWORD* pdwOp )
 | 
						|
 | 
						|
    /* Initializes 'pInfo' data for use by the property sheet or wizard.
 | 
						|
    ** 'PszPhonebook', 'pszEntry', and 'pArgs', are the arguments passed by
 | 
						|
    ** user to the API.  '*pdwOp' is set to the operation code associated with
 | 
						|
    ** any error.
 | 
						|
    **
 | 
						|
    ** Assumes EuInit0 has been previously called.
 | 
						|
    **
 | 
						|
    ** Returns 0 if successful, or an error code.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DWORD    dwErr;
 | 
						|
    DTLLIST* pListPorts;
 | 
						|
 | 
						|
    *pdwOp = 0;
 | 
						|
 | 
						|
    /* Load the phonebook file or figure out that caller already loaded it.
 | 
						|
    */
 | 
						|
    if (pInfo->pApiArgs->reserved)
 | 
						|
    {
 | 
						|
        INTERNALARGS* piargs;
 | 
						|
 | 
						|
        /* We've received an open phonebook file, user preferences, and
 | 
						|
        ** possibly user-less information via the secret hack.
 | 
						|
        */
 | 
						|
        piargs = (INTERNALARGS* )pInfo->pApiArgs->reserved;
 | 
						|
        pInfo->pFile = piargs->pFile;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        /* Load and parse the phonebook file.
 | 
						|
        */
 | 
						|
        dwErr = ReadPhonebookFile(
 | 
						|
            pInfo->pszPhonebook, &pInfo->user, NULL,
 | 
						|
            (pInfo->fRouter) ? RPBF_Router : 0,
 | 
						|
            &pInfo->file );
 | 
						|
        if (dwErr != 0)
 | 
						|
        {
 | 
						|
            *pdwOp = SID_OP_LoadPhonebook;
 | 
						|
            return dwErr;
 | 
						|
        }
 | 
						|
 | 
						|
        pInfo->pFile = &pInfo->file;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Load the list of ports.
 | 
						|
    */
 | 
						|
    dwErr = LoadPortsList2( &pListPorts, pInfo->fRouter );
 | 
						|
    if (dwErr != 0)
 | 
						|
    {
 | 
						|
        TRACE1("LoadPortsList=%d",dwErr);
 | 
						|
        *pdwOp = SID_OP_RetrievingData;
 | 
						|
        return dwErr;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DtlGetNodes( pListPorts ) <= 0)
 | 
						|
        pInfo->fNoPortsConfigured = TRUE;
 | 
						|
 | 
						|
    /* Set up work entry node.
 | 
						|
    */
 | 
						|
    if (pInfo->pApiArgs->dwFlags & RASEDFLAG_NewEntry)
 | 
						|
    {
 | 
						|
        DTLNODE* pNodeL;
 | 
						|
        DTLNODE* pNodeP;
 | 
						|
        PBLINK*  pLink;
 | 
						|
        PBPORT*  pPort;
 | 
						|
 | 
						|
        /* New entry mode, so 'pNode' set to default settings.
 | 
						|
        */
 | 
						|
        pInfo->pNode = CreateEntryNode( TRUE );
 | 
						|
        if (!pInfo->pNode)
 | 
						|
        {
 | 
						|
            TRACE("CreateEntryNode failed");
 | 
						|
            *pdwOp = SID_OP_RetrievingData;
 | 
						|
            return dwErr;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Store entry within work node stored in context for convenience
 | 
						|
        ** elsewhere.
 | 
						|
        */
 | 
						|
        pInfo->pEntry = (PBENTRY* )DtlGetData( pInfo->pNode );
 | 
						|
        ASSERT(pInfo->pEntry);
 | 
						|
 | 
						|
        if (pInfo->fRouter)
 | 
						|
        {
 | 
						|
            /* Set router specific defaults.
 | 
						|
            */
 | 
						|
            pInfo->pEntry->dwIpNameSource = ASRC_None;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Use caller's last choice for area and country code.
 | 
						|
        */
 | 
						|
        if (pInfo->pUser->fUseAreaAndCountry)
 | 
						|
            pInfo->pEntry->fUseCountryAndAreaCode = TRUE;
 | 
						|
 | 
						|
        /* Use caller's default name, if any.
 | 
						|
        */
 | 
						|
        if (pInfo->pszEntry)
 | 
						|
            pInfo->pEntry->pszEntryName = StrDup( pInfo->pszEntry );
 | 
						|
 | 
						|
        /* Set an appropriate default device.
 | 
						|
        */
 | 
						|
        pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
 | 
						|
        ASSERT(pNodeL);
 | 
						|
        pLink = (PBLINK* )DtlGetData( pNodeL );
 | 
						|
        ASSERT(pLink);
 | 
						|
 | 
						|
        pNodeP = DtlGetFirstNode( pListPorts );
 | 
						|
        if (!pNodeP)
 | 
						|
        {
 | 
						|
            TRACE("No ports configured");
 | 
						|
            pNodeP = CreatePortNode();
 | 
						|
        }
 | 
						|
 | 
						|
        if (pNodeP)
 | 
						|
        {
 | 
						|
            pPort = (PBPORT* )DtlGetData( pNodeP );
 | 
						|
 | 
						|
            if (pInfo->fNoPortsConfigured)
 | 
						|
            {
 | 
						|
                /* Make up a bogus COM port with unknown Unimodem attached.
 | 
						|
                ** Hereafter, this will behave like an entry whose modem has
 | 
						|
                ** been de-installed.
 | 
						|
                */
 | 
						|
                pPort->pszPort = PszFromId( g_hinstDll, SID_DefaultPort );
 | 
						|
                pPort->fConfigured = FALSE;
 | 
						|
                pPort->pszMedia = StrDup( TEXT(SERIAL_TXT) );
 | 
						|
                pPort->pbdevicetype = PBDT_Modem;
 | 
						|
            }
 | 
						|
 | 
						|
            CopyToPbport( &pLink->pbport, pPort );
 | 
						|
            if (pLink->pbport.pbdevicetype == PBDT_Modem)
 | 
						|
                SetDefaultModemSettings( pLink );
 | 
						|
        }
 | 
						|
 | 
						|
        if (!pNodeP || !pLink->pbport.pszPort || !pLink->pbport.pszMedia)
 | 
						|
        {
 | 
						|
            *pdwOp = SID_OP_RetrievingData;
 | 
						|
            return ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        DTLNODE* pNode;
 | 
						|
 | 
						|
        /* Edit or clone entry mode, so 'pNode' set to entry's current
 | 
						|
        ** settings.
 | 
						|
        */
 | 
						|
        pInfo->pOldNode = EntryNodeFromName(
 | 
						|
            pInfo->pFile->pdtllistEntries, pInfo->pszEntry );
 | 
						|
 | 
						|
        if (!pInfo->pOldNode)
 | 
						|
        {
 | 
						|
            *pdwOp = SID_OP_RetrievingData;
 | 
						|
            return ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
 | 
						|
        }
 | 
						|
 | 
						|
        if (pInfo->pApiArgs->dwFlags & RASEDFLAG_CloneEntry)
 | 
						|
            pInfo->pNode = CloneEntryNode( pInfo->pOldNode );
 | 
						|
        else
 | 
						|
            pInfo->pNode = DuplicateEntryNode( pInfo->pOldNode );
 | 
						|
        if (!pInfo->pNode)
 | 
						|
        {
 | 
						|
            TRACE("DuplicateEntryNode failed");
 | 
						|
            *pdwOp = SID_OP_RetrievingData;
 | 
						|
            return ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Store entry within work node stored in context for convenience
 | 
						|
        ** elsewhere.
 | 
						|
        */
 | 
						|
        pInfo->pEntry = (PBENTRY* )DtlGetData( pInfo->pNode );
 | 
						|
 | 
						|
        /* Save original entry name for comparison later.
 | 
						|
        */
 | 
						|
        lstrcpy( pInfo->szOldEntryName, pInfo->pEntry->pszEntryName );
 | 
						|
 | 
						|
        /* For router, want unconfigured ports to show up as "unavailable" so
 | 
						|
        ** they stand out to user who has been directed to change them.
 | 
						|
        */
 | 
						|
        if (pInfo->fRouter)
 | 
						|
        {
 | 
						|
            DTLNODE* pNodeL;
 | 
						|
            PBLINK* pLink;
 | 
						|
 | 
						|
            pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
 | 
						|
            pLink = (PBLINK* )DtlGetData( pNodeL );
 | 
						|
 | 
						|
            if (!pLink->pbport.fConfigured)
 | 
						|
            {
 | 
						|
                Free0( pLink->pbport.pszDevice );
 | 
						|
                pLink->pbport.pszDevice = NULL;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Append links containing all remaining configured ports to the list of
 | 
						|
    ** links with the new links marked "unenabled".  This lets us make the
 | 
						|
    ** port<->port and single-link<->multi-link transitions behave more as
 | 
						|
    ** user expects.
 | 
						|
    */
 | 
						|
    {
 | 
						|
        DTLNODE* pNodeP;
 | 
						|
        DTLNODE* pNodeL;
 | 
						|
 | 
						|
        for (pNodeP = DtlGetFirstNode( pListPorts );
 | 
						|
             pNodeP;
 | 
						|
             pNodeP = DtlGetNextNode( pNodeP ))
 | 
						|
        {
 | 
						|
            PBPORT* pPort;
 | 
						|
            BOOL    fPortUsed;
 | 
						|
 | 
						|
            pPort = (PBPORT* )DtlGetData( pNodeP );
 | 
						|
            fPortUsed = FALSE;
 | 
						|
 | 
						|
            for (pNodeL = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
 | 
						|
                 pNodeL;
 | 
						|
                 pNodeL = DtlGetNextNode( pNodeL ))
 | 
						|
            {
 | 
						|
                PBLINK* pLink = (PBLINK* )DtlGetData( pNodeL );
 | 
						|
 | 
						|
                ASSERT( pPort->pszPort );
 | 
						|
                ASSERT( pLink->pbport.pszPort );
 | 
						|
 | 
						|
                if (lstrcmp( pLink->pbport.pszPort, pPort->pszPort ) == 0)
 | 
						|
                {
 | 
						|
                    fPortUsed = TRUE;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (!fPortUsed)
 | 
						|
            {
 | 
						|
                DTLNODE* pNode;
 | 
						|
 | 
						|
                pNode = CreateLinkNode();
 | 
						|
                if (pNode)
 | 
						|
                {
 | 
						|
                    PBLINK* pLink = (PBLINK* )DtlGetData( pNode );
 | 
						|
 | 
						|
                    if (CopyToPbport( &pLink->pbport, pPort ) != 0)
 | 
						|
                        DestroyLinkNode( pNode );
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        if (pPort->pbdevicetype == PBDT_Modem)
 | 
						|
                            SetDefaultModemSettings( pLink );
 | 
						|
 | 
						|
                        pLink->fEnabled = FALSE;
 | 
						|
                        DtlAddNodeLast( pInfo->pEntry->pdtllistLinks, pNode );
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    DtlDestroyList( pListPorts, DestroyPortNode );
 | 
						|
 | 
						|
    if (pInfo->fRouter)
 | 
						|
    {
 | 
						|
        pInfo->pEntry->dwfExcludedProtocols |= NP_Nbf;
 | 
						|
        pInfo->pEntry->fIpPrioritizeRemote = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuLbCountryCodeSelChange(
 | 
						|
    IN EINFO* pEinfo,
 | 
						|
    IN HWND   hwndLbCountryCodes )
 | 
						|
 | 
						|
    /* Called when the country list selection has changed.  'PEinfo' is the
 | 
						|
    ** common entry context.  'HwndLbCountryCode' is the country code
 | 
						|
    ** combobox.
 | 
						|
    */
 | 
						|
{
 | 
						|
    LONG lSign;
 | 
						|
    LONG i;
 | 
						|
 | 
						|
    TRACE("EuLbCountryCodeSelChange");
 | 
						|
 | 
						|
    /* Make sure all the country codes are loaded.  When a partial list is
 | 
						|
    ** there are dummy entries placed before and after the single country
 | 
						|
    ** code.  This allows us to give transparent behavior when user presses
 | 
						|
    ** left/right arrows to change selection.
 | 
						|
    */
 | 
						|
    lSign =
 | 
						|
        (LONG )ComboBox_GetItemData( hwndLbCountryCodes,
 | 
						|
                   ComboBox_GetCurSel( hwndLbCountryCodes ) );
 | 
						|
 | 
						|
    if (lSign != -1 && lSign != 1)
 | 
						|
        lSign = 0;
 | 
						|
 | 
						|
    EuFillCountryCodeList( pEinfo, hwndLbCountryCodes, TRUE );
 | 
						|
 | 
						|
    i = (LONG )ComboBox_GetCurSel( hwndLbCountryCodes );
 | 
						|
    if (ComboBox_SetCurSel( hwndLbCountryCodes, i + lSign ) < 0)
 | 
						|
        ComboBox_SetCurSel( hwndLbCountryCodes, i );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
DWORD
 | 
						|
EuLoadScpScriptsList(
 | 
						|
    OUT DTLLIST** ppList )
 | 
						|
 | 
						|
    /* Loads '*ppList' with a list of Psz nodes containing the pathnames of
 | 
						|
    ** the .SCP files in the RAS directory.  It is caller's responsibility to
 | 
						|
    ** call DtlDestroyList on the returned list.
 | 
						|
    **
 | 
						|
    ** Returns 0 if successful or an error code.
 | 
						|
    */
 | 
						|
{
 | 
						|
    UINT            cch;
 | 
						|
    TCHAR           szPath[ MAX_PATH ];
 | 
						|
    TCHAR*          pszFile;
 | 
						|
    WIN32_FIND_DATA data;
 | 
						|
    HANDLE          h;
 | 
						|
    DTLLIST*        pList;
 | 
						|
 | 
						|
    cch = g_pGetSystemDirectory( szPath, MAX_PATH );
 | 
						|
    if (cch == 0)
 | 
						|
        return GetLastError();
 | 
						|
 | 
						|
    pList = DtlCreateList( 0L );
 | 
						|
    if (!pList)
 | 
						|
        return ERROR_NOT_ENOUGH_MEMORY;
 | 
						|
 | 
						|
    lstrcat( szPath, TEXT("\\ras\\*.scp") );
 | 
						|
 | 
						|
    h = FindFirstFile( szPath, &data );
 | 
						|
    if (h != INVALID_HANDLE_VALUE)
 | 
						|
    {
 | 
						|
        /* Find the address of the file name part of the path since the 'data'
 | 
						|
        ** provides only the filename and not the rest of the path.
 | 
						|
        */
 | 
						|
        pszFile = szPath + lstrlen( szPath ) - 5;
 | 
						|
 | 
						|
        do
 | 
						|
        {
 | 
						|
            DTLNODE* pNode;
 | 
						|
 | 
						|
            /* Ignore any directories that happen to match.
 | 
						|
            */
 | 
						|
            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 | 
						|
                continue;
 | 
						|
 | 
						|
            /* Create a Psz node with the path to the found file and append it
 | 
						|
            ** to the end of the list.
 | 
						|
            */
 | 
						|
            lstrcpy( pszFile, data.cFileName );
 | 
						|
            pNode = CreatePszNode( szPath );
 | 
						|
            if (!pNode)
 | 
						|
                continue;
 | 
						|
            DtlAddNodeLast( pList, pNode );
 | 
						|
        }
 | 
						|
        while (FindNextFile( h, &data ));
 | 
						|
 | 
						|
        FindClose( h );
 | 
						|
    }
 | 
						|
 | 
						|
    *ppList = pList;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuPhoneNumberStashFromEntry(
 | 
						|
    IN     EINFO*    pEinfo,
 | 
						|
    IN OUT DTLLIST** ppListPhoneNumbers,
 | 
						|
    OUT    BOOL*     pfPromoteHuntNumbers )
 | 
						|
 | 
						|
    /* Replace single link stashed phone number settings with first link
 | 
						|
    ** versions.  'PEinfo' is the common entry context.  '*ppListPhoneNumbers'
 | 
						|
    ** is the current stash phone number list or NULL if none.
 | 
						|
    ** 'PfPromoteHuntNumber' receives the "promote hunt number" flag.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DTLLIST* pList;
 | 
						|
    DTLNODE* pNode;
 | 
						|
    PBLINK*  pLink;
 | 
						|
 | 
						|
    TRACE("EuPhoneNumberStashFromEntry");
 | 
						|
 | 
						|
    pNode = DtlGetFirstNode( pEinfo->pEntry->pdtllistLinks );
 | 
						|
    ASSERT(pNode);
 | 
						|
    pLink = (PBLINK* )DtlGetData( pNode );
 | 
						|
    ASSERT(pLink);
 | 
						|
    ASSERT(pLink->pdtllistPhoneNumbers);
 | 
						|
    pList = DtlDuplicateList( pLink->pdtllistPhoneNumbers,
 | 
						|
        DuplicatePszNode, DestroyPszNode );
 | 
						|
    if (pList)
 | 
						|
    {
 | 
						|
        DtlDestroyList( *ppListPhoneNumbers, DestroyPszNode );
 | 
						|
        *ppListPhoneNumbers = pList;
 | 
						|
    }
 | 
						|
    *pfPromoteHuntNumbers = pLink->fPromoteHuntNumbers;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuPhoneNumberStashToEntry(
 | 
						|
    IN EINFO*   pEinfo,
 | 
						|
    IN DTLLIST* pListPhoneNumbers,
 | 
						|
    IN BOOL     fPromoteHuntNumbers,
 | 
						|
    IN BOOL     fAllEnabled )
 | 
						|
 | 
						|
    /* Replace first link, or all enabled links if 'fAllEnabled' is set, phone
 | 
						|
    ** number settings with the single link stash versions.  'PEinfo' is the
 | 
						|
    ** common entry context.  'PListPhoneNumbers' is the current stash list.
 | 
						|
    ** 'fPromoteHuntNumbers' is the current "promote hunt number" flag.
 | 
						|
    */
 | 
						|
{
 | 
						|
    DTLLIST* pList;
 | 
						|
    DTLNODE* pNode;
 | 
						|
    PBLINK*  pLink;
 | 
						|
 | 
						|
    TRACE("EuPhoneNumberStashToEntry");
 | 
						|
 | 
						|
    for (pNode = DtlGetFirstNode( pEinfo->pEntry->pdtllistLinks );
 | 
						|
         pNode;
 | 
						|
         pNode = DtlGetNextNode( pNode ))
 | 
						|
    {
 | 
						|
        pLink = (PBLINK* )DtlGetData( pNode );
 | 
						|
        ASSERT(pLink);
 | 
						|
        ASSERT(pListPhoneNumbers );
 | 
						|
 | 
						|
        if (fAllEnabled && !pLink->fEnabled)
 | 
						|
            continue;
 | 
						|
 | 
						|
        pList = DtlDuplicateList( pListPhoneNumbers,
 | 
						|
            DuplicatePszNode, DestroyPszNode );
 | 
						|
        if (pList)
 | 
						|
        {
 | 
						|
            DtlDestroyList( pLink->pdtllistPhoneNumbers, DestroyPszNode );
 | 
						|
            pLink->pdtllistPhoneNumbers = pList;
 | 
						|
        }
 | 
						|
        pLink->fPromoteHuntNumbers = fPromoteHuntNumbers;
 | 
						|
 | 
						|
        if (!fAllEnabled)
 | 
						|
            break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EuSaveCountryInfo(
 | 
						|
    IN EINFO* pEinfo,
 | 
						|
    IN HWND   hwndLbCountryCodes )
 | 
						|
 | 
						|
    /* Save the country code and ID from 'hwndLbCountryCodes' into the working
 | 
						|
    ** entry in common entry context 'pEinfo'.
 | 
						|
    */
 | 
						|
{
 | 
						|
    if (pEinfo->pCountries)
 | 
						|
    {
 | 
						|
        COUNTRY* pCountry;
 | 
						|
        INT      iSel;
 | 
						|
 | 
						|
        iSel = ComboBox_GetCurSel( hwndLbCountryCodes );
 | 
						|
        if (iSel < 0)
 | 
						|
            return;
 | 
						|
 | 
						|
        pCountry = (COUNTRY* )ComboBox_GetItemDataPtr(
 | 
						|
            hwndLbCountryCodes, iSel );
 | 
						|
 | 
						|
        ASSERT(pCountry);
 | 
						|
        pEinfo->pEntry->dwCountryID = pCountry->dwId;
 | 
						|
        pEinfo->pEntry->dwCountryCode = pCountry->dwCode;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
BOOL
 | 
						|
EuValidateAreaCode(
 | 
						|
    IN HWND   hwndOwner,
 | 
						|
    IN EINFO* pEinfo )
 | 
						|
 | 
						|
    /* Validates the area code in the working buffer popping up a message if
 | 
						|
    ** invalid.  'HwndOwner' is the window that owns the popup message, if
 | 
						|
    ** any.  'PEinfo' is the common entry context.
 | 
						|
    **
 | 
						|
    ** Returns true if valid, false if not.
 | 
						|
    */
 | 
						|
{
 | 
						|
    if (!ValidateAreaCode( pEinfo->pEntry->pszAreaCode ))
 | 
						|
    {
 | 
						|
        /* Invalid area code.  If it's disabled anyway, just silently lose it.
 | 
						|
        */
 | 
						|
        if (pEinfo->pEntry->fUseCountryAndAreaCode)
 | 
						|
        {
 | 
						|
            MsgDlg( hwndOwner, SID_BadAreaCode, NULL );
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
        else
 | 
						|
            *pEinfo->pEntry->pszAreaCode = TEXT('\0');
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
BOOL
 | 
						|
EuValidateName(
 | 
						|
    IN HWND   hwndOwner,
 | 
						|
    IN EINFO* pEinfo )
 | 
						|
 | 
						|
    /* Validates the working entry name and pops up a message if invalid.
 | 
						|
    ** 'HwndOwner' is the window to own the error popup.  'PEinfo' is the
 | 
						|
    ** common dialog context containing the name to validate.
 | 
						|
    **
 | 
						|
    ** Returns true if the name is valid, false if not.
 | 
						|
    */
 | 
						|
{
 | 
						|
    PBENTRY* pEntry;
 | 
						|
    BOOL     fEditMode;
 | 
						|
    BOOL     fChangedNameInEditMode;
 | 
						|
 | 
						|
    pEntry = pEinfo->pEntry;
 | 
						|
 | 
						|
    /* Validate the sheet data.
 | 
						|
    */
 | 
						|
    if (!ValidateEntryName( pEinfo->pEntry->pszEntryName ))
 | 
						|
    {
 | 
						|
        /* Invalid entry name.
 | 
						|
        */
 | 
						|
        MsgDlg( hwndOwner, SID_BadEntry, NULL );
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    EuGetEditFlags( pEinfo, &fEditMode, &fChangedNameInEditMode );
 | 
						|
 | 
						|
    if ((fChangedNameInEditMode || !fEditMode)
 | 
						|
        && EntryNodeFromName(
 | 
						|
               pEinfo->pFile->pdtllistEntries, pEntry->pszEntryName ))
 | 
						|
    {
 | 
						|
        /* Duplicate entry name.
 | 
						|
        */
 | 
						|
        MSGARGS msgargs;
 | 
						|
        ZeroMemory( &msgargs, sizeof(msgargs) );
 | 
						|
        msgargs.apszArgs[ 0 ] = pEntry->pszEntryName;
 | 
						|
        MsgDlg( hwndOwner, SID_DuplicateEntry, &msgargs );
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 |