/// <summary>
        ///  The NetrServerPasswordSet method sets a new one-way
        ///  function (OWF) of a password for an account used by
        ///  the domain controller (as detailed in section) for
        ///  setting up the secure channel from the client. Opnum
        ///  : 6 
        /// </summary>
        /// <param name="PrimaryName">
        ///  The custom RPC binding handle, as specified in section
        ///  .
        /// </param>
        /// <param name="AccountName">
        ///  The null-terminated Unicode string that contains the
        ///  name of the account whose password is being changed. In
        ///  windows, all machine account names are the name of
        ///  the machine with a $ (dollar sign) appended.
        /// </param>
        /// <param name="SecureChannelType">
        ///  An enumerated value (specified in section) that indicates
        ///  the type of secure channel used by the client.
        /// </param>
        /// <param name="ComputerName">
        ///  A null-terminated Unicode string that contains the NetBIOS
        ///  name of the client computer calling this method.
        /// </param>
        /// <param name="Authenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, as
        ///  specified in section , that contains the client authenticator.
        /// </param>
        /// <param name="ReturnAuthenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, as
        ///  specified in section , that contains the server return
        ///  authenticator.
        /// </param>
        /// <param name="UasNewPassword">
        ///  A pointer to an ENCRYPTED_LM_OWF_PASSWORD structure,
        ///  as specified in section  and encrypted by the algorithm
        ///  specified in section.
        /// </param>
        public NtStatus NetrServerPasswordSet(
            string PrimaryName,
            string AccountName,
            _NETLOGON_SECURE_CHANNEL_TYPE SecureChannelType,
            string ComputerName,
            _NETLOGON_AUTHENTICATOR? Authenticator,
            out _NETLOGON_AUTHENTICATOR? ReturnAuthenticator,
            _LM_OWF_PASSWORD? UasNewPassword)
        {
            const ushort opnum = 6;

            byte[] requestStub;
            byte[] responseStub;
            Int3264[] paramList;
            int retVal;

            SafeIntPtr pPrimaryName = Marshal.StringToHGlobalUni(PrimaryName);
            SafeIntPtr pAccountName = Marshal.StringToHGlobalUni(AccountName);
            SafeIntPtr pComputerName = Marshal.StringToHGlobalUni(ComputerName);
            SafeIntPtr pAuthenticator = TypeMarshal.ToIntPtr(Authenticator);
            SafeIntPtr pUasNewPassword = TypeMarshal.ToIntPtr(UasNewPassword);

            paramList = new Int3264[] {
                pPrimaryName,
                pAccountName,
                (uint)SecureChannelType,
                pComputerName,
                pAuthenticator,
                IntPtr.Zero,
                pUasNewPassword,
                0 // retVal
            };

            requestStub = RpceStubEncoder.ToBytes(
                     RpceStubHelper.GetPlatform(),
                    NrpcRpcStubFormatString.TypeFormatString,
                    new RpceStubExprEval[] { new RpceStubExprEval(logon__NETLOGON_DELTA_USERExprEval_0000) },
                    NrpcRpcStubFormatString.ProcFormatString,
                    NrpcRpcStubFormatString.ProcFormatStringOffsetTable[opnum],
                    true,
                    paramList);

            rpceClientTransport.Call(opnum, requestStub, rpceTimeout, out responseStub);

            using (RpceInt3264Collection outParamList = RpceStubDecoder.ToParamList(
                     RpceStubHelper.GetPlatform(),
                    NrpcRpcStubFormatString.TypeFormatString,
                    new RpceStubExprEval[] { new RpceStubExprEval(logon__NETLOGON_DELTA_USERExprEval_0000) },
                    NrpcRpcStubFormatString.ProcFormatString,
                    NrpcRpcStubFormatString.ProcFormatStringOffsetTable[opnum],
                    true,
                    responseStub,
                    paramList))
            {
                IntPtr pReturnAuthenticator = outParamList[5];
                ReturnAuthenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(pReturnAuthenticator);

                retVal = outParamList[7].ToInt32();
            }

            pPrimaryName.Dispose();
            pAccountName.Dispose();
            pComputerName.Dispose();
            pAuthenticator.Dispose();
            pUasNewPassword.Dispose();

            return (NtStatus)retVal;
        }
        /// <summary>
        ///  The NetrServerPasswordSet method sets a new one-way
        ///  function (OWF) of a password for an account used by
        ///  the domain controller for
        ///  setting up the secure channel from the client. Opnum: 6 
        /// </summary>
        /// <param name="primaryName">
        ///  The custom RPC binding handle.
        /// </param>
        /// <param name="accountName">
        ///  The null-terminated Unicode string that contains the
        ///  name of the account whose password is being changed. In
        ///  windows, all machine account names are the name of
        ///  the machine with a $ (dollar sign) appended.
        /// </param>
        /// <param name="secureChannelType">
        ///  An enumerated value that indicates
        ///  the type of secure channel used by the client.
        /// </param>
        /// <param name="computerName">
        ///  A null-terminated Unicode string that contains the NetBIOS
        ///  name of the client computer calling this method.
        /// </param>
        /// <param name="authenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, 
        ///  that contains the client authenticator.
        /// </param>
        /// <param name="returnAuthenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, 
        ///  that contains the server return
        ///  authenticator.
        /// </param>
        /// <param name="uasNewPassword">
        ///  A pointer to an ENCRYPTED_LM_OWF_PASSWORD structure,
        ///  and encrypted.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrServerPasswordSet(
            string primaryName,
            string accountName,
            _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType,
            string computerName,
            _NETLOGON_AUTHENTICATOR? authenticator,
            out _NETLOGON_AUTHENTICATOR? returnAuthenticator,
            _LM_OWF_PASSWORD? uasNewPassword)
        {
            NtStatus status = rpc.NetrServerPasswordSet(
                primaryName,
                accountName,
                secureChannelType,
                computerName,
                authenticator,
                out returnAuthenticator,
                uasNewPassword);

            context.ConnectionStatus = status;
            return status;
        }
        /// <summary>
        /// Encrypt LM_OWF_PASSWORD and NT_OWF_PASSWORD by RC4 and session key.
        /// </summary>
        /// <param name="lmOwfPassword">LM_OWF_PASSWORD</param>
        /// <param name="ntOwfPassword">NT_OWF_PASSWORD</param>
        /// <exception cref="InvalidOperationException">
        /// Thrown when the method is called before establishing a NRPC secure channel.<para/>
        /// Thrown when neither AES nore RC4 is negotiated.
        /// </exception>
        private void EncryptLmAndNtOwfPassword(
            ref _LM_OWF_PASSWORD lmOwfPassword,
            ref _NT_OWF_PASSWORD ntOwfPassword)
        {
            if (lmOwfPassword.data == null || lmOwfPassword.data.Length != 2)
            {
                throw new ArgumentException("lmOwfPassword is invalid", "lmOwfPassword");
            }
            if (ntOwfPassword.data == null || ntOwfPassword.data.Length != 2)
            {
                throw new ArgumentException("ntOwfPassword is invalid", "ntOwfPassword");
            }
            ValidateSecureChannelExists();

            //For all versions of Windows except Windows NT 3.1,
            //encrypt by using RC4 and the session key.
            byte[] lmOwf = ArrayUtility.ConcatenateArrays(
                lmOwfPassword.data[0].data,
                lmOwfPassword.data[1].data);
            byte[] ntOwf = ArrayUtility.ConcatenateArrays(
                ntOwfPassword.data[0].data,
                ntOwfPassword.data[1].data);

            bool isAesNegotiated = IsAesOrRc4Negotiated();

            lmOwf = NrpcUtility.EncryptBuffer(isAesNegotiated, context.SessionKey, lmOwf);
            ntOwf = NrpcUtility.EncryptBuffer(isAesNegotiated, context.SessionKey, ntOwf);

            lmOwfPassword.data = NrpcUtility.CreateCypherBlocks(lmOwf);
            ntOwfPassword.data = NrpcUtility.CreateCypherBlocks(ntOwf);
        }
        /// <summary>
        /// Encrypt password before calling NetrServerPasswordSet.
        /// </summary>
        /// <param name="password">
        /// The password to be encrypted.
        /// </param>
        /// <returns>
        /// A LM_OWF_PASSWORD struct with encrypted password.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when password is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when SAMR failed to encrypt password.
        /// Thrown when the method is called before establishing a NRPC secure channel.
        /// </exception>
        public _LM_OWF_PASSWORD EncryptUasNewPassword(string password)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            ValidateSecureChannelExists();

            //Compute the NTOWFv1 ([MS-NLMP] section 3.3.1) of the new password.
            byte[] ntOwfV1 = NlmpUtility.NtOWF(NlmpVersion.v1, null, null, password);

            //Encrypt ([MS-SAMR] section 2.2.11.1.1) the result of step 1 using
            //the Session-Key for the secure channel as the Specified Key.
            _ENCRYPTED_LM_OWF_PASSWORD samrEncryptedLmOwfPassword
                    = SamrCryptography.EncryptBlockWithKey(ntOwfV1, context.SessionKey);

            if (samrEncryptedLmOwfPassword.data == null
                && samrEncryptedLmOwfPassword.data.Length != NrpcUtility.OWF_PASSWORD_LENGTH)
            {
                throw new InvalidOperationException("SAMR failed to encrypt LM_OWF_PASSWORD.");
            }

            _LM_OWF_PASSWORD encryptedLmOwfPassword = new _LM_OWF_PASSWORD();
            encryptedLmOwfPassword.data = NrpcUtility.CreateCypherBlocks(samrEncryptedLmOwfPassword.data);
            return encryptedLmOwfPassword;
        }