package smb2

import 

// ----------------------------------------------------------------------------
// SMB2 NEGOTIATE Request Packet
//

type NegotiateRequest struct {
	PacketHeader

	SecurityMode uint16
	Capabilities uint32
	ClientGuid   [16]byte
	Dialects     []uint16

	Contexts []Encoder
}

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

func ( *NegotiateRequest) () int {
	 := 36 + len(.Dialects)*2

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

		 += .Size()
	}

	return 64 + 
}

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

	 := [64:]
	le.PutUint16([:2], 36) // StructureSize
	le.PutUint16([4:6], .SecurityMode)
	le.PutUint32([8:12], .Capabilities)
	copy([12:28], .ClientGuid[:])

	{
		 := [36:]
		for ,  := range .Dialects {
			le.PutUint16([2*:2*+2], )
		}
		le.PutUint16([2:4], uint16(len(.Dialects)))
	}

	 := 36 + len(.Dialects)*2

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

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

		.Encode([:])

		 += .Size()
	}

	le.PutUint16([32:34], uint16(len(.Contexts))) // NegotiateContextCount
}

type NegotiateRequestDecoder []byte

func ( NegotiateRequestDecoder) () bool {
	if len() < 36 {
		return true
	}

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

	 := .NegotiateContextOffset()

	if &7 != 0 {
		return true
	}

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

	return false
}

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

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

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

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

func ( NegotiateRequestDecoder) () []byte {
	return [12:28]
}

func ( NegotiateRequestDecoder) () []byte {
	return [28:36]
}

func ( NegotiateRequestDecoder) () []uint16 {
	 := [36 : 36+2*.DialectCount()]
	 := make([]uint16, len()/2)
	for  := range  {
		[] = le.Uint16([2* : 2*+2])
	}
	return 
}

// From SMB311

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

func ( NegotiateRequestDecoder) () uint16 {
	return le.Uint16([32:34])
}

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

// ----------------------------------------------------------------------------
// SMB2 SESSION_SETUP Request Packet
//

type SessionSetupRequest struct {
	PacketHeader

	Flags             uint8
	SecurityMode      uint8
	Capabilities      uint32
	Channel           uint32
	SecurityBuffer    []byte
	PreviousSessionId uint64
}

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

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

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

	 := [64:]
	le.PutUint16([:2], 25)
	[2] = .Flags
	[3] = .SecurityMode
	le.PutUint32([4:8], .Capabilities)
	le.PutUint32([8:12], .Channel)
	le.PutUint64([16:24], .PreviousSessionId)

	// SecurityBuffer
	{
		copy([24:], .SecurityBuffer)
		le.PutUint16([12:14], 64+24)                         // SecurityBufferOffset
		le.PutUint16([14:16], uint16(len(.SecurityBuffer))) // SecurityBufferLength
	}
}

type SessionSetupRequestDecoder []byte

func ( SessionSetupRequestDecoder) () bool {
	if len() < 24 {
		return true
	}

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

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

	return false
}

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

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

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

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

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

func ( SessionSetupRequestDecoder) () uint64 {
	return le.Uint64([16:24])
}

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

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

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

// ----------------------------------------------------------------------------
// SMB2 LOGOFF Request Packet
//

type LogoffRequest struct {
	PacketHeader
}

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

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

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

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

type LogoffRequestDecoder []byte

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

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

	return false
}

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

// ----------------------------------------------------------------------------
// SMB2 TREE_CONNECT Request Packet
//

type TreeConnectRequest struct {
	PacketHeader

	Flags uint16
	Path  string
}

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

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

	return 64 + 8 + utf16le.EncodedStringLen(.Path)
}

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

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

	// Path
	{
		 := utf16le.EncodeString([8:], .Path)

		le.PutUint16([4:6], 8+64)         // PathOffset
		le.PutUint16([6:8], uint16()) // PathLength
	}
}

type TreeConnectRequestDecoder []byte

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

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

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

	return false
}

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

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

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

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

func ( TreeConnectRequestDecoder) () string {
	 := .PathOffset()
	if  < 64+8 {
		return ""
	}
	 -= 64
	 := .PathLength()
	return utf16le.DecodeToString([ : +])
}

// ----------------------------------------------------------------------------
// SMB2 TREE_DISCONNECT Request Packet
//

type TreeDisconnectRequest struct {
	PacketHeader
}

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

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

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

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

type TreeDisconnectRequestDecoder []byte

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

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

	return false
}

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

// ----------------------------------------------------------------------------
// SMB2 CREATE Request Packet
//

