Пример #1
0
        public static SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] writeBuffer, int size, int headerSize, int trailerSize, out int resultSize)
        {
            // Encryption using SCHANNEL requires 4 buffers: header, payload, trailer, empty.
            SecurityBuffer[] securityBuffer = new SecurityBuffer[4];

            securityBuffer[0] = new SecurityBuffer(writeBuffer, 0, headerSize, SecurityBufferType.Header);
            securityBuffer[1] = new SecurityBuffer(writeBuffer, headerSize, size, SecurityBufferType.Data);
            securityBuffer[2] = new SecurityBuffer(writeBuffer, headerSize + size, trailerSize, SecurityBufferType.Trailer);
            securityBuffer[3] = new SecurityBuffer(null, SecurityBufferType.Empty);

            int errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPISecureChannel, securityContext, securityBuffer, 0);

            if (errorCode != 0)
            {
                GlobalLog.Print("SslStreamPal.Windows: SecureChannel#" + Logging.HashString(securityContext) + "::Encrypt ERROR" + errorCode.ToString("x"));
                resultSize = 0;
            }
            else
            {
                // The full buffer may not be used.
                resultSize = securityBuffer[0].size + securityBuffer[1].size + securityBuffer[2].size;
            }

            return(GetSecurityStatusPalFromWin32Int(errorCode));
        }
Пример #2
0
        // This method is guaranteed to be called only once.  If called with a non-zero userToken, the context is not flowed.
        protected override void Complete(IntPtr userToken)
        {
            GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::Complete() _Context(set):" + (_context != null).ToString() + " userToken:" + userToken.ToString());

            // If no flowing, just complete regularly.
            if ((_flags & StateFlags.PostBlockStarted) == 0)
            {
                base.Complete(userToken);
                return;
            }

            // At this point, IsCompleted is set and CompletedSynchronously is fixed.  If it's synchronous, then we want to hold
            // the completion for the CaptureOrComplete() call to avoid the context flow.  If not, we know CaptureOrComplete() has completed.
            if (CompletedSynchronously)
            {
                return;
            }

            ExecutionContext context = _context;

            // If the context is being abandoned or wasn't captured (SuppressFlow, null AsyncCallback), just
            // complete regularly, as long as CaptureOrComplete() has finished.
            //
            if (userToken != IntPtr.Zero || context == null)
            {
                base.Complete(userToken);
                return;
            }

            ExecutionContext.Run((_flags & StateFlags.ThreadSafeContextCopy) != 0 ? context.CreateCopy() : context,
                                 new ContextCallback(CompleteCallback), null);
        }
Пример #3
0
        private object _event;                     // Lazy allocated event to be returned in the IAsyncResult for the client to wait on.


        internal LazyAsyncResult(object myObject, object myState, AsyncCallback myCallBack)
        {
            _asyncObject   = myObject;
            _asyncState    = myState;
            _asyncCallback = myCallBack;
            _result        = DBNull.Value;
            GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::.ctor()");
        }
Пример #4
0
 internal static void Exit(TraceSource traceSource, object obj, string method, string retValue)
 {
     if (!ValidateSettings(traceSource, TraceEventType.Information))
     {
         return;
     }
     Exit(traceSource, GetObjectName(obj) + "#" + Logging.HashString(obj), method, retValue);
 }
Пример #5
0
 internal static void Enter(TraceSource traceSource, object obj, string method, object paramObject)
 {
     if (!ValidateSettings(traceSource, TraceEventType.Information))
     {
         return;
     }
     Enter(traceSource, GetObjectName(obj) + "#" + Logging.HashString(obj), method, paramObject);
 }
Пример #6
0
 internal static void PrintError(TraceSource traceSource, object obj, string method, string msg)
 {
     if (!ValidateSettings(traceSource, TraceEventType.Error))
     {
         return;
     }
     PrintLine(traceSource, TraceEventType.Error, 0,
               GetObjectName(obj) + "#" + Logging.HashString(obj)
               + "::" + method + "() - " + msg);
 }
