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;
 }
Ejemplo n.º 2
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        // 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();
            }
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        // 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);
        }
Ejemplo n.º 6
0
        // 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);
        }
Ejemplo n.º 11
0
        // 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);
        }