enum SMBVersion {
	SMB1 = 0xff534d42, # \xffSMB
	SMB2 = 0xfe534d42, # \xfeSMB
	SMB3 = 0xfd534d42, # \xfdSMB (implies use of transform_header)
};

enum TransactionType {
	SMB_MAILSLOT_BROWSE, # \MAILSLOT\BROWSE - MS Browse Protocol
	SMB_MAILSLOT_LANMAN, # \MAILSLOT\LANMAN - deprecated cmds
	SMB_PIPE,            # \PIPE\* named pipes?
	SMB_RAP,             # \PIPE\LANMAN - remote administration protocol
	SMB_UNKNOWN,         # there are probably lots of these
};

enum SMB_Command {
	SMB_COM_CREATE_DIRECTORY = 0x00,
	SMB_COM_DELETE_DIRECTORY = 0x01,
	SMB_COM_OPEN = 0x02,
	SMB_COM_CREATE = 0x03,
	SMB_COM_CLOSE = 0x04,
	SMB_COM_FLUSH = 0x05,
	SMB_COM_DELETE = 0x06,
	SMB_COM_RENAME = 0x07,
	SMB_COM_QUERY_INFORMATION = 0x08,
	SMB_COM_SET_INFORMATION = 0x09,
	SMB_COM_READ = 0x0A,
	SMB_COM_WRITE = 0x0B,
	SMB_COM_LOCK_BYTE_RANGE = 0x0C,
	SMB_COM_UNLOCK_BYTE_RANGE = 0x0D,
	SMB_COM_CREATE_TEMPORARY = 0x0E,
	SMB_COM_CREATE_NEW = 0x0F,
	SMB_COM_CHECK_DIRECTORY = 0x10,
	SMB_COM_PROCESS_EXIT = 0x11,
	SMB_COM_SEEK = 0x12,
	SMB_COM_LOCK_AND_READ = 0x13,
	SMB_COM_WRITE_AND_UNLOCK = 0x14,
	SMB_COM_READ_RAW = 0x1A,
	SMB_COM_READ_MPX = 0x1B,
	SMB_COM_READ_MPX_SECONDARY = 0x1C,
	SMB_COM_WRITE_RAW = 0x1D,
	SMB_COM_WRITE_MPX = 0x1E,
	SMB_COM_WRITE_MPX_SECONDARY = 0x1F,
	SMB_COM_WRITE_COMPLETE = 0x20,
	SMB_COM_QUERY_SERVER = 0x21,
	SMB_COM_SET_INFORMATION2 = 0x22,
	SMB_COM_QUERY_INFORMATION2 = 0x23,
	SMB_COM_LOCKING_ANDX = 0x24,
	SMB_COM_TRANSACTION = 0x25,
	SMB_COM_TRANSACTION_SECONDARY = 0x26,
	SMB_COM_IOCTL = 0x27,
	SMB_COM_IOCTL_SECONDARY = 0x28,
	SMB_COM_COPY = 0x29,
	SMB_COM_MOVE = 0x2A,
	SMB_COM_ECHO = 0x2B,
	SMB_COM_WRITE_AND_CLOSE = 0x2C,
	SMB_COM_OPEN_ANDX = 0x2D,
	SMB_COM_READ_ANDX = 0x2E,
	SMB_COM_WRITE_ANDX = 0x2F,
	SMB_COM_NEW_FILE_SIZE = 0x30,
	SMB_COM_CLOSE_AND_TREE_DISC = 0x31,
	SMB_COM_TRANSACTION2 = 0x32,
	SMB_COM_TRANSACTION2_SECONDARY = 0x33,
	SMB_COM_FIND_CLOSE2 = 0x34,
	SMB_COM_FIND_NOTIFY_CLOSE = 0x35,

