/// <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); }
public DialCompletedEventArgs(RasHandle handle, Exception error, bool cancelled, bool timedOut, bool connected, object userState) : base(error, cancelled, userState) { Handle = handle; TimedOut = timedOut; Connected = connected; }
private bool RasDialCallback(IntPtr callbackId, int subEntryId, IntPtr dangerousHandle, int message, RasConnectionState state, int errorCode, int extendedErrorCode) { bool retval = true; lock (this.syncRoot) { RasHandle connectionHandle = null; try { connectionHandle = new RasHandle(dangerousHandle, subEntryId > 1); if (!this.IsBusy) { // The connection is no longer being dialed, stop receiving notifications for this connection attempt. retval = false; } else { string errorMessage = null; if (errorCode != NativeMethods.SUCCESS) { errorMessage = RasHelper.Default.GetRasErrorString(errorCode); } StateChangedEventArgs e = new StateChangedEventArgs(callbackId, subEntryId, connectionHandle, state, errorCode, errorMessage, extendedErrorCode); this.OnStateChanged(e); if (errorCode != NativeMethods.SUCCESS) { this.Abort(); this.PostCompleted(new RasDialException(errorCode, extendedErrorCode), false, false, false); retval = false; } else if (state == RasConnectionState.Connected) { this.PostCompleted(null, false, false, true); } } } catch (Exception ex) { this.OnError(new System.IO.ErrorEventArgs(ex)); } finally { DiagnosticTrace.Default.TraceEvent(TraceEventType.Verbose, new RasDialCallbackTraceEvent(retval, callbackId, subEntryId, dangerousHandle, message, state, errorCode, extendedErrorCode)); if (connectionHandle != null) { connectionHandle.Dispose(); } } } return(retval); }
/// <summary> /// Initializes a new instance of the <see cref="DotRas.StateChangedEventArgs"/> class. /// </summary> /// <param name="callbackId">The application defined value that was specified during dialing.</param> /// <param name="subEntryId">The one-based index for the phone book entry associated with this connection.</param> /// <param name="handle">The handle of the connection.</param> /// <param name="state">The state the remote access connection is about to enter.</param> /// <param name="errorCode">The error code (if any) that occurred.</param> /// <param name="errorMessage">The error message of the <paramref name="errorCode"/> that occurred.</param> /// <param name="extendedErrorCode">The extended error code (if any) that occurred.</param> internal StateChangedEventArgs(IntPtr callbackId, int subEntryId, RasHandle handle, RasConnectionState state, int errorCode, string errorMessage, int extendedErrorCode) { this.CallbackId = callbackId; this.SubEntryId = subEntryId; this.Handle = handle; this.State = state; this.ErrorCode = errorCode; this.ErrorMessage = errorMessage; this.ExtendedErrorCode = extendedErrorCode; }
private void Register(NativeMethods.RASCN changeType, RasHandle handle) { AutoResetEvent waitObject = new AutoResetEvent(false); int ret = SafeNativeMethods.Instance.RegisterConnectionNotification(handle, waitObject.SafeWaitHandle, changeType); if (ret == NativeMethods.SUCCESS) { RasConnectionWatcherStateObject stateObject = new RasConnectionWatcherStateObject(changeType); stateObject.WaitObject = waitObject; stateObject.WaitHandle = ThreadPool.RegisterWaitForSingleObject(waitObject, new WaitOrTimerCallback(this.ConnectionStateChanged), stateObject, Timeout.Infinite, false); this._stateObjects.Add(stateObject); } }
public static RasConnection GetActiveConnectionByHandle(RasHandle handle) { if (handle == null) { ThrowHelper.ThrowArgumentNullException("handle"); } RasConnection retval = null; foreach (RasConnection connection in GetActiveConnections()) { if (connection.Handle == handle) { retval = connection; break; } } return(retval); }
/// <summary> /// Notifies the asynchronous operation in progress the operation has completed. /// </summary> /// <param name="error">Any error that occurred during the asynchronous operation.</param> /// <param name="cancelled"><b>true</b> if the asynchronous operation was cancelled, otherwise <b>false</b>.</param> /// <param name="timedOut"><b>true</b> if the operation timed out, otherwise <b>false</b>.</param> /// <param name="connected"><b>true</b> if the connection attempt successfully connected, otherwise <b>false</b>.</param> private void PostCompleted(Exception error, bool cancelled, bool timedOut, bool connected) { lock (this.syncRoot) { if (connected) { // The client has connected successfully, attempt to update the credentials. this.SaveCredentialsToPhoneBook(); } this.ReleaseEapIdentity(); this.IsBusy = false; if (this.asyncOp != null) { this.asyncOp.PostOperationCompleted(this.dialCompletedCallback, new DialCompletedEventArgs(this.handle, error, cancelled, timedOut, connected, null)); this.asyncOp = null; this.handle = null; this.timer = null; } } }
/// <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); }
/// <summary> /// Initializes a new instance of the <see cref="DotRas.InvalidHandleException"/> class. /// </summary> /// <param name="handle">The <see cref="DotRas.RasHandle"/> that caused the exception.</param> /// <param name="message">A message that describes the error.</param> /// <param name="innerException">The exception that is the cause of the current exception, or null reference (<b>Nothing</b> in Visual Basic) if no inner exception is specified.</param> public InvalidHandleException(RasHandle handle, string message, Exception innerException) : base(message, innerException) { this.Handle = handle; }
/// <summary> /// Initializes a new instance of the <see cref="DotRas.InvalidHandleException"/> class. /// </summary> /// <param name="handle">The <see cref="DotRas.RasHandle"/> that caused the exception.</param> /// <param name="message">A message that describes the error.</param> public InvalidHandleException(RasHandle handle, string message) : this(handle, message, null) { }
/// <summary> /// Initializes a new instance of the <see cref="DotRas.InvalidHandleException"/> class. /// </summary> /// <param name="handle">The <see cref="DotRas.RasHandle"/> that caused the exception.</param> public InvalidHandleException(RasHandle handle) : this(handle, null) { }