package smb2

import 

// ----------------------------------------------------------------------------
// SMB2 Error Response
//

type ErrorResponse struct {
	PacketHeader

	ErrorData Encoder // ErrorContextListResponse | (SymbolicLinkErrorResponse | SmallBufferErrorResponse)
}

func ( *ErrorResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *ErrorResponse) () int {
	if .ErrorData == nil {
		return 64 + 8 + 1
	}
	return 64 + 8 + .ErrorData.Size()
}

// it doesn't handle Command property, set it yourself
func ( *ErrorResponse) ( []byte) {
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 9) // StructureSize
	if .ErrorData != nil {
		le.PutUint16([2:4], uint16(.ErrorData.Size()))
		.ErrorData.Encode([8:])

		if ,  := .ErrorData.(ErrorContextListResponse);  {
			[2] = uint8(len())
		}
	}
}

type ErrorResponseDecoder []byte

func ( ErrorResponseDecoder) () bool {
	if len() < 8 {
		return true
	}

	if .StructureSize() != 9 {
		return true
	}

	if uint32(len()) < 8+.ByteCount() {
		return true
	}

	return false
}

func ( ErrorResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( ErrorResponseDecoder) () uint8 {
	return [2]
}

func ( ErrorResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( ErrorResponseDecoder) () []byte {
	return [8 : 8+.ByteCount()]
}

// ----------------------------------------------------------------------------
// SMB2 Error Context Response
//

// for SMB311

type ErrorContextListResponse []*ErrorContextResponse

func ( ErrorContextListResponse) () int {
	 := 0
	for ,  := range  {
		 = Roundup(, 8)
		 += .Size()
	}
	return 
}

func ( ErrorContextListResponse) ( []byte) {
	 := 0
	for ,  := range  {
		 = Roundup(, 8)

		.Encode([:])

		 += .Size()
	}
}

type ErrorContextResponse struct {
	ErrorId uint32

	ErrorData Encoder
}

func ( *ErrorContextResponse) () int {
	return 8 + .ErrorData.Size()
}

func ( *ErrorContextResponse) ( []byte) {
	le.PutUint32([:4], uint32(.ErrorData.Size()))
	le.PutUint32([4:8], .ErrorId)
	if .ErrorData != nil {
		.ErrorData.Encode([8:])
	}
}

type ErrorContextResponseDecoder []byte

func ( ErrorContextResponseDecoder) () bool {
	if len() < 8 {
		return true
	}

	if uint32(len()) < 8+.ErrorDataLength() {
		return true
	}

	return false
}

func ( ErrorContextResponseDecoder) () uint32 {
	return le.Uint32([:4])
}

func ( ErrorContextResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( ErrorContextResponseDecoder) () []byte {
	return [8 : 8+.ErrorDataLength()]
}

func ( ErrorContextResponseDecoder) () int {
	return 8 + Roundup(int(.ErrorDataLength()), 8)
}

// ----------------------------------------------------------------------------
// SMB2 ErrorData formats
//

type SmallBufferErrorResponse struct {
	RequiredBufferLength uint32
}

func ( *SmallBufferErrorResponse) () int {
	return 4
}

func ( *SmallBufferErrorResponse) ( []byte) {
	le.PutUint32([:4], .RequiredBufferLength)
}

type SmallBufferErrorResponseDecoder []byte

func ( SmallBufferErrorResponseDecoder) () bool {
	return len() != 4
}

func ( SmallBufferErrorResponseDecoder) () uint32 {
	return le.Uint32()
}

type SymbolicLinkErrorResponse struct {
	UnparsedPathLength uint16
	Flags              uint32
	SubstituteName     string
	PrintName          string
}

func ( *SymbolicLinkErrorResponse) () int {
	return 28 + utf16le.EncodedStringLen(.SubstituteName) + utf16le.EncodedStringLen(.PrintName)
}

func ( *SymbolicLinkErrorResponse) ( []byte) {
	 := utf16le.EncodeString([24:], .SubstituteName)
	 := utf16le.EncodeString([24+:], .PrintName)

	le.PutUint32([:4], uint32(len()-4)) // SymLinkLength
	le.PutUint32([4:8], 0x4c4d5953)
	le.PutUint32([8:12], IO_REPARSE_TAG_SYMLINK)
	le.PutUint16([14:16], .UnparsedPathLength)
	le.PutUint32([24:28], .Flags)
	le.PutUint16([12:14], uint16(len()-12)) // ReparseDataLength
	le.PutUint16([16:18], 0)                 // SubstituteNameOffset
	le.PutUint16([18:20], uint16())      // SubstituteNameLength
	le.PutUint16([20:22], uint16())      // PrintNameOffset
	le.PutUint16([22:24], uint16())      // PrintNameLength
}

type SymbolicLinkErrorResponseDecoder []byte

func ( SymbolicLinkErrorResponseDecoder) () bool {
	if len() < 28 {
		return true
	}

	if .SymLinkErrorTag() != 0x4c4d5953 {
		return true
	}

	if .ReparseTag() != IO_REPARSE_TAG_SYMLINK {
		return true
	}

	 := int(.SymLinkLength())
	 := int(.ReparseDataLength())
	 := int(.SubstituteNameOffset())
	 := int(.SubstituteNameLength())
	 := int(.PrintNameOffset())
	 := int(.PrintNameLength())

	if (&1 | &1) != 0 {
		return true
	}

	if len() < 4+ {
		return true
	}

	if  < 12+ {
		return true
	}

	if  < 12++ ||  < 12++ {
		return true
	}

	return false
}

func ( SymbolicLinkErrorResponseDecoder) () uint32 {
	return le.Uint32([:4])
}

func ( SymbolicLinkErrorResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( SymbolicLinkErrorResponseDecoder) () uint32 {
	return le.Uint32([8:12])
}

func ( SymbolicLinkErrorResponseDecoder) () uint16 {
	return le.Uint16([12:14])
}

func ( SymbolicLinkErrorResponseDecoder) () uint16 {
	return le.Uint16([14:16])
}

func ( SymbolicLinkErrorResponseDecoder) () uint16 {
	return le.Uint16([16:18])
}

func ( SymbolicLinkErrorResponseDecoder) () uint16 {
	return le.Uint16([18:20])
}

func ( SymbolicLinkErrorResponseDecoder) () uint16 {
	return le.Uint16([20:22])
}

func ( SymbolicLinkErrorResponseDecoder) () uint16 {
	return le.Uint16([22:24])
}

func ( SymbolicLinkErrorResponseDecoder) () uint32 {
	return le.Uint32([24:28])
}

func ( SymbolicLinkErrorResponseDecoder) () []byte {
	return [28:]
}

func ( SymbolicLinkErrorResponseDecoder) () string {
	 := .SubstituteNameOffset()
	 := .SubstituteNameLength()
	return utf16le.DecodeToString(.PathBuffer()[ : +])
}

func ( SymbolicLinkErrorResponseDecoder) () string {
	 := .PrintNameOffset()
	 := .PrintNameLength()
	return utf16le.DecodeToString(.PathBuffer()[ : +])
}

func ( SymbolicLinkErrorResponseDecoder) ( string) (string, string) {
	 := UTF16FromString()
	 := int(.UnparsedPathLength())
	if /2 > len() {
		return "", ""
	}

	return UTF16ToString([:len()-/2]), UTF16ToString([len()-/2:])
}

// ----------------------------------------------------------------------------
// SMB2 NEGOTIATE Response
//

type NegotiateResponse struct {
	PacketHeader

	SecurityMode    uint16
	DialectRevision uint16
	ServerGuid      [16]byte
	Capabilities    uint32
	MaxTransactSize uint32
	MaxReadSize     uint32
	MaxWriteSize    uint32
	SystemTime      *Filetime
	ServerStartTime *Filetime
	SecurityBuffer  []byte

	Contexts []Encoder
}

func ( *NegotiateResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *NegotiateResponse) () int {
	 := 64 + len(.SecurityBuffer)

	for ,  := range .Contexts {
		 = Roundup(, 8)

		 += .Size()
	}

	if  == 64 {
		return 64 + 64 + 1
	}

	return 64 + 
}

func ( *NegotiateResponse) ( []byte) {
	.Command = SMB2_NEGOTIATE
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 65) // StructureSize
	le.PutUint16([2:4], .SecurityMode)
	le.PutUint16([4:6], .DialectRevision)
	copy([8:24], .ServerGuid[:])
	le.PutUint32([24:28], .Capabilities)
	le.PutUint32([28:32], .MaxTransactSize)
	le.PutUint32([32:36], .MaxReadSize)
	le.PutUint32([36:40], .MaxWriteSize)
	.SystemTime.Encode([40:48])
	.ServerStartTime.Encode([48:56])

	// SecurityBuffer
	{
		copy([64:], .SecurityBuffer)
		le.PutUint16([56:58], 64+64)                         // SecurityBufferOffset
		le.PutUint16([58:60], uint16(len(.SecurityBuffer))) // SecurityBufferLength
	}

	 := 64 + len(.SecurityBuffer)

	for ,  := range .Contexts {
		 = Roundup(, 8)

		if  == 0 {
			le.PutUint32([60:64], uint32(+64)) // NegotiateContextOffset
		}

		.Encode([:])

		 += .Size()
	}

	le.PutUint16([6:8], uint16(len(.Contexts))) // NegotiateContextCount
}

type NegotiateResponseDecoder []byte

func ( NegotiateResponseDecoder) () bool {
	if len() < 64 {
		return true
	}

	if .StructureSize() != 65 {
		return true
	}

	if len() < int(.SecurityBufferOffset()+.SecurityBufferLength())-64 {
		return true
	}

	if .DialectRevision() == SMB311 {
		 := .NegotiateContextOffset()

		if &7 != 0 {
			return true
		}

		if len() < int()-64 {
			return true
		}
	}

	return false
}

func ( NegotiateResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( NegotiateResponseDecoder) () uint16 {
	return le.Uint16([2:4])
}

func ( NegotiateResponseDecoder) () uint16 {
	return le.Uint16([4:6])
}

func ( NegotiateResponseDecoder) () []byte {
	return [8:24]
}

func ( NegotiateResponseDecoder) () uint32 {
	return le.Uint32([24:28])
}

func ( NegotiateResponseDecoder) () uint32 {
	return le.Uint32([28:32])
}

func ( NegotiateResponseDecoder) () uint32 {
	return le.Uint32([32:36])
}

func ( NegotiateResponseDecoder) () uint32 {
	return le.Uint32([36:40])
}

func ( NegotiateResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([40:48])
}

func ( NegotiateResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([48:56])
}

func ( NegotiateResponseDecoder) () uint16 {
	return le.Uint16([56:58])
}

func ( NegotiateResponseDecoder) () uint16 {
	return le.Uint16([58:60])
}

// func (r NegotiateResponseDecoder) Buffer() []byte {
// return r[64:]
// }

func ( NegotiateResponseDecoder) () []byte {
	 := .SecurityBufferOffset()
	if  < 64+64 {
		return nil
	}
	 -= 64
	 := .SecurityBufferLength()
	return [ : +]
}

// From SMB311

func ( NegotiateResponseDecoder) () uint16 {
	return le.Uint16([6:8])
}

func ( NegotiateResponseDecoder) () uint32 {
	return le.Uint32([60:64])
}

func ( NegotiateResponseDecoder) () []byte {
	 := .NegotiateContextOffset()
	if  < 64 {
		return nil
	}
	return [-64:]
}

// ----------------------------------------------------------------------------
// SMB2 SESSION_SETUP Response
//

type SessionSetupResponse struct {
	PacketHeader

	SessionFlags   uint16
	SecurityBuffer []byte
}

func ( *SessionSetupResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *SessionSetupResponse) () int {
	if len(.SecurityBuffer) == 0 {
		return 64 + 8 + 1
	}

	return 64 + 8 + len(.SecurityBuffer)
}

func ( *SessionSetupResponse) ( []byte) {
	.Command = SMB2_SESSION_SETUP
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 9) // StructureSize
	le.PutUint16([2:4], .SessionFlags)

	if len(.SecurityBuffer) != 0 {
		le.PutUint16([4:6], 8+64) // SecurityBufferOffset

		copy([8:], .SecurityBuffer)

		le.PutUint16([6:8], uint16(len(.SecurityBuffer)))
	}
}

type SessionSetupResponseDecoder []byte

func ( SessionSetupResponseDecoder) () bool {
	if len() < 8 {
		return true
	}

	if .StructureSize() != 9 {
		return true
	}

	if len() < int(.SecurityBufferOffset()+.SecurityBufferLength())-64 {
		return true
	}

	return false
}

func ( SessionSetupResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( SessionSetupResponseDecoder) () uint16 {
	return le.Uint16([2:4])
}

func ( SessionSetupResponseDecoder) () uint16 {
	return le.Uint16([4:6])
}

func ( SessionSetupResponseDecoder) () uint16 {
	return le.Uint16([6:8])
}

// func (req SessionSetupResponseDecoder) Buffer() []byte {
// return req[8:]
// }

func ( SessionSetupResponseDecoder) () []byte {
	 := .SecurityBufferOffset()
	if  < 8+64 {
		return nil
	}
	 -= 64
	 := .SecurityBufferLength()
	return [ : +]
}

// ----------------------------------------------------------------------------
// SMB2 LOGOFF Response
//

type LogoffResponse struct {
	PacketHeader
}

func ( *LogoffResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *LogoffResponse) () int {
	return 64 + 4
}

func ( *LogoffResponse) ( []byte) {
	.Command = SMB2_LOGOFF
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 4) // StructureSize
}

type LogoffResponseDecoder []byte

func ( LogoffResponseDecoder) () bool {
	if len() < 4 {
		return true
	}

	if .StructureSize() != 4 {
		return true
	}

	return false
}

func ( LogoffResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

// ----------------------------------------------------------------------------
// SMB2 TREE_CONNECT Response
//

type TreeConnectResponse struct {
	PacketHeader

	ShareType     uint8
	ShareFlags    uint32
	Capabilities  uint32
	MaximalAccess uint32
}

func ( *TreeConnectResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *TreeConnectResponse) () int {
	return 64 + 16
}

func ( *TreeConnectResponse) ( []byte) {
	.Command = SMB2_TREE_CONNECT
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 16) // StructureSize
	[2] = .ShareType
	le.PutUint32([4:8], .ShareFlags)
	le.PutUint32([8:12], .Capabilities)
	le.PutUint32([12:16], .MaximalAccess)
}

type TreeConnectResponseDecoder []byte

func ( TreeConnectResponseDecoder) () bool {
	if len() < 16 {
		return true
	}

	if .StructureSize() != 16 {
		return true
	}

	return false
}

func ( TreeConnectResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( TreeConnectResponseDecoder) () uint8 {
	return [2]
}

func ( TreeConnectResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( TreeConnectResponseDecoder) () uint32 {
	return le.Uint32([8:12])
}

func ( TreeConnectResponseDecoder) () uint32 {
	return le.Uint32([12:16])
}

// ----------------------------------------------------------------------------
// SMB2 TREE_DISCONNECT Response
//

type TreeDisconnectResponse struct {
	PacketHeader
}

func ( *TreeDisconnectResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *TreeDisconnectResponse) () int {
	return 4
}

func ( *TreeDisconnectResponse) ( []byte) {
	.Command = SMB2_TREE_DISCONNECT
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 4) // StructureSize
}

type TreeDisconnectResponseDecoder []byte

func ( TreeDisconnectResponseDecoder) () bool {
	if len() < 4 {
		return true
	}

	if .StructureSize() != 4 {
		return true
	}

	return false
}

func ( TreeDisconnectResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

// ----------------------------------------------------------------------------
// SMB2 CREATE Response
//

type CreateResponse struct {
	PacketHeader

	OplockLevel    uint8
	Flags          uint8
	CreateAction   uint32
	CreationTime   *Filetime
	LastAccessTime *Filetime
	LastWriteTime  *Filetime
	ChangeTime     *Filetime
	AllocationSize int64
	EndofFile      int64
	FileAttributes uint32
	FileId         *FileId

	Contexts []Encoder
}

func ( *CreateResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *CreateResponse) () int {
	if len(.Contexts) == 0 {
		return 64 + 88 + 1
	}

	 := 64 + 88

	for ,  := range .Contexts {
		 = Roundup(, 8)
		 += .Size()
	}

	return 
}

func ( *CreateResponse) ( []byte) {
	.Command = SMB2_CREATE
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 89) // StructureSize
	[2] = .OplockLevel
	[3] = .Flags
	le.PutUint32([4:8], .CreateAction)
	.CreationTime.Encode([8:16])
	.LastAccessTime.Encode([16:24])
	.LastWriteTime.Encode([24:32])
	.ChangeTime.Encode([32:40])
	le.PutUint64([40:48], uint64(.AllocationSize))
	le.PutUint64([48:56], uint64(.EndofFile))
	le.PutUint32([56:60], .FileAttributes)
	.FileId.Encode([64:80])

	 := 88

	var  []byte
	var  int

	for ,  := range .Contexts {
		 = Roundup(, 8)

		if  == 0 {
			le.PutUint32([80:84], uint32(64+)) // CreateContextsOffset
		} else {
			le.PutUint32([:4], uint32()) // Next
		}

		 = [:]

		.Encode()

		 = .Size()

		 += 
	}

	le.PutUint32([84:88], uint32(-88)) // CreateContextsLength
}

type CreateResponseDecoder []byte

func ( CreateResponseDecoder) () bool {
	if len() < 88 {
		return true
	}

	if .StructureSize() != 89 {
		return true
	}

	 := .CreateContextsOffset()

	if &7 != 0 {
		return true
	}

	if len() < int(+.CreateContextsLength())-64 {
		return true
	}

	return false
}

func ( CreateResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( CreateResponseDecoder) () uint8 {
	return [2]
}

func ( CreateResponseDecoder) () uint8 {
	return [3]
}

func ( CreateResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( CreateResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([8:16])
}

func ( CreateResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([16:24])
}

func ( CreateResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([24:32])
}

func ( CreateResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([32:40])
}

func ( CreateResponseDecoder) () int64 {
	return int64(le.Uint64([40:48]))
}

func ( CreateResponseDecoder) () int64 {
	return int64(le.Uint64([48:56]))
}

func ( CreateResponseDecoder) () uint32 {
	return le.Uint32([56:60])
}

func ( CreateResponseDecoder) () FileIdDecoder {
	return FileIdDecoder([64:80])
}

func ( CreateResponseDecoder) () uint32 {
	return le.Uint32([80:84])
}

func ( CreateResponseDecoder) () uint32 {
	return le.Uint32([84:88])
}

// func (r CreateResponseDecoder) Buffer() []byte {
// return r[88:]
// }

func ( CreateResponseDecoder) () []byte {
	 := .CreateContextsOffset()
	if  < 88+64 {
		return nil
	}
	 -= 64
	 := .CreateContextsLength()
	return [ : +]
}

// ----------------------------------------------------------------------------
// SMB2 CLOSE Response
//

type CloseResponse struct {
	PacketHeader

	Flags          uint16
	CreationTime   *Filetime
	LastAccessTime *Filetime
	LastWriteTime  *Filetime
	ChangeTime     *Filetime
	AllocationSize int64
	EndofFile      int64
	FileAttributes uint32
}

func ( *CloseResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *CloseResponse) () int {
	return 64 + 60
}

func ( *CloseResponse) ( []byte) {
	.Command = SMB2_CLOSE
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 60) // StructureSize
	le.PutUint16([2:4], .Flags)
	.CreationTime.Encode([8:16])
	.LastAccessTime.Encode([16:24])
	.LastWriteTime.Encode([24:32])
	.ChangeTime.Encode([32:40])
	le.PutUint64([40:48], uint64(.AllocationSize))
	le.PutUint64([48:56], uint64(.EndofFile))
	le.PutUint32([56:60], .FileAttributes)
}

type CloseResponseDecoder []byte

func ( CloseResponseDecoder) () bool {
	if len() < 60 {
		return true
	}

	if .StructureSize() != 60 {
		return true
	}

	return false
}

func ( CloseResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( CloseResponseDecoder) () uint16 {
	return le.Uint16([2:4])
}

func ( CloseResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([8:16])
}

func ( CloseResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([16:24])
}

func ( CloseResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([24:32])
}

func ( CloseResponseDecoder) () FiletimeDecoder {
	return FiletimeDecoder([32:40])
}

func ( CloseResponseDecoder) () int64 {
	return int64(le.Uint64([40:48]))
}

func ( CloseResponseDecoder) () int64 {
	return int64(le.Uint64([48:56]))
}

func ( CloseResponseDecoder) () uint32 {
	return le.Uint32([56:60])
}

// ----------------------------------------------------------------------------
// SMB2 FLUSH Response
//

type FlushResponse struct {
	PacketHeader
}

func ( *FlushResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *FlushResponse) () int {
	return 64 + 4
}

func ( *FlushResponse) ( []byte) {
	.Command = SMB2_FLUSH
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 4) // StructureSize
}

type FlushResponseDecoder []byte

func ( FlushResponseDecoder) () bool {
	if len() < 4 {
		return true
	}

	if .StructureSize() != 4 {
		return true
	}

	return false
}

func ( FlushResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

// ----------------------------------------------------------------------------
// SMB2 READ Response
//

type ReadResponse struct {
	PacketHeader

	Data          []byte
	DataRemaining uint32
}

func ( *ReadResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *ReadResponse) () int {
	if len(.Data) == 0 {
		return 64 + 16 + 1
	}
	return 64 + 16 + len(.Data)
}

func ( *ReadResponse) ( []byte) {
	.Command = SMB2_READ
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 17) // StructureSize
	[2] = 16               // DataOffset
	copy([16:], .Data)
	le.PutUint32([4:8], uint32(len(.Data))) // DataLength
	le.PutUint32([8:12], .DataRemaining)
}

type ReadResponseDecoder []byte

func ( ReadResponseDecoder) () bool {
	if len() < 16 {
		return true
	}

	if .StructureSize() != 17 {
		return true
	}

	if len() < int(uint32(.DataOffset())+.DataLength())-64 {
		return true
	}

	return false
}

func ( ReadResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( ReadResponseDecoder) () uint8 {
	return [2]
}

func ( ReadResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( ReadResponseDecoder) () uint32 {
	return le.Uint32([8:12])
}

// func (r ReadResponseDecoder) Buffer() []byte {
// return r[16:]
// }

func ( ReadResponseDecoder) () []byte {
	 := .DataOffset()
	if  < 16+64 {
		return nil
	}
	 -= 64
	 := .DataLength()
	return [ : uint32()+]
}

// ----------------------------------------------------------------------------
// SMB2 WRITE Response
//

type WriteResponse struct {
	PacketHeader

	Count     uint32
	Remaining uint32
}

func ( *WriteResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *WriteResponse) () int {
	return 64 + 16 + 1
}

func ( *WriteResponse) ( []byte) {
	.Command = SMB2_WRITE
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 17) // StructureSize
	le.PutUint32([4:8], .Count)
	le.PutUint32([8:12], .Remaining)
}

type WriteResponseDecoder []byte

func ( WriteResponseDecoder) () bool {
	if len() < 16 {
		return true
	}

	if .StructureSize() != 17 {
		return true
	}

	return false
}

func ( WriteResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( WriteResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( WriteResponseDecoder) () uint32 {
	return le.Uint32([8:12])
}

func ( WriteResponseDecoder) () uint16 {
	return le.Uint16([12:14])
}

func ( WriteResponseDecoder) () uint16 {
	return le.Uint16([14:16])
}

// ----------------------------------------------------------------------------
// SMB2 OPLOCK_BREAK Notification and Response
//

// ----------------------------------------------------------------------------
// SMB2 LOCK Response
//

// ----------------------------------------------------------------------------
// SMB2 ECHO Response
//

// ----------------------------------------------------------------------------
// SMB2 IOCTL Response
//

type IoctlResponse struct {
	PacketHeader

	CtlCode uint32
	FileId  *FileId
	Flags   uint32
	Input   Encoder
	Output  Encoder
}

func ( *IoctlResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *IoctlResponse) () int {
	if .Input == nil && .Output == nil {
		return 64 + 48 + 1
	}
	return 64 + 48 + .Input.Size() + .Output.Size()
}

func ( *IoctlResponse) ( []byte) {
	.Command = SMB2_IOCTL
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 49) // StructureSize
	le.PutUint32([4:8], .CtlCode)
	.FileId.Encode([8:24])
	le.PutUint32([40:44], .Flags)

	 := 48

	if .Input != nil {
		le.PutUint32([24:28], uint32(+64)) // InputOffset

		.Input.Encode([:])

		le.PutUint32([28:32], uint32(.Input.Size())) // InputCount
	}

	if .Output != nil {
		le.PutUint32([32:36], uint32(+64)) // InputOffset

		.Output.Encode([:])

		le.PutUint32([36:40], uint32(.Output.Size())) // InputCount
	}
}

type IoctlResponseDecoder []byte

func ( IoctlResponseDecoder) () bool {
	if len() < 48 {
		return true
	}

	if .StructureSize() != 49 {
		return true
	}

	if len() < int(.InputOffset()+.InputCount())-64 {
		return true
	}

	if len() < int(.OutputOffset()+.OutputCount())-64 {
		return true
	}

	return false
}

func ( IoctlResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( IoctlResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

func ( IoctlResponseDecoder) () FileIdDecoder {
	return FileIdDecoder([8:24])
}

func ( IoctlResponseDecoder) () uint32 {
	return le.Uint32([24:28])
}

func ( IoctlResponseDecoder) () uint32 {
	return le.Uint32([28:32])
}

func ( IoctlResponseDecoder) () uint32 {
	return le.Uint32([32:36])
}

func ( IoctlResponseDecoder) () uint32 {
	return le.Uint32([36:40])
}

func ( IoctlResponseDecoder) () uint32 {
	return le.Uint32([40:44])
}

// func (r IoctlResponseDecoder) Buffer() []byte {
// return r[48:]
// }

func ( IoctlResponseDecoder) () []byte {
	 := .InputOffset()
	if  < 64+48 {
		return nil
	}
	 -= 64
	 := .InputCount()
	return [ : +]
}

func ( IoctlResponseDecoder) () []byte {
	 := .OutputOffset()
	if  < 64+48 {
		return nil
	}
	 -= 64
	 := .OutputCount()
	return [ : +]
}

// ----------------------------------------------------------------------------
// SMB2 QUERY_DIRECTORY Response
//

type QueryDirectoryResponse struct {
	PacketHeader

	Output Encoder
}

func ( *QueryDirectoryResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *QueryDirectoryResponse) () int {
	if .Output == nil {
		return 64 + 8 + 1
	}
	return 64 + 8 + .Output.Size()
}

func ( *QueryDirectoryResponse) ( []byte) {
	.Command = SMB2_QUERY_DIRECTORY
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 9) // StructureSize

	 := 8

	if .Output != nil {
		le.PutUint16([2:4], uint16(+64))
		.Output.Encode([8:])
		le.PutUint32([4:8], uint32(.Output.Size()))
	}
}

type QueryDirectoryResponseDecoder []byte

func ( QueryDirectoryResponseDecoder) () bool {
	if len() < 8 {
		return true
	}

	if .StructureSize() != 9 {
		return true
	}

	if len() < int(uint32(.OutputBufferOffset())+.OutputBufferLength())-64 {
		return true
	}

	return false
}

func ( QueryDirectoryResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( QueryDirectoryResponseDecoder) () uint16 {
	return le.Uint16([2:4])
}

func ( QueryDirectoryResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

// func (r QueryDirectoryResponseDecoder) Buffer() []byte {
// return r[8:]
// }

func ( QueryDirectoryResponseDecoder) () []byte {
	 := .OutputBufferOffset()
	if  < 64+8 {
		return nil
	}
	 -= 64
	 := .OutputBufferLength()
	return [ : uint32()+]
}

// ----------------------------------------------------------------------------
// SMB2 CHANGE_NOTIFY Response
//

// ----------------------------------------------------------------------------
// SMB2 QUERY_INFO Response
//

type QueryInfoResponse struct {
	PacketHeader

	Output Encoder
}

func ( *QueryInfoResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *QueryInfoResponse) () int {
	if .Output == nil {
		return 64 + 8 + 1
	}
	return 64 + 8 + .Output.Size()
}

func ( *QueryInfoResponse) ( []byte) {
	.Command = SMB2_QUERY_INFO
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 9) // StructureSize

	 := 8

	if .Output != nil {
		le.PutUint16([2:4], uint16(+64))
		.Output.Encode([8:])
		le.PutUint32([4:8], uint32(.Output.Size()))
	}
}

type QueryInfoResponseDecoder []byte

func ( QueryInfoResponseDecoder) () bool {
	if len() < 8 {
		return true
	}

	if .StructureSize() != 9 {
		return true
	}

	if len() < int(uint32(.OutputBufferOffset())+.OutputBufferLength())-64 {
		return true
	}

	return false
}

func ( QueryInfoResponseDecoder) () uint16 {
	return le.Uint16([:2])
}

func ( QueryInfoResponseDecoder) () uint16 {
	return le.Uint16([2:4])
}

func ( QueryInfoResponseDecoder) () uint32 {
	return le.Uint32([4:8])
}

// func (r QueryInfoResponseDecoder) Buffer() []byte {
// return r[8:]
// }

func ( QueryInfoResponseDecoder) () []byte {
	 := .OutputBufferOffset()
	if  < 64+8 {
		return nil
	}
	 -= 64
	 := .OutputBufferLength()
	return [ : uint32()+]
}

// ----------------------------------------------------------------------------
// SMB2 SET_INFO Response
//

type SetInfoResponse struct {
	PacketHeader
}

func ( *SetInfoResponse) () *PacketHeader {
	return &.PacketHeader
}

func ( *SetInfoResponse) () int {
	return 64 + 2
}

func ( *SetInfoResponse) ( []byte) {
	.Command = SMB2_SET_INFO
	.encodeHeader()

	 := [64:]
	le.PutUint16([:2], 2) // StructureSize
}

type SetInfoResponseDecoder []byte

func ( SetInfoResponseDecoder) () bool {
	if len() < 2 {
		return true
	}

	if .StructureSize() != 2 {
		return true
	}

	return false
}

func ( SetInfoResponseDecoder) () uint16 {
	return le.Uint16([:2])
}