|
|
// Copyright (c) 1995, Microsoft Corporation, all rights reserved
//
// dial.c
// Remote Access Common Dialog APIs
// RasDialDlg APIs
//
// 11/19/95 Steve Cobb
#include "rasdlgp.h"
#include "raseapif.h"
#include "inetcfgp.h"
#include "netconp.h"
#include "pref.h"
// Posted message codes for tasks that should not or cannot occur in the
// RasDial callback.
//
#define WM_RASEVENT 0xCCCC
#define WM_RASERROR 0xCCCD
#define WM_RASDIAL 0xCCCE
#define WM_RASBUNDLEERROR 0xCCCF
#define WM_DPENDDIALOG 0xCCD0
// Dialer dialog mode bits
//
#define DR_U 0x00000001 // Username and password present
#define DR_D 0x00000002 // Domain present
#define DR_N 0x00000004 // Phone number present
#define DR_L 0x00000008 // Location controls present
#define DR_I 0x00000010 // Eap identity dialog
// For whistler bug 500731
#define DR_B 0x00000020 // No User name No Password(Basic)Eap dialog
// Internal constants used by DrXxx routines to implement the "manual edit"
// combo-box.
//
#define DR_WM_SETTEXT 0xCCC0
#define DR_BOGUSWIDTH 19591
#define EAP_RASTLS 13
// For whistler 460931 459793 gangz
extern BOOL WINAPI LinkWindow_RegisterClass();
//----------------------------------------------------------------------------
// Help maps
//----------------------------------------------------------------------------
static DWORD g_adwDrHelp[] = { CID_DR_BM_Useless, HID_DR_BM_Useless, CID_DR_ST_User, HID_DR_EB_User, CID_DR_EB_User, HID_DR_EB_User, CID_DR_ST_Password, HID_DR_EB_Password, CID_DR_EB_Password, HID_DR_EB_Password, CID_DR_ST_Domain, HID_DR_EB_Domain, CID_DR_EB_Domain, HID_DR_EB_Domain, CID_DR_CB_SavePassword, HID_DR_CB_SavePassword, CID_DR_ST_Numbers, HID_DR_CLB_Numbers, CID_DR_CLB_Numbers, HID_DR_CLB_Numbers, CID_DR_ST_Locations, HID_DR_LB_Locations, CID_DR_LB_Locations, HID_DR_LB_Locations, CID_DR_PB_Rules, HID_DR_PB_Rules, CID_DR_PB_Properties, HID_DR_PB_Properties, CID_DR_PB_DialConnect, HID_DR_PB_DialConnect, CID_DR_PB_Cancel, HID_DR_PB_Cancel, CID_DR_PB_Help, HID_DR_PB_Help, CID_DR_RB_SaveForMe, HID_DR_RB_SaveForMe, CID_DR_RB_SaveForEveryone, HID_DR_RB_SaveForEveryone, 0, 0 };
static DWORD g_adwCpHelp[] = { CID_CP_ST_Explain, HID_CP_ST_Explain, CID_CP_ST_OldPassword, HID_CP_EB_OldPassword, CID_CP_EB_OldPassword, HID_CP_EB_OldPassword, CID_CP_ST_Password, HID_CP_EB_Password, CID_CP_EB_Password, HID_CP_EB_Password, CID_CP_ST_ConfirmPassword, HID_CP_EB_ConfirmPassword, CID_CP_EB_ConfirmPassword, HID_CP_EB_ConfirmPassword, 0, 0 };
static DWORD g_adwDcHelp[] = { CID_DC_ST_Explain, HID_DC_ST_Explain, CID_DC_ST_Number, HID_DC_EB_Number, CID_DC_EB_Number, HID_DC_EB_Number, 0, 0 };
static DWORD g_adwDeHelp[] = { CID_DE_CB_EnableDiag, HID_DE_CB_EnableDiag, CID_DE_ST_ConfigureLnk, HID_DE_ST_ConfigureLnk, CID_DE_PB_More, HID_DE_PB_More, IDOK, HID_DE_PB_Redial, 0, 0 };
static DWORD g_adwPrHelp[] = { CID_PR_ST_Text, HID_PR_ST_Text, CID_PR_CB_DisableProtocols, CID_PR_CB_DisableProtocols, IDOK, HID_PR_PB_Accept, IDCANCEL, HID_PR_PB_HangUp, 0, 0 };
static DWORD g_adwUaHelp[] = { CID_UA_ST_UserName, HID_UA_EB_UserName, CID_UA_EB_UserName, HID_UA_EB_UserName, CID_UA_ST_Password, HID_UA_EB_Password, CID_UA_EB_Password, HID_UA_EB_Password, CID_UA_ST_Domain, HID_UA_EB_Domain, CID_UA_EB_Domain, HID_UA_EB_Domain, CID_UA_CB_SavePassword, HID_UA_CB_SavePassword, 0, 0 };
CONST WCHAR g_pszSavedPasswordToken[] = L"****************"; #define g_dwSavedPasswordTokenLength \
( sizeof(g_pszSavedPasswordToken) / sizeof(TCHAR) )
// Save password macro, determines if either User or Global password is saved
// (p) must be a pointer to a DINFO struct (see dial.c)
//
// Whistler bug: 288234 When switching back and forth from "I connect" and
// "Any user connects" password is not caching correctly
//
#define HaveSavedPw(p) \
((p)->fHaveSavedPwUser || (p)->fHaveSavedPwGlobal)
//----------------------------------------------------------------------------
// Local datatypes
//----------------------------------------------------------------------------
// Dial dialogs common context block. This block contains information common
// to more than one dialog in the string of dial-related dialogs.
//
typedef struct _DINFO { // Caller's arguments to the RAS API. Outputs in 'pArgs' are visible to
// the API which has the address of same. Careful using 'pszEntry' as
// 'pEntry->pszEntryName' is generally more appropriate, the latter
// reflecting the name of any prerequisite entry while the prequisite is
// being dialed.
//
LPTSTR pszPhonebook; LPTSTR pszEntry; LPTSTR pszPhoneNumber; RASDIALDLG* pArgs;
// Phonebook settings read from the phonebook file. All access should be
// thru 'pFile'. 'PFile' is set to either '&filePrereq' or 'pFileMain'
// depending on 'fFilePrereqOpen'. 'File' will only be used in cases
// where the open phonebook is not passed thru the reserved word hack, and
// in that case 'pFileMain' will point to it. 'FilePrereq' is the
// phonebook file of the prequisite entry which may be different from the
// main entry. During prerequisite dial 'pFile' points to 'filePrereq'
// rather than 'file' and 'fFilePrereqOpen is true. Otherwise, 'pFile'
// points to whatever 'pFileMain' points at.
//
PBFILE* pFile; PBFILE* pFileMain; PBFILE file; PBFILE filePrereq; BOOL fFilePrereqOpen; BOOL fIsPublicPbk;
// Global preferences read via phonebook library. All access should be
// thru 'pUser' as 'user' will only be used in cases where the preferences
// are not passed thru the reserved word hack.
//
PBUSER* pUser; PBUSER user;
// User credentials provided by API caller for "during logon" dialing
// where there is no current user. If user changes the credentials
// *pfNoUserChanged is set and the 'pNoUser' credentials updated.
//
RASNOUSER* pNoUser; BOOL* pfNoUserChanged;
// Set if the call is unattended, i.e. a call by RASAUTO to redial a
// failed link.
//
BOOL fUnattended;
// Private flags from calling RAS API, the first informing us he wants to
// be hidden off the desktop while we dial, and the second that he will
// close if we return "connected" so we can avoid flicker and not bother
// restoring him.
//
BOOL fMoveOwnerOffDesktop; BOOL fForceCloseOnDial;
// Set when something occurs during dial that affects the phonebook entry.
// The entry is re-read after a successful connection.
//
BOOL fResetAutoLogon; DWORD dwfExcludedProtocols; DTLLIST* pListPortsToDelete;
// The entry node and a shortcut pointer to the entry inside.
//
DTLNODE* pNode; PBENTRY* pEntry;
// The entry of the main entry that referred to any prerequisite entry
// that might be contained by 'pEntry'. If no prerequisite entry is
// involved this is the same as 'pEntry'.
//
PBENTRY* pEntryMain;
// Set is admin has disabled the save password feature in the registry.
//
BOOL fDisableSavePw;
// Set true if a cached password is available for the entry.
//
BOOL fHaveSavedPwUser; // whether there are saved per-user creds
BOOL fHaveSavedPwGlobal; // whether there are saved per-connect creds
// Set when the dial in progress is the prerequisite entry, rather than
// the main entry.
//
BOOL fPrerequisiteDial;
// Set when calling RasDial on a connected entry to add a reference only.
// All interaction with user is skipped in this case. See bug 272794.
//
BOOL fDialForReferenceOnly;
// The dial parameters used on this connection attempt. Initialized in
// RasDialDlgW. Credentials are updated by DialerDlg. Callback number is
// updated by DialProgressDlg.
//
RASDIALPARAMS rdp; // actual dial parameters passed to RasDial
RASDIALPARAMS rdpu; // per-user credentials
RASDIALPARAMS rdpg; // per-connection credentials
// The dial parameter extensions used on this connection attempt. Set in
// RasDialDlgW, except hwndOwner which is set in DialProgressDlg.
//
RASDIALEXTENSIONS rde; } DINFO;
// Dialer dialogs argument block. Used for all 5 variations of the dialer.
//
typedef struct _DRARGS { DINFO* pDinfo; DWORD dwfMode; DWORD fReload; } DRARGS;
// Dialer dialogs context block. Used for all 5 variations of the dialer.
//
typedef struct DRINFO { // Common dial context information including the RAS API arguments.
//
DRARGS* pArgs;
// Handle of the dialog and some of it's controls.
//
HWND hwndDlg; HWND hwndEbUser; HWND hwndEbPw; HWND hwndEbDomain; HWND hwndCbSavePw; HWND hwndRbSaveForMe; HWND hwndRbSaveForEveryone; HWND hwndClbNumbers; HWND hwndStLocations; HWND hwndLbLocations; HWND hwndPbRules; HWND hwndPbProperties; HWND hwndBmDialer;
// Whistler bug: 195480 Dial-up connection dialog - Number of
// asterisks does not match the length of the password and causes
// confusion
//
WCHAR szPasswordChar; HFONT hNormalFont; HFONT hItalicFont;
// TAPI session handle.
//
HLINEAPP hlineapp;
// The phonebook entry link containing the displayed phone number list.
// Set up only when DR_N mode bit is set.
//
DTLNODE* pLinkNode; PBLINK* pLink;
// The index of the item initially selected in the phone number list.
//
DWORD iFirstSelectedPhone;
// Window handles and original window procedure of the subclassed
// 'hwndClbNumbers' control's edit-box and list-box child windows.
//
HWND hwndClbNumbersEb; HWND hwndClbNumbersLb; WNDPROC wndprocClbNumbersEb; WNDPROC wndprocClbNumbersLb; INetConnectionUiUtilities * pNetConUtilities;
// Set if COM has been initialized (necessary for calls to netshell).
//
BOOL fComInitialized;
// Handle to the original bitmap for the dialer if it is modified
// in DrSetBitmap
//
HBITMAP hbmOrig; } DRINFO;
// Context of an item in the dialer's 'ClbNumbers' list.
//
typedef struct _DRNUMBERSITEM { TCHAR* pszNumber; PBPHONE* pPhone; } DRNUMBERSITEM;
// Subentry state information.
//
typedef struct _DPSTATE { RASCONNSTATE state; DWORD dwError; DWORD dwExtendedError; TCHAR szExtendedError[ NETBIOS_NAME_LEN + 1 ]; TCHAR* pszStatusArg; TCHAR* pszFormatArg; PBDEVICETYPE pbdt; DWORD sidState; DWORD sidFormatMsg; DWORD sidPrevState; BOOL fNotPreSwitch; HRASCONN hrasconnLink; } DPSTATE;
// Dial Progress dialog context block.
//
typedef struct _DPINFO { // When the block is valid contains the value 0xC0BBC0DE, otherwise 0.
// Used as a workaround until RasDial is fixed to stop calling
// RasDialFunc2 after being told not to, see bug 49469.
//
DWORD dwValid;
// RAS API arguments.
//
DINFO* pArgs;
// Handle of this dialog and some of it's controls.
//
HWND hwndDlg; HWND hwndStState;
// The saved username and password that authenticated but resulted in a
// change password event. If the change password operation fails these
// are restored to make the redial button work properly.
//
TCHAR* pszGoodUserName; TCHAR* pszGoodPassword;
// The handle to the RAS connection being initiated.
//
HRASCONN hrasconn;
// The original window proc we subclassed.
//
WNDPROC pOldWndProc;
// Number of auto-redials not yet attempted on the connection.
//
DWORD dwRedialAttemptsLeft;
// Array of RasDial states, one per subentry, set by DpRasDialFunc2 and
// used by DpRasDialEvent.
//
DPSTATE* pStates; DWORD cStates;
// The number of the most advanced subentry and the "latest" state it has
// reached. Note that certain states, like RASCS_AuthNotify, are
// revisited after reaching a "later" state. Such changes are ignored.
//
RASCONNSTATE state; DWORD dwSubEntry;
// UI thread, Call back function synchronization members
// for XPSP2 511810, .Net 668164, 668164 gangz
CRITICAL_SECTION * pcsActiveLock;
//Add a per-thread Terminate flag for whistler bug 277365,291613 gangz
//
// Flag indicating that RasDial callbacks are active. The callback
// context must not be destroyed when this flag is set. Access to this
// field is protected by g_csCallbacks, see Get/SetCallbackActive .
//
BOOL fCallbacksActive; BOOL fTerminateAsap;
//for whistler bug 381337
//
BOOL fCancelPressed; } DPINFO;
// Dial Error dialog argument block.
//
typedef struct _DEARGS { DINFO* pDinfo; // For whistler 474514
TCHAR* pszPhonebook; // For whistler 460931
TCHAR* pszEntry; DWORD dwError; DWORD sidState; TCHAR* pszStatusArg; DWORD sidFormatMsg; TCHAR* pszFormatArg; LONG lRedialCountdown; BOOL fPopupOnTop; } DEARGS;
// Dial Error dialog context block.
//
typedef struct _DEINFO { // Caller's arguments to the stub API.
//
DEARGS* pArgs;
// Handle of dialog and controls.
//
HWND hwndDlg; HWND hwndStText; HWND hwndPbRedial; HWND hwndPbCancel; HWND hwndPbMore;
// For whistler 460931 459793
//
DiagnosticInfo diagInfo; HWND hwndCbEnableDiagLog; HWND hwndStConfigureLnk; HWND hwndStEnableHelp; HWND hwndStLinkHelp;
// Number of seconds remaining in "Redial=x" countdown or -1 if inactive.
//
LONG lRedialCountdown; } DEINFO;
// Projection Result dialog argument block.
//
typedef struct _PRARGS { TCHAR* pszLines; BOOL* pfDisableFailedProtocols; } PRARGS;
// Change Password dialog argument block.
//
typedef struct _CPARGS { BOOL fOldPassword; TCHAR* pszOldPassword; TCHAR* pszNewPassword; } CPARGS;
// Change Password dialog context block.
// (unconventional name because CPINFO conflicts with a system header)
//
typedef struct _CPWINFO { // Caller's arguments to the stub API.
//
CPARGS* pArgs;
// Handle of dialog and controls.
//
HWND hwndDlg; HWND hwndEbOldPassword; HWND hwndEbNewPassword; HWND hwndEbNewPassword2; } CPWINFO;
// Retry Authentication dialog context block.
//
typedef struct UAINFO { // Commond dial context including original RAS API arguments.
//
DINFO* pArgs;
// Handle of this dialog and some of it's controls.
//
HWND hwndDlg; HWND hwndEbUserName; HWND hwndEbPassword; HWND hwndEbDomain; HWND hwndCbSavePw;
// Set when the password field contains a phony password in place of the
// "" one we don't really know.
//
BOOL fAutoLogonPassword;
// Set when the Domain field is present.
//
BOOL fDomain; } UAINFO;
//-----------------------------------------------------------------------------
// Local prototypes (alphabetically)
//-----------------------------------------------------------------------------
BOOL BeCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
INT_PTR CALLBACK BeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
VOID BeFillLvErrors( IN HWND hwndLv, IN DPINFO* pInfo );
TCHAR* BeGetErrorPsz( IN DWORD dwError );
BOOL BeInit( IN HWND hwndDlg, IN DPINFO* pArgs );
LVXDRAWINFO* BeLvErrorsCallback( IN HWND hwndLv, IN DWORD dwItem );
BOOL BundlingErrorsDlg( IN OUT DPINFO* pInfo );
BOOL ChangePasswordDlg( IN HWND hwndOwner, IN BOOL fOldPassword, OUT TCHAR* pszOldPassword, OUT TCHAR* pszNewPassword );
BOOL CpCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
INT_PTR CALLBACK CpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL CpInit( IN HWND hwndDlg, IN CPARGS* pArgs );
BOOL CcCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
INT_PTR CALLBACK CcDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL CcInit( IN HWND hwndDlg, IN DINFO* pInfo );
VOID ConnectCompleteDlg( IN HWND hwndOwner, IN DINFO* pInfo );
BOOL DcCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
INT_PTR CALLBACK DcDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL DcInit( IN HWND hwndDlg, IN TCHAR* pszNumber );
VOID DeAdjustPbRedial( IN DEINFO* pInfo );
BOOL DeCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
INT_PTR CALLBACK DeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
void DeEnableDiagnostic( IN HWND hwnd );
BOOL DeInit( IN HWND hwndDlg, IN DEARGS* pArgs );
DWORD DeleteSavedCredentials( IN DINFO* pDinfo, IN HWND hwndDlg, IN BOOL fDefault, IN BOOL fDeleteIdentity );
VOID DeTerm( IN HWND hwndDlg );
BOOL DialCallbackDlg( IN HWND hwndOwner, IN OUT TCHAR* pszNumber );
BOOL DialErrorDlg( IN HWND hwndOwner, IN DINFO * pDinfo, // For whistler bug 474514
IN TCHAR* pszPhonebook, // For whistler 460931
IN TCHAR* pszEntry, IN DWORD dwError, IN DWORD sidState, IN TCHAR* pszStatusArg, IN DWORD sidFormatMsg, IN TCHAR* pszFormatArg, IN LONG lRedialCountdown, IN BOOL fPopupOnTop );
BOOL DialerDlg( IN HWND hwndOwner, IN OUT DINFO* pInfo );
BOOL DialProgressDlg( IN DINFO* pInfo );
VOID DpAppendBlankLine( IN OUT TCHAR* pszLines );
VOID DpAppendConnectErrorLine( IN OUT TCHAR* pszLines, IN DWORD sidProtocol, IN DWORD dwError );
VOID DpAppendConnectOkLine( IN OUT TCHAR* pszLines, IN DWORD sidProtocol );
VOID DpAppendFailCodeLine( IN OUT TCHAR* pszLines, IN DWORD dw );
VOID DpAppendNameLine( IN OUT TCHAR* pszLines, IN TCHAR* psz );
VOID DpAuthNotify( IN DPINFO* pInfo, IN DPSTATE* pState );
VOID DpCallbackSetByCaller( IN DPINFO* pInfo, IN DPSTATE* pState );
VOID DpCancel( IN DPINFO* pInfo );
BOOL DpCommand( IN DPINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
VOID DpConnectDevice( IN DPINFO* pInfo, IN DPSTATE* pState );
VOID DpDeviceConnected( IN DPINFO* pInfo, IN DPSTATE* pState );
VOID DpDial( IN DPINFO* pInfo, IN BOOL fPauseRestart );
INT_PTR CALLBACK DpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
//For whistler 435725
void DpEndDialog( IN DPINFO * pInfo, IN BOOL fFlag);
VOID DpError( IN DPINFO* pInfo, IN DPSTATE* pState );
DWORD DpEvent( IN DPINFO* pInfo, IN DWORD dwSubEntry );
BOOL DpInit( IN HWND hwndDlg, IN DINFO* pArgs );
VOID DpInitStates( DPINFO* pInfo );
BOOL DpInteractive( IN DPINFO* pInfo, IN DPSTATE* pState, OUT BOOL* pfChange );
BOOL DpIsLaterState( IN RASCONNSTATE stateNew, IN RASCONNSTATE stateOld );
BOOL DpPasswordExpired( IN DPINFO* pInfo, IN DPSTATE* pState );
BOOL DpProjected( IN DPINFO* pInfo, IN DPSTATE* pState );
BOOL DpProjectionError( IN RASPPPNBF* pnbf, IN RASPPPIPX* pipx, IN RASPPPIP* pip, OUT BOOL* pfIncomplete, OUT DWORD* pdwfFailedProtocols, OUT TCHAR** ppszLines, OUT DWORD* pdwError );
DWORD WINAPI DpRasDialFunc2( ULONG_PTR dwCallbackId, DWORD dwSubEntry, HRASCONN hrasconn, UINT unMsg, RASCONNSTATE state, DWORD dwError, DWORD dwExtendedError );
VOID DpTerm( IN HWND hwndDlg );
INT_PTR CALLBACK DrDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL CALLBACK DrClbNumbersEnumChildProc( IN HWND hwnd, IN LPARAM lparam );
BOOL CALLBACK DrClbNumbersEnumWindowsProc( IN HWND hwnd, IN LPARAM lparam );
BOOL DrCommand( IN DRINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
VOID DrEditSelectedLocation( IN DRINFO* pInfo );
DWORD DrFillLocationList( IN DRINFO* pInfo );
VOID DrFillNumbersList( IN DRINFO* pInfo );
DWORD DrFindAndSubclassClbNumbersControls( IN DRINFO* pInfo );
VOID DrFreeClbNumbers( IN DRINFO* pInfo );
BOOL DrInit( IN HWND hwndDlg, IN DRARGS* pArgs );
VOID DrLocationsSelChange( IN DRINFO* pInfo );
VOID DrNumbersSelChange( IN DRINFO* pInfo );
DWORD DrPopulateIdentificationFields( IN DRINFO* pInfo, IN BOOL fForMe);
DWORD DrPopulatePasswordField( IN DRINFO* pInfo, IN BOOL fInit, IN BOOL fDisable, OUT BOOL * pfUseDefaultFocus );
VOID DrProperties( IN DRINFO* pInfo );
VOID DrSave( IN DRINFO* pInfo );
DWORD DrSetBitmap( IN DRINFO* pInfo); VOID DrSetClbNumbersText( IN DRINFO* pInfo, IN TCHAR* pszText );
VOID DrTerm( IN HWND hwndDlg );
LRESULT APIENTRY DpWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam );
DWORD FindEntryAndSetDialParams( IN DINFO* pInfo );
BOOL GetTerminateFlag( IN DPINFO * pInfo);
BOOL SetTerminateFlag( IN DPINFO * pInfo);
BOOL ResetTerminateFlag( IN DPINFO * pInfo);
BOOL GetCallbackActive( IN DPINFO * pInfo);
BOOL SetCallbackActive( IN DPINFO * pInfo);
BOOL ResetCallbackActive( IN DPINFO * pInfo);
INT_PTR CALLBACK PrDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL PrCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
BOOL PrInit( IN HWND hwndDlg, IN PRARGS* pArgs );
BOOL ProjectionResultDlg( IN HWND hwndOwner, IN TCHAR* pszLines, OUT BOOL* pfDisableFailedProtocols );
BOOL RetryAuthenticationDlg( IN HWND hwndOwner, IN DINFO* pDinfo );
INT_PTR CALLBACK UaDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL UaCommand( IN UAINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
BOOL UaInit( IN HWND hwndDlg, IN DINFO* pArgs );
VOID UaSave( IN UAINFO* pInfo );
VOID UaTerm( IN HWND hwndDlg );
BOOL VpnDoubleDialDlg( IN HWND hwndOwner, IN DINFO* pInfo );
INT_PTR CALLBACK ViDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL ViCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
BOOL ViInit( IN HWND hwndDlg, IN DINFO* pInfo );
//-----------------------------------------------------------------------------
// External entry points
//-----------------------------------------------------------------------------
typedef struct EAPFREE_DATA { BOOL bInitialized; HINSTANCE hLib; RASEAPFREE pFreeFunc; } EAPFREE_DATA;
//Add those OutputDebug_XXXX() functions for debug use when debugging 291613
// gangz
//
void OutputDebug_DWCODE(DWORD dwCode) { WCHAR tmpBuf[100];
wsprintf(tmpBuf, L"The dwCode returned is %x\n", dwCode); OutputDebugStringW(tmpBuf); }
void OutputDebug_NumOfCallbacksActive(ULONG ulCallbacksActive) { WCHAR tmpBuf[100];
wsprintf(tmpBuf, L"Current CallbacksActive is %x\n", ulCallbacksActive); OutputDebugStringW(tmpBuf); }
void OutputDebug_ThreadId() { DWORD dwId; WCHAR tmpBuf[100];
dwId = GetCurrentThreadId(); wsprintf(tmpBuf, L"Current Thread is %x\n", dwId); OutputDebugStringW(tmpBuf); }
void OutputDebug_ProcessThreadId() { DWORD dwIdProc, dwIdThread; WCHAR tmpBuf[100];
dwIdProc = GetCurrentProcessId(); dwIdThread = GetCurrentThreadId(); wsprintf(tmpBuf, L"Current Proc is: %x , Thread is: %x\n", dwIdProc, dwIdThread); OutputDebugStringW(tmpBuf); }
//
// Raises the appriate eap indentity dialog
//
DWORD DialerDlgEap ( IN HWND hwndOwner, IN PWCHAR lpszPhonebook, IN PWCHAR lpszEntry, IN PBENTRY * pEntry, IN DINFO *pInfo, OUT PBYTE * ppUserDataOut, OUT DWORD * lpdwSizeOfUserDataOut, OUT LPWSTR * lplpwszIdentity, OUT PHANDLE phFree ) { DWORD dwErr = NO_ERROR, dwInSize = 0; PBYTE pbUserIn = NULL; HINSTANCE hLib = NULL; EAPFREE_DATA * pFreeData = NULL; DTLLIST * pListEaps = NULL; DTLNODE * pEapcfgNode = NULL; EAPCFG * pEapcfg = NULL; RASEAPFREE pFreeFunc = NULL; RASEAPGETIDENTITY pIdenFunc = NULL; DWORD dwFlags; DWORD cbData = 0; PBYTE pbData = NULL;
// Initialize the free data handle we'll return
pFreeData = Malloc ( sizeof(EAPFREE_DATA) ); if (pFreeData == NULL) return ERROR_NOT_ENOUGH_MEMORY; ZeroMemory( pFreeData, sizeof(EAPFREE_DATA) );
// Make sure we're configured with some list of
// eap configuration options
pListEaps = ReadEapcfgList( NULL ); if (pListEaps == NULL) { Free(pFreeData); return ERROR_CAN_NOT_COMPLETE; }
// for whistler 522872, use __leave instead of directly return in the __try
// ..__finally block
//
__try { // Find the eap node we're interested in
pEapcfgNode = EapcfgNodeFromKey( pListEaps, pEntry->dwCustomAuthKey ); if (pEapcfgNode) pEapcfg = (EAPCFG*)DtlGetData( pEapcfgNode ); else { dwErr = ERROR_CAN_NOT_COMPLETE; __leave; }
// Only call eap identity ui if we're told not to
// get the user name through the standard credentials
// dialog
if (pEapcfg->dwStdCredentialFlags & EAPCFG_FLAG_RequireUsername) { dwErr = NO_ERROR; __leave; }
if(!pInfo->pNoUser) { // Get the size of the input user data
dwErr = RasGetEapUserData( NULL, lpszPhonebook, lpszEntry, NULL, &dwInSize);
// Read in the user data
if (dwErr != NO_ERROR) { if (dwErr == ERROR_BUFFER_TOO_SMALL) { if (dwInSize == 0) { pbUserIn = NULL; // return ERROR_CAN_NOT_COMPLETE;
} else { // Allocate a blob to hold the data
pbUserIn = Malloc (dwInSize); if (pbUserIn == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; __leave; }
// Read in the new blob
dwErr = RasGetEapUserData( NULL, lpszPhonebook, lpszEntry, pbUserIn, &dwInSize); if (dwErr != NO_ERROR) { __leave; } } } else { __leave; } } } else { INTERNALARGS *piargs;
piargs = (INTERNALARGS *) pInfo->pArgs->reserved;
if( (NULL != piargs) && (NULL != piargs->pvEapInfo) // pmay: 386489
//
&& (pEntry->dwCustomAuthKey == EAPCFG_DefaultKey)) { pbUserIn = (BYTE *) piargs->pvEapInfo; dwInSize = ((EAPLOGONINFO *) piargs->pvEapInfo)->dwSize; } else { pbUserIn = NULL; dwInSize = 0; } }
// Load the identity library
hLib = LoadLibrary (pEapcfg->pszIdentityDll); if (hLib == NULL) { dwErr = GetLastError(); __leave; }
// Get pointers to the functions we'll be needing
pIdenFunc = (RASEAPGETIDENTITY) GetProcAddress(hLib, "RasEapGetIdentity"); pFreeFunc = (RASEAPFREE) GetProcAddress(hLib, "RasEapFreeMemory"); if ( (pFreeFunc == NULL) || (pIdenFunc == NULL) ) { dwErr = ERROR_CAN_NOT_COMPLETE; __leave; }
dwFlags = (pInfo->pNoUser) ? RAS_EAP_FLAG_LOGON : 0; if (!pEntry->fAutoLogon && pEntry->fPreviewUserPw) { dwFlags |= RAS_EAP_FLAG_PREVIEW; }
if(pInfo->fUnattended) { dwFlags &= ~RAS_EAP_FLAG_PREVIEW; } dwErr = DwGetCustomAuthData( pEntry, &cbData, &pbData);
if(ERROR_SUCCESS != dwErr) { __leave; }
// Call the eap-provided identity UI
dwErr = (*(pIdenFunc))( pEntry->dwCustomAuthKey, hwndOwner, dwFlags, lpszPhonebook, lpszEntry, pbData, cbData, pbUserIn, dwInSize, ppUserDataOut, lpdwSizeOfUserDataOut, lplpwszIdentity); if (dwErr != NO_ERROR) { __leave; }
// Assign the data used to cleanup later
pFreeData->bInitialized = TRUE; pFreeData->hLib = hLib; pFreeData->pFreeFunc = pFreeFunc; *phFree = (HANDLE)pFreeData; } __finally { if (pListEaps) { DtlDestroyList(pListEaps, NULL); } if ( (!pInfo->pNoUser) && (pbUserIn)) { Free0(pbUserIn); } if ((pFreeData) && (!pFreeData->bInitialized)) { Free(pFreeData); if(NULL != hLib) { FreeLibrary(hLib); } } }
return dwErr; }
DWORD DialerEapCleanup ( IN HANDLE hEapFree, IN PBYTE pUserDataOut, IN LPWSTR lpwszIdentity) { EAPFREE_DATA * pFreeData = (EAPFREE_DATA*)hEapFree;
if (pFreeData == NULL) return ERROR_INVALID_PARAMETER;
if (pFreeData->pFreeFunc) { if (pUserDataOut) (*(pFreeData->pFreeFunc))(pUserDataOut); if (lpwszIdentity) (*(pFreeData->pFreeFunc))((BYTE*)lpwszIdentity); }
if (pFreeData->hLib) FreeLibrary(pFreeData->hLib);
Free (pFreeData);
return NO_ERROR; }
//
// Customizes the dialer flags for the eap provider
// of the given entry;
//
// TODO -- try to optimize this. The list of eaps
// may not need to be read if we keep enough state
// in the phonebook.
//
DWORD DialerEapAssignMode( IN DINFO* pInfo, OUT LPDWORD lpdwfMode) { DWORD dwfMode = *lpdwfMode; DTLLIST * pListEaps; DTLNODE * pEapcfgNode; EAPCFG * pEapcfg;
// If eap is not used in this entry,
// then no action is required
if (! (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)) return NO_ERROR;
// Make sure we're configured with some list of
// eap configuration options
pListEaps = ReadEapcfgList( NULL ); if (pListEaps == NULL) return ERROR_CAN_NOT_COMPLETE;
// Find the eap node we're interested in
pEapcfgNode = EapcfgNodeFromKey( pListEaps, pInfo->pEntry->dwCustomAuthKey ); if (pEapcfgNode) pEapcfg = (EAPCFG*)DtlGetData( pEapcfgNode ); else { if (pListEaps) DtlDestroyList(pListEaps, NULL); return ERROR_CAN_NOT_COMPLETE; }
// If eap provider requests user name then
// request identity.
if (pEapcfg->dwStdCredentialFlags & EAPCFG_FLAG_RequireUsername ) { // Use the "I" flavors if the eap wants a user
// name but no password.
//
if (!(pEapcfg->dwStdCredentialFlags & EAPCFG_FLAG_RequirePassword) ) { // Clear the username+password property (DR_U) if it
// exists and replace it with the username property
// (DR_I). Only do this if DR_U is already set. It
// wont be set for autodial connections or for connections
// where that option was specifically disabled as can
// be seen in the DialerDlg function.
//
// See whistler bug 30841
//
if (dwfMode & DR_U) { dwfMode &= ~DR_U; dwfMode |= DR_I; } } } else { // Otherwise, make sure that we request neither user name nor password
// Since domain cannot appear without username clear that also.
//
dwfMode &= ~(DR_U | DR_D);
// For whistler bug 500731 gangz
if ( 0 == dwfMode && (pInfo->pEntry->fPreviewUserPw) ) { dwfMode |= DR_B; } }
// Cleanup
if (pListEaps) DtlDestroyList(pListEaps, NULL);
// Assign the correct mode
*lpdwfMode = dwfMode;
return NO_ERROR; }
BOOL APIENTRY RasDialDlgA( IN LPSTR lpszPhonebook, IN LPSTR lpszEntry, IN LPSTR lpszPhoneNumber, IN OUT LPRASDIALDLG lpInfo )
// Win32 ANSI entrypoint that displays the dial progress and related
// dialogs, including authentication, error w/redial, callback, and retry
// authentication. 'LpszPhonebook' is the full path the phonebook or NULL
// indicating the default phonebook. 'LpszEntry' is the entry to dial.
// 'LpszPhoneNumber' is caller's override phone number or NULL to use the
// one in the entry. 'LpInfo' is caller's additional input/output
// parameters.
//
// Returns true if user establishes a connection, false otherwise.
//
{ WCHAR* pszPhonebookW; WCHAR* pszEntryW; WCHAR* pszPhoneNumberW; BOOL fStatus;
TRACE( "RasDialDlgA" );
if (!lpInfo) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; }
if (!lpszEntry) { lpInfo->dwError = ERROR_INVALID_PARAMETER; return FALSE; }
if (lpInfo->dwSize != sizeof(RASDIALDLG)) { lpInfo->dwError = ERROR_INVALID_SIZE; return FALSE; }
// Thunk "A" arguments to "W" arguments.
//
if (lpszPhonebook) { pszPhonebookW = StrDupTFromAUsingAnsiEncoding( lpszPhonebook ); if (!pszPhonebookW) { lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY; return FALSE; } } else { pszPhonebookW = NULL; }
pszEntryW = StrDupTFromAUsingAnsiEncoding( lpszEntry ); if (!pszEntryW) { Free0( pszPhonebookW ); lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY; return FALSE; }
if (lpszPhoneNumber) { pszPhoneNumberW = StrDupTFromAUsingAnsiEncoding( lpszPhoneNumber ); if (!pszPhoneNumberW) { Free0( pszPhonebookW ); Free( pszEntryW ); lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY; return FALSE; } } else { pszPhoneNumberW = NULL; }
// Thunk to the equivalent "W" API.
//
fStatus = RasDialDlgW( pszPhonebookW, pszEntryW, pszPhoneNumberW, lpInfo );
Free0( pszPhonebookW ); Free( pszEntryW );
return fStatus; }
DWORD DoEapProcessing( LPRASDIALDLG lpInfo, DINFO *pInfo, PBYTE *ppbEapUserData, WCHAR **ppwszEapIdentity, HANDLE *phEapFree, BOOL *pfStatus ) { // If this is an eap connection, then use the eap identity
// ui to get the user name and password.
//
DWORD dwSize = 0; DWORD dwErr = NO_ERROR;
*pfStatus = TRUE; // Bring up the Eap dialer dialog
dwErr = DialerDlgEap( lpInfo->hwndOwner, pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName, pInfo->pEntry, pInfo, ppbEapUserData, &dwSize, ppwszEapIdentity, phEapFree);
if (dwErr != NO_ERROR) { if (ERROR_CANCELLED == dwErr) { dwErr = NO_ERROR; }
*pfStatus = FALSE;
goto done; }
if(!pInfo->pNoUser) { // Set the extended dial params accordingly
pInfo->rde.RasEapInfo.dwSizeofEapInfo = dwSize; pInfo->rde.RasEapInfo.pbEapInfo = *ppbEapUserData; } else if ( (*ppbEapUserData != NULL) && (dwSize != 0)) { pInfo->rde.RasEapInfo.dwSizeofEapInfo = dwSize; pInfo->rde.RasEapInfo.pbEapInfo = *ppbEapUserData; } else { INTERNALARGS *piargs;
piargs = (INTERNALARGS *) (pInfo->pArgs->reserved); if( (NULL != piargs) && (NULL != piargs->pvEapInfo) // pmay: 386489
//
&& (pInfo->pEntry->dwCustomAuthKey == EAPCFG_DefaultKey)) { pInfo->rde.RasEapInfo.dwSizeofEapInfo = ((EAPLOGONINFO *) piargs->pvEapInfo)->dwSize;
pInfo->rde.RasEapInfo.pbEapInfo = (BYTE *) piargs->pvEapInfo; } else { pInfo->rde.RasEapInfo.dwSizeofEapInfo = 0; pInfo->rde.RasEapInfo.pbEapInfo = NULL; } }
if (*ppwszEapIdentity) { DWORD dwSizeTmp = sizeof(pInfo->rdp.szUserName) / sizeof(WCHAR);
wcsncpy(pInfo->rdp.szUserName, *ppwszEapIdentity, dwSizeTmp - 1); pInfo->rdp.szUserName[dwSizeTmp - 1] = 0;
// Ignore the domain setting if the EAP supplied the
// identity.
pInfo->rdp.szDomain[ 0 ] = L'\0'; }
done: return dwErr; }
INT DialDlgDisplayError( IN LPRASDIALDLG pInfo, IN HWND hwndOwner, IN DWORD dwSid, IN DWORD dwError, IN ERRORARGS* pArgs) { if (pInfo->dwFlags & RASDDFLAG_NoPrompt) { return 0; }
return ErrorDlg(hwndOwner, dwSid, dwError, pArgs); }
BOOL APIENTRY RasDialDlgW( IN LPWSTR lpszPhonebook, IN LPWSTR lpszEntry, IN LPWSTR lpszPhoneNumber, IN OUT LPRASDIALDLG lpInfo )
// Win32 UNICODE entrypoint that displays the dial progress and related
// dialogs, including authentication, error w/redial, callback, and retry
// authentication. 'LpszPhonebook' is the full path the phonebook or NULL
// indicating the default phonebook. 'LpszEntry' is the entry to dial.
// 'LpszPhoneNumber' is caller's override phone number or NULL to use the
// one in the entry. 'LpInfo' is caller's additional input/output
// parameters.
//
// Returns true if user establishes a connection, false otherwise. If
// 'RASDDFLAG_AutoDialQueryOnly' is set, returns true if user pressed
// "Dial", false otherwise.
//
{ DWORD dwErr; BOOL fStatus; BOOL fFirstPass; DINFO* pInfo; LPWSTR pwszEapIdentity = NULL; PBYTE pbEapUserData = NULL; HANDLE hEapFree = NULL; BOOL fCustom = FALSE; PVOID pvInfo = NULL; HRASCONN hrasconnPrereq = NULL;
TRACE( "RasDialDlgW" );
if (!lpInfo) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; }
if (!lpszEntry) { lpInfo->dwError = ERROR_INVALID_PARAMETER; return FALSE; }
if (lpInfo->dwSize != sizeof(RASDIALDLG)) { lpInfo->dwError = ERROR_INVALID_SIZE; return FALSE; }
if (lpszPhoneNumber && lstrlen( lpszPhoneNumber ) > RAS_MaxPhoneNumber) { lpInfo->dwError = ERROR_INVALID_PARAMETER; return FALSE; }
// Load RAS DLL entrypoints which starts RASMAN, if necessary.
//
lpInfo->dwError = LoadRas( g_hinstDll, lpInfo->hwndOwner ); if (lpInfo->dwError != 0) { // Whistler bug 301784
//
// Check specifically for access denied.
//
if (lpInfo->dwError == ERROR_ACCESS_DENIED) { DialDlgDisplayError( lpInfo, lpInfo->hwndOwner, SID_OP_LoadRasAccessDenied, lpInfo->dwError, NULL ); } else { DialDlgDisplayError( lpInfo, lpInfo->hwndOwner, SID_OP_LoadRas, lpInfo->dwError, NULL ); } return FALSE; }
// Allocate the context information block and initialize it enough so that
// it can be destroyed properly.
//
pInfo = Malloc( sizeof(*pInfo) ); if (!pInfo) { DialDlgDisplayError( lpInfo, lpInfo->hwndOwner, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY; return FALSE; }
ZeroMemory( pInfo, sizeof(*pInfo) ); pInfo->pszPhonebook = lpszPhonebook; pInfo->pszEntry = lpszEntry; pInfo->pszPhoneNumber = lpszPhoneNumber; pInfo->pArgs = lpInfo;
fStatus = FALSE; dwErr = 0;
do { // Load the phonebook file and user preferences, or figure out that
// caller has already loaded them.
//
if (lpInfo->reserved) { INTERNALARGS* piargs;
// We've received an open phonebook file and user preferences via
// the secret hack.
//
piargs = (INTERNALARGS* )lpInfo->reserved; pInfo->pFile = pInfo->pFileMain = piargs->pFile; pInfo->pUser = piargs->pUser; pInfo->pNoUser = piargs->pNoUser; pInfo->pfNoUserChanged = &piargs->fNoUserChanged; pInfo->fMoveOwnerOffDesktop = piargs->fMoveOwnerOffDesktop; pInfo->fForceCloseOnDial = piargs->fForceCloseOnDial;
} else { // Read user preferences from registry.
//
dwErr = g_pGetUserPreferences( NULL, &pInfo->user, UPM_Normal ); if (dwErr != 0) { DialDlgDisplayError( lpInfo, lpInfo->hwndOwner, SID_OP_LoadPrefs, dwErr, NULL ); break; }
pInfo->pUser = &pInfo->user;
// Load and parse the phonebook file.
//
dwErr = ReadPhonebookFile( lpszPhonebook, &pInfo->user, NULL, 0, &pInfo->file ); if (dwErr != 0) { DialDlgDisplayError( lpInfo, lpInfo->hwndOwner, SID_OP_LoadPhonebook, dwErr, NULL ); break; }
pInfo->pFile = pInfo->pFileMain = &pInfo->file; }
// Record whether this is a for-all-users phonebook
//
// Whistler bug 288596 Autodial has wrong save password option marked -
// prompts user to save password for all users
//
pInfo->fIsPublicPbk = (!pInfo->pszPhonebook) || IsPublicPhonebook(pInfo->pszPhonebook);
if (!pInfo->pNoUser) { DWORD dwErrR; HKEY hkey;
// See if admin has disabled the "save password" feature.
//
pInfo->fDisableSavePw = FALSE;
dwErrR = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\RasMan\\Parameters"), 0, KEY_READ, &hkey );
if (dwErrR == 0) { DWORD dwResult;
dwResult = (DWORD )pInfo->fDisableSavePw; GetRegDword( hkey, TEXT("DisableSavePassword"), &dwResult ); pInfo->fDisableSavePw = (BOOL )dwResult;
RegCloseKey( hkey ); } }
// Hide parent dialog when initiated by another RAS API that requests
// it. This is the first stage of "close on dial" behavior, allowing
// the parent to appear closed to user though, as owner, it must
// really stay open until the dial dialogs complete. At that point it
// can silently close or reappear as desired.
//
if (lpInfo->hwndOwner && pInfo->fMoveOwnerOffDesktop) { SetOffDesktop( lpInfo->hwndOwner, SOD_MoveOff, NULL ); }
// Set true initially, but will be set false by
// FindEntryAndSetDialParams if the entry has no "dial first" entry
// associated with it.
//
pInfo->fPrerequisiteDial = TRUE; fFirstPass = TRUE; for (;;) { pInfo->fDialForReferenceOnly = FALSE;
// Look up the entry and fill in the RASDIALPARAMS structure
// accordingly. This done as a routine so it can be re-done
// should user press the Properties button.
//
dwErr = FindEntryAndSetDialParams( pInfo ); if (dwErr != 0) { // we need to maintain 2 phonebooks
// but we need to do this in case we break existing
// apps which look specifically in system\ras dir.
// Feel free to rip this code off, if you feel
// strongly about it.
//
if( (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwErr) && (NULL == lpszPhonebook)) { DTLNODE *pNode;
//
// Close the all users phonebook file
//
ClosePhonebookFile(&pInfo->file);
dwErr = GetPbkAndEntryName( lpszPhonebook, lpszEntry, 0, &pInfo->file, &pNode);
if( (NULL == pNode) || (ERROR_SUCCESS != dwErr)) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; break; }
pInfo->pFile = pInfo->pFileMain = &pInfo->file;
dwErr = FindEntryAndSetDialParams(pInfo);
if(dwErr != 0) { break; } } else { break; } }
if(lpInfo->reserved) { INTERNALARGS *piargs = (INTERNALARGS *) lpInfo->reserved;
if (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) { pvInfo = piargs->pvEapInfo; } else { pvInfo = piargs->pNoUser; } }
if(pInfo->fPrerequisiteDial && (NULL != pInfo->pEntry->pszCustomDialerName) && (TEXT('\0') != pInfo->pEntry->pszCustomDialerName[0])) { RASDIALDLG Info; DWORD dwCustomFlags = 0; RASNOUSER nouser, *pNoUser = NULL;
ZeroMemory(&Info, sizeof(RASDIALDLG)); ZeroMemory(&nouser, sizeof(RASNOUSER));
Info.dwSize = sizeof(RASDIALDLG); Info.hwndOwner = lpInfo->hwndOwner; Info.xDlg = lpInfo->xDlg; Info.yDlg = lpInfo->yDlg;
fCustom = TRUE;
if(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) { dwCustomFlags |= RCD_Eap; }
if( (NULL != pInfo->pNoUser) && (RASNOUSER_SmartCard & pInfo->pNoUser->dwFlags) && ( (0 == (dwCustomFlags & RCD_Eap)) || (EAP_RASTLS != pInfo->pEntry->dwCustomAuthKey) )) { CopyMemory(&nouser, pInfo->pNoUser, sizeof(RASNOUSER)); RtlSecureZeroMemory(nouser.szPassword, (PWLEN+1) * sizeof(TCHAR)); pvInfo = &nouser; }
// DwCustomDialDlg returns ERROR_SUCCESS if it handled
// the CustomRasDial. returns E_NOINTERFACE otherwise
// which implies that there is no custom dlg interface
// supported for this entry and the default dial should
// happen
//
// Whistler bug 314578 When connecting with CM via Winlogon I
// get the following error "Error 1: Incorrect function"
//
// This is a case where we call into a custom dialer, ie CM,
// and we are using creds that we got from winlogon. They are
// currently encoded and must be decoded before we call out.
// We have to assume that the Custom Dialer leaves the password
// un-encoded upon return.
//
if ( !(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) ) { // pNoUser is used to encode/decode passwords. If this
// is an EAP connection, then pvInfo will point to an
// eap blob, not a "no user" blob.
//
pNoUser = pvInfo; } if ( pNoUser ) { DecodePassword( pNoUser->szPassword ); }
if(pInfo->pNoUser) { dwCustomFlags |= RCD_Logon; }
dwErr = DwCustomDialDlg(pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName, NULL, &Info, dwCustomFlags, &fStatus, pvInfo, pInfo->pEntry->pszCustomDialerName); if ( pNoUser ) { EncodePassword( pNoUser->szPassword ); }
if(!fStatus) { lpInfo->dwError = Info.dwError; break; } else { pInfo->fPrerequisiteDial = FALSE; fCustom = FALSE; continue; } } else if ((NULL != pInfo->pEntry->pszCustomDialerName) && (TEXT('\0') != pInfo->pEntry->pszCustomDialerName[0])) { DWORD dwCustomFlags = 0; RASNOUSER nouser, *pNoUser = NULL;
ZeroMemory(&nouser, sizeof(RASNOUSER));
if(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) { dwCustomFlags |= RCD_Eap; }
if( (NULL != pInfo->pNoUser) && (RASNOUSER_SmartCard & pInfo->pNoUser->dwFlags) && ( (0 == (dwCustomFlags & RCD_Eap)) || (EAP_RASTLS != pInfo->pEntry->dwCustomAuthKey)) ) { CopyMemory(&nouser, pInfo->pNoUser, sizeof(RASNOUSER)); RtlSecureZeroMemory(nouser.szPassword, (PWLEN+1) * sizeof(TCHAR)); pvInfo = &nouser; }
fCustom = TRUE;
// DwCustomDialDlg returns ERROR_SUCCESS if it handled
// the CustomRasDial. returns E_NOINTERFACE otherwise
// which implies that there is no custom dlg interface
// supported for this entry and the default dial should
// happen
//
// Whistler bug 314578 When connecting with CM via Winlogon I
// get the following error "Error 1: Incorrect function"
//
// This is a case where we call into a custom dialer, ie CM,
// and we are using creds that we got from winlogon. They are
// currently encoded and must be decoded before we call out.
// We have to assume that the Custom Dialer leaves the password
// un-encoded upon return.
//
if ( !(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) ) { // pNoUser is used to encode/decode passwords. If this
// is an EAP connection, then pvInfo will point to an
// eap blob, not a "no user" blob.
//
pNoUser = pvInfo; } if ( pNoUser ) { DecodePassword( pNoUser->szPassword ); }
if(pInfo->pNoUser) { dwCustomFlags |= RCD_Logon; }
dwErr = DwCustomDialDlg(lpszPhonebook, lpszEntry, lpszPhoneNumber, lpInfo, dwCustomFlags, &fStatus, pvInfo, pInfo->pEntry->pszCustomDialerName); if ( pNoUser ) { EncodePassword( pNoUser->szPassword ); }
break; }
// If a prerequisite entry is already connected, there's no need
// for any UI but the dial must occur to set the reference in the
// RASAPI level.
//
if (pInfo->fPrerequisiteDial && HrasconnFromEntry( pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName )) { pInfo->fDialForReferenceOnly = TRUE; }
// Set up extension parameter block, except 'hwndOwner' which is
// set to the Dial Progress dialog window later.
//
{ RASDIALEXTENSIONS* prde = &pInfo->rde;
ZeroMemory( prde, sizeof(*prde) ); prde->dwSize = sizeof(*prde); prde->dwfOptions = RDEOPT_PausedStates | RDEOPT_PauseOnScript;
if (pInfo->pNoUser) { prde->dwfOptions |= RDEOPT_NoUser; }
if (!pInfo->pszPhoneNumber) { prde->dwfOptions |= RDEOPT_UsePrefixSuffix; } }
if ( (pInfo->fUnattended) && ((HaveSavedPw( pInfo )) || (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP))) { // Popup the countdown to link failure redial version of the
// dial error dialog, which will lead to a dial unless user
// stops it.
//
fStatus = DialErrorDlg( lpInfo->hwndOwner, pInfo, // For whistler 474514
pInfo->pszPhonebook, // For whislter 460931
pInfo->pEntry->pszEntryName, 0, 0, NULL, 0, NULL, GetOverridableParam( pInfo->pUser, pInfo->pEntry, RASOR_RedialSeconds ), GetOverridableParam( pInfo->pUser, pInfo->pEntry, RASOR_PopupOnTopWhenRedialing ) );
if(!fStatus) { break; } if (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) { dwErr = DoEapProcessing( lpInfo, pInfo, &pbEapUserData, &pwszEapIdentity, &hEapFree, &fStatus);
if( (NO_ERROR != dwErr) || (!fStatus)) { break; } } } else if (!pInfo->fDialForReferenceOnly) { if (!pInfo->fUnattended && fFirstPass) { // Warn about active NWC LAN connections being blown away,
// if indicated.
//
if (!NwConnectionCheck( lpInfo->hwndOwner, (pInfo->pArgs->dwFlags & RASDDFLAG_PositionDlg), pInfo->pArgs->xDlg, pInfo->pArgs->yDlg, pInfo->pFile, pInfo->pEntry )) { break; }
// Popup the double-dial help popup, if indicated.
//
if (!VpnDoubleDialDlg( lpInfo->hwndOwner, pInfo )) { break; } }
// Check to see if its smartcardlogon case and blank
// out the password if its not an eap tls connectoid
//
if( (NULL != pInfo->pNoUser) && (RASNOUSER_SmartCard & pInfo->pNoUser->dwFlags) && (pInfo->pEntry->dwCustomAuthKey != EAP_RASTLS)) { RtlSecureZeroMemory(pInfo->rdp.szPassword, (PWLEN+1) * sizeof(TCHAR)); }
// Prompt for credentials and/or phone number (or not)
// as configured in the entry properties.
//
if (!DialerDlg( lpInfo->hwndOwner, pInfo )) { if(!fFirstPass) { fStatus = FALSE; } break; }
if (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) { dwErr = DoEapProcessing( lpInfo, pInfo, &pbEapUserData, &pwszEapIdentity, &hEapFree, &fStatus);
if( (NO_ERROR != dwErr) || (!fStatus)) { break; } }
fStatus = TRUE; } else { fStatus = TRUE; }
// Dial and show progress.
//
if (fStatus && !fCustom) {
// Clear this here because beyond this rasman
// will take care of dropping the prereq link
// since beyond this point rasdial api will get
// called. [raos]
//
hrasconnPrereq = NULL;
fStatus = DialProgressDlg( pInfo );
// Show connect complete dialog unless user has nixed it or
// it's a prerequisite dial.
// (AboladeG) Also suppress the dialog in no-prompt mode.
//
if (!pInfo->fPrerequisiteDial && fStatus && !pInfo->pUser->fSkipConnectComplete && !(pInfo->pArgs->dwFlags & RASDDFLAG_NoPrompt)) { //For whistler bug 378078 gangz
//We will comment out this status explaination dialog
//box because some users complained that it is confusing
//
// ConnectCompleteDlg( lpInfo->hwndOwner, pInfo );
} }
// Don't loop a second time to dial the main entry if the
// prerequisite dial failed.
//
if (!fStatus || !pInfo->fPrerequisiteDial) { break; }
// Save the rasconn of the prereq dial in case we need to hang
// it up for the case where the vpn dialog fails before rasdial
// gets called. [raos]
//
if (pInfo->fPrerequisiteDial) { hrasconnPrereq = HrasconnFromEntry( pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName); }
pInfo->fPrerequisiteDial = FALSE; fFirstPass = FALSE; // Cleanup eap stuff
if (hEapFree) { DialerEapCleanup(hEapFree, pbEapUserData, pwszEapIdentity); hEapFree = NULL; pbEapUserData = NULL; pwszEapIdentity = NULL; } } } while (FALSE);
// Unhide parent dialog when initiated by another RAS API.
//
if (lpInfo->hwndOwner && pInfo->fMoveOwnerOffDesktop && (!fStatus || !(pInfo->pUser->fCloseOnDial || pInfo->fForceCloseOnDial))) { SetOffDesktop( lpInfo->hwndOwner, SOD_MoveBackFree, NULL ); }
if(!fCustom) { // Save the several little user preferences adjustments we may have made.
//
g_pSetUserPreferences( NULL, pInfo->pUser, (pInfo->pNoUser) ? UPM_Logon : UPM_Normal );
// Report error, if any.
//
if (dwErr) { DialDlgDisplayError( lpInfo, lpInfo->hwndOwner, SID_OP_LoadDlg, dwErr, NULL ); lpInfo->dwError = dwErr; }
TRACE1("hrasconnPrereq=0x%x",hrasconnPrereq);
//
// Drop the connection if we failed to connect the vpn connection
//
if( !fStatus && (NULL != hrasconnPrereq) && (pInfo->pEntry) && (pInfo->pEntry->pszPrerequisiteEntry) && *(pInfo->pEntry->pszPrerequisiteEntry)) { g_pRasHangUp(hrasconnPrereq); } }
// Clean up.
//
if (!lpInfo->reserved) { if (pInfo->pFileMain) { ClosePhonebookFile( pInfo->pFileMain ); }
if (pInfo->pUser) { DestroyUserPreferences( pInfo->pUser ); } }
if (pInfo->fFilePrereqOpen) { ClosePhonebookFile( &pInfo->filePrereq ); }
RtlSecureZeroMemory( pInfo->rdp.szPassword, sizeof(pInfo->rdp.szPassword) ); if (pInfo->pListPortsToDelete) { DtlDestroyList( pInfo->pListPortsToDelete, DestroyPszNode ); }
if (hEapFree) DialerEapCleanup(hEapFree, pbEapUserData, pwszEapIdentity); Free( pInfo ); pInfo = NULL;
return fStatus; }
//----------------------------------------------------------------------------
// Local utilities
// Listed alphabetically
//----------------------------------------------------------------------------
DWORD RasCredToDialParam( IN TCHAR* pszDefaultUserName, IN TCHAR* pszDefaultDomain, IN RASCREDENTIALS* pCreds, OUT RASDIALPARAMS* pParams) { TCHAR* pszComputer = NULL; TCHAR* pszLogonDomain = NULL; TCHAR* pszUser = NULL;
// Set the user name, defaulting it if needed
//
if (pCreds->dwMask & RASCM_UserName) { lstrcpyn( pParams->szUserName, pCreds->szUserName, sizeof(pParams->szUserName) / sizeof(TCHAR)); } else if (pszDefaultUserName) { lstrcpyn( pParams->szUserName, pszDefaultUserName, sizeof(pParams->szUserName) / sizeof(TCHAR)); } else { pszUser = GetLogonUser(); if (pszUser) { lstrcpyn( pParams->szUserName, pszUser, sizeof(pParams->szUserName) / sizeof(TCHAR)); } }
// Set the domain name, defaulting it if needed
//
if (pCreds->dwMask & RASCM_Domain) { lstrcpyn( pParams->szDomain, pCreds->szDomain, sizeof(pParams->szDomain) / sizeof(TCHAR)); } else if ( pszDefaultDomain ) { lstrcpyn( pParams->szDomain, pszDefaultDomain, sizeof(pParams->szDomain) / sizeof(TCHAR)); } else { pszComputer = GetComputer(); pszLogonDomain = GetLogonDomain(); if ( (pszComputer) && (pszLogonDomain) && (lstrcmp( pszComputer, pszLogonDomain ) != 0)) { lstrcpyn( pParams->szDomain, pszLogonDomain, sizeof(pParams->szDomain) / sizeof(TCHAR)); } }
// Fill in the password field
//
if (pCreds->dwMask & RASCM_Password) { // Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( pCreds->szPassword ); lstrcpyn( pParams->szPassword, pCreds->szPassword, sizeof(pParams->szPassword) / sizeof(TCHAR) ); EncodePassword( pCreds->szPassword ); EncodePassword( pParams->szPassword ); }
return NO_ERROR; }
DWORD FindEntryCredentials( IN TCHAR* pszPath, IN TCHAR* pszEntryName, IN TCHAR* pszDefaultUserName, IN TCHAR* pszDefaultDomain, OUT RASDIALPARAMS* pUser, // per user credentials
OUT RASDIALPARAMS* pGlobal, // global credentials
OUT BOOL* pfUser, // set true if per user creds found
OUT BOOL* pfGlobal // set true if global creds found
)
// Loads the credentials for the given entry into memory. This routine
// determines whether per-user or per-connection credentials exist or
// both.
//
// The logic is a little complicated because RasGetCredentials had to
// support legacy usage of the API.
//
// Here's how it works. If only one set of credentials is stored for a
// connection, then RasGetCredentials will return that set regardless of
// whether the RASCM_DefalutCreds flag is set. If two sets of credentials
// are saved, then RasGetCredentials will return the per-user credentials
// if the RASCM_DefaultCreds bit is set, and the per-connection credentials
// otherwise.
//
// Here is the algorithm for loading the credentials
//
// 1. Call RasGetCredentials with the RASCM_DefaultCreds bit cleared
// 1a. If nothing is returned, no credentials are saved
// 1b. If the RASCM_DefaultCreds bit is set on return, then only
// global credentials are saved.
//
// 2. Call RasGetCredentials with the RASCM_DefaultCreds bit set
// 2a. If the RASCM_DefaultCreds bit is set on return, then
// both global and per-connection credentials are saved.
// 2b. Otherwise, only per-user credentials are saved.
//
{ DWORD dwErr; RASCREDENTIALS rc1, rc2; BOOL fUseLogonDomain;
TRACE( "FindEntryCredentials" );
// Initialize
//
*pfUser = FALSE; *pfGlobal = FALSE; ZeroMemory( &rc1, sizeof(rc1) ); ZeroMemory( &rc2, sizeof(rc2) ); rc1.dwSize = sizeof(rc1); rc2.dwSize = sizeof(rc2);
do {
// Look up per-user cached username, password, and domain.
// See comment '1.' in the function header
//
rc1.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain; ASSERT( g_pRasGetCredentials ); TRACE( "RasGetCredentials per-user" ); dwErr = g_pRasGetCredentials(pszPath, pszEntryName, &rc1 ); TRACE2( "RasGetCredentials=%d,m=%d", dwErr, rc1.dwMask ); if (dwErr != NO_ERROR) { break; }
// See 1a. in the function header comments
//
if (rc1.dwMask == 0) { // No credentials are saved. pUser will be used for the
// connection in this case so initialize it to use the default
// user name and domain name. XP 446571
//
ZeroMemory(&rc1, sizeof(rc1)); RasCredToDialParam( pszDefaultUserName, pszDefaultDomain, &rc1, pUser ); dwErr = NO_ERROR; break; }
// See 1b. in the function header comments
//
else if (rc1.dwMask & RASCM_DefaultCreds) { *pfGlobal = TRUE;
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by RasGetCredentials()
//
EncodePassword( rc1.szPassword ); RasCredToDialParam( pszDefaultUserName, pszDefaultDomain, &rc1, pGlobal );
dwErr = NO_ERROR; break; }
// Look up global per-user cached username, password, domain.
// See comment 2. in the function header
//
rc2.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain | RASCM_DefaultCreds; ASSERT( g_pRasGetCredentials ); TRACE( "RasGetCredentials global" ); dwErr = g_pRasGetCredentials(pszPath, pszEntryName, &rc2 ); TRACE2( "RasGetCredentials=%d,m=%d", dwErr, rc2.dwMask ); if (dwErr != NO_ERROR) { break; }
// See 2a. in the function header comments
//
if (rc2.dwMask & RASCM_DefaultCreds) { *pfGlobal = TRUE;
if (rc1.dwMask & RASCM_Password) { *pfUser = TRUE; }
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by RasGetCredentials()
//
EncodePassword( rc1.szPassword ); RasCredToDialParam( pszDefaultUserName, pszDefaultDomain, &rc1, pUser );
EncodePassword( rc2.szPassword ); RasCredToDialParam( pszDefaultUserName, pszDefaultDomain, &rc2, pGlobal ); }
// See 2b. in the function header comments
//
else { if (rc1.dwMask & RASCM_Password) { *pfUser = TRUE; }
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by RasGetCredentials()
//
EncodePassword( rc1.szPassword ); RasCredToDialParam( pszDefaultUserName, pszDefaultDomain, &rc1, pUser ); }
}while (FALSE);
// Cleanup
//
{ // Whistler bug 254385 encode password when not being used
//
RtlSecureZeroMemory( rc1.szPassword, sizeof(rc1.szPassword) ); RtlSecureZeroMemory( rc2.szPassword, sizeof(rc2.szPassword) ); }
return dwErr; }
DWORD FindEntryAndSetDialParams( IN DINFO* pInfo )
// Look up the entry and fill in the RASDIALPARAMS parameters accordingly.
// This routine contains all DINFO context initialization that can be
// affected by user actions on the property sheet. 'PInfo' is the
// partially initialized common dial dialog context.
//
// 'pInfo->fPrerequisiteDial'is set at entry if the prerequisite entry, if
// any, should be dialed first. If there is no prerequisite entry, the
// flag is cleared and the main entry dialed.
//
{ DWORD dwErr = NO_ERROR; RASDIALPARAMS* prdp, *prdpu, *prdpg;
if (pInfo->fFilePrereqOpen) { ClosePhonebookFile( pInfo->pFile ); pInfo->pFile = pInfo->pFileMain; pInfo->fFilePrereqOpen = FALSE; }
// Lookup entry node specified by caller and save reference for
// convenience elsewhere.
//
pInfo->pNode = EntryNodeFromName( pInfo->pFile->pdtllistEntries, pInfo->pszEntry ); if (!pInfo->pNode) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; return dwErr; }
pInfo->pEntry = pInfo->pEntryMain = (PBENTRY* )DtlGetData( pInfo->pNode ); ASSERT( pInfo->pEntry );
// Switch to the prerequisite entry, if indicated.
//
if (pInfo->fPrerequisiteDial) { if (pInfo->pEntry->pszPrerequisiteEntry && *(pInfo->pEntry->pszPrerequisiteEntry)) { ASSERT( !pInfo->fFilePrereqOpen );
// GetPbkAndEntryName first looks in the All Users phonebook file
// if a phonebook file is not specified. If the entry is not
// found there it looks in files present in the Users profile.
// This needs to be done since we are discontinuing the per-user
// pbk file being set through user preferences.
//
dwErr = GetPbkAndEntryName( pInfo->pEntry->pszPrerequisitePbk, pInfo->pEntry->pszPrerequisiteEntry, 0, &pInfo->filePrereq, &pInfo->pNode);
if (dwErr != 0) { return dwErr; }
pInfo->pFile = &pInfo->filePrereq; pInfo->fFilePrereqOpen = TRUE;
pInfo->pEntry = (PBENTRY* )DtlGetData( pInfo->pNode ); ASSERT( pInfo->pEntry ); } else { pInfo->fPrerequisiteDial = FALSE; } }
// Set up RasDial parameter blocks.
//
prdp = &pInfo->rdp; prdpu = &pInfo->rdpu; prdpg = &pInfo->rdpg; ZeroMemory( prdp, sizeof(*prdp) ); pInfo->fUnattended = FALSE; prdp->dwSize = sizeof(*prdp); lstrcpyn( prdp->szEntryName, pInfo->pEntry->pszEntryName, sizeof(prdp->szEntryName) / sizeof(TCHAR));
if (pInfo->pszPhoneNumber) { lstrcpyn( prdp->szPhoneNumber, pInfo->pszPhoneNumber, RAS_MaxPhoneNumber + 1); }
// Whistler bug 272819 Not prompted for callback number
// We must do this before the init of per-user and global variants
//
if (!pInfo->fUnattended) { // '*' means "behave as defined in user preferences", while leaving it
// zero would mean "don't request callback if server offers".
//
// Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
//
lstrcpyn( prdp->szCallbackNumber, TEXT("*"), sizeof(prdp->szCallbackNumber) / sizeof(TCHAR) ); }
// Initialze the per-user and global variants
//
CopyMemory(prdpu, prdp, sizeof(*prdp)); CopyMemory(prdpg, prdp, sizeof(*prdp));
// Set the subentry link to whatever the RasDialDlg caller specified. See
// bug 200351.
//
prdp->dwSubEntry = pInfo->pArgs->dwSubEntry;
// If running in "unattended" mode, i.e. called by RASAUTO to redial on
// link failure, read the user/password/domain and callback number used on
// the original call. (Actually found a use for the crappy
// RasGetEntryDialParams API)
//
if (pInfo->pArgs->dwFlags & RASDDFLAG_LinkFailure) { RASDIALPARAMS rdp; BOOL fSavedPw = HaveSavedPw( pInfo );
ZeroMemory( &rdp, sizeof(rdp) ); rdp.dwSize = sizeof(rdp); lstrcpyn( rdp.szEntryName, pInfo->pEntry->pszEntryName, sizeof(rdp.szEntryName) / sizeof(TCHAR) );
//For whistler bug 313509 gangz
//We use FindEntryCredentials() to get saved password perUser and
//perConnection inforation, use RasGetEntryDialParams() to get back
//Callback Numbers
//
{ RASDIALPARAMS rdTemp; TCHAR * pszTempUser, * pszTempDomain;
pszTempUser = pszTempDomain = NULL; TRACE("FindEntryCredentials"); dwErr = FindEntryCredentials( pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName, pszTempUser, pszTempDomain, &rdTemp, &rdTemp, &(pInfo->fHaveSavedPwUser), &(pInfo->fHaveSavedPwGlobal)); TRACE1("FindEntryCredentials=%d", dwErr); ZeroMemory( &rdTemp, sizeof(rdTemp) ); Free0(pszTempUser); Free0(pszTempDomain); } TRACE( "RasGetEntryDialParams" ); ASSERT( g_pRasGetEntryDialParams ); dwErr = g_pRasGetEntryDialParams( pInfo->pFile->pszPath, &rdp, &fSavedPw ); TRACE2( "RasGetEntryDialParams=%d,f=%d", dwErr, &fSavedPw ); TRACEW1( "u=%s", rdp.szUserName ); //TRACEW1( "p=%s", rdp.szPassword );
TRACEW1( "d=%s", rdp.szDomain ); TRACEW1( "c=%s", rdp.szCallbackNumber );
if (dwErr == 0) { lstrcpyn( prdp->szUserName, rdp.szUserName, sizeof(prdp->szUserName) / sizeof(TCHAR));
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by RasGetEntryDialParams()
//
lstrcpyn( prdp->szPassword, rdp.szPassword, sizeof(prdp->szPassword) / sizeof(TCHAR) ); EncodePassword( prdp->szPassword );
lstrcpyn( prdp->szDomain, rdp.szDomain, sizeof(prdp->szDomain) / sizeof(TCHAR)); lstrcpyn( prdp->szCallbackNumber, rdp.szCallbackNumber, sizeof(prdp->szCallbackNumber) / sizeof(TCHAR));
pInfo->fUnattended = TRUE; }
RtlSecureZeroMemory( rdp.szPassword, sizeof(rdp.szPassword) ); }
if (pInfo->pNoUser) { // Use the credentials we got from API caller, presumably the ones
// entered at Ctrl-Alt-Del.
//
lstrcpyn( prdp->szUserName, pInfo->pNoUser->szUserName, sizeof(prdp->szUserName) / sizeof(TCHAR));
//
// Don't copy the password if its smartcard logon
// and the entry being used is a non-eap connectoid
//
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded by caller of RasDialDlg()
//
DecodePassword( pInfo->pNoUser->szPassword ); lstrcpyn( prdp->szPassword, pInfo->pNoUser->szPassword, sizeof(prdp->szPassword) / sizeof(TCHAR) ); EncodePassword( pInfo->pNoUser->szPassword ); EncodePassword( prdp->szPassword );
if (pInfo->pEntry->fPreviewDomain) { lstrcpyn( prdp->szDomain, pInfo->pNoUser->szDomain, sizeof(prdp->szDomain) / sizeof(TCHAR)); } else { // Don't use Winlogon domain unless "include domain" option is
// selected. See bug 387266.
//
// Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
//
lstrcpyn( prdp->szDomain, TEXT(""), sizeof(prdp->szDomain) / sizeof(TCHAR) ); } } else if (!pInfo->fUnattended) { DWORD dwErrRc; BOOL fUseLogonDomain; TCHAR* pszDefaultUser;
dwErrRc = FindEntryCredentials( pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName, pInfo->pEntry->pszOldUser, pInfo->pEntry->pszOldDomain, prdpu, prdpg, &(pInfo->fHaveSavedPwUser), &(pInfo->fHaveSavedPwGlobal));
if (! pInfo->pEntry->fAutoLogon) { // If saved passwords are disabled, clear here
//
if (pInfo->fDisableSavePw) { pInfo->fHaveSavedPwUser = FALSE; pInfo->fHaveSavedPwGlobal = FALSE; RtlSecureZeroMemory(prdp->szPassword, sizeof(prdp->szPassword)); RtlSecureZeroMemory(prdpu->szPassword, sizeof(prdpu->szPassword)); RtlSecureZeroMemory(prdpg->szPassword, sizeof(prdpg->szPassword)); }
// If including domains is disabled, clear here
//
if (! pInfo->pEntry->fPreviewDomain) { // (SteveC) Don't do this in the 'fAutoLogon' case. See bug
// 207611.
//
ZeroMemory(prdp->szDomain, sizeof(prdp->szDomain)); ZeroMemory(prdpu->szDomain, sizeof(prdpu->szDomain)); ZeroMemory(prdpg->szDomain, sizeof(prdpg->szDomain)); } } if(!pInfo->pEntry->fAutoLogon) { // Initialize the dial params that will be passed to RasDial.
//
// Note that per-user credentials are always used when both
// per-user and global credentials are saved. The per-user
// credentials should be copied even if there is no saved
// password since there may be a saved identity.
//
CopyMemory(prdp, prdpu, sizeof(*prdp)); if (pInfo->fHaveSavedPwGlobal && !pInfo->fHaveSavedPwUser) { CopyMemory(prdp, prdpg, sizeof(*prdp)); } } }
return 0; }
//----------------------------------------------------------------------------
// Bundling Errors dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL BundlingErrorsDlg( IN OUT DPINFO* pInfo )
// Popup the Bundling Errors dialog. 'PInfo' is the dialing progress
// dialog context.
//
// Returns true if user chooses to accept the results or false if he
// chooses to hang up.
//
{ INT_PTR nStatus;
TRACE( "BundlingErrorsDlg" );
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_BE_BundlingErrors ), pInfo->hwndDlg, BeDlgProc, (LPARAM )pInfo );
if (nStatus == -1) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (BOOL )nStatus; }
INT_PTR CALLBACK BeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the Bundling Errors dialog. Parameters and
// return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "BeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
if (ListView_OwnerHandler( hwnd, unMsg, wparam, lparam, BeLvErrorsCallback )) { return TRUE; }
switch (unMsg) { case WM_INITDIALOG: { return BeInit( hwnd, (DPINFO* )lparam ); }
case WM_COMMAND: { return BeCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } }
return FALSE; }
BOOL BeCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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.
//
{ DWORD dwErr;
TRACE3( "BeCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case IDOK: case IDCANCEL: { TRACE1( "%s pressed", (wId==IDOK) ? "OK" : "Cancel" );
if (IsDlgButtonChecked( hwnd, CID_BE_CB_DisableLink )) { DWORD i; DPINFO* pInfo; DPSTATE* pState;
// Caller says to delete the links that failed in the entry.
// Create a list of Psz nodes containing the unique port name
// of each failed link so they can be removed after the state
// information is freed.
//
pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
for (i = 0, pState = pInfo->pStates; i < pInfo->cStates; ++i, ++pState) { DTLNODE* pNode; DTLNODE* pNodePtd; PBLINK* pLink;
if (pState->dwError != 0) { if (!pInfo->pArgs->pListPortsToDelete) { pInfo->pArgs->pListPortsToDelete = DtlCreateList( 0L ); if (!pInfo->pArgs->pListPortsToDelete) { continue; } }
pNode = DtlNodeFromIndex( pInfo->pArgs->pEntry->pdtllistLinks, (LONG )i ); if (!pNode) { continue; }
pLink = (PBLINK* )DtlGetData( pNode );
pNodePtd = CreatePszNode( pLink->pbport.pszPort ); if (!pNodePtd) { continue; }
DtlAddNodeLast( pInfo->pArgs->pListPortsToDelete, pNodePtd ); } } }
EndDialog( hwnd, (wId == IDOK) ); return TRUE; } }
return FALSE; }
VOID BeFillLvErrors( IN HWND hwndLv, IN DPINFO* pInfo )
// Fill the listview 'hwndLv' with devices and error strings and select
// the first item. 'PInfo' is the dialing progress dialog context.
//
{ INT iItem; DWORD i; DPSTATE* pState;
TRACE( "BeFillLvErrors" );
ListView_DeleteAllItems( hwndLv );
// Add columns.
//
{ LV_COLUMN col; TCHAR* pszHeader0; TCHAR* pszHeader1;
pszHeader0 = PszFromId( g_hinstDll, SID_DeviceColHead ); pszHeader1 = PszFromId( g_hinstDll, SID_StatusColHead );
ZeroMemory( &col, sizeof(col) ); col.mask = LVCF_FMT + LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.pszText = (pszHeader0) ? pszHeader0 : TEXT(""); ListView_InsertColumn( hwndLv, 0, &col );
ZeroMemory( &col, sizeof(col) ); col.mask = LVCF_FMT + LVCF_SUBITEM + LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.pszText = (pszHeader1) ? pszHeader1 : TEXT(""); col.iSubItem = 1; ListView_InsertColumn( hwndLv, 1, &col );
Free0( pszHeader0 ); Free0( pszHeader1 ); }
// Add the modem and adapter images.
//
ListView_SetDeviceImageList( hwndLv, g_hinstDll );
// Load listview with device/status pairs.
//
iItem = 0; for (i = 0, pState = pInfo->pStates; i < pInfo->cStates; ++i, ++pState) { LV_ITEM item; DTLNODE* pNode; PBLINK* pLink; TCHAR* psz;
pNode = DtlNodeFromIndex( pInfo->pArgs->pEntry->pdtllistLinks, (LONG )i ); if (pNode) { pLink = (PBLINK* )DtlGetData( pNode );
psz = DisplayPszFromDeviceAndPort( pLink->pbport.pszDevice, pLink->pbport.pszPort ); if (psz) { ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT + LVIF_IMAGE; item.iItem = iItem; item.pszText = psz; item.iImage = (pLink->pbport.pbdevicetype == PBDT_Modem) ? DI_Modem : DI_Adapter; ListView_InsertItem( hwndLv, &item ); Free( psz );
if (pState->dwError == 0) { psz = PszFromId( g_hinstDll, SID_Connected ); ListView_SetItemText( hwndLv, iItem, 1, psz ); Free( psz ); } else { psz = BeGetErrorPsz( pState->dwError ); ListView_SetItemText( hwndLv, iItem, 1, psz ); LocalFree( psz ); }
++iItem; } } }
// Auto-size columns to look good with the text they contain.
//
ListView_SetColumnWidth( hwndLv, 0, LVSCW_AUTOSIZE_USEHEADER ); ListView_SetColumnWidth( hwndLv, 1, LVSCW_AUTOSIZE_USEHEADER );
// Select the first item.
//
ListView_SetItemState( hwndLv, 0, LVIS_SELECTED, LVIS_SELECTED ); }
TCHAR* BeGetErrorPsz( IN DWORD dwError )
// Returns a string suitable for the Status column with error 'dwError' or
// NULL on error. 'DwError' is assumed to be non-0. It is caller's
// responsiblility to LocalFree the returned string.
//
{ TCHAR* pszErrStr; TCHAR szErrNumBuf[ MAXLTOTLEN + 1 ]; TCHAR* pszLineFormat; TCHAR* pszLine; TCHAR* apszArgs[ 2 ];
LToT( dwError, szErrNumBuf, 10 );
pszErrStr = NULL; GetErrorText( dwError, &pszErrStr );
pszLine = NULL; pszLineFormat = PszFromId( g_hinstDll, SID_FMT_Error ); if (pszLineFormat) { apszArgs[ 0 ] = szErrNumBuf; apszArgs[ 1 ] = (pszErrStr) ? pszErrStr : TEXT("");
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1, (va_list* )apszArgs );
Free( pszLineFormat ); }
Free0( pszErrStr ); return pszLine; }
BOOL BeInit( IN HWND hwndDlg, IN DPINFO* pArgs )
// Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
// 'PArgs' is caller's arguments to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr; HWND hwndLvErrors; HWND hwndCbDisableLink;
TRACE( "BeInit" );
hwndLvErrors = GetDlgItem( hwndDlg, CID_BE_LV_Errors ); ASSERT( hwndLvErrors ); hwndCbDisableLink = GetDlgItem( hwndDlg, CID_BE_CB_DisableLink ); ASSERT( hwndCbDisableLink );
// Save Dial Progress context as dialog context.
//
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pArgs );
// Load listview with device/error information.
//
BeFillLvErrors( hwndLvErrors, pArgs );
// Display the finished window above all other windows. The window
// position is set to "topmost" then immediately set to "not topmost"
// because we want it on top but not always-on-top. Always-on-top alone
// is incredibly annoying, e.g. it is always on top of the on-line help if
// user presses the Help button.
//
SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); ShowWindow( hwndDlg, SW_SHOW );
SetWindowPos( hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
SetFocus( hwndCbDisableLink ); return FALSE; }
LVXDRAWINFO* BeLvErrorsCallback( IN HWND hwndLv, IN DWORD dwItem )
// Enhanced list view callback to report drawing information. 'HwndLv' is
// the handle of the list view control. 'DwItem' is the index of the item
// being drawn.
//
// Returns the address of the column information.
//
{ // Use "wide selection bar" feature and the other recommended options.
//
// Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'.
//
static LVXDRAWINFO info = { 2, 0, LVXDI_Blend50Dis + LVXDI_DxFill, { 0, 0 } };
return &info; }
//----------------------------------------------------------------------------
// Change Password dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL ChangePasswordDlg( IN HWND hwndOwner, IN BOOL fOldPassword, OUT TCHAR* pszOldPassword, OUT TCHAR* pszNewPassword )
// Popup the Change Password dialog. 'HwndOwner' is the owning window.
// 'FOldPassword' is set true if user must supply an old password, false
// if no old password is required. 'PszOldPassword' and 'pszNewPassword'
// are caller's buffers for the returned passwords.
//
// Returns true if user presses OK and succeeds, false otherwise.
//
{ INT_PTR nStatus; CPARGS args;
TRACE( "ChangePasswordDlg" );
args.fOldPassword = fOldPassword; args.pszOldPassword = pszOldPassword; args.pszNewPassword = pszNewPassword;
nStatus = (BOOL )DialogBoxParam( g_hinstDll, (fOldPassword) ? MAKEINTRESOURCE( DID_CP_ChangePassword2 ) : MAKEINTRESOURCE( DID_CP_ChangePassword ), hwndOwner, CpDlgProc, (LPARAM )&args );
if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (BOOL )nStatus; }
INT_PTR CALLBACK CpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the Change Password dialog. Parameters and
// return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "CpDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return CpInit( hwnd, (CPARGS* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwCpHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { return CpCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } }
return FALSE; }
BOOL CpCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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.
//
{ DWORD dwErr;
TRACE3( "CpCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case IDOK: { CPWINFO* pInfo; TCHAR szNewPassword[ PWLEN + 1 ]; TCHAR szNewPassword2[ PWLEN + 1 ];
TRACE( "OK pressed" );
pInfo = (CPWINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
szNewPassword[ 0 ] = TEXT('\0'); GetWindowText( pInfo->hwndEbNewPassword, szNewPassword, PWLEN + 1 ); szNewPassword2[ 0 ] = TEXT('\0'); GetWindowText( pInfo->hwndEbNewPassword2, szNewPassword2, PWLEN + 1 );
if (lstrcmp( szNewPassword, szNewPassword2 ) != 0) { // The two passwords don't match, i.e. user made a typo. Make
// him re-enter.
//
MsgDlg( hwnd, SID_PasswordsDontMatch, NULL ); SetWindowText( pInfo->hwndEbNewPassword, TEXT("") ); SetWindowText( pInfo->hwndEbNewPassword2, TEXT("") ); SetFocus( pInfo->hwndEbNewPassword ); RtlSecureZeroMemory( szNewPassword, sizeof(szNewPassword) ); RtlSecureZeroMemory( szNewPassword2, sizeof(szNewPassword2) ); return TRUE; }
if (pInfo->pArgs->fOldPassword) { pInfo->pArgs->pszOldPassword[ 0 ] = TEXT('\0');
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by GetWindowText()
//
GetWindowText( pInfo->hwndEbOldPassword, pInfo->pArgs->pszOldPassword, PWLEN + 1 ); EncodePassword( pInfo->pArgs->pszOldPassword ); }
// Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
//
// pInfo->pArgs->pszNewPassword points back to RASDIALPARAMS->
// szPassword[ PWLEN + 1 ]
//
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by GetWindowText()
//
lstrcpyn( pInfo->pArgs->pszNewPassword, szNewPassword, PWLEN + 1 ); EncodePassword( pInfo->pArgs->pszNewPassword ); RtlSecureZeroMemory( szNewPassword, sizeof(szNewPassword) ); RtlSecureZeroMemory( szNewPassword2, sizeof(szNewPassword2) ); EndDialog( hwnd, TRUE ); return TRUE; }
case IDCANCEL: { TRACE( "Cancel pressed" ); EndDialog( hwnd, FALSE ); return TRUE; } }
return FALSE; }
BOOL CpInit( IN HWND hwndDlg, IN CPARGS* pArgs )
// Called on WM_INITDIALOG. 'HwndDlg' is the handle of the dialog window.
// 'PArgs' is caller's arguments to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr; CPWINFO* pInfo;
TRACE( "CpInit" );
// 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;
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo ); TRACE( "Context set" ); }
if (pArgs->fOldPassword) { pInfo->hwndEbOldPassword = GetDlgItem( hwndDlg, CID_CP_EB_OldPassword ); ASSERT( pInfo->hwndEbOldPassword ); Edit_LimitText( pInfo->hwndEbOldPassword, PWLEN ); } pInfo->hwndEbNewPassword = GetDlgItem( hwndDlg, CID_CP_EB_Password ); ASSERT( pInfo->hwndEbNewPassword ); Edit_LimitText( pInfo->hwndEbNewPassword, PWLEN );
pInfo->hwndEbNewPassword2 = GetDlgItem( hwndDlg, CID_CP_EB_ConfirmPassword ); ASSERT( pInfo->hwndEbNewPassword2 ); Edit_LimitText( pInfo->hwndEbNewPassword2, PWLEN );
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
// Display finished window.
//
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); SetForegroundWindow( hwndDlg );
return TRUE; }
//----------------------------------------------------------------------------
// Connect Complete dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
VOID ConnectCompleteDlg( IN HWND hwndOwner, IN DINFO* pInfo )
// Popup the connection complete dialog. 'HwndOwner' is the owning
// window. 'PUser' is the user preferences.
//
{ INT_PTR nStatus;
TRACE( "ConnectCompleteDlg" );
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_CC_ConnectComplete ), hwndOwner, CcDlgProc, (LPARAM )pInfo ); }
INT_PTR CALLBACK CcDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the dialog. Parameters and return value are as
// described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "CcDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return CcInit( hwnd, (DINFO* )lparam ); }
case WM_COMMAND: { return CcCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); }
case WM_DESTROY: //For whistler bug 372078
//GetCurrentIconEntryType() loads Icon from netshell where the icon is loaded
//by LoadImage() without LR_SHARED, so I have to destroy it when we are done
//with it
//
{ HICON hIcon=NULL; hIcon = (HICON)SendMessage( GetDlgItem( hwnd, CID_CC_I_Rasmon ), STM_GETICON, (WPARAM)0, (LPARAM)0); ASSERT(hIcon); if( hIcon ) { DestroyIcon(hIcon); } else { TRACE("CcDlgProc:Destroy Icon"); } } break; }
return FALSE; }
BOOL CcCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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( "CcCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case IDOK: { DINFO * pInfo = (DINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); PBUSER* pUser = pInfo->pUser; ASSERT( pUser );
if (IsDlgButtonChecked( hwnd, CID_CC_CB_SkipMessage )) { pUser->fSkipConnectComplete = TRUE; pUser->fDirty = TRUE; } }
// ...fall thru...
case IDCANCEL: { EndDialog( hwnd, TRUE ); return TRUE; } }
return FALSE; }
BOOL CcInit( IN HWND hwndDlg, IN DINFO* pInfo )
// Called on WM_INITDIALOG. 'HwndDlg' is the handle of dialog. 'PUser'
// is caller's argument to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ TRACE( "CcInit" );
// Set the dialog context.
//
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
// Set the explanatory text.
//
{ MSGARGS msgargs;
ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.apszArgs[ 0 ] = pInfo->pEntry->pszEntryName; msgargs.fStringOutput = TRUE;
MsgDlgUtil( NULL, SID_ConnectComplete, &msgargs, g_hinstDll, 0 );
if (msgargs.pszOutput) { SetDlgItemText( hwndDlg, CID_CC_ST_Text, msgargs.pszOutput ); Free( msgargs.pszOutput ); } }
// Set the correct icon. For whistler bug 372078
//
SetIconFromEntryType( GetDlgItem( hwndDlg, CID_CC_I_Rasmon ), pInfo->pEntry->dwType, FALSE); //FALSE means Large Icon
// Display finished window.
//
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); SetForegroundWindow( hwndDlg );
return TRUE; }
//----------------------------------------------------------------------------
// Dial Callback dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL DialCallbackDlg( IN HWND hwndOwner, IN OUT TCHAR* pszNumber )
// Popup the Dial Callback dialog. 'HwndOwner' is the owning window.
// 'PszNumber' is caller's buffer for the number of the local machine that
// the server will be told to callback. It contains the default number on
// entry and the user-edited number on exit.
//
// Returns true if user OK and succeeds, false if Cancel or error.
//
{ INT_PTR nStatus;
TRACE( "DialCallbackDlg" );
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_DC_DialCallback ), hwndOwner, DcDlgProc, (LPARAM )pszNumber );
if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (BOOL )nStatus; }
INT_PTR CALLBACK DcDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the Dial Callback dialog. Parameters and
// return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "DcDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return DcInit( hwnd, (TCHAR* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwDcHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { return DcCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } }
return FALSE; }
BOOL DcCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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.
//
{ DWORD dwErr;
TRACE3( "DcCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case IDOK: { BOOL fStatus; HWND hwndEbNumber; TCHAR* pszNumber;
TRACE( "OK pressed" );
hwndEbNumber = GetDlgItem( hwnd, CID_DC_EB_Number ); ASSERT( hwndEbNumber ); pszNumber = (TCHAR* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pszNumber ); GetWindowText( hwndEbNumber, pszNumber, RAS_MaxCallbackNumber + 1 );
if (IsAllWhite( pszNumber )) { // OK with blank callback number is same as Cancel.
//
TRACE( "Blank number cancel" ); fStatus = FALSE; } else { fStatus = TRUE; }
EndDialog( hwnd, fStatus ); return TRUE; }
case IDCANCEL: { TRACE( "Cancel pressed" ); EndDialog( hwnd, FALSE ); return TRUE; } }
return FALSE; }
BOOL DcInit( IN HWND hwndDlg, IN TCHAR* pszNumber )
// Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
// 'PszNumber' is the callback number.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr; HWND hwndEbNumber;
TRACE( "DcInit" );
// Stash address of caller's buffer for OK processing.
//
ASSERT( pszNumber ); SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pszNumber );
// Initialize edit field to caller's default.
//
hwndEbNumber = GetDlgItem( hwndDlg, CID_DC_EB_Number ); ASSERT( hwndEbNumber ); Edit_LimitText( hwndEbNumber, RAS_MaxCallbackNumber ); SetWindowText( hwndEbNumber, pszNumber );
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
// Display finished window.
//
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); SetForegroundWindow( hwndDlg );
return TRUE; }
//----------------------------------------------------------------------------
// Dial Error dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL DialErrorDlg( IN HWND hwndOwner, IN DINFO * pDinfo, // For whistler bug 474514
IN TCHAR* pszPhonebook, // For whistler 460931
IN TCHAR* pszEntry, IN DWORD dwError, IN DWORD sidState, IN TCHAR* pszStatusArg, IN DWORD sidFormatMsg, IN TCHAR* pszFormatArg, IN LONG lRedialCountdown, IN BOOL fPopupOnTop )
// Popup the Dial Error dialog. 'HwndOwner' is the owning window.
// 'PszEntry' is the entry being dialed. 'DwError' is the error that
// occurred or 0 if redialing after a link failure. 'sidStatusArg' is the
// argument to the 'sidState' 'SidState' is the string ID of the dial
// state executing when the error occurred. string or NULL if none.
// 'SidFormatMsg' is the string containing the format of the error message
// or 0 to use the default. 'PszFormatArg' is the additional argument to
// the format message or NULL if none. 'LRedialCountdown' is the number
// of seconds before auto-redial, or -1 to disable countdown, or -2 to
// hide the "Redial" button entirely. 'FPopupOnTop' indicates the status
// window should be brought to the front when redialing.
//
// Returns true if user chooses to redial or lets it timeout, false if
// cancels.
//
{ INT_PTR nStatus; DEARGS args;
TRACE( "DialErrorDlg" );
// For whistler 460931 459793 gangz
//
LinkWindow_RegisterClass();
args.pszPhonebook = pszPhonebook; // For whistler 460931
args.pDinfo = pDinfo; // For whislter 474514
args.pszEntry = pszEntry; args.dwError = dwError; args.sidState = sidState; args.pszStatusArg = pszStatusArg; args.sidFormatMsg = sidFormatMsg; args.pszFormatArg = pszFormatArg; args.lRedialCountdown = lRedialCountdown; args.fPopupOnTop = fPopupOnTop;
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_DE_DialError ), hwndOwner, DeDlgProc, (LPARAM )&args );
if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (BOOL )nStatus; }
INT_PTR CALLBACK DeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the Dial Error dialog. Parameters and return
// value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "DeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return DeInit( hwnd, (DEARGS* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwDeHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { return DeCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); }
case WM_TIMER: { DEINFO* pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
KillTimer( pInfo->hwndDlg, 1 ); if (pInfo->lRedialCountdown > 0) { --pInfo->lRedialCountdown; }
DeAdjustPbRedial( pInfo );
if (pInfo->lRedialCountdown == 0) { // Fake a press of the Redial button. Note that BM_CLICK
// cannot be used because it doesn't generate the WM_COMMAND
// when the thread is not the foreground window, due to
// SetCapture use and restriction.
//
SendMessage( pInfo->hwndDlg, WM_COMMAND, MAKEWPARAM( IDOK, BN_CLICKED ), (LPARAM )pInfo->hwndPbRedial ); } else { SetTimer( pInfo->hwndDlg, 1, 1000L, NULL ); }
return TRUE; }
case WM_DESTROY: { DeTerm( hwnd ); break; }
// For whistler bug 460931 459793 gangz
//
case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case NM_CLICK: case NM_RETURN: { DEINFO* pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); BOOL bCommit = FALSE; ASSERT(pInfo);
KillTimer( pInfo->hwndDlg, 1 ); DeAdjustPbRedial( pInfo );
TRACE( "RasUserPrefsDlgInternal");
// Because the launched property pages will do the
// Load/UnLoad too.
RasUserPrefDiagOnly ( hwnd, &bCommit );
if( bCommit ) { if ( NULL == pInfo->diagInfo.pfnGetDiagFunc || NULL == pInfo->diagInfo.strDiagFuncs.GetState ) { break; } else { BOOL fEnable = FALSE;
fEnable = pInfo->diagInfo.strDiagFuncs.GetState(); Button_SetCheck( pInfo->hwndCbEnableDiagLog, fEnable); } }
SetTimer( pInfo->hwndDlg, 1, 1000L, NULL );
break; } } } break;
}
return FALSE; }
VOID DeAdjustPbRedial( IN DEINFO* pInfo )
// Set the label of the Redial button or disable it as indicated by the
// redial countdown. If enabled, the button shows the number of seconds
// to auto-redial unless this is not the final redial. 'PInfo' is the
// dialog context block.
//
{ TCHAR* psz;
if (pInfo->lRedialCountdown == -2) { // Redial button is to be hidden. See bug 230594.
//
SetFocus( pInfo->hwndPbCancel ); ShowWindow( pInfo->hwndPbRedial, SW_HIDE ); EnableWindow( pInfo->hwndPbRedial, FALSE ); } else { // Go ahead and change the label "Redial" or "Redial=%d" as
// appropriate.
//
psz = PszFromId( g_hinstDll, SID_RedialLabel ); if (psz) { TCHAR szBuf[ 128 ];
lstrcpyn( szBuf, psz, (sizeof(szBuf) / sizeof(TCHAR)) - 4); Free( psz );
if (pInfo->lRedialCountdown >= 0) { TCHAR szNum[ MAXLTOTLEN + 1 ]; DWORD dwLen, dwSize = sizeof(szBuf)/sizeof(TCHAR); LToT( pInfo->lRedialCountdown, szNum, 10 ); lstrcat( szBuf, TEXT(" = ") ); dwLen = lstrlen(szBuf) + 1; lstrcpyn( szBuf + (dwLen - 1), szNum, dwSize - dwLen ); }
SetWindowText( pInfo->hwndPbRedial, szBuf ); } } }
void DeEnableDiagnostic( IN HWND hwnd ) { DEINFO* pInfo = NULL;
do { pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
if( NULL == pInfo ) { break; }
// For whistler bug 474514 gangz
//
if( pInfo->pArgs->pDinfo->pNoUser ) { break; }
if ( NULL == pInfo->diagInfo.pfnGetDiagFunc || NULL == pInfo->diagInfo.strDiagFuncs.SetAll ) { // ErrorDlg( hwnd, SID_DG_LoadDiag, ERROR_UNKNOWN, NULL );
break; } else { BOOL fEnable = FALSE;
fEnable = Button_GetCheck( pInfo->hwndCbEnableDiagLog ); pInfo->diagInfo.strDiagFuncs.SetAll( fEnable ); } } while(FALSE);
return; }
BOOL DeCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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.
//
{ DWORD dwErr;
TRACE3( "DeCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
TRACE2("Current proces:(0x%d), Current Thread:(0x%d)", GetCurrentProcessId(), GetCurrentThreadId());
switch (wId) { case IDOK: { TRACE( "Redial pressed" ); DeEnableDiagnostic( hwnd ); EndDialog( hwnd, TRUE ); return TRUE; }
case IDCANCEL: { TRACE( "Cancel pressed" ); DeEnableDiagnostic( hwnd ); EndDialog( hwnd, FALSE ); return TRUE; }
case CID_DE_PB_More: { DEINFO* pInfo; DWORD dwContext;
pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
if (pInfo->pArgs->dwError >= RASBASE && pInfo->pArgs->dwError <= RASBASEEND) { dwContext = HID_RASERRORBASE - RASBASE + pInfo->pArgs->dwError; } else if (pInfo->pArgs->dwError == 0) { dwContext = HID_RECONNECTING; } else { dwContext = HID_NONRASERROR; }
WinHelp( hwnd, g_pszHelpFile, HELP_CONTEXTPOPUP, dwContext ); } break;
// For whistler 460931
//
case CID_DE_CB_EnableDiag: { DEINFO* pInfo = NULL;
pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
if( NULL == pInfo ) { break; }
if ( NULL == pInfo->diagInfo.pfnGetDiagFunc || NULL == pInfo->diagInfo.strDiagFuncs.SetAll ) { ErrorDlg( hwnd, SID_DG_LoadDiag, ERROR_UNKNOWN, NULL ); break; } } break; }
return FALSE; }
BOOL DeInit( IN HWND hwndDlg, IN DEARGS* pArgs )
// Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
// 'PArgs' is caller's arguments to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr; DEINFO* pInfo;
TRACE( "DeInit" );
// 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;
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo ); TRACE( "Context set" ); }
pInfo->hwndStText = GetDlgItem( hwndDlg, CID_DE_ST_Text ); ASSERT( pInfo->hwndStText ); pInfo->hwndPbRedial = GetDlgItem( hwndDlg, IDOK ); ASSERT( pInfo->hwndPbRedial ); pInfo->hwndPbCancel = GetDlgItem( hwndDlg, IDCANCEL ); ASSERT( pInfo->hwndPbCancel ); pInfo->hwndPbMore = GetDlgItem( hwndDlg, CID_DE_PB_More ); ASSERT( pInfo->hwndPbMore ); // For whistler 460931 459793
//
pInfo->hwndCbEnableDiagLog= GetDlgItem( hwndDlg, CID_DE_CB_EnableDiag); ASSERT( pInfo->hwndCbEnableDiagLog ); pInfo->hwndStConfigureLnk= GetDlgItem( hwndDlg, CID_DE_ST_ConfigureLnk); ASSERT( pInfo->hwndStConfigureLnk); pInfo->hwndStEnableHelp = GetDlgItem( hwndDlg, CID_DE_ST_EnableHelp ); ASSERT( pInfo->hwndStEnableHelp ); pInfo->hwndStLinkHelp = GetDlgItem( hwndDlg, CID_DE_ST_LinkHelp ); ASSERT( pInfo->hwndStLinkHelp );
// For whistler 474514 gangz
// Have to block the diagnostic functionality from winlogon
// For .Net 530448, diagnostic functionality is only availabe for
// Administrator or Power users
if( pInfo->pArgs->pDinfo->pNoUser || !FIsUserAdminOrPowerUser() ) { EnableWindow(pInfo->hwndCbEnableDiagLog, FALSE); EnableWindow(pInfo->hwndStConfigureLnk, FALSE); ShowWindow(pInfo->hwndStConfigureLnk, SW_HIDE); EnableWindow(pInfo->hwndStEnableHelp, FALSE); EnableWindow(pInfo->hwndStLinkHelp, FALSE); } else { // For whistler bug 460931 gangz
// Load the Diagnostic functions
//
// Have to zero memory, or else LoadDiagnosticDll may fail
ZeroMemory( &pInfo->diagInfo, sizeof(pInfo->diagInfo ) ); if ( NO_ERROR == LoadDiagnosticDll( &pInfo->diagInfo ) ) { BOOL fEnable = FALSE;
fEnable = pInfo->diagInfo.strDiagFuncs.GetState();
Button_SetCheck( pInfo->hwndCbEnableDiagLog, fEnable ); } else { ; // EnableWindow( pInfo->hwndCbEnableDiagLog, FALSE );
// EnableWindow( pInfo->hwndStConfigureLnk, FALSE );
} } // Hide/disable "more info" button if WinHelp won't work. See
// common\uiutil\ui.c.
//
{ extern BOOL g_fNoWinHelp;
if (g_fNoWinHelp) { ShowWindow( pInfo->hwndPbMore, SW_HIDE ); EnableWindow( pInfo->hwndPbMore, FALSE ); } }
if (pArgs->dwError == 0) { TCHAR* pszFormat; TCHAR* psz; TCHAR* apszArgs[ 1 ];
// Redialing on link failure. Set title to "Dial-Up Networking".
//
psz = PszFromId( g_hinstDll, SID_PopupTitle ); if (psz) { SetWindowText( hwndDlg, psz ); Free( psz ); }
// Set static placeholder text control to "Link to <entry> failed.
// Reconnect pending...".
//
pszFormat = PszFromId( g_hinstDll, SID_DE_LinkFailed ); if (pszFormat) { apszArgs[ 0 ] = pArgs->pszEntry; psz = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszFormat, 0, 0, (LPTSTR )&psz, 1, (va_list* )apszArgs );
Free( pszFormat );
if (psz) { SetWindowText( pInfo->hwndStText, psz ); LocalFree( psz ); } } } else { TCHAR* pszTitleFormat; TCHAR* pszTitle; TCHAR* apszArgs[ 1 ]; ERRORARGS args;
// Set title to "Error Connecting to <entry>".
//
pszTitleFormat = GetText( hwndDlg ); if (pszTitleFormat) { apszArgs[ 0 ] = pArgs->pszEntry; pszTitle = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1, (va_list* )apszArgs );
Free( pszTitleFormat );
if (pszTitle) { SetWindowText( hwndDlg, pszTitle ); LocalFree( pszTitle ); } }
// Build the error text and load it into the placeholder text control.
//
ZeroMemory( &args, sizeof(args) ); if (pArgs->pszStatusArg) args.apszOpArgs[ 0 ] = pArgs->pszStatusArg; if (pArgs->pszFormatArg) args.apszAuxFmtArgs[ 0 ] = pArgs->pszFormatArg; args.fStringOutput = TRUE;
ErrorDlgUtil( hwndDlg, pArgs->sidState, pArgs->dwError, &args, g_hinstDll, 0, (pArgs->sidFormatMsg) ? pArgs->sidFormatMsg : SID_FMT_ErrorMsg );
if (args.pszOutput) { SetWindowText( pInfo->hwndStText, args.pszOutput ); LocalFree( args.pszOutput ); } }
// Stretch the dialog window to a vertical size appropriate for the text
// we loaded.
//
{ HDC hdc; RECT rect; RECT rectNew; HFONT hfont; LONG dyGrow; TCHAR* psz;
psz = GetText( pInfo->hwndStText ); if (psz) { GetClientRect( pInfo->hwndStText, &rect ); hdc = GetDC( pInfo->hwndStText );
if(NULL != hdc) {
hfont = (HFONT )SendMessage( pInfo->hwndStText, WM_GETFONT, 0, 0 ); if (hfont) { SelectObject( hdc, hfont ); }
rectNew = rect; DrawText( hdc, psz, -1, &rectNew, DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS | DT_NOPREFIX ); ReleaseDC( pInfo->hwndStText, hdc ); }
dyGrow = rectNew.bottom - rect.bottom; ExpandWindow( pInfo->hwndDlg, 0, dyGrow ); ExpandWindow( pInfo->hwndStText, 0, dyGrow ); // For whistler 460931 459793
//
SlideWindow( pInfo->hwndCbEnableDiagLog, pInfo->hwndDlg, 0, dyGrow ); SlideWindow( pInfo->hwndStLinkHelp, pInfo->hwndDlg, 0, dyGrow ); SlideWindow( pInfo->hwndStConfigureLnk, pInfo->hwndDlg, 0, dyGrow ); SlideWindow( pInfo->hwndStEnableHelp, pInfo->hwndDlg, 0, dyGrow ); SlideWindow( pInfo->hwndPbRedial, pInfo->hwndDlg, 0, dyGrow ); SlideWindow( pInfo->hwndPbCancel, pInfo->hwndDlg, 0, dyGrow ); SlideWindow( pInfo->hwndPbMore, pInfo->hwndDlg, 0, dyGrow ); Free( psz ); } }
// Set Redial button label or disable the button. Always choose to redial
// after 5 seconds for the biplex error, since this will normally solve
// the problem. Otherwise, no countdown is used.
//
if (pArgs->dwError == ERROR_BIPLEX_PORT_NOT_AVAILABLE) { pInfo->lRedialCountdown = 5; } else { pInfo->lRedialCountdown = pArgs->lRedialCountdown; }
DeAdjustPbRedial( pInfo );
if (pInfo->lRedialCountdown >= 0) { SetTimer( pInfo->hwndDlg, 1, 1000L, NULL ); }
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
if (pArgs->fPopupOnTop) { // Display the finished window above all other windows. The window
// position is set to "topmost" then immediately set to "not topmost"
// because we want it on top but not always-on-top. Always-on-top
// alone is too annoying.
//
SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE ); }
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); ShowWindow( hwndDlg, SW_SHOW );
if (pArgs->fPopupOnTop) { SetForegroundWindow( hwndDlg );
SetWindowPos( hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE ); }
return TRUE; }
// Helper function to delete credentials
//
// fDeleteDefault specifies whether it is the default credentials that
// should be deleted.
//
// fDeleteIdentity specifies whether to delete the user and domain names
// in addition to the password.
//
DWORD DeleteSavedCredentials( IN DINFO* pDinfo, IN HWND hwndDlg, IN BOOL fDefault, IN BOOL fDeleteIdentity ) { RASCREDENTIALS rc; DWORD dwErr = NO_ERROR;
TRACE2( "DeleteSavedCredentials: %d %d", fDefault, fDeleteIdentity );
ZeroMemory(&rc, sizeof(rc)); rc.dwSize = sizeof(RASCREDENTIALS); rc.dwMask = RASCM_Password;
if (fDeleteIdentity) { rc.dwMask |= (RASCM_UserName | RASCM_Domain); }
if ( (fDefault) && (IsPublicPhonebook(pDinfo->pFile->pszPath))) { rc.dwMask |= RASCM_DefaultCreds; }
dwErr = g_pRasSetCredentials( pDinfo->pFile->pszPath, pDinfo->pEntry->pszEntryName, &rc, TRUE );
if (dwErr != 0) { ErrorDlg( hwndDlg, SID_OP_UncachePw, dwErr, NULL ); }
TRACE1( "DeleteSavedCredentials: RasSetCredentials=%d", dwErr );
return dwErr; }
VOID DeTerm( IN HWND hwndDlg )
// Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
//
{ DEINFO* pInfo = (DEINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
TRACE( "DeTerm" );
if (pInfo) { if(! pInfo->pArgs->pDinfo->pNoUser ) { UnLoadDiagnosticDll( &pInfo->diagInfo); } Free( pInfo ); pInfo = NULL; } }
//----------------------------------------------------------------------------
// Dial Progress dialog
// Listed alphabetically following stub API dialog proc
//----------------------------------------------------------------------------
BOOL DialProgressDlg( IN DINFO* pInfo )
// Popup the Dial Progress dialog. 'PInfo' is the dialog context.
//
// Returns true if user connected successfully, false is he cancelled or
// hit an error.
//
{ INT_PTR nStatus;
// Run the dialog.
//
nStatus = DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_DP_DialProgress ), pInfo->pArgs->hwndOwner, DpDlgProc, (LPARAM )pInfo );
if (nStatus == -1) { ErrorDlg( pInfo->pArgs->hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); pInfo->pArgs->dwError = ERROR_UNKNOWN; nStatus = FALSE; }
if (nStatus) { DWORD dwErr; PBFILE file;
// Connected successfully, so read possible changes to the entry made
// by RasDial.
//
dwErr = ReadPhonebookFile( pInfo->pFile->pszPath, pInfo->pUser, pInfo->pEntry->pszEntryName, RPBF_ReadOnly, &file ); if (dwErr == 0) { DTLNODE* pNodeNew;
pNodeNew = DtlGetFirstNode( file.pdtllistEntries ); if (pNodeNew) { DtlRemoveNode( pInfo->pFile->pdtllistEntries, pInfo->pNode ); DestroyEntryNode( pInfo->pNode );
DtlRemoveNode( file.pdtllistEntries, pNodeNew ); DtlAddNodeLast( pInfo->pFile->pdtllistEntries, pNodeNew );
pInfo->pNode = pNodeNew; pInfo->pEntry = (PBENTRY* )DtlGetData( pNodeNew ); }
ClosePhonebookFile( &file ); } }
// See if we need to change the entry based on what happened while
// dialing.
//
{ BOOL fChange = FALSE;
if (pInfo->fResetAutoLogon) { ASSERT( !pInfo->pNoUser ); pInfo->pEntry->fAutoLogon = FALSE; fChange = TRUE; }
if (pInfo->dwfExcludedProtocols) { pInfo->pEntry->dwfExcludedProtocols |= pInfo->dwfExcludedProtocols; fChange = TRUE; }
if (pInfo->pListPortsToDelete) { DTLNODE* pNode;
pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks ); while (pNode) { DTLNODE* pNodeNext; DTLNODE* pNodePtd; PBLINK* pLink; TCHAR* pszPort;
pNodeNext = DtlGetNextNode( pNode );
pLink = (PBLINK* )DtlGetData( pNode ); pszPort = pLink->pbport.pszPort;
for (pNodePtd = DtlGetFirstNode( pInfo->pListPortsToDelete ); pNodePtd; pNodePtd = DtlGetNextNode( pNodePtd )) { TCHAR* pszPtd = (TCHAR* )DtlGetData( pNodePtd );
if (lstrcmp( pszPtd, pszPort ) == 0) { pNode = DtlRemoveNode( pInfo->pEntry->pdtllistLinks, pNode ); DestroyLinkNode( pNode ); fChange = TRUE; break; } }
pNode = pNodeNext; } }
if (fChange) { pInfo->pEntry->fDirty = TRUE; WritePhonebookFile( pInfo->pFile, NULL ); } }
return (BOOL )nStatus; }
INT_PTR CALLBACK DpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the User Authentication dialog. Parameters and
// return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "DpDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return DpInit( hwnd, (DINFO* )lparam ); }
case WM_COMMAND: { DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
return DpCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); }
case WM_RASDIAL: { DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
Sleep( 0 ); DpDial( pInfo, (BOOL)wparam ); return TRUE; }
case WM_RASERROR: { DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
Sleep( 0 );
//For whistler bug 381337
//
if ( !pInfo->fCancelPressed ) { DpError( pInfo, (DPSTATE* )lparam ); } else { TRACE("DpDlgProc is already canceled, wont respond to WM_RASERROR"); } return TRUE; }
case WM_RASBUNDLEERROR: { DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
Sleep( 0 ); if (BundlingErrorsDlg( pInfo )) { EndDialog( pInfo->hwndDlg, TRUE ); } else { DpCancel( pInfo ); } return TRUE; }
case WM_DPENDDIALOG: { DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
// XPSP2 511810, .Net 668164
if ( GetCallbackActive(pInfo)) { // Callbacks are active. Stall until they complete.
//
// SetTerminateFlag(pInfo);
TRACE( "Stall until callbacks disabled" ); PostMessage( hwnd, WM_DPENDDIALOG, wparam, lparam ); } else { EndDialog( hwnd, (BOOL)lparam); } } return TRUE; case WM_DESTROY: { DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
// Whistler Bugs: 344019 SECBUGBASH: leaving leaked password in
// memory when user changes password over RAS
//
// 289587 Failed RAS connections reset password to blank
//
if (pInfo->pszGoodPassword) { ZeroMemory( pInfo->pszGoodPassword, (lstrlen( pInfo->pszGoodPassword ) + 1) * sizeof(TCHAR) ); Free( pInfo->pszGoodPassword ); pInfo->pszGoodPassword = NULL; }
if (pInfo->pszGoodUserName) { Free( pInfo->pszGoodUserName ); pInfo->pszGoodUserName = NULL; }
if (GetCallbackActive(pInfo)) { // Callbacks are active. Stall until they complete.
//
TRACE( "Stall until callbacks disabled" );
SetTerminateFlag(pInfo);
PostMessage( hwnd, WM_DESTROY, wparam, lparam ); return TRUE; } DpTerm( hwnd ); break; } }
return FALSE; }
VOID DpAppendBlankLine( IN OUT TCHAR* pszLines )
// Append a blank line on the end of 'pszLines'.
//
{ lstrcat( pszLines, TEXT("\n") ); }
VOID DpAppendConnectErrorLine( IN OUT TCHAR* pszLines, IN DWORD sidProtocol, IN DWORD dwError )
// Append a connect error line for protocol 'sidProtocol' and error
// 'dwError' onto the end of 'pszLines'.
//
{ #define MAXRASERRORLEN 256
TCHAR* pszProtocol; TCHAR* pszErrStr; TCHAR szErrNumBuf[ MAXLTOTLEN + 1 ];
// Gather the argument strings.
//
pszProtocol = PszFromId( g_hinstDll, sidProtocol ); if (!pszProtocol) { return; }
LToT( dwError, szErrNumBuf, 10 );
pszErrStr = NULL; GetErrorText( dwError, &pszErrStr );
// Format the line and append it to caller's line buffer.
//
{ TCHAR* pszLineFormat; TCHAR* pszLine; TCHAR* apszArgs[ 3 ];
pszLineFormat = PszFromId( g_hinstDll, SID_FMT_ProjectError ); if (pszLineFormat) { apszArgs[ 0 ] = pszProtocol; apszArgs[ 1 ] = szErrNumBuf; apszArgs[ 2 ] = (pszErrStr) ? pszErrStr : TEXT(""); pszLine = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1, (va_list* )apszArgs );
Free( pszLineFormat );
if (pszLine) { lstrcat( pszLines, pszLine ); LocalFree( pszLine ); } } }
Free( pszProtocol ); Free0( pszErrStr ); }
VOID DpAppendConnectOkLine( IN OUT TCHAR* pszLines, IN DWORD sidProtocol )
// Append a "connected successfully" line for protocol 'sidProtocol' onto
// the end of 'pszLines'.
//
{ TCHAR* pszProtocol;
// Get the argument string.
//
pszProtocol = PszFromId( g_hinstDll, sidProtocol ); if (!pszProtocol) { return; }
// Format the line and append it to caller's line buffer.
//
{ TCHAR* pszLineFormat; TCHAR* pszLine; TCHAR* apszArgs[ 1 ];
pszLineFormat = PszFromId( g_hinstDll, SID_FMT_ProjectOk ); if (pszLineFormat) { apszArgs[ 0 ] = pszProtocol; pszLine = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1, (va_list* )apszArgs );
Free( pszLineFormat );
if (pszLine) { lstrcat( pszLines, pszLine ); LocalFree( pszLine ); } } }
Free( pszProtocol ); }
VOID DpAppendFailCodeLine( IN OUT TCHAR* pszLines, IN DWORD dw )
// Append hexidecimal fail code 'dw' as an extended error line on the end
// of 'pszLines'.
//
{ TCHAR szNumBuf[ MAXLTOTLEN + 1 ];
// Get the argument string.
//
LToT( dw, szNumBuf, 16 );
// Format the line and append it to caller's line buffer.
//
{ TCHAR* pszLineFormat; TCHAR* pszLine; TCHAR* apszArgs[ 1 ];
pszLineFormat = PszFromId( g_hinstDll, SID_FMT_FailCode ); if (pszLineFormat) { apszArgs[ 0 ] = szNumBuf; pszLine = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1, (va_list* )apszArgs );
Free( pszLineFormat );
if (pszLine) { lstrcat( pszLines, pszLine ); LocalFree( pszLine ); } } } }
VOID DpAppendNameLine( IN OUT TCHAR* pszLines, IN TCHAR* psz )
// Append NetBIOS name 'psz' as an extended error line on the end of
// 'pszLines'.
//
{ TCHAR* pszLineFormat; TCHAR* pszLine; TCHAR* apszArgs[ 1 ];
pszLineFormat = PszFromId( g_hinstDll, SID_FMT_Name ); if (pszLineFormat) { apszArgs[ 0 ] = psz; pszLine = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1, (va_list* )apszArgs );
Free( pszLineFormat );
if (pszLine) { lstrcat( pszLines, pszLine ); LocalFree( pszLine ); } } }
VOID DpAuthNotify( IN DPINFO* pInfo, IN DPSTATE* pState )
// Called on an authentication notify, i.e. a message from RASCAUTH.DLL or
// RASPPPEN.DLL. 'PInfo' is the dialog context. 'PState' is the current
// link's context.
//
{ PBENTRY* pEntry;
TRACE( "DpAuthNotify" );
pEntry = pInfo->pArgs->pEntry;
if (pState->dwError == ERROR_ACCESS_DENIED && pEntry->fAutoLogon) { // A third party box has negotiated an authentication protocol that
// can't deal with the NT one-way-hashed password, i.e. something
// besides MS-extended CHAP or AMB. Map the error to a more
// informative error message.
//
pState->dwError = ERROR_CANNOT_USE_LOGON_CREDENTIALS;
if (!pInfo->pArgs->pNoUser) { TRACE( "Disable auto-logon" ); pEntry->fAutoLogon = FALSE; pInfo->pArgs->fResetAutoLogon = TRUE; } }
if (pState->dwError == ERROR_CHANGING_PASSWORD) { TRACE( "DpAuthNotify - ERROR_CHANGING_PASSWORD" );
// Change password failed. Restore the password that worked for the
// "button" redial.
//
if (pInfo->pszGoodPassword) { // Whistler bug 254385 encode password when not being used
// Assumed password was encoded by DpPasswordExpired()
//
DecodePassword( pInfo->pszGoodPassword ); lstrcpyn( pInfo->pArgs->rdp.szPassword, pInfo->pszGoodPassword, sizeof(pInfo->pArgs->rdp.szPassword) / sizeof(TCHAR) ); EncodePassword( pInfo->pArgs->rdp.szPassword );
ZeroMemory( pInfo->pszGoodPassword, (lstrlen( pInfo->pszGoodPassword ) + 1) * sizeof(TCHAR) ); Free( pInfo->pszGoodPassword ); pInfo->pszGoodPassword = NULL; }
if (pInfo->pszGoodUserName) { lstrcpyn( pInfo->pArgs->rdp.szUserName, pInfo->pszGoodUserName, sizeof(pInfo->pArgs->rdp.szUserName) / sizeof(TCHAR) ); Free( pInfo->pszGoodUserName ); pInfo->pszGoodUserName = NULL; } }
// Update cached credentials, if any, with new password.
//
// Whistler Bugs: 344019 SECBUGBASH: leaving leaked password in memory when
// user changes password over RAS
//
// 289587 Failed RAS connections reset password to blank
//
if ((pState->sidState == SID_S_Projected) && (pInfo->pszGoodPassword) && (pInfo->pszGoodUserName)) { DWORD dwErr; RASCREDENTIALS rc;
TRACE( "DpAuthNotify - Success changing password, caching if necessary" );
ZeroMemory( &rc, sizeof(rc) ); rc.dwSize = sizeof(rc);
// Look up cached password. Since we are only calling in with the
// RASCM_Password flag here, with the current implementation of
// RasGet/SetCredentials, this works for the Set below whether we are
// saving a Per-User, Global, or the special case of having both saved
// at the same time. Whew, complicated!
//
rc.dwMask = RASCM_Password; ASSERT( g_pRasGetCredentials ); TRACE( "RasGetCredentials" ); dwErr = g_pRasGetCredentials( pInfo->pArgs->pFile->pszPath, pInfo->pArgs->pEntry->pszEntryName, &rc ); TRACE2( "RasGetCredentials=%d,m=%x", dwErr, rc.dwMask );
if (dwErr == 0 && (rc.dwMask & RASCM_Password)) { // Password was cached, so update it.
//
DecodePassword( pInfo->pArgs->rdp.szPassword ); lstrcpyn( rc.szPassword, pInfo->pArgs->rdp.szPassword, sizeof(rc.szPassword) / sizeof(TCHAR) ); EncodePassword( pInfo->pArgs->rdp.szPassword );
ASSERT( g_pRasSetCredentials ); TRACE( "RasSetCredentials(p,FALSE)" ); dwErr = g_pRasSetCredentials( pInfo->pArgs->pFile->pszPath, pInfo->pArgs->pEntry->pszEntryName, &rc, FALSE ); TRACE1( "RasSetCredentials=%d", dwErr );
if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_UncachePw, dwErr, NULL ); } }
// Clean up
//
RtlSecureZeroMemory( rc.szPassword, sizeof(rc.szPassword) );
RtlSecureZeroMemory( pInfo->pszGoodPassword, (lstrlen( pInfo->pszGoodPassword ) + 1) * sizeof(TCHAR) ); Free( pInfo->pszGoodPassword ); pInfo->pszGoodPassword = NULL;
Free( pInfo->pszGoodUserName ); pInfo->pszGoodUserName = NULL; } }
VOID DpCallbackSetByCaller( IN DPINFO* pInfo, IN DPSTATE* pState )
// RASCS_CallbackSetByCaller state handling. 'PInfo' is the dialog
// context. 'PState' is the subentry state.
//
// Returns true if successful, or an error code.
//
{ TCHAR* pszDefault; TCHAR szNum[ RAS_MaxCallbackNumber + 1 ];
TRACE( "DpCallbackSetByCaller" );
pszDefault = pInfo->pArgs->pUser->pszLastCallbackByCaller; if (!pszDefault) { pszDefault = TEXT(""); }
lstrcpyn( szNum, pszDefault, RAS_MaxCallbackNumber + 1 );
if (DialCallbackDlg( pInfo->hwndDlg, szNum )) { lstrcpyn( pInfo->pArgs->rdp.szCallbackNumber, szNum, RAS_MaxCallbackNumber + 1 );
if (lstrcmp( szNum, pszDefault ) != 0) { Free0( pInfo->pArgs->pUser->pszLastCallbackByCaller ); pInfo->pArgs->pUser->pszLastCallbackByCaller = StrDup( szNum ); pInfo->pArgs->pUser->fDirty = TRUE; } } else { pInfo->pArgs->rdp.szCallbackNumber[ 0 ] = TEXT('\0'); }
pState->sidState = 0; }
BOOL GetTerminateFlag( IN DPINFO * pInfo) { BOOL ret = FALSE; __try { EnterCriticalSection( &g_csCallBacks );
ret = pInfo->fTerminateAsap; } __finally { LeaveCriticalSection( &g_csCallBacks ); }
return ret; }
BOOL SetTerminateFlag( IN DPINFO * pInfo) { BOOL ret = FALSE; __try { EnterCriticalSection( &g_csCallBacks );
ret = pInfo->fTerminateAsap = 1; TRACE1("CallActive is:%d", ret); } __finally { LeaveCriticalSection( &g_csCallBacks ); }
return ret; }
BOOL ResetTerminateFlag( IN DPINFO * pInfo) { BOOL ret = FALSE; __try { EnterCriticalSection( &g_csCallBacks );
ret = pInfo->fTerminateAsap = 0; TRACE1("CallActive is:%d", ret); } __finally { LeaveCriticalSection( &g_csCallBacks ); }
return ret; }
BOOL GetCallbackActive( IN DPINFO * pInfo) { BOOL ret = FALSE; __try { EnterCriticalSection( &g_csCallBacks );
ret = pInfo->fCallbacksActive; TRACE1("CallActive is:%d", ret); } __finally { LeaveCriticalSection( &g_csCallBacks ); }
return ret; }
BOOL SetCallbackActive( IN DPINFO * pInfo) { BOOL ret = FALSE; __try { EnterCriticalSection( &g_csCallBacks );
ret = pInfo->fCallbacksActive = 1; TRACE1("CallActive is:%d", ret); } __finally { LeaveCriticalSection( &g_csCallBacks ); }
return ret; }
BOOL ResetCallbackActive( IN DPINFO * pInfo) { BOOL ret = FALSE; __try { EnterCriticalSection( &g_csCallBacks );
ret = pInfo->fCallbacksActive = 0; TRACE1("CallActive is:%d", ret); } __finally { LeaveCriticalSection( &g_csCallBacks ); }
return ret; }
VOID DpCancel( IN DPINFO* pInfo )
// Kill the dialog and any partially initiated call, as when cancel button
// is pressed. 'PInfo' is the dialog context block.
//
{ TRACE( "DpCancel" );
// Hide window to prevent visual complaints that arise if RasHangUp takes
// a long time to complete.
//
ShowWindow( pInfo->hwndDlg, SW_HIDE );
if (pInfo->hrasconn) { DWORD dwErr;
ASSERT( g_pRasHangUp ); TRACE( "RasHangUp" );
TRACE("DpCancel:call RasHangUp");
dwErr = g_pRasHangUp( pInfo->hrasconn );
TRACE1("DpCancel:get dwErr from RasHangUp:(%d)", dwErr); TRACE1( "RasHangUp=%d", dwErr ); }
//For whistler 435725
//
if( !pInfo->fCancelPressed ) { TRACE("DpEndDialog:Cancel pressed"); pInfo->fCancelPressed = TRUE; } DpEndDialog( pInfo, FALSE ); }
BOOL DpCommand( IN DPINFO* 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.
//
{ DWORD dwErr = NO_ERROR;
TRACE3( "DpCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
TRACE2("DpCommand:pInfo address (0x%x), Dialog Handle (0x%x)", pInfo, pInfo->hwndDlg); TRACE2("DpCommand:Current proces:(0x%d), Current Thread:(0x%d)", GetCurrentProcessId(), GetCurrentThreadId());
switch (wId) { case IDCANCEL: { BOOL fCallbackActive = FALSE;
ShowWindow( pInfo->hwndDlg, SW_HIDE );
//For whistler bug 381337
//
if( !pInfo->fCancelPressed) { TRACE("DpCommand:Cancel pressed"); pInfo->fCancelPressed = TRUE; } if (pInfo->hrasconn) { ASSERT( g_pRasHangUp ); TRACE( "RasHangUp" ); dwErr = g_pRasHangUp( pInfo->hrasconn ); TRACE1( "RasHangUp=%d", dwErr ); }
// for XPSP2 511810, .Net 668164
fCallbackActive = GetCallbackActive(pInfo); if ( TRUE == fCallbackActive ) { TRACE1( "DpCommand stall, current thread's fCallbacksActive n=%d", fCallbackActive );
SetTerminateFlag(pInfo);
PostMessage( pInfo->hwndDlg, WM_COMMAND, MAKEWPARAM(wId, wNotification), (LPARAM) hwndCtrl );
//For whistler bug 378086 gangz
//to sleep a bit to give the rasdial machine a break to call our callback
//function DpRasDialFunc2()
//
Sleep(10); return TRUE; }
EndDialog( pInfo->hwndDlg, FALSE );
//Reset the pInfo->fTerminateAsap flag
// for XPSP2 511810, .Net 668164
ResetTerminateFlag(pInfo); return TRUE; } }
return FALSE; }
VOID DpConnectDevice( IN DPINFO* pInfo, IN DPSTATE* pState )
// RASCS_ConnectDevice state handling. 'PInfo' is the dialog context.
// 'PState' is the subentry state.
//
{ DWORD dwErr; RASCONNSTATUS rcs; DWORD cb; HRASCONN hrasconn; TCHAR* pszPhoneNumber;
TRACE( "DpConnectDevice" );
// Get fully translated phone number, if any.
//
ZeroMemory( &rcs, sizeof(rcs) ); rcs.dwSize = sizeof(rcs); ASSERT( g_pRasGetConnectStatus ); TRACE1( "RasGetConnectStatus($%08x)", pState->hrasconnLink ); dwErr = g_pRasGetConnectStatus( pState->hrasconnLink, &rcs ); TRACE1( "RasGetConnectStatus=%d", dwErr ); TRACEW1( " dt=%s", rcs.szDeviceType ); TRACEW1( " dn=%s", rcs.szDeviceName ); TRACEW1( " pn=%s", rcs.szPhoneNumber ); if (dwErr != 0) { pState->pbdt = PBDT_None; }
pState->pbdt = PbdevicetypeFromPszType( rcs.szDeviceType ); pszPhoneNumber = rcs.szPhoneNumber;
switch (pState->pbdt) { case PBDT_Modem: { Free0( pState->pszStatusArg ); pState->pszStatusArg = StrDup( pszPhoneNumber );
if (pInfo->pArgs->pUser->fOperatorDial && AllLinksAreModems( pInfo->pArgs->pEntry )) { pState->sidState = SID_S_ConnectModemOperator; } else if (pInfo->pArgs->pEntry->fPreviewPhoneNumber) { pState->sidState = SID_S_ConnectNumber; } else { pState->sidState = SID_S_ConnectModemNoNum; } break; }
case PBDT_Pad: { Free0( pState->pszStatusArg ); pState->pszStatusArg = StrDup( rcs.szDeviceName ); pState->sidState = SID_S_ConnectPad;
if (pState->dwError == ERROR_X25_DIAGNOSTIC) { TCHAR* psz;
// Get the X.25 diagnostic string for display in the
// custom "diagnostics" error message format.
//
Free0( pState->pszFormatArg ); pState->pszFormatArg = GetRasX25Diagnostic( pState->hrasconnLink ); } break; }
case PBDT_Switch: { Free0( pState->pszStatusArg ); pState->pszStatusArg = StrDup( rcs.szDeviceName );
pState->sidState = (pState->fNotPreSwitch) ? SID_S_ConnectPostSwitch : SID_S_ConnectPreSwitch; break; }
case PBDT_Null: { pState->sidState = SID_S_ConnectNull; break; }
case PBDT_Parallel: { pState->sidState = SID_S_ConnectParallel; break; }
case PBDT_Irda: { pState->sidState = SID_S_ConnectIrda; break; }
case PBDT_Isdn: { Free0( pState->pszStatusArg ); pState->pszStatusArg = StrDup( pszPhoneNumber ); pState->sidState = SID_S_ConnectNumber; break; }
case PBDT_Vpn: { Free0( pState->pszStatusArg ); pState->pszStatusArg = StrDup( pszPhoneNumber ); pState->sidState = SID_S_ConnectVpn; break; }
default: { Free0( pState->pszStatusArg ); if (pszPhoneNumber[ 0 ] != TEXT('\0')) { pState->pszStatusArg = StrDup( pszPhoneNumber ); pState->sidState = SID_S_ConnectNumber; } else { pState->pszStatusArg = StrDup( rcs.szDeviceName ); pState->sidState = SID_S_ConnectDevice; } break; } } }
VOID DpDeviceConnected( IN DPINFO* pInfo, IN DPSTATE* pState )
// RASCS_DeviceConnected state handling. 'PInfo' is the dialog context.
// 'PState' is the subentry state.
//
// Returns 0 if successful, or an error code.
//
{ TRACE( "DpDeviceConnected" );
switch (pState->pbdt) { case PBDT_Modem: { pState->sidState = SID_S_ModemConnected; pState->fNotPreSwitch = TRUE; break; }
case PBDT_Pad: { pState->sidState = SID_S_PadConnected; pState->fNotPreSwitch = TRUE; break; }
case PBDT_Switch: { pState->sidState = (pState->fNotPreSwitch) ? SID_S_PostSwitchConnected : SID_S_PreSwitchConnected; pState->fNotPreSwitch = TRUE; break; }
case PBDT_Null: { pState->sidState = SID_S_NullConnected; pState->fNotPreSwitch = TRUE; break; }
case PBDT_Parallel: { pState->sidState = SID_S_ParallelConnected; pState->fNotPreSwitch = TRUE; break; }
case PBDT_Irda: { pState->sidState = SID_S_IrdaConnected; pState->fNotPreSwitch = TRUE; break; }
default: { pState->sidState = SID_S_DeviceConnected; break; } } }
VOID DpDial( IN DPINFO* pInfo, IN BOOL fPauseRestart )
// Dial with the parameters in the 'pInfo' dialog context block.
// 'FPausedRestart' indicates the dial is restarting from a paused state
// and dial states should not be reset.
//
{ DWORD dwErr;
TRACE1( "DpDial,fPauseRestart=%d", fPauseRestart );
if (!fPauseRestart) { DpInitStates( pInfo ); //comment for bug 277365, 291613 gangz
//Set the fCallbacksActive to be TRUE
//
TRACE("DpDial:Init global actives");
// XPSP2 511810, .Net 668164
SetCallbackActive(pInfo); IncGlobalCallbackActive(); } else { TRACE("DpDial:WONT Init global actives for pausedRestart"); }
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( pInfo->pArgs->rdp.szPassword );
TRACE1( "RasDial(h=$%08x)", pInfo->hrasconn ); ASSERT( g_pRasDial ); dwErr = g_pRasDial( &pInfo->pArgs->rde, pInfo->pArgs->pFile->pszPath, &pInfo->pArgs->rdp, 2, (LPVOID )DpRasDialFunc2, &pInfo->hrasconn ); TRACE2( "RasDial=%d,h=$%08x", dwErr, pInfo->hrasconn );
EncodePassword( pInfo->pArgs->rdp.szPassword );
if (dwErr != 0) { // This same error will show up via the callback route on restarts
// from PAUSEd states so avoid double popups in that case. See bug
// 367482.
//
if (!fPauseRestart) { // ErrorDlg( pInfo->hwndDlg, SID_OP_RasDial, dwErr, NULL );
// For whistler 460931
//
DialErrorDlg( pInfo->hwndDlg, pInfo->pArgs, // For whistler 474514
pInfo->pArgs->pszPhonebook, pInfo->pArgs->pszEntry, dwErr, SID_OP_RasDial, NULL, SID_FMT_ErrorMsg, NULL, -2, TRUE); //for XPSP2 511810, .Net 668164
ResetCallbackActive(pInfo); DecGlobalCallbackActive(); } // If we receive error 668 here, it means that a rasevent is currently
// posted for state RASCS_Disconnected. We shouldn't cancel in this
// case since we Normal processing of RASCS_Disconnected will allow the
// user to redial. Also, calling DpCancel below will insert
// WM_DESTROY which will process before the popup that the rasevent
// produces can display. 367482
//
if (dwErr != ERROR_NO_CONNECTION) { DpCancel( pInfo ); } } }
VOID DpError( IN DPINFO* pInfo, IN DPSTATE* pState )
// Popup error dialog for error identified by 'pState' and cancel or
// redial as indicated by user. 'PInfo' is the dialog context.
//
{ DWORD dwErr; DWORD dwRedialAttemptsLeft; DWORD sidState;
TRACE( "DpError" );
// Retrieve additional text from RASMXS on those special errors where the
// device returned something useful to display.
//
if (pState->dwError == ERROR_FROM_DEVICE || pState->dwError == ERROR_UNRECOGNIZED_RESPONSE) { TCHAR* pszMessage;
dwErr = GetRasMessage( pInfo->hrasconn, &pszMessage ); if (dwErr == 0) { pState->sidFormatMsg = SID_FMT_ErrorMsgResp; Free0( pState->pszFormatArg ); pState->pszFormatArg = pszMessage; } }
if (pState->sidFormatMsg == 0) { if (pState->dwExtendedError != 0) { // Translate extended error code into arguments.
//
TCHAR szNum[ 2 + MAXLTOTLEN + 1 ];
pState->sidFormatMsg = SID_FMT_ErrorMsgExt;
szNum[ 0 ] = TEXT('0'); szNum[ 1 ] = TEXT('x'); LToT( pState->dwExtendedError, szNum + 2, 16 );
Free0( pState->pszFormatArg ); pState->pszFormatArg = StrDup( szNum ); } else if (pState->szExtendedError[ 0 ] != TEXT('\0')) { // Translate extended error string to argument. Currently, the
// string is always a NetBIOS name.
//
pState->sidFormatMsg = SID_FMT_ErrorMsgName; Free0( pState->pszFormatArg ); pState->pszFormatArg = StrDup( pState->szExtendedError ); } }
if (pInfo->hrasconn) { // Hang up before displaying error popup so server side resources are
// not tied up waiting for client to acknowledge error.
//
ASSERT( g_pRasHangUp ); TRACE( "RasHangUp" ); dwErr = g_pRasHangUp( pInfo->hrasconn ); TRACE1( "RasHangUp=%d", dwErr ); pInfo->hrasconn = NULL; }
if (pInfo->pArgs->pEntry->pszPrerequisiteEntry && *pInfo->pArgs->pEntry->pszPrerequisiteEntry) { // Select "no Redial button" mode for entries that have prerequisite
// entries. This is because RASMAN drops the prerequisite entry as
// soon as the dependent entry fails, thus dooming to defeat a redial
// of only the dependent entry. Yes, it should really redial both
// entries here, but that is not really feasible with the current
// non-integrated serial implementation of prerequisite entries. This
// at least improves the poor behavior cited in bug 230594.
//
dwRedialAttemptsLeft = -2; } else if (pInfo->dwRedialAttemptsLeft <= 0) { // No auto-redial countdown, but "Redial" button does appear in place
// of the default "OK".
//
dwRedialAttemptsLeft = -1; } else { // Auto-redial countdown based on the entries configuration.
//
dwRedialAttemptsLeft = GetOverridableParam( pInfo->pArgs->pUser, pInfo->pArgs->pEntry, RASOR_RedialSeconds ); }
// This hack works around a bug in RasDial API. See bug 313102.
//
sidState = pState ->sidState; if (!sidState) { sidState = SID_S_AuthNotify; }
if (DialErrorDlg( pInfo->hwndDlg, pInfo->pArgs, // For whistler 474514
pInfo->pArgs->pszPhonebook, // For whislter 460931
pInfo->pArgs->pEntry->pszEntryName, pState->dwError, sidState, pState->pszStatusArg, pState->sidFormatMsg, pState->pszFormatArg, dwRedialAttemptsLeft, GetOverridableParam( pInfo->pArgs->pUser, pInfo->pArgs->pEntry, RASOR_PopupOnTopWhenRedialing ) )) { TRACE( "User redials" ); if (pInfo->dwRedialAttemptsLeft > 0) { --pInfo->dwRedialAttemptsLeft; }
TRACE(" Post(DIAL)" ); PostMessage( pInfo->hwndDlg, WM_RASDIAL, FALSE, 0 ); } else { TRACE( "User cancels" ); DpCancel( pInfo ); }
//
// Set the error so that the error is propagated back
// to the caller of the RasDialDlg api.
//
TRACE2("DpError settings error (0x%x) to %d", &pInfo->pArgs->pArgs->dwError, pState->dwError); pInfo->pArgs->pArgs->dwError = pState->dwError; }
// For whistler 435725
//
void DpEndDialog( IN DPINFO * pInfo, IN BOOL fFlag) {
PostMessage( pInfo->hwndDlg, WM_DPENDDIALOG, 0, (WPARAM)fFlag ); }
DWORD DpEvent( IN DPINFO* pInfo, IN DWORD dwSubEntry )
// Handle a RasDial callback event on subentry 'dwSubEntry'. 'PInfo' is
// the dialog context.
//
// Return 0 to stop callbacks from RasDial, or 1 to continue callbacks
// (normal), or 2 to indicate that the phonebook entry has changed and
// should be re-read by RasDial.
//
{ DWORD dwErr; DWORD dwCode; BOOL fLeader; DWORD dwcSuccessLinks, dwcFailedLinks, i; DPSTATE* pState; BOOL fPartialMultilink; BOOL fIsLaterState;
TRACE( "DpEvent" );
// Default to "normal" return.
//
dwCode = 1; fPartialMultilink = FALSE;
TRACE2("Current proces:(0x%d), Current Thread:(0x%d)", GetCurrentProcessId(), GetCurrentThreadId()); // Find the associated state information and figure out if this is the
// most advanced sub-entry.
//
pState = &pInfo->pStates[ dwSubEntry - 1 ]; fIsLaterState = DpIsLaterState( pState->state, pInfo->state ); if (dwSubEntry == pInfo->dwSubEntry || fIsLaterState) { fLeader = TRUE; if (fIsLaterState) { pInfo->dwSubEntry = dwSubEntry; pInfo->state = pState->state; } } else { fLeader = FALSE; TRACE( "Trailing" ); }
// Execute the state.
//
TRACE1("State is:(%d)", pState->state);
switch (pState->state) { case RASCS_OpenPort: { pState->pbdt = PBDT_None; pState->sidState = SID_S_OpenPort; break; }
case RASCS_PortOpened: { // Should have an hrasconnLink for this subentry now. Look it up
// and stash it in our context.
//
ASSERT( g_pRasGetSubEntryHandle ); TRACE1( "RasGetSubEntryHandle(se=%d)", dwSubEntry ); dwErr = g_pRasGetSubEntryHandle( pInfo->hrasconn, dwSubEntry, &pState->hrasconnLink ); TRACE2( "RasGetSubEntryHandle=%d,hL=$%08x", dwErr, pState->hrasconnLink ); if (dwErr != 0) { pState->dwError = dwErr; }
pState->sidState = SID_S_PortOpened; break; }
case RASCS_ConnectDevice: { DTLNODE* pNode; PBLINK* pLink;
pNode = DtlNodeFromIndex( pInfo->pArgs->pEntry->pdtllistLinks, dwSubEntry - 1 ); ASSERT( pNode );
if(NULL == pNode) { pState->dwError = ERROR_NOT_ENOUGH_MEMORY; } else { pLink = (PBLINK* )DtlGetData( pNode ); }
if ((pState->dwError == ERROR_PORT_OR_DEVICE && (pLink->pbport.fScriptBeforeTerminal || pLink->pbport.fScriptBefore)) || (pState->dwError == ERROR_USER_DISCONNECTION && (pInfo->pArgs->pUser->fOperatorDial && AllLinksAreModems( pInfo->pArgs->pEntry )))) { // This happens when user presses Cancel on the Unimodem
// "Pre-Dial Terminal Screen" or "Operator Assisted or Manual
// Dial" dialog.
//
TRACE("DpEvent:Call DpCancel() in connectDevice, but still return 1\n"); DpCancel( pInfo ); return dwCode; }
DpConnectDevice( pInfo, pState ); break; }
case RASCS_DeviceConnected: { DpDeviceConnected( pInfo, pState ); break; }
case RASCS_AllDevicesConnected: { pState->sidState = SID_S_AllDevicesConnected; break; }
case RASCS_Authenticate: { pState->sidState = SID_S_Authenticate; break; }
case RASCS_AuthNotify: { DpAuthNotify( pInfo, pState ); break; }
case RASCS_AuthRetry: { pState->sidState = SID_S_AuthRetry; break; }
case RASCS_AuthCallback: { pState->sidState = SID_S_AuthCallback; break; }
case RASCS_AuthChangePassword: { pState->sidState = SID_S_AuthChangePassword; break; }
case RASCS_AuthProject: { pState->sidState = SID_S_AuthProject; break; }
case RASCS_AuthLinkSpeed: { pState->sidState = SID_S_AuthLinkSpeed; break; }
case RASCS_AuthAck: { pState->sidState = SID_S_AuthAck; break; }
case RASCS_ReAuthenticate: { pState->sidState = SID_S_ReAuthenticate; break; }
case RASCS_Authenticated: { pState->sidState = SID_S_Authenticated; break; }
case RASCS_PrepareForCallback: { pState->sidState = SID_S_PrepareForCallback; break; }
case RASCS_WaitForModemReset: { pState->sidState = SID_S_WaitForModemReset; break; }
case RASCS_WaitForCallback: { pState->sidState = SID_S_WaitForCallback; break; }
case RASCS_Projected: { if (fLeader) { // If DpProjected returns FALSE, it detected a fatal error,
// and the dialing process will stop. If DpProjected returns
// with pState->dwError non-zero, we display the error in a
// redial dialog, if redial is configured.
//
if (!DpProjected( pInfo, pState )) { TRACE("DpEvent:Call DpCancel() in RASCS_Projected, but still return 1 to DpRasDialFunc2()\n"); DpCancel( pInfo ); return dwCode; } else if (pState->dwError) { TRACE("DpCancel() in RASCS_Projected,return 0 to DpRasDialFunc2()"); TRACE( "DpEvent:Post(ERROR), return 0 to DpRasDialFunc2()" ); PostMessage( pInfo->hwndDlg, WM_RASERROR, 0, (LPARAM )pState ); return 0; } } break; }
case RASCS_Interactive: { BOOL fChange = FALSE;
if (!DpInteractive( pInfo, pState, &fChange )) { DpCancel( pInfo ); return dwCode; }
if (fChange) { dwCode = 2; } break; }
case RASCS_RetryAuthentication: { if (!RetryAuthenticationDlg( pInfo->hwndDlg, pInfo->pArgs )) { DpCancel( pInfo ); return dwCode; }
pState->sidState = 0; break; }
case RASCS_InvokeEapUI: { if (g_pRasInvokeEapUI( pInfo->hrasconn, dwSubEntry, &pInfo->pArgs->rde, pInfo->hwndDlg )) { DpCancel( pInfo ); return dwCode; }
pState->sidState = 0; break; }
case RASCS_CallbackSetByCaller: { DpCallbackSetByCaller( pInfo, pState ); break; }
case RASCS_PasswordExpired: { if (!DpPasswordExpired( pInfo, pState )) { DpCancel( pInfo ); return dwCode; } break; }
case RASCS_SubEntryConnected: { if (pInfo->cStates > 1) { pState->sidState = SID_S_SubConnected; } break; }
case RASCS_SubEntryDisconnected: { break; }
case RASCS_Connected: { pState->sidState = SID_S_Connected; break; }
case RASCS_Disconnected: { pState->sidState = SID_S_Disconnected; break; }
default: { pState->sidState = SID_S_Unknown; break; } }
// Count the successful and failed links.
//
{ DPSTATE* p;
dwcSuccessLinks = dwcFailedLinks = 0; for (i = 0, p = pInfo->pStates; i < pInfo->cStates; ++i, ++p) { if (p->state == RASCS_SubEntryConnected) { ++dwcSuccessLinks; }
if (p->dwError) { ++dwcFailedLinks; } } } TRACE3( "s=%d,f=%d,t=%d", dwcSuccessLinks, dwcFailedLinks, pInfo->cStates );
if (pState->dwError) { DTLNODE *pdtlnode = NULL; DWORD dwIndex = pInfo->pArgs->rdp.dwSubEntry;
if(0 != dwIndex) {
pdtlnode = DtlNodeFromIndex( pInfo->pArgs->pEntry->pdtllistLinks, dwIndex - 1); }
if ( (dwcFailedLinks == pInfo->cStates) || ( (RASEDM_DialAll != pInfo->pArgs->pEntry->dwDialMode) && (dwcSuccessLinks == 0)) || (NULL != pdtlnode)) { // A terminal error state has occurred on all links. Post a
// message telling ourselves to popup an error, then release the
// callback so it doesn't hold the port open while the error popup
// is up,
//
TRACE( "Post(ERROR)" ); PostMessage( pInfo->hwndDlg, WM_RASERROR, 0, (LPARAM )pState ); return 0; } else if (dwcSuccessLinks + dwcFailedLinks == pInfo->cStates) { // An error occurred on the final link, but some link connected.
// It would be nice if RasDial would followup with a
// RASCS_Connected in that case, but it doesn't, so we duplicate
// the RASCS_Connected-style exit here.
//
TRACE( "Post(BUNDLEERROR)" ); PostMessage( pInfo->hwndDlg, WM_RASBUNDLEERROR, 0, (LPARAM )pState ); return 0; }
// A fatal error has occurred on a link, but there are other links
// still trying, so let it die quietly.
//
TRACE2( "Link %d fails, e=%d", dwSubEntry + 1, pState->dwError ); return dwCode; }
// Display the status string for this state.
//
if (pState->sidState) { if (pState->sidState != pState->sidPrevState) { pState->sidPrevState = pState->sidState; }
if (fLeader) { TCHAR* pszState = PszFromId( g_hinstDll, pState->sidState );
if ( (NULL != pszState) && pState->pszStatusArg) { TCHAR* pszFormattedState; TCHAR* pszArg; TCHAR* apszArgs[ 1 ]; DWORD cch;
pszArg = (pState->pszStatusArg) ? pState->pszStatusArg : TEXT("");
// Find length of formatted string with text argument (if any)
// inserted and any progress dots appended.
//
cch = lstrlen( pszState ) + lstrlen( pszArg ) + 1;
pszFormattedState = Malloc( cch * sizeof(TCHAR) ); if (pszFormattedState) { apszArgs[ 0 ] = pszArg; *pszFormattedState = TEXT('\0');
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszState, 0, 0, pszFormattedState, cch, (va_list* )apszArgs );
Free( pszState ); pszState = pszFormattedState; } }
TRACE1("DpEvent:State:'%s'",pszState); if (pszState) { SetWindowText( pInfo->hwndStState, pszState ); InvalidateRect( pInfo->hwndStState, NULL, TRUE ); UpdateWindow( pInfo->hwndStState ); LocalFree( pszState ); } } }
if (pState->state & RASCS_PAUSED) { // Paused state just processed. Release the callback, and dial again
// to resume.
//
TRACE("DpEvent:Paused, will dial again\nthe global callbacks wont init again"); TRACE( "Post(DIAL)" ); PostMessage( pInfo->hwndDlg, WM_RASDIAL, TRUE, 0 ); return dwCode; }
if (pState->state & RASCS_DONE) { // Terminal state just processed.
//
if (pState->state == RASCS_Connected) { // For multi-link entries, if there is at least one successful
// line and at least one failed line, popup the bundling error
// dialog.
//
if (pInfo->cStates > 1) { DPSTATE* p;
dwcSuccessLinks = dwcFailedLinks = 0; for (i = 0, p = pInfo->pStates; i < pInfo->cStates; ++i, ++p) { if (p->dwError == 0) { ++dwcSuccessLinks; } else { ++dwcFailedLinks; } }
if (dwcSuccessLinks > 0 && dwcFailedLinks > 0) { TRACE( "Post(BUNDLEERROR)" ); PostMessage( pInfo->hwndDlg, WM_RASBUNDLEERROR, 0, (LPARAM )pState ); return 0; } }
//For whistler 435725
//
DpEndDialog( pInfo, TRUE ); } else { DpCancel( pInfo ); }
return 0; }
TRACE1("DpEvent:returned dwCode:(%d)", dwCode); TRACE("End of DpEvent"); return dwCode; }
BOOL DpInit( IN HWND hwndDlg, IN DINFO* 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; DPINFO* pInfo; PBENTRY* pEntry;
TRACE( "DpInit" );
// 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->dwValid = 0xC0BBC0DE; pInfo->pArgs = pArgs; pInfo->hwndDlg = hwndDlg;
//Add a per-thread Terminate flag for whistler bug 291613 gangz
//
pInfo->fTerminateAsap = FALSE;
// for XPSP2 511810, .Net 668164, 668164
pInfo->pcsActiveLock = (CRITICAL_SECTION*)Malloc(sizeof(CRITICAL_SECTION)); if(NULL == pInfo->pcsActiveLock ) { TRACE("No memory for critical section"); ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); EndDialog( hwndDlg, FALSE ); return TRUE; } __try { InitializeCriticalSection( pInfo->pcsActiveLock ); } __except(EXCEPTION_EXECUTE_HANDLER) { DWORD dwExceptionCode = GetExceptionCode(); TRACE1("InitializeCriticalSection() raise:0x%x",dwExceptionCode); ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); EndDialog( hwndDlg, FALSE ); return TRUE; } SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo ); TRACE( "Context set" ); }
pInfo->hwndStState = GetDlgItem( hwndDlg, CID_DP_ST_State ); ASSERT( pInfo->hwndStState );
pEntry = pArgs->pEntry;
// Set up our context to be returned by the RasDialFunc2 callback.
//
pInfo->pArgs->rdp.dwCallbackId = (ULONG_PTR )pInfo;
// Subclass the dialog so we can get the result from
// SendMessage(WM_RASDIALEVENT) in RasDlgFunc2.
//
pInfo->pOldWndProc = (WNDPROC )SetWindowLongPtr( pInfo->hwndDlg, GWLP_WNDPROC, (ULONG_PTR )DpWndProc );
// Set the title.
//
{ TCHAR* pszTitleFormat; TCHAR* pszTitle; TCHAR* apszArgs[ 1 ];
pszTitleFormat = GetText( hwndDlg ); if (pszTitleFormat) { apszArgs[ 0 ] = pEntry->pszEntryName; pszTitle = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1, (va_list* )apszArgs );
Free( pszTitleFormat );
if (pszTitle) { SetWindowText( hwndDlg, pszTitle ); LocalFree( pszTitle ); } } }
// Set the correct icon. For whistler bug 372078 gangz
//
SetIconFromEntryType( GetDlgItem( hwndDlg, CID_DP_Icon ), pArgs->pEntry->dwType, FALSE); //FALSE means large Icon
// Position the dialog per caller's instructions.
//
PositionDlg( hwndDlg, pArgs->pArgs->dwFlags & RASDDFLAG_PositionDlg, pArgs->pArgs->xDlg, pArgs->pArgs->yDlg );
// Hide the dialog if "no progress" user preference is set.
//
if (!pArgs->pEntry->fShowDialingProgress || pArgs->fDialForReferenceOnly) { SetOffDesktop( hwndDlg, SOD_MoveOff, NULL ); }
SetForegroundWindow( hwndDlg );
// Allocate subentry status array. It's initialized by DpDial.
//
{ DWORD cb;
ASSERT( pEntry->pdtllistLinks ); pInfo->cStates = DtlGetNodes( pEntry->pdtllistLinks ); cb = sizeof(DPSTATE) * pInfo->cStates; pInfo->pStates = Malloc( cb ); if (!pInfo->pStates) { ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); EndDialog( hwndDlg, FALSE ); return TRUE; }
pInfo->dwRedialAttemptsLeft = GetOverridableParam( pInfo->pArgs->pUser, pInfo->pArgs->pEntry, RASOR_RedialAttempts ); }
//for whistler bug 316622 gangz
//The dwSubEntry is not initialized
//
pInfo->pArgs->rdp.dwSubEntry = pInfo->pArgs->pArgs->dwSubEntry; // Rock and roll.
//
DpDial( pInfo, FALSE );
return TRUE; }
VOID DpInitStates( DPINFO* pInfo )
// Resets 'pInfo->pStates' to initial values. 'PInfo' is the dialog
// context.
//
{ DWORD i; DPSTATE* pState;
for (i = 0, pState = pInfo->pStates; i < pInfo->cStates; ++i, ++pState) { ZeroMemory( pState, sizeof(*pState) ); pInfo->state = (RASCONNSTATE )-1; pState->dwError = 0; } }
BOOL DpInteractive( IN DPINFO* pInfo, IN DPSTATE* pState, OUT BOOL* pfChange )
// RASCS_Interactive handling. 'PInfo' is the dialog context. 'PState'
// is the subentry state. '*pfChange' is set true if the entry (i.e. SLIP
// address) was changed or false otherwise.
//
// Returns true if successful, false if cancel.
//
{ DWORD dwErr = NO_ERROR; DWORD sidTitle; TCHAR szIpAddress[ TERM_IpAddress ]; TCHAR* pszIpAddress; PBENTRY* pEntry;
TRACE( "DpInteractive" );
*pfChange = FALSE; pEntry = pInfo->pArgs->pEntry;
if (pEntry->dwBaseProtocol == BP_Slip) { lstrcpyn( szIpAddress, (pEntry->pszIpAddress) ? pEntry->pszIpAddress : TEXT("0.0.0.0"), sizeof(szIpAddress) / sizeof(TCHAR)); pszIpAddress = szIpAddress; sidTitle = SID_T_SlipTerminal; } else { szIpAddress[0] = TEXT('\0'); pszIpAddress = szIpAddress; sidTitle = (pState->sidState == SID_S_ConnectPreSwitch) ? SID_T_PreconnectTerminal : (pState->sidState == SID_S_ConnectPostSwitch) ? SID_T_PostconnectTerminal : SID_T_ManualDialTerminal; }
if(1 == pEntry->dwCustomScript) { dwErr = DwCustomTerminalDlg( pInfo->pArgs->pFile->pszPath, pInfo->hrasconn, pEntry, pInfo->hwndDlg, &pInfo->pArgs->rdp, NULL);
if(SUCCESS == dwErr) { #if 0
//
// Reread the phonebook file since the
// custom script could have written
// new information to the file.
//
ClosePhonebookFile(pInfo->pArgs->pFile);
dwErr = ReadPhonebookFile( pInfo->pArgs->pszPhonebook, &pInfo->pArgs->user, NULL, 0, &pInfo->pArgs->file );
if(SUCCESS == dwErr) { pInfo->pArgs->pFile = &pInfo->pArgs->file; } #endif
} if ( 0 != dwErr ) { ErrorDlg( pInfo->hwndDlg, SID_OP_ScriptHalted, dwErr, NULL ); } return (ERROR_SUCCESS == dwErr); }
if (!TerminalDlg( pInfo->pArgs->pEntry, &pInfo->pArgs->rdp, pInfo->hwndDlg, pState->hrasconnLink, sidTitle, pszIpAddress )) { TRACE( "TerminalDlg==FALSE" ); return FALSE; }
TRACE2( "pszIpAddress=0x%08x(%ls)", pszIpAddress, pszIpAddress ? pszIpAddress : TEXT("") ); TRACE2( "pEntry->pszIpAddress=0x%08x(%ls)", pEntry->pszIpAddress, pEntry->pszIpAddress ? pEntry->pszIpAddress : TEXT("") );
if (pszIpAddress[0] && (!pEntry->pszIpAddress || lstrcmp( pszIpAddress, pEntry->pszIpAddress ) != 0)) { Free0( pEntry->pszIpAddress ); pEntry->pszIpAddress = StrDup( szIpAddress ); pEntry->fDirty = TRUE; *pfChange = TRUE;
dwErr = WritePhonebookFile( pInfo->pArgs->pFile, NULL ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook, dwErr, NULL ); } }
pState->sidState = 0; return TRUE; }
BOOL DpIsLaterState( IN RASCONNSTATE stateNew, IN RASCONNSTATE stateOld )
// Returns true if 'stateNew' is farther along in the connection than
// 'stateOld' false if the same or not as far along.
//
{ // This array is in the order events normally occur.
//
// !!! New EAP states?
//
static RASCONNSTATE aState[] = { (RASCONNSTATE )-1, RASCS_OpenPort, RASCS_PortOpened, RASCS_ConnectDevice, RASCS_DeviceConnected, RASCS_Interactive, RASCS_AllDevicesConnected, RASCS_StartAuthentication, RASCS_Authenticate, RASCS_InvokeEapUI, RASCS_AuthNotify, RASCS_AuthRetry, RASCS_AuthAck, RASCS_PasswordExpired, RASCS_AuthChangePassword, RASCS_AuthCallback, RASCS_CallbackSetByCaller, RASCS_PrepareForCallback, RASCS_WaitForModemReset, RASCS_WaitForCallback, RASCS_CallbackComplete, RASCS_RetryAuthentication, RASCS_ReAuthenticate, RASCS_Authenticated, RASCS_AuthLinkSpeed, RASCS_AuthProject, RASCS_Projected, RASCS_LogonNetwork, RASCS_SubEntryDisconnected, RASCS_SubEntryConnected, RASCS_Disconnected, RASCS_Connected, (RASCONNSTATE )-2, };
RASCONNSTATE* pState;
for (pState = aState; *pState != (RASCONNSTATE )-2; ++pState) { if (*pState == stateNew) { return FALSE; } else if (*pState == stateOld) { return TRUE; } }
return FALSE; }
BOOL DpPasswordExpired( IN DPINFO* pInfo, IN DPSTATE* pState )
// RASCS_PasswordExpired state handling. 'PInfo' is the dialog context.
// 'PState' is the subentry state.
//
// Returns true if successful, false otherwise.
//
{ TCHAR szOldPassword[ PWLEN + 1 ]; BOOL fSuppliedOldPassword;
TRACE( "DpPasswordExpired" );
szOldPassword[ 0 ] = TEXT('\0');
// Stash "good" username and password which are restored if the password
// change fails.
//
pInfo->pszGoodUserName = StrDup( pInfo->pArgs->rdp.szUserName );
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( pInfo->pArgs->rdp.szPassword ); pInfo->pszGoodPassword = StrDup( pInfo->pArgs->rdp.szPassword ); EncodePassword( pInfo->pArgs->rdp.szPassword ); EncodePassword( pInfo->pszGoodPassword );
fSuppliedOldPassword = (!pInfo->pArgs->pEntry->fAutoLogon || pInfo->pArgs->pNoUser);
if (!ChangePasswordDlg( pInfo->hwndDlg, !fSuppliedOldPassword, szOldPassword, pInfo->pArgs->rdp.szPassword )) { // Whistler bug 254385 encode password when not being used
//
RtlSecureZeroMemory( szOldPassword, sizeof(szOldPassword) ); return FALSE; }
if (pInfo->pArgs->pNoUser) { // Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( pInfo->pArgs->rdp.szPassword ); lstrcpyn( pInfo->pArgs->pNoUser->szPassword, pInfo->pArgs->rdp.szPassword, PWLEN + 1); EncodePassword( pInfo->pArgs->rdp.szPassword ); EncodePassword( pInfo->pArgs->pNoUser->szPassword ); *pInfo->pArgs->pfNoUserChanged = TRUE; }
// The old password (in text form) is explicitly set, since in AutoLogon
// case a text form has not yet been specified. The old password in text
// form is required to change the password. The "old" private API expects
// an ANSI argument.
//
if (!fSuppliedOldPassword) { // Whistler bug 254385 encode password when not being used
// Assumed password was encoded by ChangePasswordDlg()
//
CHAR* pszOldPasswordA;
DecodePassword( szOldPassword ); pszOldPasswordA = StrDupAFromT( szOldPassword ); if (pszOldPasswordA) { ASSERT( g_pRasSetOldPassword ); g_pRasSetOldPassword( pInfo->hrasconn, pszOldPasswordA ); RtlSecureZeroMemory( pszOldPasswordA, lstrlenA( pszOldPasswordA ) ); Free( pszOldPasswordA ); } }
RtlSecureZeroMemory( szOldPassword, sizeof(szOldPassword) );
if (pInfo->pArgs->rdp.szUserName[ 0 ] == TEXT('\0')) { // Explicitly set the username, effectively turning off AutoLogon for
// the "resume" password authentication, where the new password should
// be used.
//
lstrcpyn( pInfo->pArgs->rdp.szUserName, GetLogonUser(), UNLEN + 1 ); }
pState->sidState = 0; return TRUE; }
BOOL DpProjected( IN DPINFO* pInfo, IN DPSTATE* pState )
// RASCS_Projected state handling. 'PInfo' is the dialog context.
// 'PState' is the subentry state.
//
// Returns true if successful, false otherwise.
//
{ DWORD dwErr; RASAMB amb; RASPPPNBF nbf; RASPPPIPX ipx; RASPPPIP ip; RASPPPLCP lcp; RASSLIP slip; RASPPPCCP ccp; BOOL fIncomplete; DWORD dwfProtocols; TCHAR* pszLines;
TRACE( "DpProjected" );
pState->sidState = SID_S_Projected;
//
// If PORT_NOT_OPEN is indicated, it probably means that the
// server disconnected the connection before result dialog
// was dismissed. In that case, this is the 2nd time DpProjected
// is called. This time, the error is indicated by ras and the
// state remains "projected".
//
// We need to return an error in this case so that the connection
// isn't hung since this is the last indication RAS will give us.
//
// See bug 382254
//
TRACE1("DpProjected: dwErr:(%d)", pState->dwError); if ( (pState->dwError == ERROR_PORT_NOT_OPEN) || (pState->dwError == ERROR_NO_CONNECTION) ) //See bug 169111 whistler
{ return FALSE; }
// Do this little dance to ignore the error that comes back from the
// "all-failed" projection since we detect this in the earlier
// notification where pState->dwError == 0. This avoids a race where the
// API comes back with the error before we can hang him up. This race
// would not occur if we called RasHangUp from within the callback thread
// (as recommended in our API doc). It's the price we pay for posting the
// error to the other thread in order to avoid holding the port open while
// an error dialog is up.
//
else if (pState->dwError != 0) { pState->dwError = 0;
//For XPSP2 511810, .Net 668164
ResetCallbackActive(pInfo); DecGlobalCallbackActive(); return TRUE; }
// Read projection info for all protocols, translating "not requested"
// into an in-structure code for later reference.
//
dwErr = GetRasProjectionInfo( pState->hrasconnLink, &amb, &nbf, &ip, &ipx, &lcp, &slip, &ccp ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_RasGetProtocolInfo, dwErr, NULL ); return FALSE; }
if (amb.dwError != ERROR_PROTOCOL_NOT_CONFIGURED) { // It's an AMB projection.
//
if (amb.dwError != 0) { // Translate AMB projection errors into regular error codes. AMB
// does not use the special PPP projection error mechanism.
//
pState->dwError = amb.dwError; lstrcpyn( pState->szExtendedError, amb.szNetBiosError, sizeof(pState->szExtendedError) / sizeof(TCHAR)); } return TRUE; }
// At this point, all projection information has been gathered
// successfully and we know it's a PPP-based projection. Now analyze the
// projection results...
//
dwfProtocols = 0; fIncomplete = FALSE; if (DpProjectionError( &nbf, &ipx, &ip, &fIncomplete, &dwfProtocols, &pszLines, &pState->dwError )) { // A projection error occurred.
//
if (fIncomplete) { BOOL fStatus; BOOL fDisable;
// An incomplete projection occurred, i.e. some requested CPs
// connected and some did not. Ask the user if what worked is
// good enough or he wants to bail.
//
pState->dwError = 0; fDisable = FALSE; fStatus = ProjectionResultDlg( pInfo->hwndDlg, pszLines, &fDisable ); Free( pszLines );
if (fDisable) { pInfo->pArgs->dwfExcludedProtocols = dwfProtocols; }
// Return now if user chose to hang up.
//
if (!fStatus) { return FALSE; } } else { // All CPs in the projection failed. Process as a regular fatal
// error with 'pState->dwError' set to the first error in NBF, IP,
// or IPX, but with a format that substitutes the status argument
// for the "Error nnn: Description" text. This lets us patch in
// the special multiple error projection text, while still giving
// a meaningful help context.
//
Free0( pState->pszFormatArg ); pState->pszFormatArg = pszLines; pState->sidFormatMsg = SID_FMT_ErrorMsgProject; } }
//
// pmay: 190394
//
// If the admin has a message, display it.
//
if ( (pState->dwError == NO_ERROR) && (wcslen (lcp.szReplyMessage) != 0) ) { MSGARGS MsgArgs, *pMsgArgs = &MsgArgs;
ZeroMemory(pMsgArgs, sizeof(MSGARGS)); pMsgArgs->dwFlags = MB_OK | MB_ICONINFORMATION; pMsgArgs->apszArgs[0] = lcp.szReplyMessage;
//MsgDlg(
// pInfo->hwndDlg,
// SID_ReplyMessageFmt,
// pMsgArgs);
}
pState->sidState = SID_S_Projected; return TRUE; }
BOOL DpProjectionError( IN RASPPPNBF* pnbf, IN RASPPPIPX* pipx, IN RASPPPIP* pip, OUT BOOL* pfIncomplete, OUT DWORD* pdwfFailedProtocols, OUT TCHAR** ppszLines, OUT DWORD* pdwError )
// Figure out if a projection error occurred and, if so, build the
// appropriate status/error text lines into '*ppszLines'. '*PfIncomlete'
// is set true if at least one CP succeeded and at least one failed.
// '*pdwfFailedProtocols' is set to the bit mask of NP_* that failed.
// '*pdwError' is set to the first error that occurred in NBF, IP, or IPX
// in that order or 0 if none. 'pnbf', 'pipx', and 'pip' are projection
// information for the respective protocols with dwError set to
// ERROR_PROTOCOL_NOT_CONFIGURED if the protocols was not requested.
//
// This routine assumes that at least one protocol was requested.
//
// Returns true if a projection error occurred, false if not. It's
// caller's responsiblity to free '*ppszLines'.
//
{ #define MAXPROJERRLEN 1024
TCHAR szLines[ MAXPROJERRLEN ]; BOOL fIp = (pip->dwError != ERROR_PROTOCOL_NOT_CONFIGURED); BOOL fIpx = (pipx->dwError != ERROR_PROTOCOL_NOT_CONFIGURED); BOOL fNbf = (pnbf->dwError != ERROR_PROTOCOL_NOT_CONFIGURED); BOOL fIpBad = (fIp && pip->dwError != 0); BOOL fIpxBad = (fIpx && pipx->dwError != 0); BOOL fNbfBad = (fNbf && pnbf->dwError != 0);
TRACE( "DpProjectionError" );
*pdwfFailedProtocols = 0; if (!fNbfBad && !fIpxBad && !fIpBad) { return FALSE; }
if (fNbfBad) { *pdwfFailedProtocols |= NP_Nbf; } if (fIpxBad) { *pdwfFailedProtocols |= NP_Ipx; } if (fIpBad) { *pdwfFailedProtocols |= NP_Ip; }
*pfIncomplete = ((fIp && pip->dwError == 0) || (fIpx && pipx->dwError == 0) || (fNbf && pnbf->dwError == 0));
szLines[ 0 ] = 0; *ppszLines = NULL; *pdwError = 0;
if (fIpBad || (*pfIncomplete && fIp)) { if (fIpBad) { *pdwError = pip->dwError; DpAppendConnectErrorLine( szLines, SID_Ip, pip->dwError ); } else { DpAppendConnectOkLine( szLines, SID_Ip ); } DpAppendBlankLine( szLines ); }
if (fIpxBad || (*pfIncomplete && fIpx)) { if (fIpxBad) { *pdwError = pipx->dwError; DpAppendConnectErrorLine( szLines, SID_Ipx, pipx->dwError ); } else { DpAppendConnectOkLine( szLines, SID_Ipx ); } DpAppendBlankLine( szLines ); }
if (fNbfBad || (*pfIncomplete && fNbf)) { if (fNbfBad) { *pdwError = pnbf->dwError; DpAppendConnectErrorLine( szLines, SID_Nbf, pnbf->dwError );
if (pnbf->dwNetBiosError) { DpAppendFailCodeLine( szLines, pnbf->dwNetBiosError ); }
if (pnbf->szNetBiosError[ 0 ] != '\0') { DpAppendNameLine( szLines, pnbf->szNetBiosError ); } } else { DpAppendConnectOkLine( szLines, SID_Nbf ); } DpAppendBlankLine( szLines ); }
*ppszLines = StrDup( szLines ); return TRUE; }
DWORD WINAPI DpRasDialFunc2( ULONG_PTR dwCallbackId, DWORD dwSubEntry, HRASCONN hrasconn, UINT unMsg, RASCONNSTATE state, DWORD dwError, DWORD dwExtendedError )
// RASDIALFUNC2 callback to receive RasDial events.
//
// Returns 0 to stop callbacks, 1 to continue callbacks (normal), and 2 to
// tell RAS API that relevant entry information (like SLIP IP address) has
// changed.
//
{ DWORD dwErr; DWORD dwCode; DPINFO* pInfo; DPSTATE* pState; BOOL fTerminateAsap; long ulCallbacksActive; TRACE4( "/DpRasDialFunc2(rcs=%d,s=%d,e=%d,x=%d)", state, dwSubEntry, dwError, dwExtendedError );
pInfo = (DPINFO* )dwCallbackId; if( NULL == pInfo ) { TRACE("DpRasDialFunc2(): Invalid pInfo"); return 0; } if (pInfo->dwValid != 0xC0BBC0DE) { TRACE( "DpRasDialFunc2 returns for Late callback?" );
return 0; }
if (dwSubEntry == 0 || dwSubEntry > pInfo->cStates) { TRACE( "DpRasDialFunc2 returns for Subentry out of range?" ); return 1; }
pState = &pInfo->pStates[ dwSubEntry - 1 ]; pState->state = state; pState->dwError = dwError; pState->dwExtendedError = dwExtendedError;
// Post the event to the Dial Progress window and wait for it to be
// processed before returning. This avoids subtle problems with Z-order
// and focus when a window is manipulated from two different threads.
//
TRACE1("Send RasEvent to Dial Progress window, subEntry:(%d)", dwSubEntry); TRACE1("Get dwError=(%d) from RasMan",pState->dwError); TRACE2("DpRasDialFunc2:Process:(%x),Thread(%x)", GetCurrentProcessId, GetCurrentThreadId); TRACE2("DpRasDialFunc2:pInfo address (0x%x), Dialog Handle (0x%x)", pInfo, pInfo->hwndDlg); dwCode = (DWORD)SendMessage( pInfo->hwndDlg, WM_RASEVENT, dwSubEntry, 0 );
TRACE1( "\\DpRasDialFunc2: dwCode from SendMessage()=%d", dwCode ); TRACE1("dwCode returned:(%d)", dwCode);
//Check if current thread is cancelled by user
//
// For XPSP2 511810, .Net 668164
fTerminateAsap = GetTerminateFlag(pInfo); ulCallbacksActive = GetCallbackActive(pInfo); TRACE1("Current thread's active:(%d)", ulCallbacksActive); if ( fTerminateAsap ) { TRACE("Current Thread wants to terminate itself, its fterminateASSP=1!"); TRACE("Current thread will decrease its own and global active!"); //reset per-thread terminateASAP flag
//
// For XPSP2 511810, .Net 668164
DecGlobalCallbackActive(); ResetTerminateFlag( pInfo ); ResetCallbackActive(pInfo);
//End callback function for this connection
//Have to return immediately after ResetCallbackActive() to avoid race
// conditions because the UI thread is polling on pInfo->fCallbackActive
//
return 0; } else { TRACE("Current Thread does NOT want to terminate itself,its fterminateASAP=0!"); } //return the global number of active callbacks for tracing
//
// For XPSP2 511810, .Net 668164
ulCallbacksActive = GetGlobalCallbackActive(); TRACE1("Global active:(%d)", ulCallbacksActive); TRACE1("Current thread's active:(%d)", GetCallbackActive(pInfo)); // Check if UI thread want the Callback because of Error, connected,
// disconnected etc.
//
if (dwCode == 0) { // Reset thread-safe flag indicating callbacks have terminated.
//for XPSP2 511810, .Net 668164
ResetCallbackActive( pInfo); DecGlobalCallbackActive(); }
TRACE1( "\\DpRasDialFunc2:final dwCode returned=%d", dwCode );
return dwCode; }
// For whistler bug 435725
//
void DpFreeStates( IN DPSTATE * pStates, IN DWORD dwSize ) { DWORD dwCount = 0;
for ( dwCount = 0; dwCount < dwSize; dwCount ++ ) { Free0( pStates[dwCount].pszFormatArg ); Free0( pStates[dwCount].pszStatusArg ); } Free0(pStates); }
VOID DpTerm( IN HWND hwndDlg )
// Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
//
{ DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
TRACE( "DpTerm" );
if (pInfo) { if (pInfo->pOldWndProc) { SetWindowLongPtr( pInfo->hwndDlg, GWLP_WNDPROC, (ULONG_PTR )pInfo->pOldWndProc ); }
// For whistler bug 435725 gangz
// Need to free the strings inside pStates
//
DpFreeStates( pInfo->pStates, pInfo->cStates ); pInfo->dwValid = 0;
// for XPSP2 511810, .Net 668164, 668164
DeleteCriticalSection(pInfo->pcsActiveLock);
Free( pInfo ); pInfo = NULL; }
//For whistler bug 372078 gangz
//
{ HICON hIcon=NULL; hIcon = (HICON)SendMessage( GetDlgItem( hwndDlg, CID_DP_Icon ), STM_GETICON, 0, 0); ASSERT(hIcon); if( hIcon ) { DestroyIcon(hIcon); } else { TRACE("DpTerm:Destroy Icon failed"); } } }
LRESULT APIENTRY DpWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam )
// Subclassed dialog window procedure.
//
{ DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
if (unMsg == WM_RASEVENT) { return DpEvent( pInfo, (DWORD )wParam ); }
return CallWindowProc( pInfo->pOldWndProc, hwnd, unMsg, wParam, lParam ); }
//----------------------------------------------------------------------------
// Dialer dialogs
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL DialerDlg( IN HWND hwndOwner, IN OUT DINFO* pInfo )
// Determine if it's necessary, and if so, popup one of the variations of
// the dialer dialog, i.e. the prompter for user/password/domain, phone
// number, and location. 'HwndOwner' is the owning window. 'PInfo' is
// the dial dialog common context.
//
// Returns true if no dialog is needed or user chooses OK.
//
{ INT_PTR nStatus = FALSE; int nDid; DWORD dwfMode; DRARGS args;
TRACE( "DialerDlg" );
do { dwfMode = 0;
if (!pInfo->pEntry->fAutoLogon && pInfo->pEntry->fPreviewUserPw && (!(pInfo->pArgs->dwFlags & RASDDFLAG_NoPrompt) || (pInfo->fUnattended && !HaveSavedPw( pInfo )))) { dwfMode |= DR_U;
if (pInfo->pEntry->fPreviewDomain) { dwfMode |= DR_D; } }
if (pInfo->pEntry->fPreviewPhoneNumber && (!(pInfo->pArgs->dwFlags & RASDDFLAG_NoPrompt) || (pInfo->fUnattended && !HaveSavedPw( pInfo )))) { DTLNODE* pNode; PBLINK* pLink;
dwfMode |= DR_N;
// Location controls mode only when at least one phone number in
// the list is TAPI-enabled.
//
pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks ); pLink = (PBLINK* )DtlGetData( pNode ); for (pNode = DtlGetFirstNode( pLink->pdtllistPhones ); pNode; pNode = DtlGetNextNode( pNode )) { PBPHONE* pPhone = (PBPHONE* )DtlGetData( pNode ); if ( pPhone->fUseDialingRules ) { dwfMode |= DR_L; break; } } }
// Customize the dialing flags for the type of eap authentication
// specified for this entry (if any)
if (DialerEapAssignMode(pInfo, &dwfMode) != NO_ERROR) break;
if (dwfMode == DR_U) { nDid = DID_DR_DialerU; } else if (dwfMode == (DR_U | DR_D)) { nDid = DID_DR_DialerUD; } else if (dwfMode == (DR_U | DR_N)) { nDid = DID_DR_DialerUN; } else if (dwfMode == (DR_U | DR_N | DR_L)) { nDid = DID_DR_DialerUNL; } else if (dwfMode == (DR_U | DR_D | DR_N)) { nDid = DID_DR_DialerUDN; } else if (dwfMode == (DR_U | DR_D | DR_N | DR_L)) { nDid = DID_DR_DialerUDNL; } else if (dwfMode == DR_N) { nDid = DID_DR_DialerN; } else if (dwfMode == (DR_N | DR_L)) { nDid = DID_DR_DialerNL; } else if (dwfMode == DR_I) { nDid = DID_DR_DialerI; } else if (dwfMode == (DR_I | DR_N)) { nDid = DID_DR_DialerIN; } else if (dwfMode == (DR_I | DR_N | DR_L)) { nDid = DID_DR_DialerINL; }
// pmay: The following 3 permutations of the
// dialer dialog were added for bug 183577 which
// states that eap modules (that use DR_I) want to
// have the domain field available to them as well.
else if (dwfMode == (DR_I | DR_D)) { nDid = DID_DR_DialerID; } else if (dwfMode == (DR_I | DR_D | DR_N)) { nDid = DID_DR_DialerIDN; } else if (dwfMode == (DR_I | DR_D | DR_N | DR_L)) { nDid = DID_DR_DialerIDNL; } else if( dwfMode == DR_B ) { nDid = DID_DR_DialerB; } else { ASSERT( dwfMode == 0 ); return TRUE; }
args.pDinfo = pInfo; args.dwfMode = dwfMode; args.fReload = FALSE;
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( nDid ), hwndOwner, DrDlgProc, (LPARAM )&args );
if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; } } while (args.fReload);
return (BOOL )nStatus; }
INT_PTR CALLBACK DrDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the dialer dialogs. Parameters and return
// value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "DrDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return DrInit( hwnd, (DRARGS* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwDrHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { DRINFO* pInfo = (DRINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
return DrCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); }
case WM_DESTROY: { DrTerm( hwnd ); break; } }
return FALSE; }
VOID DrGetFriendlyFont( IN HWND hwnd, IN BOOL fUpdate, OUT HFONT* phFont )
// Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
// does not match the length of the password and causes confusion
//
{ LOGFONT BoldLogFont; HFONT hFont; HDC hdc;
*phFont = NULL;
// Get the font used by the specified window
//
hFont = (HFONT)SendMessage( hwnd, WM_GETFONT, 0, 0L ); if (NULL == hFont) { // If not found then the control is using the system font
//
hFont = (HFONT)GetStockObject( SYSTEM_FONT ); }
if (hFont && GetObject( hFont, sizeof(BoldLogFont), &BoldLogFont )) { if (fUpdate) { BoldLogFont.lfItalic = TRUE; }
hdc = GetDC( hwnd ); if (hdc) { *phFont = CreateFontIndirect( &BoldLogFont ); ReleaseDC( hwnd, hdc ); } }
return; }
DWORD DrEnableDisablePwControls( IN DRINFO* pInfo, IN BOOL fEnable ) { if (pInfo->pArgs->pDinfo->fIsPublicPbk) { EnableWindow( pInfo->hwndRbSaveForEveryone, fEnable ); } else { EnableWindow( pInfo->hwndRbSaveForEveryone, FALSE ); }
EnableWindow( pInfo->hwndRbSaveForMe, fEnable );
return NO_ERROR; }
VOID DrClearFriendlyPassword( IN DRINFO* pInfo, IN BOOL fFocus ) { SetWindowText( pInfo->hwndEbPw, L"" );
if (fFocus) { SendMessage( pInfo->hwndEbPw, EM_SETPASSWORDCHAR, pInfo->szPasswordChar, 0 );
if (pInfo->hNormalFont) { SendMessage( pInfo->hwndEbPw, WM_SETFONT, (WPARAM)pInfo->hNormalFont, MAKELPARAM(TRUE, 0) ); }
SetFocus( pInfo->hwndEbPw ); }
return; }
VOID DrDisplayFriendlyPassword( IN DRINFO* pInfo, IN TCHAR* pszFriendly ) { if (pszFriendly) { SendMessage( pInfo->hwndEbPw, EM_SETPASSWORDCHAR, 0, 0 ); SetWindowText( pInfo->hwndEbPw, pszFriendly ); } else { SetWindowText( pInfo->hwndEbPw, L"" ); }
if (pInfo->hItalicFont) { SendMessage( pInfo->hwndEbPw, WM_SETFONT, (WPARAM)pInfo->hItalicFont, MAKELPARAM(TRUE, 0) ); }
return; }
BOOL DrIsPasswordStyleEnabled( IN HWND hWnd ) { return SendMessage( hWnd, EM_GETPASSWORDCHAR, 0, 0 ) ? TRUE : FALSE; }
BOOL DrCommand( IN DRINFO* 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.
//
{ DWORD dwErr = NO_ERROR;
TRACE3( "DrCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case CID_DR_CLB_Numbers: { if (wNotification == CBN_SELCHANGE) { DrNumbersSelChange( pInfo ); return TRUE; } break; }
case CID_DR_CB_SavePassword: { BOOL fEnable = Button_GetCheck( hwndCtrl ); DrEnableDisablePwControls( pInfo, fEnable ); DrPopulatePasswordField( pInfo, FALSE, FALSE, NULL ); return TRUE; }
// Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
// does not match the length of the password and causes confusion
//
case CID_DR_EB_Password: { // This is a hack really so that we restore the Tab Stop to the
// username field. The reason it had to be removed was because we
// were receiving complaints that the focus shouldn't always go to
// the username field if it's non-null. The only way to fix this,
// since windows sets the initial focus to the first visible non-
// hidden tab stopped field, is to remove the tab stop temporarily
// from the username field.
//
if (wNotification == EN_KILLFOCUS) { LONG lStyle = GetWindowLong( pInfo->hwndEbUser, GWL_STYLE ); HWND hwndTmp = NULL; /*
if (!(lStyle & WS_TABSTOP)) { // If we detect tap stop removed from the username field,
// restore it. Since this case only fires when the password
// was not previously saved on init, we can return here.
//
SetWindowLong( pInfo->hwndEbUser, GWL_STYLE, lStyle | WS_TABSTOP );
// for whistler bug 424209 gangz
// The help button receive the focus before the kill focus
// sent to password edit box
//
hwndTmp = GetDlgItem( pInfo->hwndDlg, CID_DR_PB_Help );
if ( GetFocus() == hwndTmp ) { SetFocus( pInfo->hwndEbUser ); } return TRUE; } */ // If the user leaves the password field w/o typing a new
// password, and a saved password is present, restore the
// friendly password text.
//
DrPopulatePasswordField( pInfo, FALSE, FALSE, NULL ); return TRUE; } // If the password field ever receives the focus, clear the
// friendly password text if applicable.
//
else if (wNotification == EN_SETFOCUS && !DrIsPasswordStyleEnabled( pInfo->hwndEbPw )) { DrPopulatePasswordField( pInfo, FALSE, TRUE, NULL ); return TRUE; } break; }
case CID_DR_LB_Locations: { if (wNotification == CBN_SELCHANGE) { DrLocationsSelChange( pInfo ); return TRUE; } break; }
case CID_DR_PB_Rules: { DrEditSelectedLocation( pInfo ); return TRUE; }
case CID_DR_PB_Properties: { DrProperties( pInfo ); DrPopulatePasswordField( pInfo, FALSE, FALSE, NULL ); return TRUE; }
case CID_DR_RB_SaveForMe: case CID_DR_RB_SaveForEveryone: { DrPopulatePasswordField( pInfo, FALSE, FALSE, NULL ); DrPopulateIdentificationFields( pInfo, (wId == CID_DR_RB_SaveForMe)); return TRUE; }
case IDOK: case CID_DR_PB_DialConnect: { DrSave( pInfo ); EndDialog( pInfo->hwndDlg, TRUE ); return TRUE; }
case IDCANCEL: case CID_DR_PB_Cancel: { EndDialog( pInfo->hwndDlg, FALSE ); return TRUE; }
case IDHELP: case CID_DR_PB_Help: { TCHAR* pszCmdLine;
// Help button now invokes troubleshooting help per bug 210247.
//
pszCmdLine = PszFromId( g_hinstDll, SID_DialerHelpCmdLine ); if (pszCmdLine) { STARTUPINFO sInfo; PROCESS_INFORMATION pProcInfo;
ZeroMemory( &sInfo, sizeof(sInfo) ); sInfo.cb = sizeof(sInfo); ZeroMemory( &pProcInfo, sizeof(pProcInfo) ); CreateProcess( NULL, pszCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pProcInfo );
Free( pszCmdLine ); } return TRUE; } }
return FALSE; }
BOOL CALLBACK DrClbNumbersEnumChildProc( IN HWND hwnd, IN LPARAM lparam )
// Standard Windows EnumChildProc routine called back for each child
// window of the 'ClbNumbers' control.
//
{ DRINFO* pInfo; LONG lId;
pInfo = (DRINFO* )lparam;
// There only one child window and it's the edit window.
//
pInfo->hwndClbNumbersEb = hwnd;
return FALSE; }
BOOL CALLBACK DrClbNumbersEnumWindowsProc( IN HWND hwnd, IN LPARAM lparam )
// Standard Windows EnumWindowsProc routine called back for each top-level
// window.
//
{ RECT rect;
GetWindowRect( hwnd, &rect ); if (rect.right - rect.left == DR_BOGUSWIDTH) { // This window has the unusual bogus width, so it must be the
// list-box.
//
((DRINFO* )lparam)->hwndClbNumbersLb = hwnd; return FALSE; }
return TRUE; }
LRESULT APIENTRY DrClbNumbersEbWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam )
// Subclassed combo-box edit-box child window procedure providing "manual
// edit" behavior.
//
// Return value depends on message type.
//
{ DRINFO* pInfo;
switch (unMsg) { case WM_SETTEXT: { // Prevent the combo-box from setting the contents of the edit box
// by discarding the request and reporting success.
//
return TRUE; }
case DR_WM_SETTEXT: { // Convert our private SETTEXT to a regular SETTEXT and pass it on
// to the edit control.
//
unMsg = WM_SETTEXT; break; } }
// Call the previous window procedure for everything else.
//
pInfo = (DRINFO* )GetProp( hwnd, g_contextId ); ASSERT( pInfo );
return CallWindowProc( pInfo->wndprocClbNumbersEb, hwnd, unMsg, wParam, lParam ); }
LRESULT APIENTRY DrClbNumbersLbWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam )
// Subclassed combo-box list-box child window procedure providing "manual
// edit" behavior.
//
// Return value depends on message type.
//
{ DRINFO* pInfo;
pInfo = (DRINFO* )GetProp( hwnd, g_contextId ); ASSERT( pInfo );
switch (unMsg) { case LB_FINDSTRINGEXACT: case LB_FINDSTRING: { // This prevents the edit-box "completion" behavior of the
// combo-box, i.e. it prevents the edit-box contents from being
// extended to the closest match in the list.
//
return -1; }
case LB_SETCURSEL: case LB_SETTOPINDEX: { // Prevent the "match selection to edit-box" combo-box behavior by
// discarding any attempts to set the selection or top index to
// anything other than what we set.
//
if (wParam != pInfo->pLink->iLastSelectedPhone) { return -1; } break; } }
// Call the previous window procedure for everything else.
//
return CallWindowProc( pInfo->wndprocClbNumbersLb, hwnd, unMsg, wParam, lParam ); }
VOID DrEditSelectedLocation( IN DRINFO* pInfo )
// Called when the Dialing Rules button is pressed. 'PInfo' is the dialog
// context.
//
{ DWORD dwErr; INT iSel; DRNUMBERSITEM* pItem;
TRACE( "DrEditSelectedLocation" );
// Look up the phone number information for the selected number.
//
pItem = (DRNUMBERSITEM* )ComboBox_GetItemDataPtr( pInfo->hwndClbNumbers, ComboBox_GetCurSel( pInfo->hwndClbNumbers ) ); ASSERT( pItem );
if(NULL == pItem) { return; } ASSERT( pItem->pPhone->fUseDialingRules );
// Popup TAPI dialing rules dialog.
//
dwErr = TapiLocationDlg( g_hinstDll, &pInfo->hlineapp, pInfo->hwndDlg, pItem->pPhone->dwCountryCode, pItem->pPhone->pszAreaCode, pItem->pPhone->pszPhoneNumber, 0 );
if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadTapiInfo, dwErr, NULL ); }
// Might have changed the location list so re-fill it.
//
DrFillLocationList( pInfo ); }
DWORD DrFillLocationList( IN DRINFO* pInfo )
// Fills the dropdown list of locations and sets the current selection.
//
// Returns 0 if successful, or an error code.
//
{ DWORD dwErr; LOCATION* pLocations; LOCATION* pLocation; DWORD cLocations; DWORD dwCurLocation; DWORD i;
TRACE( "DrFillLocationList" );
ComboBox_ResetContent( pInfo->hwndLbLocations );
pLocations = NULL; cLocations = 0; dwCurLocation = 0xFFFFFFFF; dwErr = GetLocationInfo( g_hinstDll, &pInfo->hlineapp, &pLocations, &cLocations, &dwCurLocation ); if (dwErr != 0) { return dwErr; }
for (i = 0, pLocation = pLocations; i < cLocations; ++i, ++pLocation) { INT iItem;
iItem = ComboBox_AddItem( pInfo->hwndLbLocations, pLocation->pszName, (VOID* )UlongToPtr(pLocation->dwId ));
if (pLocation->dwId == dwCurLocation) { ComboBox_SetCurSelNotify( pInfo->hwndLbLocations, iItem ); } }
FreeLocationInfo( pLocations, cLocations ); ComboBox_AutoSizeDroppedWidth( pInfo->hwndLbLocations );
return dwErr; }
VOID DrFillNumbersList( IN DRINFO* pInfo )
// Fill the "Dial" combo-box with phone numbers and comments, and
// re-select the selected item in the list, or if none, the last one
// selected as specified in the PBLINK.
//
{ DTLNODE* pNode; PBLINK* pLink; PBPHONE* pPhone; INT cItems; INT i;
DrFreeClbNumbers( pInfo );
for (pNode = DtlGetFirstNode( pInfo->pLink->pdtllistPhones ), i = 0; pNode; pNode = DtlGetNextNode( pNode ), ++i) { TCHAR szBuf[ RAS_MaxPhoneNumber + RAS_MaxDescription + 3 + 1 ]; DRNUMBERSITEM* pItem;
pPhone = (PBPHONE* )DtlGetData( pNode ); ASSERT( pPhone );
pItem = Malloc( sizeof(DRNUMBERSITEM) ); if (!pItem) { break; }
// Build the "<number> - <comment>" string in 'szBuf'.
//
pItem->pszNumber = LinkPhoneNumberFromParts( g_hinstDll, &pInfo->hlineapp, pInfo->pArgs->pDinfo->pUser, pInfo->pArgs->pDinfo->pEntry, pInfo->pLink, i, NULL, FALSE );
if (!pItem->pszNumber) { // Should not happen.
//
Free( pItem ); break; }
lstrcpyn( szBuf, pItem->pszNumber, RAS_MaxPhoneNumber); if (pPhone->pszComment && !IsAllWhite( pPhone->pszComment )) { DWORD dwLen, dwSize = sizeof(szBuf) / sizeof(TCHAR); lstrcat( szBuf, TEXT(" - ") ); dwLen = lstrlen(szBuf) + 1; lstrcpyn( szBuf + (dwLen - 1), pPhone->pszComment, dwSize - dwLen ); }
pItem->pPhone = pPhone;
ComboBox_AddItem( pInfo->hwndClbNumbers, szBuf, pItem ); }
// Make the selection and trigger the update of the edit-box to the number
// without the comment.
//
cItems = ComboBox_GetCount( pInfo->hwndClbNumbers ); if (cItems > 0) { if ((INT )pInfo->pLink->iLastSelectedPhone >= cItems) { pInfo->pLink->iLastSelectedPhone = 0; }
ListBox_SetTopIndex( pInfo->hwndClbNumbersLb, pInfo->pLink->iLastSelectedPhone ); ComboBox_SetCurSelNotify( pInfo->hwndClbNumbers, pInfo->pLink->iLastSelectedPhone ); }
ComboBox_AutoSizeDroppedWidth( pInfo->hwndClbNumbers ); }
VOID DrFreeClbNumbers( IN DRINFO* pInfo )
// Free up the displayable number string associated with each entry of the
// phone number combo-box leaving the box empty.
//
{ DRNUMBERSITEM* pItem;
while (pItem = ComboBox_GetItemDataPtr( pInfo->hwndClbNumbers, 0 )) { ComboBox_DeleteString( pInfo->hwndClbNumbers, 0 ); Free( pItem->pszNumber ); Free( pItem ); } }
DWORD DrFindAndSubclassClbNumbersControls( IN DRINFO* pInfo )
// Locate and sub-class the edit-box and list-box child controls of the
// phone number combo-box. This is necessary to get "manual edit"
// behavior, i.e. prevent the combo-box from automatically updating the
// edit box at various times. We need this because the phone number
// comments are to be appended in the list, but not in the edit box.
// 'PInfo' is the dialog context.
//
// Returns 0 if successful or an error code.
//
{ DWORD dxOld;
// Find the edit window which is simply a child enumeration.
//
EnumChildWindows( pInfo->hwndClbNumbers, DrClbNumbersEnumChildProc, (LPARAM)pInfo );
if (!pInfo->hwndClbNumbersEb) { return ERROR_NOT_FOUND; }
// Find the list window which *sigh* doesn't show up in the child
// enumeration though it has WS_CHILD style because Windows sets it's
// parent window to NULL after it is created. To find it, we set the
// dropped width to an unusual bogus value, then search all windows for
// one with that width.
//
dxOld = (DWORD )SendMessage( pInfo->hwndClbNumbers, CB_GETDROPPEDWIDTH, 0, 0 ); SendMessage( pInfo->hwndClbNumbers, CB_SETDROPPEDWIDTH, (WPARAM )DR_BOGUSWIDTH, 0 ); EnumWindows( DrClbNumbersEnumWindowsProc, (LPARAM)pInfo ); SendMessage( pInfo->hwndClbNumbers, CB_SETDROPPEDWIDTH, (WPARAM )dxOld, 0 );
if (!pInfo->hwndClbNumbersLb) { return ERROR_NOT_FOUND; }
// Subclass the windows after associating the dialog context with them for
// retrieval in the WndProcs.
//
SetProp( pInfo->hwndClbNumbersEb, g_contextId, pInfo ); SetProp( pInfo->hwndClbNumbersLb, g_contextId, pInfo );
pInfo->wndprocClbNumbersEb = (WNDPROC )SetWindowLongPtr( pInfo->hwndClbNumbersEb, GWLP_WNDPROC, (ULONG_PTR )DrClbNumbersEbWndProc );
pInfo->wndprocClbNumbersLb = (WNDPROC )SetWindowLongPtr( pInfo->hwndClbNumbersLb, GWLP_WNDPROC, (ULONG_PTR )DrClbNumbersLbWndProc );
return 0; }
void DrEnsureNetshellLoaded ( IN DRINFO* pInfo) { // Load the netshell utilities interface. The interface is freed in PeTerm.
//
if (!pInfo->pNetConUtilities) { // Initialize the NetConnectionsUiUtilities
//
HrCreateNetConnectionUtilities( &pInfo->pNetConUtilities ); } }
BOOL DrInit( IN HWND hwndDlg, IN DRARGS* pArgs )
// Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
// 'PArgs' is caller's arguments to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr = NO_ERROR; DRINFO* pInfo; PBENTRY* pEntry; BOOL fEnableProperties; // For whistler bug 424209 gangz
//
BOOL fUseDefaultFocus = TRUE; TRACE( "DrInit" );
// 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;
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo ); TRACE( "Context set" ); }
pEntry = pArgs->pDinfo->pEntry;
pInfo->hwndBmDialer = GetDlgItem( hwndDlg, CID_DR_BM_Useless ); ASSERT( pInfo->hwndBmDialer );
// Look up control handles.
//
if ((pArgs->dwfMode & DR_U) || (pArgs->dwfMode & DR_I)) { pInfo->hwndEbUser = GetDlgItem( hwndDlg, CID_DR_EB_User ); ASSERT( pInfo->hwndEbUser );
if (pArgs->dwfMode & DR_U) { pInfo->hwndEbPw = GetDlgItem( hwndDlg, CID_DR_EB_Password ); ASSERT( pInfo->hwndEbPw );
pInfo->hwndCbSavePw = GetDlgItem( hwndDlg, CID_DR_CB_SavePassword ); ASSERT( pInfo->hwndCbSavePw ); pInfo->hwndRbSaveForMe = GetDlgItem( hwndDlg, CID_DR_RB_SaveForMe ); ASSERT( pInfo->hwndRbSaveForMe ); pInfo->hwndRbSaveForEveryone = GetDlgItem( hwndDlg, CID_DR_RB_SaveForEveryone ); ASSERT( pInfo->hwndRbSaveForEveryone ); }
if (pArgs->dwfMode & DR_D) { pInfo->hwndEbDomain = GetDlgItem( hwndDlg, CID_DR_EB_Domain ); ASSERT( pInfo->hwndEbDomain ); } }
if (pArgs->dwfMode & DR_N) { pInfo->hwndClbNumbers = GetDlgItem( hwndDlg, CID_DR_CLB_Numbers ); ASSERT( pInfo->hwndClbNumbers );
if (pArgs->dwfMode & DR_L) { pInfo->hwndStLocations = GetDlgItem( hwndDlg, CID_DR_ST_Locations ); ASSERT( pInfo->hwndStLocations ); pInfo->hwndLbLocations = GetDlgItem( hwndDlg, CID_DR_LB_Locations ); ASSERT( pInfo->hwndLbLocations ); pInfo->hwndPbRules = GetDlgItem( hwndDlg, CID_DR_PB_Rules ); ASSERT( pInfo->hwndPbRules ); } }
pInfo->hwndPbProperties = GetDlgItem( hwndDlg, CID_DR_PB_Properties ); ASSERT( pInfo->hwndPbProperties );
// In location-enabled mode, popup TAPI's "first location" dialog if they
// are uninitialized. Typically, this will do nothing.
//
if (pArgs->dwfMode & DR_L) { dwErr = TapiNoLocationDlg( g_hinstDll, &pInfo->hlineapp, hwndDlg ); if (dwErr != 0) { // Error here is treated as a "cancel" per bug 288385.
//
pArgs->pDinfo->pArgs->dwError = 0; EndDialog( hwndDlg, FALSE ); return TRUE; } }
// Set the title.
//
{ TCHAR* pszTitleFormat; TCHAR* pszTitle; TCHAR* apszArgs[ 1 ];
if (pArgs->pDinfo->fUnattended) { pszTitleFormat = PszFromId( g_hinstDll, SID_DR_ReconnectTitle ); } else { pszTitleFormat = GetText( hwndDlg ); }
if (pszTitleFormat) { apszArgs[ 0 ] = pEntry->pszEntryName; pszTitle = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1, (va_list* )apszArgs );
Free( pszTitleFormat );
if (pszTitle) { SetWindowText( hwndDlg, pszTitle ); LocalFree( pszTitle ); } } }
// Change the Dial button to Connect for non-phone devices.
//
if (pEntry->dwType != RASET_Phone) { TCHAR* psz;
psz = PszFromId( g_hinstDll, SID_ConnectButton ); if (psz) { SetWindowText( GetDlgItem( hwndDlg, CID_DR_PB_DialConnect ), psz ); Free( psz ); } }
// Initialize credentials section.
//
if (pArgs->dwfMode & DR_U) { ASSERT( !pEntry->fAutoLogon );
// Fill credential fields with initial values.
//
Edit_LimitText( pInfo->hwndEbUser, UNLEN ); SetWindowText( pInfo->hwndEbUser, pArgs->pDinfo->rdp.szUserName ); Edit_LimitText( pInfo->hwndEbPw, PWLEN );
if (pArgs->dwfMode & DR_D) { Edit_LimitText( pInfo->hwndEbDomain, DNLEN ); SetWindowText( pInfo->hwndEbDomain, pArgs->pDinfo->rdp.szDomain ); }
if (pArgs->pDinfo->pNoUser || pArgs->pDinfo->fDisableSavePw) { // Can't stash password without a logon context, so hide the
// checkbox.
//
ASSERT( !HaveSavedPw( pArgs->pDinfo )) ; EnableWindow( pInfo->hwndCbSavePw, FALSE ); EnableWindow( pInfo->hwndRbSaveForMe, FALSE ); EnableWindow( pInfo->hwndRbSaveForEveryone, FALSE );
// Whistler bug 400714 RAS does not grab password at winlogon time
// when Connect dialog is displayed
//
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( pArgs->pDinfo->rdp.szPassword ); SetWindowText( pInfo->hwndEbPw, pArgs->pDinfo->rdp.szPassword ); EncodePassword( pArgs->pDinfo->rdp.szPassword ); } else { // Whistler bug: 195480 Dial-up connection dialog - Number of
// asterisks does not match the length of the password and causes
// confusion
//
// Init the password character. Default to the round dot if we fail
// to get it.
//
pInfo->szPasswordChar = (WCHAR) SendMessage( pInfo->hwndEbPw, EM_GETPASSWORDCHAR, 0, 0 ); if (!pInfo->szPasswordChar) { pInfo->szPasswordChar = 0x25CF; }
// Init the fonts for the password field
//
DrGetFriendlyFont( hwndDlg, TRUE, &(pInfo->hItalicFont) ); DrGetFriendlyFont( hwndDlg, FALSE, &(pInfo->hNormalFont) );
// Check "save password" and render the type of saved
// password.
//
Button_SetCheck( pInfo->hwndCbSavePw, HaveSavedPw( pArgs->pDinfo ));
if ((!pArgs->pDinfo->fIsPublicPbk) || (!HaveSavedPw( pArgs->pDinfo ))) { // If this is a for-me-only connection or if
// there is no saved password, then initialize the
// pw save type to save-for-me
//
Button_SetCheck( pInfo->hwndRbSaveForMe, TRUE ); } else { // Check the appropriate radio button
// Note that a per-user password is always used if
// both a per-user and global password are saved.
// Dont check global password if its a per-user connectoid
//
Button_SetCheck( (pArgs->pDinfo->fHaveSavedPwUser) ? pInfo->hwndRbSaveForMe : pInfo->hwndRbSaveForEveryone, TRUE); }
DrEnableDisablePwControls( pInfo, HaveSavedPw( pArgs->pDinfo ) );
// Whistler bug: 195480 Dial-up connection dialog - Number of
// asterisks does not match the length of the password and causes
// confusion
//
DrPopulatePasswordField( pInfo, TRUE, FALSE, &fUseDefaultFocus);
} }
if (pArgs->dwfMode & DR_N) { pInfo->pLinkNode = NULL; if (pArgs->pDinfo->pArgs->dwSubEntry > 0) { // Look up the API caller specified link.
//
pInfo->pLinkNode = DtlNodeFromIndex( pArgs->pDinfo->pEntry->pdtllistLinks, pArgs->pDinfo->pArgs->dwSubEntry - 1 ); }
if (!pInfo->pLinkNode) { // Look up the default (first) link.
//
pInfo->pLinkNode = DtlGetFirstNode( pArgs->pDinfo->pEntry->pdtllistLinks ); }
ASSERT( pInfo->pLinkNode ); pInfo->pLink = (PBLINK* )DtlGetData( pInfo->pLinkNode );
dwErr = DrFindAndSubclassClbNumbersControls( pInfo ); if (dwErr != 0) { pArgs->pDinfo->pArgs->dwError = ERROR_NOT_FOUND; EndDialog( hwndDlg, FALSE ); return TRUE; }
// Ignore any "last selected" information when the "try next on fail"
// flag is set. New entries will not have "last selected" non-0 in
// this case but pre-existing entries might, so double-check here.
// See bug 150958.
//
if (pInfo->pLink->fTryNextAlternateOnFail) { pInfo->pLink->iLastSelectedPhone = 0; }
// Record the initially selected phone number, used to determine
// whether user has changed the selection.
//
pInfo->iFirstSelectedPhone = pInfo->pLink->iLastSelectedPhone;
DrFillNumbersList( pInfo );
if (pArgs->dwfMode & DR_L) { DrFillLocationList( pInfo ); } }
// danielwe: Bug #222744, scottbri Bug #245310
// Disable Properties... button if user does not have sufficent rights.
//
{ HRESULT hr;
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); if (hr == RPC_E_CHANGED_MODE) { hr = CoInitializeEx( NULL, COINIT_MULTITHREADED ); }
if (hr == S_OK || hr == S_FALSE) { pInfo->fComInitialized = TRUE; } }
fEnableProperties = FALSE; DrEnsureNetshellLoaded (pInfo); if (NULL != pInfo->pNetConUtilities) { //For whislter bug 409504 gangz
//for a VPN double dial scenario,if now it is in the prerequiste dial
//process, we should use DINFO->pEntryMain->pszPrerequisitePbk to check
//if it is a publicPhonebook
//
BOOL fAllUsers = TRUE; if( pArgs->pDinfo->fPrerequisiteDial ) { fAllUsers = IsPublicPhonebook(pArgs->pDinfo->pEntryMain->pszPrerequisitePbk); } else { fAllUsers = IsPublicPhonebook(pArgs->pDinfo->pszPhonebook); } if (((fAllUsers && INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_RasAllUserProperties)) || (!fAllUsers && INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_RasMyProperties))) && (NULL == pArgs->pDinfo->pNoUser)) { fEnableProperties = TRUE; }
// We only needed it breifly, release it
INetConnectionUiUtilities_Release(pInfo->pNetConUtilities); pInfo->pNetConUtilities = NULL; }
// stevec: 267157-Allow access at win-login if admin enables.
//
if (NULL != pArgs->pDinfo->pNoUser && pArgs->pDinfo->pUser->fAllowLogonPhonebookEdits) { fEnableProperties = TRUE; }
EnableWindow( pInfo->hwndPbProperties, fEnableProperties );
// The help engine doesn't work at win-logon as it requires a user
// context, so disable the Help button in that case. See bug 343030.
//
if (pArgs->pDinfo->pNoUser) { HWND hwndPbHelp;
hwndPbHelp = GetDlgItem( hwndDlg, CID_DR_PB_Help ); ASSERT( hwndPbHelp );
EnableWindow( hwndPbHelp, FALSE ); ShowWindow( hwndPbHelp, SW_HIDE ); }
// Set the bitmap to the low res version if that is appropriate
//
// Ignore the error -- it is non-critical
//
DrSetBitmap(pInfo);
// Position the dialog per caller's instructions.
//
PositionDlg( hwndDlg, !!(pArgs->pDinfo->pArgs->dwFlags & RASDDFLAG_PositionDlg), pArgs->pDinfo->pArgs->xDlg, pArgs->pDinfo->pArgs->yDlg );
//Add this function for whislter bug 320863 gangz
//To adjust the bitmap's position and size
//
CenterExpandWindowRemainLeftMargin( pInfo->hwndBmDialer, hwndDlg, TRUE, TRUE, pInfo->hwndEbUser);
// Adjust the title bar widgets.
//
//TweakTitleBar( hwndDlg );
AddContextHelpButton( hwndDlg );
return fUseDefaultFocus; }
VOID DrLocationsSelChange( IN DRINFO* pInfo )
// Called when a location is selected from the list. 'PInfo' is the
// dialog context.
//
{ DWORD dwErr; DWORD dwLocationId;
TRACE("DuLocationChange");
// Set global TAPI location based on user's selection.
//
dwLocationId = (DWORD )ComboBox_GetItemData( pInfo->hwndLbLocations, ComboBox_GetCurSel( pInfo->hwndLbLocations ) );
dwErr = SetCurrentLocation( g_hinstDll, &pInfo->hlineapp, dwLocationId ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_SaveTapiInfo, dwErr, NULL ); }
// Location change may cause changes in built numbers so re-fill the
// numbers combo-box.
//
DrFillNumbersList( pInfo ); }
VOID DrNumbersSelChange( IN DRINFO* pInfo )
// Called when a phone number is selected from the list. 'PInfo' is the
// dialog context.
//
{ INT iSel; BOOL fEnable; DRNUMBERSITEM* pItem;
iSel = ComboBox_GetCurSel( pInfo->hwndClbNumbers ); if (iSel >= 0) { if (iSel != (INT )pInfo->pLink->iLastSelectedPhone) { pInfo->pArgs->pDinfo->pEntry->fDirty = TRUE; } pInfo->pLink->iLastSelectedPhone = (DWORD )iSel; }
pItem = (DRNUMBERSITEM* )ComboBox_GetItemDataPtr( pInfo->hwndClbNumbers, iSel ); ASSERT( pItem );
if(NULL == pItem) { return; }
// Enable/disable the location fields based on whether they are relevant
// to the selected number.
//
if (pInfo->pArgs->dwfMode & DR_L) { fEnable = pItem->pPhone->fUseDialingRules; EnableWindow( pInfo->hwndStLocations, fEnable ); EnableWindow( pInfo->hwndLbLocations, fEnable ); EnableWindow( pInfo->hwndPbRules, fEnable ); }
DrSetClbNumbersText( pInfo, pItem->pszNumber ); }
DWORD DrPopulateIdentificationFields( IN DRINFO* pInfo, IN BOOL fForMe )
// Updates the identification fields in the dialer
// UI according to whether the all-user or per-user
// dialparms should be used.
//
{ RASDIALPARAMS* prdp, *prdpOld; BOOL fUpdate; TCHAR pszUser[UNLEN + 1]; INT iCount;
prdp = (fForMe) ? &(pInfo->pArgs->pDinfo->rdpu) : &(pInfo->pArgs->pDinfo->rdpg); prdpOld = (fForMe) ? &(pInfo->pArgs->pDinfo->rdpg) : &(pInfo->pArgs->pDinfo->rdpu);
iCount = GetWindowText( pInfo->hwndEbUser, pszUser, UNLEN + 1); if (iCount == 0) { fUpdate = TRUE; } else { if (lstrcmp(prdpOld->szUserName, pszUser) == 0) { fUpdate = TRUE; } else { fUpdate = FALSE; } }
if (fUpdate) { if (pInfo->hwndEbUser && *(prdp->szUserName)) { SetWindowText(pInfo->hwndEbUser, prdp->szUserName); } if (pInfo->hwndEbDomain && *(prdp->szDomain)) { SetWindowText(pInfo->hwndEbDomain, prdp->szDomain); } }
return NO_ERROR; }
DWORD DrPopulatePasswordField( IN DRINFO* pInfo, IN BOOL fInit, IN BOOL fDisable, OUT BOOL * pfUseDefaultFocus) { BOOL fSave, fMeOnly; TCHAR* pszFriendly = NULL;
// Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
// does not match the length of the password and causes confusion
//
// Case 1. The user has clicked on the password field. We clear the
// friendly password and set the font back to normal.
//
if(NULL != pfUseDefaultFocus ) { *pfUseDefaultFocus = TRUE; } if (fDisable) { DrClearFriendlyPassword( pInfo, TRUE ); return NO_ERROR; }
// Initialze
//
fSave = Button_GetCheck( pInfo->hwndCbSavePw ); fMeOnly = Button_GetCheck( pInfo->hwndRbSaveForMe ); pszFriendly = PszFromId( g_hinstDll, SID_SavePasswordFrndly );
// Case 2. Clear the password field if the user a) choose not to save the
// password and b) has not manually entered a password.
//
if ( (!fSave) && !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ) ) { DrClearFriendlyPassword( pInfo, FALSE ); }
// Case 3. Show the friendly saved password text if the user a) choose to
// save the password of himself only and b) there is a per-user password
// saved and c) the user has not entered a password manually.
//
else if ( (fSave) && (fMeOnly) && ((fInit) || ( !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ))) ) { // Whistler bug: 288234 When switching back and forth from
// "I connect" and "Any user connects" password is not
// caching correctly
//
if (pInfo->pArgs->pDinfo->fHaveSavedPwUser) { DrDisplayFriendlyPassword(pInfo, pszFriendly ); } else { DrClearFriendlyPassword( pInfo, FALSE ); } }
// Case 4. Show the friendly saved password text if the user a) choose to
// save the password for everyone and b) there is a default password saved
// and c) the user has not entered a password manually.
//
else if ( (fSave) && (!fMeOnly) && ((fInit) || ( !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ))) ) { if (pInfo->pArgs->pDinfo->fHaveSavedPwGlobal) { DrDisplayFriendlyPassword( pInfo, pszFriendly ); } else { DrClearFriendlyPassword( pInfo, FALSE ); } }
// Case 5. Show the friendly saved password text if the user a) choose to
// save the password for everyone or himself and b) there is a
// corresponding password saved and c) the user has not entered a password
// manually.
//
// This case catches a) when the user is switching between "me" and
// "everyone" and b) when the user leaves the focus of the password field
// but hasn't changed the password
//
else if ( (fSave) && !GetWindowTextLength( pInfo->hwndEbPw ) && DrIsPasswordStyleEnabled( pInfo->hwndEbPw ) && ((pInfo->pArgs->pDinfo->fHaveSavedPwGlobal && !fMeOnly) || (pInfo->pArgs->pDinfo->fHaveSavedPwUser && fMeOnly)) ) { DrDisplayFriendlyPassword( pInfo, pszFriendly ); }
// NT5 bug: 215432, Whistler bug: 364341
//
// Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
// does not match the length of the password and causes confusion
//
// Set focus appropiately
//
if (fInit) { if (!GetWindowTextLength( pInfo->hwndEbUser )) { SetFocus( pInfo->hwndEbUser ); } else if (!GetWindowTextLength( pInfo->hwndEbPw )) { SetFocus( pInfo->hwndEbPw );
// This removes the tab stop property from the username field. This
// is a hack so we can set the focus properly. Tab stop is put back
// in DrCommand.
//
/*
SetWindowLong( pInfo->hwndEbUser, GWL_STYLE, GetWindowLong( pInfo->hwndEbUser, GWL_STYLE ) & ~WS_TABSTOP ); */ // For whistler bug 424209 gangz
// Dont hack the WS_TABSTOP attribute, just let DrInit() return
// false to indicate that we set the focus ourself
//
if( NULL != pfUseDefaultFocus ) { *pfUseDefaultFocus = FALSE; }
} else { SetFocus( pInfo->hwndEbUser ); } }
// Clean up
//
Free0( pszFriendly );
return NO_ERROR; }
VOID DrProperties( IN DRINFO* pInfo )
// Called when the Properties button is pressed. 'PInfo' is the dialog
// context.
//
{ BOOL fOk; RASENTRYDLG info; INTERNALARGS iargs; DINFO* pDinfo;
// First, save any entry related changes user has made on the dial dialog.
//
DrSave( pInfo );
// Set up for parameters for call to RasEntryDlg.
//
ZeroMemory( &info, sizeof(info) ); info.dwSize = sizeof(info); info.hwndOwner = pInfo->hwndDlg;
{ RECT rect;
info.dwFlags = RASEDFLAG_PositionDlg; GetWindowRect( pInfo->hwndDlg, &rect ); info.xDlg = rect.left + DXSHEET; info.yDlg = rect.top + DYSHEET; }
// The secret hack to share information already loaded with the entry API.
//
pDinfo = pInfo->pArgs->pDinfo; ZeroMemory( &iargs, sizeof(iargs) ); iargs.pFile = pDinfo->pFile; iargs.pUser = pDinfo->pUser; iargs.pNoUser = pDinfo->pNoUser; iargs.fNoUser = !!(pDinfo->pNoUser);
//For whislter bug 234515 set fDisableFirstConnect to be FALSE
//
iargs.fDisableFirstConnect = FALSE; info.reserved = (ULONG_PTR )&iargs;
TRACE( "RasEntryDlg" ); fOk = RasEntryDlg( pDinfo->pszPhonebook, pDinfo->pEntry->pszEntryName, &info ); TRACE1( "RasEntryDlg=%d", fOk );
if (fOk) { DWORD dwErr;
// Reload when user presses OK on properties since that may change the
// appearance and content of this dialog. Must first reset the DINFO
// context parameters based on the replaced PBENTRY from the property
// sheet.
//
dwErr = FindEntryAndSetDialParams( pInfo->pArgs->pDinfo ); if (dwErr != 0) { // Should not happen.
//
EndDialog( pInfo->hwndDlg, FALSE ); }
pInfo->pArgs->fReload = TRUE; EndDialog( pInfo->hwndDlg, FALSE ); } }
VOID DrSave( IN DRINFO* pInfo )
// Saves dialog field contents to RASDIALPARAMS, and if appropriate to LSA
// secret area or NOUSER output argument. 'PInfo' is the dialog context.
//
{ DWORD dwErr; RASDIALPARAMS* prdp; RASCREDENTIALS rc; DINFO* pDinfo;
pDinfo = pInfo->pArgs->pDinfo;
if ((pInfo->pArgs->dwfMode & DR_U) || (pInfo->pArgs->dwfMode & DR_I)) { // Save credentials into parameter block to be passed to RasDial.
//
prdp = &pDinfo->rdp; GetWindowText( pInfo->hwndEbUser, prdp->szUserName, UNLEN + 1 );
if (pInfo->pArgs->dwfMode & DR_U) { // Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by GetWindowText()
//
// Whistler bug: 195480 Dial-up connection dialog - Number of
// asterisks does not match the length of the password and causes
// confusion
//
if (!DrIsPasswordStyleEnabled( pInfo->hwndEbPw )) { lstrcpyn( prdp->szPassword, g_pszSavedPasswordToken, g_dwSavedPasswordTokenLength ); } else { GetWindowText( pInfo->hwndEbPw, prdp->szPassword, PWLEN + 1 ); }
SetWindowText( pInfo->hwndEbPw, L"" ); EncodePassword( prdp->szPassword ); }
if (pInfo->pArgs->dwfMode & DR_D) { GetWindowText( pInfo->hwndEbDomain, prdp->szDomain, DNLEN + 1 ); }
ZeroMemory( &rc, sizeof(rc) ); rc.dwSize = sizeof(rc); lstrcpyn( rc.szUserName, prdp->szUserName, UNLEN + 1 );
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( prdp->szPassword ); lstrcpyn( rc.szPassword, prdp->szPassword, PWLEN + 1 ); EncodePassword( prdp->szPassword );
lstrcpyn( rc.szDomain, prdp->szDomain, DNLEN + 1);
if (pDinfo->pNoUser) { // Save credentials into output block for return to caller,
// typically WinLogon.
//
lstrcpyn( pDinfo->pNoUser->szUserName, rc.szUserName, UNLEN + 1 );
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded previously
//
lstrcpyn( pDinfo->pNoUser->szPassword, rc.szPassword, PWLEN + 1 ); EncodePassword( pDinfo->pNoUser->szPassword );
lstrcpyn( pDinfo->pNoUser->szDomain, rc.szDomain, DNLEN + 1 ); *(pDinfo->pfNoUserChanged) = TRUE; } else if (pInfo->pArgs->dwfMode & DR_I) { // Nothing to do
} else if (!pDinfo->fDisableSavePw) { BOOL fGlobalCreds = FALSE; ASSERT( g_pRasSetCredentials );
if (Button_GetCheck( pInfo->hwndCbSavePw )) { rc.dwMask = 0; // If the user elected to save the credentials for
// everybody, then clear any previously saved per-user
// credentials
//
fGlobalCreds = Button_GetCheck( pInfo->hwndRbSaveForEveryone ); if( (fGlobalCreds) && IsPublicPhonebook(pDinfo->pFile->pszPath)) { DeleteSavedCredentials( pDinfo, pInfo->hwndDlg, FALSE, TRUE ); pDinfo->fHaveSavedPwUser = FALSE; rc.dwMask = RASCM_DefaultCreds; }
// If there is currently no saved per-user password and the user
// opts to save the password himself, then ask whetehr the global
// password should be deleted if it exists.
//
else if (pDinfo->fHaveSavedPwGlobal && !pDinfo->fHaveSavedPwUser) { MSGARGS msgargs; ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_ICONQUESTION | MB_YESNO;
// Delete the default credentials if the user answers yes
//
if (IDYES == MsgDlg(pInfo->hwndDlg, SID_DR_GlobalPassword, &msgargs)) { DeleteSavedCredentials( pDinfo, pInfo->hwndDlg, TRUE, TRUE ); pDinfo->fHaveSavedPwGlobal = FALSE; } }
// User chose to save password. Cache username, password, and
// domain.
//
rc.dwMask |= RASCM_UserName | RASCM_Password | RASCM_Domain;
TRACE( "RasSetCredentials(u|p|d,FALSE)" ); dwErr = g_pRasSetCredentials( pDinfo->pFile->pszPath, pDinfo->pEntry->pszEntryName, &rc, FALSE ); TRACE1( "RasSetCredentials=%d", dwErr ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_CachePw, dwErr, NULL ); } else { if (fGlobalCreds) { pDinfo->fHaveSavedPwGlobal = TRUE; } else { // Whistler bug: 288234 When switching back and forth
// from "I connect" and "Any user connects" password is
// not caching correctly
//
pDinfo->fHaveSavedPwUser = TRUE; } } } else { // Delete the global credentials.
//
// Note that we have to delete the global identity
// as well because we do not support deleting
// just the global password. This is so that
// RasSetCredentials can emulate RasSetDialParams.
//
DeleteSavedCredentials( pDinfo, pInfo->hwndDlg, TRUE, TRUE );
// Delete the password saved per-user. Keep the user name
// and domain saved, however.
//
DeleteSavedCredentials( pDinfo, pInfo->hwndDlg, FALSE, FALSE );
pDinfo->fHaveSavedPwUser = FALSE; pDinfo->fHaveSavedPwGlobal = FALSE; } }
RtlSecureZeroMemory( rc.szPassword, sizeof(rc.szPassword) ); }
if (pInfo->pArgs->dwfMode & DR_N) { TCHAR* pszNumber; TCHAR* pszOriginal; DTLNODE* pPhoneNode; DRNUMBERSITEM* pItem; PBPHONE* pPhone; BOOL fUserChange;
pszNumber = GetText( pInfo->hwndClbNumbers ); if (!pszNumber) { return; }
pItem = (DRNUMBERSITEM* )ComboBox_GetItemDataPtr( pInfo->hwndClbNumbers, pInfo->pLink->iLastSelectedPhone ); if (pItem) { pszOriginal = pItem->pszNumber; } else { pszOriginal = TEXT(""); }
if (lstrcmp( pszNumber, pszOriginal ) != 0 || (pInfo->pLink->iLastSelectedPhone != pInfo->iFirstSelectedPhone)) { MSGARGS msgargs; BOOL fMultiLink; BOOL fSingleNumber;
// The phone number was edited by user to something not originally
// on the list OR the user selected a different item on the list.
//
fSingleNumber = (DtlGetNodes( pInfo->pLink->pdtllistPhones ) == 1); fMultiLink = (DtlGetNodes( pDinfo->pEntry->pdtllistLinks ) > 1);
ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2;
if (fSingleNumber && (!fMultiLink || pDinfo->pEntry->fSharedPhoneNumbers) && MsgDlg( pInfo->hwndDlg, SID_SavePreview, &msgargs ) == IDYES) { // User says he wants to make the change permanent.
//
pDinfo->pEntry->fDirty = TRUE;
if (pItem) { pPhone = pItem->pPhone; Free0( pItem->pszNumber ); pItem->pszNumber = StrDup( pszNumber ); } else { pPhoneNode = CreatePhoneNode(); if (pPhoneNode) { DtlAddNodeFirst( pInfo->pLink->pdtllistPhones, pPhoneNode ); pPhone = (PBPHONE* )DtlGetData( pPhoneNode ); } }
if (pItem) { ASSERT( pItem->pPhone ); Free0( pPhone->pszPhoneNumber ); pPhone->pszPhoneNumber = StrDup( pszNumber ); pPhone->fUseDialingRules = FALSE;
if (fMultiLink) { DTLNODE* pNode;
for (pNode = DtlGetFirstNode( pDinfo->pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); ASSERT( pLink->fEnabled ); CopyLinkPhoneNumberInfo( pNode, pInfo->pLinkNode ); } } } }
fUserChange = TRUE; } else { fUserChange = FALSE; }
if (fUserChange || !pInfo->pLink->fTryNextAlternateOnFail) { if (!*pszNumber) { TCHAR* psz;
// We have a problem when user edits in an empty string,
// because the RasDial API does not accept an empty override
// phone number. Convert it to a single blank string in this
// case, which is as good as we can do. If user really needs
// to dial an empty string they can enter one as the entry's
// permanent phone number. See bug 179561.
//
psz = StrDup( TEXT(" ") ); if (psz) { Free( pszNumber ); pszNumber = psz; } }
// Set the override phone number to what user typed or selected.
//
lstrcpyn( pDinfo->rdp.szPhoneNumber, pszNumber, RAS_MaxPhoneNumber + 1); }
Free( pszNumber ); }
if (pDinfo->pEntry->fDirty) { // Write the new phone number and/or "last selected phone number" to
// the phonebook.
//
dwErr = WritePhonebookFile( pDinfo->pFile, NULL ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook, dwErr, NULL ); } } }
DWORD DrSetBitmap( IN DRINFO* pInfo)
// Set the appropriate bitmap for this dialer.
//
{ DWORD dwErr = NO_ERROR; HBITMAP hbmNew = NULL; HDC hdc = NULL; INT iDepth = 0;
do { if (pInfo->hwndBmDialer == NULL) { dwErr = ERROR_CAN_NOT_COMPLETE; break; } // Get the device context for the window
//
hdc = GetDC( pInfo->hwndBmDialer ); if (hdc == NULL) { dwErr = GetLastError(); break; }
// If the color depth >= 8bit, the current bitmap
// is fine (high res is default)
//
iDepth = GetDeviceCaps(hdc, NUMCOLORS); if ( (iDepth == -1) || (iDepth == 256) ) { dwErr = NO_ERROR; break; }
// Load in the low-res bitmap
//
hbmNew = LoadBitmap(g_hinstDll, MAKEINTRESOURCE( BID_Dialer )); if (hbmNew == NULL) { dwErr = GetLastError(); break; }
// Set the low-res bitmap
//
pInfo->hbmOrig = (HBITMAP) SendMessage( pInfo->hwndBmDialer, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM )hbmNew ); } while (FALSE);
// Cleanup
//
{ if (hdc) { ReleaseDC(pInfo->hwndBmDialer, hdc); } } return dwErr; }
VOID DrSetClbNumbersText( IN DRINFO* pInfo, IN TCHAR* pszText )
// Set the text of the 'ClbNumbers' edit box to 'pszText'. See
// DrClbNumbersEbWndProc. 'PInfo' is the dialog context.
//
{ ASSERT( pInfo->hwndClbNumbersEb );
SendMessage( pInfo->hwndClbNumbersEb, DR_WM_SETTEXT, 0, (LPARAM )pszText ); }
VOID DrTerm( IN HWND hwndDlg )
// Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
//
{ DRINFO* pInfo = (DRINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER ); HBITMAP hbmNew = NULL;
TRACE( "DrTerm" );
if (pInfo) { // Note: Don't use 'pInfo->pLinkNode' or 'pInfo->pLink' here as they
// are not currently restored prior to exit for post-Property
// button reloading.
//
if (pInfo->hwndClbNumbers) { DrFreeClbNumbers( pInfo );
if (pInfo->wndprocClbNumbersEb) { SetWindowLongPtr( pInfo->hwndClbNumbersEb, GWLP_WNDPROC, (ULONG_PTR )pInfo->wndprocClbNumbersEb ); }
if (pInfo->wndprocClbNumbersLb) { SetWindowLongPtr( pInfo->hwndClbNumbersLb, GWLP_WNDPROC, (ULONG_PTR )pInfo->wndprocClbNumbersLb ); } }
// Whistler bug: 195480 Dial-up connection dialog - Number of
// asterisks does not match the length of the password and causes
// confusion
//
if (pInfo->hItalicFont) { DeleteObject( pInfo->hItalicFont ); }
if (pInfo->hNormalFont) { DeleteObject( pInfo->hNormalFont ); }
if (pInfo->fComInitialized) { CoUninitialize(); }
// Clean up the low-res bitmap if appropriate
//
if ( pInfo->hbmOrig ) { hbmNew = (HBITMAP) SendMessage( pInfo->hwndBmDialer, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM ) pInfo->hbmOrig ); if (hbmNew) { DeleteObject(hbmNew); } }
Free( pInfo ); pInfo = NULL; } }
//----------------------------------------------------------------------------
// Projection Result dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL ProjectionResultDlg( IN HWND hwndOwner, IN TCHAR* pszLines, OUT BOOL* pfDisableFailedProtocols )
// Popup the Projection Result dialog. 'HwndOwner' is the owning window.
// 'PszLines' is the status line text to display. See DpProjectionError.
// 'DwfDisableFailedProtocols' indicates user chose to disable the failed
// protocols.
//
// Returns true if user chooses to redial or lets it timeout, false if
// cancels.
//
{ INT_PTR nStatus; PRARGS args;
TRACE( "ProjectionResultDlg" );
args.pszLines = pszLines; args.pfDisableFailedProtocols = pfDisableFailedProtocols;
nStatus = DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_PR_ProjectionResult ), hwndOwner, PrDlgProc, (LPARAM )&args );
if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (nStatus) ? TRUE : FALSE; }
INT_PTR CALLBACK PrDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the Projection Result dialog. Parameters and
// return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "PrDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return PrInit( hwnd, (PRARGS* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwPrHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { return PrCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } }
return FALSE; }
BOOL PrCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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.
//
{ DWORD dwErr;
TRACE3( "PrCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case IDOK: case IDCANCEL: { BOOL fCb; BOOL* pfDisable;
TRACE1( "%s pressed", (wId==IDOK) ? "OK" : "Cancel" );
fCb = IsDlgButtonChecked( hwnd, CID_PR_CB_DisableProtocols ); pfDisable = (BOOL* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pfDisable ); *pfDisable = fCb; EndDialog( hwnd, (wId == IDOK) ); return TRUE; } }
return FALSE; }
BOOL PrInit( IN HWND hwndDlg, IN PRARGS* pArgs )
// Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
// 'PArgs' is caller's arguments to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr; HWND hwndStText; HWND hwndPbAccept; HWND hwndPbHangUp; HWND hwndCbDisable;
TRACE( "PrInit" );
hwndStText = GetDlgItem( hwndDlg, CID_PR_ST_Text ); ASSERT( hwndStText ); hwndPbAccept = GetDlgItem( hwndDlg, IDOK ); ASSERT( hwndPbAccept ); hwndPbHangUp = GetDlgItem( hwndDlg, IDCANCEL ); ASSERT( hwndPbHangUp ); hwndCbDisable = GetDlgItem( hwndDlg, CID_PR_CB_DisableProtocols ); ASSERT( hwndCbDisable );
{ TCHAR szBuf[ 1024 ]; TCHAR* psz;
// Build the message text.
//
szBuf[ 0 ] = TEXT('\0'); psz = PszFromId( g_hinstDll, SID_ProjectionResult1 ); if (psz) { lstrcat( szBuf, psz ); Free( psz ); } lstrcat( szBuf, pArgs->pszLines ); psz = PszFromId( g_hinstDll, SID_ProjectionResult2 ); if (psz) { lstrcat( szBuf, psz ); Free( psz ); }
// Load the text into the static control, then stretch the window to a
// vertical size appropriate for the text.
//
{ HDC hdc; RECT rect; RECT rectNew; HFONT hfont; LONG dyGrow;
SetWindowText( hwndStText, szBuf ); GetClientRect( hwndStText, &rect ); hdc = GetDC( hwndStText );
if(NULL != hdc) {
hfont = (HFONT )SendMessage( hwndStText, WM_GETFONT, 0, 0 ); if (hfont) SelectObject( hdc, hfont );
rectNew = rect; DrawText( hdc, szBuf, -1, &rectNew, DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS | DT_NOPREFIX ); ReleaseDC( hwndStText, hdc ); }
dyGrow = rectNew.bottom - rect.bottom; ExpandWindow( hwndDlg, 0, dyGrow ); ExpandWindow( hwndStText, 0, dyGrow ); SlideWindow( hwndPbAccept, hwndDlg, 0, dyGrow ); SlideWindow( hwndPbHangUp, hwndDlg, 0, dyGrow ); SlideWindow( hwndCbDisable, hwndDlg, 0, dyGrow ); } }
// Save address of caller's BOOL as the dialog context.
//
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pArgs->pfDisableFailedProtocols );
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
// Display the finished window above all other windows. The window
// position is set to "topmost" then immediately set to "not topmost"
// because we want it on top but not always-on-top. Always-on-top alone
// is incredibly annoying, e.g. it is always on top of the on-line help if
// user presses the Help button.
//
SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); ShowWindow( hwndDlg, SW_SHOW );
SetWindowPos( hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
return TRUE; }
//----------------------------------------------------------------------------
// Retry Authentication dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL RetryAuthenticationDlg( IN HWND hwndOwner, IN DINFO* pDinfo )
// Pops up the retry authentication dialog. 'PDinfo' is the dial dialog
// common context.
//
// Returns true if user presses OK, false if Cancel or an error occurs.
//
{ INT_PTR nStatus;
TRACE( "RetryAuthenticationDlg" );
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_UA_RetryAuthenticationUD ), hwndOwner, UaDlgProc, (LPARAM )pDinfo );
if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (BOOL )nStatus; }
INT_PTR CALLBACK UaDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the User Authentication dialog. Parameters and
// return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "UaDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return UaInit( hwnd, (DINFO* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwUaHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { UAINFO* pInfo = (UAINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
if (!pInfo) { // This happened in stress one night. Don't understand how
// unless it was a WinUser bug or something. Anyhow, this
// avoids an AV in such case.
//
break; }
return UaCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); }
case WM_DESTROY: { UaTerm( hwnd ); break; } }
return FALSE; }
BOOL UaCommand( IN UAINFO* 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( "UaCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case CID_UA_EB_UserName: { if (pInfo->fAutoLogonPassword && wNotification == EN_CHANGE) { // User's changing the username in auto-logon retry mode,
// which means we have to admit we don't really have the text
// password and force him to re-enter it.
//
pInfo->fAutoLogonPassword = FALSE; SetWindowText( pInfo->hwndEbPassword, TEXT("") ); } break; }
case CID_UA_EB_Password: { if (wNotification == EN_CHANGE) { pInfo->fAutoLogonPassword = FALSE; } break; }
case IDOK: { UaSave( pInfo ); EndDialog( pInfo->hwndDlg, TRUE ); return TRUE; }
case IDCANCEL: { TRACE( "Cancel pressed" ); EndDialog( pInfo->hwndDlg, FALSE ); return TRUE; } }
return FALSE; }
BOOL UaInit( IN HWND hwndDlg, IN DINFO* 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; UAINFO* pInfo; PBENTRY* pEntry;
TRACE( "UaInit" );
// 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;
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo ); TRACE( "Context set" ); }
pInfo->fDomain = TRUE;
pInfo->hwndEbUserName = GetDlgItem( hwndDlg, CID_UA_EB_UserName ); ASSERT( pInfo->hwndEbUserName ); pInfo->hwndEbPassword = GetDlgItem( hwndDlg, CID_UA_EB_Password ); ASSERT( pInfo->hwndEbPassword ); if (pInfo->fDomain) { pInfo->hwndEbDomain = GetDlgItem( hwndDlg, CID_UA_EB_Domain ); ASSERT( pInfo->hwndEbDomain ); } pInfo->hwndCbSavePw = GetDlgItem( hwndDlg, CID_UA_CB_SavePassword ); ASSERT( pInfo->hwndCbSavePw );
pEntry = pArgs->pEntry;
// Set the title.
//
{ TCHAR* pszTitleFormat; TCHAR* pszTitle; TCHAR* apszArgs[ 1 ];
pszTitleFormat = GetText( hwndDlg ); if (pszTitleFormat) { apszArgs[ 0 ] = pEntry->pszEntryName; pszTitle = NULL;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1, (va_list* )apszArgs );
Free( pszTitleFormat );
if (pszTitle) { SetWindowText( hwndDlg, pszTitle ); LocalFree( pszTitle ); } } }
// Fill edit fields with initial values.
//
Edit_LimitText( pInfo->hwndEbUserName, UNLEN ); Edit_LimitText( pInfo->hwndEbPassword, PWLEN ); if (pInfo->fDomain) { Edit_LimitText( pInfo->hwndEbDomain, DNLEN ); }
{ BOOL fUserNameSet = FALSE; BOOL fPasswordSet = FALSE;
if (pEntry->fAutoLogon && !pInfo->pArgs->pNoUser) { // On the first retry use the logged on user's name. Act like the
// user's password is in the edit box. If he changes the username
// or password we'll have to admit we don't have it, but he'll
// probably just change the domain.
//
if (pArgs->rdp.szUserName[ 0 ] == TEXT('\0')) { SetWindowText( pInfo->hwndEbUserName, GetLogonUser() ); fUserNameSet = TRUE; }
if (pArgs->rdp.szPassword[ 0 ] == TEXT('\0')) { SetWindowText( pInfo->hwndEbPassword, TEXT("********") ); pInfo->fAutoLogonPassword = TRUE; fPasswordSet = TRUE; } }
if (!fUserNameSet) { SetWindowText( pInfo->hwndEbUserName, pArgs->rdp.szUserName ); }
if (!fPasswordSet) { // Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( pArgs->rdp.szPassword ); SetWindowText( pInfo->hwndEbPassword, pArgs->rdp.szPassword ); EncodePassword( pArgs->rdp.szPassword ); }
if (pInfo->fDomain) { SetWindowText( pInfo->hwndEbDomain, pArgs->rdp.szDomain ); } }
if (pArgs->pNoUser || pArgs->fDisableSavePw) { // Can't stash password without a logon context, so hide the checkbox.
//
ASSERT( !HaveSavedPw( pArgs ) ); EnableWindow( pInfo->hwndCbSavePw, FALSE ); ShowWindow( pInfo->hwndCbSavePw, SW_HIDE ); } else { // Check "save password" if a password was previously cached. Maybe
// he changed the password while on the LAN.
//
Button_SetCheck( pInfo->hwndCbSavePw, HaveSavedPw( pArgs ) ); }
// Position the dialog per caller's instructions.
//
PositionDlg( hwndDlg, (pArgs->pArgs->dwFlags & RASDDFLAG_PositionDlg), pArgs->pArgs->xDlg, pArgs->pArgs->yDlg ); SetForegroundWindow( hwndDlg );
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
// Set focus to the empty username or empty password, or if both are
// present to the domain if auto-logon or the password if not.
//
if (Edit_GetTextLength( pInfo->hwndEbUserName ) == 0) { Edit_SetSel( pInfo->hwndEbUserName, 0, -1 ); SetFocus( pInfo->hwndEbUserName ); } else if (Edit_GetTextLength( pInfo->hwndEbPassword ) == 0 || !pEntry->fAutoLogon || !pInfo->fDomain) { Edit_SetSel( pInfo->hwndEbPassword, 0, -1 ); SetFocus( pInfo->hwndEbPassword ); } else { ASSERT( pInfo->fDomain ); Edit_SetSel( pInfo->hwndEbDomain, 0, -1 ); SetFocus( pInfo->hwndEbDomain ); }
// Hide the Dial Progress dialog.
//
SetOffDesktop( GetParent( hwndDlg ), SOD_MoveOff, NULL );
return FALSE; }
VOID UaSave( IN UAINFO* pInfo )
// Called when the OK button is pressed.
//
// Returns true if user presses OK, false if Cancel or an error occurs.
//
{ DWORD dwErr; PBENTRY* pEntry; BOOL fSavePw; RASDIALPARAMS* prdp; RASCREDENTIALS rc;
TRACE( "UaSave" );
prdp = &pInfo->pArgs->rdp; GetWindowText( pInfo->hwndEbUserName, prdp->szUserName, UNLEN + 1 );
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded by GetWindowText()
//
GetWindowText( pInfo->hwndEbPassword, prdp->szPassword, PWLEN + 1 ); EncodePassword( prdp->szPassword ); if (pInfo->fDomain) { GetWindowText( pInfo->hwndEbDomain, prdp->szDomain, DNLEN + 1 ); //
//if the Domain is not empty, set the "include Windows Logon Domain check box on Option Tab"
// for bug 167229 whistler
//
if ( ( 0 < lstrlen ( prdp->szDomain ) ) && (!pInfo->pArgs->pEntry->fPreviewDomain )) { pInfo->pArgs->pEntry->fPreviewDomain = TRUE; pInfo->pArgs->pEntry->fDirty = TRUE; dwErr = WritePhonebookFile( pInfo->pArgs->pFile, NULL );
if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook, dwErr, NULL ); } } }
pEntry = pInfo->pArgs->pEntry; if (pEntry->fAutoLogon && !pInfo->pArgs->pNoUser) { if (pInfo->fAutoLogonPassword) { // User did not change username or password, so continue to
// retrieve logon username and password credentials.
//
TRACE( "Retain auto-logon" ); prdp->szUserName[ 0 ] = TEXT('\0'); prdp->szPassword[ 0 ] = TEXT('\0'); } else { // User changed username and/or password so we can no longer
// retrieve the logon username and password credentials from the
// system. Switch the entry to non-auto-logon mode.
//
TRACE( "Disable auto-logon" ); pEntry->fAutoLogon = FALSE; pInfo->pArgs->fResetAutoLogon = TRUE; } }
ZeroMemory( &rc, sizeof(rc) ); rc.dwSize = sizeof(rc); lstrcpyn( rc.szUserName, prdp->szUserName, UNLEN + 1 );
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded previously
//
DecodePassword( prdp->szPassword ); lstrcpyn( rc.szPassword, prdp->szPassword, PWLEN + 1 ); EncodePassword( prdp->szPassword );
lstrcpyn( rc.szDomain, prdp->szDomain, DNLEN + 1 );
if (pInfo->pArgs->pNoUser) { lstrcpyn( pInfo->pArgs->pNoUser->szUserName, rc.szUserName, UNLEN + 1 );
// Whistler bug 254385 encode password when not being used
// Assumed password was not encoded previously
//
lstrcpyn( pInfo->pArgs->pNoUser->szPassword, rc.szPassword, PWLEN + 1 ); EncodePassword( pInfo->pArgs->pNoUser->szPassword );
lstrcpyn( pInfo->pArgs->pNoUser->szDomain, rc.szDomain, DNLEN + 1 ); *pInfo->pArgs->pfNoUserChanged = TRUE; } else if (!pInfo->pArgs->fDisableSavePw) { ASSERT( g_pRasSetCredentials );
if (Button_GetCheck( pInfo->hwndCbSavePw )) { // User chose "save password". Cache username, password, and
// domain.
//
rc.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain;
// Whistler bug: 288234 When switching back and forth from
// "I connect" and "Any user connects" password is not
// caching correctly
//
if( (pInfo->pArgs->fHaveSavedPwGlobal) && !pInfo->pArgs->fHaveSavedPwUser && IsPublicPhonebook(pInfo->pArgs->pFile->pszPath)) { rc.dwMask |= RASCM_DefaultCreds; } TRACE( "RasSetCredentials(u|p|d,FALSE)" ); dwErr = g_pRasSetCredentials( pInfo->pArgs->pFile->pszPath, pInfo->pArgs->pEntry->pszEntryName, &rc, FALSE ); TRACE1( "RasSetCredentials=%d", dwErr );
if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_CachePw, dwErr, NULL ); } } else { // Whistler bug: 288234 When switching back and forth from
// "I connect" and "Any user connects" password is not
// caching correctly
//
// User chose not to save password; Cache username and domain only
//
rc.dwMask = RASCM_UserName | RASCM_Domain;
TRACE( "RasSetCredentials(u|d,FALSE)" ); dwErr = g_pRasSetCredentials( pInfo->pArgs->pFile->pszPath, pInfo->pArgs->pEntry->pszEntryName, &rc, FALSE ); TRACE1( "RasSetCredentials=%d", dwErr );
if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_UncachePw, dwErr, NULL ); }
// Whistler bug: 288234 When switching back and forth from
// "I connect" and "Any user connects" password is not
// caching correctly
//
// Delete the password saved per-user; Keep the user name
// and domain saved, however.
//
if (pInfo->pArgs->fHaveSavedPwUser) { DeleteSavedCredentials( pInfo->pArgs, pInfo->hwndDlg, FALSE, FALSE ); pInfo->pArgs->fHaveSavedPwUser = FALSE; }
// Delete the global credentials.
//
// Note that we have to delete the global identity
// as well because we do not support deleting
// just the global password. This is so that
// RasSetCredentials can emulate RasSetDialParams.
//
else if (pInfo->pArgs->fHaveSavedPwGlobal) { DeleteSavedCredentials( pInfo->pArgs, pInfo->hwndDlg, TRUE, TRUE ); pInfo->pArgs->fHaveSavedPwGlobal = FALSE; } } }
RtlSecureZeroMemory( rc.szPassword, sizeof(rc.szPassword) ); }
VOID UaTerm( IN HWND hwndDlg )
// Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
//
{ UAINFO* pInfo = (UAINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
TRACE( "UaTerm" );
if (pInfo) { // Restore the Dial Progress dialog.
//
SetOffDesktop( GetParent( hwndDlg ), SOD_MoveBackFree, NULL );
Free( pInfo ); pInfo = NULL; } }
//----------------------------------------------------------------------------
// VPN Double Dial help dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL VpnDoubleDialDlg( IN HWND hwndOwner, IN DINFO* pInfo )
// Popup the VPN double dial help dialog. 'HwndOwner' is the owning
// window. 'PInfo' is the dialing context information.
//
// Returns false if user sees the dialog and decides not to continue, true
// otherwise.
//
{ INT_PTR nStatus;
TRACE( "VpnDoubleDialDlg" );
if (pInfo->pEntryMain->dwType != RASET_Vpn || !pInfo->fPrerequisiteDial || pInfo->pEntryMain->fSkipDoubleDialDialog) { return TRUE; }
nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_VI_VpnInitial ), hwndOwner, ViDlgProc, (LPARAM )pInfo );
if (nStatus == -1) { nStatus = FALSE; }
return !!(nStatus); }
INT_PTR CALLBACK ViDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the dialog. Parameters and return value are as
// described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "ViDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return ViInit( hwnd, (DINFO* )lparam ); }
case WM_COMMAND: { return ViCommand( hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } }
return FALSE; }
BOOL ViCommand( IN HWND hwnd, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'Hwnd' is the dialog window. '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( "ViCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case IDYES: case IDNO: { // Per bug 261955, the box setting is saved when either the Yes or
// No, but not the 'X' button, is pressed.
//
DINFO* pInfo = (DINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT( pInfo );
if (IsDlgButtonChecked( hwnd, CID_VI_CB_SkipMessage )) { pInfo->pEntryMain->fSkipDoubleDialDialog = TRUE; pInfo->pEntryMain->fDirty = TRUE; WritePhonebookFile( pInfo->pFileMain, NULL ); }
EndDialog( hwnd, (wId == IDYES) ); return TRUE; }
case IDCANCEL: { EndDialog( hwnd, FALSE ); return TRUE; } }
return FALSE; }
BOOL ViInit( IN HWND hwndDlg, IN DINFO* pInfo )
// Called on WM_INITDIALOG. 'HwndDlg' is the handle of dialog. 'PUser'
// is caller's argument to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ TRACE( "ViInit" );
// Set the dialog context.
//
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
// Set the explanatory text.
//
{ MSGARGS msgargs;
ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.apszArgs[ 0 ] = pInfo->pEntryMain->pszEntryName; msgargs.apszArgs[ 1 ] = pInfo->pEntry->pszEntryName; msgargs.fStringOutput = TRUE;
MsgDlgUtil( NULL, SID_VI_ST_Explain, &msgargs, g_hinstDll, 0 );
if (msgargs.pszOutput) { SetDlgItemText( hwndDlg, CID_VI_ST_Explain, msgargs.pszOutput ); Free( msgargs.pszOutput ); } }
// Display finished window.
//
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); SetForegroundWindow( hwndDlg );
return TRUE; }
DWORD DwTerminalDlg( LPCWSTR lpszPhonebook, LPCWSTR lpszEntry, RASDIALPARAMS *prdp, HWND hwndOwner, HRASCONN hRasconn) { DWORD dwErr = ERROR_SUCCESS; PBENTRY *pEntry = NULL; PBFILE pbfile; DTLNODE *pNode = NULL; WCHAR szIpAddress[ TERM_IpAddress ]; DWORD sidTitle; WCHAR *pszIpAddress;
//
//Initialize memory for Whistler bug 160888
//
ZeroMemory(&pbfile, sizeof(PBFILE)); pbfile.hrasfile = -1;
dwErr = LoadRas( g_hinstDll, hwndOwner );
if (ERROR_SUCCESS != dwErr) { goto done; } dwErr = GetPbkAndEntryName( lpszPhonebook, lpszEntry, 0, &pbfile, &pNode);
if( (NULL == pNode) || (ERROR_SUCCESS != dwErr)) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; goto done; }
pEntry = (PBENTRY *) DtlGetData(pNode); ASSERT(NULL != pEntry);
if(NULL == pEntry) { goto done; }
if (pEntry->dwBaseProtocol == BP_Slip) { lstrcpyn( szIpAddress, (pEntry->pszIpAddress) ? pEntry->pszIpAddress : TEXT("0.0.0.0"), sizeof(szIpAddress) / sizeof(TCHAR)); pszIpAddress = szIpAddress; sidTitle = SID_T_SlipTerminal; } else { szIpAddress[0] = TEXT('\0'); pszIpAddress = szIpAddress; sidTitle = SID_T_PostconnectTerminal; }
if (!TerminalDlg( pEntry, prdp, hwndOwner, hRasconn, sidTitle, pszIpAddress )) { TRACE( "TerminalDlg==FALSE" ); dwErr = E_FAIL; goto done; }
TRACE2( "pszIpAddress=0x%08x(%ls)", pszIpAddress, pszIpAddress ? pszIpAddress : TEXT("") ); TRACE2( "pEntry->pszIpAddress=0x%08x(%ls)", pEntry->pszIpAddress, pEntry->pszIpAddress ? pEntry->pszIpAddress : TEXT("") );
if (pszIpAddress[0] && (!pEntry->pszIpAddress || lstrcmp( pszIpAddress, pEntry->pszIpAddress ) != 0)) { Free0( pEntry->pszIpAddress ); pEntry->pszIpAddress = StrDup( szIpAddress ); pEntry->fDirty = TRUE; dwErr = WritePhonebookFile( &pbfile, NULL ); if (dwErr != 0) { ErrorDlg( hwndOwner, SID_OP_WritePhonebook, dwErr, NULL ); } } done: ClosePhonebookFile(&pbfile); return dwErr; }
|