	SMB_COM_TREE_CONNECT = 0x70,
	SMB_COM_TREE_DISCONNECT = 0x71,
	SMB_COM_NEGOTIATE = 0x72,
	SMB_COM_SESSION_SETUP_ANDX = 0x73,
	SMB_COM_LOGOFF_ANDX = 0x74,
	SMB_COM_TREE_CONNECT_ANDX = 0x75,
	SMB_COM_QUERY_INFORMATION_DISK = 0x80,
	SMB_COM_SEARCH = 0x81,
	SMB_COM_FIND = 0x82,
	SMB_COM_FIND_UNIQUE = 0x83,
	SMB_COM_FIND_CLOSE = 0x84,
	SMB_COM_NT_TRANSACT = 0xA0,
	SMB_COM_NT_TRANSACT_SECONDARY = 0xA1,
	SMB_COM_NT_CREATE_ANDX = 0xA2,
	SMB_COM_NT_CANCEL = 0xA4,
	SMB_COM_NT_RENAME = 0xA5,
	SMB_COM_OPEN_PRINT_FILE = 0xC0,
	SMB_COM_WRITE_PRINT_FILE = 0xC1,
	SMB_COM_CLOSE_PRINT_FILE = 0xC2,
	SMB_COM_GET_PRINT_QUEUE = 0xC3,
	SMB_COM_READ_BULK = 0xD8,
	SMB_COM_WRITE_BULK = 0xD9,
	SMB_COM_WRITE_BULK_DATA = 0xDA,
};