Пример #7
0
 internal static void PrintInfo(TraceSource traceSource, object obj, string method, string param)
 {
     if (!ValidateSettings(traceSource, TraceEventType.Information))
     {
         return;
     }
     PrintLine(traceSource, TraceEventType.Information, 0,
               GetObjectName(obj) + "#" + Logging.HashString(obj)
               + "::" + method + "(" + param + ")");
 }
Пример #8
0
 internal static void PrintInfo(TraceSource traceSource, object obj, string msg)
 {
     if (!ValidateSettings(traceSource, TraceEventType.Information))
     {
         return;
     }
     PrintLine(traceSource, TraceEventType.Information, 0,
               GetObjectName(obj) + "#" + Logging.HashString(obj)
               + " - " + msg);
 }
Пример #9
0
        protected override void Cleanup()
        {
            base.Cleanup();

            GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::Cleanup()");
            if (_windowsIdentity != null)
            {
                _windowsIdentity.Dispose();
                _windowsIdentity = null;
            }
        }
Пример #10
0
        protected override void Cleanup()
        {
            base.Cleanup();

            GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::Cleanup()");
            if (_Wi != null)
            {
                _Wi.Dispose();
                _Wi = null;
            }
        }
Пример #11
0
        internal static void Associate(TraceSource traceSource, object objA, object objB)
        {
            if (!ValidateSettings(traceSource, TraceEventType.Information))
            {
                return;
            }

            string lineA = GetObjectName(objA) + "#" + Logging.HashString(objA);
            string lineB = GetObjectName(objB) + "#" + Logging.HashString(objB);

            PrintLine(traceSource, TraceEventType.Information, 0, "Associating " + lineA + " with " + lineB);
        }
Пример #12
0
        //
        // Used only by client SSL code, never returns null.
        //
        internal override string[] GetRequestCertificateAuthorities(SafeDeleteContext securityContext)
        {
            string[] issuers = Array.Empty <string>();

            object outObj;

            int errorCode = SSPIWrapper.QueryContextIssuerList(GlobalSSPI.SSPISecureChannel, securityContext, out outObj);

            GlobalLog.Assert(errorCode == 0, "QueryContextIssuerList returned errorCode:" + errorCode);

            Interop.Secur32.IssuerListInfoEx issuerList = (Interop.Secur32.IssuerListInfoEx)outObj;

            try
            {
                if (issuerList.cIssuers > 0)
                {
                    unsafe
                    {
                        uint count = issuerList.cIssuers;
                        issuers = new string[issuerList.cIssuers];
                        Interop.Secur32._CERT_CHAIN_ELEMENT *pIL = (Interop.Secur32._CERT_CHAIN_ELEMENT *)issuerList.aIssuers.DangerousGetHandle();
                        for (int i = 0; i < count; ++i)
                        {
                            Interop.Secur32._CERT_CHAIN_ELEMENT *pIL2 = pIL + i;
                            GlobalLog.Assert(pIL2->cbSize > 0, "SecureChannel::GetIssuers()", "Interop.Secur32._CERT_CHAIN_ELEMENT size is not positive: " + pIL2->cbSize.ToString());
                            if (pIL2->cbSize > 0)
                            {
                                uint   size = pIL2->cbSize;
                                byte * ptr  = (byte *)(pIL2->pCertContext);
                                byte[] x    = new byte[size];
                                for (int j = 0; j < size; j++)
                                {
                                    x[j] = *(ptr + j);
                                }

                                X500DistinguishedName x500DistinguishedName = new X500DistinguishedName(x);
                                issuers[i] = x500DistinguishedName.Name;
                                GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::GetIssuers() IssuerListEx[" + i + "]:" + issuers[i]);
                            }
                        }
                    }
                }
            }
            finally
            {
                if (issuerList.aIssuers != null)
                {
                    issuerList.aIssuers.Dispose();
                }
            }

            return(issuers);
        }
Пример #13
0
        internal static void Exit(TraceSource traceSource, string obj, string method, object retObject)
        {
            if (!ValidateSettings(traceSource, TraceEventType.Information))
            {
                return;
            }
            string retValue = "";

            if (retObject != null)
            {
                retValue = GetObjectName(retObject) + "#" + Logging.HashString(retObject);
            }
            Exit(traceSource, obj, method, retValue);
        }
