/// <summary>
        /// A continuation Windows Security Context.
        /// </summary>
        /// <param name="init">
        /// Initial context that contains a handle to the credentials returned by
        /// AcquireCredentialsHandle. This handle is used to build the security context.
        /// </param>
        /// <param name="continueToken">
        /// Token returned by the remote computer.
        /// </param>
        /// <param name="fContextReq">
        /// Bit flags that indicate requests for the context. Not all packages can support all requirements.
        /// Flags used for this parameter are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE.
        /// </param>
        /// <param name="targetDataRep">
        /// </param>
        public WindowsSecurityContext(WindowsSecurityContext init, byte[] continueToken, int fContextReq, int targetDataRep)
        {
            _securityPackage = init._securityPackage;
            Secur32.SecBufferDesc continueTokenBuffer = new Secur32.SecBufferDesc(continueToken);
            _token = new Secur32.SecBufferDesc(Secur32.MAX_TOKEN_SIZE);

            int rc = Secur32.InitializeSecurityContext(
                ref init._credentials,
                ref init._context,
                init._username,
                fContextReq,
                0,
                targetDataRep,
                ref continueTokenBuffer,
                0,
                ref _context,
                ref _token,
                out _contextAttributes,
                out _contextLifetime);

            switch (rc)
            {
            case Secur32.SEC_E_OK:
                break;

            case Secur32.SEC_I_CONTINUE_NEEDED:
                _continue = true;
                break;

            default:
                throw new Win32Exception(rc);
            }
        }
        /// <summary>
        /// A continuation Windows Security Context.
        /// </summary>
        /// <param name="init">
        /// Initial context that contains a handle to the credentials returned by
        /// AcquireCredentialsHandle. This handle is used to build the security context.
        /// </param>
        /// <param name="continueToken">
        /// Token returned by the remote computer.
        /// </param>
        /// <param name="fContextReq">
        /// Bit flags that indicate requests for the context. Not all packages can support all requirements.
        /// Flags used for this parameter are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE.
        /// </param>
        /// <param name="targetDataRep">
        /// </param>
        public WindowsSecurityContext(WindowsSecurityContext init, byte[] continueToken, int fContextReq, int targetDataRep)
        {
            _targetName      = init._targetName;
            _credentials     = init._credentials;
            _securityPackage = init._securityPackage;

            using (var continueTokenBuffer = new Secur32.SecBufferDesc(continueToken))
            {
                Initialize(_credentials, _targetName, fContextReq, targetDataRep, init._context, continueTokenBuffer);
            }
        }
        /// <summary>
        /// A continuation Windows Security Context.
        /// </summary>
        /// <param name="init">
        /// Initial context that contains a handle to the credentials returned by 
        /// AcquireCredentialsHandle. This handle is used to build the security context. 
        /// </param>
        /// <param name="continueToken">
        /// Token returned by the remote computer.
        /// </param>
        /// <param name="fContextReq">
        /// Bit flags that indicate requests for the context. Not all packages can support all requirements. 
        /// Flags used for this parameter are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE.
        /// </param>
        /// <param name="targetDataRep">
        /// </param>
        public WindowsSecurityContext(WindowsSecurityContext init, byte[] continueToken, int fContextReq, int targetDataRep)
        {
            _securityPackage = init._securityPackage;
            Secur32.SecBufferDesc continueTokenBuffer = new Secur32.SecBufferDesc(continueToken);
            _token = new Secur32.SecBufferDesc(Secur32.MAX_TOKEN_SIZE);

            int rc = Secur32.InitializeSecurityContext(
                ref init._credentials,
                ref init._context,
                init._username,
                fContextReq,
                0,
                targetDataRep,
                ref continueTokenBuffer,
                0,
                ref _context,
                ref _token,
                out _contextAttributes,
                out _contextLifetime);

            switch (rc)
            {
                case Secur32.SEC_E_OK:
                    break;
                case Secur32.SEC_I_CONTINUE_NEEDED:
                    _continue = true;
                    break;
                default:
                    throw new Win32Exception(rc);
            }
        }
        /// <summary>
        /// A continuation Windows Security Context.
        /// </summary>
        /// <param name="init">
        /// Initial context that contains a handle to the credentials returned by 
        /// AcquireCredentialsHandle. This handle is used to build the security context. 
        /// </param>
        /// <param name="continueToken">
        /// Token returned by the remote computer.
        /// </param>
        /// <param name="fContextReq">
        /// Bit flags that indicate requests for the context. Not all packages can support all requirements. 
        /// Flags used for this parameter are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE.
        /// </param>
        /// <param name="targetDataRep">
        /// </param>
        public WindowsSecurityContext(WindowsSecurityContext init, byte[] continueToken, int fContextReq, int targetDataRep)
        {
            _targetName = init._targetName;
            _credentials = init._credentials;
            _securityPackage = init._securityPackage;

            using (var continueTokenBuffer = new Secur32.SecBufferDesc(continueToken))
            {
                Initialize(_credentials, _targetName, fContextReq, targetDataRep, init._context, continueTokenBuffer);
            }
        }
        public void TestNegotiate()
        {
            string package = "Negotiate";
            WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
            WindowsSecurityContext initContext = WindowsSecurityContext.GetCurrent(package,
                WindowsIdentity.GetCurrent().Name, Secur32.ISC_REQ_CONNECTION, Secur32.SECURITY_NATIVE_DREP);
            IWindowsSecurityContext continueContext = initContext;
            IWindowsSecurityContext responseContext = null;
            string connectionId = Guid.NewGuid().ToString();
            do
            {
                responseContext = provider.AcceptSecurityToken(connectionId, continueContext.Token, package,
                    Secur32.ISC_REQ_CONNECTION, Secur32.SECURITY_NATIVE_DREP);
                if (responseContext.Token != null)
                {
                    Console.WriteLine("  Token: {0}", Convert.ToBase64String(responseContext.Token));
                    Console.WriteLine("  Continue: {0}", responseContext.Continue);
                }
                continueContext = new WindowsSecurityContext(initContext, responseContext.Token,
                    Secur32.ISC_REQ_CONNECTION, Secur32.SECURITY_NATIVE_DREP);
            } while (responseContext.Continue);

            Assert.IsFalse(responseContext.Continue);
            Console.WriteLine(responseContext.Identity.Fqn);
        }