/// <summary> /// Builds a new <see cref="NativeMethods.RASDIALPARAMS"/> structure based on the component settings. /// </summary> /// <returns>A new <see cref="NativeMethods.RASDIALPARAMS"/> structure.</returns> private NativeMethods.RASDIALPARAMS BuildDialParams() { NativeMethods.RASDIALPARAMS result = new NativeMethods.RASDIALPARAMS(); result.callbackId = this.CallbackId; result.subEntryId = this.SubEntryId; #if (WIN7 || WIN8) result.interfaceIndex = this.InterfaceIndex; #endif if (!string.IsNullOrEmpty(this.CallbackNumber)) { result.callbackNumber = this.CallbackNumber; } if (!string.IsNullOrEmpty(this.EntryName)) { result.entryName = this.EntryName; } if (!string.IsNullOrEmpty(this.PhoneNumber)) { result.phoneNumber = this.PhoneNumber; } if (this.Credentials == null && this.AllowUseStoredCredentials) { // Attempt to use any credentials stored for the entry since the caller didn't explicitly specify anything. NetworkCredential storedCredentials = RasHelper.Default.GetCredentials(this.PhoneBookPath, this.EntryName, NativeMethods.RASCM.UserName | NativeMethods.RASCM.Password | NativeMethods.RASCM.Domain); if (storedCredentials != null) { result.userName = storedCredentials.UserName; result.password = storedCredentials.Password; result.domain = storedCredentials.Domain; storedCredentials = null; } } else if (this.Credentials != null) { result.userName = this.Credentials.UserName; result.password = this.Credentials.Password; result.domain = this.Credentials.Domain; } return(result); }
/// <summary> /// Performs the dialing operation. /// </summary> /// <param name="asynchronous"><b>true</b> if the dialing operation should be asynchronous, otherwise <b>false</b>.</param> /// <returns>The handle of the connection.</returns> /// <exception cref="System.InvalidOperationException">A phone number or an entry name with phone book path is required to dial.</exception> private RasHandle InternalDial(bool asynchronous) { if (string.IsNullOrEmpty(this.PhoneNumber) && (string.IsNullOrEmpty(this.EntryName) || string.IsNullOrEmpty(this.PhoneBookPath))) { ThrowHelper.ThrowInvalidOperationException(Resources.Exception_PhoneNumberOrEntryNameRequired); } lock (this.syncRoot) { // NOTE: The synchronization object MUST be locked prior to testing of the component is already busy. // WARNING! Ensure no exceptions are thrown because existing dial attempts are already in progress. Doing so leaves the // connection open and cannot be closed if the application is terminated. if (!this.IsBusy) { this.IsBusy = true; try { NativeMethods.RASDIALPARAMS parameters = this.BuildDialParams(); NativeMethods.RASDIALEXTENSIONS extensions = this.BuildDialExtensions(); if (!string.IsNullOrEmpty(this.EntryName)) { byte[] data = null; if (this.eapUserData != null) { data = this.eapUserData; } else { data = RasHelper.Default.GetEapUserData(IntPtr.Zero, this.PhoneBookPath, this.EntryName); } if (data != null) { this.eapDataAddress = Marshal.AllocHGlobal(data.Length); Marshal.Copy(data, 0, this.eapDataAddress, data.Length); extensions.eapInfo.eapData = this.eapDataAddress; extensions.eapInfo.sizeOfEapData = data.Length; } } NativeMethods.RasDialFunc2 callback = null; if (asynchronous) { callback = this.rasDialCallback; this.asyncOp = AsyncOperationManager.CreateOperation(null); if (this.timer != null) { // Dispose of any existing timer if the component is being reused. this.timer.Dispose(); this.timer = null; } if (this.Timeout != System.Threading.Timeout.Infinite) { // A timeout has been requested, create the timer used to handle the connection timeout. this.timer = new Timer(this.timeoutCallback, null, this.Timeout, System.Threading.Timeout.Infinite); } } this.handle = RasHelper.Default.Dial(this.PhoneBookPath, parameters, extensions, callback, this.GetRasEapOptions()); if (!asynchronous) { this.SaveCredentialsToPhoneBook(); this.ReleaseEapIdentity(); // The synchronous dialing operation has completed, reset the dialing flag so the component can be reused. this.IsBusy = false; } } catch (Exception) { // An exception was thrown when the component was attempting to dial a connection. Release the EAP identity and reset the dialing flag so the component can be reused. this.ReleaseEapIdentity(); this.IsBusy = false; throw; } } } return(this.handle); }