enum SMB_Status {
	# 0x000
	STATUS_SUCCESS				= 0x00000000,
	STATUS_NOTIFY_ENUM_DIR			= 0x0000010C,
	STATUS_INVALID_SMB			= 0x00010002,
	STATUS_SMB_BAD_TID			= 0x00050002,
	STATUS_SMB_BAD_FID			= 0x00060001,
	STATUS_OS2_INVALID_ACCESS		= 0x000C0001,
	# 0x001
	STATUS_SMB_BAD_COMMAND			= 0x00160002,
	# 0x005
	STATUS_SMB_BAD_UID			= 0x005B0002,
	# 0x007
	STATUS_OS2_NO_MORE_SIDS			= 0x00710001,
	STATUS_OS2_INVALID_LEVEL		= 0x007C0001,
	# 0x008
	STATUS_OS2_NEGATIVE_SEEK		= 0x00830001,
	# 0x00A
	STATUS_OS2_CANCEL_VIOLATION		= 0x00AD0001,
	STATUS_OS2_ATOMIC_LOCKS_NOT_SUPPORTED	= 0x00AE0001,
	# 0x00F
	STATUS_SMB_USE_MPX			= 0x00FA0002,
	STATUS_SMB_USE_STANDARD			= 0x00FB0002,
	STATUS_SMB_CONTINUE_MPX			= 0x00FC0002,
	# 0x01
	STATUS_OS2_CANNOT_COPY			= 0x010A0001,
	STATUS_OS2_EAS_DIDNT_FIT		= 0x01130001,
	# 0x03
	STATUS_OS2_EA_ACCESS_DENIED		= 0x03E20001,
	# 0x8
	STATUS_BUFFER_OVERFLOW			= 0x80000005,
	STATUS_NO_MORE_FILES			= 0x80000006,
	STATUS_DEVICE_PAPER_EMPTY		= 0x8000000E,
	STATUS_STOPPED_ON_SYMLINK		= 0x8000002D,
	# 0xC000000
	STATUS_UNSUCCESSFUL			= 0xC0000001,
	STATUS_NOT_IMPLEMENTED			= 0xC0000002,
	STATUS_INVALID_INFO_CLASS		= 0xC0000003,
	STATUS_INVALID_HANDLE			= 0xC0000008,
	STATUS_INVALID_PARAMETER		= 0xC000000D,
	STATUS_NO_SUCH_DEVICE			= 0xC000000E,
	STATUS_NO_SUCH_FILE			= 0xC000000F,
	# 0xC000001
	STATUS_INVALID_DEVICE_REQUEST		= 0xC0000010,
	STATUS_END_OF_FILE			= 0xC0000011,
	STATUS_WRONG_VOLUME			= 0xC0000012,
	STATUS_NONEXISTENT_SECTOR		= 0xC0000015,
	STATUS_NO_MEDIA_IN_DEVICE		= 0xC0000013,
	STATUS_MORE_PROCESSING_REQUIRED		= 0xC0000016,
	STATUS_INVALID_LOCK_SEQUENCE		= 0xC000001E,
	STATUS_INVALID_VIEW_SIZE		= 0xC000001F,
	# 0xC000002
	STATUS_ALREADY_COMMITTED		= 0xC0000021,
	STATUS_ACCESS_DENIED			= 0xC0000022,
	STATUS_BUFFER_TOO_SMALL			= 0xC0000023,
	STATUS_OBJECT_TYPE_MISMATCH		= 0xC0000024,
	STATUS_HANDLE_NOT_CLOSABLE		= 0xC0000025,
	# 0xC000003
	STATUS_DISK_CORRUPT_ERROR		= 0xC0000032,
	STATUS_OBJECT_NAME_NOT_FOUND		= 0xC0000034,
	STATUS_OBJECT_NAME_COLLISION		= 0xC0000035,
	STATUS_PORT_DISCONNECTED		= 0xC0000037,
	STATUS_OBJECT_PATH_INVALID		= 0xC0000039,
	STATUS_OBJECT_PATH_NOT_FOUND		= 0xC000003A,
	STATUS_OBJECT_PATH_SYNTAX_BAD		= 0xC000003B,
	STATUS_DATA_ERROR			= 0xC000003E,
	STATUS_CRC_ERROR			= 0xC000003F,
	# 0xC000004
	STATUS_SECTION_TOO_BIG			= 0xC0000040,
	STATUS_PORT_CONNECTION_REFUSED		= 0xC0000041,
	STATUS_INVALID_PORT_HANDLE		= 0xC0000042,
	STATUS_SHARING_VIOLATION		= 0xC0000043,
	STATUS_THREAD_IS_TERMINATING		= 0xC000004B,
	STATUS_EAS_NOT_SUPPORTED		= 0xC000004F,
	# 0xC000005
	STATUS_EA_TOO_LARGE			= 0xC0000050,
	STATUS_FILE_LOCK_CONFLICT		= 0xC0000054,
	STATUS_LOCK_NOT_GRANTED			= 0xC0000055,
	STATUS_DELETE_PENDING			= 0xC0000056,
	# 0xC000006
	STATUS_PRIVILEGE_NOT_HELD		= 0xC0000061,
	STATUS_LOGON_FAILURE			= 0xC000006D,
	STATUS_WRONG_PASSWORD			= 0xC000006A,
	STATUS_INVALID_LOGON_HOURS		= 0xC000006F,
	# 0xC000007
	STATUS_INVALID_WORKSTATION		= 0xC0000070,
	STATUS_PASSWORD_EXPIRED			= 0xC0000071,
	STATUS_ACCOUNT_DISABLED			= 0xC0000072,
	STATUS_RANGE_NOT_LOCKED			= 0xC000007E,
	STATUS_DISK_FULL			= 0xC000007F,
	# 0xC000009
	STATUS_TOO_MANY_PAGING_FILES		= 0xC0000097,
	STATUS_DFS_EXIT_PATH_FOUND		= 0xC000009B,
	STATUS_DEVICE_DATA_ERROR		= 0xC000009C,
	# 0xC00000A
	STATUS_MEDIA_WRITE_PROTECTED		= 0xC00000A2,
	STATUS_BAD_IMPERSONATION_LEVEL		= 0xC00000A5,
	STATUS_INSTANCE_NOT_AVAILABLE		= 0xC00000AB,
	STATUS_PIPE_NOT_AVAILABLE		= 0xC00000AC,
	STATUS_PIPE_STATE			= 0xC00000AD,
	STATUS_PIPE_BUSY			= 0xC00000AE,
	STATUS_ILLEGAL_FUNCTION			= 0xC00000AF,
	# 0xC00000B
	STATUS_PIPE_DISCONNECTED		= 0xC00000B0,
	STATUS_PIPE_CLOSING			= 0xC00000B1,
	STATUS_INVALID_READ_MODE		= 0xC00000B4,
	STATUS_IO_TIMEOUT			= 0xC00000B5,
	STATUS_FILE_IS_A_DIRECTORY		= 0xC00000BA,
	STATUS_NOT_SUPPORTED			= 0xC00000BB,
	# 0xC00000C
	STATUS_UNEXPECTED_NETWORK_ERROR		= 0xC00000C4,
	STATUS_PRINT_QUEUE_FULL			= 0xC00000C6,
	STATUS_NO_SPOOL_SPACE			= 0xC00000C7,
	STATUS_PRINT_CANCELLED			= 0xC00000C8,
	STATUS_NETWORK_NAME_DELETED		= 0xC00000C9,
	STATUS_NETWORK_ACCESS_DENIED		= 0xC00000CA,
	STATUS_BAD_DEVICE_TYPE			= 0xC00000CB,
	STATUS_BAD_NETWORK_NAME			= 0xC00000CC,
	STATUS_TOO_MANY_SESSIONS		= 0xC00000CE,
	# 0xC00000D
	STATUS_REQUEST_NOT_ACCEPTED		= 0xC00000D0,
	STATUS_NOT_SAME_DEVICE			= 0xC00000D4,
	STATUS_FILE_RENAMED			= 0xC00000D5,
	STATUS_PIPE_EMPTY			= 0xC00000D9,
	# 0xC00000F
	STATUS_REDIRECTOR_NOT_STARTED		= 0xC00000FB,
	# 0xC00001
	STATUS_DIRECTORY_NOT_EMPTY		= 0xC0000101,
	STATUS_PROCESS_IS_TERMINATING		= 0xC000010A,
	STATUS_TOO_MANY_OPENED_FILES		= 0xC000011F,
	STATUS_CANNOT_DELETE			= 0xC0000121,
	STATUS_FILE_DELETED			= 0xC0000123,
	STATUS_FILE_CLOSED			= 0xC0000128,
	STATUS_INVALID_DEVICE_STATE		= 0xC0000184,
	STATUS_ACCOUNT_EXPIRED			= 0xC0000193,
	# 0xC00002
	STATUS_USER_SESSION_DELETED		= 0xC0000203,
	STATUS_INSUFF_SERVER_RESOURCES		= 0xC0000205,
	STATUS_PASSWORD_MUST_CHANGE		= 0xC0000224,
	STATUS_ACCOUNT_LOCKED_OUT		= 0xC0000234,
	STATUS_PATH_NOT_COVERED			= 0xC0000257,
	# 0xC00003
	STATUS_NETWORK_SESSION_EXPIRED		= 0xC000035C,
	# 0xC0002
	STATUS_SMB_TOO_MANY_UIDS		= 0xC000205A,
	# 0xF
	STATUS_SMB_NO_SUPPORT			= 0xFFFF0002,
};

