/// <summary>
        /// Constructor
        /// </summary>
        /// <param name="negotiationInfo">NegotiationInfo defined by SSPI</param>
        internal SecurityPackageContextNegotiationInfo(SspiSecurityPackageContextNegotiationInfo negotiationInfo)
        {
            SspiSecurityPackageInformation sspiNegotiationInfo;

            sspiNegotiationInfo = (SspiSecurityPackageInformation)Marshal.PtrToStructure(
                negotiationInfo.PackageInfo,
                typeof(SspiSecurityPackageInformation));
            this.PackageInfo      = new SecurityPackageInformation(sspiNegotiationInfo);
            this.NegotiationState = negotiationInfo.NegotiationState;
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="negotiationInfo">NegotiationInfo defined by SSPI</param>
        internal SecurityPackageContextNegotiationInfo(SspiSecurityPackageContextNegotiationInfo negotiationInfo)
        {
            SspiSecurityPackageInformation sspiNegotiationInfo;

            sspiNegotiationInfo = (SspiSecurityPackageInformation)Marshal.PtrToStructure(
                negotiationInfo.PackageInfo,
                typeof(SspiSecurityPackageInformation));
            this.PackageInfo = new SecurityPackageInformation(sspiNegotiationInfo);
            this.NegotiationState = negotiationInfo.NegotiationState;
        }
        internal static object QueryContextAttributes(ref SecurityHandle contextHandle, string contextAttribute)
        {
            uint attribute = 0;
            IntPtr pBuffer = IntPtr.Zero;
            string stringAttribute = contextAttribute.ToUpper(CultureInfo.InvariantCulture);

            switch (stringAttribute)
            {
                case SECPKG_ATTR_SIZES:
                    attribute = NativeMethods.SECPKG_ATTR_SIZES;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextSizes)));
                    break;
                case SECPKG_ATTR_LIFESPAN:
                    attribute = NativeMethods.SECPKG_ATTR_LIFESPAN;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextLifespan)));
                    break;
                case SECPKG_ATTR_STREAM_SIZES:
                    attribute = NativeMethods.SECPKG_ATTR_STREAM_SIZES;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextStreamSizes)));
                    break;
                case SECPKG_ATTR_KEY_INFO:
                    attribute = NativeMethods.SECPKG_ATTR_KEY_INFO;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SspiSecurityPackageContextKeyInfo)));
                    break;
                case SECPKG_ATTR_AUTHORITY:
                    attribute = NativeMethods.SECPKG_ATTR_AUTHORITY;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextAuthority)));
                    break;
                case SECPKG_ATTR_PASSWORD_EXPIRY:
                    attribute = NativeMethods.SECPKG_ATTR_PASSWORD_EXPIRY;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityInteger)));
                    break;
                case SECPKG_ATTR_SESSION_KEY:
                    attribute = NativeMethods.SECPKG_ATTR_SESSION_KEY;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextSessionKey)));
                    break;
                case SECPKG_ATTR_PACKAGE_INFO:
                    attribute = NativeMethods.SECPKG_ATTR_PACKAGE_INFO;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                    break;
                case SECPKG_ATTR_NEGOTIATION_INFO:
                    attribute = NativeMethods.SECPKG_ATTR_NEGOTIATION_INFO;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SspiSecurityPackageContextNegotiationInfo)));
                    break;
                case SECPKG_ATTR_NATIVE_NAMES:
                    attribute = NativeMethods.SECPKG_ATTR_NATIVE_NAMES;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SspiSecurityPackageContextNativeNames)));
                    break;
                case SECPKG_ATTR_FLAGS:
                    attribute = NativeMethods.SECPKG_ATTR_FLAGS;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)));
                    break;
                case SECPKG_ATTR_TARGET_INFORMATION:
                    attribute = NativeMethods.SECPKG_ATTR_TARGET_INFORMATION;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextTargetInformation)));
                    break;
                case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
                    attribute = NativeMethods.SECPKG_ATTR_REMOTE_CERT_CONTEXT;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                    break;
                case SECPKG_ATTR_LOCAL_CERT_CONTEXT:
                    attribute = NativeMethods.SECPKG_ATTR_LOCAL_CERT_CONTEXT;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                    break;
                case SECPKG_ATTR_ROOT_STORE:
                    attribute = NativeMethods.SECPKG_ATTR_ROOT_STORE;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                    break;
                case SECPKG_ATTR_ISSUER_LIST_EX:
                    attribute = NativeMethods.SECPKG_ATTR_ISSUER_LIST_EX;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SspiSecurityPackageContextIssuerListInfo)));
                    break;
                case SECPKG_ATTR_CONNECTION_INFO:
                    attribute = NativeMethods.SECPKG_ATTR_CONNECTION_INFO;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextConnectionInfo)));
                    break;
                case SECPKG_ATTR_EAP_KEY_BLOCK:
                    attribute = NativeMethods.SECPKG_ATTR_EAP_KEY_BLOCK;
                    pBuffer = Marshal.AllocHGlobal(SchannelKeySize + SchannelIvSize);
                    break;
                case SECPKG_ATTR_APP_DATA:
                    attribute = NativeMethods.SECPKG_ATTR_APP_DATA;
                    pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityPackageContextSessionAppData)));
                    break;
                default:
                    throw new ArgumentException("Error context attribute name.", "contextAttribute");
            }

            uint hResult = NativeMethods.QueryContextAttributes(ref contextHandle, attribute, pBuffer);
            if (hResult == NativeMethods.SEC_E_OK)
            {
                object attributeValue;
                switch (stringAttribute)
                {
                    case SECPKG_ATTR_SIZES:
                        attributeValue = Marshal.PtrToStructure(pBuffer, typeof(SecurityPackageContextSizes));
                        break;
                    case SECPKG_ATTR_LIFESPAN:
                        attributeValue = Marshal.PtrToStructure(pBuffer, typeof(SecurityPackageContextLifespan));
                        break;
                    case SECPKG_ATTR_STREAM_SIZES:
                        attributeValue = Marshal.PtrToStructure(pBuffer, typeof(SecurityPackageContextStreamSizes));
                        break;
                    case SECPKG_ATTR_KEY_INFO:
                        SspiSecurityPackageContextKeyInfo keyInfo;

                        keyInfo = (SspiSecurityPackageContextKeyInfo)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SspiSecurityPackageContextKeyInfo));
                        attributeValue = new SecurityPackageContextKeyInfo(keyInfo);
                        Marshal.FreeHGlobal(keyInfo.sSignatureAlgorithmName);
                        Marshal.FreeHGlobal(keyInfo.sEncryptAlgorithmName);
                        break;
                    case SECPKG_ATTR_AUTHORITY:
                        SecurityPackageContextAuthority authority;

                        authority = (SecurityPackageContextAuthority)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SecurityPackageContextAuthority));
                        attributeValue = Marshal.PtrToStringUni(authority.sAuthorityName);
                        break;
                    case SECPKG_ATTR_PASSWORD_EXPIRY:
                        attributeValue = Marshal.PtrToStructure(pBuffer, typeof(SecurityInteger));
                        break;
                    case SECPKG_ATTR_SESSION_KEY:
                        SecurityPackageContextSessionKey sessionKey;

                        sessionKey = (SecurityPackageContextSessionKey)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SecurityPackageContextSessionKey));
                        attributeValue = sessionKey.GetSessionKey();
                        Marshal.FreeHGlobal(sessionKey.SessionKey);
                        break;
                    case SECPKG_ATTR_PACKAGE_INFO:
                        SspiSecurityPackageInformation packageInfo;

                        packageInfo = (SspiSecurityPackageInformation)Marshal.PtrToStructure(
                            Marshal.ReadIntPtr(pBuffer),
                            typeof(SspiSecurityPackageInformation));
                        attributeValue = new SecurityPackageInformation(packageInfo);
                        break;
                    case SECPKG_ATTR_NEGOTIATION_INFO:
                        SspiSecurityPackageContextNegotiationInfo negotiationInfo;

                        negotiationInfo = (SspiSecurityPackageContextNegotiationInfo)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SspiSecurityPackageContextNegotiationInfo));
                        attributeValue = new SecurityPackageContextNegotiationInfo(negotiationInfo);
                        Marshal.FreeHGlobal(negotiationInfo.PackageInfo);
                        break;
                    case SECPKG_ATTR_NATIVE_NAMES:
                        SspiSecurityPackageContextNativeNames nativeNames;

                        nativeNames = (SspiSecurityPackageContextNativeNames)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SspiSecurityPackageContextNativeNames));
                        attributeValue = new SecurityPackageContextNativeNames(nativeNames);
                        break;
                    case SECPKG_ATTR_FLAGS:
                        attributeValue = (uint)Marshal.ReadInt32(pBuffer);
                        break;
                    case SECPKG_ATTR_TARGET_INFORMATION:
                        SecurityPackageContextTargetInformation targetInformation;

                        targetInformation = (SecurityPackageContextTargetInformation)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SecurityPackageContextTargetInformation));
                        attributeValue = targetInformation.GetTargetInfo();
                        Marshal.FreeHGlobal(targetInformation.MarshalledTargetInfo);
                        break;
                    case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
                        SspiCertContext remoteCertContext;

                        remoteCertContext = (SspiCertContext)Marshal.PtrToStructure(
                            Marshal.ReadIntPtr(pBuffer),
                            typeof(SspiCertContext));
                        attributeValue = new CertContext(remoteCertContext);
                        Marshal.FreeHGlobal(remoteCertContext.pbCertEncoded);
                        break;
                    case SECPKG_ATTR_LOCAL_CERT_CONTEXT:
                        SspiCertContext localCertContext;

                        localCertContext = (SspiCertContext)Marshal.PtrToStructure(
                            Marshal.ReadIntPtr(pBuffer),
                            typeof(SspiCertContext));
                        attributeValue = new CertContext(localCertContext);
                        Marshal.FreeHGlobal(localCertContext.pbCertEncoded);
                        break;
                    case SECPKG_ATTR_ROOT_STORE:
                        attributeValue = Marshal.ReadIntPtr(pBuffer);
                        break;
                    case SECPKG_ATTR_ISSUER_LIST_EX:
                        SspiSecurityPackageContextIssuerListInfo issuerList;

                        issuerList = (SspiSecurityPackageContextIssuerListInfo)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SspiSecurityPackageContextIssuerListInfo));
                        attributeValue = new SecurityPackageContextIssuerListInfo(issuerList);
                        NativeMethods.FreeContextBuffer(issuerList.aIssuers);
                        break;
                    case SECPKG_ATTR_CONNECTION_INFO:
                        SecurityPackageContextConnectionInfo connectionInfo;

                        connectionInfo = (SecurityPackageContextConnectionInfo)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SecurityPackageContextConnectionInfo));
                        attributeValue = connectionInfo;
                        break;
                    case SECPKG_ATTR_EAP_KEY_BLOCK:
                        SecurityPackageContextEapKeyBlock eapKeyBlock = new SecurityPackageContextEapKeyBlock();

                        eapKeyBlock.rgbKeys = new byte[SchannelKeySize];
                        Marshal.Copy(pBuffer, eapKeyBlock.rgbKeys, 0, SchannelKeySize);
                        eapKeyBlock.rgbIVs = new byte[SchannelIvSize];
                        Marshal.Copy(new IntPtr(pBuffer.ToInt64() + SchannelKeySize),
                            eapKeyBlock.rgbIVs,
                            0,
                            SchannelIvSize);
                        attributeValue = eapKeyBlock;
                        break;
                    case SECPKG_ATTR_APP_DATA:
                        SecurityPackageContextSessionAppData sessionAppData;

                        sessionAppData = (SecurityPackageContextSessionAppData)Marshal.PtrToStructure(
                            pBuffer,
                            typeof(SecurityPackageContextSessionAppData));
                        attributeValue = sessionAppData.GetAppData();
                        Marshal.FreeHGlobal(sessionAppData.pbAppData);
                        break;
                    default:
                        throw new ArgumentException("Error context attribute name.", "contextAttribute");
                }
                Marshal.FreeHGlobal(pBuffer);

                return attributeValue;
            }
            else
            {
                Marshal.FreeHGlobal(pBuffer);
                throw new SspiException("QueryContextAttributes failed.", hResult);
            }
        }