Пример #14
0
        internal static void Enter(TraceSource traceSource, string obj, string method, object paramObject)
        {
            if (!ValidateSettings(traceSource, TraceEventType.Information))
            {
                return;
            }
            string paramObjectValue = "";

            if (paramObject != null)
            {
                paramObjectValue = GetObjectName(paramObject) + "#" + Logging.HashString(paramObject);
            }
            Enter(traceSource, obj + "::" + method + "(" + paramObjectValue + ")");
        }
Пример #15
0
        internal static SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SSPIInterface SecModule, SafeDeleteContext securityContext, ChannelBindingKind contextAttribute)
        {
            GlobalLog.Enter("QueryContextChannelBinding", contextAttribute.ToString());

            SafeFreeContextBufferChannelBinding result;

            int errorCode = SecModule.QueryContextChannelBinding(securityContext, contextAttribute, out result);

            if (result != null)
            {
                GlobalLog.Leave("QueryContextChannelBinding", Logging.HashString(result));
            }

            return(result);
        }
Пример #16
0
        public static SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.Secur32.ContextAttribute contextAttribute)
        {
            GlobalLog.Enter("QueryContextChannelBinding", contextAttribute.ToString());

            SafeFreeContextBufferChannelBinding result;
            int errorCode = secModule.QueryContextChannelBinding(securityContext, contextAttribute, out result);

            if (errorCode != 0)
            {
                GlobalLog.Leave("QueryContextChannelBinding", "ERROR = " + ErrorDescription(errorCode));
                return(null);
            }

            GlobalLog.Leave("QueryContextChannelBinding", Logging.HashString(result));
            return(result);
        }
Пример #17
0
        //
        //  MUST NOT BE CALLED DIRECTLY
        //  A protected method that does callback job and it is guaranteed to be called exactly once.
        //  A derived overriding method must call the base class somewhere or the completion is lost.
        //
        protected virtual void Complete(IntPtr userToken)
        {
            bool          offloaded     = false;
            ThreadContext threadContext = CurrentThreadContext;

            try
            {
                ++threadContext.m_NestedIOCount;
                if (_asyncCallback != null)
                {
                    GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::Complete() invoking callback");

                    if (threadContext.m_NestedIOCount >= c_ForceAsyncCount)
                    {
                        GlobalLog.Print("LazyAsyncResult::Complete *** OFFLOADED the user callback ***");
                        Task.Factory.StartNew(
                            s => WorkerThreadComplete(s),
                            null,
                            CancellationToken.None,
                            TaskCreationOptions.DenyChildAttach,
                            TaskScheduler.Default);

                        offloaded = true;
                    }
                    else
                    {
                        _asyncCallback(this);
                    }
                }
                else
                {
                    GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::Complete() no callback to invoke");
                }
            }
            finally
            {
                --threadContext.m_NestedIOCount;

                // Never call this method unless interlocked m_IntCompleted check has succeeded (like in this case)
                if (!offloaded)
                {
                    Cleanup();
                }
            }
        }
Пример #18
0
        // A method for completing the IO with a result and invoking the user's callback.
        // Used by derived classes to pass context into an overridden Complete().  Useful
        // for determining the 'winning' thread in case several may simultaneously call
        // the equivalent of InvokeCallback().
        protected void ProtectedInvokeCallback(object result, IntPtr userToken)
        {
            GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::ProtectedInvokeCallback() result = " +
                            (result is Exception ? ((Exception)result).Message : result == null ? "<null>" : result.ToString()) +
                            ", userToken:" + userToken.ToString());

            // Critical to disallow DBNull here - it could result in a stuck spinlock in WaitForCompletion.
            if (result == DBNull.Value)
            {
                throw new ArgumentNullException("result");
            }

#if DEBUG
            // Always safe to ask for the state now.
            _ProtectState = false;
#endif

            if ((_intCompleted & ~c_HighBit) == 0 && (Interlocked.Increment(ref _intCompleted) & ~c_HighBit) == 1)
            {
                // DBNull.Value is used to guarantee that the first caller wins,
                // even if the result was set to null.
                if (_result == DBNull.Value)
                {
                    _result = result;
                }

                ManualResetEvent asyncEvent = (ManualResetEvent)_event;
                if (asyncEvent != null)
                {
                    try
                    {
                        asyncEvent.Set();
                    }
                    catch (ObjectDisposedException)
                    {
                        // Simply ignore this exception - There is apparently a rare race condition
                        // where the event is disposed before the completion method is called.
                    }
                }

                Complete(userToken);
            }
        }