type CreateRequest struct {
	PacketHeader

	SecurityFlags        uint8
	RequestedOplockLevel uint8
	ImpersonationLevel   uint32
	SmbCreateFlags       uint64
	DesiredAccess        uint32
	FileAttributes       uint32
	ShareAccess          uint32
	CreateDisposition    uint32
	CreateOptions        uint32
	Name                 string

	Contexts []Encoder
}

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

func ( *CreateRequest) () int {
	if len(.Name) == 0 && len(.Contexts) == 0 {
		return 64 + 56 + 1
	}

	 := 64 + 56 + utf16le.EncodedStringLen(.Name)

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

	return 
}

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

	 := [64:]
	le.PutUint16([:2], 57) // StructureSize
	[2] = .SecurityFlags
	[3] = .RequestedOplockLevel
	le.PutUint32([4:8], .ImpersonationLevel)
	le.PutUint64([8:16], .SmbCreateFlags)
	le.PutUint32([24:28], .DesiredAccess)
	le.PutUint32([28:32], .FileAttributes)
	le.PutUint32([32:36], .ShareAccess)
	le.PutUint32([36:40], .CreateDisposition)
	le.PutUint32([40:44], .CreateOptions)

	// Name
	 := utf16le.EncodeString([56:], .Name)

	le.PutUint16([44:46], 56+64)
	le.PutUint16([46:48], uint16())

	 := 56 + 

	var  []byte
	var  int

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

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

		 = [:]

		.Encode()

		 = .Size()

		 += 
	}

	le.PutUint32([52:56], uint32(-(56+))) // CreateContextsLength
}

type CreateRequestDecoder []byte

func ( CreateRequestDecoder) () bool {
	if len() < 56 {
		return true
	}

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

	 := .NameOffset()

	if &7 != 0 {
		return true
	}

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

	 := .CreateContextsOffset()

	if &7 != 0 {
		return true
	}

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

	return false
}

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

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

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

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

func ( CreateRequestDecoder) () uint64 {
	return le.Uint64([8:16])
}

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

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

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

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

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

func ( CreateRequestDecoder) () uint16 {
	return le.Uint16([44:46])
}

func ( CreateRequestDecoder) () uint16 {
	return le.Uint16([46:48])
}

func ( CreateRequestDecoder) () uint32 {
	return le.Uint32([48:52])
}

func ( CreateRequestDecoder) () uint32 {
	return le.Uint32([52:56])
}

// ----------------------------------------------------------------------------
// SMB2 CLOSE Request Packet
//

type CloseRequest struct {
	PacketHeader

	Flags  uint16
	FileId *FileId
}

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

func ( *CloseRequest) () int {
	return 64 + 24
}

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

	 := [64:]
	le.PutUint16([:2], 24) // StructureSize
	le.PutUint16([2:4], .Flags)
	.FileId.Encode([8:24])
}

type CloseRequestDecoder []byte

func ( CloseRequestDecoder) () bool {
	if len() < 24 {
		return true
	}

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

	return false
}

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

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

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

// ----------------------------------------------------------------------------
// SMB2 FLUSH Request Packet
//

type FlushRequest struct {
	PacketHeader

	FileId *FileId
}

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

func ( *FlushRequest) () int {
	return 64 + 24
}

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

	 := [64:]
	le.PutUint16([:2], 24) // StructureSize
	.FileId.Encode([8:24])
}

type FlushRequestDecoder []byte

func ( FlushRequestDecoder) () bool {
	if len() < 24 {
		return true
	}

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

	return false
}

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

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

// ----------------------------------------------------------------------------
// SMB2 READ Request Packet
//

type ReadRequest struct {
	PacketHeader

	Padding         uint8
	Flags           uint8
	Length          uint32
	Offset          uint64
	FileId          *FileId
	MinimumCount    uint32
	Channel         uint32
	RemainingBytes  uint32
	ReadChannelInfo []Encoder
}

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

func ( *ReadRequest) () int {
	if len(.ReadChannelInfo) == 0 {
		return 64 + 48 + 1
	}

	 := 64 + 48
	for ,  := range .ReadChannelInfo {
		 += .Size()
	}
	return 
}

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

	 := [64:]
	le.PutUint16([:2], 49)
	[2] = .Padding
	[3] = .Flags
	le.PutUint32([4:8], .Length)
	le.PutUint64([8:16], .Offset)
	.FileId.Encode([16:32])
	le.PutUint32([32:36], .MinimumCount)
	le.PutUint32([36:40], .Channel)
	le.PutUint32([40:44], .RemainingBytes)

	 := 48

	for ,  := range .ReadChannelInfo {
		if  == 0 {
			le.PutUint16([44:46], uint16(64+)) // ReadChannelInfoOffset
		}

		.Encode([:])

		 += .Size()
	}

	le.PutUint16([46:48], uint16(-48)) // ReadChannelInfoLength
}

