/// <summary>
        ///  The NetrLogonSamLogonWithFlags method Supported in windows_xpwindows_server_2003,
        ///  windows_vista, windows_server_2008, windows_7, and
        ///  windows_server_7. handles logon requests for the SAM
        ///  accounts. Opnum: 45 
        /// </summary>
        /// <param name="LogonServer">
        ///  The custom RPC binding handle, as specified in section
        ///  .
        /// </param>
        /// <param name="ComputerName">
        ///  The 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="LogonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, as specified
        ///  in section , that specifies the type of logon information
        ///  passed in the LogonInformation parameter.
        /// </param>
        /// <param name="LogonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, as specified
        ///  in section , that describes the logon request information.
        /// </param>
        /// <param name="ValidationLevel">
        ///  A NETLOGON_VALIDATION_INFO_CLASS enumerated type, as
        ///  specified in section , that contains the validation
        ///  level requested by the client.
        /// </param>
        /// <param name="ValidationInformation">
        ///  A pointer to a NETLOGON_VALIDATION structure, as specified
        ///  in section , that describes the user validation information
        ///  returned to the client. The type of the NETLOGON_VALIDATION
        ///  used is determined by the value of the ValidationLevel
        ///  parameter.
        /// </param>
        /// <param name="Authoritative">
        ///  A pointer to a char value representing a Boolean condition.
        ///  FALSE is indicated by the value 0x00; TRUE SHOULD be
        ///  indicated by the value 0x01 and MAY also be indicated
        ///  by any nonzero value. Windows uses the value of 0x01
        ///  as the representation of TRUE and 0x00 for FALSE. This
        ///  Boolean value indicates whether the validation information
        ///  is final. This field is necessary because the request
        ///  might be forwarded through multiple servers. A value
        ///  of TRUE indicates that the validation information is
        ///  final and MUST remain unchanged.
        /// </param>
        /// <param name="ExtraFlags">
        ///  A pointer to a set of bit flags that specify delivery
        ///  settings. A flag is TRUE (or set) if its value is equal
        ///  to 1. The value is constructed from zero or more bit
        ///  flags from the following table.
        /// </param>
        public NtStatus NetrLogonSamLogonWithFlags(
            string LogonServer,
            string ComputerName,
            _NETLOGON_AUTHENTICATOR? Authenticator,
            ref _NETLOGON_AUTHENTICATOR? ReturnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS LogonLevel,
            _NETLOGON_LEVEL? LogonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
            out _NETLOGON_VALIDATION? ValidationInformation,
            out byte? Authoritative,
            ref uint? ExtraFlags)
        {
            const ushort opnum = 45;

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

            SafeIntPtr pLogonServer = Marshal.StringToHGlobalUni(LogonServer);
            SafeIntPtr pComputerName = Marshal.StringToHGlobalUni(ComputerName);
            SafeIntPtr pAuthenticator = TypeMarshal.ToIntPtr(Authenticator);
            SafeIntPtr pReturnAuthenticatorIn = TypeMarshal.ToIntPtr(ReturnAuthenticator);
            SafeIntPtr pLogonInformation = TypeMarshal.ToIntPtr(LogonInformation, LogonLevel, null, null);
            SafeIntPtr pExtraFlags = TypeMarshal.ToIntPtr(ExtraFlags);

            paramList = new Int3264[] {
                pLogonServer,
                pComputerName,
                pAuthenticator,
                pReturnAuthenticatorIn,
                (uint)LogonLevel,
                pLogonInformation,
                (uint)ValidationLevel,
                IntPtr.Zero,
                IntPtr.Zero,
                pExtraFlags,
                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 pReturnAuthenticatorOut = outParamList[3];
                ReturnAuthenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(pReturnAuthenticatorOut);

                IntPtr pValidationInformation = outParamList[7];
                ValidationInformation = TypeMarshal.ToNullableStruct<_NETLOGON_VALIDATION>(
                    pValidationInformation,
                    ValidationLevel,
                    null,
                    null);

                Authoritative = TypeMarshal.ToNullableStruct<byte>(outParamList[8]);

                ExtraFlags = TypeMarshal.ToNullableStruct<uint>(outParamList[9]);

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

            pLogonServer.Dispose();
            pComputerName.Dispose();
            pAuthenticator.Dispose();
            pReturnAuthenticatorIn.Dispose();
            pLogonInformation.Dispose();
            pExtraFlags.Dispose();

            return (NtStatus)retVal;
        }
 /// <summary>
 ///  Decodes the request stub, and fills the fields of the class
 /// </summary>
 /// <param name="sessionContext">The session context of the request received</param>
 /// <param name="requestStub">The request stub got from RPCE layer</param>
 internal override void Decode(NrpcServerSessionContext sessionContext, byte[] requestStub)
 {
     using (RpceInt3264Collection outParamList = RpceStubDecoder.ToParamList(
       RpceStubHelper.GetPlatform(),
         NrpcRpcStubFormatString.TypeFormatString,
         new RpceStubExprEval[] {
             new RpceStubExprEval(NrpcRpcAdapter.logon__NETLOGON_DELTA_USERExprEval_0000) },
         NrpcRpcStubFormatString.ProcFormatString,
         NrpcRpcStubFormatString.ProcFormatStringOffsetTable[(int)Opnum],
         false,
         requestStub))
     {
         LogonServer = Marshal.PtrToStringUni(outParamList[0]);
         ComputerName = Marshal.PtrToStringUni(outParamList[1]);
         Authenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(outParamList[2]);
         ReturnAuthenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(outParamList[3]);
         LogonLevel = (_NETLOGON_LOGON_INFO_CLASS)outParamList[4].ToInt32();
         LogonInformation = TypeMarshal.ToNullableStruct<_NETLOGON_LEVEL>(outParamList[5], LogonLevel, null, null);
         ValidationLevel = (_NETLOGON_VALIDATION_INFO_CLASS)outParamList[6].ToInt32();
         ExtraFlags = TypeMarshal.ToNullableStruct<uint>(outParamList[9]);
     }
 }
        /// <summary>
        ///  The NetrLogonSamLogonWithFlags method Supported in windows_xpwindows_server_2003,
        ///  windows_vista, windows_server_2008, windows_7, and
        ///  windows_server_7. handles logon requests for the SAM
        ///  accounts. Opnum: 45 
        /// </summary>
        /// <param name="logonServer">
        ///  The custom RPC binding handle.
        /// </param>
        /// <param name="computerName">
        ///  The 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="logonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, 
        ///  that specifies the type of logon information
        ///  passed in the LogonInformation parameter.
        /// </param>
        /// <param name="logonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, 
        ///  that describes the logon request information.
        /// </param>
        /// <param name="validationLevel">
        ///  A NETLOGON_VALIDATION_INFO_CLASS enumerated type, 
        ///  that contains the validation
        ///  level requested by the client.
        /// </param>
        /// <param name="validationInformation">
        ///  A pointer to a NETLOGON_VALIDATION structure, 
        ///  that describes the user validation information
        ///  returned to the client. The type of the NETLOGON_VALIDATION
        ///  used is determined by the value of the ValidationLevel
        ///  parameter.
        /// </param>
        /// <param name="authoritative">
        ///  A pointer to a char value representing a Boolean condition.
        ///  FALSE is indicated by the value 0x00; TRUE SHOULD be
        ///  indicated by the value 0x01 and MAY also be indicated
        ///  by any nonzero value. Windows uses the value of 0x01
        ///  as the representation of TRUE and 0x00 for FALSE. This
        ///  Boolean value indicates whether the validation information
        ///  is final. This field is necessary because the request
        ///  might be forwarded through multiple servers. A value
        ///  of TRUE indicates that the validation information is
        ///  final and MUST remain unchanged.
        /// </param>
        /// <param name="extraFlags">
        ///  A pointer to a set of bit flags that specify delivery
        ///  settings. A flag is TRUE (or set) if its value is equal
        ///  to 1. The value is constructed from zero or more bit
        ///  flags from the following table.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogonWithFlags(
            string logonServer,
            string computerName,
            _NETLOGON_AUTHENTICATOR? authenticator,
            ref _NETLOGON_AUTHENTICATOR? returnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            out _NETLOGON_VALIDATION? validationInformation,
            out byte? authoritative,
            ref NrpcNetrLogonSamLogonExtraFlags? extraFlags)
        {
            uint? flags = (uint?)extraFlags;

            NtStatus status = rpc.NetrLogonSamLogonWithFlags(
                logonServer,
                computerName,
                authenticator,
                ref returnAuthenticator,
                logonLevel,
                logonInformation,
                validationLevel,
                out validationInformation,
                out authoritative,
                ref flags);

            context.ConnectionStatus = status;
            extraFlags = (NrpcNetrLogonSamLogonExtraFlags?)flags;
            return status;
        }
        /// <summary>
        ///  The NetrLogonSamLogonEx method Supported in windows_2000_server,
        ///  windows_xp, windows_server_2003, windows_vista, windows_server_2008,
        ///  windows_7, and windows_server_7. provides an extension
        ///  to NetrLogonSamLogon that accepts an extra flags parameter
        ///  and uses Secure RPC ([MS-RPCE]) instead of
        ///  Netlogon authenticators. This method handles logon
        ///  requests for the SAM accounts and allows for generic
        ///  pass-through authentication.
        ///  For more information about fields and structures
        ///  used by Netlogon pass-through methods.
        ///  Opnum: 39 
        /// </summary>
        /// <param name="contextHandle">
        ///  A primitive RPC handle that identifies a particular
        ///  client/server binding.
        /// </param>
        /// <param name="logonServer">
        ///  The null-terminated Unicode string that contains the
        ///  NetBIOS name of the server that will handle the logon
        ///  request.
        /// </param>
        /// <param name="computerName">
        ///  The null-terminated Unicode string that contains the
        ///  NetBIOS name of the client computer sending the logon
        ///  request.
        /// </param>
        /// <param name="logonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, 
        ///  that specifies the type of the logon information
        ///  passed in the LogonInformation parameter.
        /// </param>
        /// <param name="logonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, 
        ///  that describes the logon request information.
        /// </param>
        /// <param name="validationLevel">
        ///  A NETLOGON_VALIDATION_INFO_CLASS enumerated type, 
        ///  that contains the validation
        ///  level requested by the client.
        /// </param>
        /// <param name="validationInformation">
        ///  A pointer to a NETLOGON_VALIDATION structure, 
        ///  that describes the user validation information
        ///  returned to the client. The type of the NETLOGON_VALIDATION
        ///  used is determined by the value of the ValidationLevel
        ///  parameter.
        /// </param>
        /// <param name="authoritative">
        ///  A pointer to a char value that represents a Boolean
        ///  condition. FALSE is indicated by the value 0x00, and
        ///  TRUE SHOULDwindows uses the value 0x01 as the representation
        ///  of TRUE and 0x00 for FALSE. be indicated by the value
        ///  0x01 and MAY also be indicated by any nonzero value.
        ///  This Boolean value indicates whether the validation
        ///  information is final. This field is necessary because
        ///  the request might be forwarded through multiple servers.
        ///  The value TRUE indicates that the validation information
        ///  is final and MUST remain unchanged. The Authoritative
        ///  parameter indicates whether the response to this call
        ///  is final or if the same request can be sent to another
        ///  server. The value SHOULD be set to FALSE if the server
        ///  encounters a transient error, and the client can resend
        ///  the request to another server. If the same request
        ///  is known to fail in all subsequent requests, the server
        ///  SHOULD return TRUE.
        /// </param>
        /// <param name="extraFlags">
        ///  A pointer to a set of bit flags that specify delivery
        ///  settings. A flag is TRUE (or set) if its value is equal
        ///  to 1. Output flags MUST be the same as input. The value
        ///  is constructed from zero or more bit flags from the
        ///  following table.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogonEx(
            IntPtr contextHandle,
            string logonServer,
            string computerName,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            out _NETLOGON_VALIDATION? validationInformation,
            out byte? authoritative,
            ref NrpcNetrLogonSamLogonExtraFlags? extraFlags)
        {
            uint? flags = (uint?)extraFlags;

            NtStatus status = rpc.NetrLogonSamLogonEx(
                contextHandle,
                logonServer,
                computerName,
                logonLevel,
                logonInformation,
                validationLevel,
                out validationInformation,
                out authoritative,
                ref flags);

            context.ConnectionStatus = status;
            extraFlags = (NrpcNetrLogonSamLogonExtraFlags?)flags;
            return status;
        }
        /// <summary>
        ///  The NetrLogonSamLogon method This method was used in
        ///  windows_nt_4_0. It was superseded by the NetrLogonSamLogonWithFlags
        ///  method in windows_2000_server, windows_xp,
        ///  windows_server_2003, windows_vista, and windows_server_2008,
        ///  windows_7, and windows_server_7. is a predecessor to
        ///  the NetrLogonSamLogonWithFlags method. All
        ///  parameters of this method have the same meanings as
        ///  the identically named parameters of the NetrLogonSamLogonWithFlags
        ///  method. Opnum: 2 
        /// </summary>
        /// <param name="logonServer">
        ///  LogonServer parameter.
        /// </param>
        /// <param name="computerName">
        ///  ComputerName parameter.
        /// </param>
        /// <param name="authenticator">
        ///  Authenticator parameter.
        /// </param>
        /// <param name="returnAuthenticator">
        ///  ReturnAuthenticator parameter.
        /// </param>
        /// <param name="logonLevel">
        ///  LogonLevel parameter.
        /// </param>
        /// <param name="logonInformation">
        ///  LogonInformation parameter.
        /// </param>
        /// <param name="validationLevel">
        ///  ValidationLevel parameter.
        /// </param>
        /// <param name="validationInformation">
        ///  ValidationInformation parameter.
        /// </param>
        /// <param name="authoritative">
        ///  Authoritative parameter.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogon(
            string logonServer,
            string computerName,
            _NETLOGON_AUTHENTICATOR? authenticator,
            ref _NETLOGON_AUTHENTICATOR? returnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            out _NETLOGON_VALIDATION? validationInformation,
            out byte? authoritative)
        {
            NtStatus status = rpc.NetrLogonSamLogon(
                logonServer,
                computerName,
                authenticator,
                ref returnAuthenticator,
                logonLevel,
                logonInformation,
                validationLevel,
                out validationInformation,
                out authoritative);

            //ConnectionStatus: A 4-byte value that contains the most recent
            //connection status return value (section 3.4.5.3.1) last returned
            //during secure channel establishment or by a method requiring
            //session key establishment (section 3.1.4.6).
            context.ConnectionStatus = status;
            return status;
        }
        /// <summary>
        /// Decrypt a _NETLOGON_VALIDATION structure based on
        /// validationInformation parameter in Nrpc NetrlogonSamLogonXXX API.
        /// </summary>        
        /// <param name="validationInfoClass">
        /// Validation Info Class
        /// </param>
        /// <param name="validationInformation">
        /// Validation info returned from NetrlogonSamLogonXXX API
        /// </param>
        /// <returns>Decrypted _NETLOGON_VALIDATION data structure</returns>
        /// <exception cref="InvalidOperationException">
        /// Thrown when the method is called before establishing a NRPC secure channel.
        /// </exception>>
        ///  <exception cref="ArgumentException">
        /// Thrown when input invalid validationInformation argument
        /// </exception>>
        public _NETLOGON_VALIDATION DecryptNetlogonValidation(
            _NETLOGON_VALIDATION_INFO_CLASS validationInfoClass,
            _NETLOGON_VALIDATION validationInformation)
        {
            ValidateSecureChannelExists();

            switch (validationInfoClass)
            {
                case _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo:
                case _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2:
                    //If the LogonLevel is NetlogonGenericInformation,
                    //then encrypt<104> the LogonData member in the
                    //NETLOGON_GENERIC_INFO structure.
                    if (validationInformation.ValidationGeneric2 == null
                     || validationInformation.ValidationGeneric2.Length != 1)
                    {
                        throw new ArgumentException("validationInformation is invalid.", "validationInformation");
                    }

                    if (validationInformation.ValidationGeneric2[0].ValidationData == null)
                    {
                        throw new ArgumentException("validationInformation is invalid.", "validationInformation");
                    }

                    validationInformation.ValidationGeneric2[0].ValidationData = NrpcUtility.DecryptBuffer(
                        (context.NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2)
                        == NrpcNegotiateFlags.SupportsAESAndSHA2,
                        context.SessionKey,
                        validationInformation.ValidationGeneric2[0].ValidationData);
                    break;

                //If the LogonLevel is NetlogonNetworkInformation or
                //NetlogonNetworkTransitiveInformation, then encrypt the
                //UserSessionKey and the first two elements of the
                //ExpansionRoom array in the NETLOGON_VALIDATION_SAM_INFO
                //(section 2.2.1.4.11) or in the NETLOGON_VALIDATION_SAM_INFO2
                //(section 2.2.1.4.12) structure.
                case _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo:
                    if (validationInformation.ValidationSam == null
                    || validationInformation.ValidationSam.Length != 1)
                    {
                        throw new ArgumentException("validationInformation is invalid.", "validationInformation");
                    }
                    validationInformation.ValidationSam[0].UserSessionKey =
                        DecryptUserSessionKey(validationInformation.ValidationSam[0].UserSessionKey);
                    validationInformation.ValidationSam[0].ExpansionRoom =
                        DecryptExpansionRoom(validationInformation.ValidationSam[0].ExpansionRoom);
                    break;

                case _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2:
                    if (validationInformation.ValidationSam2 == null
                    || validationInformation.ValidationSam2.Length != 1)
                    {
                        throw new ArgumentException("validationInformation is invalid.", "validationInformation");
                    }
                    validationInformation.ValidationSam2[0].UserSessionKey =
                        DecryptUserSessionKey(validationInformation.ValidationSam2[0].UserSessionKey);
                    validationInformation.ValidationSam2[0].ExpansionRoom =
                        DecryptExpansionRoom(validationInformation.ValidationSam2[0].ExpansionRoom);
                    break;

                case _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4:
                case _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationUasInfo:
                    // no encrypted field
                    break;

                default:
                    throw new ArgumentException("validationInfoClass is invalid.", "validationInfoClass");
            }

            return validationInformation;
        }