Пример #19
0
        // Allows creating a pre-completed result with less interlockeds.  Beware!  Constructor calls the callback.
        // If a derived class ever uses this and overloads Cleanup, this may need to change.
        internal LazyAsyncResult(object myObject, object myState, AsyncCallback myCallBack, object result)
        {
            GlobalLog.Assert(result != DBNull.Value, "LazyAsyncResult#{0}::.ctor()|Result can't be set to DBNull - it's a special internal value.", Logging.HashString(this));
            _asyncObject   = myObject;
            _asyncState    = myState;
            _asyncCallback = myCallBack;
            _result        = result;
            _intCompleted  = 1;

            if (_asyncCallback != null)
            {
                GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::Complete() invoking callback");
                _asyncCallback(this);
            }
            else
            {
                GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::Complete() no callback to invoke");
            }

            GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::.ctor() (pre-completed)");
        }
Пример #20
0
        //
        // Extracts a remote certificate upon request.
        //
        internal override X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateStore)
        {
            remoteCertificateStore = null;

            if (securityContext == null)
            {
                return(null);
            }

            GlobalLog.Enter("SecureChannel#" + Logging.HashString(this) + "::RemoteCertificate{get;}");
            X509Certificate2    result        = null;
            SafeFreeCertContext remoteContext = null;

            try
            {
                int errorCode = SSPIWrapper.QueryContextRemoteCertificate(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext);
                if (remoteContext != null && !remoteContext.IsInvalid)
                {
                    result = new X509Certificate2(remoteContext.DangerousGetHandle());
                }
            }
            finally
            {
                if (remoteContext != null && !remoteContext.IsInvalid)
                {
                    remoteCertificateStore = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext);

                    remoteContext.Dispose();
                }
            }

            if (Logging.On)
            {
                Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_remote_certificate, (result == null ? "null" : result.ToString(true))));
            }

            GlobalLog.Leave("SecureChannel#" + Logging.HashString(this) + "::RemoteCertificate{get;}", (result == null ? "null" : result.Subject));

            return(result);
        }
        //
        // Extracts a remote certificate upon request.
        //
        internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateStore)
        {
            remoteCertificateStore = null;

            if (securityContext == null)
            {
                return(null);
            }

            GlobalLog.Enter("CertificateValidationPal.Windows SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()");
            X509Certificate2    result        = null;
            SafeFreeCertContext remoteContext = null;

            try
            {
                remoteContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.Secur32.ContextAttribute.RemoteCertificate) as SafeFreeCertContext;
                if (remoteContext != null && !remoteContext.IsInvalid)
                {
                    result = new X509Certificate2(remoteContext.DangerousGetHandle());
                }
            }
            finally
            {
                if (remoteContext != null && !remoteContext.IsInvalid)
                {
                    remoteCertificateStore = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext);

                    remoteContext.Dispose();
                }
            }

            if (Logging.On)
            {
                Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_remote_certificate, (result == null ? "null" : result.ToString(true))));
            }

            GlobalLog.Leave("CertificateValidationPal.Windows SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()", (result == null ? "null" : result.Subject));

            return(result);
        }