type ReadRequestDecoder []byte

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

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

	if len() < int(.ReadChannelInfoOffset()+.ReadChannelInfoLength()) {
		return true
	}

	return false
}

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

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

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

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

func ( ReadRequestDecoder) () uint64 {
	return le.Uint64([8:16])
}

func ( ReadRequestDecoder) () FileIdDecoder {
	return FileIdDecoder([16:32])
}

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

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

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

func ( ReadRequestDecoder) () uint16 {
	return le.Uint16([44:46])
}

func ( ReadRequestDecoder) () uint16 {
	return le.Uint16([46:48])
}

// ----------------------------------------------------------------------------
// SMB2 WRITE Request Packet
//

type WriteRequest struct {
	PacketHeader

	FileId           *FileId
	Flags            uint32
	Channel          uint32
	RemainingBytes   uint32
	Offset           uint64
	WriteChannelInfo []Encoder
	Data             []byte
}

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

func ( *WriteRequest) () int {
	if len(.Data) == 0 && len(.WriteChannelInfo) == 0 {
		return 64 + 48 + 1
	}

	 := 64 + 48

	for ,  := range .WriteChannelInfo {
		 += .Size()
	}

	 += len(.Data)

	return 
}

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

	 := [64:]
	le.PutUint16([:2], 49) // StructureSize
	le.PutUint64([8:16], .Offset)
	.FileId.Encode([16:32])
	le.PutUint32([32:36], .Channel)
	le.PutUint32([36:40], .RemainingBytes)
	le.PutUint32([44:48], .Flags)

	 := 48

	for ,  := range .WriteChannelInfo {
		if  == 0 {
			le.PutUint16([40:42], uint16(64+)) // WriteChannelInfoOffset
		}

		.Encode([:])

		 += .Size()
	}

	le.PutUint16([42:44], uint16(-48)) // WriteChannelInfoLength

	le.PutUint16([2:4], uint16(64+)) // DataOffset

	copy([:], .Data)

	le.PutUint32([4:8], uint32(len(.Data))) // Length
}

type WriteRequestDecoder []byte

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

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

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

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

	return false
}

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

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

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

func ( WriteRequestDecoder) () uint64 {
	return le.Uint64([8:16])
}

func ( WriteRequestDecoder) () FileIdDecoder {
	return FileIdDecoder([16:32])
}

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

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

func ( WriteRequestDecoder) () uint16 {
	return le.Uint16([40:42])
}

func ( WriteRequestDecoder) () uint16 {
	return le.Uint16([42:44])
}

func ( WriteRequestDecoder) () uint32 {
	return le.Uint32([44:48])
}

// ----------------------------------------------------------------------------
// SMB2 OPLOCK_BREAK Acknowledgement
//

// ----------------------------------------------------------------------------
// SMB2 LOCK Request Packet
//

// ----------------------------------------------------------------------------
// SMB2 ECHO Request Packet
//

// ----------------------------------------------------------------------------
// SMB2 CANCEL Request Packet
//

type CancelRequest struct {
	PacketHeader
}

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

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

func ( *CancelRequest) ( []byte) {
	.Command = SMB2_CANCEL
	.encodeHeader()

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

type CancelRequestDecoder []byte

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

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

	return false
}

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

// ----------------------------------------------------------------------------
// SMB2 IOCTL Request Packet
//

type IoctlRequest struct {
	PacketHeader

	CtlCode           uint32
	FileId            *FileId
	OutputOffset      uint32
	OutputCount       uint32
	MaxInputResponse  uint32
	MaxOutputResponse uint32
	Flags             uint32
	Input             Encoder
}

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

func ( *IoctlRequest) () int {
	if .Input == nil {
		return 64 + 56 + 1
	}

	return 64 + 56 + .Input.Size()
}

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

	 := [64:]
	le.PutUint16([:2], 57) // StructureSize
	le.PutUint32([4:8], .CtlCode)
	.FileId.Encode([8:24])
	le.PutUint32([32:36], .MaxInputResponse)
	le.PutUint32([36:40], .OutputOffset)
	le.PutUint32([40:44], .OutputCount)
	le.PutUint32([44:48], .MaxOutputResponse)
	le.PutUint32([48:52], .Flags)

	 := 56

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

		.Input.Encode([:])

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

type IoctlRequestDecoder []byte

func ( IoctlRequestDecoder) () bool {
	if len() < 56 {
		return true
	}

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

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

	return false
}

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

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

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

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

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

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

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

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

func ( IoctlRequestDecoder) () uint32 {
	return le.Uint32([44:48])
}

func ( IoctlRequestDecoder) () uint32 {
	return le.Uint32([48:52])
}

// ----------------------------------------------------------------------------
// SMB2 QUERY_DIRECTORY Request Packet
//