function determine_transaction_type(header: SMB_Header, name: SMB_string): TransactionType
	%{
	if ( name == nullptr )
		{
		return SMB_UNKNOWN;
		}

	if ( (${header.unicode} && ${name.u.s}->size() > 10 && ${name.u.s[0]} == '\\' &&
	                                                       ${name.u.s[2]} == 'P' &&
	                                                       ${name.u.s[4]} == 'I' &&
	                                                       ${name.u.s[6]} == 'P' &&
	                                                       ${name.u.s[8]} == 'E' &&
	                                                       ${name.u.s[10]} == '\\') ||
	     (!${header.unicode} && ${name.a}->size() > 5 && ${name.a}->val()->at(0) == '\\' &&
	                                                     ${name.a}->val()->at(1) == 'P' &&
	                                                     ${name.a}->val()->at(2) == 'I' &&
	                                                     ${name.a}->val()->at(3) == 'P' &&
	                                                     ${name.a}->val()->at(4) == 'E' &&
	                                                     ${name.a}->val()->at(5) == '\\') )
		{
		if ( (${header.unicode} && ${name.u.s}->size() > 22 && ${name.u.s[12]} == 'L' &&
		                                                       ${name.u.s[14]} == 'A' &&
		                                                       ${name.u.s[16]} == 'N' &&
		                                                       ${name.u.s[18]} == 'M' &&
		                                                       ${name.u.s[20]} == 'A' &&
		                                                       ${name.u.s[22]} == 'N') ||
	         (!${header.unicode} && ${name.a}->size() > 11 && ${name.a}->val()->at(6) == 'L' &&
	                                                          ${name.a}->val()->at(7) == 'A' &&
	                                                          ${name.a}->val()->at(8) == 'N' &&
	                                                          ${name.a}->val()->at(9) == 'M' &&
	                                                          ${name.a}->val()->at(10) == 'A' &&
	                                                          ${name.a}->val()->at(11) == 'N') )
			{
			return SMB_RAP;
			}

		return SMB_PIPE;
		}

	return SMB_UNKNOWN;
	%}