Пример #22
0
        public SecurityStatus EncryptMessage(SafeDeleteContext securityContext, byte[] buffer, int size, int headerSize, int trailerSize, out int resultSize)
        {
            resultSize = 0;

            // Encryption using SCHANNEL requires 4 buffers: header, payload, trailer, empty.
            SecurityBuffer[] securityBuffer = new SecurityBuffer[4];

            securityBuffer[0] = new SecurityBuffer(buffer, 0, headerSize, SecurityBufferType.Header);
            securityBuffer[1] = new SecurityBuffer(buffer, headerSize, size, SecurityBufferType.Data);
            securityBuffer[2] = new SecurityBuffer(buffer, headerSize + size, trailerSize, SecurityBufferType.Trailer);
            securityBuffer[3] = new SecurityBuffer(null, SecurityBufferType.Empty);

            SecurityStatus secStatus = EncryptDecryptHelper(OP.Encrypt, securityContext, securityBuffer, 0);

            if (secStatus == 0)
            {
                // The full buffer may not be used.
                resultSize = securityBuffer[0].size + securityBuffer[1].size + securityBuffer[2].size;
                GlobalLog.Leave("SecureChannel#" + Logging.HashString(this) + "::Encrypt OK", "data size:" + resultSize.ToString());
            }

            return(secStatus);
        }
        //
        // Extracts a remote certificate upon request.
        //
        internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateStore)
        {
            remoteCertificateStore = null;
            bool gotReference = false;

            if (securityContext == null)
            {
                return null;
            }

            GlobalLog.Enter("CertificateValidationPal.Unix SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()");
            X509Certificate2 result = null;
            SafeFreeCertContext remoteContext = null;
            try
            {
                int errorCode = QueryContextRemoteCertificate(securityContext, out remoteContext);

                if (remoteContext != null && !remoteContext.IsInvalid)
                {
                    remoteContext.DangerousAddRef(ref gotReference);
                    result = new X509Certificate2(remoteContext.DangerousGetHandle());
                }

                remoteCertificateStore = new X509Certificate2Collection();

                using (SafeSharedX509StackHandle chainStack =
                    Interop.OpenSsl.GetPeerCertificateChain(securityContext.SslContext))
                {
                    if (!chainStack.IsInvalid)
                    {
                        int count = Interop.Crypto.GetX509StackFieldCount(chainStack);

                        for (int i = 0; i < count; i++)
                        {
                            IntPtr certPtr = Interop.Crypto.GetX509StackField(chainStack, i);

                            if (certPtr != IntPtr.Zero)
                            {
                                // X509Certificate2(IntPtr) calls X509_dup, so the reference is appropriately tracked.
                                X509Certificate2 chainCert = new X509Certificate2(certPtr);
                                remoteCertificateStore.Add(chainCert);
                            }
                        }
                    }
                }
            }
            finally
            {
                if (gotReference)
                {
                    remoteContext.DangerousRelease();
                }

                if (remoteContext != null)
                {
                    remoteContext.Dispose();
                }
            }

            if (Logging.On)
            {
                Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_remote_certificate, (result == null ? "null" : result.ToString(true))));
            }

            GlobalLog.Leave("CertificateValidationPal.Unix SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()", (result == null ? "null" : result.Subject));

            return result;
        }      
Пример #24
0
 private void CompleteCallback(object state)
 {
     GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CompleteCallback() Context set, calling callback.");
     base.Complete(IntPtr.Zero);
 }
Пример #25
0
        internal CookieCollection CookieCutter(Uri uri, string headerName, string setCookieHeader, bool isThrow)
        {
            bool globalLogEnabled = GlobalLog.IsEnabled;

            if (globalLogEnabled)
            {
                GlobalLog.Print("CookieContainer#" + Logging.HashString(this) + "::CookieCutter() uri:" + uri + " headerName:" + headerName + " setCookieHeader:" + setCookieHeader + " isThrow:" + isThrow);
            }

            CookieCollection cookies = new CookieCollection();
            CookieVariant    variant = CookieVariant.Unknown;

            if (headerName == null)
            {
                variant = CookieVariant.Default;
            }
            else
            {
                for (int i = 0; i < s_headerInfo.Length; ++i)
                {
                    if ((String.Compare(headerName, s_headerInfo[i].Name, StringComparison.OrdinalIgnoreCase) == 0))
                    {
                        variant = s_headerInfo[i].Variant;
                    }
                }
            }

            bool isLocalDomain = IsLocalDomain(uri.Host);

            try
            {
                CookieParser parser = new CookieParser(setCookieHeader);
                do
                {
                    Cookie cookie = parser.Get();
                    if (globalLogEnabled)
                    {
                        GlobalLog.Print("CookieContainer#" + Logging.HashString(this) + "::CookieCutter() CookieParser returned cookie:" + Logging.ObjectToString(cookie));
                    }

                    if (cookie == null)
                    {
                        break;
                    }

                    // Parser marks invalid cookies this way
                    if (String.IsNullOrEmpty(cookie.Name))
                    {
                        if (isThrow)
                        {
                            throw new CookieException(SR.net_cookie_format);
                        }
                        // Otherwise, ignore (reject) cookie
                        continue;
                    }

                    // This will set the default values from the response URI
                    // AND will check for cookie validity
                    if (!cookie.VerifySetDefaults(variant, uri, isLocalDomain, _fqdnMyDomain, true, isThrow))
                    {
                        continue;
                    }
                    // If many same cookies arrive we collapse them into just one, hence setting
                    // parameter isStrict = true below
                    cookies.InternalAdd(cookie, true);
                } while (true);
            }
            catch (OutOfMemoryException)
            {
                throw;
            }
            catch (Exception e)
            {
                if (isThrow)
                {
                    throw new CookieException(SR.Format(SR.net_cookie_parse_header, uri.AbsoluteUri), e);
                }
            }

            foreach (Cookie c in cookies)
            {
                Add(c, isThrow);
            }

            return(cookies);
        }
