/// <summary> /// Releases the unmanaged resources used by the <see cref="DotRas.RasDialer"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing"><b>true</b> to release both managed and unmanaged resources; <b>false</b> to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (disposing) { if (this.IsBusy) { // The component is currently dialing a connection, abort the connection attempt. this.Abort(); this.handle = null; this.asyncOp = null; } if (this.timer != null) { this.timer.Dispose(); this.timer = null; } this.ReleaseEapIdentity(); this.Credentials = null; this.dialCompletedCallback = null; this.rasDialCallback = null; this.timeoutCallback = null; } base.Dispose(disposing); }
/// <summary> /// Initializes the component. /// </summary> protected override void InitializeComponent() { this.Timeout = System.Threading.Timeout.Infinite; this.HangUpPollingInterval = NativeMethods.HangUpPollingInterval; this.dialCompletedCallback = new SendOrPostCallback(this.DialCompletedCallback); this.timeoutCallback = new TimerCallback(this.TimeoutCallback); this.rasDialCallback = new NativeMethods.RasDialFunc2(this.RasDialCallback); base.InitializeComponent(); }
/// <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); }