public static bool UnsafeNotifyStableUnicastIpAddressTable(Action<object> callback, object state) { TeredoHelper item = new TeredoHelper(callback, state); uint num = 0; SafeFreeMibTable table = null; lock (pendingNotifications) { if (impendingAppDomainUnload) { return false; } num = UnsafeNetInfoNativeMethods.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out table, item.onStabilizedDelegate, IntPtr.Zero, out item.cancelHandle); if (table != null) { table.Dispose(); } if (num == 0x3e5) { pendingNotifications.Add(item); return false; } } if (num != 0) { throw new Win32Exception((int) num); } return true; }
private static void OnStabilized(IntPtr context, IntPtr table) { Interop.IpHlpApi.FreeMibTable(table); TeredoHelper helper = (TeredoHelper)GCHandle.FromIntPtr(context).Target !; // Lock the TeredoHelper instance to ensure that only the first call to OnStabilized will get to call // RunCallback. This is the only place that TeredoHelpers get locked, as individual instances are not // exposed to higher layers, so there's no chance for deadlock. if (!helper._runCallbackCalled) { lock (helper) { if (!helper._runCallbackCalled) { helper._runCallbackCalled = true; ThreadPool.QueueUserWorkItem(o => { TeredoHelper helper = (TeredoHelper)o !; // We are intentionally not calling Dispose synchronously inside the OnStabilized callback. // According to MSDN, calling CancelMibChangeNotify2 inside the callback results into deadlock. helper.Dispose(); helper._callback.Invoke(helper._state); }, helper); } } } }
// Returns true if the address table is already stable. Otherwise, calls callback when it becomes stable. // 'Unsafe' because it does not flow ExecutionContext to the callback. public static unsafe bool UnsafeNotifyStableUnicastIpAddressTable(Action <object> callback, object state) { Debug.Assert(callback != null); TeredoHelper?helper = new TeredoHelper(callback, state); try { uint err = Interop.IpHlpApi.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out SafeFreeMibTable table, &OnStabilized, GCHandle.ToIntPtr(helper._gcHandle), out helper._cancelHandle); table.Dispose(); if (err == Interop.IpHlpApi.ERROR_IO_PENDING) { Debug.Assert(helper._cancelHandle != null && !helper._cancelHandle.IsInvalid); // Suppress synchronous Dispose. Dispose will be called asynchronously by the callback. helper = null; return(false); } if (err != Interop.IpHlpApi.ERROR_SUCCESS) { throw new Win32Exception((int)err); } return(true); } finally { helper?.Dispose(); } }
public static bool UnsafeNotifyStableUnicastIpAddressTable(Action <object> callback, object state) { TeredoHelper item = new TeredoHelper(callback, state); uint num = 0; SafeFreeMibTable table = null; lock (pendingNotifications) { if (impendingAppDomainUnload) { return(false); } num = UnsafeNetInfoNativeMethods.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out table, item.onStabilizedDelegate, IntPtr.Zero, out item.cancelHandle); if (table != null) { table.Dispose(); } if (num == 0x3e5) { pendingNotifications.Add(item); return(false); } } if (num != 0) { throw new Win32Exception((int)num); } return(true); }
// Returns true if the address table is already stable. Otherwise, calls callback when it becomes stable. // 'Unsafe' because it does not flow ExecutionContext to the callback. public static bool UnsafeNotifyStableUnicastIpAddressTable(Action <object> callback, object state) { if (callback == null) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("UnsafeNotifyStableUnicastIpAddressTable called without specifying callback!"); } Debug.Fail("UnsafeNotifyStableUnicastIpAddressTable called without specifying callback!"); } TeredoHelper helper = new TeredoHelper(callback, state); uint err = Interop.IpHlpApi.ERROR_SUCCESS; SafeFreeMibTable table = null; lock (s_pendingNotifications) { // If OnAppDomainUnload gets the lock first, tell our caller that we'll finish async. Their AppDomain // is about to go down anyways. If we do, hold the lock until we've added helper to the // s_pendingNotifications list (if we're going to complete asynchronously). if (Environment.HasShutdownStarted) { return(false); } err = Interop.IpHlpApi.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out table, helper._onStabilizedDelegate, IntPtr.Zero, out helper._cancelHandle); if (table != null) { table.Dispose(); } if (err == Interop.IpHlpApi.ERROR_IO_PENDING) { if (helper._cancelHandle.IsInvalid) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("CancelHandle invalid despite returning ERROR_IO_PENDING"); } Debug.Fail("CancelHandle invalid despite returning ERROR_IO_PENDING"); } // Async completion: add us to the s_pendingNotifications list so we'll be canceled in the // event of an AppDomain unload. s_pendingNotifications.Add(helper); return(false); } } if (err != Interop.IpHlpApi.ERROR_SUCCESS) { throw new Win32Exception((int)err); } return(true); }
// Returns true if the address table is already stable. Otherwise, calls callback when it becomes stable. // 'Unsafe' because it does not flow ExecutionContext to the callback. public static bool UnsafeNotifyStableUnicastIpAddressTable(Action<object> callback, object state) { if (callback == null) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("UnsafeNotifyStableUnicastIpAddressTable called without specifying callback!"); } Debug.Fail("UnsafeNotifyStableUnicastIpAddressTable called without specifying callback!"); } TeredoHelper helper = new TeredoHelper(callback, state); uint err = Interop.IpHlpApi.ERROR_SUCCESS; SafeFreeMibTable table = null; lock (s_pendingNotifications) { // If OnAppDomainUnload gets the lock first, tell our caller that we'll finish async. Their AppDomain // is about to go down anyways. If we do, hold the lock until we've added helper to the // s_pendingNotifications list (if we're going to complete asynchronously). if (Environment.HasShutdownStarted) { return false; } err = Interop.IpHlpApi.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out table, helper._onStabilizedDelegate, IntPtr.Zero, out helper._cancelHandle); if (table != null) { table.Dispose(); } if (err == Interop.IpHlpApi.ERROR_IO_PENDING) { if (helper._cancelHandle.IsInvalid) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("CancelHandle invalid despite returning ERROR_IO_PENDING"); } Debug.Fail("CancelHandle invalid despite returning ERROR_IO_PENDING"); } // Async completion: add us to the s_pendingNotifications list so we'll be canceled in the // event of an AppDomain unload. s_pendingNotifications.Add(helper); return false; } } if (err != Interop.IpHlpApi.ERROR_SUCCESS) { throw new Win32Exception((int)err); } return true; }
public override UnicastIPAddressInformationCollection GetUnicastAddresses() { // Wait for the Address Table to stabilize using (ManualResetEvent stable = new ManualResetEvent(false)) { if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(StableUnicastAddressTableCallback, stable)) { stable.WaitOne(); } } return(GetUnicastAddressTable()); }
public override IAsyncResult BeginGetUnicastAddresses(AsyncCallback callback, object state) { ContextAwareResult asyncResult = new ContextAwareResult(false, false, this, state, callback); asyncResult.StartPostingAsyncOp(false); if (TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(StableUnicastAddressTableCallback, asyncResult)) { asyncResult.InvokeCallback(); } asyncResult.FinishPostingAsyncOp(); return(asyncResult); }
public override UnicastIPAddressInformationCollection GetUnicastAddresses() { if (!ComNetOS.IsVista) { throw new PlatformNotSupportedException(SR.GetString("VistaRequired")); } using (ManualResetEvent event2 = new ManualResetEvent(false)) { if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(new Action <object>(SystemIPGlobalProperties.StableUnicastAddressTableCallback), event2)) { event2.WaitOne(); } } return(GetUnicastAddressTable()); }
public override IAsyncResult BeginGetUnicastAddresses(AsyncCallback callback, object state) { if (!ComNetOS.IsVista) { throw new PlatformNotSupportedException(SR.GetString("VistaRequired")); } ContextAwareResult result = new ContextAwareResult(false, false, this, state, callback); result.StartPostingAsyncOp(false); if (TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(new Action <object>(SystemIPGlobalProperties.StableUnicastAddressTableCallback), result)) { result.InvokeCallback(); } result.FinishPostingAsyncOp(); return(result); }
// Returns true if the address table is already stable. Otherwise, calls callback when it becomes stable. // 'Unsafe' because it does not flow ExecutionContext to the callback. public static bool UnsafeNotifyStableUnicastIpAddressTable(Action<object> callback, object state) { GlobalLog.Assert(callback != null, "UnsafeNotifyStableUnicastIpAddressTable called without specifying callback!"); TeredoHelper helper = new TeredoHelper(callback, state); uint err = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; SafeFreeMibTable table = null; lock (pendingNotifications) { // If OnAppDomainUnload gets the lock first, tell our caller that we'll finish async. Their AppDomain // is about to go down anyways. If we do, hold the lock until we've added helper to the // pendingNotifications list (if we're going to complete asynchronously). if (impendingAppDomainUnload) { return false; } err = UnsafeNetInfoNativeMethods.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out table, helper.onStabilizedDelegate, IntPtr.Zero, out helper.cancelHandle); if (table != null) { table.Dispose(); } if (err == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { GlobalLog.Assert(!helper.cancelHandle.IsInvalid, "CancelHandle invalid despite returning ERROR_IO_PENDING"); // Async completion: add us to the pendingNotifications list so we'll be canceled in the // event of an AppDomain unload. pendingNotifications.Add(helper); return false; } } if (err != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { throw new Win32Exception((int)err); } return true; }
// Returns true if the address table is already stable. Otherwise, calls callback when it becomes stable. // 'Unsafe' because it does not flow ExecutionContext to the callback. public static bool UnsafeNotifyStableUnicastIpAddressTable(Action <object> callback, object state) { GlobalLog.Assert(callback != null, "UnsafeNotifyStableUnicastIpAddressTable called without specifying callback!"); TeredoHelper helper = new TeredoHelper(callback, state); uint err = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; SafeFreeMibTable table = null; lock (pendingNotifications) { // If OnAppDomainUnload gets the lock first, tell our caller that we'll finish async. Their AppDomain // is about to go down anyways. If we do, hold the lock until we've added helper to the // pendingNotifications list (if we're going to complete asynchronously). if (impendingAppDomainUnload) { return(false); } err = UnsafeNetInfoNativeMethods.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified, out table, helper.onStabilizedDelegate, IntPtr.Zero, out helper.cancelHandle); if (table != null) { table.Dispose(); } if (err == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { GlobalLog.Assert(!helper.cancelHandle.IsInvalid, "CancelHandle invalid despite returning ERROR_IO_PENDING"); // Async completion: add us to the pendingNotifications list so we'll be canceled in the // event of an AppDomain unload. pendingNotifications.Add(helper); return(false); } } if (err != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { throw new Win32Exception((int)err); } return(true); }