Пример #26
0
        // This must be called right before returning the result to the user.  It might call the callback itself,
        // to avoid flowing context.  Even if the operation completes before this call, the callback won't have been
        // called.
        //
        // Returns whether the operation completed sync or not.
        private bool CaptureOrComplete(ref ExecutionContext cachedContext, bool returnContext)
        {
            GlobalLog.Assert((_flags & StateFlags.PostBlockStarted) != 0, "ContextAwareResult#{0}::CaptureOrComplete|Called without calling StartPostingAsyncOp.", Logging.HashString(this));

            // See if we're going to need to capture the context.
            bool capturingContext = AsyncCallback != null || (_flags & StateFlags.CaptureContext) != 0;

            // Peek if we've already completed, but don't fix CompletedSynchronously yet
            // Capture the identity if requested, unless we're going to capture the context anyway, unless
            // capturing the context won't be sufficient.
            if ((_flags & StateFlags.CaptureIdentity) != 0 && !InternalPeekCompleted && (!capturingContext))
            {
                GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() starting identity capture");
                SafeCaptureIdentity();
            }

            // No need to flow if there's no callback, unless it's been specifically requested.
            // Note that Capture() can return null, for example if SuppressFlow() is in effect.
            if (capturingContext && !InternalPeekCompleted)
            {
                GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() starting capture");
                if (cachedContext == null)
                {
                    cachedContext = ExecutionContext.Capture();
                }

                if (cachedContext != null)
                {
                    if (!returnContext)
                    {
                        _context      = cachedContext;
                        cachedContext = null;
                    }
                    else
                    {
                        _context = cachedContext.CreateCopy();
                    }
                }
                GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() _Context:" + Logging.HashString(_context));
            }
            else
            {
                // Otherwise we have to have completed synchronously, or not needed the context.
                GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() skipping capture");
                cachedContext = null;
                GlobalLog.Assert(AsyncCallback == null || CompletedSynchronously, "ContextAwareResult#{0}::CaptureOrComplete|Didn't capture context, but didn't complete synchronously!", Logging.HashString(this));
            }

            // Now we want to see for sure what to do.  We might have just captured the context for no reason.
            // This has to be the first time the state has been queried "for real" (apart from InvokeCallback)
            // to guarantee synchronization with Complete() (otherwise, Complete() could try to call the
            // callback without the context having been gotten).
            DebugProtectState(false);
            if (CompletedSynchronously)
            {
                GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() completing synchronously");
                base.Complete(IntPtr.Zero);
                return(true);
            }

            return(false);
        }
Пример #27
0
 internal static string GetObjectLogHash(object obj)
 {
     return(GetObjectName(obj) + "#" + Logging.HashString(obj));
 }
Пример #28
0
        // If ContextCopy or Identity will be used, the return value should be locked until FinishPostingAsyncOp() is called
        // or the operation has been aborted (e.g. by BeginXxx throwing).  Otherwise, this can be called with false to prevent the lock
        // object from being created.
        internal object StartPostingAsyncOp(bool lockCapture)
        {
            GlobalLog.Assert(!InternalPeekCompleted, "ContextAwareResult#{0}::StartPostingAsyncOp|Called on completed result.", Logging.HashString(this));

            DebugProtectState(true);

            _lock   = lockCapture ? new object() : null;
            _flags |= StateFlags.PostBlockStarted;
            return(_lock);
        }