type QueryDirectoryRequest struct {
	PacketHeader

	FileInfoClass      uint8
	Flags              uint8
	FileIndex          uint32
	FileId             *FileId
	OutputBufferLength uint32
	FileName           string
}

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

func ( *QueryDirectoryRequest) () int {
	if len(.FileName) == 0 {
		return 64 + 32 + 1
	}

	return 64 + 32 + utf16le.EncodedStringLen(.FileName)
}

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

	 := [64:]
	le.PutUint16([:2], 33) // StructureSize
	[2] = .FileInfoClass
	[3] = .Flags
	le.PutUint32([4:8], .FileIndex)
	.FileId.Encode([8:24])
	le.PutUint32([28:32], .OutputBufferLength)

	 := 32

	le.PutUint16([24:26], uint16(+64)) // FileNameOffset

	 := utf16le.EncodeString([:], .FileName)

	le.PutUint16([26:28], uint16()) // FileNameLength
}

type QueryDirectoryRequestDecoder []byte

func ( QueryDirectoryRequestDecoder) () bool {
	if len() < 32 {
		return true
	}

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

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

	return false
}

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

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

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

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

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

func ( QueryDirectoryRequestDecoder) () uint16 {
	return le.Uint16([24:26])
}

func ( QueryDirectoryRequestDecoder) () uint16 {
	return le.Uint16([26:28])
}

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

// ----------------------------------------------------------------------------
// SMB2 CHANGE_NOTIFY Request Packet
//

// ----------------------------------------------------------------------------
// SMB2 QUERY_INFO Request Packet
//

type QueryInfoRequest struct {
	PacketHeader

	InfoType              uint8
	FileInfoClass         uint8
	OutputBufferLength    uint32
	AdditionalInformation uint32
	Flags                 uint32
	FileId                *FileId
	Input                 Encoder
}

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

func ( *QueryInfoRequest) () int {
	if .Input == nil {
		return 64 + 40 + 1
	}

	return 64 + 40 + .Input.Size()
}

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

	 := [64:]
	le.PutUint16([:2], 41) // StructureSize
	[2] = .InfoType
	[3] = .FileInfoClass
	le.PutUint32([4:8], .OutputBufferLength)
	le.PutUint32([16:20], .AdditionalInformation)
	le.PutUint32([20:24], .Flags)
	.FileId.Encode([24:40])

	 := 40

	if .Input != nil {
		le.PutUint16([8:10], uint16(+64)) // InputBufferOffset

		.Input.Encode([:])

		le.PutUint32([12:16], uint32(.Input.Size())) // InputBufferLength
	}
}

type QueryInfoRequestDecoder []byte

func ( QueryInfoRequestDecoder) () bool {
	if len() < 40 {
		return true
	}

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

	if len() < int(uint32(.InputBufferOffset())+.InputBufferLength())-64 {
		return true
	}

	return false
}

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

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

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

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

func ( QueryInfoRequestDecoder) () uint16 {
	return le.Uint16([8:10])
}

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

func ( QueryInfoRequestDecoder) () uint32 {
	return le.Uint32([16:20])
}

func ( QueryInfoRequestDecoder) () uint32 {
	return le.Uint32([20:24])
}

func ( QueryInfoRequestDecoder) () FileIdDecoder {
	return FileIdDecoder([24:40])
}

// ----------------------------------------------------------------------------
// SMB2 SET_INFO Request Packet
//

type SetInfoRequest struct {
	PacketHeader

	InfoType              uint8
	FileInfoClass         uint8
	AdditionalInformation uint32
	FileId                *FileId
	Input                 Encoder
}

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

func ( *SetInfoRequest) () int {
	if .Input == nil {
		return 64 + 32 + 1
	}

	return 64 + 32 + .Input.Size()
}

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

	 := [64:]
	le.PutUint16([:2], 33) // StructureSize
	[2] = .InfoType
	[3] = .FileInfoClass
	le.PutUint32([12:16], .AdditionalInformation)
	.FileId.Encode([16:32])

	 := 32

	if .Input != nil {
		le.PutUint16([8:10], uint16(+64)) // BufferOffset

		.Input.Encode([:])

		le.PutUint32([4:8], uint32(.Input.Size())) // BufferLength
	}
}

type SetInfoRequestDecoder []byte

func ( SetInfoRequestDecoder) () bool {
	if len() < 32 {
		return true
	}

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

	if len() < int(uint32(.BufferOffset())+.BufferLength())-64 {
		return true
	}

	return false
}

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

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

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

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

func ( SetInfoRequestDecoder) () uint16 {
	return le.Uint16([8:10])
}

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

func ( SetInfoRequestDecoder) () FileIdDecoder {
	return FileIdDecoder([16:32])
}