Пример #29
0
        internal static void Dump(TraceSource traceSource, object obj, string method, byte[] buffer, int offset, int length)
        {
            if (!ValidateSettings(traceSource, TraceEventType.Verbose))
            {
                return;
            }

            if (buffer == null)
            {
                PrintLine(traceSource, TraceEventType.Verbose, 0, "(null)");
                return;
            }

            if (offset > buffer.Length)
            {
                PrintLine(traceSource, TraceEventType.Verbose, 0, "(offset out of range)");
                return;
            }

            PrintLine(traceSource, TraceEventType.Verbose, 0, "Data from " + GetObjectName(obj) + "#" + Logging.HashString(obj) + "::" + method);
            int maxDumpSize = GetMaxDumpSizeSetting(traceSource);

            if (length > maxDumpSize)
            {
                PrintLine(traceSource, TraceEventType.Verbose, 0, "(printing " + maxDumpSize.ToString(NumberFormatInfo.InvariantInfo) + " out of " + length.ToString(NumberFormatInfo.InvariantInfo) + ")");
                length = maxDumpSize;
            }

            if ((length < 0) || (length > buffer.Length - offset))
            {
                length = buffer.Length - offset;
            }

            do
            {
                int    n    = Math.Min(length, 16);
                string disp = string.Format(CultureInfo.CurrentCulture, "{0:X8} : ", offset);
                for (int i = 0; i < n; ++i)
                {
                    disp += string.Format(CultureInfo.CurrentCulture, "{0:X2}", buffer[offset + i]) + ((i == 7) ? '-' : ' ');
                }

                for (int i = n; i < 16; ++i)
                {
                    disp += "   ";
                }

                disp += ": ";
                for (int i = 0; i < n; ++i)
                {
                    disp += ((buffer[offset + i] < 0x20) || (buffer[offset + i] > 0x7e))
                                ? '.'
                                : (char)(buffer[offset + i]);
                }

                PrintLine(traceSource, TraceEventType.Verbose, 0, disp);
                offset += n;
                length -= n;
            } while (length > 0);
        }
Пример #30
0
        private object WaitForCompletion(bool snap)
        {
            ManualResetEvent waitHandle  = null;
            bool             createdByMe = false;
            bool             complete    = snap ? IsCompleted : InternalPeekCompleted;

            if (!complete)
            {
                // Not done yet, so wait:
                waitHandle = (ManualResetEvent)_event;
                if (waitHandle == null)
                {
                    createdByMe = LazilyCreateEvent(out waitHandle);
                }
            }

            if (waitHandle != null)
            {
                try
                {
                    GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::InternalWaitForCompletion() Waiting for completion m_Event#" + Logging.HashString(waitHandle));
                    waitHandle.WaitOne(Timeout.Infinite);
                }
                catch (ObjectDisposedException)
                {
                    // This can occur if this method is called from two different threads.
                    // This possibility is the trade-off for not locking.
                }
                finally
                {
                    // We also want to dispose the event although we can't unless we did wait on it here.
                    if (createdByMe && !_userEvent)
                    {
                        // Does m_UserEvent need to be volatile (or m_Event set via Interlocked) in order
                        // to avoid giving a user a disposed event?
                        ManualResetEvent oldEvent = (ManualResetEvent)_event;
                        _event = null;
                        if (!_userEvent)
                        {
                            oldEvent.Dispose();
                        }
                    }
                }
            }

            // A race condition exists because InvokeCallback sets m_IntCompleted before m_Result (so that m_Result
            // can benefit from the synchronization of m_IntCompleted).  That means you can get here before m_Result got
            // set (although rarely - once every eight hours of stress).  Handle that case with a spin-lock.

            SpinWait sw = new SpinWait();

            while (_result == DBNull.Value)
            {
                sw.SpinOnce();
            }

            GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::InternalWaitForCompletion() done: " +
                            (_result is Exception ? ((Exception)_result).Message : _result == null ? "<null>" : _result.ToString()));

            return(_result);
        }