The hash table merely associates data structures with conversations,
[obnox/wireshark/wip.git] / packet-smb.c
index 79e914f87b8f2250809371d497c9b7b61c18dc41..c8e790041bec94e8ada0acbe0de59fbc1f567455 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for smb packet dissection
  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
  *
- * $Id: packet-smb.c,v 1.122 2001/10/20 19:29:21 guy Exp $
+ * $Id: packet-smb.c,v 1.146 2001/11/12 21:43:49 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "packet-smb-mailslot.h"
 #include "packet-smb-pipe.h"
 
+/*
+ * Various specifications and documents about SMB can be found in
+ *
+ *     ftp://ftp.microsoft.com/developr/drg/CIFS/
+ *
+ * and a CIFS draft from the Storage Networking Industry Association
+ * can be found on a link from the page at
+ *
+ *     http://www.snia.org/English/Work_Groups/NAS/CIFS/WG_CIFS_Docs.html
+ *
+ * (it supercedes the document at
+ *
+ *     ftp://ftp.microsoft.com/developr/drg/CIFS/draft-leach-cifs-v1-spec-01.txt
+ *
+ * ).
+ *
+ * There are also some Open Group publications documenting CIFS for sale;
+ * catalog entries for them are at:
+ *
+ *     http://www.opengroup.org/products/publications/catalog/c209.htm
+ *
+ *     http://www.opengroup.org/products/publications/catalog/c195.htm
+ *
+ * The document "NT LAN Manager SMB File Sharing Protocol Extensions"
+ * can be found at
+ *
+ *     http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+ *
+ * (or, presumably a similar path under the Samba mirrors).  As the
+ * ".doc" indicates, it's a Word document.  Some of the specs from the
+ * Microsoft FTP site can be found in the
+ *
+ *     http://www.samba.org/samba/ftp/specs/
+ *
+ * directory as well.
+ *
+ * Beware - these specs may have errors.
+ */
 static int proto_smb = -1;
-
 static int hf_smb_cmd = -1;
-static int hf_smb_status = -1;
-static int hf_smb_errcls = -1;
-static int hf_smb_flags = -1;
-static int hf_smb_flags2 = -1;
-static int hf_smb_tid = -1;
 static int hf_smb_pid = -1;
+static int hf_smb_tid = -1;
 static int hf_smb_uid = -1;
 static int hf_smb_mid = -1;
+static int hf_smb_response_to = -1;
+static int hf_smb_response_in = -1;
+static int hf_smb_nt_status = -1;
+static int hf_smb_error_class = -1;
+static int hf_smb_error_code = -1;
+static int hf_smb_reserved = -1;
+static int hf_smb_flags_lock = -1;
+static int hf_smb_flags_receive_buffer = -1;
+static int hf_smb_flags_caseless = -1;
+static int hf_smb_flags_canon = -1;
+static int hf_smb_flags_oplock = -1;
+static int hf_smb_flags_notify = -1;
+static int hf_smb_flags_response = -1;
+static int hf_smb_flags2_long_names_allowed = -1;
+static int hf_smb_flags2_ea = -1;
+static int hf_smb_flags2_sec_sig = -1;
+static int hf_smb_flags2_long_names_used = -1;
+static int hf_smb_flags2_esn = -1;
+static int hf_smb_flags2_dfs = -1;
+static int hf_smb_flags2_roe = -1;
+static int hf_smb_flags2_nt_error = -1;
+static int hf_smb_flags2_string = -1;
+static int hf_smb_word_count = -1;
+static int hf_smb_byte_count = -1;
+static int hf_smb_buffer_format = -1;
+static int hf_smb_dialect_name = -1;
+static int hf_smb_dialect_index = -1;
+static int hf_smb_max_trans_buf_size = -1;
+static int hf_smb_max_mpx_count = -1;
+static int hf_smb_max_vcs_num = -1;
+static int hf_smb_session_key = -1;
+static int hf_smb_server_timezone = -1;
+static int hf_smb_encryption_key_length = -1;
+static int hf_smb_encryption_key = -1;
+static int hf_smb_primary_domain = -1;
+static int hf_smb_max_raw_buf_size = -1;
+static int hf_smb_server_guid = -1;
+static int hf_smb_security_blob_len = -1;
+static int hf_smb_security_blob = -1;
+static int hf_smb_sm_mode16 = -1;
+static int hf_smb_sm_password16 = -1;
+static int hf_smb_sm_mode = -1;
+static int hf_smb_sm_password = -1;
+static int hf_smb_sm_signatures = -1;
+static int hf_smb_sm_sig_required = -1;
+static int hf_smb_rm_read = -1;
+static int hf_smb_rm_write = -1;
+static int hf_smb_server_date_time = -1;
+static int hf_smb_server_smb_date = -1;
+static int hf_smb_server_smb_time = -1;
+static int hf_smb_server_cap_raw_mode = -1;
+static int hf_smb_server_cap_mpx_mode = -1;
+static int hf_smb_server_cap_unicode = -1;
+static int hf_smb_server_cap_large_files = -1;
+static int hf_smb_server_cap_nt_smbs = -1;
+static int hf_smb_server_cap_rpc_remote_apis = -1;
+static int hf_smb_server_cap_nt_status = -1;
+static int hf_smb_server_cap_level_ii_oplocks = -1;
+static int hf_smb_server_cap_lock_and_read = -1;
+static int hf_smb_server_cap_nt_find = -1;
+static int hf_smb_server_cap_dfs = -1;
+static int hf_smb_server_cap_infolevel_passthru = -1;
+static int hf_smb_server_cap_large_readx = -1;
+static int hf_smb_server_cap_large_writex = -1;
+static int hf_smb_server_cap_unix = -1;
+static int hf_smb_server_cap_reserved = -1;
+static int hf_smb_server_cap_bulk_transfer = -1;
+static int hf_smb_server_cap_compressed_data = -1;
+static int hf_smb_server_cap_extended_security = -1;
+static int hf_smb_system_time = -1;
+static int hf_smb_unknown = -1;
+static int hf_smb_dir_name = -1;
+static int hf_smb_echo_count = -1;
+static int hf_smb_echo_data = -1;
+static int hf_smb_echo_seq_num = -1;
+static int hf_smb_max_buf_size = -1;
+static int hf_smb_password = -1;
+static int hf_smb_password_len = -1;
+static int hf_smb_ansi_password = -1;
+static int hf_smb_ansi_password_len = -1;
+static int hf_smb_unicode_password = -1;
+static int hf_smb_unicode_password_len = -1;
+static int hf_smb_path = -1;
+static int hf_smb_service = -1;
+static int hf_smb_move_flags_file = -1;
+static int hf_smb_move_flags_dir = -1;
+static int hf_smb_move_flags_verify = -1;
+static int hf_smb_count = -1;
+static int hf_smb_file_name = -1;
+static int hf_smb_open_function_open = -1;
+static int hf_smb_open_function_create = -1;
+static int hf_smb_fid = -1;
+static int hf_smb_file_attr_read_only_16bit = -1;
+static int hf_smb_file_attr_read_only_8bit = -1;
+static int hf_smb_file_attr_hidden_16bit = -1;
+static int hf_smb_file_attr_hidden_8bit = -1;
+static int hf_smb_file_attr_system_16bit = -1;
+static int hf_smb_file_attr_system_8bit = -1;
+static int hf_smb_file_attr_volume_16bit = -1;
+static int hf_smb_file_attr_volume_8bit = -1;
+static int hf_smb_file_attr_directory_16bit = -1;
+static int hf_smb_file_attr_directory_8bit = -1;
+static int hf_smb_file_attr_archive_16bit = -1;
+static int hf_smb_file_attr_archive_8bit = -1;
+static int hf_smb_file_attr_device = -1;
+static int hf_smb_file_attr_normal = -1;
+static int hf_smb_file_attr_temporary = -1;
+static int hf_smb_file_attr_sparse = -1;
+static int hf_smb_file_attr_reparse = -1;
+static int hf_smb_file_attr_compressed = -1;
+static int hf_smb_file_attr_offline = -1;
+static int hf_smb_file_attr_not_content_indexed = -1;
+static int hf_smb_file_attr_encrypted = -1;
+static int hf_smb_file_size = -1;
+static int hf_smb_search_attribute_read_only = -1;
+static int hf_smb_search_attribute_hidden = -1;
+static int hf_smb_search_attribute_system = -1;
+static int hf_smb_search_attribute_volume = -1;
+static int hf_smb_search_attribute_directory = -1;
+static int hf_smb_search_attribute_archive = -1;
+static int hf_smb_access_mode = -1;
+static int hf_smb_access_sharing = -1;
+static int hf_smb_access_locality = -1;
+static int hf_smb_access_caching = -1;
+static int hf_smb_access_writetru = -1;
+static int hf_smb_create_time = -1;
+static int hf_smb_create_dos_date = -1;
+static int hf_smb_create_dos_time = -1;
+static int hf_smb_last_write_time = -1;
+static int hf_smb_last_write_dos_date = -1;
+static int hf_smb_last_write_dos_time = -1;
+static int hf_smb_access_time = -1;
+static int hf_smb_access_dos_date = -1;
+static int hf_smb_access_dos_time = -1;
+static int hf_smb_old_file_name = -1;
+static int hf_smb_offset = -1;
+static int hf_smb_remaining = -1;
+static int hf_smb_padding = -1;
+static int hf_smb_file_data = -1;
+static int hf_smb_total_data_len = -1;
+static int hf_smb_data_len = -1;
+static int hf_smb_seek_mode = -1;
+static int hf_smb_data_size = -1;
+static int hf_smb_alloc_size = -1;
+static int hf_smb_alloc_size64 = -1;
+static int hf_smb_max_count = -1;
+static int hf_smb_min_count = -1;
+static int hf_smb_timeout = -1;
+static int hf_smb_high_offset = -1;
+static int hf_smb_units = -1;
+static int hf_smb_bpu = -1;
+static int hf_smb_blocksize = -1;
+static int hf_smb_freeunits = -1;
+static int hf_smb_data_offset = -1;
+static int hf_smb_dcm = -1;
+static int hf_smb_request_mask = -1;
+static int hf_smb_response_mask = -1;
+static int hf_smb_sid = -1;
+static int hf_smb_write_raw_mode_write_through = -1;
+static int hf_smb_write_raw_mode_return_remaining = -1;
+static int hf_smb_write_raw_mode_connectionless = -1;
+static int hf_smb_resume_key_len = -1;
+static int hf_smb_resume_server_cookie = -1;
+static int hf_smb_resume_client_cookie = -1;
+static int hf_smb_andxoffset = -1;
+static int hf_smb_lock_type_large = -1;
+static int hf_smb_lock_type_cancel = -1;
+static int hf_smb_lock_type_change = -1;
+static int hf_smb_lock_type_oplock = -1;
+static int hf_smb_lock_type_shared = -1;
+static int hf_smb_locking_ol = -1;
+static int hf_smb_number_of_locks = -1;
+static int hf_smb_number_of_unlocks = -1;
+static int hf_smb_lock_long_offset = -1;
+static int hf_smb_lock_long_length = -1;
+static int hf_smb_file_type = -1;
+static int hf_smb_ipc_state_nonblocking = -1;
+static int hf_smb_ipc_state_endpoint = -1;
+static int hf_smb_ipc_state_pipe_type = -1;
+static int hf_smb_ipc_state_read_mode = -1;
+static int hf_smb_ipc_state_icount = -1;
+static int hf_smb_server_fid = -1;
+static int hf_smb_open_flags_add_info = -1;
+static int hf_smb_open_flags_ex_oplock = -1;
+static int hf_smb_open_flags_batch_oplock = -1;
+static int hf_smb_open_flags_ealen = -1;
+static int hf_smb_open_action_open = -1;
+static int hf_smb_open_action_lock = -1;
+static int hf_smb_vc_num = -1;
+static int hf_smb_account = -1;
+static int hf_smb_os = -1;
+static int hf_smb_lanman = -1;
+static int hf_smb_setup_action_guest = -1;
+static int hf_smb_fs = -1;
+static int hf_smb_connect_flags_dtid = -1;
+static int hf_smb_connect_support_search = -1;
+static int hf_smb_connect_support_in_dfs = -1;
+static int hf_smb_max_setup_count = -1;
+static int hf_smb_total_param_count = -1;
+static int hf_smb_total_data_count = -1;
+static int hf_smb_max_param_count = -1;
+static int hf_smb_max_data_count = -1;
+static int hf_smb_param_disp16 = -1;
+static int hf_smb_param_count16 = -1;
+static int hf_smb_param_offset16 = -1;
+static int hf_smb_param_disp32 = -1;
+static int hf_smb_param_count32 = -1;
+static int hf_smb_param_offset32 = -1;
+static int hf_smb_data_disp16 = -1;
+static int hf_smb_data_count16 = -1;
+static int hf_smb_data_offset16 = -1;
+static int hf_smb_data_disp32 = -1;
+static int hf_smb_data_count32 = -1;
+static int hf_smb_data_offset32 = -1;
+static int hf_smb_setup_count = -1;
+static int hf_smb_nt_trans_subcmd = -1;
+static int hf_smb_nt_ioctl_function_code = -1;
+static int hf_smb_nt_ioctl_isfsctl = -1;
+static int hf_smb_nt_ioctl_flags_root_handle = -1;
+static int hf_smb_nt_ioctl_data = -1;
+static int hf_smb_nt_security_information = -1;
+static int hf_smb_nt_notify_action = -1;
+static int hf_smb_nt_notify_watch_tree = -1;
+static int hf_smb_nt_notify_stream_write = -1;
+static int hf_smb_nt_notify_stream_size = -1;
+static int hf_smb_nt_notify_stream_name = -1;
+static int hf_smb_nt_notify_security = -1;
+static int hf_smb_nt_notify_ea = -1;
+static int hf_smb_nt_notify_creation = -1;
+static int hf_smb_nt_notify_last_access = -1;
+static int hf_smb_nt_notify_last_write = -1;
+static int hf_smb_nt_notify_size = -1;
+static int hf_smb_nt_notify_attributes = -1;
+static int hf_smb_nt_notify_dir_name = -1;
+static int hf_smb_nt_notify_file_name = -1;
+static int hf_smb_root_dir_fid = -1;
+static int hf_smb_nt_create_disposition = -1;
+static int hf_smb_sd_length = -1;
+static int hf_smb_ea_length = -1;
+static int hf_smb_file_name_len = -1;
+static int hf_smb_nt_impersonation_level = -1;
+static int hf_smb_nt_security_flags_context_tracking = -1;
+static int hf_smb_nt_security_flags_effective_only = -1;
+static int hf_smb_nt_access_mask_generic_read = -1;
+static int hf_smb_nt_access_mask_generic_write = -1;
+static int hf_smb_nt_access_mask_generic_execute = -1;
+static int hf_smb_nt_access_mask_generic_all = -1;
+static int hf_smb_nt_access_mask_maximum_allowed = -1;
+static int hf_smb_nt_access_mask_system_security = -1;
+static int hf_smb_nt_access_mask_synchronize = -1;
+static int hf_smb_nt_access_mask_write_owner = -1;
+static int hf_smb_nt_access_mask_write_dac = -1;
+static int hf_smb_nt_access_mask_read_control = -1;
+static int hf_smb_nt_access_mask_delete = -1;
+static int hf_smb_nt_access_mask_write_attributes = -1;
+static int hf_smb_nt_access_mask_read_attributes = -1;
+static int hf_smb_nt_access_mask_delete_child = -1;
+static int hf_smb_nt_access_mask_execute = -1;
+static int hf_smb_nt_access_mask_write_ea = -1;
+static int hf_smb_nt_access_mask_read_ea = -1;
+static int hf_smb_nt_access_mask_append = -1;
+static int hf_smb_nt_access_mask_write = -1;
+static int hf_smb_nt_access_mask_read = -1;
+static int hf_smb_nt_create_bits_oplock = -1;
+static int hf_smb_nt_create_bits_boplock = -1;
+static int hf_smb_nt_create_bits_dir = -1;
+static int hf_smb_nt_create_options_directory_file = -1;
+static int hf_smb_nt_create_options_write_through = -1;
+static int hf_smb_nt_create_options_sequential_only = -1;
+static int hf_smb_nt_create_options_sync_io_alert = -1;
+static int hf_smb_nt_create_options_sync_io_nonalert = -1;
+static int hf_smb_nt_create_options_non_directory_file = -1;
+static int hf_smb_nt_create_options_no_ea_knowledge = -1;
+static int hf_smb_nt_create_options_eight_dot_three_only = -1;
+static int hf_smb_nt_create_options_random_access = -1;
+static int hf_smb_nt_create_options_delete_on_close = -1;
+static int hf_smb_nt_share_access_read = -1;
+static int hf_smb_nt_share_access_write = -1;
+static int hf_smb_nt_share_access_delete = -1;
+static int hf_smb_file_eattr_read_only = -1;
+static int hf_smb_file_eattr_hidden = -1;
+static int hf_smb_file_eattr_system = -1;
+static int hf_smb_file_eattr_volume = -1;
+static int hf_smb_file_eattr_directory = -1;
+static int hf_smb_file_eattr_archive = -1;
+static int hf_smb_file_eattr_device = -1;
+static int hf_smb_file_eattr_normal = -1;
+static int hf_smb_file_eattr_temporary = -1;
+static int hf_smb_file_eattr_sparse = -1;
+static int hf_smb_file_eattr_reparse = -1;
+static int hf_smb_file_eattr_compressed = -1;
+static int hf_smb_file_eattr_offline = -1;
+static int hf_smb_file_eattr_not_content_indexed = -1;
+static int hf_smb_file_eattr_encrypted = -1;
+static int hf_smb_file_eattr_write_through = -1;
+static int hf_smb_file_eattr_no_buffering = -1;
+static int hf_smb_file_eattr_random_access = -1;
+static int hf_smb_file_eattr_sequential_scan = -1;
+static int hf_smb_file_eattr_delete_on_close = -1;
+static int hf_smb_file_eattr_backup_semantics = -1;
+static int hf_smb_file_eattr_posix_semantics = -1;
+static int hf_smb_security_descriptor_len = -1;
+static int hf_smb_security_descriptor = -1;
+static int hf_smb_nt_qsd_owner = -1;
+static int hf_smb_nt_qsd_group = -1;
+static int hf_smb_nt_qsd_dacl = -1;
+static int hf_smb_nt_qsd_sacl = -1;
+static int hf_smb_extended_attributes = -1;
+static int hf_smb_oplock_level = -1;
+static int hf_smb_create_action = -1;
+static int hf_smb_ea_error_offset = -1;
+static int hf_smb_end_of_file = -1;
+static int hf_smb_device_type = -1;
+static int hf_smb_is_directory = -1;
+static int hf_smb_next_entry_offset = -1;
+static int hf_smb_change_time = -1;
+static int hf_smb_setup_len = -1;
+static int hf_smb_print_mode = -1;
+static int hf_smb_print_identifier = -1;
+static int hf_smb_restart_index = -1;
+static int hf_smb_print_queue_date = -1;
+static int hf_smb_print_queue_dos_date = -1;
+static int hf_smb_print_queue_dos_time = -1;
+static int hf_smb_print_status = -1;
+static int hf_smb_print_spool_file_number = -1;
+static int hf_smb_print_spool_file_size = -1;
+static int hf_smb_print_spool_file_name = -1;
+static int hf_smb_start_index = -1;
+static int hf_smb_cancel_to = -1;
+static int hf_smb_trans2_subcmd = -1;
+static int hf_smb_trans_name = -1;
+static int hf_smb_transaction_flags_dtid = -1;
+static int hf_smb_transaction_flags_owt = -1;
+static int hf_smb_search_count = -1;
+static int hf_smb_search_pattern = -1;
+static int hf_smb_ff2_backup = -1;
+static int hf_smb_ff2_continue = -1;
+static int hf_smb_ff2_resume = -1;
+static int hf_smb_ff2_close_eos = -1;
+static int hf_smb_ff2_close = -1;
+static int hf_smb_ff2_information_level = -1;
+static int hf_smb_qpi_loi = -1;
+static int hf_smb_storage_type = -1;
+static int hf_smb_resume = -1;
+static int hf_smb_max_referral_level = -1;
+static int hf_smb_qfsi_information_level = -1;
+static int hf_smb_ea_size = -1;
+static int hf_smb_list_length = -1;
+static int hf_smb_number_of_links = -1;
+static int hf_smb_delete_pending = -1;
+static int hf_smb_index_number = -1;
+static int hf_smb_current_offset = -1;
+static int hf_smb_t2_alignment = -1;
+static int hf_smb_t2_stream_name_length = -1;
+static int hf_smb_t2_stream_size = -1;
+static int hf_smb_t2_compressed_file_size = -1;
+static int hf_smb_t2_compressed_format = -1;
+static int hf_smb_t2_compressed_unit_shift = -1;
+static int hf_smb_t2_compressed_chunk_shift = -1;
+static int hf_smb_t2_compressed_cluster_shift = -1;
+static int hf_smb_dfs_path_consumed = -1;
+static int hf_smb_dfs_num_referrals = -1;
+static int hf_smb_get_dfs_server_hold_storage = -1;
+static int hf_smb_get_dfs_fielding = -1;
+static int hf_smb_dfs_referral_version = -1;
+static int hf_smb_dfs_referral_size = -1;
+static int hf_smb_dfs_referral_server_type = -1;
+static int hf_smb_dfs_referral_flags_strip = -1;
+static int hf_smb_dfs_referral_node_offset = -1;
+static int hf_smb_dfs_referral_node = -1;
+static int hf_smb_dfs_referral_proximity = -1;
+static int hf_smb_dfs_referral_ttl = -1;
+static int hf_smb_dfs_referral_path_offset = -1;
+static int hf_smb_dfs_referral_path = -1;
+static int hf_smb_dfs_referral_alt_path_offset = -1;
+static int hf_smb_dfs_referral_alt_path = -1;
+static int hf_smb_end_of_search = -1;
+static int hf_smb_last_name_offset = -1;
+static int hf_smb_file_index = -1;
+static int hf_smb_short_file_name = -1;
+static int hf_smb_short_file_name_len = -1;
+static int hf_smb_fs_id = -1;
+static int hf_smb_sector_unit = -1;
+static int hf_smb_fs_units = -1;
+static int hf_smb_fs_sector = -1;
+static int hf_smb_avail_units = -1;
+static int hf_smb_volume_serial_num = -1;
+static int hf_smb_volume_label_len = -1;
+static int hf_smb_volume_label = -1;
+static int hf_smb_free_alloc_units64 = -1;
+static int hf_smb_max_name_len = -1;
+static int hf_smb_fs_name_len = -1;
+static int hf_smb_fs_name = -1;
+static int hf_smb_device_char_removable = -1;
+static int hf_smb_device_char_read_only = -1;
+static int hf_smb_device_char_floppy = -1;
+static int hf_smb_device_char_write_once = -1;
+static int hf_smb_device_char_remote = -1;
+static int hf_smb_device_char_mounted = -1;
+static int hf_smb_device_char_virtual = -1;
+static int hf_smb_fs_attr_css = -1;
+static int hf_smb_fs_attr_cpn = -1;
+static int hf_smb_fs_attr_pacls = -1;
+static int hf_smb_fs_attr_fc = -1;
+static int hf_smb_fs_attr_vq = -1;
+static int hf_smb_fs_attr_dim = -1;
+static int hf_smb_fs_attr_vic = -1;
 
 static gint ett_smb = -1;
 static gint ett_smb_hdr = -1;
+static gint ett_smb_command = -1;
 static gint ett_smb_fileattributes = -1;
 static gint ett_smb_capabilities = -1;
 static gint ett_smb_aflags = -1;
+static gint ett_smb_dialect = -1;
 static gint ett_smb_dialects = -1;
 static gint ett_smb_mode = -1;
 static gint ett_smb_rawmode = -1;
@@ -84,13 +526,205 @@ static gint ett_smb_writemode = -1;
 static gint ett_smb_lock_type = -1;
 static gint ett_smb_ssetupandxaction = -1;
 static gint ett_smb_optionsup = -1;
+static gint ett_smb_time_date = -1;
+static gint ett_smb_64bit_time = -1;
+static gint ett_smb_move_flags = -1;
+static gint ett_smb_file_attributes = -1;
+static gint ett_smb_search_resume_key = -1;
+static gint ett_smb_search_dir_info = -1;
+static gint ett_smb_unlocks = -1;
+static gint ett_smb_unlock = -1;
+static gint ett_smb_locks = -1;
+static gint ett_smb_lock = -1;
+static gint ett_smb_open_flags = -1;
+static gint ett_smb_ipc_state = -1;
+static gint ett_smb_open_action = -1;
+static gint ett_smb_setup_action = -1;
+static gint ett_smb_connect_flags = -1;
+static gint ett_smb_connect_support_bits = -1;
+static gint ett_smb_nt_access_mask = -1;
+static gint ett_smb_nt_create_bits = -1;
+static gint ett_smb_nt_create_options = -1;
+static gint ett_smb_nt_share_access = -1;
+static gint ett_smb_nt_security_flags = -1;
+static gint ett_smb_nt_trans_setup = -1;
+static gint ett_smb_nt_notify_completion_filter = -1;
+static gint ett_smb_nt_ioctl_flags = -1;
+static gint ett_smb_security_information_mask = -1;
+static gint ett_smb_print_queue_entry = -1;
+static gint ett_smb_transaction_flags = -1;
+static gint ett_smb_transaction_params = -1;
+static gint ett_smb_find_first2_flags = -1;
+static gint ett_smb_transaction_data = -1;
+static gint ett_smb_dfs_referrals = -1;
+static gint ett_smb_dfs_referral = -1;
+static gint ett_smb_dfs_referral_flags = -1;
+static gint ett_smb_get_dfs_flags = -1;
+static gint ett_smb_ff2_data = -1;
+static gint ett_smb_device_characteristics = -1;
+static gint ett_smb_fs_attributes = -1;
+
+
+static char *decode_smb_name(unsigned char);
+static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree, guint8 cmd);
+static const gchar *get_unicode_or_ascii_string_tvb(tvbuff_t *tvb,
+    int *offsetp, packet_info *pinfo, int *len, gboolean nopad,
+    gboolean exactlen, guint16 *bcp);
 
+/*
+ * Macros for use in the main dissector routines for an SMB.
+ */
+
+#define WORD_COUNT     \
+       /* Word Count */                                \
+       wc = tvb_get_guint8(tvb, offset);               \
+       proto_tree_add_uint(tree, hf_smb_word_count,    \
+               tvb, offset, 1, wc);                    \
+       offset += 1;                                    \
+       if(wc==0) goto bytecount;
+
+#define BYTE_COUNT     \
+       bytecount:                                      \
+       bc = tvb_get_letohs(tvb, offset);               \
+       proto_tree_add_uint(tree, hf_smb_byte_count,    \
+                       tvb, offset, 2, bc);            \
+       offset += 2;                                    \
+       if(bc==0) goto endofcommand;
+
+#define CHECK_BYTE_COUNT(len)  \
+       if (bc < len) goto endofcommand;
+
+#define COUNT_BYTES(len)       \
+       offset += len;          \
+       bc -= len;
+
+#define END_OF_SMB     \
+       if (bc != 0) { \
+               proto_tree_add_text(tree, tvb, offset, bc, \
+                   "Extra byte parameters");           \
+               offset += bc;                           \
+       }                                               \
+       endofcommand:
 
 /*
- * Struct passed to each SMB decode routine of info it may need
+ * Macros for use in routines called by them.
+ */
+#define CHECK_BYTE_COUNT_SUBR(len)     \
+       if (*bcp < len) {               \
+               *trunc = TRUE;          \
+               return offset;          \
+       }
+
+#define CHECK_STRING_SUBR(fn)  \
+       if (fn == NULL) {       \
+               *trunc = TRUE;  \
+               return offset;  \
+       }
+
+#define COUNT_BYTES_SUBR(len)  \
+       offset += len;          \
+       *bcp -= len;
+
+/*
+ * Macros for use when dissecting transaction parameters and data
+ */
+#define CHECK_BYTE_COUNT_TRANS(len)    \
+       if (bc < len) return offset;
+
+#define CHECK_STRING_TRANS(fn) \
+       if (fn == NULL) return offset;
+
+#define COUNT_BYTES_TRANS(len) \
+       offset += len;          \
+       bc -= len;
+
+/*
+ * Macros for use in subrroutines dissecting transaction parameters or data
+ */
+#define CHECK_BYTE_COUNT_TRANS_SUBR(len)       \
+       if (*bcp < len) return offset;
+
+#define CHECK_STRING_TRANS_SUBR(fn)    \
+       if (fn == NULL) return offset;
+
+#define COUNT_BYTES_TRANS_SUBR(len)    \
+       offset += len;                  \
+       *bcp -= len;
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   These variables and functions are used to match
+   responses with calls
+   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+static GMemChunk *smb_info_chunk = NULL;
+static int smb_info_init_count = 200;
+static GHashTable *smb_info_table = NULL;
+
+/*
+ * XXX - MID/PID/UID/TID/command/source/destination are *NOT* unique;
+ * I have at least one capture with multiple Transaction2 SMB exchanges
+ * in a row, all with the *same* MID, PID, UID, and TID, and all between
+ * the *same* machines on the *same* connection.  The MID is merely
+ * intended to distinguish between replies to multiple *in-flight*
+ * requests; once the reply comes back, an SMB client can reused the
+ * MID of the request, and, apparently, some clients *do*.
+ *
+ * To make this work correctly, you have to include the frame number
+ * of the matching packet in the hash key, just as is done for the
+ * transaction hash table.
  */
+static gint
+smb_info_equal(gconstpointer k1, gconstpointer k2)
+{
+       smb_info_t *key1 = (smb_info_t *)k1;
+       smb_info_t *key2 = (smb_info_t *)k2;
+       gint res;
+
+       /* make sure to always compare mid first since this is most
+          likely to differ ==> shortcircuiting the expression */
+       res= (  (key1->mid==key2->mid)
+               &&      (key1->pid==key2->pid)
+               &&      (key1->uid==key2->uid)
+               &&      (key1->cmd==key2->cmd)
+               &&      (key1->tid==key2->tid)
+               &&      (ADDRESSES_EQUAL(key1->src, key2->src))
+               &&      (ADDRESSES_EQUAL(key1->dst, key2->dst)) );
+
+       return res;
+}
+
+static guint
+smb_info_hash(gconstpointer k)
+{
+       smb_info_t *key = (smb_info_t *)k;
+
+       /* multiplex id is very likely to differ between calls
+          it should be sufficient for a good distribution of hash
+          values.
+       */
+       return key->mid;
+}
+static gboolean
+free_all_smb_info(gpointer key_arg, gpointer value, gpointer user_data)
+{
+       smb_info_t *key = (smb_info_t *)key_arg;
+
+       if((key->src)&&(key->src->data)){
+               g_free((gpointer)key->src->data);
+               key->src->data = NULL;
+               g_free((gpointer)key->src);
+               key->src = NULL;
+       }
 
-char *decode_smb_name(unsigned char);
+       if((key->dst)&&(key->dst->data)){
+               g_free((gpointer)key->dst->data);
+               key->dst->data = NULL;
+               g_free((gpointer)key->dst);
+               key->dst = NULL;
+       }
+       return TRUE;
+}
 
 int smb_packet_init_count = 200;
 
@@ -493,9826 +1127,10500 @@ do_continuation_hashing(conversation_t *conversation, struct smb_info si,
   return continuation_val;
 }
 
-static void
-smb_init_protocol(void)
-{
-#if defined(DEBUG_SMB_HASH)
-  printf("Initializing SMB hashtable area\n");
-#endif
-
-  if (smb_request_hash) {
-    /*
-     * Remove all entries from the hash table and free all strings
-     * attached to the keys and values.  (The keys and values
-     * themselves are freed with "g_mem_chunk_destroy()" calls
-     * below.)
-     */
-    g_hash_table_foreach_remove(smb_request_hash, free_request_val_data, NULL);
-    g_hash_table_destroy(smb_request_hash);
-  }
-  if (smb_continuation_hash)
-    g_hash_table_destroy(smb_continuation_hash);
-  if (smb_request_keys)
-    g_mem_chunk_destroy(smb_request_keys);
-  if (smb_request_vals)
-    g_mem_chunk_destroy(smb_request_vals);
-  if (smb_continuation_vals)
-    g_mem_chunk_destroy(smb_continuation_vals);
-
-  smb_request_hash = g_hash_table_new(smb_hash, smb_equal);
-  smb_continuation_hash = g_hash_table_new(smb_hash, smb_equal);
-  smb_request_keys = g_mem_chunk_new("smb_request_keys",
-                                    sizeof(struct smb_request_key),
-                                    smb_packet_init_count * sizeof(struct smb_request_key), G_ALLOC_AND_FREE);
-  smb_request_vals = g_mem_chunk_new("smb_request_vals",
-                                    sizeof(struct smb_request_val),
-                                    smb_packet_init_count * sizeof(struct smb_request_val), G_ALLOC_AND_FREE);
-  smb_continuation_vals = g_mem_chunk_new("smb_continuation_vals",
-                                    sizeof(struct smb_continuation_val),
-                                    smb_packet_init_count * sizeof(struct smb_continuation_val), G_ALLOC_AND_FREE);
-}
-
-static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info si, int, int);
-
-static const value_string smb_cmd_vals[] = {
-  { 0x00, "SMBcreatedirectory" },
-  { 0x01, "SMBdeletedirectory" },
-  { 0x02, "SMBopen" },
-  { 0x03, "SMBcreate" },
-  { 0x04, "SMBclose" },
-  { 0x05, "SMBflush" },
-  { 0x06, "SMBunlink" },
-  { 0x07, "SMBmv" },
-  { 0x08, "SMBgetatr" },
-  { 0x09, "SMBsetatr" },
-  { 0x0A, "SMBread" },
-  { 0x0B, "SMBwrite" },
-  { 0x0C, "SMBlock" },
-  { 0x0D, "SMBunlock" },
-  { 0x0E, "SMBctemp" },
-  { 0x0F, "SMBmknew" },
-  { 0x10, "SMBchkpth" },
-  { 0x11, "SMBexit" },
-  { 0x12, "SMBlseek" },
-  { 0x13, "SMBlockread" },
-  { 0x14, "SMBwriteunlock" },
-  { 0x1A, "SMBreadBraw" },
-  { 0x1B, "SMBreadBmpx" },
-  { 0x1C, "SMBreadBs" },
-  { 0x1D, "SMBwriteBraw" },
-  { 0x1E, "SMBwriteBmpx" },
-  { 0x1F, "SMBwriteBs" },
-  { 0x20, "SMBwriteC" },
-  { 0x22, "SMBsetattrE" },
-  { 0x23, "SMBgetattrE" },
-  { 0x24, "SMBlockingX" },
-  { 0x25, "SMBtrans" },
-  { 0x26, "SMBtranss" },
-  { 0x27, "SMBioctl" },
-  { 0x28, "SMBioctls" },
-  { 0x29, "SMBcopy" },
-  { 0x2A, "SMBmove" },
-  { 0x2B, "SMBecho" },
-  { 0x2C, "SMBwriteclose" },
-  { 0x2D, "SMBopenX" },
-  { 0x2E, "SMBreadX" },
-  { 0x2F, "SMBwriteX" },
-  { 0x31, "SMBcloseandtreedisc" },
-  { 0x32, "SMBtrans2" },
-  { 0x33, "SMBtrans2secondary" },
-  { 0x34, "SMBfindclose2" },
-  { 0x35, "SMBfindnotifyclose" },
-  { 0x70, "SMBtcon" },
-  { 0x71, "SMBtdis" },
-  { 0x72, "SMBnegprot" },
-  { 0x73, "SMBsesssetupX" },
-  { 0x74, "SMBlogoffX" },
-  { 0x75, "SMBtconX" },
-  { 0x80, "SMBdskattr" },
-  { 0x81, "SMBsearch" },
-  { 0x82, "SMBffirst" },
-  { 0x83, "SMBfunique" },
-  { 0x84, "SMBfclose" },
-  { 0xA0, "SMBnttransact" },
-  { 0xA1, "SMBnttransactsecondary" },
-  { 0xA2, "SMBntcreateX" },
-  { 0xA4, "SMBntcancel" },
-  { 0xC0, "SMBsplopen" },
-  { 0xC1, "SMBsplwr" },
-  { 0xC2, "SMBsplclose" },
-  { 0xC3, "SMBsplretq" },
-  { 0xD0, "SMBsends" },
-  { 0xD1, "SMBsendb" },
-  { 0xD2, "SMBfwdname" },
-  { 0xD3, "SMBcancelf" },
-  { 0xD4, "SMBgetmac" },
-  { 0xD5, "SMBsendstrt" },
-  { 0xD6, "SMBsendend" },
-  { 0xD7, "SMBsendtxt" },
-  { 0xD8, "SMBreadbulk" },
-  { 0xD9, "SMBwritebulk" },
-  { 0xDA, "SMBwritebulkdata" },
-  { 0xFE, "SMBinvalid" },
-  { 0x00, NULL },
-};
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   End of request/response matching functions
+   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-char *SMB_names[256] = {
-  "SMBcreatedirectory",
-  "SMBdeletedirectory",
-  "SMBopen",
-  "SMBcreate",
-  "SMBclose",
-  "SMBflush",
-  "SMBunlink",
-  "SMBmv",
-  "SMBgetatr",
-  "SMBsetatr",
-  "SMBread",
-  "SMBwrite",
-  "SMBlock",
-  "SMBunlock",
-  "SMBctemp",
-  "SMBmknew",
-  "SMBchkpth",
-  "SMBexit",
-  "SMBlseek",
-  "SMBlockread",
-  "SMBwriteunlock",
-  "unknown-0x15",
-  "unknown-0x16",
-  "unknown-0x17",
-  "unknown-0x18",
-  "unknown-0x19",
-  "SMBreadBraw",
-  "SMBreadBmpx",
-  "SMBreadBs",
-  "SMBwriteBraw",
-  "SMBwriteBmpx",
-  "SMBwriteBs",
-  "SMBwriteC",
-  "unknown-0x21",
-  "SMBsetattrE",
-  "SMBgetattrE",
-  "SMBlockingX",
-  "SMBtrans",
-  "SMBtranss",
-  "SMBioctl",
-  "SMBioctls",
-  "SMBcopy",
-  "SMBmove",
-  "SMBecho",
-  "SMBwriteclose",
-  "SMBopenX",
-  "SMBreadX",
-  "SMBwriteX",
-  "unknown-0x30",
-  "SMBcloseandtreedisc",
-  "SMBtrans2",
-  "SMBtrans2secondary",
-  "SMBfindclose2",
-  "SMBfindnotifyclose",
-  "unknown-0x36",
-  "unknown-0x37",
-  "unknown-0x38",
-  "unknown-0x39",
-  "unknown-0x3A",
-  "unknown-0x3B",
-  "unknown-0x3C",
-  "unknown-0x3D",
-  "unknown-0x3E",
-  "unknown-0x3F",
-  "unknown-0x40",
-  "unknown-0x41",
-  "unknown-0x42",
-  "unknown-0x43",
-  "unknown-0x44",
-  "unknown-0x45",
-  "unknown-0x46",
-  "unknown-0x47",
-  "unknown-0x48",
-  "unknown-0x49",
-  "unknown-0x4A",
-  "unknown-0x4B",
-  "unknown-0x4C",
-  "unknown-0x4D",
-  "unknown-0x4E",
-  "unknown-0x4F",
-  "unknown-0x50",
-  "unknown-0x51",
-  "unknown-0x52",
-  "unknown-0x53",
-  "unknown-0x54",
-  "unknown-0x55",
-  "unknown-0x56",
-  "unknown-0x57",
-  "unknown-0x58",
-  "unknown-0x59",
-  "unknown-0x5A",
-  "unknown-0x5B",
-  "unknown-0x5C",
-  "unknown-0x5D",
-  "unknown-0x5E",
-  "unknown-0x5F",
-  "unknown-0x60",
-  "unknown-0x61",
-  "unknown-0x62",
-  "unknown-0x63",
-  "unknown-0x64",
-  "unknown-0x65",
-  "unknown-0x66",
-  "unknown-0x67",
-  "unknown-0x68",
-  "unknown-0x69",
-  "unknown-0x6A",
-  "unknown-0x6B",
-  "unknown-0x6C",
-  "unknown-0x6D",
-  "unknown-0x6E",
-  "unknown-0x6F",
-  "SMBtcon",
-  "SMBtdis",
-  "SMBnegprot",
-  "SMBsesssetupX",
-  "SMBlogoffX",
-  "SMBtconX",
-  "unknown-0x76",
-  "unknown-0x77",
-  "unknown-0x78",
-  "unknown-0x79",
-  "unknown-0x7A",
-  "unknown-0x7B",
-  "unknown-0x7C",
-  "unknown-0x7D",
-  "unknown-0x7E",
-  "unknown-0x7F",
-  "SMBdskattr",
-  "SMBsearch",
-  "SMBffirst",
-  "SMBfunique",
-  "SMBfclose",
-  "unknown-0x85",
-  "unknown-0x86",
-  "unknown-0x87",
-  "unknown-0x88",
-  "unknown-0x89",
-  "unknown-0x8A",
-  "unknown-0x8B",
-  "unknown-0x8C",
-  "unknown-0x8D",
-  "unknown-0x8E",
-  "unknown-0x8F",
-  "unknown-0x90",
-  "unknown-0x91",
-  "unknown-0x92",
-  "unknown-0x93",
-  "unknown-0x94",
-  "unknown-0x95",
-  "unknown-0x96",
-  "unknown-0x97",
-  "unknown-0x98",
-  "unknown-0x99",
-  "unknown-0x9A",
-  "unknown-0x9B",
-  "unknown-0x9C",
-  "unknown-0x9D",
-  "unknown-0x9E",
-  "unknown-0x9F",
-  "SMBnttransact",
-  "SMBnttransactsecondary",
-  "SMBntcreateX",
-  "unknown-0xA3",
-  "SMBntcancel",
-  "unknown-0xA5",
-  "unknown-0xA6",
-  "unknown-0xA7",
-  "unknown-0xA8",
-  "unknown-0xA9",
-  "unknown-0xAA",
-  "unknown-0xAB",
-  "unknown-0xAC",
-  "unknown-0xAD",
-  "unknown-0xAE",
-  "unknown-0xAF",
-  "unknown-0xB0",
-  "unknown-0xB1",
-  "unknown-0xB2",
-  "unknown-0xB3",
-  "unknown-0xB4",
-  "unknown-0xB5",
-  "unknown-0xB6",
-  "unknown-0xB7",
-  "unknown-0xB8",
-  "unknown-0xB9",
-  "unknown-0xBA",
-  "unknown-0xBB",
-  "unknown-0xBC",
-  "unknown-0xBD",
-  "unknown-0xBE",
-  "unknown-0xBF",
-  "SMBsplopen",
-  "SMBsplwr",
-  "SMBsplclose",
-  "SMBsplretq",
-  "unknown-0xC4",
-  "unknown-0xC5",
-  "unknown-0xC6",
-  "unknown-0xC7",
-  "unknown-0xC8",
-  "unknown-0xC9",
-  "unknown-0xCA",
-  "unknown-0xCB",
-  "unknown-0xCC",
-  "unknown-0xCD",
-  "unknown-0xCE",
-  "unknown-0xCF",
-  "SMBsends",
-  "SMBsendb",
-  "SMBfwdname",
-  "SMBcancelf",
-  "SMBgetmac",
-  "SMBsendstrt",
-  "SMBsendend",
-  "SMBsendtxt",
-  "SMBreadbulk",
-  "SMBwritebulk",
-  "SMBwritebulkdata",
-  "unknown-0xDB",
-  "unknown-0xDC",
-  "unknown-0xDD",
-  "unknown-0xDE",
-  "unknown-0xDF",
-  "unknown-0xE0",
-  "unknown-0xE1",
-  "unknown-0xE2",
-  "unknown-0xE3",
-  "unknown-0xE4",
-  "unknown-0xE5",
-  "unknown-0xE6",
-  "unknown-0xE7",
-  "unknown-0xE8",
-  "unknown-0xE9",
-  "unknown-0xEA",
-  "unknown-0xEB",
-  "unknown-0xEC",
-  "unknown-0xED",
-  "unknown-0xEE",
-  "unknown-0xEF",
-  "unknown-0xF0",
-  "unknown-0xF1",
-  "unknown-0xF2",
-  "unknown-0xF3",
-  "unknown-0xF4",
-  "unknown-0xF5",
-  "unknown-0xF6",
-  "unknown-0xF7",
-  "unknown-0xF8",
-  "unknown-0xF9",
-  "unknown-0xFA",
-  "unknown-0xFB",
-  "unknown-0xFC",
-  "unknown-0xFD",
-  "SMBinvalid",
-  "unknown-0xFF"
+static const value_string buffer_format_vals[] = {
+       {1,     "Data Block"},
+       {2,     "Dialect"},
+       {3,     "Pathname"},
+       {4,     "ASCII"},
+       {5,     "Variable Block"},
+       {0,     NULL}
 };
 
-void 
-dissect_unknown_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-{
-
-  if (tree) {
-
-    proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (%u bytes)", 
-                       END_OF_FRAME); 
-
-  }
-
-}
-
-/* 
- * Dissect a UNIX like date ...
+/*
+ * UTIME - this is *almost* like a UNIX time stamp, except that it's
+ * in seconds since January 1, 1970, 00:00:00 *local* time, not since
+ * January 1, 1970, 00:00:00 GMT.
+ *
+ * This means we have to do some extra work to convert it.  This code is
+ * based on the Samba code:
+ *
+ *     Unix SMB/Netbios implementation.
+ *     Version 1.9.
+ *     time handling functions
+ *     Copyright (C) Andrew Tridgell 1992-1998
  */
 
-struct tm *_gtime; /* Add leading underscore ("_") to prevent symbol
-                      conflict with /usr/include/time.h on some NetBSD
-                      systems */
-
-static char *
-dissect_smbu_date(guint16 date, guint16 time)
+/*
+ * Yield the difference between *A and *B, in seconds, ignoring leap
+ * seconds.
+ */
+#define TM_YEAR_BASE 1900
 
+static int
+tm_diff(struct tm *a, struct tm *b)
 {
-  static char         datebuf[4+2+2+2+1+10];
-  time_t              ltime = (date << 16) + time;
-
-  _gtime = gmtime(&ltime);
-
-  if (_gtime)
-    sprintf(datebuf, "%04d-%02d-%02d",
-           1900 + (_gtime -> tm_year), 1 + (_gtime -> tm_mon), _gtime -> tm_mday);
-  else 
-    sprintf(datebuf, "Bad date format");
-
-  return datebuf;
-
+       int ay = a->tm_year + (TM_YEAR_BASE - 1);
+       int by = b->tm_year + (TM_YEAR_BASE - 1);
+       int intervening_leap_days =
+           (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
+       int years = ay - by;
+       int days =
+           365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
+       int hours = 24*days + (a->tm_hour - b->tm_hour);
+       int minutes = 60*hours + (a->tm_min - b->tm_min);
+       int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
+
+       return seconds;
 }
 
 /*
- * Relies on time
+ * Return the UTC offset in seconds west of UTC, or 0 if it cannot be
+ * determined.
  */
-static char *
-dissect_smbu_time(guint16 date, guint16 time)
-
+static int
+TimeZone(time_t t)
 {
-  static char timebuf[2+2+2+2+1+10];
-
-  if (_gtime)
-    sprintf(timebuf, "%02d:%02d:%02d",
-           _gtime -> tm_hour, _gtime -> tm_min, _gtime -> tm_sec);
-  else
-    sprintf(timebuf, "Bad time format");
-
-  return timebuf;
-
+       struct tm *tm = gmtime(&t);
+       struct tm tm_utc;
+
+       if (tm == NULL)
+               return 0;
+       tm_utc = *tm;
+       tm = localtime(&t);
+       if (tm == NULL)
+               return 0;
+       return tm_diff(&tm_utc,tm);
 }
 
 /*
- * Dissect a DOS-format date.
+ * Return the same value as TimeZone, but it should be more efficient.
+ *
+ * We keep a table of DST offsets to prevent calling localtime() on each 
+ * call of this function. This saves a LOT of time on many unixes.
+ *
+ * Updated by Paul Eggert <eggert@twinsun.com>
  */
-static char *
-dissect_dos_date(guint16 date)
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef TIME_T_MIN
+#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
+                   : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
+#endif
+#ifndef TIME_T_MAX
+#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
+#endif
+
+static int
+TimeZoneFaster(time_t t)
 {
-       static char datebuf[4+2+2+1];
+       static struct dst_table {time_t start,end; int zone;} *tdt;
+       static struct dst_table *dst_table = NULL;
+       static int table_size = 0;
+       int i;
+       int zone = 0;
+
+       if (t == 0)
+               t = time(NULL);
+
+       /* Tunis has a 8 day DST region, we need to be careful ... */
+#define MAX_DST_WIDTH (365*24*60*60)
+#define MAX_DST_SKIP (7*24*60*60)
+
+       for (i = 0; i < table_size; i++) {
+               if (t >= dst_table[i].start && t <= dst_table[i].end)
+                       break;
+       }
 
-       sprintf(datebuf, "%04d-%02d-%02d",
-           ((date>>9)&0x7F) + 1980, (date>>5)&0x0F, date&0x1F);
-       return datebuf;
+       if (i < table_size) {
+               zone = dst_table[i].zone;
+       } else {
+               time_t low,high;
+
+               zone = TimeZone(t);
+               if (dst_table == NULL)
+                       tdt = g_malloc(sizeof(dst_table[0])*(i+1));
+               else
+                       tdt = g_realloc(dst_table, sizeof(dst_table[0])*(i+1));
+               if (tdt == NULL) {
+                       if (dst_table)
+                               free(dst_table);
+                       table_size = 0;
+               } else {
+                       dst_table = tdt;
+                       table_size++;
+    
+                       dst_table[i].zone = zone; 
+                       dst_table[i].start = dst_table[i].end = t;
+    
+                       /* no entry will cover more than 6 months */
+                       low = t - MAX_DST_WIDTH/2;
+                       if (t < low)
+                               low = TIME_T_MIN;
+      
+                       high = t + MAX_DST_WIDTH/2;
+                       if (high < t)
+                               high = TIME_T_MAX;
+      
+                       /*
+                        * Widen the new entry using two bisection searches.
+                        */
+                       while (low+60*60 < dst_table[i].start) {
+                               if (dst_table[i].start - low > MAX_DST_SKIP*2)
+                                       t = dst_table[i].start - MAX_DST_SKIP;
+                               else
+                                       t = low + (dst_table[i].start-low)/2;
+                               if (TimeZone(t) == zone)
+                                       dst_table[i].start = t;
+                               else
+                                       low = t;
+                       }
+
+                       while (high-60*60 > dst_table[i].end) {
+                               if (high - dst_table[i].end > MAX_DST_SKIP*2)
+                                       t = dst_table[i].end + MAX_DST_SKIP;
+                               else
+                                       t = high - (high-dst_table[i].end)/2;
+                               if (TimeZone(t) == zone)
+                                       dst_table[i].end = t;
+                               else
+                                       high = t;
+                       }
+               }
+       }
+       return zone;
 }
 
 /*
- * Dissect a DOS-format time.
+ * Return the UTC offset in seconds west of UTC, adjusted for extra time
+ * offset, for a local time value.  If ut = lt + LocTimeDiff(lt), then
+ * lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
+ * daylight savings transitions because some local times are ambiguous.
+ * LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
  */
-static char *
-dissect_dos_time(guint16 time)
+static int
+LocTimeDiff(time_t lt)
 {
-       static char timebuf[2+2+2+1];
+       int d = TimeZoneFaster(lt);
+       time_t t = lt + d;
 
-       sprintf(timebuf, "%02d:%02d:%02d",
-           (time>>11)&0x1F, (time>>5)&0x3F, (time&0x1F)*2);
-       return timebuf;
+       /* if overflow occurred, ignore all the adjustments so far */
+       if (((t < lt) ^ (d < 0)))
+               t = lt;
+
+       /*
+        * Now t should be close enough to the true UTC to yield the
+        * right answer.
+        */
+       return TimeZoneFaster(t);
 }
 
-/* Max string length for displaying Unicode strings.  */
-#define        MAX_UNICODE_STR_LEN     256
+static int
+dissect_smb_UTIME(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int hf_date)
+{
+       guint32 timeval;
+       nstime_t ts;
+       timeval = tvb_get_letohl(tvb, offset);
+       if (timeval == 0xffffffff) {
+               proto_tree_add_text(tree, tvb, offset, 4,
+                   "%s: No time specified (0xffffffff)",
+                   proto_registrar_get_name(hf_date));
+               offset += 4;
+               return offset;
+       }
 
-/* Turn a little-endian Unicode '\0'-terminated string into a string we
-   can display.
-   XXX - for now, we just handle the ISO 8859-1 characters. */
-static gchar *
-unicode_to_str(const guint8 *us, int *us_lenp) {
-  static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
-  static gchar *cur;
-  gchar        *p;
-  int           len;
-  int           us_len;
-  int           overflow = 0;
+       /*
+        * We add the local time offset.
+        */
+       ts.secs = timeval + LocTimeDiff(timeval);
+       ts.nsecs = 0;
 
-  if (cur == &str[0][0]) {
-    cur = &str[1][0];
-  } else if (cur == &str[1][0]) {  
-    cur = &str[2][0];
-  } else {  
-    cur = &str[0][0];
-  }
-  p = cur;
-  len = MAX_UNICODE_STR_LEN;
-  us_len = 0;
-  while (*us != 0 || *(us + 1) != 0) {
-    if (len > 0) {
-      *p++ = *us;
-      len--;
-    } else
-      overflow = 1;
-    us += 2;
-    us_len += 2;
-  }
-  if (overflow) {
-    /* Note that we're not showing the full string.  */
-    *p++ = '.';
-    *p++ = '.';
-    *p++ = '.';
-  }
-  *p = '\0';
-  *us_lenp = us_len;
-  return cur;
+       proto_tree_add_time(tree, hf_date, tvb, offset, 4, &ts);
+       offset += 4;
+       return offset;
 }
 
-/* Get a null terminated string, which is Unicode if "is_unicode" is true
-   and ASCII (OEM character set) otherwise.
-   XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
-static const gchar *
-get_unicode_or_ascii_string(const u_char *pd, int *offsetp, int SMB_offset,
-    gboolean is_unicode, int *len)
+static int
+dissect_smb_64bit_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, char *str, int hf_date)
 {
-  int offset = *offsetp;
-  const gchar *string;
-  int string_len;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       nstime_t tv;
 
-  if (is_unicode) {
-    if ((offset - SMB_offset) % 2) {
-      /*
-       * XXX - this should be an offset relative to the beginning of the SMB,
-       * not an offset relative to the beginning of the frame; if the stuff
-       * before the SMB has an odd number of bytes, an offset relative to
-       * the beginning of the frame will give the wrong answer.
-       */
-      offset++;   /* Looks like a pad byte there sometimes */
-      *offsetp = offset;
-    }
-    string = unicode_to_str(pd + offset, &string_len);
-    string_len += 2;
-  } else {
-    string = pd + offset;
-    string_len = strlen(string) + 1;
-  }
-  *len = string_len;
-  return string;
-}
+       /* XXXX we need some way to represent this as a time
+          properly. For now we display everything as 8 bytes*/
 
-static const value_string buffer_format_vals[] = {
-       { 1, "Data block" },
-       { 2, "Dialect" },
-       { 3, "Pathname" },
-       { 4, "ASCII" },
-       { 5, "Variable block" },
-       { 0, NULL }
-};
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 8,
+                       str);
+               tree = proto_item_add_subtree(item, ett_smb_64bit_time);
+       }
 
-/*
- * Each dissect routine is passed an offset to wct and works from there 
- */
+       proto_tree_add_bytes_format(tree, hf_smb_unknown, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8), "%s: can't decode this yet", str);
 
-void
-dissect_flush_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
+       offset += 8;
+       return offset;
+}
 
+static int
+dissect_smb_datetime(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, int hf_date, int hf_dos_date,
+    int hf_dos_time, gboolean time_first)
 {
-  guint8        WordCount;
-  guint16       FID;
-  guint16       ByteCount;
+       guint16 dos_time, dos_date;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       struct tm tm;
+       time_t t;
+       static const int mday_noleap[12] = {
+               31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+       };
+       static const int mday_leap[12] = {
+               31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+       };
+#define ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+       nstime_t tv;
 
-  if (si.request) {
-    /* Request(s) dissect code */
+       if (time_first) {
+               dos_time = tvb_get_letohs(tvb, offset);
+               dos_date = tvb_get_letohs(tvb, offset+2);
+       } else {
+               dos_date = tvb_get_letohs(tvb, offset);
+               dos_time = tvb_get_letohs(tvb, offset+2);
+       }
 
-    /* Build display for: Word Count (WCT) */
+       if ((dos_time == 0xffff && dos_time == 0xffff) ||
+           (dos_time == 0 && dos_time == 0)) {
+               /*
+                * No date/time specified.
+                */
+               if(parent_tree){
+                       proto_tree_add_text(parent_tree, tvb, offset, 4,
+                           "%s: No time specified (0x%08x)",
+                           proto_registrar_get_name(hf_date),
+                           (dos_date << 16) | dos_time);
+               }
+               offset += 4;
+               return offset;
+       }
 
-    WordCount = GBYTE(pd, offset);
+       tm.tm_sec = (dos_time&0x1f)*2;
+       tm.tm_min = (dos_time>>5)&0x3f;
+       tm.tm_hour = (dos_time>>11)&0x1f;
+       tm.tm_mday = dos_date&0x1f;
+       tm.tm_mon = ((dos_date>>5)&0x0f) - 1;
+       tm.tm_year = ((dos_date>>9)&0x7f) + 1980 - 1900;
+       tm.tm_isdst = -1;
 
-    if (tree) {
+       /*
+        * Do some sanity checks before calling "mktime()";
+        * "mktime()" doesn't do them, it "normalizes" out-of-range
+        * values.
+        */
+       if (tm.tm_sec > 59 || tm.tm_min > 59 || tm.tm_hour > 23 ||
+          tm.tm_mon < 0 || tm.tm_mon > 11 ||
+          (ISLEAP(tm.tm_year + 1900) ?
+            tm.tm_mday > mday_leap[tm.tm_mon] :
+            tm.tm_mday > mday_noleap[tm.tm_mon]) ||
+            (t = mktime(&tm)) == -1) {
+               /*
+                * Invalid date/time.
+                */
+               if (parent_tree) {
+                       item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                           "%s: Invalid time",
+                           proto_registrar_get_name(hf_date));
+                       tree = proto_item_add_subtree(item, ett_smb_time_date);
+                       if (time_first) {
+                               proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+                               proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+                       } else {
+                               proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+                               proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset+2, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+                       }
+               }
+               offset += 4;
+               return offset;
+       }
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       tv.secs = t;
+       tv.nsecs = 0;
+
+       if(parent_tree){
+               item = proto_tree_add_time(parent_tree, hf_date, tvb, offset, 4, &tv);
+               tree = proto_item_add_subtree(item, ett_smb_time_date);
+               if (time_first) {
+                       proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+                       proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+               } else {
+                       proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+                       proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset+2, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+               }
+       }
 
-    }
+       offset += 4;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       return offset;
+}
 
-    /* Build display for: FID */
 
-    FID = GSHORT(pd, offset);
+static const value_string da_access_vals[] = {
+       { 0,            "Open for reading"},
+       { 1,            "Open for writing"},
+       { 2,            "Open for reading and writing"},
+       { 3,            "Open for execute"},
+       {0, NULL}
+};
+static const value_string da_sharing_vals[] = {
+       { 0,            "Compatibility mode"},
+       { 1,            "Deny read/write/execute (exclusive)"},
+       { 2,            "Deny write"},
+       { 3,            "Deny read/execute"},
+       { 4,            "Deny none"},
+       {0, NULL}
+};
+static const value_string da_locality_vals[] = {
+       { 0,            "Locality of reference unknown"},
+       { 1,            "Mainly sequential access"},
+       { 2,            "Mainly random access"},
+       { 3,            "Random access with some locality"},
+       {0, NULL}
+};
+static const true_false_string tfs_da_caching = {
+       "Do not cache this file",
+       "Caching permitted on this file"
+};
+static const true_false_string tfs_da_writetru = {
+       "Write through enabled",
+       "Write through disabled"
+};
+static int
+dissect_access(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, char *type)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    if (tree) {
+       mask = tvb_get_letohs(tvb, offset);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "%s Access: 0x%04x", type, mask);
+               tree = proto_item_add_subtree(item, ett_smb_desiredaccess);
+       }
 
-    }
+       proto_tree_add_boolean(tree, hf_smb_access_writetru,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_access_caching,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_access_locality,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_access_sharing,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_access_mode,
+               tvb, offset, 2, mask);
 
-    offset += 2; /* Skip FID */
+       offset += 2;
 
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
+       return offset;
+}
 
-    if (tree) {
+#define FILE_ATTRIBUTE_READ_ONLY               0x00000001
+#define FILE_ATTRIBUTE_HIDDEN                  0x00000002
+#define FILE_ATTRIBUTE_SYSTEM                  0x00000004
+#define FILE_ATTRIBUTE_VOLUME                  0x00000008
+#define FILE_ATTRIBUTE_DIRECTORY               0x00000010
+#define FILE_ATTRIBUTE_ARCHIVE                 0x00000020
+#define FILE_ATTRIBUTE_DEVICE                  0x00000040
+#define FILE_ATTRIBUTE_NORMAL                  0x00000080
+#define FILE_ATTRIBUTE_TEMPORARY               0x00000100
+#define FILE_ATTRIBUTE_SPARSE                  0x00000200
+#define FILE_ATTRIBUTE_REPARSE                 0x00000400
+#define FILE_ATTRIBUTE_COMPRESSED              0x00000800
+#define FILE_ATTRIBUTE_OFFLINE                 0x00001000
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED     0x00002000
+#define FILE_ATTRIBUTE_ENCRYPTED               0x00004000
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+/*
+ * These are flags to be used in NT Create operations.
+ */
+#define FILE_ATTRIBUTE_WRITE_THROUGH           0x80000000
+#define FILE_ATTRIBUTE_NO_BUFFERING            0x20000000
+#define FILE_ATTRIBUTE_RANDOM_ACCESS           0x10000000
+#define FILE_ATTRIBUTE_SEQUENTIAL_SCAN         0x08000000
+#define FILE_ATTRIBUTE_DELETE_ON_CLOSE         0x04000000
+#define FILE_ATTRIBUTE_BACKUP_SEMANTICS                0x02000000
+#define FILE_ATTRIBUTE_POSIX_SEMANTICS         0x01000000
+
+static const true_false_string tfs_file_attribute_write_through = {
+       "This object requires WRITE THROUGH",
+       "This object does NOT require write through",
+};
+static const true_false_string tfs_file_attribute_no_buffering = {
+       "This object requires NO BUFFERING",
+       "This object can be buffered",
+};
+static const true_false_string tfs_file_attribute_random_access = {
+       "This object will be RANDOM ACCESSed",
+       "Random access is NOT requested",
+};
+static const true_false_string tfs_file_attribute_sequential_scan = {
+       "This object is optimized for SEQUENTIAL SCAN",
+       "This object is NOT optimized for sequential scan",
+};
+static const true_false_string tfs_file_attribute_delete_on_close = {
+       "This object will be DELETED ON CLOSE",
+       "This object will not be deleted on close",
+};
+static const true_false_string tfs_file_attribute_backup_semantics = {
+       "This object supports BACKUP SEMANTICS",
+       "This object does NOT support backup semantics",
+};
+static const true_false_string tfs_file_attribute_posix_semantics = {
+       "This object supports POSIX SEMANTICS",
+       "This object does NOT support POSIX semantics",
+};
+static const true_false_string tfs_file_attribute_read_only = {
+       "This file is READ ONLY",
+       "This file is NOT read only",
+};
+static const true_false_string tfs_file_attribute_hidden = {
+       "This is a HIDDEN file",
+       "This is NOT a hidden file"
+};
+static const true_false_string tfs_file_attribute_system = {
+       "This is a SYSTEM file",
+       "This is NOT a system file"
+};
+static const true_false_string tfs_file_attribute_volume = {
+       "This is a VOLUME ID",
+       "This is NOT a volume ID"
+};
+static const true_false_string tfs_file_attribute_directory = {
+       "This is a DIRECTORY",
+       "This is NOT a directory"
+};
+static const true_false_string tfs_file_attribute_archive = {
+       "This is an ARCHIVE file",
+       "This is NOT an archive file"
+};
+static const true_false_string tfs_file_attribute_device = {
+       "This is a DEVICE",
+       "This is NOT a device"
+};
+static const true_false_string tfs_file_attribute_normal = {
+       "This file is an ordinary file",
+       "This file has some attribute set"
+};
+static const true_false_string tfs_file_attribute_temporary = {
+       "This is a TEMPORARY file",
+       "This is NOT a temporary file"
+};
+static const true_false_string tfs_file_attribute_sparse = {
+       "This is a SPARSE file",
+       "This is NOT a sparse file"
+};
+static const true_false_string tfs_file_attribute_reparse = {
+       "This file has an associated REPARSE POINT",
+       "This file does NOT have an associated reparse point"
+};
+static const true_false_string tfs_file_attribute_compressed = {
+       "This is a COMPRESSED file",
+       "This is NOT a compressed file"
+};
+static const true_false_string tfs_file_attribute_offline = {
+       "This file is OFFLINE",
+       "This file is NOT offline"
+};
+static const true_false_string tfs_file_attribute_not_content_indexed = {
+       "This file MAY NOT be indexed by the CONTENT INDEXING service",
+       "This file MAY be indexed by the content indexing service"
+};
+static const true_false_string tfs_file_attribute_encrypted = {
+       "This is an ENCRYPTED file",
+       "This is NOT an encrypted file"
+};
 
-    }
+static int
+dissect_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    offset += 2; /* Skip Byte Count */
+       mask = tvb_get_letohs(tvb, offset);
 
-  } else {
-    /* Response(s) dissect code */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "File Attributes: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+       }
+       proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
+               tvb, offset, 2, mask);
 
-    /* Build display for: Word Count (WCT) */
+       offset += 2;
 
-    WordCount = GBYTE(pd, offset);
+       return offset;
+}
 
-    if (tree) {
+/* 3.11 */
+static int
+dissect_file_ext_attr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       mask = tvb_get_letohl(tvb, offset);
 
-    }
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "File Attributes: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+       }
 
-    offset += 1; /* Skip Word Count (WCT) */
+       /*
+        * XXX - Network Monitor disagrees on some of the
+        * bits, e.g. the bits above temporary are "atomic write"
+        * and "transaction write", and it says nothing about the
+        * bits above that.
+        *
+        * Does the Win32 API documentation, or the NT Native API book,
+        * suggest anything?
+        */
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_write_through,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_no_buffering,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_random_access,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_sequential_scan,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_delete_on_close,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_backup_semantics,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_posix_semantics,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_encrypted,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_not_content_indexed,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_offline,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_compressed,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_reparse,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_sparse,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_temporary,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_normal,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_device,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_archive,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_directory,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_volume,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_system,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_hidden,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_eattr_read_only,
+               tvb, offset, 4, mask);
+
+       offset += 4;
+
+       return offset;
+}
 
-    /* Build display for: Byte Count (BCC) */
+static int
+dissect_dir_info_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint8 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    ByteCount = GSHORT(pd, offset);
+       mask = tvb_get_guint8(tvb, offset);
 
-    if (tree) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+                       "File Attributes: 0x%02x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+       }
+       proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_8bit,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_8bit,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_system_8bit,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_volume_8bit,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_directory_8bit,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_archive_8bit,
+               tvb, offset, 1, mask);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       offset += 1;
 
-    }
+       return offset;
+}
 
-    offset += 2; /* Skip Byte Count (BCC) */
+static const true_false_string tfs_search_attribute_read_only = {
+       "Include READ ONLY files in search results",
+       "Do NOT include read only files in search results",
+};
+static const true_false_string tfs_search_attribute_hidden = {
+       "Include HIDDEN files in search results",
+       "Do NOT include hidden files in search results"
+};
+static const true_false_string tfs_search_attribute_system = {
+       "Include SYSTEM files in search results",
+       "Do NOT include system files in search results"
+};
+static const true_false_string tfs_search_attribute_volume = {
+       "Include VOLUME IDs in search results",
+       "Do NOT include volume IDs in search results"
+};
+static const true_false_string tfs_search_attribute_directory = {
+       "Include DIRECTORIES in search results",
+       "Do NOT include directories in search results"
+};
+static const true_false_string tfs_search_attribute_archive = {
+       "Include ARCHIVE files in search results",
+       "Do NOT include archive files in search results"
+};
 
-  }
+static int
+dissect_search_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-}
+       mask = tvb_get_letohs(tvb, offset);
 
-void
-dissect_get_disk_attr_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Search Attributes: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_search);
+       }
 
-{
-  guint8        WordCount;
-  guint16       TotalUnits;
-  guint16       Reserved;
-  guint16       FreeUnits;
-  guint16       ByteCount;
-  guint16       BlocksPerUnit;
-  guint16       BlockSize;
+       proto_tree_add_boolean(tree, hf_smb_search_attribute_read_only,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_search_attribute_hidden,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_search_attribute_system,
+               tvb, offset, 2, mask);  
+       proto_tree_add_boolean(tree, hf_smb_search_attribute_volume,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_search_attribute_directory,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_search_attribute_archive,
+               tvb, offset, 2, mask);
 
-  if (si.request) {
-    /* Request(s) dissect code */
+       offset += 2;
+       return offset;
+}
 
-    /* Build display for: Word Count (WCT) */
+#if 0
+/*
+ * XXX - this isn't used.
+ * Is this used for anything?  NT Create AndX doesn't use it.
+ * Is there some 16-bit attribute field with more bits than Read Only,
+ * Hidden, System, Volume ID, Directory, and Archive?
+ */
+static int
+dissect_extended_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    WordCount = GBYTE(pd, offset);
+       mask = tvb_get_letohl(tvb, offset);
 
-    if (tree) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "File Attributes: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+       }
+       proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_device,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_normal,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_temporary,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_sparse,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_reparse,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_compressed,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_offline,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_not_content_indexed,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_encrypted,
+               tvb, offset, 2, mask);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       offset += 2;
 
-    }
+       return offset;
+}
+#endif
 
-    offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Byte Count (BCC) */
+#define SERVER_CAP_RAW_MODE            0x00000001
+#define SERVER_CAP_MPX_MODE            0x00000002
+#define SERVER_CAP_UNICODE             0x00000004
+#define SERVER_CAP_LARGE_FILES         0x00000008
+#define SERVER_CAP_NT_SMBS             0x00000010
+#define SERVER_CAP_RPC_REMOTE_APIS     0x00000020
+#define SERVER_CAP_STATUS32            0x00000040
+#define SERVER_CAP_LEVEL_II_OPLOCKS    0x00000080
+#define SERVER_CAP_LOCK_AND_READ       0x00000100
+#define SERVER_CAP_NT_FIND             0x00000200
+#define SERVER_CAP_DFS                 0x00001000
+#define SERVER_CAP_INFOLEVEL_PASSTHRU  0x00002000
+#define SERVER_CAP_LARGE_READX         0x00004000
+#define SERVER_CAP_LARGE_WRITEX        0x00008000
+#define SERVER_CAP_UNIX                0x00800000
+#define SERVER_CAP_RESERVED            0x02000000
+#define SERVER_CAP_BULK_TRANSFER       0x20000000
+#define SERVER_CAP_COMPRESSED_DATA     0x40000000
+#define SERVER_CAP_EXTENDED_SECURITY   0x80000000
+static const true_false_string tfs_server_cap_raw_mode = {
+       "Read Raw and Write Raw are supported",
+       "Read Raw and Write Raw are not supported"
+};
+static const true_false_string tfs_server_cap_mpx_mode = {
+       "Read Mpx and Write Mpx are supported",
+       "Read Mpx and Write Mpx are not supported"
+};
+static const true_false_string tfs_server_cap_unicode = {
+       "Unicode strings are supported",
+       "Unicode strings are not supported"
+};
+static const true_false_string tfs_server_cap_large_files = {
+       "Large files are supported",
+       "Large files are not supported",
+};
+static const true_false_string tfs_server_cap_nt_smbs = {
+       "NT SMBs are supported",
+       "NT SMBs are not supported"
+};
+static const true_false_string tfs_server_cap_rpc_remote_apis = {
+       "RPC remote APIs are supported",
+       "RPC remote APIs are not supported"
+};
+static const true_false_string tfs_server_cap_nt_status = {
+       "NT status codes are supported",
+       "NT status codes are not supported"
+};
+static const true_false_string tfs_server_cap_level_ii_oplocks = {
+       "Level 2 oplocks are supported",
+       "Level 2 oplocks are not supported"
+};
+static const true_false_string tfs_server_cap_lock_and_read = {
+       "Lock and Read is supported",
+       "Lock and Read is not supported"
+};
+static const true_false_string tfs_server_cap_nt_find = {
+       "NT Find is supported",
+       "NT Find is not supported"
+};
+static const true_false_string tfs_server_cap_dfs = {
+       "Dfs is supported",
+       "Dfs is not supported"
+};
+static const true_false_string tfs_server_cap_infolevel_passthru = {
+       "NT information level request passthrough is supported",
+       "NT information level request passthrough is not supported"
+};
+static const true_false_string tfs_server_cap_large_readx = {
+       "Large Read andX is supported",
+       "Large Read andX is not supported"
+};
+static const true_false_string tfs_server_cap_large_writex = {
+       "Large Write andX is supported",
+       "Large Write andX is not supported"
+};
+static const true_false_string tfs_server_cap_unix = {
+       "UNIX extensions are supported",
+       "UNIX extensions are not supported"
+};
+static const true_false_string tfs_server_cap_reserved = {
+       "Reserved",
+       "Reserved"
+};
+static const true_false_string tfs_server_cap_bulk_transfer = {
+       "Bulk Read and Bulk Write are supported",
+       "Bulk Read and Bulk Write are not supported"
+};
+static const true_false_string tfs_server_cap_compressed_data = {
+       "Compressed data transfer is supported",
+       "Compressed data transfer is not supported"
+};
+static const true_false_string tfs_server_cap_extended_security = {
+       "Extended security exchanges are supported",
+       "Extended security exchanges are not supported"
+};
+static int
+dissect_negprot_capabilities(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    ByteCount = GSHORT(pd, offset);
+       mask = tvb_get_letohl(tvb, offset);
 
-    if (tree) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4, "Capabilities: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_capabilities);
+       }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_raw_mode,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_mpx_mode,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_unicode,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_large_files,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_nt_smbs,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_rpc_remote_apis,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_nt_status,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_level_ii_oplocks,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_lock_and_read,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_nt_find,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_dfs,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_infolevel_passthru,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_large_readx,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_large_writex,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_unix,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_reserved,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_bulk_transfer,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_compressed_data,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_server_cap_extended_security,
+               tvb, offset, 4, mask);
+
+       return mask;
+}
 
-    }
+#define RAWMODE_READ   0x01
+#define RAWMODE_WRITE  0x02
+static const true_false_string tfs_rm_read = {
+       "Read Raw is supported",
+       "Read Raw is not supported"
+};
+static const true_false_string tfs_rm_write = {
+       "Write Raw is supported",
+       "Write Raw is not supported"
+};
 
-    offset += 2; /* Skip Byte Count (BCC) */
+static int
+dissect_negprot_rawmode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-  } else {
-    /* Response(s) dissect code */
+       mask = tvb_get_letohs(tvb, offset);
 
-    /* Build display for: Word Count (WCT) */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2, "Raw Mode: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_rawmode);
+       }
 
-    WordCount = GBYTE(pd, offset);
+       proto_tree_add_boolean(tree, hf_smb_rm_read, tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_rm_write, tvb, offset, 2, mask);
 
-    if (tree) {
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       return offset;
+}
 
-    }
+#define SECURITY_MODE_MODE             0x01
+#define SECURITY_MODE_PASSWORD         0x02
+#define SECURITY_MODE_SIGNATURES       0x04
+#define SECURITY_MODE_SIG_REQUIRED     0x08
+static const true_false_string tfs_sm_mode = {
+       "USER security mode",
+       "SHARE security mode"
+};
+static const true_false_string tfs_sm_password = {
+       "ENCRYPTED password. Use challenge/response",
+       "PLAINTEXT password"
+};
+static const true_false_string tfs_sm_signatures = {
+       "Security signatures ENABLED",
+       "Security signatures NOT enabled"
+};
+static const true_false_string tfs_sm_sig_required = {
+       "Security signatures REQUIRED",
+       "Security signatures NOT required"
+};
 
-    offset += 1; /* Skip Word Count (WCT) */
+static int
+dissect_negprot_security_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int wc)
+{
+       guint16 mask = 0;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+
+       switch(wc){
+       case 13:
+               mask = tvb_get_letohs(tvb, offset);
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                               "Security Mode: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_mode);
+               proto_tree_add_boolean(tree, hf_smb_sm_mode16, tvb, offset, 2, mask);
+               proto_tree_add_boolean(tree, hf_smb_sm_password16, tvb, offset, 2, mask);
+               offset += 2;
+               break;
+
+       case 17:
+               mask = tvb_get_guint8(tvb, offset);
+               item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+                               "Security Mode: 0x%02x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_mode);
+               proto_tree_add_boolean(tree, hf_smb_sm_mode, tvb, offset, 1, mask);
+               proto_tree_add_boolean(tree, hf_smb_sm_password, tvb, offset, 1, mask);
+               proto_tree_add_boolean(tree, hf_smb_sm_signatures, tvb, offset, 1, mask);
+               proto_tree_add_boolean(tree, hf_smb_sm_sig_required, tvb, offset, 1, mask);
+               offset += 1;
+               break;
+       }
 
-    if (WordCount != 0) {
+       return offset;
+}
 
-      /* Build display for: Total Units */
+static int
+dissect_negprot_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       proto_item *it = NULL;
+       proto_tree *tr = NULL;
+       guint16 bc;
+       guint8 wc;
 
-      TotalUnits = GSHORT(pd, offset);
+       WORD_COUNT;
 
-      if (tree) {
+       BYTE_COUNT;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Total Units: %u", TotalUnits);
+       if(tree){
+               it = proto_tree_add_text(tree, tvb, offset, bc,
+                               "Requested Dialects");
+               tr = proto_item_add_subtree(it, ett_smb_dialects);
+       }
 
-      }
+       while(bc){
+               int len;
+               int old_offset = offset;
+               const guint8 *str;
+               proto_item *dit = NULL;
+               proto_tree *dtr = NULL;
+
+               /* XXX - what if this runs past bc? */
+               len = tvb_strsize(tvb, offset+1);
+               str = tvb_get_ptr(tvb, offset+1, len);
+
+               if(tr){
+                       dit = proto_tree_add_text(tr, tvb, offset, len+1,
+                                       "Dialect: %s", str);
+                       dtr = proto_item_add_subtree(dit, ett_smb_dialect);
+               }
+
+               /* Buffer Format */
+               CHECK_BYTE_COUNT(1);
+               proto_tree_add_item(dtr, hf_smb_buffer_format, tvb, offset, 1,
+                       TRUE);
+               COUNT_BYTES(1);
+
+               /*Dialect Name */
+               CHECK_BYTE_COUNT(len);
+               proto_tree_add_string(dtr, hf_smb_dialect_name, tvb, offset,
+                       len, str);
+               COUNT_BYTES(len);
+       }
 
-      offset += 2; /* Skip Total Units */
+       END_OF_SMB
 
-      /* Build display for: Blocks Per Unit */
+       return offset;
+}
 
-      BlocksPerUnit = GSHORT(pd, offset);
+static int
+dissect_negprot_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 dialect;
+       const char *dn;
+       int dn_len;
+       guint16 bc;
+       guint16 ekl=0;
+       guint32 caps=0;
+       gint16 tz;
+
+       WORD_COUNT;
+
+       /* Dialect Index */
+       dialect = tvb_get_letohs(tvb, offset);
+       switch(wc){
+       case 1:
+               if(dialect==0xffff){
+                       proto_tree_add_uint_format(tree, hf_smb_dialect_index,
+                               tvb, offset, 2, dialect,
+                               "Selected Index: -1, PC NETWORK PROGRAM 1.0 choosen");
+               } else {
+                       proto_tree_add_uint(tree, hf_smb_dialect_index,
+                               tvb, offset, 2, dialect);
+               }
+               break;
+       case 13:
+               proto_tree_add_uint_format(tree, hf_smb_dialect_index,
+                       tvb, offset, 2, dialect,
+                       "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", dialect);
+               break;
+       case 17:
+               proto_tree_add_uint_format(tree, hf_smb_dialect_index,
+                       tvb, offset, 2, dialect,
+                       "Dialect Index: %u, greater than LANMAN2.1", dialect);
+               break;
+       default:
+               proto_tree_add_text(tree, tvb, offset, wc*2,
+                       "Words for unknown response format");
+               offset += wc*2;
+               goto bytecount;
+       }
+       offset += 2;
 
-      if (tree) {
+       switch(wc){
+       case 13:
+               /* Security Mode */
+               offset = dissect_negprot_security_mode(tvb, pinfo, tree, offset,
+                               wc);
+
+               /* Maximum Transmit Buffer Size */
+               proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
+                       tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* Maximum Multiplex Count */
+               proto_tree_add_item(tree, hf_smb_max_mpx_count,
+                       tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* Maximum Vcs Number */
+               proto_tree_add_item(tree, hf_smb_max_vcs_num,
+                       tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* raw mode */
+               offset = dissect_negprot_rawmode(tvb, pinfo, tree, offset);
+
+               /* session key */
+               proto_tree_add_item(tree, hf_smb_session_key,
+                       tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* current time and date at server */
+               offset = dissect_smb_datetime(tvb, pinfo, tree, offset, hf_smb_server_date_time, hf_smb_server_smb_date, hf_smb_server_smb_time,
+                   TRUE);
+
+               /* time zone */
+               tz = tvb_get_letohs(tvb, offset);
+               proto_tree_add_int_format(tree, hf_smb_server_timezone, tvb, offset, 2, tz, "Server Time Zone: %d min from UTC", tz);
+               offset += 2;
+
+               /* encryption key length */
+               ekl = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_encryption_key_length, tvb, offset, 2, ekl);
+               offset += 2;
+
+               /* 2 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               break;
+
+       case 17:
+               /* Security Mode */
+               offset = dissect_negprot_security_mode(tvb, pinfo, tree, offset, wc);
+
+               /* Maximum Multiplex Count */
+               proto_tree_add_item(tree, hf_smb_max_mpx_count,
+                       tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* Maximum Vcs Number */
+               proto_tree_add_item(tree, hf_smb_max_vcs_num,
+                       tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* Maximum Transmit Buffer Size */
+               proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
+                       tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* maximum raw buffer size */
+               proto_tree_add_item(tree, hf_smb_max_raw_buf_size,
+                       tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* session key */
+               proto_tree_add_item(tree, hf_smb_session_key,
+                       tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* server capabilities */
+               caps = dissect_negprot_capabilities(tvb, pinfo, tree, offset);
+               offset += 4;
+
+               /* system time */
+               offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                               "System Time", hf_smb_system_time);
+
+               /* time zone */
+               tz = tvb_get_letohs(tvb, offset);
+               proto_tree_add_int_format(tree, hf_smb_server_timezone,
+                       tvb, offset, 2, tz,
+                       "Server Time Zone: %d min from UTC", tz);
+               offset += 2;
+
+               /* encryption key length */
+               ekl = tvb_get_guint8(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_encryption_key_length,
+                       tvb, offset, 1, ekl);
+               offset += 1;
+
+               break;
+       }
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Blocks Per Unit: %u", BlocksPerUnit);
+       BYTE_COUNT;
+
+       switch(wc){
+       case 13:
+               /* challenge/response encryption key */
+               if(ekl){
+                       CHECK_BYTE_COUNT(ekl);
+                       proto_tree_add_item(tree, hf_smb_encryption_key, tvb, offset, ekl, TRUE);
+                       COUNT_BYTES(ekl);
+               }
+
+               /* domain */
+               dn = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &dn_len, FALSE, FALSE, &bc);
+               if (dn == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+                       offset, dn_len,dn);
+               COUNT_BYTES(dn_len);
+               break;
+
+       case 17:
+               if(!(caps&SERVER_CAP_EXTENDED_SECURITY)){
+                       smb_info_t *si;
+
+                       /* challenge/response encryption key */
+                       /* XXX - is this aligned on an even boundary? */
+                       if(ekl){
+                               CHECK_BYTE_COUNT(ekl);
+                               proto_tree_add_item(tree, hf_smb_encryption_key,
+                                       tvb, offset, ekl, TRUE);
+                               COUNT_BYTES(ekl);
+                       }
+
+                       /* domain */
+                       /* this string is special, unicode is flagged in caps */
+                       /* This string is NOT padded to be 16bit aligned. (seen in actual capture) */
+                       si = pinfo->private_data;
+                       si->unicode = (caps&SERVER_CAP_UNICODE);
+                       dn = get_unicode_or_ascii_string_tvb(tvb,
+                               &offset, pinfo, &dn_len, TRUE, FALSE,
+                               &bc);
+                       if (dn == NULL)
+                               goto endofcommand;
+                       proto_tree_add_string(tree, hf_smb_primary_domain,
+                               tvb, offset, dn_len, dn);
+                       COUNT_BYTES(dn_len);
+               } else {
+                       int len;
+
+                       /* guid */
+                       /* XXX - show it in the standard Microsoft format
+                          for GUIDs? */
+                       CHECK_BYTE_COUNT(16);
+                       proto_tree_add_item(tree, hf_smb_server_guid,
+                               tvb, offset, 16, TRUE);
+                       COUNT_BYTES(16);
+
+                       /* security blob */
+                       /* XXX - is this ASN.1-encoded?  Is it a Kerberos
+                          data structure, at least in NT 5.0-and-later
+                          server replies? */
+                       if(bc){
+                               proto_tree_add_item(tree, hf_smb_security_blob,
+                                       tvb, offset, bc, TRUE);
+                               COUNT_BYTES(bc);
+                       }
+               }
+               break;
+       }
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip Blocks Per Unit */
+       return offset;
+}
 
-      /* Build display for: Block Size */
 
-      BlockSize = GSHORT(pd, offset);
+static int
+dissect_old_dir_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int dn_len;
+       const char *dn;
+       guint8 wc;
+       guint16 bc;
 
-      if (tree) {
+       WORD_COUNT;
+       BYTE_COUNT;
+
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+
+       /* dir name */
+       dn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &dn_len,
+               FALSE, FALSE, &bc);
+       if (dn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, dn_len,
+               dn);
+       COUNT_BYTES(dn_len);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Block Size: %u", BlockSize);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Directory: %s", dn);
+       }
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip Block Size */
+       return offset;
+}
 
-      /* Build display for: Free Units */
+static int
+dissect_empty(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
+       WORD_COUNT;
+       BYTE_COUNT;
 
-      FreeUnits = GSHORT(pd, offset);
+       END_OF_SMB
 
-      if (tree) {
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Free Units: %u", FreeUnits);
+static int
+dissect_echo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 ec, bc;
+       guint8 wc;
 
-      }
+       WORD_COUNT;
 
-      offset += 2; /* Skip Free Units */
+       /* echo count */
+       ec = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_echo_count, tvb, offset, 2, ec);
+       offset += 2;
 
-      /* Build display for: Reserved */
+       BYTE_COUNT;
 
-      Reserved = GSHORT(pd, offset);
+       if (bc != 0) {
+               /* echo data */
+               proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
+               COUNT_BYTES(bc);
+       }
 
-      if (tree) {
+       END_OF_SMB
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+       return offset;
+}
 
-      }
+static int
+dissect_echo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 bc;
+       guint8 wc;
 
-      offset += 2; /* Skip Reserved */
+       WORD_COUNT;
 
-    }
+       /* echo sequence number */
+       proto_tree_add_item(tree, hf_smb_echo_seq_num, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    /* Build display for: Byte Count (BCC) */
+       BYTE_COUNT;
 
-    ByteCount = GSHORT(pd, offset);
+       if (bc != 0) {
+               /* echo data */
+               proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
+               COUNT_BYTES(bc);
+       }
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       return offset;
+}
 
-    }
+static int
+dissect_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int an_len, pwlen;
+       const char *an;
+       guint8 wc;
+       guint16 bc;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       WORD_COUNT;
+       BYTE_COUNT;
+
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+
+       /* Path */
+       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+               pinfo, &an_len, FALSE, FALSE, &bc);
+       if (an == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_path, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
 
-  }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", an);
+       }
 
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+
+       /* password, ANSI */
+       /* XXX - what if this runs past bc? */
+       pwlen = tvb_strsize(tvb, offset);
+       CHECK_BYTE_COUNT(pwlen);
+       proto_tree_add_item(tree, hf_smb_password,
+               tvb, offset, pwlen, TRUE);
+       COUNT_BYTES(pwlen);
+
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+
+       /* Service */
+       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+               pinfo, &an_len, FALSE, FALSE, &bc);
+       if (an == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_service, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
+
+       END_OF_SMB
+
+       return offset;
 }
 
-void
-dissect_set_file_attr_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
+static int
+dissect_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  proto_tree    *Attributes_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        ByteCount;
-  guint8        BufferFormat;
-  guint16       Reserved5;
-  guint16       Reserved4;
-  guint16       Reserved3;
-  guint16       Reserved2;
-  guint16       Reserved1;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       Attributes;
-  const char    *FileName;
-  int           string_len;
+       guint8 wc;
+       guint16 bc;
 
-  if (si.request) {
-    /* Request(s) dissect code */
+       WORD_COUNT;
+       /* Maximum Buffer Size */
+       proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    /* Build display for: Word Count (WCT) */
+       /* tid */
+       proto_tree_add_item(tree, hf_smb_tid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    WordCount = GBYTE(pd, offset);
+       BYTE_COUNT;
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       return offset;
+}
 
-    }
+static const true_false_string tfs_of_create = {
+       "Create file if it does not exist",
+       "Fail if file does not exist"
+};
+static const value_string of_open[] = {
+       { 0,            "Fail if file exists"},
+       { 1,            "Open file if it exists"},
+       { 2,            "Truncate file if it exists"},
+       {0, NULL}
+};
+static int
+dissect_open_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       mask = tvb_get_letohs(tvb, offset);
 
-    if (WordCount != 0) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Open Function: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_openfunction);
+       }
 
-      /* Build display for: Attributes */
+       proto_tree_add_boolean(tree, hf_smb_open_function_create,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_open_function_open,
+               tvb, offset, 2, mask);
 
-      Attributes = GSHORT(pd, offset);
+       offset += 2;
 
-      if (tree) {
+       return offset;
+}
 
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Attributes: 0x%02x", Attributes);
-       Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
-       
-      }
 
-      offset += 2; /* Skip Attributes */
+static const true_false_string tfs_mf_file = {
+       "Target must be a file",
+       "Target needn't be a file"
+ };
+static const true_false_string tfs_mf_dir = {
+       "Target must be a directory",
+       "Target needn't be a directory"
+};
+static const true_false_string tfs_mf_verify = {
+       "MUST verify all writes",
+       "Don't have to verify writes"
+};
+static int
+dissect_move_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      /* Build display for: Last Write Time */
+       mask = tvb_get_letohs(tvb, offset);
 
-      LastWriteTime = GSHORT(pd, offset);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_move_flags);
+       }
+       proto_tree_add_boolean(tree, hf_smb_move_flags_verify,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_move_flags_dir,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_move_flags_file,
+               tvb, offset, 2, mask);
 
-      if (tree) {
+       offset += 2;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
+       return offset;
+}
 
-      }
+static int
+dissect_move_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       guint16 tid;
+       guint16 bc;
+       guint8 wc;
+       const char *fn;
 
-      offset += 2; /* Skip Last Write Time */
+       WORD_COUNT;
 
-      /* Build display for: Last Write Date */
+       /* tid */
+       tid = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
+               "TID (target): 0x%04x", tid);
+       offset += 2;
 
-      LastWriteDate = GSHORT(pd, offset);
+       /* open function */
+       offset = dissect_open_function(tvb, pinfo, tree, offset);
 
-      if (tree) {
+       /* move flags */
+       offset = dissect_move_flags(tvb, pinfo, tree, offset);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
+       BYTE_COUNT;
 
-      }
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      offset += 2; /* Skip Last Write Date */
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
+               fn_len, fn, "Old File Name: %s", fn);
+       COUNT_BYTES(fn_len);
 
-      /* Build display for: Reserved 1 */
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Old Name: %s", fn);
+       }
 
-      Reserved1 = GSHORT(pd, offset);
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      if (tree) {
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
+               fn_len, fn, "New File Name: %s", fn);
+       COUNT_BYTES(fn_len);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", New Name: %s", fn);
+       }
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip Reserved 1 */
+       return offset;
+}
 
-      /* Build display for: Reserved 2 */
+static int
+dissect_move_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-      Reserved2 = GSHORT(pd, offset);
+       WORD_COUNT;
 
-      if (tree) {
+       /* read count */
+       proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
+       BYTE_COUNT;
 
-      }
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      offset += 2; /* Skip Reserved 2 */
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-      /* Build display for: Reserved 3 */
+       END_OF_SMB
 
-      Reserved3 = GSHORT(pd, offset);
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
+       WORD_COUNT;
 
-      }
+       /* desired access */
+       offset = dissect_access(tvb, pinfo, tree, offset, "Desired");
 
-      offset += 2; /* Skip Reserved 3 */
+       /* Search Attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-      /* Build display for: Reserved 4 */
+       BYTE_COUNT;
 
-      Reserved4 = GSHORT(pd, offset);
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      if (tree) {
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 4: %u", Reserved4);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip Reserved 4 */
+       return offset;
+}
 
-      /* Build display for: Reserved 5 */
+static int
+dissect_open_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-      Reserved5 = GSHORT(pd, offset);
+       WORD_COUNT;
 
-      if (tree) {
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 5: %u", Reserved5);
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-      }
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
+       
+       /* File Size */
+       proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      offset += 2; /* Skip Reserved 5 */
+       /* granted access */
+       offset = dissect_access(tvb, pinfo, tree, offset, "Granted");
 
-    }
+       BYTE_COUNT;
 
-    /* Build display for: Byte Count (BCC) */
+       END_OF_SMB
 
-    ByteCount = GSHORT(pd, offset);
+       return offset;
+}
 
-    if (tree) {
+static int
+dissect_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       WORD_COUNT;
 
-    }
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       BYTE_COUNT;
 
-    /* Build display for: Buffer Format */
+       END_OF_SMB
 
-    BufferFormat = GBYTE(pd, offset);
+       return offset;
+}
 
-    if (tree) {
+static int
+dissect_create_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+       WORD_COUNT;
 
-    }
+       /* file attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-    offset += 1; /* Skip Buffer Format */
+       /* creation time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
 
-    /* Build display for: File Name */
+       BYTE_COUNT;
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    if (tree) {
+       /* File Name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-    }
+       END_OF_SMB
 
-    offset += string_len; /* Skip File Name */
+       return offset;
+}
 
-  } else {
-    /* Response(s) dissect code */
+static int
+dissect_close_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    /* Build display for: Word Count (WCT) */
+       WORD_COUNT;
 
-    WordCount = GBYTE(pd, offset);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       BYTE_COUNT;
 
-    }
+       END_OF_SMB
 
-    offset += 1; /* Skip Word Count (WCT) */
+       return offset;
+}
 
-    /* Build display for: Byte Count (BCC) */
+static int
+dissect_delete_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-    ByteCount = GBYTE(pd, offset);
+       WORD_COUNT;
 
-    if (tree) {
+       /* search attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Byte Count (BCC): %u", ByteCount);
+       BYTE_COUNT;
 
-    }
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    offset += 1; /* Skip Byte Count (BCC) */
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-  }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-}
+       END_OF_SMB
 
-void
-dissect_write_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
+       return offset;
+}
 
+static int
+dissect_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint32       Offset;
-  guint16       Remaining;
-  guint16       FID;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
+       WORD_COUNT;
 
-    /* Build display for: FID */
+       /* search attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-    FID = GSHORT(pd, offset);
+       BYTE_COUNT;
 
-    if (tree) {
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       /* old file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-    }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Old Name: %s", fn);
+       }
 
-    offset += 2; /* Skip FID */
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    /* Build display for: Count */
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-    Count = GSHORT(pd, offset);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", New Name: %s", fn);
+       }
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+       return offset;
+}
 
-    }
+static int
+dissect_query_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 bc;
+       guint8 wc;
+       const char *fn;
+       int fn_len;
 
-    offset += 2; /* Skip Count */
+       WORD_COUNT;
 
-    /* Build display for: Offset */
+       BYTE_COUNT;
 
-    Offset = GWORD(pd, offset);
+       /* Buffer Format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    if (tree) {
+       /* File Name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-    }
+       END_OF_SMB
 
-    offset += 4; /* Skip Offset */
+       return offset;
+}
+static int
+dissect_query_information_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 bc;
+       guint8 wc;
+       nstime_t ts;
 
-    /* Build display for: Remaining */
+       WORD_COUNT;
 
-    Remaining = GSHORT(pd, offset);
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-    if (tree) {
+       /* Last Write Time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+       /* File Size */
+       proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    }
+       /* 10 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+       offset += 10;
 
-    offset += 2; /* Skip Remaining */
+       BYTE_COUNT;
 
-    /* Build display for: Byte Count (BCC) */
+       END_OF_SMB
 
-    ByteCount = GSHORT(pd, offset);
+       return offset;
+}
 
-    if (tree) {
+static int
+dissect_set_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       WORD_COUNT;
 
-    }
+       /* file attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
 
-    /* Build display for: Buffer Format */
+       /* 10 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+       offset += 10;
 
-    BufferFormat = GBYTE(pd, offset);
+       BYTE_COUNT;
 
-    if (tree) {
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-    }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-    offset += 1; /* Skip Buffer Format */
+       END_OF_SMB
 
-    /* Build display for: Data Length */
+       return offset;
+}
 
-    DataLength = GSHORT(pd, offset);
+static int
+dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    if (tree) {
+       WORD_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* read count */
+       proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += 2; /* Skip Data Length */
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    if (DataLength > 0 && tree) {
+       /* remaining */
+       proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       if(END_OF_FRAME >= DataLength)
-           proto_tree_add_text(tree, NullTVB, offset, DataLength, "Data (%u bytes)", DataLength);
-       else
-           proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (first %u bytes)", END_OF_FRAME);
+       BYTE_COUNT;
 
-    }
+       END_OF_SMB
 
-  } else {
-    /* Response(s) dissect code */
+       return offset;
+}
 
-    /* Build display for: Word Count (WCT) */
+static int
+dissect_file_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 bc, guint16 datalen)
+{
+       int tvblen;
+
+       if(bc>datalen){
+               /* We have some initial padding bytes. */
+               /* XXX - use the data offset here instead? */
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
+                       TRUE);
+               offset += bc-datalen;
+               bc = datalen;
+       }
+       tvblen = tvb_length_remaining(tvb, offset);
+       if(bc>tvblen){
+               proto_tree_add_bytes_format(tree, hf_smb_file_data, tvb, offset, tvblen, tvb_get_ptr(tvb, offset, tvblen),"File Data: Incomplete. Only %d of %u bytes", tvblen, bc);
+               offset += tvblen;
+       } else {
+               proto_tree_add_item(tree, hf_smb_file_data, tvb, offset, bc, TRUE);
+               offset += bc;
+       }
+       return offset;
+}
 
-    WordCount = GBYTE(pd, offset);
+static int
+dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 cnt=0, bc;
+       guint8 wc;
 
-    if (tree) {
+       WORD_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       /* read count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-    }
+       /* 8 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
+       offset += 8;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       BYTE_COUNT;
 
-    /* Build display for: Count */
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    Count = GSHORT(pd, offset);
+       /* data len */
+       CHECK_BYTE_COUNT(2);
+       proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+       COUNT_BYTES(2);
 
-    if (tree) {
+       if (bc != 0) {
+               /* file data */
+               offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
+               bc = 0;
+       }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+       END_OF_SMB
 
-    }
+       return offset;
+}
 
-    offset += 2; /* Skip Count */
+static int
+dissect_lock_and_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 cnt, bc;
+       guint8 wc;
 
-    /* Build display for: Byte Count (BCC) */
+       WORD_COUNT;
 
-    ByteCount = GSHORT(pd, offset);
+       /* read count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-    if (tree) {
+       /* 8 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
+       offset += 8;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       BYTE_COUNT;
 
-    }
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* data len */
+       CHECK_BYTE_COUNT(2);
+       proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+       COUNT_BYTES(2);
 
-  }
+       END_OF_SMB
 
+       return offset;
 }
 
-void
-dissect_read_mpx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *arent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
 
+static int
+dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  guint8        WordCount;
-  guint8        Pad;
-  guint32       Reserved1;
-  guint32       Offset;
-  guint16       Reserved2;
-  guint16       Reserved;
-  guint16       MinCount;
-  guint16       MaxCount;
-  guint16       FID;
-  guint16       DataOffset;
-  guint16       DataLength;
-  guint16       DataCompactionMode;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
+       guint16 cnt=0, bc;
+       guint8 wc;
 
-    /* Build display for: Word Count (WCT) */
+       WORD_COUNT;
 
-    WordCount = GBYTE(pd, offset);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       /* write count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    }
+       /* remaining */
+       proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       BYTE_COUNT;
 
-    /* Build display for: FID */
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    FID = GSHORT(pd, offset);
+       /* data len */
+       CHECK_BYTE_COUNT(2);
+       proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+       COUNT_BYTES(2);
 
-    if (tree) {
+       if (bc != 0) {
+               /* file data */
+               offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
+               bc = 0;
+       }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       END_OF_SMB
 
-    }
+       return offset;
+}
+static int
+dissect_write_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    offset += 2; /* Skip FID */
+       WORD_COUNT;
 
-    /* Build display for: Offset */
+       /* write count */
+       proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    Offset = GWORD(pd, offset);
+       BYTE_COUNT;
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+       return offset;
+}
 
-    }
+static int
+dissect_lock_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    offset += 4; /* Skip Offset */
+       WORD_COUNT;
 
-    /* Build display for: Max Count */
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    MaxCount = GSHORT(pd, offset);
+       /* lock count */
+       proto_tree_add_item(tree, hf_smb_count, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    if (tree) {
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+       BYTE_COUNT;
 
-    }
+       END_OF_SMB
 
-    offset += 2; /* Skip Max Count */
+       return offset;
+}
 
-    /* Build display for: Min Count */
+static int
+dissect_create_temporary_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-    MinCount = GSHORT(pd, offset);
+       WORD_COUNT;
 
-    if (tree) {
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
+       /* Creation time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
 
-    }
+       BYTE_COUNT;
 
-    offset += 2; /* Skip Min Count */
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-    /* Build display for: Reserved 1 */
+       /* directory name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-    Reserved1 = GWORD(pd, offset);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 1: %u", Reserved1);
+       return offset;
+}
 
-    }
+static int
+dissect_create_temporary_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-    offset += 4; /* Skip Reserved 1 */
+       WORD_COUNT;
 
-    /* Build display for: Reserved 2 */
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    Reserved2 = GSHORT(pd, offset);
+       BYTE_COUNT;
 
-    if (tree) {
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-    }
+       END_OF_SMB
 
-    offset += 2; /* Skip Reserved 2 */
+       return offset;
+}
 
-    /* Build display for: Byte Count (BCC) */
+static const value_string seek_mode_vals[] = {
+       {0,     "From Start Of File"},
+       {1,     "From Current Position"},
+       {2,     "From End Of File"},
+       {0,     NULL}
+};
 
-    ByteCount = GSHORT(pd, offset);
+static int
+dissect_seek_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    if (tree) {
+       WORD_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* Seek Mode */
+       proto_tree_add_item(tree, hf_smb_seek_mode, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-  } else {
-    /* Response(s) dissect code */
+       BYTE_COUNT;
 
-    /* Build display for: Word Count */
+       END_OF_SMB
 
-    WordCount = GBYTE(pd, offset);
+       return offset;
+}
 
-    if (tree) {
+static int
+dissect_seek_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
+       WORD_COUNT;
 
-    }
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    offset += 1; /* Skip Word Count */
+       BYTE_COUNT;
 
-    if (WordCount != 0) {
+       END_OF_SMB
 
-      /* Build display for: Offset */
+       return offset;
+}
+static int
+dissect_set_information2_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-      Offset = GWORD(pd, offset);
+       WORD_COUNT;
 
-      if (tree) {
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+       /* create time */
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_create_time,
+               hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
 
-      }
+       /* access time */
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_access_time,
+               hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
 
-      offset += 4; /* Skip Offset */
+       /* last write time */
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_last_write_time,
+               hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
 
-      /* Build display for: Count */
+       BYTE_COUNT;
 
-      Count = GSHORT(pd, offset);
+       END_OF_SMB
 
-      if (tree) {
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+static int
+dissect_query_information2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-      }
+       WORD_COUNT;
 
-      offset += 2; /* Skip Count */
+       /* create time */
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_create_time,
+               hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
 
-      /* Build display for: Reserved */
+       /* access time */
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_access_time,
+               hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
 
-      Reserved = GSHORT(pd, offset);
+       /* last write time */
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_last_write_time,
+               hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
 
-      if (tree) {
+       /* data size */
+       proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+       offset += 4;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+       /* allocation size */
+       proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      }
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-      offset += 2; /* Skip Reserved */
+       BYTE_COUNT;
 
-      /* Build display for: Data Compaction Mode */
+       END_OF_SMB
 
-      DataCompactionMode = GSHORT(pd, offset);
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_write_and_close_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 cnt=0;
+       guint16 bc;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
+       WORD_COUNT;
 
-      }
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      offset += 2; /* Skip Data Compaction Mode */
+       /* write count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-      /* Build display for: Reserved */
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      Reserved = GSHORT(pd, offset);
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
+       
+       if(wc==12){
+               /* 12 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 12, TRUE);
+               offset += 12;
+       }
 
-      if (tree) {
+       BYTE_COUNT;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+       /* 1 pad byte */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+       
+       offset = dissect_file_data(tvb, pinfo, tree, offset, cnt, cnt);
+       bc = 0; /* XXX */
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip Reserved */
+       return offset;
+}
+static int
+dissect_write_and_close_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 cnt;
+       guint8 wc;
+       guint16 bc;
 
-      /* Build display for: Data Length */
+       WORD_COUNT;
 
-      DataLength = GSHORT(pd, offset);
+       /* write count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-      if (tree) {
+       BYTE_COUNT;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+       END_OF_SMB
 
-      }
+       return offset;
+}
 
-      offset += 2; /* Skip Data Length */
+static int
+dissect_read_raw_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
+       guint32 to;
 
-      /* Build display for: Data Offset */
+       WORD_COUNT;
 
-      DataOffset = GSHORT(pd, offset);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      if (tree) {
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
+       /* max count */
+       proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      }
+       /* min count */
+       proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      offset += 2; /* Skip Data Offset */
+       /* timeout */
+       to = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+       offset += 4;
 
-    }
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    /* Build display for: Byte Count (BCC) */
+       if(wc==10){
+               /* high offset */
+               proto_tree_add_item(tree, hf_smb_high_offset, tvb, offset, 4, TRUE);
+               offset += 4;
+       }
 
-    ByteCount = GSHORT(pd, offset);
+       BYTE_COUNT;
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       return offset;
+}
 
-    }
+static int
+dissect_query_information_disk_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       WORD_COUNT;
 
-    /* Build display for: Pad */
+       /* units */
+       proto_tree_add_item(tree, hf_smb_units, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    Pad = GBYTE(pd, offset);
+       /* bpu */
+       proto_tree_add_item(tree, hf_smb_bpu, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       /* block size */
+       proto_tree_add_item(tree, hf_smb_blocksize, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
+       /* free units */
+       proto_tree_add_item(tree, hf_smb_freeunits, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += 1; /* Skip Pad */
+       BYTE_COUNT;
 
-  }
+       END_OF_SMB
 
+       return offset;
 }
 
-void
-dissect_delete_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *paernt, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
+static int
+dissect_read_mpx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       SearchAttributes;
-  guint16       ByteCount;
-  const char    *FileName;
-  int           string_len;
+       guint8 wc;
+       guint16 bc;
 
-  if (si.request) {
-    /* Request(s) dissect code */
+       WORD_COUNT;
 
-    /* Build display for: Word Count (WCT) */
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    WordCount = GBYTE(pd, offset);
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    if (tree) {
+       /* max count */
+       proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       /* min count */
+       proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* 6 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 6, TRUE);
+       offset += 6;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       BYTE_COUNT;
 
-    /* Build display for: SearchAttributes */
+       END_OF_SMB
 
-    SearchAttributes = GSHORT(pd, offset);
-
-    if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
-    }
+       return offset;
+}
 
-    offset += 2; /* Skip SearchAttributes */
+static int
+dissect_read_mpx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 datalen=0, bc;
+       guint8 wc;
+       int tvblen;
 
-    /* Build display for: Byte Count (BCC) */
+       WORD_COUNT;
 
-    ByteCount = GSHORT(pd, offset);
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    if (tree) {
+       /* count */
+       proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* data compaction mode */
+       proto_tree_add_item(tree, hf_smb_dcm, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    /* Build display for: Buffer Format */
+       /* data len */
+       datalen = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+       offset += 2;
 
-    BufferFormat = GBYTE(pd, offset);
+       /* data offset */
+       proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       BYTE_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+       /* file data */
+       offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
+       bc = 0;
 
-    }
+       END_OF_SMB
 
-    offset += 1; /* Skip Buffer Format */
+       return offset;
+}
 
-    /* Build display for: File Name */
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+static const true_false_string tfs_write_raw_mode_write_through = {
+       "WRITE THROUGH requested",
+       "Write through not requested"
+};
+static const true_false_string tfs_write_raw_mode_return_remaining = {
+       "RETURN REMAINING (pipe/dev) requested",
+       "DON'T return remaining (pipe/dev)"
+};
+static const true_false_string tfs_write_raw_mode_connectionless = {
+       "CONNECTIONLESS mode requested",
+       "Connectionless mode NOT requested"
+};
+static int
+dissect_write_raw_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int bm)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    if (tree) {
+       mask = tvb_get_letohs(tvb, offset);
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Write Mode: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_rawmode);
+       }
 
-    }
+       if(bm&0x0008){
+               proto_tree_add_boolean(tree, hf_smb_write_raw_mode_connectionless,
+                       tvb, offset, 2, mask);
+       }
+       if(bm&0x0002){
+               proto_tree_add_boolean(tree, hf_smb_write_raw_mode_return_remaining,
+                       tvb, offset, 2, mask);
+       }
+       if(bm&0x0001){
+               proto_tree_add_boolean(tree, hf_smb_write_raw_mode_write_through,
+                       tvb, offset, 2, mask);
+       }
 
-    offset += string_len; /* Skip File Name */
+       offset += 2;
+       return offset;
+}
 
-  } else {
-    /* Response(s) dissect code */
+static int
+dissect_write_raw_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint32 to;
+       guint16 datalen=0, bc;
+       guint8 wc;
+       int tvblen;
 
-    /* Build display for: Word Count (WCT) */
+       WORD_COUNT;
 
-    WordCount = GBYTE(pd, offset);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       /* total data length */
+       proto_tree_add_item(tree, hf_smb_total_data_len, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       /* timeout */
+       to = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+       offset += 4;
 
-    /* Build display for: Byte Count (BCC) */
+       /* mode */
+       offset = dissect_write_raw_mode(tvb, pinfo, tree, offset, 0x0003);
 
-    ByteCount = GSHORT(pd, offset);
+       /* 4 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    if (tree) {
+       /* data len */
+       datalen = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* data offset */
+       proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       BYTE_COUNT;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* file data */
+       /* XXX - use the data offset to determine where the data starts? */
+       offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
+       bc = 0;
 
-  }
+       END_OF_SMB
 
+       return offset;
 }
-
-void
-dissect_query_info2_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
+static int
+dissect_write_raw_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  proto_tree    *Attributes_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint32       FileDataSize;
-  guint32       FileAllocationSize;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       LastAccessTime;
-  guint16       LastAccessDate;
-  guint16       FID;
-  guint16       CreationTime;
-  guint16       CreationDate;
-  guint16       ByteCount;
-  guint16       Attributes;
-
-  if (si.request) {
-    /* Request(s) dissect code */
+       guint8 wc;
+       guint16 bc;
 
-    /* Build display for: Word Count (WCT) */
+       WORD_COUNT;
 
-    WordCount = GBYTE(pd, offset);
+       /* remaining */
+       proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       BYTE_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       END_OF_SMB
 
-    }
+       return offset;
+}
 
-    offset += 1; /* Skip Word Count (WCT) */
+static int
+dissect_write_mpx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint32 to;
+       guint16 datalen=0, bc;
+       guint8 wc;
+       int tvblen;
 
-    /* Build display for: FID */
+       WORD_COUNT;
 
-    FID = GSHORT(pd, offset);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       /* total data length */
+       proto_tree_add_item(tree, hf_smb_total_data_len, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    offset += 2; /* Skip FID */
+       /* timeout */
+       to = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+       offset += 4;
 
-    /* Build display for: Byte Count */
+       /* mode */
+       offset = dissect_write_raw_mode(tvb, pinfo, tree, offset, 0x0083);
 
-    ByteCount = GSHORT(pd, offset);
+       /* request mask */
+       proto_tree_add_item(tree, hf_smb_request_mask, tvb, offset, 4, TRUE);
+       offset += 4;
+       
+       /* data len */
+       datalen = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+       offset += 2;
 
-    if (tree) {
+       /* data offset */
+       proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+       BYTE_COUNT;
 
-    }
+       /* file data */
+       /* XXX - use the data offset to determine where the data starts? */
+       offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
+       bc = 0;
 
-    offset += 2; /* Skip Byte Count */
+       END_OF_SMB
 
-  } else {
-    /* Response(s) dissect code */
+       return offset;
+}
+static int
+dissect_write_mpx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    /* Build display for: Word Count (WCT) */
+       WORD_COUNT;
 
-    WordCount = GBYTE(pd, offset);
+       /* response mask */
+       proto_tree_add_item(tree, hf_smb_response_mask, tvb, offset, 4, TRUE);
+       offset += 4;
+       
+       BYTE_COUNT;
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       return offset;
+}
 
-    }
+static int
+dissect_sid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       WORD_COUNT;
 
-    if (WordCount != 0) {
+       /* sid */
+       proto_tree_add_item(tree, hf_smb_sid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      /* Build display for: Creation Date */
+       BYTE_COUNT;
 
-      CreationDate = GSHORT(pd, offset);
+       END_OF_SMB
 
-      if (tree) {
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
+static int
+dissect_search_resume_key(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       int fn_len;
+       const char *fn;
+       char fname[11+1];
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 21,
+                       "Resume Key");
+               tree = proto_item_add_subtree(item, ett_smb_search_resume_key);
+       }
 
-      }
+       /* reserved byte */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+
+       /* file name */
+       fn_len = 11;
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               TRUE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       /* ensure that it's null-terminated */
+       strncpy(fname, fn, 11);
+       fname[11] = '\0';
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, 11,
+               fname);
+       COUNT_BYTES_SUBR(fn_len);
+
+       /* server cookie */
+       CHECK_BYTE_COUNT_SUBR(5);
+       proto_tree_add_item(tree, hf_smb_resume_server_cookie, tvb, offset, 5, TRUE);
+       COUNT_BYTES_SUBR(5);
+
+       /* client cookie */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_resume_client_cookie, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      offset += 2; /* Skip Creation Date */
+static int
+dissect_search_dir_info(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       int fn_len;
+       const char *fn;
+       char fname[13+1];
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 46,
+                       "Directory Information");
+               tree = proto_item_add_subtree(item, ett_smb_search_dir_info);
+       }
 
-      /* Build display for: Creation Time */
+       /* resume key */
+       offset = dissect_search_resume_key(tvb, pinfo, tree, offset, bcp, trunc);
+       if (*trunc)
+               return offset;
+
+       /* File Attributes */
+       CHECK_BYTE_COUNT_SUBR(1);
+       offset = dissect_dir_info_file_attributes(tvb, pinfo, tree, offset);
+       *bcp -= 1;
+
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_last_write_time,
+               hf_smb_last_write_dos_date, hf_smb_last_write_dos_time,
+               TRUE);
+       *bcp -= 4;
+
+       /* File Size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name */
+       fn_len = 13;
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               TRUE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       /* ensure that it's null-terminated */
+       strncpy(fname, fn, 13);
+       fname[13] = '\0';
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fname);
+       COUNT_BYTES_SUBR(fn_len);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      CreationTime = GSHORT(pd, offset);
 
-      if (tree) {
+static int
+dissect_search_dir_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint16 rkl;
+       guint8 wc;
+       guint16 bc;
+       gboolean trunc;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
+       WORD_COUNT;
 
-      }
+       /* max count */
+       proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      offset += 2; /* Skip Creation Time */
+       /* Search Attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-      /* Build display for: Last Access Date */
+       BYTE_COUNT;
 
-      LastAccessDate = GSHORT(pd, offset);
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      if (tree) {
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               TRUE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Date: %s", dissect_dos_date(LastAccessDate));
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", File: %s", fn);
+       }
 
-      }
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+
+       /* resume key length */
+       CHECK_BYTE_COUNT(2);
+       rkl = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_resume_key_len, tvb, offset, 2, rkl);
+       COUNT_BYTES(2);
+
+       /* resume key */
+       if(rkl){
+               offset = dissect_search_resume_key(tvb, pinfo, tree, offset,
+                   &bc, &trunc);
+               if (trunc)
+                       goto endofcommand;
+       }
 
-      offset += 2; /* Skip Last Access Date */
+       END_OF_SMB
 
-      /* Build display for: Last Access Time */
+       return offset;
+}
 
-      LastAccessTime = GSHORT(pd, offset);
+static int
+dissect_search_dir_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 count=0;
+       guint8 wc;
+       guint16 bc;
+       gboolean trunc;
 
-      if (tree) {
+       WORD_COUNT;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Time: %s", dissect_dos_time(LastAccessTime));
+       /* count */
+       count = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, count);
+       offset += 2;
 
-      }
+       BYTE_COUNT;
 
-      offset += 2; /* Skip Last Access Time */
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      /* Build display for: Last Write Date */
+       /* data len */
+       CHECK_BYTE_COUNT(2);
+       proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+       COUNT_BYTES(2);
 
-      LastWriteDate = GSHORT(pd, offset);
+       while(count--){
+               offset = dissect_search_dir_info(tvb, pinfo, tree, offset,
+                   &bc, &trunc);
+               if (trunc)
+                       goto endofcommand;
+       }
 
-      if (tree) {
+       END_OF_SMB
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
+       return offset;
+}
 
-      }
+static const value_string locking_ol_vals[] = {
+       {0,     "Client is not holding oplock on this file"},
+       {1,     "Level 2 oplock currently held by client"},
+       {0, NULL}
+};
 
-      offset += 2; /* Skip Last Write Date */
+static const true_false_string tfs_lock_type_large = {
+       "Large file locking format requested",
+       "Large file locking format not requested"
+};
+static const true_false_string tfs_lock_type_cancel = {
+       "Cancel outstanding lock request",
+       "Don't cancel outstanding lock request"
+};
+static const true_false_string tfs_lock_type_change = {
+       "Change lock type",
+       "Don't change lock type"
+};
+static const true_false_string tfs_lock_type_oplock = {
+       "This is an oplock break notification/response",
+       "This is not an oplock break notification/response"
+};
+static const true_false_string tfs_lock_type_shared = {
+       "This is a shared lock",
+       "This is an exclusive lock"
+};
+static int
+dissect_locking_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff, lt=0;
+       guint16 andxoffset=0, un=0, ln=0, bc;
+       guint32 to;
+       proto_item *litem = NULL;
+       proto_tree *ltree = NULL;
+       proto_item *it = NULL;
+       proto_tree *tr = NULL;
+       int old_offset = offset;
+
+       WORD_COUNT;
+
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-      /* Build display for: Last Write Time */
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      LastWriteTime = GSHORT(pd, offset);
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      if (tree) {
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
+       /* lock type */
+       lt = tvb_get_guint8(tvb, offset);
+       if(tree){
+               litem = proto_tree_add_text(tree, tvb, offset, 1,
+                       "Lock Type: 0x%02x", lt);
+               ltree = proto_item_add_subtree(litem, ett_smb_lock_type);
+       }
+       proto_tree_add_boolean(ltree, hf_smb_lock_type_large,
+               tvb, offset, 1, lt);
+       proto_tree_add_boolean(ltree, hf_smb_lock_type_cancel,
+               tvb, offset, 1, lt);
+       proto_tree_add_boolean(ltree, hf_smb_lock_type_change,
+               tvb, offset, 1, lt);
+       proto_tree_add_boolean(ltree, hf_smb_lock_type_oplock,
+               tvb, offset, 1, lt);
+       proto_tree_add_boolean(ltree, hf_smb_lock_type_shared,
+               tvb, offset, 1, lt);
+       offset += 1;
 
-      }
+       /* oplock level */
+       proto_tree_add_item(tree, hf_smb_locking_ol, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      offset += 2; /* Skip Last Write Time */
+       /* timeout */
+       to = tvb_get_letohl(tvb, offset);
+       if (to == 0)
+               proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: Return immediately (0)");
+       else if (to == 0xffffffff)
+               proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: Wait indefinitely (-1)");
+       else
+               proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+       offset += 4;
 
-      /* Build display for: File Data Size */
+       /* number of unlocks */
+       un = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_number_of_unlocks, tvb, offset, 2, un);
+       offset += 2;
 
-      FileDataSize = GWORD(pd, offset);
+       /* number of locks */
+       ln = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_number_of_locks, tvb, offset, 2, ln);
+       offset += 2;
 
-      if (tree) {
-       
-       proto_tree_add_text(tree, NullTVB, offset, 4, "File Data Size: %u", FileDataSize);
+       BYTE_COUNT;
+
+       /* unlocks */
+       if(un){
+               old_offset = offset;
+
+               it = proto_tree_add_text(tree, tvb, offset, 0,
+                       "Unlocks");
+               tr = proto_item_add_subtree(it, ett_smb_unlocks);
+               while(un--){
+                       proto_item *litem = NULL;
+                       proto_tree *ltree = NULL;
+                       if(lt&0x10){
+                               /* large lock format */
+                               litem = proto_tree_add_text(tr, tvb, offset, 20,
+                                       "Unlock");
+                               ltree = proto_item_add_subtree(litem, ett_smb_unlock);
+                               
+                               /* PID */
+                               CHECK_BYTE_COUNT(2);
+                               proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+                               COUNT_BYTES(2);
+
+                               /* 2 reserved bytes */
+                               CHECK_BYTE_COUNT(2);
+                               proto_tree_add_item(ltree, hf_smb_reserved, tvb, offset, 2, TRUE);
+                               COUNT_BYTES(2);
+
+                               /* offset */
+                               CHECK_BYTE_COUNT(8);
+                               proto_tree_add_item(ltree, hf_smb_lock_long_offset, tvb, offset, 8, TRUE);
+                               COUNT_BYTES(8);
+
+                               /* length */
+                               CHECK_BYTE_COUNT(8);
+                               proto_tree_add_item(ltree, hf_smb_lock_long_length, tvb, offset, 8, TRUE);
+                               COUNT_BYTES(8);
+                       } else {
+                               /* normal lock format */
+                               litem = proto_tree_add_text(tr, tvb, offset, 10,
+                                       "Unlock");
+                               ltree = proto_item_add_subtree(litem, ett_smb_unlock);
+                               
+                               /* PID */
+                               CHECK_BYTE_COUNT(2);
+                               proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+                               COUNT_BYTES(2);
+
+                               /* offset */
+                               CHECK_BYTE_COUNT(4);
+                               proto_tree_add_item(ltree, hf_smb_offset, tvb, offset, 4, TRUE);
+                               COUNT_BYTES(4);
+
+                               /* lock count */
+                               CHECK_BYTE_COUNT(4);
+                               proto_tree_add_item(ltree, hf_smb_count, tvb, offset, 4, TRUE);
+                               COUNT_BYTES(4);
+                       }
+               }
+               proto_item_set_len(it, offset-old_offset);
+               it = NULL;
+       }
 
-      }
+       /* locks */
+       if(ln){
+               old_offset = offset;
+
+               it = proto_tree_add_text(tree, tvb, offset, 0,
+                       "Locks");
+               tr = proto_item_add_subtree(it, ett_smb_locks);
+               while(ln--){
+                       proto_item *litem = NULL;
+                       proto_tree *ltree = NULL;
+                       if(lt&0x10){
+                               /* large lock format */
+                               litem = proto_tree_add_text(tr, tvb, offset, 20,
+                                       "Lock");
+                               ltree = proto_item_add_subtree(litem, ett_smb_lock);
+                               
+                               /* PID */
+                               CHECK_BYTE_COUNT(2);
+                               proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+                               COUNT_BYTES(2);
+
+                               /* 2 reserved bytes */
+                               CHECK_BYTE_COUNT(2);
+                               proto_tree_add_item(ltree, hf_smb_reserved, tvb, offset, 2, TRUE);
+                               COUNT_BYTES(2);
+
+                               /* offset */
+                               CHECK_BYTE_COUNT(8);
+                               proto_tree_add_item(ltree, hf_smb_lock_long_offset, tvb, offset, 8, TRUE);
+                               COUNT_BYTES(8);
+
+                               /* length */
+                               CHECK_BYTE_COUNT(8);
+                               proto_tree_add_item(ltree, hf_smb_lock_long_length, tvb, offset, 8, TRUE);
+                               COUNT_BYTES(8);
+                       } else {
+                               /* normal lock format */
+                               litem = proto_tree_add_text(tr, tvb, offset, 10,
+                                       "Unlock");
+                               ltree = proto_item_add_subtree(litem, ett_smb_unlock);
+                               
+                               /* PID */
+                               CHECK_BYTE_COUNT(2);
+                               proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+                               COUNT_BYTES(2);
+
+                               /* offset */
+                               CHECK_BYTE_COUNT(4);
+                               proto_tree_add_item(ltree, hf_smb_offset, tvb, offset, 4, TRUE);
+                               COUNT_BYTES(4);
+
+                               /* lock count */
+                               CHECK_BYTE_COUNT(4);
+                               proto_tree_add_item(ltree, hf_smb_count, tvb, offset, 4, TRUE);
+                               COUNT_BYTES(4);
+                       }
+               }
+               proto_item_set_len(it, offset-old_offset);
+               it = NULL;
+       }
 
-      offset += 4; /* Skip File Data Size */
+       END_OF_SMB
 
-      /* Build display for: File Allocation Size */
+       if (it != NULL) {
+               /*
+                * We ran out of byte count in the middle of dissecting
+                * the locks or the unlocks; set the site of the item
+                * we were dissecting.
+                */
+               proto_item_set_len(it, offset-old_offset);
+       }
 
-      FileAllocationSize = GWORD(pd, offset);
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      if (tree) {
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 4, "File Allocation Size: %u", FileAllocationSize);
+static int
+dissect_locking_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0;
+       guint16 bc;
 
-      }
+       WORD_COUNT;
 
-      offset += 4; /* Skip File Allocation Size */
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-      /* Build display for: Attributes */
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      Attributes = GSHORT(pd, offset);
-      
-      if (tree) {
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Attributes: 0x%02x", Attributes);
-       Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
-    
-      }
+       BYTE_COUNT;
 
-      offset += 2; /* Skip Attributes */
+       END_OF_SMB
 
-    }
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-    /* Build display for: Byte Count */
+       return offset;
+}
 
-    ByteCount = GSHORT(pd, offset);
 
-    if (tree) {
+static const value_string oa_open_vals[] = {
+       { 0,            "No action taken?"},
+       { 1,            "The file existed and was opened"},
+       { 2,            "The file did not exist but was created"},
+       { 3,            "The file existed and was truncated"},
+       {0,     NULL}
+};
+static const true_false_string tfs_oa_lock = {
+       "File is currently opened only by this user",
+       "File is opened by another user (or mode not supported by server)"
+};
+static int
+dissect_open_action(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+       mask = tvb_get_letohs(tvb, offset);
 
-    }
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Action: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_open_action);
+       }
 
-    offset += 2; /* Skip Byte Count */
+       proto_tree_add_boolean(tree, hf_smb_open_action_lock,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_open_action_open,
+               tvb, offset, 2, mask);
 
-  }
+       offset += 2;
 
+       return offset;
 }
 
-void
-dissect_treecon_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
+static const true_false_string tfs_open_flags_add_info = {
+       "Additional information requested",
+       "Additional information not requested"
+};
+static const true_false_string tfs_open_flags_ex_oplock = {
+       "Exclusive oplock requested",
+       "Exclusive oplock not requested"
+};
+static const true_false_string tfs_open_flags_batch_oplock = {
+       "Batch oplock requested",
+       "Batch oplock not requested"
+};
+static const true_false_string tfs_open_flags_ealen = {
+       "Total length of EAs requested",
+       "Total length of EAs not requested"
+};
+static int
+dissect_open_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int bm)
 {
-  guint8        WordCount;
-  guint8        BufferFormat3;
-  guint8        BufferFormat2;
-  guint8        BufferFormat1;
-  guint16       TID;
-  guint16       MaxBufferSize;
-  guint16       ByteCount;
-  const char    *SharePath;
-  const char    *Service;
-  const char    *Password;
-  int           string_len;
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-  if (si.request) {
-    /* Request(s) dissect code */
+       mask = tvb_get_letohs(tvb, offset);
 
-    /* Build display for: Word Count (WCT) */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_open_flags);
+       }
 
-    WordCount = GBYTE(pd, offset);
+       if(bm&0x0001){
+               proto_tree_add_boolean(tree, hf_smb_open_flags_add_info,
+                       tvb, offset, 2, mask);
+       }
+       if(bm&0x0002){
+               proto_tree_add_boolean(tree, hf_smb_open_flags_ex_oplock,
+                       tvb, offset, 2, mask);
+       }
+       if(bm&0x0004){
+               proto_tree_add_boolean(tree, hf_smb_open_flags_batch_oplock,
+                       tvb, offset, 2, mask);
+       }
+       if(bm&0x0008){
+               proto_tree_add_boolean(tree, hf_smb_open_flags_ealen,
+                       tvb, offset, 2, mask);
+       }
 
-    if (tree) {
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       return offset;
+}
 
-    }
+static const value_string filetype_vals[] = {
+       { 0,            "Disk file or directory"},
+       { 1,            "Named pipe in byte mode"},
+       { 2,            "Named pipe in message mode"},
+       { 3,            "Spooled printer"},
+       {0, NULL}
+};
+static int
+dissect_open_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0, bc;
+       int fn_len;
+       const char *fn;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       WORD_COUNT;
 
-    /* Build display for: Byte Count (BCC) */
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-    ByteCount = GSHORT(pd, offset);
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-    if (tree) {
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* open flags */
+       offset = dissect_open_flags(tvb, pinfo, tree, offset, 0x0007);
 
-    }
+       /* desired access */
+       offset = dissect_access(tvb, pinfo, tree, offset, "Desired");
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* Search Attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-    /* Build display for: BufferFormat1 */
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-    BufferFormat1 = GBYTE(pd, offset);
+       /* creation time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
+       
+       /* open function */
+       offset = dissect_open_function(tvb, pinfo, tree, offset);
 
-    if (tree) {
+       /* allocation size */
+       proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 1: %s (%u)",
-                         val_to_str(BufferFormat1, buffer_format_vals, "Unknown"),
-                         BufferFormat1);
+       /* 8 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
+       offset += 8;
 
-    }
+       BYTE_COUNT;
 
-    offset += 1; /* Skip BufferFormat1 */
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+               FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-    /* Build display for: Share Path */
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-    SharePath = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       END_OF_SMB
 
-    if (tree) {
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Share Path: %s", SharePath);
+       return offset;
+}
 
-    }
+static const true_false_string tfs_ipc_state_nonblocking = {
+       "Reads/writes return immediately if no data available",
+       "Reads/writes block if no data available"
+};
+static const value_string ipc_state_endpoint_vals[] = {
+       { 0,            "Consumer end of pipe"},
+       { 1,            "Server end of pipe"},
+       {0,     NULL}
+};
+static const value_string ipc_state_pipe_type_vals[] = {
+       { 0,            "Byte stream pipe"},
+       { 1,            "Message pipe"},
+       {0,     NULL}
+};
+static const value_string ipc_state_read_mode_vals[] = {
+       { 0,            "Read pipe as a byte stream"},
+       { 1,            "Read messages from pipe"},
+       {0,     NULL}
+};
 
-    offset += string_len; /* Skip Share Path */
+static int
+dissect_ipc_state(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    /* Build display for: BufferFormat2 */
+       mask = tvb_get_letohs(tvb, offset);
 
-    BufferFormat2 = GBYTE(pd, offset);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "IPC State: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_ipc_state);
+       }
 
-    if (tree) {
+       proto_tree_add_boolean(tree, hf_smb_ipc_state_nonblocking,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_ipc_state_endpoint,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_ipc_state_pipe_type,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_ipc_state_read_mode,
+               tvb, offset, 2, mask);
+       proto_tree_add_uint(tree, hf_smb_ipc_state_icount,
+               tvb, offset, 2, mask);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 2: %s (%u)",
-                         val_to_str(BufferFormat2, buffer_format_vals, "Unknown"),
-                         BufferFormat2);
+       offset += 2;
 
-    }
+       return offset;
+}
 
-    offset += 1; /* Skip BufferFormat2 */
+static int
+dissect_open_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0, bc;
 
-    /* Build display for: Password */
+       WORD_COUNT;
 
-    Password = pd + offset;
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-    if (tree) {
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      proto_tree_add_text(tree, NullTVB, offset, strlen(Password) + 1, "Password: %s", Password);
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-    }
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    offset += strlen(Password) + 1; /* Skip Password */
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-    /* Build display for: BufferFormat3 */
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
+       
+       /* File Size */
+       proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    BufferFormat3 = GBYTE(pd, offset);
+       /* granted access */
+       offset = dissect_access(tvb, pinfo, tree, offset, "Granted");
 
-    if (tree) {
+       /* File Type */
+       proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 3: %s (%u)",
-                         val_to_str(BufferFormat3, buffer_format_vals, "Unknown"),
-                         BufferFormat3);
+       /* IPC State */
+       offset = dissect_ipc_state(tvb, pinfo, tree, offset);
 
-    }
+       /* open_action */
+       offset = dissect_open_action(tvb, pinfo, tree, offset);
 
-    offset += 1; /* Skip BufferFormat3 */
+       /* server fid */
+       proto_tree_add_item(tree, hf_smb_server_fid, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    /* Build display for: Service */
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    Service = pd + offset;
+       BYTE_COUNT;
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, strlen(Service) + 1, "Service: %s", Service);
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-    }
+       return offset;
+}
 
-    offset += strlen(Service) + 1; /* Skip Service */
+static int
+dissect_read_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0, bc;
 
-  } else {
-    /* Response(s) dissect code */
+       WORD_COUNT;
 
-    /* Build display for: Word Count (WCT) */
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-    WordCount = GBYTE(pd, offset);
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-    if (tree) {
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* offset */
+       proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+       offset += 4;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       /* max count */
+       proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (WordCount != 0) {
+       /* min count */
+       proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      /* Build display for: Max Buffer Size */
+       /* XXX - max count high */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      MaxBufferSize = GSHORT(pd, offset);
+       /* remaining */
+       proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      if (tree) {
+       if(wc==12){
+               /* high offset */
+               proto_tree_add_item(tree, hf_smb_high_offset, tvb, offset, 4, TRUE);
+               offset += 4;
+       }
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Max Buffer Size: %u", MaxBufferSize);
+       BYTE_COUNT;
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip Max Buffer Size */
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      /* Build display for: TID */
+       return offset;
+}
 
-      TID = GSHORT(pd, offset);
+static int
+dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0, bc, datalen=0;
+       int len;
 
-      if (tree) {
+       WORD_COUNT;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "TID: %u", TID);
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      }
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      offset += 2; /* Skip TID */
+       /* remaining */
+       proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    }
+       /* data compaction mode */
+       proto_tree_add_item(tree, hf_smb_dcm, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    /* Build display for: Byte Count (BCC) */
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    ByteCount = GSHORT(pd, offset);
+       /* data len */
+       datalen = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+       offset += 2;
 
-    if (tree) {
+       /* data offset */
+       proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* 10 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+       offset += 10;
 
-    }
+       BYTE_COUNT;
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       /* file data */
+       offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
+       bc = 0;
 
-  }
+       END_OF_SMB
 
-}
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-/* Generated by build-dissect.pl Vesion 0.6 27-Jun-1999, ACT */
-void
-dissect_ssetup_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
+       return offset;
+}
 
+static const true_false_string tfs_setup_action_guest = {
+       "Logged in as GUEST",
+       "Not logged in as GUEST"
+};
+static int
+dissect_setup_action(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
 {
-  proto_tree    *Capabilities_tree;
-  proto_tree    *Action_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        AndXReserved;
-  guint8        AndXCommand = 0xFF;
-  guint32       SessionKey;
-  guint32       Reserved;
-  guint32       Capabilities;
-  guint16       VcNumber;
-  guint16       SecurityBlobLength;
-  guint16       ANSIAccountPasswordLength;
-  guint16       UNICODEAccountPasswordLength;
-  guint16       PasswordLen;
-  guint16       MaxMpxCount;
-  guint16       MaxBufferSize;
-  guint16       ByteCount;
-  guint16       AndXOffset = 0;
-  guint16       Action;
-  const char    *ANSIPassword;
-  const char    *UNICODEPassword;
-  const char    *SecurityBlob;
-  const char    *Password;
-  const char    *PrimaryDomain;
-  const char    *NativeOS;
-  const char    *NativeLanManType;
-  const char    *NativeLanMan;
-  const char    *AccountName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       mask = tvb_get_letohs(tvb, offset);
 
-    }
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Action: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_setup_action);
+       }
 
-    offset += 1; /* Skip Word Count (WCT) */
+       proto_tree_add_boolean(tree, hf_smb_setup_action_guest,
+               tvb, offset, 2, mask);
 
-    switch (WordCount) {
+       offset += 2;
 
-    case 10:
+       return offset;
+}
 
-      /* Build display for: AndXCommand */
+static int
+dissect_session_setup_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 bc;
+       guint16 andxoffset=0;
+       int an_len;
+       const char *an;
+       int dn_len;
+       const char *dn;
+       guint16 pwlen=0;
+       guint16 sbloblen=0;
+       guint16 apwlen=0, upwlen=0;
+
+       WORD_COUNT;
+
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-      AndXCommand = GBYTE(pd, offset);
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      if (tree) {
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+       /* Maximum Buffer Size */
+       proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      }
+       /* Maximum Multiplex Count */
+       proto_tree_add_item(tree, hf_smb_max_mpx_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      offset += 1; /* Skip AndXCommand */
+       /* VC Number */
+       proto_tree_add_item(tree, hf_smb_vc_num, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      /* Build display for: AndXReserved */
+       /* session key */
+       proto_tree_add_item(tree, hf_smb_session_key, tvb, offset, 4, TRUE);
+       offset += 4;
+
+       switch (wc) {
+       case 10:
+               /* password length, ASCII*/
+               pwlen = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_password_len,
+                       tvb, offset, 2, pwlen);
+               offset += 2;
+
+               /* 4 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               break;
+
+       case 12:
+               /* security blob length */
+               sbloblen = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_security_blob_len, tvb, offset, 2, sbloblen);
+               offset += 2;
+
+               /* 4 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* capabilities */
+               dissect_negprot_capabilities(tvb, pinfo, tree, offset);
+               offset += 4;
+
+               break;
+
+       case 13:
+               /* password length, ANSI*/
+               apwlen = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_ansi_password_len,
+                       tvb, offset, 2, apwlen);
+               offset += 2;
+
+               /* password length, Unicode*/
+               upwlen = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_unicode_password_len,
+                       tvb, offset, 2, upwlen);
+               offset += 2;
+
+               /* 4 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* capabilities */
+               dissect_negprot_capabilities(tvb, pinfo, tree, offset);
+               offset += 4;
+
+               break;
+       }
 
-      AndXReserved = GBYTE(pd, offset);
+       BYTE_COUNT;
+
+       if (wc==12) {
+               /* security blob */
+               /* XXX - is this ASN.1-encoded?  Is it a Kerberos
+                  data structure, at least in NT 5.0-and-later
+                  server replies? */
+               if(sbloblen){
+                       CHECK_BYTE_COUNT(sbloblen);
+                       proto_tree_add_item(tree, hf_smb_security_blob,
+                               tvb, offset, sbloblen, TRUE);
+                       COUNT_BYTES(sbloblen);
+               }
+
+               /* OS */
+               an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &an_len, FALSE, FALSE, &bc);
+               if (an == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_os, tvb,
+                       offset, an_len, an);
+               COUNT_BYTES(an_len);
+
+               /* LANMAN */
+               /* XXX - pre-W2K NT systems appear to stick an extra 2 bytes of
+                * padding/null string/whatever in front of this. W2K doesn't
+                * appear to. I suspect that's a bug that got fixed; I also
+                * suspect that, in practice, nobody ever looks at that field
+                * because the bug didn't appear to get fixed until NT 5.0....
+                */
+               an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &an_len, FALSE, FALSE, &bc);
+               if (an == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_lanman, tvb,
+                       offset, an_len, an);
+               COUNT_BYTES(an_len);
+
+               /* Primary domain */
+               /* XXX - pre-W2K NT systems sometimes appear to stick an extra
+                * byte in front of this, at least if all the strings are
+                * ASCII and the account name is empty. Another bug?
+                */
+               dn = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &dn_len, FALSE, FALSE, &bc);
+               if (dn == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+                       offset, dn_len, dn);
+               COUNT_BYTES(dn_len);
+       } else {
+               switch (wc) {
+
+               case 10:
+                       if(pwlen){
+                               /* password, ASCII */
+                               CHECK_BYTE_COUNT(pwlen);
+                               proto_tree_add_item(tree, hf_smb_password, 
+                                       tvb, offset, pwlen, TRUE);
+                               COUNT_BYTES(pwlen);
+                       }
+
+                       break;
+
+               case 13:
+                       if(apwlen){
+                               /* password, ANSI */
+                               CHECK_BYTE_COUNT(apwlen);
+                               proto_tree_add_item(tree, hf_smb_ansi_password, 
+                                       tvb, offset, apwlen, TRUE);
+                               COUNT_BYTES(apwlen);
+                       }
+
+                       if(upwlen){
+                               /* password, Unicode */
+                               CHECK_BYTE_COUNT(upwlen);
+                               proto_tree_add_item(tree, hf_smb_unicode_password, 
+                                       tvb, offset, upwlen, TRUE);
+                               COUNT_BYTES(upwlen);
+                       }
+
+                       break;
+               }
+
+               /* Account Name */
+               an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &an_len, FALSE, FALSE, &bc);
+               if (an == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_account, tvb, offset, an_len,
+                       an);
+               COUNT_BYTES(an_len);
+
+               /* Primary domain */
+               /* XXX - pre-W2K NT systems sometimes appear to stick an extra
+                * byte in front of this, at least if all the strings are
+                * ASCII and the account name is empty. Another bug?
+                */
+               dn = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &dn_len, FALSE, FALSE, &bc);
+               if (dn == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+                       offset, dn_len, dn);
+               COUNT_BYTES(dn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", User: %s@%s",
+                       an,dn);
+               }
+
+               /* OS */
+               an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &an_len, FALSE, FALSE, &bc);
+               if (an == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_os, tvb,
+                       offset, an_len, an);
+               COUNT_BYTES(an_len);
+
+               /* LANMAN */
+               /* XXX - pre-W2K NT systems appear to stick an extra 2 bytes of
+                * padding/null string/whatever in front of this. W2K doesn't
+                * appear to. I suspect that's a bug that got fixed; I also
+                * suspect that, in practice, nobody ever looks at that field
+                * because the bug didn't appear to get fixed until NT 5.0....
+                */
+               an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &an_len, FALSE, FALSE, &bc);
+               if (an == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_lanman, tvb,
+                       offset, an_len, an);
+               COUNT_BYTES(an_len);
+       }
 
-      if (tree) {
+       END_OF_SMB
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      }
+       return offset;
+}
 
-      offset += 1; /* Skip AndXReserved */
+static int
+dissect_session_setup_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0, bc;
+       guint16 sbloblen=0;
+       int an_len;
+       const char *an;
+
+       WORD_COUNT;
+
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-      /* Build display for: AndXOffset */
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      AndXOffset = GSHORT(pd, offset);
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      if (tree) {
+       /* flags */
+       offset = dissect_setup_action(tvb, pinfo, tree, offset);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+       if(wc==4){
+               /* security blob length */
+               sbloblen = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_security_blob_len, tvb, offset, 2, sbloblen);
+               offset += 2;
+       }
 
-      }
+       BYTE_COUNT;
+
+       if(wc==4) {
+               /* security blob */
+               /* XXX - is this ASN.1-encoded?  Is it a Kerberos
+                  data structure, at least in NT 5.0-and-later
+                  server replies? */
+               if(sbloblen){
+                       CHECK_BYTE_COUNT(sbloblen);
+                       proto_tree_add_item(tree, hf_smb_security_blob,
+                               tvb, offset, sbloblen, TRUE);
+                       COUNT_BYTES(sbloblen);
+               }
+       }
 
-      offset += 2; /* Skip AndXOffset */
+       /* OS */
+       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+               pinfo, &an_len, FALSE, FALSE, &bc);
+       if (an == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_os, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
+
+       /* LANMAN */
+       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+               pinfo, &an_len, FALSE, FALSE, &bc);
+       if (an == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_lanman, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
+
+       if(wc==3) {
+               /* Primary domain */
+               an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                       pinfo, &an_len, FALSE, FALSE, &bc);
+               if (an == NULL)
+                       goto endofcommand;
+               proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+                       offset, an_len, an);
+               COUNT_BYTES(an_len);
+       }
 
-      /* Build display for: MaxBufferSize */
+       END_OF_SMB
 
-      MaxBufferSize = GSHORT(pd, offset);
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      if (tree) {
+       return offset;
+}
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
+static int
+dissect_empty_andx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0;
+       guint16 bc;
 
-      }
+       WORD_COUNT;
 
-      offset += 2; /* Skip MaxBufferSize */
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-      /* Build display for: MaxMpxCount */
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      MaxMpxCount = GSHORT(pd, offset);
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      if (tree) {
+       BYTE_COUNT;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
+       END_OF_SMB
 
-      }
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      offset += 2; /* Skip MaxMpxCount */
+       return offset;
+}
 
-      /* Build display for: VcNumber */
+static const true_false_string tfs_connect_support_search = {
+       "Exclusive search bits supported",
+       "Exclusive search bits not supported"
+};
+static const true_false_string tfs_connect_support_in_dfs = {
+       "Share is in Dfs",
+       "Share isn't in Dfs"
+};
 
-      VcNumber = GSHORT(pd, offset);
+static int
+dissect_connect_support_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      if (tree) {
+       mask = tvb_get_letohs(tvb, offset);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Optional Support: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_connect_support_bits);
+       }
 
-      }
+       proto_tree_add_boolean(tree, hf_smb_connect_support_search,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_connect_support_in_dfs,
+               tvb, offset, 2, mask);
 
-      offset += 2; /* Skip VcNumber */
+       offset += 2;
 
-      /* Build display for: SessionKey */
+       return offset;
+}
 
-      SessionKey = GWORD(pd, offset);
+static const true_false_string tfs_disconnect_tid = {
+       "DISCONNECT TID",
+       "Do NOT disconnect TID"
+};
 
-      if (tree) {
+static int
+dissect_connect_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
+       mask = tvb_get_letohs(tvb, offset);
 
-      }
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_connect_flags);
+       }
 
-      offset += 4; /* Skip SessionKey */
+       proto_tree_add_boolean(tree, hf_smb_connect_flags_dtid,
+               tvb, offset, 2, mask);
 
-      /* Build display for: PasswordLen */
+       offset += 2;
 
-      PasswordLen = GSHORT(pd, offset);
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_tree_connect_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 bc;
+       guint16 andxoffset=0, pwlen=0;
+       int an_len;
+       const char *an;
+
+       WORD_COUNT;
+
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands");
+       }
+       offset += 1;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "PasswordLen: %u", PasswordLen);
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      }
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      offset += 2; /* Skip PasswordLen */
+       /* flags */
+       offset = dissect_connect_flags(tvb, pinfo, tree, offset);
 
-      /* Build display for: Reserved */
+       /* password length*/
+       pwlen = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_password_len, tvb, offset, 2, pwlen);
+       offset += 2;
 
-      Reserved = GWORD(pd, offset);
+       BYTE_COUNT;
 
-      if (tree) {
+       /* password */
+       CHECK_BYTE_COUNT(pwlen);
+       proto_tree_add_item(tree, hf_smb_password, 
+               tvb, offset, pwlen, TRUE);
+       COUNT_BYTES(pwlen);
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
+       /* Path */
+       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+               pinfo, &an_len, FALSE, FALSE, &bc);
+       if (an == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_path, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
 
-      }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", an);
+       }
 
-      offset += 4; /* Skip Reserved */
+       /*
+        * NOTE: the Service string is always ASCII, even if the
+        * "strings are Unicode" bit is set in the flags2 field
+        * of the SMB.
+        */
 
-      /* Build display for: Byte Count (BCC) */
+       /* Service */
+       /* XXX - what if this runs past bc? */
+       an_len = tvb_strsize(tvb, offset);
+       CHECK_BYTE_COUNT(an_len);
+       an = tvb_get_ptr(tvb, offset, an_len);
+       proto_tree_add_string(tree, hf_smb_service, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
 
-      ByteCount = GSHORT(pd, offset);
+       END_OF_SMB
 
-      if (tree) {
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       return offset;
+}
 
-      }
 
-      offset += 2; /* Skip Byte Count (BCC) */
+static int
+dissect_tree_connect_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, wleft, cmd=0xff;
+       guint16 andxoffset=0;
+       guint16 bc;
+       int an_len;
+       const char *an;
 
-      if (ByteCount > 0) {
+       WORD_COUNT;
 
-       /* Build display for: Password */
+       wleft = wc;     /* this is at least 1 */
 
-        Password = pd + offset;
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands");
+       }
+       offset += 1;
 
-       if (tree) {
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-         proto_tree_add_text(tree, NullTVB, offset, strlen(Password) + 1, "Password: %s", Password);
+       wleft--;
+       if (wleft == 0)
+               goto bytecount;
 
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
+       wleft--;
+       if (wleft == 0)
+               goto bytecount;
+
+       /* flags */
+       offset = dissect_connect_support_bits(tvb, pinfo, tree, offset);
+       wleft--;
+
+       /* XXX - I've seen captures where this is 7, but I have no
+          idea how to dissect it.  I'm guessing the third word
+          contains connect support bits, which looks plausible
+          from the values I've seen. */
+
+       while (wleft != 0) {
+               proto_tree_add_text(tree, tvb, offset, 2,
+                   "Word parameter: 0x%04x", tvb_get_letohs(tvb, offset));
+               offset += 2;
+               wleft--;
        }
 
-       offset += PasswordLen;
+       BYTE_COUNT;
 
-       /* Build display for: AccountName */
-
-       AccountName = pd + offset;
-
-       if (tree) {
+       /*
+        * NOTE: even though the SNIA CIFS spec doesn't say there's
+        * a "Service" string if there's a word count of 2, the
+        * document at
+        *
+        *      ftp://ftp.microsoft.com/developr/drg/CIFS/dosextp.txt
+        *
+        * (it's in an ugly format - text intended to be sent to a
+        * printer, with backspaces and overstrikes used for boldfacing
+        * and underlining; UNIX "col -b" can be used to strip the
+        * overstrikes out) says there's a "Service" string there, and
+        * some network traffic has it.
+        */
 
-         proto_tree_add_text(tree, NullTVB, offset, strlen(AccountName) + 1, "AccountName: %s", AccountName);
+       /*
+        * NOTE: the Service string is always ASCII, even if the
+        * "strings are Unicode" bit is set in the flags2 field
+        * of the SMB.
+        */
 
+       /* Service */
+       /* XXX - what if this runs past bc? */
+       an_len = tvb_strsize(tvb, offset);
+       CHECK_BYTE_COUNT(an_len);
+       an = tvb_get_ptr(tvb, offset, an_len);
+       proto_tree_add_string(tree, hf_smb_service, tvb,
+               offset, an_len, an);
+       COUNT_BYTES(an_len);
+
+       if(wc==3){
+               if (bc != 0) {
+                       /*
+                        * Sometimes this isn't present.
+                        */
+
+                       /* Native FS */
+                       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                               pinfo, &an_len, /*TRUE*/FALSE, FALSE, &bc);
+                       if (an == NULL)
+                               goto endofcommand;
+                       proto_tree_add_string(tree, hf_smb_fs, tvb,
+                               offset, an_len, an);
+                       COUNT_BYTES(an_len);
+               }
        }
 
-       offset += strlen(AccountName) + 1; /* Skip AccountName */
+       END_OF_SMB
 
-       /* Build display for: PrimaryDomain */
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-       PrimaryDomain = pd + offset;
+       return offset;
+}
 
-       if (tree) {
 
-         proto_tree_add_text(tree, NullTVB, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
 
-       }
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   NT Transaction command  begins here
+   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+#define NT_TRANS_CREATE                1
+#define NT_TRANS_IOCTL         2
+#define NT_TRANS_SSD           3
+#define NT_TRANS_NOTIFY                4
+#define NT_TRANS_RENAME                5
+#define NT_TRANS_QSD           6
+static const value_string nt_cmd_vals[] = {
+       {NT_TRANS_CREATE,       "NT CREATE"},
+       {NT_TRANS_IOCTL,        "NT IOCTL"},
+       {NT_TRANS_SSD,          "NT SET SECURITY DESC"},
+       {NT_TRANS_NOTIFY,       "NT NOTIFY"},
+       {NT_TRANS_RENAME,       "NT RENAME"},
+       {NT_TRANS_QSD,          "NT QUERY SECURITY DESC"},
+       {0, NULL}
+};
 
-       offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
+static const value_string nt_ioctl_isfsctl_vals[] = {
+       {0,     "Device IOCTL"},
+       {1,     "FS control : FSCTL"},
+       {0, NULL}
+};
 
-       /* Build display for: NativeOS */
+#define NT_IOCTL_FLAGS_ROOT_HANDLE     0x01
+static const true_false_string tfs_nt_ioctl_flags_root_handle = {
+       "Apply the command to share root handle (MUST BE Dfs)",
+       "Apply to this share",
+};
 
-       NativeOS = pd + offset;
+static const value_string nt_notify_action_vals[] = {
+       {1,     "ADDED (object was added"},
+       {2,     "REMOVED (object was removed)"},
+       {3,     "MODIFIED (object was modified)"},
+       {4,     "RENAMED_OLD_NAME (this is the old name of object)"},
+       {5,     "RENAMED_NEW_NAME (this is the new name of object)"},
+       {6,     "ADDED_STREAM (a stream was added)"},
+       {7,     "REMOVED_STREAM (a stream was removed)"},
+       {8,     "MODIFIED_STREAM (a stream was modified)"},
+       {0, NULL}
+};
 
-       if (tree) {
+static const value_string watch_tree_vals[] = {
+       {0,     "Current directory only"},
+       {1,     "Subdirectories also"},
+       {0, NULL}
+};
 
-         proto_tree_add_text(tree, NullTVB, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
+#define NT_NOTIFY_STREAM_WRITE 0x00000800
+#define NT_NOTIFY_STREAM_SIZE  0x00000400
+#define NT_NOTIFY_STREAM_NAME  0x00000200
+#define NT_NOTIFY_SECURITY     0x00000100
+#define NT_NOTIFY_EA           0x00000080
+#define NT_NOTIFY_CREATION     0x00000040
+#define NT_NOTIFY_LAST_ACCESS  0x00000020
+#define NT_NOTIFY_LAST_WRITE   0x00000010
+#define NT_NOTIFY_SIZE         0x00000008
+#define NT_NOTIFY_ATTRIBUTES   0x00000004
+#define NT_NOTIFY_DIR_NAME     0x00000002
+#define NT_NOTIFY_FILE_NAME    0x00000001
+static const true_false_string tfs_nt_notify_stream_write = {
+       "Notify on changes to STREAM WRITE",
+       "Do NOT notify on changes to stream write",
+};
+static const true_false_string tfs_nt_notify_stream_size = {
+       "Notify on changes to STREAM SIZE",
+       "Do NOT notify on changes to stream size",
+};
+static const true_false_string tfs_nt_notify_stream_name = {
+       "Notify on changes to STREAM NAME",
+       "Do NOT notify on changes to stream name",
+};
+static const true_false_string tfs_nt_notify_security = {
+       "Notify on changes to SECURITY",
+       "Do NOT notify on changes to security",
+};
+static const true_false_string tfs_nt_notify_ea = {
+       "Notify on changes to EA",
+       "Do NOT notify on changes to EA",
+};
+static const true_false_string tfs_nt_notify_creation = {
+       "Notify on changes to CREATION TIME",
+       "Do NOT notify on changes to creation time",
+};
+static const true_false_string tfs_nt_notify_last_access = {
+       "Notify on changes to LAST ACCESS TIME",
+       "Do NOT notify on changes to last access time",
+};
+static const true_false_string tfs_nt_notify_last_write = {
+       "Notify on changes to LAST WRITE TIME",
+       "Do NOT notify on changes to last write time",
+};
+static const true_false_string tfs_nt_notify_size = {
+       "Notify on changes to SIZE",
+       "Do NOT notify on changes to size",
+};
+static const true_false_string tfs_nt_notify_attributes = {
+       "Notify on changes to ATTRIBUTES",
+       "Do NOT notify on changes to attributes",
+};
+static const true_false_string tfs_nt_notify_dir_name = {
+       "Notify on changes to DIR NAME",
+       "Do NOT notify on changes to dir name",
+};
+static const true_false_string tfs_nt_notify_file_name = {
+       "Notify on changes to FILE NAME",
+       "Do NOT notify on changes to file name",
+};
 
-       }
+static const value_string create_disposition_vals[] = {
+       {0,     "Supersede (supersede existing file (if it exists))"},
+       {1,     "Open (if file exists open it, else fail)"},
+       {2,     "Create (if file exists fail, else create it)"},
+       {3,     "Open If (if file exists open it, else create it)"},
+       {4,     "Overwrite (if file exists overwrite, else fail)"},
+       {5,     "Overwrite If (if file exists overwrite, else create it)"},
+       {0, NULL}
+};
 
-       offset += strlen(NativeOS) + 1; /* Skip NativeOS */
+static const value_string impersonation_level_vals[] = {
+       {0,     "Anonymous"},
+       {1,     "Identification"},
+       {2,     "Impersonation"},
+       {3,     "Delegation"},
+       {0, NULL}
+};
 
-       /* Build display for: NativeLanMan */
+static const true_false_string tfs_nt_security_flags_context_tracking = {
+       "Security tracking mode is DYNAMIC",
+       "Security tracking mode is STATIC",
+};
 
-       NativeLanMan = pd + offset;
+static const true_false_string tfs_nt_security_flags_effective_only = {
+       "ONLY ENABLED aspects of the client's security context are available",
+       "ALL aspects of the client's security context are available",
+};
 
-       if (tree) {
+static const true_false_string tfs_nt_create_bits_oplock = {
+       "Requesting OPLOCK",
+       "Does NOT request oplock"
+};
 
-         proto_tree_add_text(tree, NullTVB, offset, strlen(NativeLanMan) + 1, "Native Lan Manager: %s", NativeLanMan);
+static const true_false_string tfs_nt_create_bits_boplock = {
+       "Requesting BATCH OPLOCK",
+       "Does NOT request batch oplock"
+};
 
-       }
+/*
+ * XXX - must be a directory, and can be a file, or can be a directory,
+ * and must be a file?
+ */
+static const true_false_string tfs_nt_create_bits_dir = {
+       "Target of open MUST be a DIRECTORY",
+       "Target of open can be a file"
+};
 
-       offset += strlen(NativeLanMan) + 1; /* Skip NativeLanMan */
+static const true_false_string tfs_nt_access_mask_generic_read = {
+       "GENERIC READ is set",
+       "Generic read is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_generic_write = {
+       "GENERIC WRITE is set",
+       "Generic write is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_generic_execute = {
+       "GENERIC EXECUTE is set",
+       "Generic execute is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_generic_all = {
+       "GENERIC ALL is set",
+       "Generic all is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_maximum_allowed = {
+       "MAXIMUM ALLOWED is set",
+       "Maximum allowed is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_system_security = {
+       "SYSTEM SECURITY is set",
+       "System security is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_synchronize = {
+       "Can wait on handle to SYNCHRONIZE on completion of I/O",
+       "Can NOT wait on handle to synchronize on completion of I/O"
+};
+static const true_false_string tfs_nt_access_mask_write_owner = {
+       "Can WRITE OWNER (take ownership)",
+       "Can NOT write owner (take ownership)"
+};
+static const true_false_string tfs_nt_access_mask_write_dac = {
+       "OWNER may WRITE the DAC",
+       "Owner may NOT write to the DAC"
+};
+static const true_false_string tfs_nt_access_mask_read_control = {
+       "READ ACCESS to owner, group and ACL of the SID",
+       "Read access is NOT granted to owner, group and ACL of the SID"
+};
+static const true_false_string tfs_nt_access_mask_delete = {
+       "DELETE access",
+       "NO delete access"
+};
+static const true_false_string tfs_nt_access_mask_write_attributes = {
+       "WRITE ATTRIBUTES access",
+       "NO write attributes access"
+};
+static const true_false_string tfs_nt_access_mask_read_attributes = {
+       "READ ATTRIBUTES access",
+       "NO read attributes access"
+};
+static const true_false_string tfs_nt_access_mask_delete_child = {
+       "DELETE CHILD access",
+       "NO delete child access"
+};
+static const true_false_string tfs_nt_access_mask_execute = {
+       "EXECUTE access",
+       "NO execute access"
+};
+static const true_false_string tfs_nt_access_mask_write_ea = {
+       "WRITE EXTENDED ATTRIBUTES access",
+       "NO write extended attributes access"
+};
+static const true_false_string tfs_nt_access_mask_read_ea = {
+       "READ EXTENDED ATTRIBUTES access",
+       "NO read extended attributes access"
+};
+static const true_false_string tfs_nt_access_mask_append = {
+       "APPEND access",
+       "NO append access"
+};
+static const true_false_string tfs_nt_access_mask_write = {
+       "WRITE access",
+       "NO write access"
+};
+static const true_false_string tfs_nt_access_mask_read = {
+       "READ access",
+       "NO read access"
+};
 
-      }
+static const true_false_string tfs_nt_share_access_delete = {
+       "Object can be shared for DELETE",
+       "Object can NOT be shared for delete"
+};
+static const true_false_string tfs_nt_share_access_write = {
+       "Object can be shared for WRITE",
+       "Object can NOT be shared for write"
+};
+static const true_false_string tfs_nt_share_access_read = {
+       "Object can be shared for READ",
+       "Object can NOT be shared for delete"
+};
 
-      break;
+static const value_string oplock_level_vals[] = {
+       {0,     "No oplock granted"},
+       {1,     "Exclusive oplock granted"},
+       {2,     "Batch oplock granted"},
+       {3,     "Level II oplock granted"},
+       {0, NULL}
+};
 
-    case 12:
+static const value_string device_type_vals[] = {
+       {0x00000001,    "Beep"},
+       {0x00000002,    "CDROM"},
+       {0x00000003,    "CDROM Filesystem"},
+       {0x00000004,    "Controller"},
+       {0x00000005,    "Datalink"},
+       {0x00000006,    "Dfs"},
+       {0x00000007,    "Disk"},
+       {0x00000008,    "Disk Filesystem"},
+       {0x00000009,    "Filesystem"},
+       {0x0000000a,    "Inport Port"},
+       {0x0000000b,    "Keyboard"},
+       {0x0000000c,    "Mailslot"},
+       {0x0000000d,    "MIDI-In"},
+       {0x0000000e,    "MIDI-Out"},
+       {0x0000000f,    "Mouse"},
+       {0x00000010,    "Multi UNC Provider"},
+       {0x00000011,    "Named Pipe"},
+       {0x00000012,    "Network"},
+       {0x00000013,    "Network Browser"},
+       {0x00000014,    "Network Filesystem"},
+       {0x00000015,    "NULL"},
+       {0x00000016,    "Parallel Port"},
+       {0x00000017,    "Physical card"},
+       {0x00000018,    "Printer"},
+       {0x00000019,    "Scanner"},
+       {0x0000001a,    "Serial Mouse port"},
+       {0x0000001b,    "Serial port"},
+       {0x0000001c,    "Screen"},
+       {0x0000001d,    "Sound"},
+       {0x0000001e,    "Streams"},
+       {0x0000001f,    "Tape"},
+       {0x00000020,    "Tape Filesystem"},
+       {0x00000021,    "Transport"},
+       {0x00000022,    "Unknown"},
+       {0x00000023,    "Video"},
+       {0x00000024,    "Virtual Disk"},
+       {0x00000025,    "WAVE-In"},
+       {0x00000026,    "WAVE-Out"},
+       {0x00000027,    "8042 Port"},
+       {0x00000028,    "Network Redirector"},
+       {0x00000029,    "Battery"},
+       {0x0000002a,    "Bus Extender"},
+       {0x0000002b,    "Modem"},
+       {0x0000002c,    "VDM"},
+       {0,     NULL}
+};
 
-      /* Build display for: AndXCommand */
+static const value_string is_directory_vals[] = {
+       {0,     "This is NOT a directory"},
+       {1,     "This is a DIRECTORY"},
+       {0, NULL}
+};
 
-      AndXCommand = GBYTE(pd, offset);
+typedef struct _nt_trans_data {
+       guint32 sd_len;
+       guint32 ea_len;
+} nt_trans_data;
 
-      if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                            (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
-      }
+static int
+dissect_nt_security_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint8 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      offset += 1; /* Skip AndXCommand */
+       mask = tvb_get_guint8(tvb, offset);
 
-      /* Build display for: AndXReserved */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+                       "Security Flags: 0x%02x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_security_flags);
+       }
 
-      AndXReserved = GBYTE(pd, offset);
+       proto_tree_add_boolean(tree, hf_smb_nt_security_flags_context_tracking,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_security_flags_effective_only,
+               tvb, offset, 1, mask);
 
-      if (tree) {
+       offset += 1;
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+       return offset;
+}
 
-      }
+static int
+dissect_nt_share_access(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      offset += 1; /* Skip AndXReserved */
+       mask = tvb_get_letohl(tvb, offset);
 
-      /* Build display for: AndXOffset */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Share Access: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_share_access);
+       }
 
-      AndXOffset = GSHORT(pd, offset);
+       proto_tree_add_boolean(tree, hf_smb_nt_share_access_delete,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_share_access_write,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_share_access_read,
+               tvb, offset, 4, mask);
 
-      if (tree) {
+       offset += 4;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+       return offset;
+}
 
-      }
 
-      offset += 2; /* Skip AndXOffset */
+static int
+dissect_nt_access_mask(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      /* Build display for: MaxBufferSize */
+       mask = tvb_get_letohl(tvb, offset);
 
-      MaxBufferSize = GSHORT(pd, offset);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Access Mask: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_access_mask);
+       }
 
-      if (tree) {
+       /*
+        * Some of these bits come from 
+        *
+        *      http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+        *
+        * and others come from the section on ZwOpenFile in "Windows(R)
+        * NT(R)/2000 Native API Reference".
+        */
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_read,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_write,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_execute,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_all,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_maximum_allowed,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_system_security,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_synchronize,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_owner,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_dac,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read_control,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_delete,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_attributes,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read_attributes,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_delete_child,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_execute,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_ea,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read_ea,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_append,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read,
+               tvb, offset, 4, mask);
+
+       offset += 4;
+
+       return offset;
+}
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
+static int
+dissect_nt_create_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      }
+       mask = tvb_get_letohl(tvb, offset);
 
-      offset += 2; /* Skip MaxBufferSize */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Create Flags: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_create_bits);
+       }
 
-      /* Build display for: MaxMpxCount */
+       /*
+        * XXX - it's 0x00000016 in at least one capture, but
+        * Network Monitor doesn't say what the 0x00000010 bit is.
+        * Does the Win32 API documentation, or NT Native API book,
+        * suggest anything?
+        */
+       proto_tree_add_boolean(tree, hf_smb_nt_create_bits_dir,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_bits_boplock,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_bits_oplock,
+               tvb, offset, 4, mask);
 
-      MaxMpxCount = GSHORT(pd, offset);
+       offset += 4;
 
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
-
-      }
-
-      offset += 2; /* Skip MaxMpxCount */
-
-      /* Build display for: VcNumber */
-
-      VcNumber = GSHORT(pd, offset);
+       return offset;
+}
 
-      if (tree) {
+/*
+ * XXX - there are some more flags in the description of "ZwOpenFile()"
+ * in "Windows(R) NT(R)/2000 Native API Reference"; do those go over
+ * the wire as well?  (The spec at
+ *
+ *     http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+ *
+ * says that "the FILE_NO_INTERMEDIATE_BUFFERING option is not exported
+ * via the SMB protocol.  The NT redirector should convert this option
+ * to FILE_WRITE_THROUGH."
+ *
+ * The "Sync I/O Alert" and "Sync I/O Nonalert" are given the bit
+ * values one would infer from their position in the list of flags for
+ * "ZwOpenFile()".  Most of the others probably have those values
+ * as well, although "8.3 only" would collide with FILE_OPEN_FOR_RECOVERY,
+ * which might go over the wire (for the benefit of backup/restore software).
+ */
+static const true_false_string tfs_nt_create_options_directory = {
+       "File being created/opened must be a directory",
+       "File being created/opened must not be a directory"
+};
+static const true_false_string tfs_nt_create_options_write_through = {
+       "Writes should flush buffered data before completing",
+       "Writes need not flush buffered data before completing"
+};
+static const true_false_string tfs_nt_create_options_sequential_only = {
+       "The file will only be accessed sequentially",
+       "The file might not only be accessed sequentially"
+};
+static const true_false_string tfs_nt_create_options_sync_io_alert = {
+       "All operations SYNCHRONOUS, waits subject to termination from alert",
+       "Operations NOT necessarily synchronous"
+};
+static const true_false_string tfs_nt_create_options_sync_io_nonalert = {
+       "All operations SYNCHRONOUS, waits not subject to alert",
+       "Operations NOT necessarily synchronous"
+};
+static const true_false_string tfs_nt_create_options_non_directory = {
+       "File being created/opened must not be a directory",
+       "File being created/opened must be a directory"
+};
+static const true_false_string tfs_nt_create_options_no_ea_knowledge = {
+       "The client does not understand extended attributes",
+       "The client understands extended attributes"
+};
+static const true_false_string tfs_nt_create_options_eight_dot_three_only = {
+       "The client understands only 8.3 file names",
+       "The client understands long file names"
+};
+static const true_false_string tfs_nt_create_options_random_access = {
+       "The file will be accessed randomly",
+       "The file will not be accessed randomly"
+};
+static const true_false_string tfs_nt_create_options_delete_on_close = {
+       "The file should be deleted when it is closed",
+       "The file should not be deleted when it is closed"
+};
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
+static int
+dissect_nt_create_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      }
+       mask = tvb_get_letohl(tvb, offset);
 
-      offset += 2; /* Skip VcNumber */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Create Options: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_create_options);
+       }
 
-      /* Build display for: SessionKey */
+       /*
+        * From
+        *
+        *      http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+        */
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_directory_file,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_write_through,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_sequential_only,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_sync_io_alert,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_sync_io_nonalert,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_non_directory_file,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_no_ea_knowledge,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_eight_dot_three_only,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_random_access,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_create_options_delete_on_close,
+               tvb, offset, 4, mask);
+
+       offset += 4;
+
+       return offset;
+}
+static int
+dissect_nt_notify_completion_filter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      SessionKey = GWORD(pd, offset);
+       mask = tvb_get_letohl(tvb, offset);
 
-      if (tree) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Completion Filter: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_notify_completion_filter);
+       }
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_stream_write,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_stream_size,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_stream_name,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_security,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_ea,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_creation,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_last_access,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_last_write,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_size,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_attributes,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_dir_name,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_notify_file_name,
+               tvb, offset, 4, mask);
+
+       offset += 4;
+       return offset;
+}
+static int
+dissect_nt_ioctl_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint8 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
+       mask = tvb_get_guint8(tvb, offset);
 
-      }
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+                       "Completion Filter: 0x%02x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_nt_ioctl_flags);
+       }
 
-      offset += 4; /* Skip SessionKey */
+       proto_tree_add_boolean(tree, hf_smb_nt_ioctl_flags_root_handle,
+               tvb, offset, 1, mask);
 
-      /* Build display for: Security Blob Length */
+       offset += 1;
+       return offset;
+}
 
-      SecurityBlobLength = GSHORT(pd, offset);
+/*
+ * From the section on ZwQuerySecurityObject in "Windows(R) NT(R)/2000
+ * Native API Reference".
+ */
+static const true_false_string tfs_nt_qsd_owner = {
+       "Requesting OWNER security information",
+       "NOT requesting owner security information",
+};
 
-      if (tree) {
+static const true_false_string tfs_nt_qsd_group = {
+       "Requesting GROUP security information",
+       "NOT requesting group security information",
+};
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Security Blob Length: %u", SecurityBlobLength);
+static const true_false_string tfs_nt_qsd_dacl = {
+       "Requesting DACL security information",
+       "NOT requesting DACL security information",
+};
 
-      }
+static const true_false_string tfs_nt_qsd_sacl = {
+       "Requesting SACL security information",
+       "NOT requesting SACL security information",
+};
 
-      offset += 2; /* Skip Security Blob Length */
+#define NT_QSD_OWNER   0x00000001
+#define NT_QSD_GROUP   0x00000002
+#define NT_QSD_DACL    0x00000004
+#define NT_QSD_SACL    0x00000008
 
-      /* Build display for: Reserved */
+static int
+dissect_security_information_mask(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      Reserved = GWORD(pd, offset);
+       mask = tvb_get_letohl(tvb, offset);
 
-      if (tree) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Security Information: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_security_information_mask);
+       }
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
+       proto_tree_add_boolean(tree, hf_smb_nt_qsd_owner,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_qsd_group,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_qsd_dacl,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_nt_qsd_sacl,
+               tvb, offset, 4, mask);
 
-      }
+       offset += 4;
 
-      offset += 4; /* Skip Reserved */
+       return offset;
+}
 
-      /* Build display for: Capabilities */
 
-      Capabilities = GWORD(pd, offset);
+static int
+dissect_nt_trans_data_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
 
-      if (tree) {
+       si = (smb_info_t *)pinfo->private_data;
 
-        ti = proto_tree_add_text(tree, NullTVB, offset, 4, "Capabilities: 0x%08x", Capabilities);
-        Capabilities_tree = proto_item_add_subtree(ti, ett_smb_capabilities);
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0001, 32, " Raw Mode supported", " Raw Mode not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0002, 32, " Raw Mode supported", " MPX Mode not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0004, 32," Unicode supported", " Unicode not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0008, 32, " Large Files supported", " Large Files not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0010, 32, " NT LM 0.12 SMBs supported", " NT LM 0.12 SMBs not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0020, 32, " RPC Remote APIs supported", " RPC Remote APIs not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0040, 32, " NT Status Codes supported", " NT Status Codes not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0080, 32, " Level 2 OpLocks supported", " Level 2 OpLocks not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0100, 32, " Lock&Read supported", " Lock&Read not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0200, 32, " NT Find supported", " NT Find not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x1000, 32, " DFS supported", " DFS not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x4000, 32, " Large READX supported", " Large READX not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x8000, 32, " Large WRITEX supported", " Large WRITEX not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x80000000, 32, " Extended Security Exchanges supported", " Extended Security Exchanges not supported"));
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Data",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+               tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+       }
 
-      }
+       switch(si->subcmd){
+       case NT_TRANS_CREATE:
+               /* security descriptor */
+               if(ntd->sd_len){
+                       proto_tree_add_item(tree, hf_smb_security_descriptor, tvb, offset, ntd->sd_len, TRUE);
+                       offset += ntd->sd_len;
+               }
+
+               /* extended attributes */
+               if(ntd->ea_len){
+                       proto_tree_add_item(tree, hf_smb_extended_attributes, tvb, offset, ntd->ea_len, TRUE);
+                       offset += ntd->ea_len;
+               }
+
+               break;
+       case NT_TRANS_IOCTL:
+               /* ioctl data */
+               proto_tree_add_item(tree, hf_smb_nt_ioctl_data, tvb, offset, len, TRUE);
+               offset += len;
+
+               break;
+       case NT_TRANS_SSD:
+               proto_tree_add_item(tree, hf_smb_security_descriptor, tvb, offset, len, TRUE);
+               offset += len;
+               break;
+       case NT_TRANS_NOTIFY:
+               break;
+       case NT_TRANS_RENAME:
+               /* XXX not documented */
+               break;
+       case NT_TRANS_QSD:
+               break;
+       }
 
-      offset += 4; /* Skip Capabilities */
+       return offset;
+}
 
-      /* Build display for: Byte Count */
+static int
+dissect_nt_trans_param_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd, guint16 bc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       guint32 fn_len;
+       const char *fn;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Parameters",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+               tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+       }
 
-      ByteCount = GSHORT(pd, offset);
+       switch(si->subcmd){
+       case NT_TRANS_CREATE:
+               /* Create flags */
+               offset = dissect_nt_create_bits(tvb, pinfo, tree, offset);
+               bc -= 4;
 
-      if (tree) {
+               /* root directory fid */
+               proto_tree_add_item(tree, hf_smb_root_dir_fid, tvb, offset, 4, TRUE);
+               COUNT_BYTES(4);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+               /* nt access mask */
+               offset = dissect_nt_access_mask(tvb, pinfo, tree, offset);
+               bc -= 4;
+       
+               /* allocation size */
+               proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+               COUNT_BYTES(8);
+       
+               /* Extended File Attributes */
+               offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
+               bc -= 4;
 
-      }
+               /* share access */
+               offset = dissect_nt_share_access(tvb, pinfo, tree, offset);
+               bc -= 4;
+       
+               /* create disposition */
+               proto_tree_add_item(tree, hf_smb_nt_create_disposition, tvb, offset, 4, TRUE);
+               COUNT_BYTES(4);
+
+               /* create options */
+               offset = dissect_nt_create_options(tvb, pinfo, tree, offset);
+               bc -= 4;
+
+               /* sd length */
+               ntd->sd_len = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_sd_length, tvb, offset, 4, ntd->sd_len);
+               COUNT_BYTES(4);
+
+               /* ea length */
+               ntd->ea_len = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_ea_length, tvb, offset, 4, ntd->ea_len);
+               COUNT_BYTES(4);
+
+               /* file name len */
+               fn_len = (guint32)tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+               COUNT_BYTES(4);
+
+               /* impersonation level */
+               proto_tree_add_item(tree, hf_smb_nt_impersonation_level, tvb, offset, 4, TRUE);
+               COUNT_BYTES(4);
+       
+               /* security flags */
+               offset = dissect_nt_security_flags(tvb, pinfo, tree, offset);
+               bc -= 1;
+
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, TRUE, TRUE, &bc);
+               if (fn != NULL) {
+                       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                               fn);
+                       COUNT_BYTES(fn_len);
+               }
+
+               break;
+       case NT_TRANS_IOCTL:
+               break;
+       case NT_TRANS_SSD:
+               /* fid */
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* 2 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* security information */
+               offset = dissect_security_information_mask(tvb, pinfo, tree, offset);
+               break;
+       case NT_TRANS_NOTIFY:
+               break;
+       case NT_TRANS_RENAME:
+               /* XXX not documented */
+               break;
+       case NT_TRANS_QSD:
+               /* fid */
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* 2 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* security information */
+               offset = dissect_security_information_mask(tvb, pinfo, tree, offset);
+               break;
+       }
 
-      offset += 2; /* Skip Byte Count */
+       return offset;
+}
 
-      if (ByteCount > 0) {
+static int
+dissect_nt_trans_setup_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       int old_offset = offset;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Setup",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+               tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+       }
+       switch(si->subcmd){
+       case NT_TRANS_CREATE:
+               break;
+       case NT_TRANS_IOCTL:
+               /* function code */
+               proto_tree_add_item(tree, hf_smb_nt_ioctl_function_code, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* fid */
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* isfsctl */
+               proto_tree_add_item(tree, hf_smb_nt_ioctl_isfsctl, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               /* isflags */
+               offset = dissect_nt_ioctl_flags(tvb, pinfo, tree, offset);
+
+               break;
+       case NT_TRANS_SSD:
+               break;
+       case NT_TRANS_NOTIFY:
+               /* completion filter */
+               offset = dissect_nt_notify_completion_filter(tvb, pinfo, tree, offset);
+
+               /* fid */
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* watch tree */
+               proto_tree_add_item(tree, hf_smb_nt_notify_watch_tree, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               /* reserved byte */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               break;
+       case NT_TRANS_RENAME:
+               /* XXX not documented */
+               break;
+       case NT_TRANS_QSD:
+               break;
+       }
+       return old_offset+len;
+}
 
-        /* Build display for: Security Blob */
 
-        SecurityBlob = pd + offset;
+static int
+dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc, sc;
+       guint32 pc=0, po=0, pd, dc=0, od=0, dd;
+       smb_info_t *si;
+       nt_trans_data ntd;
+       guint16 bc;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       WORD_COUNT;
+
+       if(wc>=19){
+               /* primary request */
+               /* max setup count */
+               proto_tree_add_item(tree, hf_smb_max_setup_count, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               /* 2 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               offset += 2;
+       } else {
+               /* secondary request */
+               /* 3 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 3, TRUE);
+               offset += 3;
+       }
 
-        if (SecurityBlobLength > 0) {
 
-          /* XXX - is this ASN.1-encoded?  Is it a Kerberos data structure,
-             at least in NT 5.0-and-later server replies? */
+       /* total param count */
+       proto_tree_add_item(tree, hf_smb_total_param_count, tvb, offset, 4, TRUE);
+       offset += 4;
+       
+       /* total data count */
+       proto_tree_add_item(tree, hf_smb_total_data_count, tvb, offset, 4, TRUE);
+       offset += 4;
+
+       if(wc>=19){
+               /* primary request */
+               /* max param count */
+               proto_tree_add_item(tree, hf_smb_max_param_count, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* max data count */
+               proto_tree_add_item(tree, hf_smb_max_data_count, tvb, offset, 4, TRUE);
+               offset += 4;
+       }
 
-          if (tree) {
+       /* param count */
+       pc = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_count32, tvb, offset, 4, pc);
+       offset += 4;
+       
+       /* param offset */
+       po = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_offset32, tvb, offset, 4, po);
+       offset += 4;
+
+       /* param displacement */
+       if(wc>=19){
+               /* primary request*/
+               pd = 0;
+       } else {
+               /* secondary request */
+               pd = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_param_disp32, tvb, offset, 4, pd);
+               offset += 4;
+       }
 
-            proto_tree_add_text(tree, NullTVB, offset, SecurityBlobLength, "Security Blob: %s",
-                                bytes_to_str(SecurityBlob, SecurityBlobLength));
+       /* data count */
+       dc = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_count32, tvb, offset, 4, dc);
+       offset += 4;
 
-          }
+       /* data offset */
+       od = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_offset32, tvb, offset, 4, od);
+       offset += 4;
 
-          offset += SecurityBlobLength; /* Skip Security Blob */
+       /* data displacement */
+       if(wc>=19){
+               /* primary request */
+               dd = 0;
+       } else {
+               /* secondary request */
+               dd = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_data_disp32, tvb, offset, 4, dd);
+               offset += 4;
+       }
 
-        }
+       /* setup count */
+       if(wc>=19){
+               /* primary request */
+               sc = tvb_get_guint8(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+               offset += 1;
+       } else {
+               /* secondary request */
+               sc = 0;
+       }
 
-        /* Build display for: Native OS */
+       /* function */
+       if(wc>=19){
+               /* primary request */
+               si->subcmd = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_nt_trans_subcmd, tvb, offset, 2, si->subcmd);
+               if(check_col(pinfo->fd, COL_INFO)){
+                       col_append_fstr(pinfo->fd, COL_INFO, ", %s",
+                               val_to_str(si->subcmd, nt_cmd_vals, "<unknown>"));
+               }
+       } else {
+               /* secondary request */
+               if(check_col(pinfo->fd, COL_INFO)){
+                       col_append_fstr(pinfo->fd, COL_INFO, " (secondary request)");
+               }
+       }
+       offset += 2;
 
-        NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       /* this is a padding byte */
+       if(offset%1){
+               /* pad byte */
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 1, TRUE);
+               offset += 1;
+       }
 
-        if (tree) {
+       /* if there were any setup bytes, decode them */
+       if(sc){
+               dissect_nt_trans_setup_request(tvb, pinfo, offset, tree, sc*2, &ntd);
+               offset += sc*2;
+       }
 
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "Native OS: %s", NativeOS);
+       BYTE_COUNT;
+       
+       /* parameters */
+       if(po>(guint32)offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = po-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(pc){
+               CHECK_BYTE_COUNT(pc);
+               dissect_nt_trans_param_request(tvb, pinfo, offset, tree, pc, &ntd, bc);
+               COUNT_BYTES(pc);
+       }
 
-        }
+       /* data */
+       if(od>(guint32)offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = od-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(dc){
+               CHECK_BYTE_COUNT(dc);
+               dissect_nt_trans_data_request(tvb, pinfo, offset, tree, dc, &ntd);
+               COUNT_BYTES(dc);
+       }
 
-        offset += string_len; /* Skip Native OS */
+       END_OF_SMB
 
-        /* Build display for: Native LanMan Type */
+       return offset;
+}
 
-        NativeLanManType = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-        if (tree) {
 
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "Native LanMan Type: %s", NativeLanManType);
+static int
+dissect_nt_trans_data_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               if(si->frame_req != 0){
+                       item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Data",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+               } else {
+                       /*
+                        * We never saw the request to which this is a
+                        * response.
+                        */
+                       item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Data",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (matching request not seen)"));
+               }
+               tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+       }
 
-        }
+       switch(si->subcmd){
+       case NT_TRANS_CREATE:
+               break;
+       case NT_TRANS_IOCTL:
+               /* ioctl data */
+               proto_tree_add_item(tree, hf_smb_nt_ioctl_data, tvb, offset, len, TRUE);
+               offset += len;
+
+               break;
+       case NT_TRANS_SSD:
+               break;
+       case NT_TRANS_NOTIFY:
+               break;
+       case NT_TRANS_RENAME:
+               /* XXX not documented */
+               break;
+       case NT_TRANS_QSD:
+               /*
+                * XXX - this is probably a SECURITY_DESCRIPTOR structure,
+                * which may be documented in the Win32 documentation
+                * somewhere.
+                */
+               proto_tree_add_item(tree, hf_smb_security_descriptor, tvb, offset, len, TRUE);
+               offset += len;
+               break;
+       }
 
-        offset += string_len; /* Skip Native LanMan Type */
+       return offset;
+}
+static int
+dissect_nt_trans_param_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd, guint16 bc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       guint32 fn_len;
+       const char *fn;
+       smb_info_t *si;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               if(si->frame_req != 0){
+                       item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Parameters",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+               } else {
+                       /*
+                        * We never saw the request to which this is a
+                        * response.
+                        */
+                       item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Parameters",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (matching request not seen)"));
+               }
+               tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+       }
 
-        /* Build display for: Primary Domain */
+       switch(si->subcmd){
+       case NT_TRANS_CREATE:
+               /* oplock level */
+               proto_tree_add_item(tree, hf_smb_oplock_level, tvb, offset, 1, TRUE);
+               offset += 1;
 
-        PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+               /* reserved byte */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+               offset += 1;
+               
+               /* fid */
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               offset += 2;
 
-        if (tree) {
+               /* create action */
+               proto_tree_add_item(tree, hf_smb_create_action, tvb, offset, 4, TRUE);
+               offset += 4;
 
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "Primary Domain: %s", PrimaryDomain);
+               /* ea error offset */
+               proto_tree_add_item(tree, hf_smb_ea_error_offset, tvb, offset, 4, TRUE);
+               offset += 4;
 
-        }
+               /* create time */
+               offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                       "Create Time", hf_smb_create_time);
+       
+               /* access time */
+               offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                       "Access Time", hf_smb_access_time);
+       
+               /* last write time */
+               offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                       "Write Time", hf_smb_last_write_time);
+       
+               /* last change time */
+               offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                       "Change Time", hf_smb_change_time);
+       
+               /* Extended File Attributes */
+               offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
+
+               /* allocation size */
+               proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+               offset += 8;
+
+               /* end of file */
+               proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+               offset += 8;
+
+               /* File Type */
+               proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* device state */
+               offset = dissect_ipc_state(tvb, pinfo, tree, offset);
+
+               /* is directory */
+               proto_tree_add_item(tree, hf_smb_is_directory, tvb, offset, 1, TRUE);
+               offset += 1;
+               break;
+       case NT_TRANS_IOCTL:
+               break;
+       case NT_TRANS_SSD:
+               break;
+       case NT_TRANS_NOTIFY:
+               while(len){
+                       /* next entry offset */
+                       proto_tree_add_item(tree, hf_smb_next_entry_offset, tvb, offset, 4, TRUE);
+                       COUNT_BYTES(4);
+                       len -= 4;
+                       /* broken implementations */
+                       if(len<0)break;
+       
+                       /* action */
+                       proto_tree_add_item(tree, hf_smb_nt_notify_action, tvb, offset, 4, TRUE);
+                       COUNT_BYTES(4);
+                       len -= 4;
+                       /* broken implementations */
+                       if(len<0)break;
+
+                       /* file name len */
+                       fn_len = (guint32)tvb_get_letohl(tvb, offset);
+                       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+                       COUNT_BYTES(4);
+                       len -= 4;
+                       /* broken implementations */
+                       if(len<0)break;
+
+                       /* file name */
+                       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, TRUE, TRUE, &bc);
+                       if (fn == NULL)
+                               break;
+                       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                               fn);
+                       COUNT_BYTES(fn_len);
+                       len -= fn_len;
+                       /* broken implementations */
+                       if(len<0)break;
+
+               }
+               break;
+       case NT_TRANS_RENAME:
+               /* XXX not documented */
+               break;
+       case NT_TRANS_QSD:
+               /*
+                * This appears to be the size of the security
+                * descriptor; the calling sequence of
+                * "ZwQuerySecurityObject()" suggests that it would
+                * be.  The actual security descriptor wouldn't
+                * follow if the max data count in the request
+                * was smaller; this lets the client know how
+                * big a buffer it needs to provide.
+                */
+               proto_tree_add_item(tree, hf_smb_security_descriptor_len, tvb, offset, 4, TRUE);
+               offset += 4;
+               break;
+       }
 
-        offset += string_len; /* Skip Primary Domain */
+       return offset;
+}
+static int
+dissect_nt_trans_setup_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               if(si->frame_req != 0){
+                       item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Setup",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+               } else {
+                       /*
+                        * We never saw the request to which this is a
+                        * response.
+                        */
+                       item = proto_tree_add_text(parent_tree, tvb, offset, len,
+                               "%s Setup",
+                               val_to_str(si->subcmd, nt_cmd_vals, "Unknown NT transaction (matching request not seen)"));
+               }
+               tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+       }
 
-      }
+       switch(si->subcmd){
+       case NT_TRANS_CREATE:
+               break;
+       case NT_TRANS_IOCTL:
+               break;
+       case NT_TRANS_SSD:
+               break;
+       case NT_TRANS_NOTIFY:
+               break;
+       case NT_TRANS_RENAME:
+               /* XXX not documented */
+               break;
+       case NT_TRANS_QSD:
+               break;
+       }
 
-      break;
+       return offset;
+}
 
-    case 13:
+static int
+dissect_nt_transaction_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc, sc;
+       guint32 pc=0, po=0, pd, dc=0, od=0, dd;
+       smb_info_t *si;
+       static nt_trans_data ntd;
+       guint16 bc;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       /* primary request */
+       if(si->frame_req != 0){
+               proto_tree_add_uint(tree, hf_smb_nt_trans_subcmd, tvb, 0, 0, si->subcmd);
+               if(check_col(pinfo->fd, COL_INFO)){
+                       col_append_fstr(pinfo->fd, COL_INFO, ", %s",
+                               val_to_str(si->subcmd, nt_cmd_vals, "<unknown (%u)>"));
+               }
+       } else {
+               proto_tree_add_text(tree, tvb, offset, 0,
+                       "Function: <unknown function - could not find matching request>");
+               if(check_col(pinfo->fd, COL_INFO)){
+                       col_append_fstr(pinfo->fd, COL_INFO, ", <unknown>");
+               }
+       }
 
-      /* Build display for: AndXCommand */
+       WORD_COUNT;
 
-      AndXCommand = GBYTE(pd, offset);
+       /* 3 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 3, TRUE);
+       offset += 3;
 
-      if (tree) {
+       /* total param count */
+       proto_tree_add_item(tree, hf_smb_total_param_count, tvb, offset, 4, TRUE);
+       offset += 4;
+       
+       /* total data count */
+       proto_tree_add_item(tree, hf_smb_total_data_count, tvb, offset, 4, TRUE);
+       offset += 4;
+
+       /* param count */
+       pc = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_count32, tvb, offset, 4, pc);
+       offset += 4;
+       
+       /* param offset */
+       po = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_offset32, tvb, offset, 4, po);
+       offset += 4;
+
+       /* param displacement */
+       pd = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_disp32, tvb, offset, 4, pd);
+       offset += 4;
+
+       /* data count */
+       dc = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_count32, tvb, offset, 4, dc);
+       offset += 4;
+
+       /* data offset */
+       od = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_offset32, tvb, offset, 4, od);
+       offset += 4;
+
+       /* data displacement */
+       dd = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_disp32, tvb, offset, 4, dd);
+       offset += 4;
+
+       /* setup count */
+       sc = tvb_get_guint8(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+       offset += 1;
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+       /* setup data */        
+       if(sc){
+               dissect_nt_trans_setup_response(tvb, pinfo, offset, tree, sc*2, &ntd);
+               offset += sc*2;
+       }
 
-      }
+       BYTE_COUNT;
+       
+       /* parameters */
+       if(po>(guint32)offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = po-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(pc){
+               CHECK_BYTE_COUNT(pc);
+               dissect_nt_trans_param_response(tvb, pinfo, offset, tree, pc, &ntd, bc);
+               COUNT_BYTES(pc);
+       }
 
-      offset += 1; /* Skip AndXCommand */
+       /* data */
+       if(od>(guint32)offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = od-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(dc){
+               CHECK_BYTE_COUNT(dc);
+               dissect_nt_trans_data_response(tvb, pinfo, offset, tree, dc, &ntd);
+               COUNT_BYTES(dc);
+       }
 
-      /* Build display for: AndXReserved */
+       END_OF_SMB
 
-      AndXReserved = GBYTE(pd, offset);
+       return offset;
+}
 
-      if (tree) {
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   NT Transaction command  ends here
+   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+static const value_string print_mode_vals[] = {
+       {0,     "Text Mode"},
+       {1,     "Graphics Mode"},
+       {0, NULL}
+};
+static int
+dissect_open_print_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-      }
+       WORD_COUNT;
 
-      offset += 1; /* Skip AndXReserved */
+       /* setup len */
+        proto_tree_add_item(tree, hf_smb_setup_len, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      /* Build display for: AndXOffset */
+       /* print mode */
+        proto_tree_add_item(tree, hf_smb_print_mode, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      AndXOffset = GSHORT(pd, offset);
+       BYTE_COUNT;
 
-      if (tree) {
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+       /* print identifier */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, TRUE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_print_identifier, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip AndXOffset */
+       return offset;
+}
 
-      /* Build display for: MaxBufferSize */
 
-      MaxBufferSize = GSHORT(pd, offset);
+static int
+dissect_write_print_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       int cnt;
+       guint8 wc;
+       guint16 bc;
 
-      if (tree) {
+       WORD_COUNT;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      }
+       BYTE_COUNT;
 
-      offset += 2; /* Skip MaxBufferSize */
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
 
-      /* Build display for: MaxMpxCount */
+       /* data len */
+       CHECK_BYTE_COUNT(2);
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, cnt);
+       COUNT_BYTES(2);
 
-      MaxMpxCount = GSHORT(pd, offset);
+       /* file data */
+       offset = dissect_file_data(tvb, pinfo, tree, offset, cnt, cnt);
 
-      if (tree) {
+       END_OF_SMB
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
+       return offset;
+}
 
-      }
 
-      offset += 2; /* Skip MaxMpxCount */
+static const value_string print_status_vals[] = {
+       {1,     "Held or Stopped"},
+       {2,     "Printing"},
+       {3,     "Awaiting print"},
+       {4,     "In intercept"},
+       {5,     "File had error"},
+       {6,     "Printer error"},
+       {0, NULL}
+};
+static int
+dissect_get_print_queue_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8 wc;
+       guint16 bc;
 
-      /* Build display for: VcNumber */
+       WORD_COUNT;
 
-      VcNumber = GSHORT(pd, offset);
+       /* max count */
+       proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      if (tree) {
+       /* start index */
+       proto_tree_add_item(tree, hf_smb_start_index, tvb, offset, 2, TRUE);
+       offset += 2;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
+       BYTE_COUNT;
 
-      }
+       END_OF_SMB
 
-      offset += 2; /* Skip VcNumber */
+       return offset;
+}
 
-      /* Build display for: SessionKey */
+static int
+dissect_print_queue_element(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       int fn_len;
+       const char *fn;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 28,
+                       "Queue entry");
+               tree = proto_item_add_subtree(item, ett_smb_print_queue_entry);
+       }
 
-      SessionKey = GWORD(pd, offset);
+       /* queued time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_print_queue_date,
+               hf_smb_print_queue_dos_date, hf_smb_print_queue_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* status */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_print_status, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+
+       /* spool file number */
+       CHECK_BYTE_COUNT_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_print_spool_file_number, tvb, offset, 2, TRUE);
+       COUNT_BYTES_SUBR(2);
+
+       /* spool file size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_print_spool_file_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* reserved byte */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+
+       /* file name */
+       fn_len = 16;
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, TRUE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_print_spool_file_name, tvb, offset, 16,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_get_print_queue_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint16 cnt=0, len;
+       guint8 wc;
+       guint16 bc;
+       gboolean trunc;
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
+       WORD_COUNT;
 
-      }
+       /* count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-      offset += 4; /* Skip SessionKey */
+       /* restart index */
+       proto_tree_add_item(tree, hf_smb_restart_index, tvb, offset, 2, TRUE);
+       offset += 2;
 
-      /* Build display for: ANSI Account Password Length */
+       BYTE_COUNT;
+
+       /* buffer format */
+       CHECK_BYTE_COUNT(1);
+       proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+       COUNT_BYTES(1);
+
+       /* data len */
+       CHECK_BYTE_COUNT(2);
+       len = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, len);
+       COUNT_BYTES(2);
+
+       /* queue elements */
+       while(cnt--){
+               offset = dissect_print_queue_element(tvb, pinfo, tree, offset,
+                   &bc, &trunc);
+               if (trunc)
+                       goto endofcommand;
+       }
 
-      ANSIAccountPasswordLength = GSHORT(pd, offset);
+       END_OF_SMB
 
-      if (tree) {
+       return offset;
+}
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "ANSI Account Password Length: %u", ANSIAccountPasswordLength);
 
-      }
+static int
+dissect_nt_create_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0;
+       guint16 bc;
+       int fn_len;
+       const char *fn;
+
+       WORD_COUNT;
+
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands (0xff)");
+       }
+       offset += 1;
 
-      offset += 2; /* Skip ANSI Account Password Length */
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      /* Build display for: UNICODE Account Password Length */
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-      UNICODEAccountPasswordLength = GSHORT(pd, offset);
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      if (tree) {
+       /* file name len */
+       fn_len = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 2, fn_len);
+       offset += 2;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "UNICODE Account Password Length: %u", UNICODEAccountPasswordLength);
+       /* Create flags */
+       offset = dissect_nt_create_bits(tvb, pinfo, tree, offset);
 
-      }
+       /* root directory fid */
+       proto_tree_add_item(tree, hf_smb_root_dir_fid, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      offset += 2; /* Skip UNICODE Account Password Length */
+       /* nt access mask */
+       offset = dissect_nt_access_mask(tvb, pinfo, tree, offset);
 
-      /* Build display for: Reserved */
+       /* allocation size */
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       offset += 8;
 
-      Reserved = GWORD(pd, offset);
+       /* Extended File Attributes */
+       offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
 
-      if (tree) {
+       /* share access */
+       offset = dissect_nt_share_access(tvb, pinfo, tree, offset);
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
+       /* create disposition */
+       proto_tree_add_item(tree, hf_smb_nt_create_disposition, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      }
+       /* create options */
+       offset = dissect_nt_create_options(tvb, pinfo, tree, offset);
 
-      offset += 4; /* Skip Reserved */
+       /* impersonation level */
+       proto_tree_add_item(tree, hf_smb_nt_impersonation_level, tvb, offset, 4, TRUE);
+       offset += 4;
 
-      /* Build display for: Capabilities */
+       /* security flags */
+       offset = dissect_nt_security_flags(tvb, pinfo, tree, offset);
 
-      Capabilities = GWORD(pd, offset);
+       BYTE_COUNT;
 
-      if (tree) {
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+       if (fn == NULL)
+               goto endofcommand;
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES(fn_len);
 
-        ti = proto_tree_add_text(tree, NullTVB, offset, 4, "Capabilities: 0x%08x", Capabilities);
-        Capabilities_tree = proto_item_add_subtree(ti, ett_smb_capabilities);
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0001, 32, " Raw Mode supported", " Raw Mode not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0002, 32, " Raw Mode supported", " MPX Mode not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0004, 32," Unicode supported", " Unicode not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0008, 32, " Large Files supported", " Large Files not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0010, 32, " NT LM 0.12 SMBs supported", " NT LM 0.12 SMBs not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0020, 32, " RPC Remote APIs supported", " RPC Remote APIs not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0040, 32, " NT Status Codes supported", " NT Status Codes not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0080, 32, " Level 2 OpLocks supported", " Level 2 OpLocks not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0100, 32, " Lock&Read supported", " Lock&Read not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x0200, 32, " NT Find supported", " NT Find not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x1000, 32, " DFS supported", " DFS not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x4000, 32, " Large READX supported", " Large READX not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x8000, 32, " Large WRITEX supported", " Large WRITEX not supported"));
-        proto_tree_add_text(Capabilities_tree, NullTVB, offset, 4, "%s",
-                            decode_boolean_bitfield(Capabilities, 0x80000000, 32, " Extended Security Exchanges supported", " Extended Security Exchanges not supported"));
-      
-      }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-      offset += 4; /* Skip Capabilities */
+       END_OF_SMB
 
-      /* Build display for: Byte Count */
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-      ByteCount = GSHORT(pd, offset);
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_nt_create_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       guint8  wc, cmd=0xff;
+       guint16 andxoffset=0;
+       guint16 bc;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+       WORD_COUNT;
 
-      }
+       /* next smb command */
+       cmd = tvb_get_guint8(tvb, offset);
+       if(cmd!=0xff){
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+       } else {
+               proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: No further commands");
+       }
+       offset += 1;
 
-      offset += 2; /* Skip Byte Count */
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-      if (ByteCount > 0) {
+       /* andxoffset */
+       andxoffset = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+       offset += 2;
 
-       /* Build display for: ANSI Password */
+       /* oplock level */
+       proto_tree_add_item(tree, hf_smb_oplock_level, tvb, offset, 1, TRUE);
+       offset += 1;
 
-       ANSIPassword = pd + offset;
+       /* fid */
+       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       if (ANSIAccountPasswordLength > 0) {
+       /* create action */
+       /*XXX is this really the same as create disposition in the request? it looks so*/
+       proto_tree_add_item(tree, hf_smb_create_action, tvb, offset, 4, TRUE);
+       offset += 4;
 
-           if (tree) {
+       /* create time */
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Create Time", hf_smb_create_time);
+       
+       /* access time */
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Access Time", hf_smb_access_time);
+       
+       /* last write time */
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Write Time", hf_smb_last_write_time);
+       
+       /* last change time */
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Change Time", hf_smb_change_time);
+       
+       /* Extended File Attributes */
+       offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
 
-               proto_tree_add_text(tree, NullTVB, offset, ANSIAccountPasswordLength, "ANSI Password: %s", format_text(ANSIPassword, ANSIAccountPasswordLength));
+       /* allocation size */
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       offset += 8;
 
-           }
+       /* end of file */
+       proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+       offset += 8;
 
-           offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
-       }
+       /* File Type */
+       proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+       offset += 2;
 
-       /* Build display for: UNICODE Password */
+       /* IPC State */
+       offset = dissect_ipc_state(tvb, pinfo, tree, offset);
 
-       UNICODEPassword = pd + offset;
+       /* is directory */
+       proto_tree_add_item(tree, hf_smb_is_directory, tvb, offset, 1, TRUE);
+       offset += 1;
 
-       if (UNICODEAccountPasswordLength > 0) {
+       BYTE_COUNT;
 
-         if (tree) {
+       END_OF_SMB
 
-           proto_tree_add_text(tree, NullTVB, offset, UNICODEAccountPasswordLength, "UNICODE Password: %s", format_text(UNICODEPassword, UNICODEAccountPasswordLength));
+       /* call AndXCommand (if there are any) */
+       dissect_smb_command(tvb, pinfo, tree, andxoffset, smb_tree, cmd);
 
-         }
+       return offset;
+}
 
-         offset += UNICODEAccountPasswordLength; /* Skip UNICODE Password */
 
+static int
+dissect_nt_cancel_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       smb_info_t      *sip;
+       guint8 wc;
+       guint16 bc;
+
+       /* XXX I think this correct to find the matching request, must test */
+       sip = pinfo->private_data;
+       sip->src = &pinfo->src;
+       sip->dst = &pinfo->dst;
+       sip = g_hash_table_lookup(smb_info_table, sip);
+       if(sip){
+               proto_tree_add_uint(tree, hf_smb_cancel_to, tvb, 0, 0, sip->frame_req);
+       } else {
+               proto_tree_add_text(tree, tvb, 0, 0,
+                       "Cancelation to: <unknown frame>");
        }
 
-       /* Build display for: Account Name */
+       WORD_COUNT;
+       BYTE_COUNT;
 
-       AccountName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       END_OF_SMB
 
-       if (tree) {
+       return offset;
+}
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Account Name: %s", AccountName);
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   BEGIN Transaction/Transaction2 Primary and secondary requests
+   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-       }
 
-       offset += string_len; /* Skip Account Name */
+static const value_string trans2_cmd_vals[] = {
+       { 0x00,         "OPEN2" },
+       { 0x01,         "FIND_FIRST2" },
+       { 0x02,         "FIND_NEXT2" },
+       { 0x03,         "QUERY_FS_INFORMATION" },
+       { 0x05,         "QUERY_PATH_INFORMATION" },
+       { 0x06,         "SET_PATH_INFORMATION" },
+       { 0x07,         "QUERY_FILE_INFORMATION" },
+       { 0x08,         "SET_FILE_INFORMATION" },
+       { 0x09,         "FSCTL" },
+       { 0x0A,         "IOCTL2" },
+       { 0x0B,         "FIND_NOTIFY_FIRST" },
+       { 0x0C,         "FIND_NOTIFY_NEXT" },
+       { 0x0D,         "CREATE_DIRECTORY" },
+       { 0x0E,         "SESSION_SETUP" },
+       { 0x10,         "GET_DFS_REFERRAL" },
+       { 0x11,         "REPORT_DFS_INCONSISTENCY" },
+       { 0,    NULL }
+};
 
-       /* Build display for: Primary Domain */
+static const true_false_string tfs_tf_dtid = {
+       "Also DISCONNECT TID",
+       "Do NOT disconnect TID"
+};
+static const true_false_string tfs_tf_owt = {
+       "One Way Transaction (NO RESPONSE)",
+       "Two way transaction"
+};
 
-       /*
-        * XXX - pre-W2K NT systems sometimes appear to stick an extra
-        * byte in front of this, at least if all the strings are
-        * ASCII and the account name is empty.  Another bug?
-        */
+static const true_false_string tfs_ff2_backup = {
+       "Find WITH backup intent",
+       "No backup intent"
+};
+static const true_false_string tfs_ff2_continue = {
+       "CONTINUE search from previous position",
+       "New search, do NOT continue from previous position"
+};
+static const true_false_string tfs_ff2_resume = {
+       "Return RESUME keys",
+       "Do NOT return resume keys"
+};
+static const true_false_string tfs_ff2_close_eos = {
+       "CLOSE search if END OF SEARCH is reached",
+       "Do NOT close search if end of search reached"
+};
+static const true_false_string tfs_ff2_close = {
+       "CLOSE search after this request",
+       "Do NOT close search after this request"
+};
 
-       PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+/* used by
+   TRANS2_FIND_FIRST2
+*/
+static const value_string ff2_il_vals[] = {
+       { 1,            "Info Standard  (4.3.4.1)"},
+       { 2,            "Info Query EA Size  (4.3.4.2)"},
+       { 3,            "Info Query EAs From List  (4.3.4.2)"},
+       { 0x0101,       "Find File Directory Info  (4.3.4.4)"},
+       { 0x0102,       "Find File Full Directory Info  (4.3.4.5)"},
+       { 0x0103,       "Find File Names Info  (4.3.4.7)"},
+       { 0x0104,       "Find File Both Directory Info  (4.3.4.6)"},
+       { 0x0202,       "Find File UNIX  (4.3.4.8)"},
+       {0, NULL}
+};
 
-       if (tree) {
+/* values used by :
+       TRANS2_QUERY_PATH_INFORMATION
+       TRANS2_SET_PATH_INFORMATION
+*/
+static const value_string qpi_loi_vals[] = {
+       { 1,            "Info Standard  (4.2.14.1)"},
+       { 2,            "Info Query EA Size  (4.2.14.1)"},
+       { 3,            "Info Query EAs From List  (4.2.14.2)"},
+       { 4,            "Info Query All EAs  (4.2.14.2)"},
+       { 6,            "Info Is Name Valid  (4.2.14.3)"},
+       { 0x0101,       "Query File Basic Info  (4.2.14.4)"},
+       { 0x0102,       "Query File Standard Info  (4.2.14.5)"},
+       { 0x0103,       "Query File EA Info  (4.2.14.6)"},
+       { 0x0104,       "Query File Name Info  (4.2.14.7)"},
+       { 0x0107,       "Query File All Info  (4.2.14.8)"},
+       { 0x0108,       "Query File Alt File Info  (4.2.14.7)"},
+       { 0x0109,       "Query File Stream Info  (4.2.14.10)"},
+       { 0x010b,       "Query File Compression Info  (4.2.14.11)"},
+       { 0x0200,       "Set File Unix Basic"},
+       { 0x0201,       "Set File Unix Link"},
+       { 0x0202,       "Set File Unix HardLink"},
+       {0, NULL}
+};
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Primary Domain: %s", PrimaryDomain);
+static const value_string qfsi_vals[] = {
+       { 1,            "Info Allocation"},
+       { 2,            "Info Volume"},
+       { 0x0102,       "Query FS Volume Info"},
+       { 0x0103,       "Query FS Size Info"},
+       { 0x0104,       "Query FS Device Info"},
+       { 0x0105,       "Query FS Attribute Info"},
+       {0, NULL}
+};
 
-       }
+static const value_string delete_pending_vals[] = {
+       {0,     "Normal, no pending delete"},
+       {1,     "This object has DELETE PENDING"},
+       {0, NULL}
+};
 
-       offset += string_len; /* Skip Primary Domain */
+static const value_string alignment_vals[] = {
+       {0,     "Byte alignment"},
+       {1,     "Word (16bit) alignment"},
+       {3,     "Long (32bit) alignment"},
+       {7,     "8 byte boundary alignment"},
+       {0x0f,  "16 byte boundary alignment"},
+       {0x1f,  "32 byte boundary alignment"},
+       {0x3f,  "64 byte boundary alignment"},
+       {0x7f,  "128 byte boundary alignment"},
+       {0xff,  "256 byte boundary alignment"},
+       {0x1ff, "512 byte boundary alignment"},
+       {0, NULL}
+};
 
-       /* Build display for: Native OS */
 
-       NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+static const true_false_string tfs_get_dfs_server_hold_storage = {
+       "Referral SERVER HOLDS STORAGE for the file",
+       "Referral server does NOT hold storage for the file"
+};
+static const true_false_string tfs_get_dfs_fielding = {
+       "The server in referral is FIELDING CAPABLE",
+       "The server in referrals is NOT fielding capable"
+};
 
-       if (tree) {
+static const true_false_string tfs_dfs_referral_flags_strip = {
+       "STRIP off pathconsumed characters before submitting",
+       "Do NOT strip off any characters"
+};
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Native OS: %s", NativeOS);
+static const value_string dfs_referral_server_type_vals[] = {
+       {0,     "Don't know"},
+       {1,     "SMB Server"},
+       {2,     "Netware Server"},
+       {3,     "Domain Server"},
+       {0, NULL}
+};
 
-       }
 
-       offset += string_len; /* Skip Native OS */
+static const true_false_string tfs_device_char_removable = {
+       "This is a REMOVABLE device",
+       "This is NOT a removable device"
+};
+static const true_false_string tfs_device_char_read_only = {
+       "This is a READ-ONLY device",
+       "This is NOT a read-only device"
+};
+static const true_false_string tfs_device_char_floppy = {
+       "This is a FLOPPY DISK device",
+       "This is NOT a floppy disk device"
+};
+static const true_false_string tfs_device_char_write_once = {
+       "This is a WRITE-ONCE device",
+       "This is NOT a write-once device"
+};
+static const true_false_string tfs_device_char_remote = {
+       "This is a REMOTE device",
+       "This is NOT a remote device"
+};
+static const true_false_string tfs_device_char_mounted = {
+       "This device is MOUNTED",
+       "This device is NOT mounted"
+};
+static const true_false_string tfs_device_char_virtual = {
+       "This is a VIRTUAL device",
+       "This is NOT a virtual device"
+};
 
-       /* Build display for: Native LanMan Type */
 
-       /*
-        * XXX - pre-W2K NT systems appear to stick an extra 2 bytes of
-        * padding/null string/whatever in front of this.  W2K doesn't
-        * appear to.  I suspect that's a bug that got fixed; I also
-        * suspect that, in practice, nobody ever looks at that field
-        * because the bug didn't appear to get fixed until NT 5.0....
-        */
+static const true_false_string tfs_fs_attr_css = {
+       "This FS supports CASE SENSITIVE SEARCHes",
+       "This FS does NOT support case sensitive searches"
+};
+static const true_false_string tfs_fs_attr_cpn = {
+       "This FS supports CASE PRESERVED NAMES",
+       "This FS does NOT support case preserved names"
+};
+static const true_false_string tfs_fs_attr_pacls = {
+       "This FS supports PERSISTENT ACLs",
+       "This FS does NOT support persistent acls"
+};
+static const true_false_string tfs_fs_attr_fc = {
+       "This FS supports COMPRESSED FILES",
+       "This FS does NOT support compressed files"
+};
+static const true_false_string tfs_fs_attr_vq = {
+       "This FS supports VOLUME QUOTAS",
+       "This FS does NOT support volume quotas"
+};
+static const true_false_string tfs_fs_attr_dim = {
+       "This FS is on a MOUNTED DEVICE",
+       "This FS is NOT on a mounted device"
+};
+static const true_false_string tfs_fs_attr_vic = {
+       "This FS is on a COMPRESSED VOLUME",
+       "This FS is NOT on a compressed volume"
+};
 
-       NativeLanManType = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-       if (tree) {
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Native LanMan Type: %s", NativeLanManType);
+static int
+dissect_ff2_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+
+       mask = tvb_get_letohs(tvb, offset);
 
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_find_first2_flags);
        }
 
-       offset += string_len; /* Skip Native LanMan Type */
+       proto_tree_add_boolean(tree, hf_smb_ff2_backup,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_ff2_continue,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_ff2_resume,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_ff2_close_eos,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_ff2_close,
+               tvb, offset, 2, mask);
 
-      }
+       offset += 2;
 
-      break;
+       return offset;
+}
 
-    default:
+static int
+dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, guint16 bc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       struct smb_request_val *request_val;
+       int fn_len;
+       const char *fn;
+       int old_offset = offset;
+
+       si = (smb_info_t *)pinfo->private_data;
+       request_val = si->request_val;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, bc,
+                               "%s Parameters",
+                               val_to_str(si->subcmd, trans2_cmd_vals, 
+                                          "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_transaction_params);
+       }
 
-      /* XXX - dump the parameter words, one word at a time? */
+       switch(si->subcmd){
+       case 0x00:      /*TRANS2_OPEN2*/
+               /* open flags */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_open_flags(tvb, pinfo, tree, offset, 0x000f);
+               bc -= 2;
+
+               /* desired access */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_access(tvb, pinfo, tree, offset, "Desired");
+               bc -= 2;
+
+               /* 2 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               /* File Attributes */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+               bc -= 2;
+
+               /* create time */
+               CHECK_BYTE_COUNT_TRANS(4);
+               offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+                       hf_smb_create_time,
+                       hf_smb_create_dos_date, hf_smb_create_dos_time,
+                       TRUE);
+               bc -= 4;
+
+               /* open function */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_open_function(tvb, pinfo, tree, offset);
+               bc -= 2;
+
+               /* allocation size */
+               CHECK_BYTE_COUNT_TRANS(4);
+               proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS(4);
+
+               /* 10 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS(10);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+               COUNT_BYTES_TRANS(10);
+
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s",
+                       fn);
+               }
+
+               /* XXX dont know how to decode FEAList */
+               break;
+       case 0x01:      /*TRANS2_FIND_FIRST2*/
+               /* Search Attributes */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_search_attributes(tvb, pinfo, tree, offset);
+               bc -= 2;
+
+               /* search count */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_search_count, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               /* Find First2 flags */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_ff2_flags(tvb, pinfo, tree, offset);
+               bc -= 2;
+
+               /* Find First2 information level */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+
+               /* storage type */
+               CHECK_BYTE_COUNT_TRANS(4);
+               proto_tree_add_item(tree, hf_smb_storage_type, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS(4);
+
+               /* search pattern */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_search_pattern, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", Pattern: %s",
+                       fn);
+               }
+
+               /* XXX dont know how to decode FEAList */
+
+               break;
+       case 0x02:      /*TRANS2_FIND_NEXT2*/
+               /* sid */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_sid, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               /* search count */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_search_count, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               /* Find First2 information level */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+
+               /* resume key */
+               CHECK_BYTE_COUNT_TRANS(4);
+               proto_tree_add_item(tree, hf_smb_resume, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS(4);
+
+               /* Find First2 flags */
+               CHECK_BYTE_COUNT_TRANS(2);
+               offset = dissect_ff2_flags(tvb, pinfo, tree, offset);
+               bc -= 2;
+
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", Continue: %s",
+                       fn);
+               }
+
+               break;
+       case 0x03:      /*TRANS2_QUERY_FS_INFORMATION*/
+               /* level of interest */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_qfsi_information_level, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+
+               break;
+       case 0x05:      /*TRANS2_QUERY_PATH_INFORMATION*/
+               /* level of interest */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+               
+               /* 4 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS(4);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS(4);
+
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s",
+                       fn);
+               }
+
+               break;
+       case 0x06:      /*TRANS2_SET_PATH_INFORMATION*/
+               /* level of interest */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+               
+               /* 4 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS(4);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS(4);
+
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s",
+                       fn);
+               }
+
+               break;
+       case 0x07:      /*TRANS2_QUERY_FILE_INFORMATION*/
+               /* fid */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               /* level of interest */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+               
+               break;
+       case 0x08:      /*TRANS2_SET_FILE_INFORMATION*/
+               /* fid */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               /* level of interest */
+               CHECK_BYTE_COUNT_TRANS(2);
+               si->info_level = tvb_get_letohs(tvb, offset);
+               if (!pinfo->fd->flags.visited)
+                       request_val->last_level = si->info_level;
+               proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level);
+               COUNT_BYTES_TRANS(2);
+               
+               /* 2 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+
+               break;
+       case 0x09:      /*TRANS2_FSCTL*/
+       case 0x0a:      /*TRANS2_IOCTL2*/
+               /* these calls have no parameter block in the request */
+               break;
+       case 0x0b:      /*TRANS2_FIND_NOTIFY_FIRST*/
+       case 0x0c:      /*TRANS2_FIND_NOTIFY_NEXT*/
+               /* XXX unknown structure*/
+               break;
+       case 0x0d:      /*TRANS2_CREATE_DIRECTORY*/
+               /* 4 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS(4);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS(4);
+
+               /* dir name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len,
+                       FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", Dir: %s",
+                       fn);
+               }
+
+               /* XXX optional FEAList, unknown what FEAList looks like*/
+               break;
+       case 0x0e:      /*TRANS2_SESSION_SETUP*/
+               /* XXX unknown structure*/
+               break;
+       case 0x10:      /*TRANS2_GET_DFS_REFERRAL*/
+               /* referral level */
+               CHECK_BYTE_COUNT_TRANS(2);
+               proto_tree_add_item(tree, hf_smb_max_referral_level, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS(2);
+               
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", File: %s",
+                       fn);
+               }
+
+               break;
+       case 0x11:      /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+               /* file name */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, &bc);
+               CHECK_STRING_TRANS(fn);
+               proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS(fn_len);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, ", File: %s",
+                       fn);
+               }
+
+               break;
+       }
 
-      offset += WordCount;
+       /* ooops there were data we didnt know how to process */
+       if((offset-old_offset) < bc){
+               proto_tree_add_bytes(tree, hf_smb_unknown, tvb, offset, bc - (offset-old_offset), tvb_get_ptr(tvb, offset, 1));
+               offset += bc - (offset-old_offset);
+       }
 
-      /* Build display for: Byte Count (BCC) */
+       return offset;
+}
 
-      ByteCount = GSHORT(pd, offset);
+/*
+ * XXX - just use "dissect_connect_flags()" here?
+ */
+static guint16
+dissect_transaction_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      if (tree) {
+       mask = tvb_get_letohs(tvb, offset);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_transaction_flags);
+       }
 
-      }
+       proto_tree_add_boolean(tree, hf_smb_transaction_flags_owt,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_transaction_flags_dtid,
+               tvb, offset, 2, mask);
 
-      offset += 2; /* Skip Byte Count (BCC) */
+       return mask;
+}
 
-      break;
+static int
+dissect_get_dfs_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    }
+       mask = tvb_get_letohs(tvb, offset);
 
-    if (AndXCommand != 0xFF) {
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_get_dfs_flags);
+       }
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+       proto_tree_add_boolean(tree, hf_smb_get_dfs_server_hold_storage,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_get_dfs_fielding,
+               tvb, offset, 2, mask);
 
-    }
+       offset += 2;
+       return offset;
+}
 
-  } else {
-    /* Response(s) dissect code */
+static int
+dissect_dfs_referral_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-    /* Build display for: Word Count (WCT) */
+       mask = tvb_get_letohs(tvb, offset);
 
-    WordCount = GBYTE(pd, offset);
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_dfs_referral_flags);
+       }
 
-    if (tree) {
+       proto_tree_add_boolean(tree, hf_smb_dfs_referral_flags_strip,
+               tvb, offset, 2, mask);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       offset += 2;
 
-    }
+       return offset;
+}
 
-    offset += 1; /* Skip Word Count (WCT) */
 
-    switch (WordCount) {
+/* dfs inconsistency data  (4.4.2)
+*/
+static int
+dissect_dfs_inconsistency_data(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *tree, int offset, guint16 *bcp)
+{
+       int fn_len;
+       const char *fn;
+
+       /*XXX shouldn this data hold version and size? unclear from doc*/
+       /* referral version */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_dfs_referral_version, tvb, offset, 2, TRUE);
+       COUNT_BYTES_TRANS_SUBR(2);
+
+       /* referral size */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_dfs_referral_size, tvb, offset, 2, TRUE);
+       COUNT_BYTES_TRANS_SUBR(2);
+
+       /* referral server type */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_dfs_referral_server_type, tvb, offset, 2, TRUE);
+       COUNT_BYTES_TRANS_SUBR(2);
+
+       /* referral flags */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       offset = dissect_dfs_referral_flags(tvb, pinfo, tree, offset);
+       *bcp -= 2;
+
+       /* node name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, bcp);
+       CHECK_STRING_TRANS_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_dfs_referral_node, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_TRANS_SUBR(fn_len);
+
+       return offset;
+}
 
-    case 3:
+/* get dfs referral data  (4.4.1)
+*/
+static int
+dissect_get_dfs_referral_data(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *tree, int offset, guint16 *bcp)
+{
+       guint16 numref;
+       guint16 refsize;
+       guint16 pathoffset;
+       guint16 altpathoffset;
+       guint16 nodeoffset;
+       int fn_len;
+       int stroffset;
+       int offsetoffset;
+       guint16 save_bc;
+       const char *fn;
+       int unklen;
+       int ucstring_end;
+       int ucstring_len;
+
+       /* path consumed */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_dfs_path_consumed, tvb, offset, 2, TRUE);
+       COUNT_BYTES_TRANS_SUBR(2);
+
+       /* num referrals */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       numref = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_dfs_num_referrals, tvb, offset, 2, numref);
+       COUNT_BYTES_TRANS_SUBR(2);
+
+       /* get dfs flags */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       offset = dissect_get_dfs_flags(tvb, pinfo, tree, offset);
+       *bcp -= 2;
+
+       /* XXX - in at least one capture there appears to be 2 bytes
+          of stuff after the Dfs flags, perhaps so that the header
+          in front of the referral list is a multiple of 4 bytes long. */
+       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 2, TRUE);
+       COUNT_BYTES_TRANS_SUBR(2);
+
+       /* if there are any referrals */
+       if(numref){
+               proto_item *ref_item = NULL;
+               proto_tree *ref_tree = NULL;
+               int old_offset=offset;
+
+               if(tree){
+                       ref_item = proto_tree_add_text(tree,
+                               tvb, offset, *bcp, "Referrals");
+                       ref_tree = proto_item_add_subtree(ref_item,
+                               ett_smb_dfs_referrals);
+               }
+               ucstring_end = -1;
+
+               while(numref--){
+                       proto_item *ri = NULL;
+                       proto_tree *rt = NULL;
+                       int old_offset=offset;
+                       guint16 version;
+
+                       if(tree){
+                               ri = proto_tree_add_text(ref_tree,
+                                       tvb, offset, *bcp, "Referral");
+                               rt = proto_item_add_subtree(ri,
+                                       ett_smb_dfs_referral);
+                       }
+               
+                       /* referral version */
+                       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                       version = tvb_get_letohs(tvb, offset);
+                       proto_tree_add_uint(rt, hf_smb_dfs_referral_version,
+                               tvb, offset, 2, version);
+                       COUNT_BYTES_TRANS_SUBR(2);
+
+                       /* referral size */
+                       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                       refsize = tvb_get_letohs(tvb, offset);
+                       proto_tree_add_uint(rt, hf_smb_dfs_referral_size, tvb, offset, 2, refsize);
+                       COUNT_BYTES_TRANS_SUBR(2);
+
+                       /* referral server type */
+                       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                       proto_tree_add_item(rt, hf_smb_dfs_referral_server_type, tvb, offset, 2, TRUE);
+                       COUNT_BYTES_TRANS_SUBR(2);
+
+                       /* referral flags */
+                       CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                       offset = dissect_dfs_referral_flags(tvb, pinfo, rt, offset);
+                       *bcp -= 2;
+
+                       switch(version){
+
+                       case 1:
+                               /* node name */
+                               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, bcp);
+                               CHECK_STRING_TRANS_SUBR(fn);
+                               proto_tree_add_string(rt, hf_smb_dfs_referral_node, tvb, offset, fn_len,
+                                       fn);
+                               COUNT_BYTES_TRANS_SUBR(fn_len);
+                               break;
+
+                       case 2:
+                       case 3: /* XXX - like version 2, but not identical;
+                                  seen in a capture, but the format isn't
+                                  documented */
+                               /* proximity */
+                               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                               proto_tree_add_item(rt, hf_smb_dfs_referral_proximity, tvb, offset, 2, TRUE);
+                               COUNT_BYTES_TRANS_SUBR(2);
+
+                               /* ttl */
+                               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                               proto_tree_add_item(rt, hf_smb_dfs_referral_ttl, tvb, offset, 2, TRUE);
+                               COUNT_BYTES_TRANS_SUBR(2);
+
+                               /* path offset */
+                               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                               pathoffset = tvb_get_letohs(tvb, offset);
+                               proto_tree_add_uint(rt, hf_smb_dfs_referral_path_offset, tvb, offset, 2, pathoffset);
+                               COUNT_BYTES_TRANS_SUBR(2);
+
+                               /* alt path offset */
+                               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                               altpathoffset = tvb_get_letohs(tvb, offset);
+                               proto_tree_add_uint(rt, hf_smb_dfs_referral_alt_path_offset, tvb, offset, 2, altpathoffset);
+                               COUNT_BYTES_TRANS_SUBR(2);
+
+                               /* node offset */
+                               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+                               nodeoffset = tvb_get_letohs(tvb, offset);
+                               proto_tree_add_uint(rt, hf_smb_dfs_referral_node_offset, tvb, offset, 2, nodeoffset);
+                               COUNT_BYTES_TRANS_SUBR(2);
+
+                               /* path */
+                               if (pathoffset != 0) {
+                                       stroffset = old_offset + pathoffset;
+                                       offsetoffset = stroffset - offset;
+                                       if (offsetoffset > 0 &&
+                                           *bcp > offsetoffset) {
+                                               save_bc = *bcp;
+                                               *bcp -= offsetoffset;
+                                               fn = get_unicode_or_ascii_string_tvb(tvb, &stroffset, pinfo, &fn_len, FALSE, FALSE, bcp);
+                                               CHECK_STRING_TRANS_SUBR(fn);
+                                               proto_tree_add_string(rt, hf_smb_dfs_referral_path, tvb, stroffset, fn_len,
+                                                       fn);
+                                               stroffset += fn_len;
+                                               if (ucstring_end < stroffset)
+                                                       ucstring_end = stroffset;
+                                               *bcp = save_bc;
+                                       }
+                               }
+                       
+                               /* alt path */
+                               if (altpathoffset != 0) {
+                                       stroffset = old_offset + altpathoffset;
+                                       offsetoffset = stroffset - offset;
+                                       if (offsetoffset > 0 &&
+                                           *bcp > offsetoffset) {
+                                               save_bc = *bcp;
+                                               *bcp -= offsetoffset;
+                                               fn = get_unicode_or_ascii_string_tvb(tvb, &stroffset, pinfo, &fn_len, FALSE, FALSE, bcp);
+                                               CHECK_STRING_TRANS_SUBR(fn);
+                                               proto_tree_add_string(rt, hf_smb_dfs_referral_alt_path, tvb, stroffset, fn_len,
+                                                       fn);
+                                               stroffset += fn_len;
+                                               if (ucstring_end < stroffset)
+                                                       ucstring_end = stroffset;
+                                               *bcp = save_bc;
+                                       }
+                               }
+                       
+                               /* node */
+                               if (nodeoffset != 0) {
+                                       stroffset = old_offset + nodeoffset;
+                                       offsetoffset = stroffset - offset;
+                                       if (offsetoffset > 0 &&
+                                           *bcp > offsetoffset) {
+                                               save_bc = *bcp;
+                                               *bcp -= offsetoffset;
+                                               fn = get_unicode_or_ascii_string_tvb(tvb, &stroffset, pinfo, &fn_len, FALSE, FALSE, bcp);
+                                               CHECK_STRING_TRANS_SUBR(fn);
+                                               proto_tree_add_string(rt, hf_smb_dfs_referral_node, tvb, stroffset, fn_len,
+                                                       fn);
+                                               stroffset += fn_len;
+                                               if (ucstring_end < stroffset)
+                                                       ucstring_end = stroffset;
+                                               *bcp = save_bc;
+                                       }
+                               }
+                               break;
+                       }
+
+                       /*
+                        * Show anything beyond the length of the referral
+                        * as unknown data.
+                        */
+                       unklen = (old_offset + refsize) - offset;
+                       if (unklen < 0) {
+                               /*
+                                * XXX - the length is bogus.
+                                */
+                               unklen = 0;
+                       }
+                       if (unklen != 0) {
+                               CHECK_BYTE_COUNT_TRANS_SUBR(unklen);
+                               proto_tree_add_item(rt, hf_smb_unknown, tvb,
+                                   offset, unklen, TRUE);
+                               COUNT_BYTES_TRANS_SUBR(unklen);
+                       }
+
+                       proto_item_set_len(ri, offset-old_offset);
+               }
 
-      /* Build display for: AndXCommand */
+               /*
+                * Treat the offset past the end of the last Unicode
+                * string after the referrals (if any) as the last
+                * offset.
+                */
+               if (ucstring_end > offset) {
+                       ucstring_len = ucstring_end - offset;
+                       if (*bcp < ucstring_len)
+                               ucstring_len = *bcp;
+                       offset += ucstring_len;
+                       *bcp -= ucstring_len;
+               }
+               proto_item_set_len(ref_item, offset-old_offset);
+       }
 
-      AndXCommand = GBYTE(pd, offset);
+       return offset;
+}
 
-      if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s",
-                            (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+/* this dissects the SMB_INFO_STANDARD and SMB_INFO_QUERY_EA_SIZE
+   as described in 4.2.14.1
+*/
+static int
+dissect_4_2_14_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_create_time, hf_smb_create_dos_date, hf_smb_create_dos_time,
+               FALSE);
+       *bcp -= 4;
+
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_access_time, hf_smb_access_dos_date, hf_smb_access_dos_time,
+               FALSE);
+       *bcp -= 4;
+
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_last_write_time, hf_smb_last_write_dos_date, hf_smb_last_write_dos_time,
+               FALSE);
+       *bcp -= 4;
+
+       /* data size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* File Attributes */
+       CHECK_BYTE_COUNT_SUBR(2);
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+       *bcp -= 2;
+
+       /* ea size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_ea_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      }
+/* this dissects the SMB_INFO_QUERY_EAS_FROM_LIST and SMB_INFO_QUERY_ALL_EAS
+   as described in 4.2.14.2
+*/
+static int
+dissect_4_2_14_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       /* list length */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_list_length, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
 
-      offset += 1; /* Skip AndXCommand */
+       *trunc = FALSE;
+       return offset;
+}
 
-      /* Build display for: AndXReserved */
+/* this dissects the SMB_INFO_IS_NAME_VALID
+   as described in 4.2.14.3
+*/
+static int
+dissect_4_2_14_3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      AndXReserved = GBYTE(pd, offset);
+/* this dissects the SMB_QUERY_FILE_BASIC_INFO
+   as described in 4.2.14.4
+*/
+static int
+dissect_4_2_14_4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Create", hf_smb_create_time);
+       *bcp -= 8;
+       
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Access Time", hf_smb_access_time);
+       *bcp -= 8;
+       
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Write Time", hf_smb_last_write_time);
+       *bcp -= 8;
+       
+       /* last change time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Change Time", hf_smb_change_time);
+       *bcp -= 8;
+       
+       /* File Attributes */
+       CHECK_BYTE_COUNT_SUBR(2);
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+       *bcp -= 2;
 
-      if (tree) {
+       *trunc = FALSE;
+       return offset;
+}
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+/* this dissects the SMB_QUERY_FILE_STANDARD_INFO
+   as described in 4.2.14.5
+*/
+static int
+dissect_4_2_14_5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* end of file */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* number of links */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_number_of_links, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* delete pending */
+       CHECK_BYTE_COUNT_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_delete_pending, tvb, offset, 2, TRUE);
+       COUNT_BYTES_SUBR(2);
+
+       /* is directory */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_is_directory, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      }
+/* this dissects the SMB_QUERY_FILE_EA_INFO
+   as described in 4.2.14.6
+*/
+static int
+dissect_4_2_14_6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       /* ea size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_ea_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
 
-      offset += 1; /* Skip AndXReserved */
+       *trunc = FALSE;
+       return offset;
+}
 
-      /* Build display for: AndXOffset */
+/* this dissects the SMB_QUERY_FILE_NAME_INFO
+   as described in 4.2.14.7
+   this is the same as SMB_QUERY_FILE_ALT_NAME_INFO
+   as described in 4.2.14.9
+*/
+static int
+dissect_4_2_14_7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_file_name_len, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      AndXOffset = GSHORT(pd, offset);
+/* this dissects the SMB_QUERY_FILE_ALL_INFO
+   as described in 4.2.14.8
+*/
+static int
+dissect_4_2_14_8(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
 
-      if (tree) {
+       offset = dissect_4_2_14_4(tvb, pinfo, tree, offset, bcp, trunc);
+       if (trunc)
+               return offset;
+       offset = dissect_4_2_14_5(tvb, pinfo, tree, offset, bcp, trunc);
+       if (trunc)
+               return offset;
+
+       /* index number */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_index_number, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       offset = dissect_4_2_14_6(tvb, pinfo, tree, offset, bcp, trunc);
+       if (trunc)
+               return offset;
+
+       /* access flags */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_nt_access_mask(tvb, pinfo, tree, offset);
+       COUNT_BYTES_SUBR(4);
+
+       /* index number */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_index_number, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* current offset */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_current_offset, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* mode */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_nt_create_options(tvb, pinfo, tree, offset);
+       *bcp -= 4;
+
+       /* alignment */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_t2_alignment, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+       
+       offset = dissect_4_2_14_6(tvb, pinfo, tree, offset, bcp, trunc);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+       return offset;
+}
 
-      }
+/* this dissects the SMB_QUERY_FILE_STREAM_INFO
+   as described in 4.2.14.10
+*/
+static int
+dissect_4_2_14_10(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
 
-      offset += 2; /* Skip AndXOffset */
+       /* next entry offset */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_next_entry_offset, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+       
+       /* stream name len */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_t2_stream_name_length, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+       
+       /* stream size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_t2_stream_name_length, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
+
+       *trunc = FALSE;
+       return offset;
+}
 
-      /* Build display for: Action */
+/* this dissects the SMB_QUERY_FILE_COMPRESSION_INFO
+   as described in 4.2.14.11
+*/
+static int
+dissect_4_2_14_11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       /* compressed file size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_t2_compressed_file_size, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* compression format */
+       CHECK_BYTE_COUNT_SUBR(2);
+       proto_tree_add_item(tree, hf_smb_t2_compressed_format, tvb, offset, 2, TRUE);
+       COUNT_BYTES_SUBR(2);
+       
+       /* compression unit shift */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_t2_compressed_unit_shift,tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+       
+       /* compression chunk shift */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_t2_compressed_chunk_shift, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+       
+       /* compression cluster shift */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_t2_compressed_cluster_shift, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+       
+       /* 3 reserved bytes */
+       CHECK_BYTE_COUNT_SUBR(3);
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 3, TRUE);
+       COUNT_BYTES_SUBR(3);
 
-      Action = GSHORT(pd, offset);
+       *trunc = FALSE;
+       return offset;
+}
 
-      if (tree) {
 
-        ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Action: %u", Action);
-        Action_tree = proto_item_add_subtree(ti, ett_smb_ssetupandxaction);
-        proto_tree_add_text(Action_tree, NullTVB, offset, 2, "%s",
-                            decode_boolean_bitfield(Action, 0x0001, 16, "Logged in as GUEST", "Not logged in as GUEST"));
 
-      }
+/*dissect the data block for TRANS2_QUERY_PATH_INFORMATION*/
+static int
+dissect_qpi_loi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+    int offset, guint16 *bcp)
+{
+       smb_info_t *si;
+       gboolean trunc;
 
-      offset += 2; /* Skip Action */
+       if(!*bcp){
+               return offset;
+       }
+       
+       si = (smb_info_t *)pinfo->private_data;
+       switch(si->info_level){
+       case 1:         /*Info Standard*/
+       case 2:         /*Info Query EA Size*/
+               offset = dissect_4_2_14_1(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 3:         /*Info Query EAs From List*/
+       case 4:         /*Info Query All EAs*/
+               offset = dissect_4_2_14_2(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 6:         /*Info Is Name Valid*/
+               offset = dissect_4_2_14_3(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0101:    /*Query File Basic Info*/
+               offset = dissect_4_2_14_4(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0102:    /*Query File Standard Info*/
+               offset = dissect_4_2_14_5(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0103:    /*Query File EA Info*/
+               offset = dissect_4_2_14_6(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0104:    /*Query File Name Info*/
+               offset = dissect_4_2_14_7(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0107:    /*Query File All Info*/
+               offset = dissect_4_2_14_8(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0108:    /*Query File Alt File Info*/
+               offset = dissect_4_2_14_7(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0109:    /*Query File Stream Info*/
+               offset = dissect_4_2_14_10(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x010b:    /*Query File Compression Info*/
+               offset = dissect_4_2_14_11(tvb, pinfo, tree, offset, bcp,
+                   &trunc);
+               break;
+       case 0x0200:    /*Set File Unix Basic*/
+               /* XXX add this from the SNIA doc */
+               break;
+       case 0x0201:    /*Set File Unix Link*/
+               /* XXX add this from the SNIA doc */
+               break;
+       case 0x0202:    /*Set File Unix HardLink*/
+               /* XXX add this from the SNIA doc */
+               break;
+       }
+       
+       return offset;
+}
 
-      /* Build display for: Byte Count (BCC) */
 
-      ByteCount = GSHORT(pd, offset);
+static int
+dissect_transaction2_request_data(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, guint16 dc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       int fn_len;
+       const char *fn;
+       int old_offset = offset;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, dc,
+                               "%s Data",
+                               val_to_str(si->subcmd, trans2_cmd_vals, 
+                                               "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_transaction_data);
+       }
 
-      if (tree) {
+       switch(si->subcmd){
+       case 0x00:      /*TRANS2_OPEN2*/
+               /* XXX FAEList here?*/
+               break;
+       case 0x01:      /*TRANS2_FIND_FIRST2*/
+               /* XXX FAEList here?*/
+               break;
+       case 0x02:      /*TRANS2_FIND_NEXT2*/
+               /* no data field in this request */
+               break;
+       case 0x03:      /*TRANS2_QUERY_FS_INFORMATION*/
+               /* no data field in this request */
+               break;
+       case 0x05:      /*TRANS2_QUERY_PATH_INFORMATION*/
+               /* no data field in this request */
+               break;
+       case 0x06:      /*TRANS2_SET_PATH_INFORMATION*/
+               offset = dissect_qpi_loi_vals(tvb, pinfo, tree, offset, &dc);
+               break;
+       case 0x07:      /*TRANS2_QUERY_FILE_INFORMATION*/
+               /* no data field in this request */
+               break;
+       case 0x08:      /*TRANS2_SET_FILE_INFORMATION*/
+               offset = dissect_qpi_loi_vals(tvb, pinfo, tree, offset, &dc);
+               break;
+       case 0x09:      /*TRANS2_FSCTL*/
+               /*XXX dont know how to decode this yet */
+               break;
+       case 0x0a:      /*TRANS2_IOCTL2*/
+               /*XXX dont know how to decode this yet */
+               break;
+       case 0x0b:      /*TRANS2_FIND_NOTIFY_FIRST*/
+               /*XXX dont know how to decode this yet */
+               break;
+       case 0x0c:      /*TRANS2_FIND_NOTIFY_NEXT*/
+               /*XXX dont know how to decode this yet */
+               break;
+       case 0x0d:      /*TRANS2_CREATE_DIRECTORY*/
+               /* no data block for this one */
+               break;
+       case 0x0e:      /*TRANS2_SESSION_SETUP*/
+               /*XXX dont know how to decode this yet */
+               break;
+       case 0x10:      /*TRANS2_GET_DFS_REFERRAL*/
+               /* no data field in this request */
+               break;
+       case 0x11:      /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+               offset = dissect_dfs_inconsistency_data(tvb, pinfo, tree, offset, &dc);
+               break;
+       }
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* ooops there were data we didnt know how to process */
+       if(dc != 0){
+               proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, dc, TRUE);
+               offset += dc;
+       }
 
-      }
+       return offset;
+}
 
-      offset += 2; /* Skip Byte Count (BCC) */
 
-      if (ByteCount > 0) {
+static int
+dissect_transaction_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+       conversation_t *conversation;
+       struct smb_request_val *request_val;
+       guint8 wc, sc=0;
+       int so=0;
+       guint16 od=0, tf, po=0, pc=0, dc=0, pd, dd=0;
+       guint32 to;
+       int an_len;
+       const char *an = NULL;
+       smb_info_t *si;
+       guint16 bc;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
 
-        /* Build display for: NativeOS */
+       /*
+        * Find out what conversation this packet is part of.
+        */
+       conversation = find_conversation(&pinfo->src, &pinfo->dst,
+           pinfo->ptype,  pinfo->srcport, pinfo->destport, 0);
 
-        NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       if (conversation == NULL) {
+               /*
+                * There isn't one yet; create it.
+                */
+               conversation = conversation_new(&pinfo->src, &pinfo->dst,
+                   pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+       }
 
-        if (tree) {
+       si->conversation = conversation;  /* Save this */
 
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeOS: %s", NativeOS);
+       request_val = do_transaction_hashing(conversation, *si, pinfo->fd);
 
-        }
+       si->request_val = request_val;  /* Save this for later */
 
-        offset += string_len; /* Skip NativeOS */
+       WORD_COUNT;
 
-        /* Build display for: NativeLanMan */
+       if(wc==8){
+       /*secondary client request*/
+               /* total param count, only a 16bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+       
+               /* total data count , only 16bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* param count */
+               pc = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_param_count16, tvb, offset, 2, pc);
+               offset += 2;
+
+               /* param offset */
+               po = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_param_offset16, tvb, offset, 2, po);
+               offset += 2;
+
+               /* param disp */
+               pd = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_param_disp16, tvb, offset, 2, pd);
+               offset += 2;
+       
+               /* data count */
+               dc = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_data_count16, tvb, offset, 2, dc);
+               offset += 2;
+
+               /* data offset */
+               od = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_data_offset16, tvb, offset, 2, od);
+               offset += 2;
+       
+               /* data disp */
+               dd = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_data_disp16, tvb, offset, 2, dd);
+               offset += 2;
+
+               if(si->cmd==0x32){
+                       /* fid */
+                       proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+                       offset += 2;
+               }
+       } else {
+       /* it is not a secondary request */
+               /* total param count , only a 16 bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* total data count , only 16bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* max param count , only 16bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_max_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* max data count , only 16bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_max_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* max setup count , only 16bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_max_setup_count, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+               offset += 1;
+
+               /* reserved byte */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               /* transaction flags */
+               tf = dissect_transaction_flags(tvb, pinfo, tree, offset);
+               offset += 2;
+
+               /* timeout */
+               to = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+               offset += 4;
+
+               /* 2 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* param count */
+               pc = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_param_count16, tvb, offset, 2, pc);
+               offset += 2;
+       
+               /* param offset */
+               po = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_param_offset16, tvb, offset, 2, po);
+               offset += 2;
+
+               /* data count */
+               dc = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_data_count16, tvb, offset, 2, dc);
+               offset += 2;
+
+               /* data offset */
+               od = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_data_offset16, tvb, offset, 2, od);
+               offset += 2;
+
+               /* data displacement is zero here */
+               dd = 0;
+
+               /* setup count */
+               sc = tvb_get_guint8(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+               offset += 1;
+
+               /* reserved byte */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+               offset += 1;
+               
+               /* this is where the setup bytes start */       
+               so = offset;
+
+               /* if there were any setup bytes, decode them */
+               if(sc){
+                       switch(si->cmd){
+
+                       case 0x32:
+                               /* TRANSACTION2 only has one setup word and
+                                  that is the subcommand code. */
+                               si->subcmd = tvb_get_letohs(tvb, offset);
+                               proto_tree_add_uint(tree, hf_smb_trans2_subcmd,
+                                   tvb, offset, 2, si->subcmd);
+
+                               if (check_col(pinfo->fd, COL_INFO)) {
+                                       col_append_fstr(pinfo->fd, COL_INFO, " %s",
+                                           val_to_str(si->subcmd, trans2_cmd_vals, 
+                                               "Unknown (0x%02x)"));
+                               }
+                               if (!pinfo->fd->flags.visited)
+                                       request_val->last_transact2_command = si->subcmd;
+                               break;
+
+                       case 0x25:
+                               /*XXX decode the TRANSACTION setup words */
+                       }
+
+                       offset += sc*2;
+               }
 
-        NativeLanMan = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       }
 
-        if (tree) {
+       BYTE_COUNT;
+       
+       if(wc!=8){
+               /* name is NULL if transaction2 */
+               if(si->cmd!=0x32){
+                       /* Transaction Name */  
+                       an = get_unicode_or_ascii_string_tvb(tvb, &offset,
+                               pinfo, &an_len, FALSE, FALSE, &bc);
+                       if (an == NULL)
+                               goto endofcommand;
+                       proto_tree_add_string(tree, hf_smb_trans_name, tvb,
+                               offset, an_len, an);
+                       COUNT_BYTES(an_len);
+               }
+       }
 
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeLanMan: %s", NativeLanMan);
+       /* parameters */
+       if(po>offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = po-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(pc){
+               CHECK_BYTE_COUNT(pc);
+               switch(si->cmd) {
+
+               case 0x32:
+                       /* TRANSACTION2 parameters*/
+                       offset = dissect_transaction2_request_parameters(tvb,
+                           pinfo, tree, offset, pc);
+                       bc -= pc;
+                       break;
+
+               case 0x25:
+                       /*XXXX process TRANSACTION parameters*/
+                       offset += pc;
+                       bc -= pc;
+                       break;
+               }
+       }
 
-        }
+       /* data */
+       if(od>offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = od-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(dc){
+               CHECK_BYTE_COUNT(dc);
+               switch(si->cmd){
+
+               case 0x32:
+                       /* TRANSACTION2 data*/
+                       offset = dissect_transaction2_request_data(tvb, pinfo,
+                           tree, offset, dc);
+                       bc -= dc;
+                       break;
+
+               case 0x25:
+                       /*XXXX process TRANSACTIOIN data*/
+                       offset += dc;
+                       bc -= pc;
+                       break;
+               }
+       }
 
-        offset += string_len; /* Skip NativeLanMan */
+#ifdef NOT_YET_TVBUFFIFIED
+       /*XXX*/
+       /*TRANSACTION request parameters */
+       if(si->cmd==0x25){
+               /*XXX replace this block with a function and use that one 
+                    for both requests/responses*/
+               if(dd==0){
+                       tvbuff_t *p_tvb, *d_tvb, *s_tvb;
+
+                       if(pc>0){
+                               if(pc>tvb_length_remaining(tvb, po)){
+                                       p_tvb = tvb_new_subset(tvb, po, tvb_length_remaining(tvb, po), pc);
+                               } else {
+                                       p_tvb = tvb_new_subset(tvb, po, pc, pc);
+                               }
+                       } else {
+                               p_tvb = NULL;
+                       }
+                       if(dc>0){
+                               if(dc>tvb_length_remaining(tvb, od)){
+                                       d_tvb = tvb_new_subset(tvb, od, tvb_length_remaining(tvb, od), dc);
+                               } else {
+                                       d_tvb = tvb_new_subset(tvb, od, dc, dc);
+                               }
+                       } else {
+                               d_tvb = NULL;
+                       }
+                       if(sc){
+                               s_tvb = tvb_new_subset(tvb, so, tvb_length_remaining(tvb, so), tvb_length_remaining(tvb, so));
+                       } else {
+                               s_tvb = NULL;
+                       }
+
+                       if(!strncmp("\\PIPE\\LANMAN", an, 12)){
+                               si->subcmd=TRANSACTION_PIPE_LANMAN;
+                                       dissect_pipe_smb(p_tvb, d_tvb, pinfo, top_tree);
+                       }
+                       if(!strncmp("\\MAILSLOT\\", an, 10)){
+                               si->subcmd=TRANSACTION_MAILSLOT;
+                                       dissect_mailslot_smb(s_tvb, d_tvb, an+10, pinfo, top_tree);
+                       }
+               } else {
+                       if(check_col(pinfo->fd, COL_INFO)){
+                               col_append_str(pinfo->fd, COL_INFO,
+                                       "[transact continuation] ");
+                       }
+               }
+       }
+#endif
 
-        /* Build display for: PrimaryDomain */
+       END_OF_SMB
 
-        PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       return offset;
+}
 
-        if (tree) {
+/*qqq*/
 
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "PrimaryDomain: %s", PrimaryDomain);
 
-        }
+static int
+dissect_4_3_4_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
+       int old_offset = offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+                   val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+       }
 
-        offset += string_len; /* Skip PrimaryDomain */
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_create_time,
+               hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_access_time,
+               hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_last_write_time,
+               hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* data size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* File Attributes */
+       CHECK_BYTE_COUNT_SUBR(2);
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+       *bcp -= 2;
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(1);
+       fn_len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 1, fn_len);
+       COUNT_BYTES_SUBR(1);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
 
-      }
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, " %s",
+               fn);
+       }
+       proto_item_append_text(item, " File: %s", fn);
+       proto_item_set_len(item, offset-old_offset);
 
-      break;
+       *trunc = FALSE;
+       return offset;
+}
 
-    case 4:
+static int
+dissect_4_3_4_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
+       int old_offset = offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+                   val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+       }
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_create_time,
+               hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_access_time,
+               hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+               hf_smb_last_write_time,
+               hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
+       *bcp -= 4;
+
+       /* data size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* File Attributes */
+       CHECK_BYTE_COUNT_SUBR(2);
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+       *bcp -= 2;
+
+       /* ea size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_ea_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(1);
+       fn_len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 1, fn_len);
+       COUNT_BYTES_SUBR(1);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
 
-      /* Build display for: AndXCommand */
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, " %s",
+               fn);
+       }
 
-      AndXCommand = GBYTE(pd, offset);
+       proto_item_append_text(item, " File: %s", fn);
+       proto_item_set_len(item, offset-old_offset);
 
-      if (tree) {
+       *trunc = FALSE;
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s",
-                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+static int
+dissect_4_3_4_4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
+       int old_offset = offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       guint32 neo;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+                   val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+       }
 
-      }
+       /* next entry offset */
+       CHECK_BYTE_COUNT_SUBR(4);
+       neo = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+       COUNT_BYTES_SUBR(4);
+       
+       /* file index */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Create Time", hf_smb_create_time);
+       *bcp -= 8;
+       
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Access Time", hf_smb_access_time);
+       *bcp -= 8;
+       
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Write Time", hf_smb_last_write_time);
+       *bcp -= 8;
+       
+       /* last change time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Change Time", hf_smb_change_time);
+       *bcp -= 8;
+       
+       /* end of file */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* Extended File Attributes */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
+       *bcp -= 4;
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(4);
+       fn_len = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
 
-      offset += 1; /* Skip AndXCommand */
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, " %s",
+               fn);
+       }
 
-      /* Build display for: AndXReserved */
+       /* skip to next structure */
+       if(neo){
+               padcnt = (old_offset + neo) - offset;
+               if (padcnt < 0) {
+                       /*
+                        * XXX - this is bogus; flag it?
+                        */
+                       padcnt = 0;
+               }
+               if (padcnt != 0) {
+                       CHECK_BYTE_COUNT_SUBR(padcnt);
+                       COUNT_BYTES_SUBR(padcnt);
+               }
+       }
 
-      AndXReserved = GBYTE(pd, offset);
+       proto_item_append_text(item, " File: %s", fn);
+       proto_item_set_len(item, offset-old_offset);
 
-      if (tree) {
+       *trunc = FALSE;
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+static int
+dissect_4_3_4_5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len;
+       const char *fn;
+       int old_offset = offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       guint32 neo;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+                   val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+       }
 
-      }
+       /* next entry offset */
+       CHECK_BYTE_COUNT_SUBR(4);
+       neo = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+       COUNT_BYTES_SUBR(4);
+       
+       /* file index */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Create Time", hf_smb_create_time);
+       *bcp -= 8;
+       
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Access Time", hf_smb_access_time);
+       *bcp -= 8;
+       
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Write Time", hf_smb_last_write_time);
+       *bcp -= 8;
+       
+       /* last change time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Change Time", hf_smb_change_time);
+       *bcp -= 8;
+       
+       /* end of file */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* Extended File Attributes */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
+       *bcp -= 4;
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(4);
+       fn_len = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+       COUNT_BYTES_SUBR(4);
+
+       /* ea size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_ea_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
 
-      offset += 1; /* Skip AndXReserved */
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, " %s",
+               fn);
+       }
 
-      /* Build display for: AndXOffset */
+       /* skip to next structure */
+       if(neo){
+               padcnt = (old_offset + neo) - offset;
+               if (padcnt < 0) {
+                       /*
+                        * XXX - this is bogus; flag it?
+                        */
+                       padcnt = 0;
+               }
+               if (padcnt != 0) {
+                       CHECK_BYTE_COUNT_SUBR(padcnt);
+                       COUNT_BYTES_SUBR(padcnt);
+               }
+       }
 
-      AndXOffset = GSHORT(pd, offset);
+       proto_item_append_text(item, " File: %s", fn);
+       proto_item_set_len(item, offset-old_offset);
 
-      if (tree) {
+       *trunc = FALSE;
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+static int
+dissect_4_3_4_6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len, sfn_len;
+       const char *fn, *sfn;
+       int old_offset = offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       guint32 neo;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+                   val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+       }
 
-      }
+       /* next entry offset */
+       CHECK_BYTE_COUNT_SUBR(4);
+       neo = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+       COUNT_BYTES_SUBR(4);
+       
+       /* file index */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* create time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Create Time", hf_smb_create_time);
+       *bcp -= 8;
+       
+       /* access time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Access Time", hf_smb_access_time);
+       *bcp -= 8;
+       
+       /* last write time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Write Time", hf_smb_last_write_time);
+       *bcp -= 8;
+       
+       /* last change time */
+       CHECK_BYTE_COUNT_SUBR(8);
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+               "Change Time", hf_smb_change_time);
+       *bcp -= 8;
+       
+       /* end of file */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* allocation size */
+       CHECK_BYTE_COUNT_SUBR(8);
+       proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+       COUNT_BYTES_SUBR(8);
+
+       /* Extended File Attributes */
+       CHECK_BYTE_COUNT_SUBR(4);
+       offset = dissect_file_ext_attr(tvb, pinfo, tree, offset);
+       *bcp -= 4;
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(4);
+       fn_len = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+       COUNT_BYTES_SUBR(4);
+
+       /* ea size */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_ea_size, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* short file name len */
+       CHECK_BYTE_COUNT_SUBR(1);
+       sfn_len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_short_file_name_len, tvb, offset, 1, sfn_len);
+       COUNT_BYTES_SUBR(1);
+
+       /* reserved byte */
+       CHECK_BYTE_COUNT_SUBR(1);
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       COUNT_BYTES_SUBR(1);
+       /* short file name */
+       sfn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &sfn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(sfn);
+       proto_tree_add_string(tree, hf_smb_short_file_name, tvb, offset, 24,
+               sfn);
+       COUNT_BYTES_SUBR(24);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
 
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, " %s",
+               fn);
+       }
 
-      offset += 2; /* Skip AndXOffset */
+       /* skip to next structure */
+       if(neo){
+               padcnt = (old_offset + neo) - offset;
+               if (padcnt < 0) {
+                       /*
+                        * XXX - this is bogus; flag it?
+                        */
+                       padcnt = 0;
+               }
+               if (padcnt != 0) {
+                       CHECK_BYTE_COUNT_SUBR(padcnt);
+                       COUNT_BYTES_SUBR(padcnt);
+               }
+       }
 
-      /* Build display for: Action */
+       proto_item_append_text(item, " File: %s", fn);
+       proto_item_set_len(item, offset-old_offset);
 
-      Action = GSHORT(pd, offset);
+       *trunc = FALSE;
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_4_3_4_7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+       int fn_len, sfn_len;
+       const char *fn, *sfn;
+       int old_offset = offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       guint32 neo;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+                   val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+               tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+       }
+       /* next entry offset */
+       CHECK_BYTE_COUNT_SUBR(4);
+       neo = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+       COUNT_BYTES_SUBR(4);
+       
+       /* file index */
+       CHECK_BYTE_COUNT_SUBR(4);
+       proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name len */
+       CHECK_BYTE_COUNT_SUBR(4);
+       fn_len = tvb_get_letohl(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+       COUNT_BYTES_SUBR(4);
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+       CHECK_STRING_SUBR(fn);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       COUNT_BYTES_SUBR(fn_len);
 
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Action: %u", Action);
-       Action_tree = proto_item_add_subtree(ti, ett_smb_ssetupandxaction);
-       proto_tree_add_text(Action_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Action, 0x0001, 16, "Logged in as GUEST", "Not logged in as GUEST"));
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, " %s",
+               fn);
+       }
 
-      }
+       /* skip to next structure */
+       if(neo){
+               padcnt = (old_offset + neo) - offset;
+               if (padcnt < 0) {
+                       /*
+                        * XXX - this is bogus; flag it?
+                        */
+                       padcnt = 0;
+               }
+               if (padcnt != 0) {
+                       CHECK_BYTE_COUNT_SUBR(padcnt);
+                       COUNT_BYTES_SUBR(padcnt);
+               }
+       }
 
-      offset += 2; /* Skip Action */
+       proto_item_append_text(item, " File: %s", fn);
+       proto_item_set_len(item, offset-old_offset);
 
-      /* Build display for: Security Blob Length */
+       *trunc = FALSE;
+       return offset;
+}
+static int
+dissect_4_3_4_8(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+    int offset, guint16 *bcp, gboolean *trunc)
+{
+/*XXX im lazy. i havnt implemented this */
+       offset += *bcp;
+       *bcp = 0;
+       *trunc = FALSE;
+       return offset;
+}
 
-      SecurityBlobLength = GSHORT(pd, offset);
+/*dissect the data block for TRANS2_FIND_FIRST2*/
+static int
+dissect_ff2_response_data(tvbuff_t * tvb, packet_info * pinfo,
+    proto_tree * tree, int offset, guint16 *bcp, gboolean *trunc)
+{
+       smb_info_t *si;
 
-      if (tree) {
+       if(!*bcp){
+               return offset;
+       }
+       
+       si = (smb_info_t *)pinfo->private_data;
+       switch(si->info_level){
+       case 1:         /*Info Standard*/
+               offset = dissect_4_3_4_1(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 2:         /*Info Query EA Size*/
+               offset = dissect_4_3_4_2(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 3:         /*Info Query EAs From List same as 
+                               InfoQueryEASize*/
+               offset = dissect_4_3_4_2(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 0x0101:    /*Find File Directory Info*/
+               offset = dissect_4_3_4_4(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 0x0102:    /*Find File Full Directory Info*/
+               offset = dissect_4_3_4_5(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 0x0103:    /*Find File Names Info*/
+               offset = dissect_4_3_4_7(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 0x0104:    /*Find File Both Directory Info*/
+               offset = dissect_4_3_4_6(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       case 0x0202:    /*Find File UNIX*/
+               offset = dissect_4_3_4_8(tvb, pinfo, tree, offset, bcp,
+                   trunc);
+               break;
+       default:        /* unknown info level */
+               *trunc = FALSE;
+               break;
+       }
+       return offset;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Security Blob Length: %u", SecurityBlobLength);
 
-      }
+static int
+dissect_fs_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-      offset += 2; /* Skip Security Blob Length */
+       mask = tvb_get_letohl(tvb, offset);
 
-      /* Build display for: Byte Count (BCC) */
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "FS Attributes: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_fs_attributes);
+       }
 
-      ByteCount = GSHORT(pd, offset);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_css,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_cpn,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_pacls,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_fc,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_vq,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_dim,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_fs_attr_vic,
+               tvb, offset, 4, mask);
+
+       offset += 4;
+       return offset;
+}
 
-      if (tree) {
+static int
+dissect_device_characteristics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint32 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       mask = tvb_get_letohl(tvb, offset);
 
-      }
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+                       "Device Characteristics: 0x%08x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_device_characteristics);
+       }
 
-      offset += 2; /* Skip Byte Count (BCC) */
+       proto_tree_add_boolean(tree, hf_smb_device_char_removable,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_device_char_read_only,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_device_char_floppy,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_device_char_write_once,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_device_char_remote,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_device_char_mounted,
+               tvb, offset, 4, mask);
+       proto_tree_add_boolean(tree, hf_smb_device_char_virtual,
+               tvb, offset, 4, mask);
+
+       offset += 4;
+       return offset;
+}
 
-      if (ByteCount > 0) {
 
-       SecurityBlob = pd + offset;
+/*dissect the data block for TRANS2_QUERY_FS_INFORMATION*/
+static int
+dissect_qfsi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+    int offset, guint16 *bcp)
+{
+       smb_info_t *si;
+       int fn_len, vll, fnl;
+       const char *fn;
 
-       if (SecurityBlobLength > 0) {
+       if(!*bcp){
+               return offset;
+       }
+       
+       si = (smb_info_t *)pinfo->private_data;
+       switch(si->info_level){
+       case 1:         /* SMB_INFO_ALLOCATION */
+               /* filesystem id */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_fs_id, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* sectors per unit */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_sector_unit, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* units */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_fs_units, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* avail units */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_avail_units, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* bytes per sector, only 16bit integer here */
+               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+               proto_tree_add_uint(tree, hf_smb_fs_sector, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               COUNT_BYTES_TRANS_SUBR(2);
+
+               break;
+       case 2:         /* SMB_INFO_VOLUME */
+               /* volume serial number */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_volume_serial_num, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* volume label length, only one byte here */
+               CHECK_BYTE_COUNT_TRANS_SUBR(1);
+               proto_tree_add_uint(tree, hf_smb_volume_label_len, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+               COUNT_BYTES_TRANS_SUBR(1);
+
+               /* label */
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE, bcp);
+               CHECK_STRING_TRANS_SUBR(fn);
+               proto_tree_add_string(tree, hf_smb_volume_label, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS_SUBR(fn_len);
+
+               break;
+       case 0x0102:    /* SMB_QUERY_FS_VOLUME_INFO */
+               /* create time */
+               CHECK_BYTE_COUNT_TRANS_SUBR(8);
+               offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                       "Create Time", hf_smb_create_time);
+               *bcp -= 8;
+       
+               /* volume serial number */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_volume_serial_num, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* volume label length */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               vll = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_volume_label_len, tvb, offset, 4, vll);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* 2 reserved bytes */
+               CHECK_BYTE_COUNT_TRANS_SUBR(2);
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+               COUNT_BYTES_TRANS_SUBR(2);
+
+               /* label */
+               fn_len = vll;
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+               CHECK_STRING_TRANS_SUBR(fn);
+               proto_tree_add_string(tree, hf_smb_volume_label, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS_SUBR(fn_len);
+
+               break;
+       case 0x0103:    /* SMB_QUERY_FS_SIZE_INFO */
+               /* allocation size */
+               CHECK_BYTE_COUNT_TRANS_SUBR(8);
+               proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+               COUNT_BYTES_TRANS_SUBR(8);
+
+               /* free allocation units */
+               CHECK_BYTE_COUNT_TRANS_SUBR(8);
+               proto_tree_add_item(tree, hf_smb_free_alloc_units64, tvb, offset, 8, TRUE);
+               COUNT_BYTES_TRANS_SUBR(8);
+
+               /* sectors per unit */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_sector_unit, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* bytes per sector */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_fs_sector, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               break;
+       case 0x0104:    /* SMB_QUERY_FS_DEVICE_INFO */
+               /* device type */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_device_type, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+               /* device characteristics */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               offset = dissect_device_characteristics(tvb, pinfo, tree, offset);
+               *bcp -= 4;
+       
+               break;
+       case 0x0105:    /* SMB_QUERY_FS_ATTRIBUTE_INFO */
+               /* FS attributes */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               offset = dissect_fs_attributes(tvb, pinfo, tree, offset);
+               *bcp -= 4;
+       
+               /* max name len */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               proto_tree_add_item(tree, hf_smb_max_name_len, tvb, offset, 4, TRUE);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* fs name length */
+               CHECK_BYTE_COUNT_TRANS_SUBR(4);
+               fnl = tvb_get_letohl(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_fs_name_len, tvb, offset, 4, fnl);
+               COUNT_BYTES_TRANS_SUBR(4);
+
+               /* label */
+               fn_len = fnl;
+               fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, TRUE, bcp);
+               CHECK_STRING_TRANS_SUBR(fn);
+               proto_tree_add_string(tree, hf_smb_fs_name, tvb, offset, fn_len,
+                       fn);
+               COUNT_BYTES_TRANS_SUBR(fn_len);
+
+               break;
+       }
+       return offset;
+}
+static int
+dissect_transaction2_response_data(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *parent_tree, int offset, guint16 dc)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       int fn_len;
+       const char *fn;
+       int count;
+       gboolean trunc;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               if (si->subcmd != -1) {
+                       item = proto_tree_add_text(parent_tree, tvb, offset, dc,
+                               "%s Data",
+                               val_to_str(si->subcmd, trans2_cmd_vals, 
+                                       "Unknown (0x%02x)"));
+                       tree = proto_item_add_subtree(item, ett_smb_transaction_data);
+               } else {
+                       item = proto_tree_add_text(parent_tree, tvb, offset, dc,
+                               "Unknown Transaction2 Data");
+               }
+       }
 
-         /* XXX - is this ASN.1-encoded?  Is it a Kerberos data structure,
-            at least in NT 5.0-and-later server replies? */
+       switch(si->subcmd){
+       case 0x00:      /*TRANS2_OPEN2*/
+               /* XXX not implemented yet. See SNIA doc */
+               break;
+       case 0x01:      /*TRANS2_FIND_FIRST2*/
+               /* returned data */
+               count = si->info_count;
+
+               if (count && check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO,
+                       ", Files:");
+               }
+
+               while(count--){
+                       offset = dissect_ff2_response_data(tvb, pinfo, tree,
+                               offset, &dc, &trunc);
+                       if (trunc)
+                               break;
+               }
+               break;
+       case 0x02:      /*TRANS2_FIND_NEXT2*/
+               /* returned data */
+               count = si->info_count;
+
+               if (count && check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO,
+                       ", Files:");
+               }
+
+               while(count--){
+                       offset = dissect_ff2_response_data(tvb, pinfo, tree,
+                               offset, &dc, &trunc);
+                       if (trunc)
+                               break;
+               }
+               break;
+       case 0x03:      /*TRANS2_QUERY_FS_INFORMATION*/
+               offset = dissect_qfsi_vals(tvb, pinfo, tree, offset, &dc);
+               break;
+       case 0x05:      /*TRANS2_QUERY_PATH_INFORMATION*/
+               offset = dissect_qpi_loi_vals(tvb, pinfo, tree, offset, &dc);
+               break;
+       case 0x06:      /*TRANS2_SET_PATH_INFORMATION*/
+               /* no data in this response */
+               break;
+       case 0x07:      /*TRANS2_QUERY_FILE_INFORMATION*/
+               /* identical to QUERY_PATH_INFO */
+               offset = dissect_qpi_loi_vals(tvb, pinfo, tree, offset, &dc);
+               break;
+       case 0x08:      /*TRANS2_SET_FILE_INFORMATION*/
+               /* no data in this response */
+               break;
+       case 0x09:      /*TRANS2_FSCTL*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0a:      /*TRANS2_IOCTL2*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0b:      /*TRANS2_FIND_NOTIFY_FIRST*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0c:      /*TRANS2_FIND_NOTIFY_NEXT*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0d:      /*TRANS2_CREATE_DIRECTORY*/
+               /* no data in this response */
+               break;
+       case 0x0e:      /*TRANS2_SESSION_SETUP*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x10:      /*TRANS2_GET_DFS_REFERRAL*/
+               offset = dissect_get_dfs_referral_data(tvb, pinfo, tree, offset, &dc);
+               break;
+       case 0x11:      /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+               /* the SNIA spec appears to say the response has no data */
+               break;
+       case -1:
+               /*
+                * We don't know what the matching request was; don't
+                * bother putting anything else into the tree for the data.
+                */
+               offset += dc;
+               dc = 0;
+               break;
+       }
 
-         if (tree) {
+       /* ooops there were data we didnt know how to process */
+       if(dc != 0){
+               proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, dc, TRUE);
+               offset += dc;
+       }
 
-           proto_tree_add_text(tree, NullTVB, offset, SecurityBlobLength, "Security Blob: %s",
-                               bytes_to_str(SecurityBlob, SecurityBlobLength));
+       return offset;
+}
 
-         }
-
-         offset += SecurityBlobLength; /* Skip Security Blob */
 
+static int
+dissect_transaction2_response_parameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int pc, int od)
+{
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       smb_info_t *si;
+       int fn_len, lno;
+       const char *fn;
+       int old_offset = offset;
+
+       si = (smb_info_t *)pinfo->private_data;
+
+       if(parent_tree){
+               if (si->subcmd != -1) {
+                       item = proto_tree_add_text(parent_tree, tvb, offset, pc,
+                               "%s Parameters",
+                               val_to_str(si->subcmd, trans2_cmd_vals, 
+                                               "Unknown (0x%02x)"));
+                       tree = proto_item_add_subtree(item, ett_smb_transaction_params);
+               } else {
+                       item = proto_tree_add_text(parent_tree, tvb, offset, pc,
+                               "Unknown Transaction2 Parameters");
+               }
        }
 
-       /* Build display for: NativeOS */
-
-       NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeOS: %s", NativeOS);
-
+       switch(si->subcmd){
+       case 0x00:      /*TRANS2_OPEN2*/
+               /* fid */
+               proto_tree_add_item(tree, hf_smb_fid, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* File Attributes */
+               offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+
+               /* create time */
+               offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
+                       hf_smb_create_time, 
+                       hf_smb_create_dos_date, hf_smb_create_dos_time, TRUE);
+
+               /* data size */
+               proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* granted access */
+               offset = dissect_access(tvb, pinfo, tree, offset, "Granted");
+
+               /* File Type */
+               proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* IPC State */
+               offset = dissect_ipc_state(tvb, pinfo, tree, offset);
+
+               /* open_action */
+               offset = dissect_open_action(tvb, pinfo, tree, offset);
+
+               /* 4 reserved bytes */
+               proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               /* ea error offset, only a 16 bit integer here */
+               proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* ea length */
+               proto_tree_add_item(tree, hf_smb_ea_length, tvb, offset, 4, TRUE);
+               offset += 4;
+
+               break;
+       case 0x01:      /*TRANS2_FIND_FIRST2*/
+               /* Find First2 information level */
+               proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, 0, 0, si->info_level);
+
+               /* sid */
+               proto_tree_add_item(tree, hf_smb_sid, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* search count */
+               si->info_count = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_search_count, tvb, offset, 2, si->info_count);
+               offset += 2;
+
+               /* end of search */
+               proto_tree_add_item(tree, hf_smb_end_of_search, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* ea error offset, only a 16 bit integer here */
+               proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* last name offset */
+               lno = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_last_name_offset, tvb, offset, 2, lno);
+               offset += 2;
+
+               break;
+       case 0x02:      /*TRANS2_FIND_NEXT2*/
+               /* search count */
+               si->info_count = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_search_count, tvb, offset, 2, si->info_count);
+               offset += 2;
+
+               /* end of search */
+               proto_tree_add_item(tree, hf_smb_end_of_search, tvb, offset, 2, TRUE);
+               offset += 2;
+
+               /* ea error offset , only a 16 bit integer here*/
+               proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               /* last name offset */
+               lno = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_smb_last_name_offset, tvb, offset, 2, lno);
+               offset += 2;
+
+               break;
+       case 0x03:      /*TRANS2_QUERY_FS_INFORMATION*/
+               /* no parameter block here */
+               break;
+       case 0x05:      /*TRANS2_QUERY_PATH_INFORMATION*/
+               /* no parameter block here */
+               break;
+       case 0x06:      /*TRANS2_SET_PATH_INFORMATION*/
+               /* no parameter block here */
+               break;
+       case 0x07:      /*TRANS2_QUERY_FILE_INFORMATION*/
+               /* no parameter block here */
+               break;
+       case 0x08:      /*TRANS2_SET_FILE_INFORMATION*/
+               /* no parameter block here */
+               break;
+       case 0x09:      /*TRANS2_FSCTL*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0a:      /*TRANS2_IOCTL2*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0b:      /*TRANS2_FIND_NOTIFY_FIRST*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0c:      /*TRANS2_FIND_NOTIFY_NEXT*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x0d:      /*TRANS2_CREATE_DIRECTORY*/
+               /* ea error offset, only a 16 bit integer here */
+               proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+               offset += 2;
+
+               break;
+       case 0x0e:      /*TRANS2_SESSION_SETUP*/
+               /* XXX dont know how to dissect this one (yet)*/
+               break;
+       case 0x10:      /*TRANS2_GET_DFS_REFERRAL*/
+               /* XXX dont know how to dissect this one (yet) see SNIA doc*/
+               break;
+       case 0x11:      /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+               /* XXX dont know how to dissect this one (yet) see SNIA doc*/
+               break;
+       case -1:
+               /*
+                * We don't know what the matching request was; don't
+                * bother putting anything else into the tree for the data.
+                */
+               offset += pc;
+               break;
        }
 
-       offset += string_len; /* Skip NativeOS */
-
-       /* Build display for: NativeLanMan */
-
-       NativeLanMan = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeLanMan: %s", NativeLanMan);
-
+       /* ooops there were data we didnt know how to process */
+       if((offset-old_offset)<pc){
+               proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, pc-(offset-old_offset), TRUE);
+               offset += pc-(offset-old_offset);
        }
 
-       offset += string_len; /* Skip NativeLanMan */
-
-      }
-
-      break;
-
-    default:
-
-      /* XXX - dump the parameter words, one word at a time? */
-
-      offset += WordCount;
-
-      /* Build display for: Byte Count (BCC) */
-
-      ByteCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-      }
-
-      offset += 2; /* Skip Byte Count (BCC) */
-
-      break;
-
-    }
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  }
-
+       return offset;
 }
 
-void
-dissect_tcon_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8      wct, andxcmd = 0xFF;
-  guint16     andxoffs = 0, flags, passwdlen, bcc, optionsup;
-  const char  *str;
-  int         string_len;
-  proto_tree  *flags_tree;
-  proto_tree  *optionsup_tree;
-  proto_item  *ti;
-
-  wct = pd[offset];
-
-  /* Now figure out what format we are talking about, 2, 3, or 4 response
-   * words ...
-   */
-
-  if (!(si.request && (wct == 4)) && !(!si.request && (wct == 2)) &&
-      !(!si.request && (wct == 3)) && !(wct == 0)) {
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Invalid TCON_ANDX format. WCT should be 0, 2, 3, or 4 ..., not %u", wct);
-
-      proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data");
-
-      return;
-
-    }
-    
-  }
-
-  if (tree) {
-
-    proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", wct);
-
-  }
-
-  offset += 1;
-
-  if (wct > 0) {
-
-    andxcmd = pd[offset];
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Next Command: %s",
-                         (andxcmd == 0xFF) ? "No further commands":
-                         decode_smb_name(andxcmd));
-               
-      proto_tree_add_text(tree, NullTVB, offset + 1, 1, "Reserved (MBZ): %u", pd[offset+1]);
-
-    }
-
-    offset += 2;
-
-    andxoffs = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Offset to next command: %u", andxoffs);
-
-    }
-
-    offset += 2;
-
-  }
-
-  switch (wct) {
-
-  case 0:
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    break;
-
-  case 4:
-
-    flags = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Additional Flags: 0x%04x", flags);
-      flags_tree = proto_item_add_subtree(ti, ett_smb_aflags);
-      proto_tree_add_text(flags_tree, NullTVB, offset, 2, "%s", 
-                         decode_boolean_bitfield(flags, 0x0001, 16,
-                                                 "Disconnect TID",
-                                                 "Don't disconnect TID"));
-
-    }
-
-    offset += 2;
-
-    passwdlen = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Password Length: %u", passwdlen);
-
-    }
-
-    offset += 2;
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    offset += 2;
-
-    str = pd + offset;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Password: %s", format_text(str, passwdlen));
-
-    }
-
-    offset += passwdlen;
-
-    str = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Path: %s", str);
-
-    }
-
-    offset += string_len;
-
-    str = pd + offset;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service: %s", str);
-
-    }
-
-    break;
-
-  case 2:
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    offset += 2;
-
-    str = pd + offset;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service Type: %s",
-                         str);
-
-    }
-
-    offset += strlen(str) + 1;
-
-    break;
-
-  case 3:
-
-    optionsup = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Optional Support: 0x%04x", 
-                         optionsup);
-      optionsup_tree = proto_item_add_subtree(ti, ett_smb_optionsup);
-      proto_tree_add_text(optionsup_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(optionsup, 0x0001, 16, "Share supports Search", "Share doesn't support Search"));
-      proto_tree_add_text(optionsup_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(optionsup, 0x0002, 16, "Share is in DFS", "Share isn't in DFS"));
-      
-    }
-
-    offset += 2;
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    offset += 2;
-
-    /*
-     * NOTE: the Service string is always ASCII, even if the "strings are
-     * Unicode" bit is set in the flags2 field of the SMB.
-     */
-
-    str = pd + offset;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service: %s", str);
-
-    }
-
-    offset += strlen(str) + 1;
-
-    str = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Native File System: %s", str);
-
-    }
-
-    offset += string_len;
-
-    
-    break;
-
-  default:
-       ; /* nothing */
-       break;
-  }
-
-  if (andxcmd != 0xFF) /* Process that next command ... ??? */
-
-    (dissect[andxcmd])(pd, SMB_offset + andxoffs, fd, parent, tree, si, max_data - offset, SMB_offset);
 
-}
-
-void 
-dissect_negprot_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
+static int
+dissect_transaction_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  guint8        wct, enckeylen;
-  guint16       bcc, mode, rawmode, dialect;
-  guint32       caps;
-  proto_tree    *dialects = NULL, *mode_tree, *caps_tree, *rawmode_tree;
-  proto_item    *ti;
-  const char    *str;
-  char          *ustr;
-  int           ustr_len;
-
-  wct = pd[offset];    /* Should be 0, 1 or 13 or 17, I think */
-
-  if (!((wct == 0) && si.request) && !((wct == 1) && !si.request) &&
-      !((wct == 13) && !si.request) && !((wct == 17) && !si.request)) {
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Invalid Negotiate Protocol format. WCT should be zero or 1 or 13 or 17 ..., not %u", wct);
-
-      proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data");
-
-      return;
-    }
-  }
-
-  if (tree) {
-
-    proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %d", wct);
-
-  }
-
-  offset += 1; 
-
-  if (!si.request && wct == 0) {
+       conversation_t *conversation;
+       struct smb_request_val *request_val;
+       guint8 sc=0, wc;
+       guint16 od=0, tf, po=0, pc=0, pd, dc=0, dd=0;
+       int so=0;
+       guint32 to;
+       smb_info_t *si;
+       guint16 bc;
+       int padcnt;
+
+       si = (smb_info_t *)pinfo->private_data;
 
-    /* Build display for: Byte Count (BCC) */
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    return;
-
-  }
-
-  /* Now decode the various formats ... */
-
-  switch (wct) {
+       /*
+        * Find out what conversation this packet is part of.
+        */
+       conversation = find_conversation(&pinfo->src, &pinfo->dst,
+           pinfo->ptype,  pinfo->srcport, pinfo->destport, 0);
 
-  case 0:     /* A request */
+       if (conversation == NULL) {
+               /*
+                * There isn't one yet; create it.
+                */
+               conversation = conversation_new(&pinfo->src, &pinfo->dst,
+                   pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+       }
 
-    bcc = GSHORT(pd, offset);
+       si->conversation = conversation;  /* Save this */
+
+       request_val = do_transaction_hashing(conversation, *si, pinfo->fd);
+
+       si->request_val = request_val;  /* Save this for later */
+
+       if(request_val != NULL){
+               switch(si->cmd){
+
+               case 0x32:
+                       /* transaction2 */
+                       si->subcmd = request_val->last_transact2_command;
+                       if (si->subcmd != -1) {
+                               proto_tree_add_uint(tree, hf_smb_trans2_subcmd, tvb, 0, 0, si->subcmd);
+                               if (check_col(pinfo->fd, COL_INFO)) {
+                                       col_append_fstr(pinfo->fd, COL_INFO, " %s",
+                                               val_to_str(si->subcmd,
+                                                       trans2_cmd_vals, 
+                                                       "<unknown (0x%02x)> "));
+                               }
+                       } else {
+                               /*
+                                * We didn't manage to extract the subcommand
+                                * from the matching request (perhaps because
+                                * the frame was short), so we don't know what
+                                * type of transaction this is.
+                                */
+                               proto_tree_add_text(tree, tvb, 0, 0,
+                                       "Subcommand: <UNKNOWN> since transaction code wasn't found in request packet");
+                               if (check_col(pinfo->fd, COL_INFO)) {
+                                       col_append_fstr(pinfo->fd, COL_INFO, "<unknown> ");
+                               }
+                       }
+                       break;
+               }
+               si->info_level = request_val->last_level;
+       } else {
+               /* we have not seen the request yet so we don't know what 
+                  subcommand it was */
+               proto_tree_add_text(tree, tvb, 0, 0,
+                       "Subcommand: <UNKNOWN> since request packet was not captured");
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_append_fstr(pinfo->fd, COL_INFO, "<unknown> ");
+               }
+               si->subcmd = -1;
+               si->info_level = -1;
+       }
 
-    if (tree) {
+       WORD_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
+       /* total param count, only a 16bit integer here */
+       proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-    }
+       /* total data count, only a 16 bit integer here */
+       proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-    offset += 2;
+       /* 2 reserved bytes */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+       offset += 2;
 
-    if (tree) {
+       /* param count */
+       pc = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_count16, tvb, offset, 2, pc);
+       offset += 2;
 
-      ti = proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Dialects");
-      dialects = proto_item_add_subtree(ti, ett_smb_dialects);
+       /* param offset */
+       po = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_offset16, tvb, offset, 2, po);
+       offset += 2;
 
-    }
+       /* param disp */
+       pd = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_param_disp16, tvb, offset, 2, pd);
+       offset += 2;
 
-    while (IS_DATA_IN_FRAME(offset)) {
-      const char *str;
-
-      if (tree) {
-
-       proto_tree_add_text(dialects, NullTVB, offset, 1, "Dialect Marker: %d", pd[offset]);
-
-      }
-
-      offset += 1;
-
-      str = pd + offset;
-
-      if (tree) {
-
-       proto_tree_add_text(dialects, NullTVB, offset, strlen(str)+1, "Dialect: %s", str);
-
-      }
-
-      offset += strlen(str) + 1;
-
-    }
-    break;
-
-  case 1:     /* PC NETWORK PROGRAM 1.0 */
-
-    dialect = GSHORT(pd, offset);
-
-    if (tree) {  /* Hmmmm, what if none of the dialects is recognized */
-
-      if (dialect == 0xFFFF) { /* Server didn't like them dialects */
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Supplied dialects not recognized");
-
-      }
-      else {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Dialect Index: %u, PC NETWORK PROTGRAM 1.0", dialect);
-
-      }
-
-    }
-
-    offset += 2;
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    break;
-
-  case 13:    /* Greater than Core and up to and incl LANMAN2.1  */
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", GSHORT(pd, offset));
-
-    }
-
-    /* Much of this is similar to response 17 below */
-
-    offset += 2;
-
-    mode = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Security Mode: 0x%04x", mode);
-      mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
-      proto_tree_add_text(mode_tree, NullTVB, offset, 2, "%s",
-                         decode_boolean_bitfield(mode, 0x0001, 16,
-                                                 "Security  = User",
-                                                 "Security  = Share"));
-      proto_tree_add_text(mode_tree, NullTVB, offset, 2, "%s",
-                         decode_boolean_bitfield(mode, 0x0002, 16,
-                                                 "Passwords = Encrypted",
-                                                 "Passwords = Plaintext"));
-
-    }
-
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max buffer size:     %u", GSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset));
-
-    }
-    
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max vcs:             %u", GSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    rawmode = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Raw Mode: 0x%04x", rawmode);
-      rawmode_tree = proto_item_add_subtree(ti, ett_smb_rawmode);
-      proto_tree_add_text(rawmode_tree, NullTVB, offset, 2, "%s",
-                         decode_boolean_bitfield(rawmode, 0x01, 16,
-                                                 "Read Raw supported",
-                                                 "Read Raw not supported"));
-      proto_tree_add_text(rawmode_tree, NullTVB, offset, 2, "%s",
-                         decode_boolean_bitfield(rawmode, 0x02, 16,
-                                                 "Write Raw supported",
-                                                 "Write Raw not supported"));
-
-    }
-
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Session key:         %08x", GWORD(pd, offset));
-
-    }
-
-    offset += 4;
-
-    /* Now the server time, two short parameters ... */
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Server Time: %s",
-                       dissect_dos_time(GSHORT(pd, offset)));
-      proto_tree_add_text(tree, NullTVB, offset + 2, 2, "Server Date: %s",
-                       dissect_dos_date(GSHORT(pd, offset + 2)));
-
-    }
-
-    offset += 4;
-
-    /* Server Time Zone, SHORT */
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Server time zone: %i min from UTC",
-                         (signed short)GSSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    /* Challenge Length */
-
-    enckeylen = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Challenge Length: %u", enckeylen);
-
-    }
-
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u (MBZ)", GSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
-
-    }
-
-    offset += 2;
-
-    if (enckeylen) { /* only if non-zero key len */
-
-      str = pd + offset;
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, enckeylen, "Challenge: %s",
-                               bytes_to_str(str, enckeylen));
-      }
-
-      offset += enckeylen;
-
-    }
-
-    /* Primary Domain ... */
-
-    str = pd + offset;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str)+1, "Primary Domain: %s", str);
-
-    }
-
-    break;
-
-  case 17:    /* Greater than LANMAN2.1 */
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Dialect Index: %u, Greater than LANMAN2.1", GSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    mode = GBYTE(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 1, "Security Mode: 0x%02x", mode);
-      mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
-      proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s",
-                         decode_boolean_bitfield(mode, 0x01, 8,
-                                                 "Security  = User",
-                                                 "Security  = Share"));
-      proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s",
-                         decode_boolean_bitfield(mode, 0x02, 8,
-                                                 "Passwords = Encrypted",
-                                                 "Passwords = Plaintext"));
-      proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s",
-                         decode_boolean_bitfield(mode, 0x04, 8,
-                                                 "Security signatures enabled",
-                                                 "Security signatures not enabled"));
-      proto_tree_add_text(mode_tree, NullTVB, offset, 1, "%s",
-                         decode_boolean_bitfield(mode, 0x08, 8,
-                                                 "Security signatures required",
-                                                 "Security signatures not required"));
-
-    }
-
-    offset += 1;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset));
-
-    }
-    
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max vcs:             %u", GSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max buffer size:     %u", GWORD(pd, offset));
-
-    }
-
-    offset += 4;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Max raw size:        %u", GWORD(pd, offset));
-
-    }
-
-    offset += 4;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Session key:         %08x", GWORD(pd, offset));
-
-    }
-
-    offset += 4;
-
-    caps = GWORD(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 4, "Capabilities: 0x%04x", caps);
-      caps_tree = proto_item_add_subtree(ti, ett_smb_capabilities);
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0001, 32,
-                                                 "Raw Mode supported",
-                                                 "Raw Mode not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0002, 32,
-                                                 "MPX Mode supported",
-                                                 "MPX Mode not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0004, 32,
-                                                 "Unicode supported",
-                                                 "Unicode not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0008, 32,
-                                                 "Large files supported",
-                                                 "Large files not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0010, 32, 
-                                                 "NT LM 0.12 SMBs supported",
-                                                 "NT LM 0.12 SMBs not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0020, 32,
-                                                 "RPC remote APIs supported",
-                                                 "RPC remote APIs not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0040, 32,
-                                                 "NT status codes supported",
-                                                 "NT status codes  not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0080, 32,
-                                                 "Level 2 OpLocks supported",
-                                                 "Level 2 OpLocks not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0100, 32,
-                                                 "Lock&Read supported",
-                                                 "Lock&Read not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x0200, 32,
-                                                 "NT Find supported",
-                                                 "NT Find not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x1000, 32,
-                                                 "DFS supported",
-                                                 "DFS not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x4000, 32,
-                                                 "Large READX supported",
-                                                 "Large READX not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x8000, 32,
-                                                 "Large WRITEX supported",
-                                                 "Large WRITEX not supported"));
-      proto_tree_add_text(caps_tree, NullTVB, offset, 4, "%s",
-                         decode_boolean_bitfield(caps, 0x80000000, 32,
-                                                 "Extended security exchanges supported",
-                                                 "Extended security exchanges not supported"));
-    }
-
-    offset += 4;
-
-    /* Server time, 2 WORDS */
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "System Time Low: 0x%08x", GWORD(pd, offset));
-      proto_tree_add_text(tree, NullTVB, offset + 4, 4, "System Time High: 0x%08x", GWORD(pd, offset + 4)); 
-
-    }
-
-    offset += 8;
-
-    /* Server Time Zone, SHORT */
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Server time zone: %i min from UTC",
-                         (signed short)GSSHORT(pd, offset));
-
-    }
-
-    offset += 2;
-
-    /* Encryption key len */
-
-    enckeylen = pd[offset];
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Encryption key len: %u", enckeylen);
-
-    }
-
-    offset += 1;
-
-    bcc = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte count (BCC): %u", bcc);
-
-    }
-
-    offset += 2;
-
-    if (caps & 0x80000000) {
-      /* Extended security */
-
-      /* GUID */
-
-      if (tree) {
-
-       /* XXX - show it in GUID form, with dashes or whatever */
-       proto_tree_add_text(tree, NullTVB, offset, 16, "GUID: %s",
-                               bytes_to_str(&pd[offset], 16));
-
-      }
-
-      offset += 16;
-
-      /* Security blob */
-      /* XXX - is this ASN.1-encoded?  Is it a Kerberos data structure,
-        at least in NT 5.0-and-later server replies? */
-
-      if (bcc > 16) {
-       bcc -= 16;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, bcc, "Security blob: %s",
-                               bytes_to_str(&pd[offset], bcc));
-
-       }
-      }
-    } else {
-      /* Non-extended security */
-
-      if (enckeylen) { /* only if non-zero key len */
-
-       /* Encryption challenge key */
-
-       str = pd + offset;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, enckeylen, "Challenge encryption key: %s",
-                               bytes_to_str(str, enckeylen));
-
-       }
-
-       offset += enckeylen;
-
-      }
-
-      /* The domain, a null terminated string; Unicode if "caps" has
-        the 0x0004 bit set, ASCII (OEM character set) otherwise.
-       XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
-
-      str = pd + offset;
-
-      if (tree) {
-
-       if (caps & 0x0004) {
-         ustr = unicode_to_str(str, &ustr_len);
-         proto_tree_add_text(tree, NullTVB, offset, ustr_len+2, "OEM domain name: %s", ustr);
-       } else {
-         proto_tree_add_text(tree, NullTVB, offset, strlen(str)+1, "OEM domain name: %s", str);
-       }
-
-      }
-    }
-
-    break;
-
-  default:    /* Baddd */
-
-    if (tree)
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Bad format, should never get here");
-    return;
-
-  }
-
-}
-
-void
-dissect_deletedir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       ByteCount;
-  const char    *DirectoryName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Directory Name */
-
-    DirectoryName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Directory Name: %s", DirectoryName);
-
-    }
-
-    offset += string_len; /* Skip Directory Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_createdir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       ByteCount;
-  const char    *DirectoryName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Directory Name */
-
-    DirectoryName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Directory Name: %s", DirectoryName);
-
-    }
-
-    offset += string_len; /* Skip Directory Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-
-void
-dissect_checkdir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       ByteCount;
-  const char    *DirectoryName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Directory Name */
-
-    DirectoryName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Directory Name: %s", DirectoryName);
-
-    }
-
-    offset += string_len; /* Skip Directory Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  static const value_string OpenFunction_0x10[] = {
-       { 0, "Fail if file does not exist"},
-       { 16, "Create file if it does not exist"},
-       { 0, NULL}
-  };
-  static const value_string OpenFunction_0x03[] = {
-       { 0, "Fail if file exists"},
-       { 1, "Open file if it exists"},
-       { 2, "Truncate File if it exists"},
-       { 0, NULL}
-  };
-  static const value_string FileType_0xFFFF[] = {
-       { 0, "Disk file or directory"},
-       { 1, "Named pipe in byte mode"},
-       { 2, "Named pipe in message mode"},
-       { 3, "Spooled printer"},
-       { 0, NULL}
-  };
-  static const value_string DesiredAccess_0x70[] = {
-       { 00, "Compatibility mode"},
-       { 16, "Deny read/write/execute (exclusive)"},
-       { 32, "Deny write"},
-       { 48, "Deny read/execute"},
-       { 64, "Deny none"},
-       { 0, NULL}
-  };
-  static const value_string DesiredAccess_0x700[] = {
-       { 0, "Locality of reference unknown"},
-       { 256, "Mainly sequential access"},
-       { 512, "Mainly random access"},
-       { 768, "Random access with some locality"},
-       {0, NULL}
-  };
-  static const value_string DesiredAccess_0x4000[] = {
-       { 0, "Write through mode disabled"},
-       { 16384, "Write through mode enabled"},
-       {0, NULL}
-  };
-  static const value_string DesiredAccess_0x1000[] = {
-       { 0, "Normal file (caching permitted)"},
-       { 4096, "Do not cache this file"},
-       {0, NULL}
-  };
-  static const value_string DesiredAccess_0x07[] = {
-       { 0, "Open for reading"},
-       { 1, "Open for writing"},
-       { 2, "Open for reading and writing"},
-       { 3, "Open for execute"},
-       {0, NULL}
-  };
-  static const value_string Action_0x8000[] = {
-       { 0, "File opened by another user (or mode not supported by server)"},
-       { 32768, "File is opened only by this user at present"},
-       {0, NULL}
-  };
-  static const value_string Action_0x0003[] = {
-       { 0, "No action taken?"},
-       { 1, "The file existed and was opened"},
-       { 2, "The file did not exist but was created"},
-       { 3, "The file existed and was truncated"},
-       {0, NULL}
-  };
-  proto_tree    *Search_tree;
-  proto_tree    *OpenFunction_tree;
-  proto_tree    *Flags_tree;
-  proto_tree    *File_tree;
-  proto_tree    *FileType_tree;
-  proto_tree    *FileAttributes_tree;
-  proto_tree    *DesiredAccess_tree;
-  proto_tree    *Action_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        AndXReserved;
-  guint8        AndXCommand = 0xFF;
-  guint32       ServerFID;
-  guint32       Reserved2;
-  guint32       Reserved1;
-  guint32       DataSize;
-  guint32       AllocatedSize;
-  guint16       Search;
-  guint16       Reserved;
-  guint16       OpenFunction;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       GrantedAccess;
-  guint16       Flags;
-  guint16       FileType;
-  guint16       FileAttributes;
-  guint16       File;
-  guint16       FID;
-  guint16       DeviceState;
-  guint16       DesiredAccess;
-  guint16       CreationTime;
-  guint16       CreationDate;
-  guint16       ByteCount;
-  guint16       AndXOffset = 0;
-  guint16       Action;
-  const char    *FileName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
-
-    AndXCommand = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                         (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
-
-    }
-
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
-
-    AndXReserved = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-    }
-
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
-
-    AndXOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-    }
-
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: Flags */
-
-    Flags = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Flags: 0x%02x", Flags);
-      Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
-      proto_tree_add_text(Flags_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Flags, 0x01, 16, "Dont Return Additional Info", "Return Additional Info"));
-      proto_tree_add_text(Flags_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Flags, 0x02, 16, "Exclusive OpLock not Requested", "Exclusive OpLock Requested"));
-      proto_tree_add_text(Flags_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Flags, 0x04, 16, "Batch OpLock not Requested", "Batch OpLock Requested"));
-    
-    }
-
-    offset += 2; /* Skip Flags */
-
-    /* Build display for: Desired Access */
-
-    DesiredAccess = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Desired Access: 0x%02x", DesiredAccess);
-      DesiredAccess_tree = proto_item_add_subtree(ti, ett_smb_desiredaccess);
-      proto_tree_add_text(DesiredAccess_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(DesiredAccess, 0x07, 16, DesiredAccess_0x07, "%s"));
-      proto_tree_add_text(DesiredAccess_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(DesiredAccess, 0x70, 16, DesiredAccess_0x70, "%s"));
-      proto_tree_add_text(DesiredAccess_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(DesiredAccess, 0x700, 16, DesiredAccess_0x700, "%s"));
-      proto_tree_add_text(DesiredAccess_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(DesiredAccess, 0x1000, 16, DesiredAccess_0x1000, "%s"));
-      proto_tree_add_text(DesiredAccess_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(DesiredAccess, 0x4000, 16, DesiredAccess_0x4000, "%s"));
-    
-    }
-
-    offset += 2; /* Skip Desired Access */
-
-    /* Build display for: Search */
-
-    Search = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Search: 0x%02x", Search);
-      Search_tree = proto_item_add_subtree(ti, ett_smb_search);
-      proto_tree_add_text(Search_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Search, 0x01, 16, "Read only file", "Not a read only file"));
-      proto_tree_add_text(Search_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Search, 0x02, 16, "Hidden file", "Not a hidden file"));
-      proto_tree_add_text(Search_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Search, 0x04, 16, "System file", "Not a system file"));
-      proto_tree_add_text(Search_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Search, 0x08, 16, " Volume", "Not a volume"));
-      proto_tree_add_text(Search_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Search, 0x10, 16, " Directory", "Not a directory"));
-      proto_tree_add_text(Search_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Search, 0x20, 16, "Archive file", "Do not archive file"));
-    
-    }
-
-    offset += 2; /* Skip Search */
-
-    /* Build display for: File */
-
-    File = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "File: 0x%02x", File);
-      File_tree = proto_item_add_subtree(ti, ett_smb_file);
-      proto_tree_add_text(File_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(File, 0x01, 16, "Read only file", "Not a read only file"));
-      proto_tree_add_text(File_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(File, 0x02, 16, "Hidden file", "Not a hidden file"));
-      proto_tree_add_text(File_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(File, 0x04, 16, "System file", "Not a system file"));
-      proto_tree_add_text(File_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(File, 0x08, 16, " Volume", "Not a volume"));
-      proto_tree_add_text(File_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(File, 0x10, 16, " Directory", "Not a directory"));
-      proto_tree_add_text(File_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(File, 0x20, 16, "Archive file", "Do not archive file"));
-    
-    }
-
-    offset += 2; /* Skip File */
-
-    /* Build display for: Creation Time */
-
-    CreationTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-
-    }
-
-    offset += 2; /* Skip Creation Time */
-
-    /* Build display for: Creation Date */
-
-    CreationDate = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_smbu_date(CreationDate, CreationTime));
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_smbu_time(CreationDate, CreationTime));
-
-    }
-
-    offset += 2; /* Skip Creation Date */
-
-    /* Build display for: Open Function */
-
-    OpenFunction = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Open Function: 0x%02x", OpenFunction);
-      OpenFunction_tree = proto_item_add_subtree(ti, ett_smb_openfunction);
-      proto_tree_add_text(OpenFunction_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(OpenFunction, 0x10, 16, OpenFunction_0x10, "%s"));
-      proto_tree_add_text(OpenFunction_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(OpenFunction, 0x03, 16, OpenFunction_0x03, "%s"));
-    
-    }
-
-    offset += 2; /* Skip Open Function */
-
-    /* Build display for: Allocated Size */
-
-    AllocatedSize = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Allocated Size: %u", AllocatedSize);
-
-    }
-
-    offset += 4; /* Skip Allocated Size */
-
-    /* Build display for: Reserved1 */
-
-    Reserved1 = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved1: %u", Reserved1);
-
-    }
-
-    offset += 4; /* Skip Reserved1 */
-
-    /* Build display for: Reserved2 */
-
-    Reserved2 = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved2: %u", Reserved2);
-
-    }
-
-    offset += 4; /* Skip Reserved2 */
-
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-    /* Build display for: File Name */
-
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
-
-    }
-
-    offset += string_len; /* Skip File Name */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: AndXCommand */
-
-      AndXCommand = GBYTE(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
-
-      }
-
-      offset += 1; /* Skip AndXCommand */
-
-      /* Build display for: AndXReserved */
-
-      AndXReserved = GBYTE(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-      }
-
-      offset += 1; /* Skip AndXReserved */
-
-      /* Build display for: AndXOffset */
-
-      AndXOffset = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-      }
-
-      offset += 2; /* Skip AndXOffset */
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-
-      /* Build display for: FileAttributes */
-
-      FileAttributes = GSHORT(pd, offset);
-
-      if (tree) {
-
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "FileAttributes: 0x%02x", FileAttributes);
-       FileAttributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
-       proto_tree_add_text(FileAttributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(FileAttributes, 0x01, 16, "Read only file", "Not a read only file"));
-       proto_tree_add_text(FileAttributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(FileAttributes, 0x02, 16, "Hidden file", "Not a hidden file"));
-       proto_tree_add_text(FileAttributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(FileAttributes, 0x04, 16, "System file", "Not a system file"));
-       proto_tree_add_text(FileAttributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(FileAttributes, 0x08, 16, " Volume", "Not a volume"));
-       proto_tree_add_text(FileAttributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(FileAttributes, 0x10, 16, " Directory", "Not a directory"));
-       proto_tree_add_text(FileAttributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(FileAttributes, 0x20, 16, "Archive file", "Do not archive file"));
-    
-      }
-
-      offset += 2; /* Skip FileAttributes */
-
-      /* Build display for: Last Write Time */
-
-      LastWriteTime = GSHORT(pd, offset);
-
-      if (tree) {
-
-      }
-
-      offset += 2; /* Skip Last Write Time */
-
-      /* Build display for: Last Write Date */
-
-      LastWriteDate = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_smbu_date(LastWriteDate, LastWriteTime));
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_smbu_time(LastWriteDate, LastWriteTime));
-
-
-      }
-
-      offset += 2; /* Skip Last Write Date */
-
-      /* Build display for: Data Size */
-
-      DataSize = GWORD(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 4, "Data Size: %u", DataSize);
-
-      }
-
-      offset += 4; /* Skip Data Size */
-
-      /* Build display for: Granted Access */
-
-      GrantedAccess = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Granted Access: %u", GrantedAccess);
-
-      }
-
-      offset += 2; /* Skip Granted Access */
-
-      /* Build display for: File Type */
-
-      FileType = GSHORT(pd, offset);
-
-      if (tree) {
-
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "File Type: 0x%02x", FileType);
-       FileType_tree = proto_item_add_subtree(ti, ett_smb_filetype);
-       proto_tree_add_text(FileType_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(FileType, 0xFFFF, 16, FileType_0xFFFF, "%s"));
-    
-      }
-
-      offset += 2; /* Skip File Type */
-
-      /* Build display for: Device State */
-
-      DeviceState = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Device State: %u", DeviceState);
-
-      }
-
-      offset += 2; /* Skip Device State */
-
-      /* Build display for: Action */
-
-      Action = GSHORT(pd, offset);
-
-      if (tree) {
-
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Action: 0x%02x", Action);
-       Action_tree = proto_item_add_subtree(ti, ett_smb_openaction);
-       proto_tree_add_text(Action_tree, NullTVB, offset, 2, "%s",
-                           decode_enumerated_bitfield(Action, 0x8000, 16, Action_0x8000, "%s"));
-       proto_tree_add_text(Action_tree, NullTVB, offset, 2, "%s",
-                           decode_enumerated_bitfield(Action, 0x0003, 16, Action_0x0003, "%s"));
-       
-      }
-      
-      offset += 2; /* Skip Action */
-
-      /* Build display for: Server FID */
-      
-      ServerFID = GWORD(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 4, "Server FID: %u", ServerFID);
-
-      }
-
-      offset += 4; /* Skip Server FID */
-
-      /* Build display for: Reserved */
-
-      Reserved = GSHORT(pd, offset);
-
-      if (tree) {
-       
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
-
-      }
-
-      offset += 2; /* Skip Reserved */
-
-    }
-
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  }
-
-}
-
-void
-dissect_write_raw_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  proto_tree    *WriteMode_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        Pad;
-  guint32       Timeout;
-  guint32       Reserved2;
-  guint32       Offset;
-  guint16       WriteMode;
-  guint16       Reserved1;
-  guint16       Remaining;
-  guint16       FID;
-  guint16       DataOffset;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    WordCount = GBYTE(pd, offset);
-
-    switch (WordCount) {
-
-    case 12:
-
-      /* Build display for: Word Count (WCT) */
-
-      WordCount = GBYTE(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-      }
-
-      offset += 1; /* Skip Word Count (WCT) */
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-      /* Build display for: Reserved 1 */
-
-      Reserved1 = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
-
-      }
-
-      offset += 2; /* Skip Reserved 1 */
-
-      /* Build display for: Offset */
-
-      Offset = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-      }
-
-      offset += 4; /* Skip Offset */
-
-      /* Build display for: Timeout */
-
-      Timeout = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-      }
-
-      offset += 4; /* Skip Timeout */
-
-      /* Build display for: WriteMode */
-
-      WriteMode = GSHORT(pd, offset);
-
-      if (tree) {
-
-        ti = proto_tree_add_text(tree, NullTVB, offset, 2, "WriteMode: 0x%02x", WriteMode);
-        WriteMode_tree = proto_item_add_subtree(ti, ett_smb_writemode);
-        proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                            decode_boolean_bitfield(WriteMode, 0x01, 16, "Write through requested", "Write through not requested"));
-        proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                            decode_boolean_bitfield(WriteMode, 0x02, 16, "Return Remaining (pipe/dev)", "Dont return Remaining (pipe/dev)"));
-      
-      }
-
-      offset += 2; /* Skip WriteMode */
-
-      /* Build display for: Reserved 2 */
-
-      Reserved2 = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 2: %u", Reserved2);
-
-      }
-
-      offset += 4; /* Skip Reserved 2 */
-
-      /* Build display for: Data Length */
-
-      DataLength = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-      }
-
-      offset += 2; /* Skip Data Length */
-
-      /* Build display for: Data Offset */
-
-      DataOffset = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
-
-      }
-
-      offset += 2; /* Skip Data Offset */
-
-      /* Build display for: Byte Count (BCC) */
-
-      ByteCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-      }
-
-      offset += 2; /* Skip Byte Count (BCC) */
-
-      /* Build display for: Pad */
-
-      Pad = GBYTE(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
-
-      }
-
-      offset += 1; /* Skip Pad */
-
-    break;
-
-    case 14:
-
-      /* Build display for: Word Count (WCT) */
-
-      WordCount = GBYTE(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-      }
-
-      offset += 1; /* Skip Word Count (WCT) */
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-      /* Build display for: Reserved 1 */
-
-      Reserved1 = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
-
-      }
-
-      offset += 2; /* Skip Reserved 1 */
-
-      /* Build display for: Timeout */
-
-      Timeout = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-      }
-
-      offset += 4; /* Skip Timeout */
-
-      /* Build display for: WriteMode */
-
-      WriteMode = GSHORT(pd, offset);
-
-      if (tree) {
-
-        ti = proto_tree_add_text(tree, NullTVB, offset, 2, "WriteMode: 0x%02x", WriteMode);
-        WriteMode_tree = proto_item_add_subtree(ti, ett_smb_writemode);
-        proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                            decode_boolean_bitfield(WriteMode, 0x01, 16, "Write through requested", "Write through not requested"));
-        proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                            decode_boolean_bitfield(WriteMode, 0x02, 16, "Return Remaining (pipe/dev)", "Dont return Remaining (pipe/dev)"));
-      
-      }
-
-      offset += 2; /* Skip WriteMode */
-
-      /* Build display for: Reserved 2 */
-
-      Reserved2 = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 2: %u", Reserved2);
-
-      }
-
-      offset += 4; /* Skip Reserved 2 */
-
-      /* Build display for: Data Length */
-
-      DataLength = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-      }
-
-      offset += 2; /* Skip Data Length */
-
-      /* Build display for: Data Offset */
-
-      DataOffset = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
-
-      }
-
-      offset += 2; /* Skip Data Offset */
-
-      /* Build display for: Byte Count (BCC) */
-
-      ByteCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-      }
-
-      offset += 2; /* Skip Byte Count (BCC) */
-
-      /* Build display for: Pad */
-
-      Pad = GBYTE(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
-
-      }
-
-      offset += 1; /* Skip Pad */
-
-    break;
-
-    }
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Remaining */
-
-      Remaining = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
-      }
-
-      offset += 2; /* Skip Remaining */
-
-    }
-
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-  }
-
-}
-
-void
-dissect_tdis_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_move_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  static const value_string Flags_0x03[] = {
-       { 0, "Target must be a file"},
-       { 1, "Target must be a directory"},
-       { 2, "Reserved"},
-       { 3, "Reserved"},
-       { 4, "Verify all writes"},
-       { 0, NULL}
-  };
-  proto_tree    *Flags_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        ErrorFileFormat;
-  guint16       TID2;
-  guint16       OpenFunction;
-  guint16       Flags;
-  guint16       Count;
-  guint16       ByteCount;
-  const char    *ErrorFileName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: TID2 */
-
-    TID2 = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "TID2: %u", TID2);
-
-    }
-
-    offset += 2; /* Skip TID2 */
-
-    /* Build display for: Open Function */
-
-    OpenFunction = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Open Function: %u", OpenFunction);
-
-    }
-
-    offset += 2; /* Skip Open Function */
-
-    /* Build display for: Flags */
-
-    Flags = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Flags: 0x%02x", Flags);
-      Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
-      proto_tree_add_text(Flags_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(Flags, 0x03, 16, Flags_0x03, "%s"));
-    
-    }
-
-    offset += 2; /* Skip Flags */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-    }
-
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-    /* Build display for: Error File Format */
-
-    ErrorFileFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Error File Format: %s (%u)",
-                         val_to_str(ErrorFileFormat, buffer_format_vals, "Unknown"),
-                         ErrorFileFormat);
-
-    }
-
-    offset += 1; /* Skip Error File Format */
-
-    /* Build display for: Error File Name */
-
-    ErrorFileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Error File Name: %s", ErrorFileName);
-
-    }
-
-    offset += string_len; /* Skip Error File Name */
-
-  }
-
-}
-
-void
-dissect_rename_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat2;
-  guint8        BufferFormat1;
-  guint16       SearchAttributes;
-  guint16       ByteCount;
-  const char    *OldFileName;
-  const char    *NewFileName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Search Attributes */
-
-    SearchAttributes = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
-
-    }
-
-    offset += 2; /* Skip Search Attributes */
-
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-    /* Build display for: Buffer Format 1 */
-
-    BufferFormat1 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 1: %s (%u)",
-                         val_to_str(BufferFormat1, buffer_format_vals, "Unknown"),
-                         BufferFormat1);
-
-    }
-
-    offset += 1; /* Skip Buffer Format 1 */
-
-    /* Build display for: Old File Name */
-
-    OldFileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Old File Name: %s", OldFileName);
-
-    }
-
-    offset += string_len; /* Skip Old File Name */
-
-    /* Build display for: Buffer Format 2 */
-
-    BufferFormat2 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 2: %s (%u)",
-                         val_to_str(BufferFormat2, buffer_format_vals, "Unknown"),
-                         BufferFormat2);
-
-    }
-
-    offset += 1; /* Skip Buffer Format 2 */
-
-    /* Build display for: New File Name */
-
-    NewFileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "New File Name: %s", NewFileName);
-
-    }
-
-    offset += string_len; /* Skip New File Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_open_print_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  static const value_string Mode_0x03[] = {
-       { 0, "Text mode (DOS expands TABs)"},
-       { 1, "Graphics mode"},
-       { 0, NULL}
-  };
-  proto_tree    *Mode_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       SetupLength;
-  guint16       Mode;
-  guint16       FID;
-  guint16       ByteCount;
-  const char    *IdentifierString;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Setup Length */
-
-    SetupLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Setup Length: %u", SetupLength);
-
-    }
-
-    offset += 2; /* Skip Setup Length */
-
-    /* Build display for: Mode */
-
-    Mode = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Mode: 0x%02x", Mode);
-      Mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
-      proto_tree_add_text(Mode_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(Mode, 0x03, 16, Mode_0x03, "%s"));
-    
-    }
-
-    offset += 2; /* Skip Mode */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Identifier String */
-
-    IdentifierString = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Identifier String: %s", IdentifierString);
-
-    }
-
-    offset += string_len; /* Skip Identifier String */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_close_print_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint16       FID;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_read_raw_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint32       Timeout;
-  guint32       OffsetHigh;
-  guint32       Offset;
-  guint16       Reserved;
-  guint16       MinCount;
-  guint16       MaxCount;
-  guint16       FID;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    WordCount = GBYTE(pd, offset);
-
-    switch (WordCount) {
-
-    case 8:
-
-      /* Build display for: Word Count (WCT) */
-
-      WordCount = GBYTE(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-      }
-
-      offset += 1; /* Skip Word Count (WCT) */
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-
-      /* Build display for: Offset */
-
-      Offset = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-      }
-
-      offset += 4; /* Skip Offset */
-
-      /* Build display for: Max Count */
-
-      MaxCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
-
-      }
-
-      offset += 2; /* Skip Max Count */
-
-      /* Build display for: Min Count */
-
-      MinCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
-
-      }
-
-      offset += 2; /* Skip Min Count */
-
-      /* Build display for: Timeout */
-
-      Timeout = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-      }
-
-      offset += 4; /* Skip Timeout */
-
-      /* Build display for: Reserved */
-
-      Reserved = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
-
-      }
-
-      offset += 2; /* Skip Reserved */
-
-      /* Build display for: Byte Count (BCC) */
-
-      ByteCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-      }
-
-      offset += 2; /* Skip Byte Count (BCC) */
-
-    break;
-
-    case 10:
-
-      /* Build display for: Word Count (WCT) */
-
-      WordCount = GBYTE(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-      }
-
-      offset += 1; /* Skip Word Count (WCT) */
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-
-      /* Build display for: Offset */
-
-      Offset = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-      }
-
-      offset += 4; /* Skip Offset */
-
-      /* Build display for: Max Count */
-
-      MaxCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
-
-      }
-
-      offset += 2; /* Skip Max Count */
-
-      /* Build display for: Min Count */
-
-      MinCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
-
-      }
-
-      offset += 2; /* Skip Min Count */
-
-      /* Build display for: Timeout */
-
-      Timeout = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-      }
-
-      offset += 4; /* Skip Timeout */
-
-      /* Build display for: Reserved */
-
-      Reserved = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
-
-      }
-
-      offset += 2; /* Skip Reserved */
-
-      /* Build display for: Offset High */
-
-      OffsetHigh = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
-
-      }
-
-      offset += 4; /* Skip Offset High */
-
-      /* Build display for: Byte Count (BCC) */
-
-      ByteCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-      }
-
-      offset += 2; /* Skip Byte Count (BCC) */
-
-    break;
-
-    }
-
-  } else {
-    /* Response(s) dissect code */
-
-  }
-
-}
-
-void
-dissect_read_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        AndXReserved;
-  guint8        AndXCommand = 0xFF;
-  guint16       ByteCount;
-  guint16       AndXOffset = 0;
-  guint16       FID;
-  guint16       DataCompactionMode;
-  guint16       DataLength;
-  guint16       DataOffset;
-  guint16       Remaining;
-  guint16       MaxCount;
-  guint16       MinCount;
-  guint16       Reserved;
-  guint32       Offset;
-  guint32       OffsetHigh;
-  int           i;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
-
-    AndXCommand = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
-
-    }
-
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
-
-    AndXReserved = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-    }
-
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
-
-    AndXOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-    }
-
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-       
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-       
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Max Count */
-
-    MaxCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
-
-    }
-
-    offset += 2; /* Skip Max Count */
-
-    /* Build display for: Min Count */
-
-    MinCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
-
-    }
-
-    offset += 2; /* Skip Min Count */
-
-    /* Build display for: Reserved */
-
-    Reserved = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
-
-    }
-
-    offset += 4; /* Skip Reserved */
-
-    /* Build display for: Remaining */
-
-    Remaining = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
-    }
-
-    offset += 2; /* Skip Remaining */
-
-    if (WordCount == 12) {
-
-       /* Build display for: Offset High */
-
-       OffsetHigh = GWORD(pd, offset);
-
-       if (tree) {
-
-           proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
-
-       }
-
-       offset += 4; /* Skip Offset High */
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
-
-    AndXCommand = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
-
-    }
-
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
-
-    AndXReserved = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-    }
-
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
-
-    AndXOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-    }
-
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: Remaining */
-
-    Remaining = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
-    }
-
-    offset += 2; /* Skip Remaining */
-
-    /* Build display for: Data Compaction Mode */
-
-    DataCompactionMode = GSHORT(pd, offset);
-
-    if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
-
-    }
-
-    offset += 2; /* Skip Data Compaction Mode */
-
-    /* Build display for: Reserved */
-
-    Reserved = GSHORT(pd, offset);
-
-    if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
-
-    }
-
-    offset += 2; /* Skip Reserved */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-    /* Build display for: Data Offset */
-
-    DataOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
-
-    }
-
-    offset += 2; /* Skip Data Offset */
-
-    /* Build display for: Reserved[5] */
-    for(i = 1; i <= 5; ++i) {
-
-       Reserved = GSHORT(pd, offset);
-
-       if (tree) {
-
-           proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved%u: %u", i, Reserved);
-
-       }
-       offset += 2;
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for data */
-
-    if (tree) {
-
-       offset = SMB_offset + DataOffset;
-       if(END_OF_FRAME >= DataLength)
-           proto_tree_add_text(tree, NullTVB, offset, DataLength, "Data (%u bytes)", DataLength);
-       else
-           proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (first %u bytes)", END_OF_FRAME);
-
-    }
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  }
-
-}
-
-void
-dissect_logoff_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        AndXReserved;
-  guint8        AndXCommand = 0xFF;
-  guint16       ByteCount;
-  guint16       AndXOffset = 0;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
-
-    AndXCommand = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
-
-    }
-
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
-
-    AndXReserved = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-    }
-
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
-
-    AndXOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-    }
-
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
-
-    AndXCommand = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
-
-    }
-
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
-
-    AndXReserved = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-    }
-
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
-
-    AndXOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-    }
-
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  }
-
-}
-
-void
-dissect_seek_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  static const value_string Mode_0x03[] = {
-       { 0, "Seek from start of file"},
-       { 1, "Seek from current position"},
-       { 2, "Seek from end of file"},
-       { 0, NULL}
-  };
-  proto_tree    *Mode_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint32       Offset;
-  guint16       Mode;
-  guint16       FID;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Mode */
-
-    Mode = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Mode: 0x%02x", Mode);
-      Mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
-      proto_tree_add_text(Mode_tree, NullTVB, offset, 2, "%s",
-                          decode_enumerated_bitfield(Mode, 0x03, 16, Mode_0x03, "%s"));
-    
-    }
-
-    offset += 2; /* Skip Mode */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_write_and_unlock_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint32       Offset;
-  guint16       Remaining;
-  guint16       FID;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Count */
-
-    Count = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-    }
-
-    offset += 2; /* Skip Count */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Remaining */
-
-    Remaining = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
-    }
-
-    offset += 2; /* Skip Remaining */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Count */
-
-    Count = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-    }
-
-    offset += 2; /* Skip Count */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_set_info2_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       LastAccessTime;
-  guint16       LastAccessDate;
-  guint16       FID;
-  guint16       CreationTime;
-  guint16       CreationDate;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Creation Date */
-
-    CreationDate = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
-
-    }
-
-    offset += 2; /* Skip Creation Date */
-
-    /* Build display for: Creation Time */
-
-    CreationTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
-
-    }
-
-    offset += 2; /* Skip Creation Time */
-
-    /* Build display for: Last Access Date */
-
-    LastAccessDate = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Date: %s", dissect_dos_date(LastAccessDate));
-
-    }
-
-    offset += 2; /* Skip Last Access Date */
-
-    /* Build display for: Last Access Time */
-
-    LastAccessTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Time: %s", dissect_dos_time(LastAccessTime));
-
-    }
-
-    offset += 2; /* Skip Last Access Time */
-
-    /* Build display for: Last Write Date */
-
-    LastWriteDate = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
-
-    }
-
-    offset += 2; /* Skip Last Write Date */
-
-    /* Build display for: Last Write Time */
-
-    LastWriteTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
-
-    }
-
-    offset += 2; /* Skip Last Write Time */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCC) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCC): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCC) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_lock_bytes_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint32       Offset;
-  guint32       Count;
-  guint16       FID;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Count */
-
-    Count = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Count: %u", Count);
-
-    }
-
-    offset += 4; /* Skip Count */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_get_print_queue_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       StartIndex;
-  guint16       RestartIndex;
-  guint16       MaxCount;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count */
-
-    /* Build display for: Max Count */
-
-    MaxCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
-
-    }
-
-    offset += 2; /* Skip Max Count */
-
-    /* Build display for: Start Index */
-
-    StartIndex = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Start Index: %u", StartIndex);
-
-    }
-
-    offset += 2; /* Skip Start Index */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-      /* Build display for: Restart Index */
-
-      RestartIndex = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Restart Index: %u", RestartIndex);
-
-      }
-
-      offset += 2; /* Skip Restart Index */
-
-      /* Build display for: Byte Count (BCC) */
-
-    }
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-  }
-
-}
-
-void
-dissect_locking_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  proto_tree    *LockType_tree;
-  proto_item    *ti;
-  guint8        LockType;
-  guint8        WordCount;
-  guint8        OplockLevel;
-  guint8        AndXReserved;
-  guint8        AndXCommand = 0xFF;
-  guint32       Timeout;
-  guint16       NumberofLocks;
-  guint16       NumberOfUnlocks;
-  guint16       FID;
-  guint16       ByteCount;
-  guint16       AndXoffset;
-  guint16       AndXOffset = 0;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
-
-    AndXCommand = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                         (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
-
-    }
-
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
-
-    AndXReserved = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-    }
-
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
-
-    AndXOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
-    }
-
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Lock Type */
-
-    LockType = GBYTE(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 1, "Lock Type: 0x%01x", LockType);
-      LockType_tree = proto_item_add_subtree(ti, ett_smb_lock_type);
-      proto_tree_add_text(LockType_tree, NullTVB, offset, 1, "%s",
-                          decode_boolean_bitfield(LockType, 0x01, 16, "Read-only lock", "Not a Read-only lock"));
-      proto_tree_add_text(LockType_tree, NullTVB, offset, 1, "%s",
-                          decode_boolean_bitfield(LockType, 0x02, 16, "Oplock break notification", "Not an Oplock break notification"));
-      proto_tree_add_text(LockType_tree, NullTVB, offset, 1, "%s",
-                          decode_boolean_bitfield(LockType, 0x04, 16, "Change lock type", "Not a lock type change"));
-      proto_tree_add_text(LockType_tree, NullTVB, offset, 1, "%s",
-                          decode_boolean_bitfield(LockType, 0x08, 16, "Cancel outstanding request", "Dont cancel outstanding request"));
-      proto_tree_add_text(LockType_tree, NullTVB, offset, 1, "%s",
-                          decode_boolean_bitfield(LockType, 0x10, 16, "Large file locking format", "Not a large file locking format"));
-    
-    }
-
-    offset += 1; /* Skip Lock Type */
-
-    /* Build display for: OplockLevel */
-
-    OplockLevel = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "OplockLevel: %u", OplockLevel);
-
-    }
-
-    offset += 1; /* Skip OplockLevel */
-
-    /* Build display for: Timeout */
-
-    Timeout = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-    }
-
-    offset += 4; /* Skip Timeout */
-
-    /* Build display for: Number Of Unlocks */
-
-    NumberOfUnlocks = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Number Of Unlocks: %u", NumberOfUnlocks);
-
-    }
-
-    offset += 2; /* Skip Number Of Unlocks */
-
-    /* Build display for: Number of Locks */
-
-    NumberofLocks = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Number of Locks: %u", NumberofLocks);
-
-    }
-
-    offset += 2; /* Skip Number of Locks */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: AndXCommand */
-
-      AndXCommand = GBYTE(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
-
-      }
-
-      offset += 1; /* Skip AndXCommand */
-
-      /* Build display for: AndXReserved */
-
-      AndXReserved = GBYTE(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
-
-      }
-
-      offset += 1; /* Skip AndXReserved */
-
-      /* Build display for: AndXoffset */
-
-      AndXoffset = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXoffset: %u", AndXoffset);
-
-      }
-
-      offset += 2; /* Skip AndXoffset */
-
-    }
-
-    /* Build display for: Byte Count */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
-
-  }
-
-}
-
-void
-dissect_unlock_bytes_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint32       Offset;
-  guint32       Count;
-  guint16       FID;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Count */
-
-    Count = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Count: %u", Count);
-
-    }
-
-    offset += 4; /* Skip Count */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_create_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  proto_tree    *Attributes_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       FID;
-  guint16       CreationTime;
-  guint16       ByteCount;
-  guint16       Attributes;
-  const char    *FileName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Attributes */
-
-    Attributes = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Attributes: 0x%02x", Attributes);
-      Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
-      proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
-      proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
-      proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
-      proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
-      proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
-      proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
-    
-    }
-
-    offset += 2; /* Skip Attributes */
-
-    /* Build display for: Creation Time */
-
-    CreationTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
-
-    }
-
-    offset += 2; /* Skip Creation Time */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: File Name */
-
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
-
-    }
-
-    offset += string_len; /* Skip File Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-      
-    }
-    
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_search_dir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat2;
-  guint8        BufferFormat1;
-  guint8        BufferFormat;
-  guint16       SearchAttributes;
-  guint16       ResumeKeyLength;
-  guint16       MaxCount;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-  const char    *FileName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Max Count */
-
-    MaxCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
-
-    }
-
-    offset += 2; /* Skip Max Count */
-
-    /* Build display for: Search Attributes */
-
-    SearchAttributes = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
-
-    }
-
-    offset += 2; /* Skip Search Attributes */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format 1 */
-
-    BufferFormat1 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 1: %s (%u)",
-                         val_to_str(BufferFormat1, buffer_format_vals, "Unknown"),
-                         BufferFormat1);
-
-    }
-
-    offset += 1; /* Skip Buffer Format 1 */
-
-    /* Build display for: File Name */
-
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
-
-    }
-
-    offset += string_len; /* Skip File Name */
-
-    /* Build display for: Buffer Format 2 */
-
-    BufferFormat2 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 2: %s (%u)",
-                         val_to_str(BufferFormat2, buffer_format_vals, "Unknown"),
-                         BufferFormat2);
-
-    }
-
-    offset += 1; /* Skip Buffer Format 2 */
-
-    /* Build display for: Resume Key Length */
-
-    ResumeKeyLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Resume Key Length: %u", ResumeKeyLength);
-
-    }
-
-    offset += 2; /* Skip Resume Key Length */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-  }
-
-}
-
-void
-dissect_create_temporary_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       Reserved;
-  guint16       FID;
-  guint16       CreationTime;
-  guint16       CreationDate;
-  guint16       ByteCount;
-  const char    *FileName;
-  const char    *DirectoryName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Reserved */
-
-    Reserved = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
-
-    }
-
-    offset += 2; /* Skip Reserved */
-
-    /* Build display for: Creation Time */
-
-    CreationTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
-
-    }
-
-    offset += 2; /* Skip Creation Time */
-
-    /* Build display for: Creation Date */
-
-    CreationDate = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
-
-    }
-
-    offset += 2; /* Skip Creation Date */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Directory Name */
-
-    DirectoryName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Directory Name: %s", DirectoryName);
-
-    }
-
-    offset += string_len; /* Skip Directory Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: FID */
-
-      FID = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-      }
-
-      offset += 2; /* Skip FID */
-
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: File Name */
-
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
-
-    }
-
-    offset += string_len; /* Skip File Name */
-
-  }
-
-}
-
-void
-dissect_close_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       FID;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Last Write Time */
-
-    LastWriteTime = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
-
-    }
-
-    offset += 2; /* Skip Last Write Time */
-
-    /* Build display for: Last Write Date */
-
-    LastWriteDate = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
-
-    }
-
-    offset += 2; /* Skip Last Write Date */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_write_print_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       FID;
-  guint16       DataLength;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_lock_and_read_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint32       Offset;
-  guint16       Reserved4;
-  guint16       Reserved3;
-  guint16       Reserved2;
-  guint16       Reserved1;
-  guint16       Remaining;
-  guint16       FID;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Count */
-
-    Count = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-    }
-
-    offset += 2; /* Skip Count */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Remaining */
-
-    Remaining = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
-    }
-
-    offset += 2; /* Skip Remaining */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-      /* Build display for: Reserved 1 */
-
-      Reserved1 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
-
-      }
-
-      offset += 2; /* Skip Reserved 1 */
-
-      /* Build display for: Reserved 2 */
-
-      Reserved2 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
-
-      }
-
-      offset += 2; /* Skip Reserved 2 */
-
-      /* Build display for: Reserved 3 */
-
-      Reserved3 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
-
-      }
-
-      offset += 2; /* Skip Reserved 3 */
-
-      /* Build display for: Reserved 4 */
-
-      Reserved4 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 4: %u", Reserved4);
-
-      }
-
-      offset += 2; /* Skip Reserved 4 */
-
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-  }
-
-}
-
-void
-dissect_process_exit_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_get_file_attr_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  proto_tree    *Attributes_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint32       FileSize;
-  guint16       Reserved5;
-  guint16       Reserved4;
-  guint16       Reserved3;
-  guint16       Reserved2;
-  guint16       Reserved1;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       ByteCount;
-  guint16       Attributes;
-  const char    *FileName;
-  int           string_len;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: File Name */
-
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
-
-    }
-
-    offset += string_len; /* Skip File Name */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Attributes */
-
-      Attributes = GSHORT(pd, offset);
-
-      if (tree) {
-
-       ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Attributes: 0x%02x", Attributes);
-       Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
-       proto_tree_add_text(Attributes_tree, NullTVB, offset, 2, "%s",
-                           decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
-       
-      }
-
-      offset += 2; /* Skip Attributes */
-
-      /* Build display for: Last Write Time */
-
-      LastWriteTime = GSHORT(pd, offset);
-
-      if (tree) {
-
-      }
-
-      offset += 2; /* Skip Last Write Time */
-
-      /* Build display for: Last Write Date */
-
-      LastWriteDate = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_smbu_date(LastWriteDate, LastWriteTime));
-
-       proto_tree_add_text(tree, NullTVB, offset - 2, 2, "Last Write Time: %s", dissect_smbu_time(LastWriteDate, LastWriteTime));
-
-      }
-
-      offset += 2; /* Skip Last Write Date */
-
-      /* Build display for: File Size */
-
-      FileSize = GWORD(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 4, "File Size: %u", FileSize);
-
-      }
-
-      offset += 4; /* Skip File Size */
-
-      /* Build display for: Reserved 1 */
-
-      Reserved1 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
-
-      }
-
-      offset += 2; /* Skip Reserved 1 */
-
-      /* Build display for: Reserved 2 */
-
-      Reserved2 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
-
-      }
-
-      offset += 2; /* Skip Reserved 2 */
-
-      /* Build display for: Reserved 3 */
-
-      Reserved3 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
-
-      }
-
-      offset += 2; /* Skip Reserved 3 */
-
-      /* Build display for: Reserved 4 */
-
-      Reserved4 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 4: %u", Reserved4);
-
-      }
-
-      offset += 2; /* Skip Reserved 4 */
-
-      /* Build display for: Reserved 5 */
-
-      Reserved5 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 5: %u", Reserved5);
-
-      }
-
-      offset += 2; /* Skip Reserved 5 */
-
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_read_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint32       Offset;
-  guint16       Reserved4;
-  guint16       Reserved3;
-  guint16       Reserved2;
-  guint16       Reserved1;
-  guint16       Remaining;
-  guint16       FID;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-  guint16       BufferFormat;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Count */
-
-    Count = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-    }
-
-    offset += 2; /* Skip Count */
-
-    /* Build display for: Offset */
-
-    Offset = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
-
-    }
-
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Remaining */
-
-    Remaining = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
-    }
-
-    offset += 2; /* Skip Remaining */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-      }
-
-      offset += 2; /* Skip Count */
-
-      /* Build display for: Reserved 1 */
-
-      Reserved1 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
-
-      }
-
-      offset += 2; /* Skip Reserved 1 */
-
-      /* Build display for: Reserved 2 */
-
-      Reserved2 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
-
-      }
-
-      offset += 2; /* Skip Reserved 2 */
-
-      /* Build display for: Reserved 3 */
-
-      Reserved3 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
-
-      }
-
-      offset += 2; /* Skip Reserved 3 */
-
-      /* Build display for: Reserved 4 */
-
-      Reserved4 = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 4: %u", Reserved4);
-
-      }
-
-      offset += 2; /* Skip Reserved 4 */
-
-    }
-    
-    /* Build display for: Byte Count (BCC) */
-    
-    ByteCount = GSHORT(pd, offset);
-      
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
-
-    }
-
-    offset += 2; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-  }
-
-}
-
-void
-dissect_write_mpx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  proto_tree    *WriteMode_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        Pad;
-  guint32       Timeout;
-  guint32       ResponseMask;
-  guint32       RequestMask;
-  guint16       WriteMode;
-  guint16       Reserved1;
-  guint16       FID;
-  guint16       DataOffset;
-  guint16       DataLength;
-  guint16       Count;
-  guint16       ByteCount;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Count */
-
-    Count = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
-
-    }
-
-    offset += 2; /* Skip Count */
-
-    /* Build display for: Reserved 1 */
-
-    Reserved1 = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
-
-    }
-
-    offset += 2; /* Skip Reserved 1 */
-
-    /* Build display for: Timeout */
-
-    Timeout = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-    }
-
-    offset += 4; /* Skip Timeout */
-
-    /* Build display for: WriteMode */
-
-    WriteMode = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "WriteMode: 0x%02x", WriteMode);
-      WriteMode_tree = proto_item_add_subtree(ti, ett_smb_writemode);
-      proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(WriteMode, 0x01, 16, "Write through requested", "Write through not requested"));
-      proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(WriteMode, 0x02, 16, "Return Remaining", "Dont return Remaining"));
-      proto_tree_add_text(WriteMode_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(WriteMode, 0x40, 16, "Connectionless mode requested", "Connectionless mode not requested"));
-    
-    }
-
-    offset += 2; /* Skip WriteMode */
-
-    /* Build display for: Request Mask */
-
-    RequestMask = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Request Mask: %u", RequestMask);
-
-    }
-
-    offset += 4; /* Skip Request Mask */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
-    }
-
-    offset += 2; /* Skip Data Length */
-
-    /* Build display for: Data Offset */
-
-    DataOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
-
-    }
-
-    offset += 2; /* Skip Data Offset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    /* Build display for: Pad */
-
-    Pad = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
-
-    }
-
-    offset += 1; /* Skip Pad */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Response Mask */
-
-      ResponseMask = GWORD(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 4, "Response Mask: %u", ResponseMask);
-
-      }
-
-      offset += 4; /* Skip Response Mask */
-
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-void
-dissect_find_close2_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  guint8        WordCount;
-  guint8        ByteCount;
-  guint16       FID;
-
-  if (si.request) {
-    /* Request(s) dissect code */
-
-    /* Build display for: Word Count (WTC) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WTC): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WTC) */
-
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-
-    }
-
-    offset += 2; /* Skip FID */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-  } else {
-    /* Response(s) dissect code */
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 1; /* Skip Byte Count (BCC) */
-
-  }
-
-}
-
-static const value_string trans2_cmd_vals[] = {
-  { 0x00, "TRANS2_OPEN" },
-  { 0x01, "TRANS2_FIND_FIRST2" },
-  { 0x02, "TRANS2_FIND_NEXT2" },
-  { 0x03, "TRANS2_QUERY_FS_INFORMATION" },
-  { 0x05, "TRANS2_QUERY_PATH_INFORMATION" },
-  { 0x06, "TRANS2_SET_PATH_INFORMATION" },
-  { 0x07, "TRANS2_QUERY_FILE_INFORMATION" },
-  { 0x08, "TRANS2_SET_FILE_INFORMATION" },
-  { 0x09, "TRANS2_FSCTL" },
-  { 0x0A, "TRANS2_IOCTL2" },
-  { 0x0B, "TRANS2_FIND_NOTIFY_FIRST" },
-  { 0x0C, "TRANS2_FIND_NOTIFY_NEXT" },
-  { 0x0D, "TRANS2_CREATE_DIRECTORY" },
-  { 0x0E, "TRANS2_SESSION_SETUP" },
-  { 0x10, "TRANS2_GET_DFS_REFERRAL" },
-  { 0x11, "TRANS2_REPORT_DFS_INCONSISTENCY" },
-  { 0,    NULL }
-};
-
-void
-dissect_transact2_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
-
-{
-  proto_tree    *Flags_tree;
-  proto_item    *ti;
-  guint8        WordCount;
-  guint8        SetupCount;
-  guint8        Reserved3;
-  guint8        Reserved1;
-  guint8        MaxSetupCount;
-  guint8        Data;
-  guint32       Timeout;
-  guint16       TotalParameterCount;
-  guint16       TotalDataCount;
-  guint16       Setup;
-  guint16       Reserved2;
-  guint16       ParameterOffset;
-  guint16       ParameterDisplacement;
-  guint16       ParameterCount;
-  guint16       MaxParameterCount;
-  guint16       MaxDataCount;
-  guint16       Flags;
-  guint16       DataOffset;
-  guint16       DataDisplacement;
-  guint16       DataCount;
-  guint16       ByteCount;
-  conversation_t *conversation;
-  struct smb_request_val *request_val;
-  struct smb_continuation_val *continuation_val;
-
-  /*
-   * Find out what conversation this packet is part of.
-   * XXX - this should really be done by the transport-layer protocol,
-   * although for connectionless transports, we may not want to do that
-   * unless we know some higher-level protocol will want it - or we
-   * may want to do it, so you can say e.g. "show only the packets in
-   * this UDP 'connection'".
-   *
-   * Note that we don't have to worry about the direction this packet
-   * was going - the conversation code handles that for us, treating
-   * packets from A:X to B:Y as being part of the same conversation as
-   * packets from B:Y to A:X.
-   */
-  conversation = find_conversation(&pi.src, &pi.dst, pi.ptype,
-                               pi.srcport, pi.destport, 0);
-  if (conversation == NULL) {
-    /* It's not part of any conversation - create a new one. */
-    conversation = conversation_new(&pi.src, &pi.dst, pi.ptype,
-                               pi.srcport, pi.destport, 0);
-  }
-
-  si.conversation = conversation;  /* Save this for later */
-
-  request_val = do_transaction_hashing(conversation, si, fd);
-
-  si.request_val = request_val;  /* Save this for later */
-
-  if (si.request) {
-    /* Request(s) dissect code */
-  
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Total Parameter Count */
-
-    TotalParameterCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Total Parameter Count: %u", TotalParameterCount);
-
-    }
-
-    offset += 2; /* Skip Total Parameter Count */
-
-    /* Build display for: Total Data Count */
-
-    TotalDataCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Total Data Count: %u", TotalDataCount);
-
-    }
-
-    offset += 2; /* Skip Total Data Count */
-
-    /* Build display for: Max Parameter Count */
-
-    MaxParameterCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Parameter Count: %u", MaxParameterCount);
-
-    }
-
-    offset += 2; /* Skip Max Parameter Count */
-
-    /* Build display for: Max Data Count */
-
-    MaxDataCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Data Count: %u", MaxDataCount);
-
-    }
-
-    offset += 2; /* Skip Max Data Count */
-
-    /* Build display for: Max Setup Count */
-
-    MaxSetupCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Max Setup Count: %u", MaxSetupCount);
-
-    }
-
-    offset += 1; /* Skip Max Setup Count */
-
-    /* Build display for: Reserved1 */
-
-    Reserved1 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Reserved1: %u", Reserved1);
-
-    }
-
-    offset += 1; /* Skip Reserved1 */
-
-    /* Build display for: Flags */
-
-    Flags = GSHORT(pd, offset);
-
-    if (tree) {
-
-      ti = proto_tree_add_text(tree, NullTVB, offset, 2, "Flags: 0x%02x", Flags);
-      Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
-      proto_tree_add_text(Flags_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Flags, 0x01, 16, "Also disconnect TID", "Dont disconnect TID"));
-      proto_tree_add_text(Flags_tree, NullTVB, offset, 2, "%s",
-                          decode_boolean_bitfield(Flags, 0x02, 16, "One way transaction", "Two way transaction"));
-    
-    }
-
-    offset += 2; /* Skip Flags */
-
-    /* Build display for: Timeout */
-
-    Timeout = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
-
-    }
-
-    offset += 4; /* Skip Timeout */
-
-    /* Build display for: Reserved2 */
-
-    Reserved2 = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved2: %u", Reserved2);
-
-    }
-
-    offset += 2; /* Skip Reserved2 */
-
-    /* Build display for: Parameter Count */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    ParameterCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Parameter Count: %u", ParameterCount);
-
-    }
-
-    offset += 2; /* Skip Parameter Count */
-
-    /* Build display for: Parameter Offset */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    ParameterOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Parameter Offset: %u", ParameterOffset);
-
-    }
-
-    offset += 2; /* Skip Parameter Offset */
-
-    /* Build display for: Data Count */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    DataCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Count: %u", DataCount);
-
-    }
-
-    offset += 2; /* Skip Data Count */
-
-    /* Build display for: Data Offset */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    DataOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
-
-    }
-
-    offset += 2; /* Skip Data Offset */
-
-    /* Build display for: Setup Count */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    SetupCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Setup Count: %u", SetupCount);
-
-    }
-
-    offset += 1; /* Skip Setup Count */
-
-    /* Build display for: Reserved3 */
-
-    Reserved3 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Reserved3: %u", Reserved3);
-
-    }
-
-    offset += 1; /* Skip Reserved3 */
-
-    /* Build display for: Setup */
-
-    if (SetupCount != 0) {
-
-      int i;
-
-      if (!BYTES_ARE_IN_FRAME(offset, 2))
-       return;
-
-      /*
-       * First Setup word is transaction code.
-       */
-      Setup = GSHORT(pd, offset);
-
-      if (!fd->flags.visited) {
-       /*
-        * This is the first time this frame has been seen; remember
-        * the transaction code.
-        */
-       g_assert(request_val -> last_transact2_command == -1);
-        request_val -> last_transact2_command = Setup;  /* Save for later */
-      }
-
-      if (check_col(fd, COL_INFO)) {
-
-       col_add_fstr(fd, COL_INFO, "%s Request",
-                    val_to_str(Setup, trans2_cmd_vals, "Unknown (0x%02X)"));
-
-      }
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Setup1: %s",
-                         val_to_str(Setup, trans2_cmd_vals, "Unknown (0x%02X)"));
-
-      }
-
-      offset += 2; /* Skip Setup word */
-
-      for (i = 2; i <= SetupCount; i++) {
-
-       if (!BYTES_ARE_IN_FRAME(offset, 2))
-         return;
-
-       Setup = GSHORT(pd, offset);
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, 2, "Setup%i: %u", i, Setup);
-
-       }
-
-       offset += 2; /* Skip Setup word */
-
-      }
-
-    }
-
-    /* Build display for: Byte Count (BCC) */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count (BCC) */
-
-    if (offset < (SMB_offset + ParameterOffset)) {
-
-      int pad1Count = SMB_offset + ParameterOffset - offset;
-
-      /* Build display for: Pad1 */
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, pad1Count, "Pad1: %s",
-                           bytes_to_str(pd + offset, pad1Count));
-      }
-
-      offset += pad1Count; /* Skip Pad1 */
-
-    }
-
-    if (ParameterCount > 0) {
-
-      /* Build display for: Parameters */
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, SMB_offset + ParameterOffset,
-                           ParameterCount, "Parameters: %s",
-                           bytes_to_str(pd + SMB_offset + ParameterOffset,
-                                        ParameterCount));
-
-      }
-
-      offset += ParameterCount; /* Skip Parameters */
-
-    }
-
-    if (DataCount > 0 && offset < (SMB_offset + DataOffset)) {
-
-      int pad2Count = SMB_offset + DataOffset - offset;
-       
-      /* Build display for: Pad2 */
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, pad2Count, "Pad2: %s",
-                           bytes_to_str(pd + offset, pad2Count));
-
-      }
-
-      offset += pad2Count; /* Skip Pad2 */
-
-    }
-
-    if (DataCount > 0) {
-
-      /* Build display for: Data */
-
-      Data = GBYTE(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, SMB_offset + DataOffset,
-                           DataCount, "Data: %s",
-                           bytes_to_str(pd + offset, DataCount));
-
-      }
-
-      offset += DataCount; /* Skip Data */
-
-    }
-  } else {
-    /* Response(s) dissect code */
-
-    /* Pick up the last transact2 command and put it in the right places */
-
-    if (check_col(fd, COL_INFO)) {
-
-      if (request_val == NULL)
-       col_set_str(fd, COL_INFO, "Response to unknown SMBtrans2");
-      else if (request_val -> last_transact2_command == -1)
-       col_set_str(fd, COL_INFO, "Response to SMBtrans2 of unknown type");
-      else
-       col_add_fstr(fd, COL_INFO, "%s Response",
-                    val_to_str(request_val -> last_transact2_command,
-                               trans2_cmd_vals, "Unknown (0x%02X)"));
-
-    }
-
-    /* Build display for: Word Count (WCT) */
-
-    WordCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount == 0) {
-
-      /* Interim response. */
-
-      if (check_col(fd, COL_INFO)) {
-
-       if (request_val == NULL)
-         col_set_str(fd, COL_INFO, "Interim response to unknown SMBtrans2");
-       else if (request_val -> last_transact2_command == -1)
-         col_set_str(fd, COL_INFO, "Interim response to SMBtrans2 of unknown type");
-       else
-         col_add_fstr(fd, COL_INFO, "%s interim response",
-                      val_to_str(request_val -> last_transact2_command,
-                                 trans2_cmd_vals, "Unknown (0x%02X)"));
-
-      }
-
-      /* Build display for: Byte Count (BCC) */
-
-      ByteCount = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
-
-      }
-
-      offset += 2; /* Skip Byte Count (BCC) */
-
-      return;
-
-    }
-
-    /* Build display for: Total Parameter Count */
-
-    TotalParameterCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Total Parameter Count: %u", TotalParameterCount);
-
-    }
-
-    offset += 2; /* Skip Total Parameter Count */
-
-    /* Build display for: Total Data Count */
-
-    TotalDataCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Total Data Count: %u", TotalDataCount);
-
-    }
-
-    offset += 2; /* Skip Total Data Count */
-
-    /* Build display for: Reserved2 */
-
-    Reserved2 = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved2: %u", Reserved2);
-
-    }
-
-    offset += 2; /* Skip Reserved2 */
-
-    /* Build display for: Parameter Count */
-
-    ParameterCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Parameter Count: %u", ParameterCount);
-
-    }
-
-    offset += 2; /* Skip Parameter Count */
-
-    /* Build display for: Parameter Offset */
-
-    ParameterOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Parameter Offset: %u", ParameterOffset);
-
-    }
-
-    offset += 2; /* Skip Parameter Offset */
-
-    /* Build display for: Parameter Displacement */
-
-    ParameterDisplacement = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Parameter Displacement: %u", ParameterDisplacement);
-
-    }
-
-    offset += 2; /* Skip Parameter Displacement */
-
-    /* Build display for: Data Count */
-
-    DataCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Count: %u", DataCount);
-
-    }
-
-    offset += 2; /* Skip Data Count */
-
-    /* Build display for: Data Offset */
-
-    DataOffset = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
-
-    }
-
-    offset += 2; /* Skip Data Offset */
-
-    /* Build display for: Data Displacement */
-
-    if (!BYTES_ARE_IN_FRAME(offset, 2))
-      return;
-
-    DataDisplacement = GSHORT(pd, offset);
-    si.ddisp = DataDisplacement;
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Displacement: %u", DataDisplacement);
-
-    }
-
-    offset += 2; /* Skip Data Displacement */
-
-    /* Build display for: Setup Count */
-
-    SetupCount = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Setup Count: %u", SetupCount);
-
-    }
-
-    offset += 1; /* Skip Setup Count */
-
-    /* Build display for: Reserved3 */
-
-    Reserved3 = GBYTE(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Reserved3: %u", Reserved3);
-
-    }
-
-    offset += 1; /* Skip Reserved3 */
+       /* data count */
+       dc = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_count16, tvb, offset, 2, dc);
+       offset += 2;
 
-    if (SetupCount != 0) {
+       /* data offset */
+       od = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_offset16, tvb, offset, 2, od);
+       offset += 2;
 
-      int i;
+       /* data disp */
+       dd = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_data_disp16, tvb, offset, 2, dd);
+       offset += 2;
 
-      for (i = 1; i <= SetupCount; i++) {
-       
-       Setup = GSHORT(pd, offset);
+       /* setup count */
+       sc = tvb_get_guint8(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+       offset += 1;
 
-       if (tree) {
+       /* reserved byte */
+       proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+       offset += 1;
 
-         proto_tree_add_text(tree, NullTVB, offset, 2, "Setup%i: %u", i, Setup);
+       /* save setup offset */ 
+       so=offset;
 
+       /* if there were any setup bytes, decode them */
+       if(sc){
+               /* XXXX dissect setup words */
+               offset += sc*2;
        }
 
-       offset += 2; /* Skip Setup */
-
-      }
-    }
+       BYTE_COUNT;
+       
+       /* parameters */
+       if(po>offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = po-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(pc){
+               CHECK_BYTE_COUNT(pc);
+               switch(si->cmd){
+
+               case 0x32:
+                       /* TRANSACTION2 parameters*/
+                       offset = dissect_transaction2_response_parameters(tvb, pinfo, tree, offset, pc, od);
+                       bc -= pc;
+                       break;
+
+               case 0x25:
+                       /*XXXX process TRANSACTION parameters*/
+                       offset += pc;
+                       bc -= pc;
+                       break;
+               }
+       }
 
-    /* Build display for: Byte Count (BCC) */
+       /* data */
+       if(od>offset){
+               /* We have some initial padding bytes.
+               */
+               padcnt = od-offset;
+               if (padcnt > bc)
+                       padcnt = bc;
+               proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+               COUNT_BYTES(padcnt);
+       }
+       if(dc){
+               CHECK_BYTE_COUNT(dc);
+               switch(si->cmd){
+
+               case 0x32:
+                       /* TRANSACTION2 data*/
+                       offset = dissect_transaction2_response_data(tvb, pinfo, tree, offset, dc);
+                       bc -= dc;
+                       break;
+
+               case 0x25:
+                       /*XXXX process TRANSACTIOIN data*/
+                       offset += dc;
+                       bc -= pc;
+                       break;
+               }
+       }
 
-    ByteCount = GSHORT(pd, offset);
+#ifdef NOT_TVBUFFIFIED_YET
+       /* TRANSACTION response parameters */
+       if(si->cmd==0x25){
+               /* only call subdissector for the first packet */
+               if(dd==0){
+                       tvbuff_t *p_tvb, *d_tvb, *s_tvb;
+
+                       if(pc>0){
+                               if(pc>tvb_length_remaining(tvb, po)){
+                                       p_tvb = tvb_new_subset(tvb, po, tvb_length_remaining(tvb, po), pc);
+                               } else {
+                                       p_tvb = tvb_new_subset(tvb, po, pc, pc);
+                               }
+                       } else {
+                               p_tvb = NULL;
+                       }
+                       if(dc>0){
+                               if(dc>tvb_length_remaining(tvb, od)){
+                                       d_tvb = tvb_new_subset(tvb, od, tvb_length_remaining(tvb, od), dc);
+                               } else {
+                                       d_tvb = tvb_new_subset(tvb, od, dc, dc);
+                               }
+                       } else {
+                               d_tvb = NULL;
+                       }
+                       if(sc){
+                               s_tvb = tvb_new_subset(tvb, so, tvb_length_remaining(tvb, so), tvb_length_remaining(tvb, so));
+                       } else {
+                               s_tvb = NULL;
+                       }
+
+                       
+                       if(si->subcmd==TRANSACTION_PIPE_LANMAN){
+                                       dissect_pipe_smb(p_tvb, d_tvb, pinfo, top_tree);
+                       }
+                       if(si->subcmd==TRANSACTION_MAILSLOT){
+                                       dissect_mailslot_smb(s_tvb, d_tvb, NULL, pinfo, top_tree);
+                       }
+               } else {
+                       if(check_col(pinfo->fd, COL_INFO)){
+                               col_append_str(pinfo->fd, COL_INFO,
+                                       "[transact continuation] ");
+                       }
+               }
+       }
+#endif
 
-    if (tree) {
+       END_OF_SMB
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       return offset;
+}
 
-    }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   END Transaction/Transaction2 Primary and secondary requests
+   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+
+typedef struct _smb_function {
+       int (*request)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+       int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+} smb_function;
+
+smb_function smb_dissector[256] = {
+  /* 0x00 Create Dir*/  {dissect_old_dir_request, dissect_empty},
+  /* 0x01 Delete Dir*/  {dissect_old_dir_request, dissect_empty},
+  /* 0x02 Open File*/  {dissect_open_file_request, dissect_open_file_response},
+  /* 0x03 Create File*/  {dissect_create_file_request, dissect_fid},
+  /* 0x04 Close File*/  {dissect_close_file_request, dissect_empty},
+  /* 0x05 Flush File*/  {dissect_fid, dissect_empty},
+  /* 0x06 Delete File*/  {dissect_delete_file_request, dissect_empty},
+  /* 0x07 Rename File*/  {dissect_rename_file_request, dissect_empty},
+  /* 0x08 Query Info*/  {dissect_query_information_request, dissect_query_information_response},
+  /* 0x09 Set Info*/  {dissect_set_information_request, dissect_empty},
+  /* 0x0a Read File*/  {dissect_read_file_request, dissect_read_file_response},
+  /* 0x0b Write File*/  {dissect_write_file_request, dissect_write_file_response},
+  /* 0x0c Lock Byte Range*/  {dissect_lock_request, dissect_empty},
+  /* 0x0d Unlock Byte Range*/  {dissect_lock_request, dissect_empty},
+  /* 0x0e Create Temp*/  {dissect_create_temporary_request, dissect_create_temporary_response},
+  /* 0x0f Create New*/  {dissect_create_file_request, dissect_fid},
+
+  /* 0x10 Check Dir*/  {dissect_old_dir_request, dissect_empty},
+  /* 0x11 Process Exit*/  {dissect_empty, dissect_empty},
+  /* 0x12 Seek File*/  {dissect_seek_file_request, dissect_seek_file_response},
+  /* 0x13 Lock And Read*/  {dissect_read_file_request, dissect_lock_and_read_response},
+  /* 0x14 Write And Unlock*/  {dissect_write_file_request, dissect_write_file_response},
+  /* 0x15 */  {NULL, NULL},
+  /* 0x16 */  {NULL, NULL},
+  /* 0x17 */  {NULL, NULL},
+  /* 0x18 */  {NULL, NULL},
+  /* 0x19 */  {NULL, NULL},
+  /* 0x1a Read Raw*/  {dissect_read_raw_request, NULL},
+  /* 0x1b Read MPX*/  {dissect_read_mpx_request, dissect_read_mpx_response},
+  /* 0x1c */  {NULL, NULL},
+  /* 0x1d Write Raw*/  {dissect_write_raw_request, dissect_write_raw_response},
+  /* 0x1e Write MPX*/  {dissect_write_mpx_request, dissect_write_mpx_response},
+  /* 0x1f */  {NULL, NULL},
+
+  /* 0x20 Write Complete*/  {NULL, dissect_write_and_close_response},
+  /* 0x21 */  {NULL, NULL},
+  /* 0x22 Set Info2*/  {dissect_set_information2_request, dissect_empty},
+  /* 0x23 Query Info2*/  {dissect_fid, dissect_query_information2_response},
+  /* 0x24 Locking And X*/  {dissect_locking_andx_request, dissect_locking_andx_response},
+  /* 0x25 */  {NULL, NULL},
+  /* 0x26 */  {NULL, NULL},
+  /* 0x27 */  {NULL, NULL},
+  /* 0x28 */  {NULL, NULL},
+  /* 0x29 */  {NULL, NULL},
+  /* 0x2a Move File*/  {dissect_move_request, dissect_move_response},
+  /* 0x2b Echo*/  {dissect_echo_request, dissect_echo_response},
+  /* 0x2c Write And Close*/  {dissect_write_and_close_request, dissect_write_and_close_response},
+  /* 0x2d Open And X*/  {dissect_open_andx_request, dissect_open_andx_response},
+  /* 0x2e Read And X*/  {dissect_read_andx_request, dissect_read_andx_response},
+  /* 0x2f */  {NULL, NULL},
+
+  /* 0x30 */  {NULL, NULL},
+  /* 0x31 */  {NULL, NULL},
+  /* 0x32 Transaction2*/               {dissect_transaction_request, dissect_transaction_response},
+  /* 0x33 */  {NULL, NULL},
+  /* 0x34 Find Close2*/  {dissect_sid, dissect_empty},
+  /* 0x35 */  {NULL, NULL},
+  /* 0x36 */  {NULL, NULL},
+  /* 0x37 */  {NULL, NULL},
+  /* 0x38 */  {NULL, NULL},
+  /* 0x39 */  {NULL, NULL},
+  /* 0x3a */  {NULL, NULL},
+  /* 0x3b */  {NULL, NULL},
+  /* 0x3c */  {NULL, NULL},
+  /* 0x3d */  {NULL, NULL},
+  /* 0x3e */  {NULL, NULL},
+  /* 0x3f */  {NULL, NULL},
+
+  /* 0x40 */  {NULL, NULL},
+  /* 0x41 */  {NULL, NULL},
+  /* 0x42 */  {NULL, NULL},
+  /* 0x43 */  {NULL, NULL},
+  /* 0x44 */  {NULL, NULL},
+  /* 0x45 */  {NULL, NULL},
+  /* 0x46 */  {NULL, NULL},
+  /* 0x47 */  {NULL, NULL},
+  /* 0x48 */  {NULL, NULL},
+  /* 0x49 */  {NULL, NULL},
+  /* 0x4a */  {NULL, NULL},
+  /* 0x4b */  {NULL, NULL},
+  /* 0x4c */  {NULL, NULL},
+  /* 0x4d */  {NULL, NULL},
+  /* 0x4e */  {NULL, NULL},
+  /* 0x4f */  {NULL, NULL},
+
+  /* 0x50 */  {NULL, NULL},
+  /* 0x51 */  {NULL, NULL},
+  /* 0x52 */  {NULL, NULL},
+  /* 0x53 */  {NULL, NULL},
+  /* 0x54 */  {NULL, NULL},
+  /* 0x55 */  {NULL, NULL},
+  /* 0x56 */  {NULL, NULL},
+  /* 0x57 */  {NULL, NULL},
+  /* 0x58 */  {NULL, NULL},
+  /* 0x59 */  {NULL, NULL},
+  /* 0x5a */  {NULL, NULL},
+  /* 0x5b */  {NULL, NULL},
+  /* 0x5c */  {NULL, NULL},
+  /* 0x5d */  {NULL, NULL},
+  /* 0x5e */  {NULL, NULL},
+  /* 0x5f */  {NULL, NULL},
+
+  /* 0x60 */  {NULL, NULL},
+  /* 0x61 */  {NULL, NULL},
+  /* 0x62 */  {NULL, NULL},
+  /* 0x63 */  {NULL, NULL},
+  /* 0x64 */  {NULL, NULL},
+  /* 0x65 */  {NULL, NULL},
+  /* 0x66 */  {NULL, NULL},
+  /* 0x67 */  {NULL, NULL},
+  /* 0x68 */  {NULL, NULL},
+  /* 0x69 */  {NULL, NULL},
+  /* 0x6a */  {NULL, NULL},
+  /* 0x6b */  {NULL, NULL},
+  /* 0x6c */  {NULL, NULL},
+  /* 0x6d */  {NULL, NULL},
+  /* 0x6e */  {NULL, NULL},
+  /* 0x6f */  {NULL, NULL},
+
+  /* 0x70 Tree Connect*/  {dissect_tree_connect_request, dissect_tree_connect_response},
+  /* 0x71 Tree Disconnect*/  {dissect_empty, dissect_empty},
+  /* 0x72 Negotiate Protocol*/ {dissect_negprot_request, dissect_negprot_response},
+  /* 0x73 Session Setup And X*/  {dissect_session_setup_andx_request, dissect_session_setup_andx_response},
+  /* 0x74 Logoff And X*/  {dissect_empty_andx, dissect_empty_andx},
+  /* 0x75 Tree Connect And X*/  {dissect_tree_connect_andx_request, dissect_tree_connect_andx_response},
+  /* 0x76 */  {NULL, NULL},
+  /* 0x77 */  {NULL, NULL},
+  /* 0x78 */  {NULL, NULL},
+  /* 0x79 */  {NULL, NULL},
+  /* 0x7a */  {NULL, NULL},
+  /* 0x7b */  {NULL, NULL},
+  /* 0x7c */  {NULL, NULL},
+  /* 0x7d */  {NULL, NULL},
+  /* 0x7e */  {NULL, NULL},
+  /* 0x7f */  {NULL, NULL},
+
+  /* 0x80 Query Info Disk*/  {dissect_empty, dissect_query_information_disk_response},
+  /* 0x81 Search Dir*/  {dissect_search_dir_request, dissect_search_dir_response},
+  /* 0x82 */  {NULL, NULL},
+  /* 0x83 */  {NULL, NULL},
+  /* 0x84 */  {NULL, NULL},
+  /* 0x85 */  {NULL, NULL},
+  /* 0x86 */  {NULL, NULL},
+  /* 0x87 */  {NULL, NULL},
+  /* 0x88 */  {NULL, NULL},
+  /* 0x89 */  {NULL, NULL},
+  /* 0x8a */  {NULL, NULL},
+  /* 0x8b */  {NULL, NULL},
+  /* 0x8c */  {NULL, NULL},
+  /* 0x8d */  {NULL, NULL},
+  /* 0x8e */  {NULL, NULL},
+  /* 0x8f */  {NULL, NULL},
+
+  /* 0x90 */  {NULL, NULL},
+  /* 0x91 */  {NULL, NULL},
+  /* 0x92 */  {NULL, NULL},
+  /* 0x93 */  {NULL, NULL},
+  /* 0x94 */  {NULL, NULL},
+  /* 0x95 */  {NULL, NULL},
+  /* 0x96 */  {NULL, NULL},
+  /* 0x97 */  {NULL, NULL},
+  /* 0x98 */  {NULL, NULL},
+  /* 0x99 */  {NULL, NULL},
+  /* 0x9a */  {NULL, NULL},
+  /* 0x9b */  {NULL, NULL},
+  /* 0x9c */  {NULL, NULL},
+  /* 0x9d */  {NULL, NULL},
+  /* 0x9e */  {NULL, NULL},
+  /* 0x9f */  {NULL, NULL},
+  /* 0xa0 NT Transaction*/     {dissect_nt_transaction_request, dissect_nt_transaction_response},
+  /* 0xa1 NT Trans secondary*/ {dissect_nt_transaction_request, dissect_nt_transaction_response},
+  /* 0xa2 NT CreateAndX*/              {dissect_nt_create_andx_request, dissect_nt_create_andx_response},
+  /* 0xa3 */  {NULL, NULL},
+  /* 0xa4 NT Cancel*/          {dissect_nt_cancel_request, NULL}, /*no response to this one*/
+  /* 0xa5 */  {NULL, NULL},
+  /* 0xa6 */  {NULL, NULL},
+  /* 0xa7 */  {NULL, NULL},
+  /* 0xa8 */  {NULL, NULL},
+  /* 0xa9 */  {NULL, NULL},
+  /* 0xaa */  {NULL, NULL},
+  /* 0xab */  {NULL, NULL},
+  /* 0xac */  {NULL, NULL},
+  /* 0xad */  {NULL, NULL},
+  /* 0xae */  {NULL, NULL},
+  /* 0xaf */  {NULL, NULL},
+
+  /* 0xb0 */  {NULL, NULL},
+  /* 0xb1 */  {NULL, NULL},
+  /* 0xb2 */  {NULL, NULL},
+  /* 0xb3 */  {NULL, NULL},
+  /* 0xb4 */  {NULL, NULL},
+  /* 0xb5 */  {NULL, NULL},
+  /* 0xb6 */  {NULL, NULL},
+  /* 0xb7 */  {NULL, NULL},
+  /* 0xb8 */  {NULL, NULL},
+  /* 0xb9 */  {NULL, NULL},
+  /* 0xba */  {NULL, NULL},
+  /* 0xbb */  {NULL, NULL},
+  /* 0xbc */  {NULL, NULL},
+  /* 0xbd */  {NULL, NULL},
+  /* 0xbe */  {NULL, NULL},
+  /* 0xbf */  {NULL, NULL},
+  /* 0xc0 Open Print File*/    {dissect_open_print_file_request, dissect_fid},
+  /* 0xc1 Write Print File*/   {dissect_write_print_file_request, dissect_empty},
+  /* 0xc2 Close Print File*/  {dissect_fid, dissect_empty},
+  /* 0xc3 Get Print Queue*/    {dissect_get_print_queue_request, dissect_get_print_queue_response},
+  /* 0xc4 */  {NULL, NULL},
+  /* 0xc5 */  {NULL, NULL},
+  /* 0xc6 */  {NULL, NULL},
+  /* 0xc7 */  {NULL, NULL},
+  /* 0xc8 */  {NULL, NULL},
+  /* 0xc9 */  {NULL, NULL},
+  /* 0xca */  {NULL, NULL},
+  /* 0xcb */  {NULL, NULL},
+  /* 0xcc */  {NULL, NULL},
+  /* 0xcd */  {NULL, NULL},
+  /* 0xce */  {NULL, NULL},
+  /* 0xcf */  {NULL, NULL},
+
+  /* 0xd0 */  {NULL, NULL},
+  /* 0xd1 */  {NULL, NULL},
+  /* 0xd2 */  {NULL, NULL},
+  /* 0xd3 */  {NULL, NULL},
+  /* 0xd4 */  {NULL, NULL},
+  /* 0xd5 */  {NULL, NULL},
+  /* 0xd6 */  {NULL, NULL},
+  /* 0xd7 */  {NULL, NULL},
+  /* 0xd8 */  {NULL, NULL},
+  /* 0xd9 */  {NULL, NULL},
+  /* 0xda */  {NULL, NULL},
+  /* 0xdb */  {NULL, NULL},
+  /* 0xdc */  {NULL, NULL},
+  /* 0xdd */  {NULL, NULL},
+  /* 0xde */  {NULL, NULL},
+  /* 0xdf */  {NULL, NULL},
+
+  /* 0xe0 */  {NULL, NULL},
+  /* 0xe1 */  {NULL, NULL},
+  /* 0xe2 */  {NULL, NULL},
+  /* 0xe3 */  {NULL, NULL},
+  /* 0xe4 */  {NULL, NULL},
+  /* 0xe5 */  {NULL, NULL},
+  /* 0xe6 */  {NULL, NULL},
+  /* 0xe7 */  {NULL, NULL},
+  /* 0xe8 */  {NULL, NULL},
+  /* 0xe9 */  {NULL, NULL},
+  /* 0xea */  {NULL, NULL},
+  /* 0xeb */  {NULL, NULL},
+  /* 0xec */  {NULL, NULL},
+  /* 0xed */  {NULL, NULL},
+  /* 0xee */  {NULL, NULL},
+  /* 0xef */  {NULL, NULL},
+
+  /* 0xf0 */  {NULL, NULL},
+  /* 0xf1 */  {NULL, NULL},
+  /* 0xf2 */  {NULL, NULL},
+  /* 0xf3 */  {NULL, NULL},
+  /* 0xf4 */  {NULL, NULL},
+  /* 0xf5 */  {NULL, NULL},
+  /* 0xf6 */  {NULL, NULL},
+  /* 0xf7 */  {NULL, NULL},
+  /* 0xf8 */  {NULL, NULL},
+  /* 0xf9 */  {NULL, NULL},
+  /* 0xfa */  {NULL, NULL},
+  /* 0xfb */  {NULL, NULL},
+  /* 0xfc */  {NULL, NULL},
+  /* 0xfd */  {NULL, NULL},
+  /* 0xfe */  {NULL, NULL},
+  /* 0xff */  {NULL, NULL},
+};
 
-    if (offset < (SMB_offset + ParameterOffset)) {
+static int
+dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree, int offset, proto_tree *smb_tree, guint8 cmd)
+{
+       int old_offset = offset;
+       smb_info_t *si;
+       si = pinfo->private_data;
+       if(cmd!=0xff){
+               proto_item *cmd_item;
+               proto_tree *cmd_tree;
+               int (*dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_add_fstr(pinfo->fd, COL_INFO, "%s %s",
+                               decode_smb_name(cmd),
+                               (si->request)? "Request" : "Response");
+               }
+
+               cmd_item = proto_tree_add_text(smb_tree, tvb, offset,
+                       0, "%s %s (0x%02x)",
+                       decode_smb_name(cmd), 
+                       (si->request)?"Request":"Response",
+                       cmd);
+
+               cmd_tree = proto_item_add_subtree(cmd_item, ett_smb_command);
+
+               dissector = (si->request)?
+                       smb_dissector[cmd].request:smb_dissector[cmd].response;
+
+               if(dissector){
+                       offset = (*dissector)(tvb, pinfo, cmd_tree, offset, smb_tree);
+               }
+               proto_item_set_len(cmd_item, offset-old_offset);
+       }
+       return offset;
+}
 
-      int pad1Count = SMB_offset + ParameterOffset - offset;
 
-      /* Build display for: Pad1 */
+/* NOTE: this value_string array will also be used to access data directly by
+ * index instead of val_to_str() since 
+ * 1, the array will always span every value from 0x00 to 0xff and
+ * 2, smb_cmd_vals[i].strptr  is much cheaper than  val_to_str(i, smb_cmd_vals,)
+ * This means that this value_string array MUST always
+ * 1, contain all entries 0x00 to 0xff
+ * 2, all entries must be in order.
+ */
+static const value_string smb_cmd_vals[] = {
+  { 0x00, "Create Directory" },
+  { 0x01, "Delete Directory" },
+  { 0x02, "Open" },
+  { 0x03, "Create" },
+  { 0x04, "Close" },
+  { 0x05, "Flush" },
+  { 0x06, "Delete" },
+  { 0x07, "Rename" },
+  { 0x08, "Query Information" },
+  { 0x09, "Set Information" },
+  { 0x0A, "Read" },
+  { 0x0B, "Write" },
+  { 0x0C, "Lock Byte Range" },
+  { 0x0D, "Unlock Byte Range" },
+  { 0x0E, "Create Temp" },
+  { 0x0F, "Create New" },
+  { 0x10, "Check Directory" },
+  { 0x11, "Process Exit" },
+  { 0x12, "Seek" },
+  { 0x13, "Lock And Read" },
+  { 0x14, "Write And Unlock" },
+  { 0x15, "unknown-0x15" },
+  { 0x16, "unknown-0x16" },
+  { 0x17, "unknown-0x17" },
+  { 0x18, "unknown-0x18" },
+  { 0x19, "unknown-0x19" },
+  { 0x1A, "Read Raw" },
+  { 0x1B, "Read MPX" },
+  { 0x1C, "Read MPX Secondary" },
+  { 0x1D, "Write Raw" },
+  { 0x1E, "Write MPX" },
+  { 0x1F, "SMBwriteBs" },
+  { 0x20, "Write Complete" },
+  { 0x21, "unknown-0x21" },
+  { 0x22, "Set Information2" },
+  { 0x23, "Query Information2" },
+  { 0x24, "Locking AndX" },
+  { 0x25, "Transaction" },
+  { 0x26, "Transaction Secondary" },
+  { 0x27, "IOCTL" },
+  { 0x28, "IOCTL Secondary" },
+  { 0x29, "Copy" },
+  { 0x2A, "Move" },
+  { 0x2B, "Echo" },
+  { 0x2C, "Write And Close" },
+  { 0x2D, "Open AndX" },
+  { 0x2E, "Read AndX" },
+  { 0x2F, "Write AndX" },
+  { 0x30, "unknown-0x30" },
+  { 0x31, "Close And Tree Discover" },
+  { 0x32, "Transaction2" },
+  { 0x33, "Transaction2 Secondary" },
+  { 0x34, "Find Close2" },
+  { 0x35, "Find Notify Close" },
+  { 0x36, "unknown-0x36" },
+  { 0x37, "unknown-0x37" },
+  { 0x38, "unknown-0x38" },
+  { 0x39, "unknown-0x39" },
+  { 0x3A, "unknown-0x3A" },
+  { 0x3B, "unknown-0x3B" },
+  { 0x3C, "unknown-0x3C" },
+  { 0x3D, "unknown-0x3D" },
+  { 0x3E, "unknown-0x3E" },
+  { 0x3F, "unknown-0x3F" },
+  { 0x40, "unknown-0x40" },
+  { 0x41, "unknown-0x41" },
+  { 0x42, "unknown-0x42" },
+  { 0x43, "unknown-0x43" },
+  { 0x44, "unknown-0x44" },
+  { 0x45, "unknown-0x45" },
+  { 0x46, "unknown-0x46" },
+  { 0x47, "unknown-0x47" },
+  { 0x48, "unknown-0x48" },
+  { 0x49, "unknown-0x49" },
+  { 0x4A, "unknown-0x4A" },
+  { 0x4B, "unknown-0x4B" },
+  { 0x4C, "unknown-0x4C" },
+  { 0x4D, "unknown-0x4D" },
+  { 0x4E, "unknown-0x4E" },
+  { 0x4F, "unknown-0x4F" },
+  { 0x50, "unknown-0x50" },
+  { 0x51, "unknown-0x51" },
+  { 0x52, "unknown-0x52" },
+  { 0x53, "unknown-0x53" },
+  { 0x54, "unknown-0x54" },
+  { 0x55, "unknown-0x55" },
+  { 0x56, "unknown-0x56" },
+  { 0x57, "unknown-0x57" },
+  { 0x58, "unknown-0x58" },
+  { 0x59, "unknown-0x59" },
+  { 0x5A, "unknown-0x5A" },
+  { 0x5B, "unknown-0x5B" },
+  { 0x5C, "unknown-0x5C" },
+  { 0x5D, "unknown-0x5D" },
+  { 0x5E, "unknown-0x5E" },
+  { 0x5F, "unknown-0x5F" },
+  { 0x60, "unknown-0x60" },
+  { 0x61, "unknown-0x61" },
+  { 0x62, "unknown-0x62" },
+  { 0x63, "unknown-0x63" },
+  { 0x64, "unknown-0x64" },
+  { 0x65, "unknown-0x65" },
+  { 0x66, "unknown-0x66" },
+  { 0x67, "unknown-0x67" },
+  { 0x68, "unknown-0x68" },
+  { 0x69, "unknown-0x69" },
+  { 0x6A, "unknown-0x6A" },
+  { 0x6B, "unknown-0x6B" },
+  { 0x6C, "unknown-0x6C" },
+  { 0x6D, "unknown-0x6D" },
+  { 0x6E, "unknown-0x6E" },
+  { 0x6F, "unknown-0x6F" },
+  { 0x70, "Tree Connect" },
+  { 0x71, "Tree Disconnect" },
+  { 0x72, "Negotiate Protocol" },
+  { 0x73, "Session Setup AndX" },
+  { 0x74, "Logoff AndX" },
+  { 0x75, "Tree Connect AndX" },
+  { 0x76, "unknown-0x76" },
+  { 0x77, "unknown-0x77" },
+  { 0x78, "unknown-0x78" },
+  { 0x79, "unknown-0x79" },
+  { 0x7A, "unknown-0x7A" },
+  { 0x7B, "unknown-0x7B" },
+  { 0x7C, "unknown-0x7C" },
+  { 0x7D, "unknown-0x7D" },
+  { 0x7E, "unknown-0x7E" },
+  { 0x7F, "unknown-0x7F" },
+  { 0x80, "Query Information Disk" },
+  { 0x81, "Search" },
+  { 0x82, "Find" },
+  { 0x83, "Find Unique" },
+  { 0x84, "SMBfclose" },
+  { 0x85, "unknown-0x85" },
+  { 0x86, "unknown-0x86" },
+  { 0x87, "unknown-0x87" },
+  { 0x88, "unknown-0x88" },
+  { 0x89, "unknown-0x89" },
+  { 0x8A, "unknown-0x8A" },
+  { 0x8B, "unknown-0x8B" },
+  { 0x8C, "unknown-0x8C" },
+  { 0x8D, "unknown-0x8D" },
+  { 0x8E, "unknown-0x8E" },
+  { 0x8F, "unknown-0x8F" },
+  { 0x90, "unknown-0x90" },
+  { 0x91, "unknown-0x91" },
+  { 0x92, "unknown-0x92" },
+  { 0x93, "unknown-0x93" },
+  { 0x94, "unknown-0x94" },
+  { 0x95, "unknown-0x95" },
+  { 0x96, "unknown-0x96" },
+  { 0x97, "unknown-0x97" },
+  { 0x98, "unknown-0x98" },
+  { 0x99, "unknown-0x99" },
+  { 0x9A, "unknown-0x9A" },
+  { 0x9B, "unknown-0x9B" },
+  { 0x9C, "unknown-0x9C" },
+  { 0x9D, "unknown-0x9D" },
+  { 0x9E, "unknown-0x9E" },
+  { 0x9F, "unknown-0x9F" },
+  { 0xA0, "NT Transact" },
+  { 0xA1, "NT Transact Secondary" },
+  { 0xA2, "NT Create AndX" },
+  { 0xA3, "unknown-0xA3" },
+  { 0xA4, "NT Cancel" },
+  { 0xA5, "unknown-0xA5" },
+  { 0xA6, "unknown-0xA6" },
+  { 0xA7, "unknown-0xA7" },
+  { 0xA8, "unknown-0xA8" },
+  { 0xA9, "unknown-0xA9" },
+  { 0xAA, "unknown-0xAA" },
+  { 0xAB, "unknown-0xAB" },
+  { 0xAC, "unknown-0xAC" },
+  { 0xAD, "unknown-0xAD" },
+  { 0xAE, "unknown-0xAE" },
+  { 0xAF, "unknown-0xAF" },
+  { 0xB0, "unknown-0xB0" },
+  { 0xB1, "unknown-0xB1" },
+  { 0xB2, "unknown-0xB2" },
+  { 0xB3, "unknown-0xB3" },
+  { 0xB4, "unknown-0xB4" },
+  { 0xB5, "unknown-0xB5" },
+  { 0xB6, "unknown-0xB6" },
+  { 0xB7, "unknown-0xB7" },
+  { 0xB8, "unknown-0xB8" },
+  { 0xB9, "unknown-0xB9" },
+  { 0xBA, "unknown-0xBA" },
+  { 0xBB, "unknown-0xBB" },
+  { 0xBC, "unknown-0xBC" },
+  { 0xBD, "unknown-0xBD" },
+  { 0xBE, "unknown-0xBE" },
+  { 0xBF, "unknown-0xBF" },
+  { 0xC0, "Open Print File" },
+  { 0xC1, "Write Print File" },
+  { 0xC2, "Close Print File" },
+  { 0xC3, "Get Print Queue" },
+  { 0xC4, "unknown-0xC4" },
+  { 0xC5, "unknown-0xC5" },
+  { 0xC6, "unknown-0xC6" },
+  { 0xC7, "unknown-0xC7" },
+  { 0xC8, "unknown-0xC8" },
+  { 0xC9, "unknown-0xC9" },
+  { 0xCA, "unknown-0xCA" },
+  { 0xCB, "unknown-0xCB" },
+  { 0xCC, "unknown-0xCC" },
+  { 0xCD, "unknown-0xCD" },
+  { 0xCE, "unknown-0xCE" },
+  { 0xCF, "unknown-0xCF" },
+  { 0xD0, "SMBsends" },
+  { 0xD1, "SMBsendb" },
+  { 0xD2, "SMBfwdname" },
+  { 0xD3, "SMBcancelf" },
+  { 0xD4, "SMBgetmac" },
+  { 0xD5, "SMBsendstrt" },
+  { 0xD6, "SMBsendend" },
+  { 0xD7, "SMBsendtxt" },
+  { 0xD8, "SMBreadbulk" },
+  { 0xD9, "SMBwritebulk" },
+  { 0xDA, "SMBwritebulkdata" },
+  { 0xDB, "unknown-0xDB" },
+  { 0xDC, "unknown-0xDC" },
+  { 0xDD, "unknown-0xDD" },
+  { 0xDE, "unknown-0xDE" },
+  { 0xDF, "unknown-0xDF" },
+  { 0xE0, "unknown-0xE0" },
+  { 0xE1, "unknown-0xE1" },
+  { 0xE2, "unknown-0xE2" },
+  { 0xE3, "unknown-0xE3" },
+  { 0xE4, "unknown-0xE4" },
+  { 0xE5, "unknown-0xE5" },
+  { 0xE6, "unknown-0xE6" },
+  { 0xE7, "unknown-0xE7" },
+  { 0xE8, "unknown-0xE8" },
+  { 0xE9, "unknown-0xE9" },
+  { 0xEA, "unknown-0xEA" },
+  { 0xEB, "unknown-0xEB" },
+  { 0xEC, "unknown-0xEC" },
+  { 0xED, "unknown-0xED" },
+  { 0xEE, "unknown-0xEE" },
+  { 0xEF, "unknown-0xEF" },
+  { 0xF0, "unknown-0xF0" },
+  { 0xF1, "unknown-0xF1" },
+  { 0xF2, "unknown-0xF2" },
+  { 0xF3, "unknown-0xF3" },
+  { 0xF4, "unknown-0xF4" },
+  { 0xF5, "unknown-0xF5" },
+  { 0xF6, "unknown-0xF6" },
+  { 0xF7, "unknown-0xF7" },
+  { 0xF8, "unknown-0xF8" },
+  { 0xF9, "unknown-0xF9" },
+  { 0xFA, "unknown-0xFA" },
+  { 0xFB, "unknown-0xFB" },
+  { 0xFC, "unknown-0xFC" },
+  { 0xFD, "unknown-0xFD" },
+  { 0xFE, "SMBinvalid" },
+  { 0xFF, "unknown-0xFF" },
+  { 0x00, NULL },
+};
 
-      if (tree) {
+static char *decode_smb_name(unsigned char cmd)
+{
+  return(smb_cmd_vals[cmd].strptr);
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, pad1Count, "Pad1: %s",
-                           bytes_to_str(pd + offset, pad1Count));
-      }
 
-      offset += pad1Count; /* Skip Pad1 */
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ * Everything TVBUFFIFIED above this line
+ * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-    }
 
-    /* Build display for: Parameters */
+/*
+ * Struct passed to each SMB decode routine of info it may need
+ */
 
-    if (ParameterCount > 0) {
+static void
+smb_init_protocol(void)
+{
+       if (smb_info_table) {
+               g_hash_table_foreach_remove(smb_info_table,
+                   free_all_smb_info, NULL);
+               g_hash_table_destroy(smb_info_table);
+       }
+       if (smb_request_hash) {
+               /*
+                * Remove all entries from the hash table and free all
+                * strings attached to the keys and values.  (The keys
+                * and values themselves are freed with
+                * "g_mem_chunk_destroy()" calls below.)
+                */
+               g_hash_table_foreach_remove(smb_request_hash,
+                   free_request_val_data, NULL);
+               g_hash_table_destroy(smb_request_hash);
+       }
+       if (smb_continuation_hash)
+               g_hash_table_destroy(smb_continuation_hash);
+       if (smb_request_keys)
+               g_mem_chunk_destroy(smb_request_keys);
+       if (smb_request_vals)
+               g_mem_chunk_destroy(smb_request_vals);
+       if (smb_continuation_vals)
+               g_mem_chunk_destroy(smb_continuation_vals);
+       if (smb_info_chunk)
+               g_mem_chunk_destroy(smb_info_chunk);
+
+       smb_info_table = g_hash_table_new(smb_info_hash, smb_info_equal);
+       smb_request_hash = g_hash_table_new(smb_hash, smb_equal);
+       smb_continuation_hash = g_hash_table_new(smb_hash, smb_equal);
+       smb_request_keys = g_mem_chunk_new("smb_request_keys",
+           sizeof(struct smb_request_key),
+           smb_packet_init_count * sizeof(struct smb_request_key),
+           G_ALLOC_AND_FREE);
+       smb_request_vals = g_mem_chunk_new("smb_request_vals",
+           sizeof(struct smb_request_val),
+           smb_packet_init_count * sizeof(struct smb_request_val),
+           G_ALLOC_AND_FREE);
+       smb_continuation_vals = g_mem_chunk_new("smb_continuation_vals",
+           sizeof(struct smb_continuation_val),
+           smb_packet_init_count * sizeof(struct smb_continuation_val),
+           G_ALLOC_AND_FREE);
+       smb_info_chunk = g_mem_chunk_new("smb_info_chunk",
+           sizeof(smb_info_t),
+           smb_info_init_count * sizeof(smb_info_t),
+           G_ALLOC_ONLY);
+}
 
-      if (tree) {
+static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info si, int, int);
 
-       proto_tree_add_text(tree, NullTVB, offset, ParameterCount,
-                           "Parameters: %s",
-                           bytes_to_str(pd + offset, ParameterCount));
+void 
+dissect_unknown_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset)
+{
 
-      }
+  if (tree) {
 
-      offset += ParameterCount; /* Skip Parameters */
+    proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (%u bytes)", 
+                       END_OF_FRAME); 
 
-    }
+  }
 
-    if (DataCount > 0 && offset < (SMB_offset + DataOffset)) {
+}
 
-      int pad2Count = SMB_offset + DataOffset - offset;
-       
-      /* Build display for: Pad2 */
+/* Max string length for displaying Unicode strings.  */
+#define        MAX_UNICODE_STR_LEN     256
 
-      if (tree) {
+/* Turn a little-endian Unicode '\0'-terminated string into a string we
+   can display.
+   XXX - for now, we just handle the ISO 8859-1 characters. */
+static gchar *
+unicode_to_str(const guint8 *us, int *us_lenp) {
+  static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
+  static gchar *cur;
+  gchar        *p;
+  int           len;
+  int           us_len;
+  int           overflow = 0;
 
-       proto_tree_add_text(tree, NullTVB, offset, pad2Count, "Pad2: %s",
-                           bytes_to_str(pd + offset, pad2Count));
+  NullTVB; /* remove this function when we are fully tvbuffified */
+  if (cur == &str[0][0]) {
+    cur = &str[1][0];
+  } else if (cur == &str[1][0]) {  
+    cur = &str[2][0];
+  } else {  
+    cur = &str[0][0];
+  }
+  p = cur;
+  len = MAX_UNICODE_STR_LEN;
+  us_len = 0;
+  while (*us != 0 || *(us + 1) != 0) {
+    if (len > 0) {
+      *p++ = *us;
+      len--;
+    } else
+      overflow = 1;
+    us += 2;
+    us_len += 2;
+  }
+  if (overflow) {
+    /* Note that we're not showing the full string.  */
+    *p++ = '.';
+    *p++ = '.';
+    *p++ = '.';
+  }
+  *p = '\0';
+  *us_lenp = us_len;
+  return cur;
+}
+/* Turn a little-endian Unicode '\0'-terminated string into a string we
+   can display.
+   XXX - for now, we just handle the ISO 8859-1 characters.
+   If exactlen==TRUE then us_lenp contains the exact len of the string in
+   bytes. It might not be null terminated !
+   bc specifies the number of bytes in the byte parameters; Windows 2000,
+   at least, appears, in some cases, to put only 1 byte of 0 at the end
+   of a Unicode string if the byte count
+*/
+static gchar *
+unicode_to_str_tvb(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen,
+                  guint16 bc)
+{
+  static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
+  static gchar *cur;
+  gchar        *p;
+  guint16       uchar;
+  int           len;
+  int           us_len;
+  int           overflow = 0;
 
+  if (cur == &str[0][0]) {
+    cur = &str[1][0];
+  } else if (cur == &str[1][0]) {  
+    cur = &str[2][0];
+  } else {  
+    cur = &str[0][0];
+  }
+  p = cur;
+  len = MAX_UNICODE_STR_LEN;
+  us_len = 0;
+  for (;;) {
+    if (bc == 0)
+      break;
+    if (bc == 1) {
+      /* XXX - explain this */
+      if (!exactlen)
+        us_len += 1;   /* this is a one-byte null terminator */
+      break;
+    }
+    uchar = tvb_get_letohs(tvb, offset);
+    if (uchar == 0) {
+      us_len += 2;     /* this is a two-byte null terminator */
+      break;
+    }
+    if (len > 0) {
+      if ((uchar & 0xFF00) == 0)
+        *p++ = uchar;  /* ISO 8859-1 */
+      else
+        *p++ = '?';    /* not 8859-1 */
+      len--;
+    } else
+      overflow = 1;
+    offset += 2;
+    bc -= 2;
+    us_len += 2;
+    if(exactlen){
+      if(us_len>= *us_lenp){
+        break;
       }
-
-      offset += pad2Count; /* Skip Pad2 */
-
     }
+  }
+  if (overflow) {
+    /* Note that we're not showing the full string.  */
+    *p++ = '.';
+    *p++ = '.';
+    *p++ = '.';
+  }
+  *p = '\0';
+  *us_lenp = us_len;
+  return cur;
+}
 
-    /* Build display for: Data */
-
-    if (DataCount > 0) {
+/* Get a null terminated string, which is Unicode if "is_unicode" is true
+   and ASCII (OEM character set) otherwise.
+   XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+static const gchar *
+get_unicode_or_ascii_string(const u_char *pd, int *offsetp, int SMB_offset,
+    gboolean is_unicode, int *len)
+{
+  int offset = *offsetp;
+  const gchar *string;
+  int string_len;
 
-      if (tree) {
+  NullTVB;  /* delete this function when we are fully tvbuffified */
+  if (is_unicode) {
+    if ((offset - SMB_offset) % 2) {
+      /*
+       * XXX - this should be an offset relative to the beginning of the SMB,
+       * not an offset relative to the beginning of the frame; if the stuff
+       * before the SMB has an odd number of bytes, an offset relative to
+       * the beginning of the frame will give the wrong answer.
+       */
+      offset++;   /* Looks like a pad byte there sometimes */
+      *offsetp = offset;
+    }
+    string = unicode_to_str(pd + offset, &string_len);
+    string_len += 2;
+  } else {
+    string = pd + offset;
+    string_len = strlen(string) + 1;
+  }
+  *len = string_len;
+  return string;
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, DataCount,
-                           "Data: %s",
-                           bytes_to_str(pd + offset, DataCount));
+/* nopad == TRUE : Do not add any padding before this string
+ * exactlen == TRUE : len contains the exact len of the string in bytes.
+ * bc: pointer to variable with amount of data left in the byte parameters
+ *   region
+ */
+static const gchar *
+get_unicode_or_ascii_string_tvb(tvbuff_t *tvb, int *offsetp,
+    packet_info *pinfo, int *len, gboolean nopad, gboolean exactlen,
+    guint16 *bcp)
+{
+  static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
+  static gchar *cur;
+  int offset = *offsetp;
+  const gchar *string;
+  int string_len;
+  smb_info_t *si;
+  int copylen;
 
+  if (*bcp == 0) {
+    /* Not enough data in buffer */
+    return NULL;
+  }
+  si = pinfo->private_data;
+  if (si->unicode) {
+    if ((!nopad) && (*offsetp % 2)) {
+      /*
+       * XXX - this should be an offset relative to the beginning of the SMB,
+       * not an offset relative to the beginning of the frame; if the stuff
+       * before the SMB has an odd number of bytes, an offset relative to
+       * the beginning of the frame will give the wrong answer.
+       */
+      (*offsetp)++;   /* Looks like a pad byte there sometimes */
+      (*bcp)--;
+      if (*bcp == 0) {
+        /* Not enough data in buffer */
+        return NULL;
       }
+    }
+    if(exactlen){
+      string_len = *len;
+      string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen, *bcp);
+    } else {
+      string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen, *bcp);
+    }
+  } else {
+    if(exactlen){
+      /*
+       * The string we return must be null-terminated.
+       */
+      if (cur == &str[0][0]) {
+        cur = &str[1][0];
+      } else if (cur == &str[1][0]) {  
+        cur = &str[2][0];
+      } else {  
+        cur = &str[0][0];
+      }
+      copylen = *len;
+      if (copylen > MAX_UNICODE_STR_LEN)
+        copylen = MAX_UNICODE_STR_LEN;
+      tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen);
+      cur[copylen] = '\0';
+      if (copylen > MAX_UNICODE_STR_LEN)
+        strcat(cur, "...");
+      string_len = *len;
+      string = cur;
+    } else {
+      string_len = tvb_strsize(tvb, *offsetp);
+      string = tvb_get_ptr(tvb, *offsetp, string_len);
+    }
+  }
+  *len = string_len;
+  return string;
+}
 
-      offset += DataCount; /* Skip Data */
 
-    }
+/*
+ * Each dissect routine is passed an offset to wct and works from there 
+ */
+
 
-  }
 
-}
 
 
 static void 
@@ -10398,7 +11706,7 @@ dissect_transact_params(const u_char *pd, int offset, frame_data *fd,
   /*
    * Pass "si" to the subdissector.
    */
-  pinfo->private = &si;
+  pinfo->private_data = &si;
 
   /*
    * Tvbuff for setup area, for mailslot call.
@@ -11137,59 +12445,62 @@ dissect_transact_smb(const u_char *pd, int offset, frame_data *fd,
 
 static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info, int, int) = {
 
-  dissect_createdir_smb,    /* unknown SMB 0x00 */
-  dissect_deletedir_smb,    /* unknown SMB 0x01 */
-  dissect_unknown_smb,      /* SMBopen open a file */
-  dissect_create_file_smb,  /* SMBcreate create a file */
-  dissect_close_smb,        /* SMBclose close a file */
-  dissect_flush_file_smb,   /* SMBflush flush a file */
-  dissect_delete_file_smb,  /* SMBunlink delete a file */
-  dissect_rename_file_smb,  /* SMBmv rename a file */
-  dissect_get_file_attr_smb,/* SMBgetatr get file attributes */
-  dissect_set_file_attr_smb,/* SMBsetatr set file attributes */
-  dissect_read_file_smb,    /* SMBread read from a file */
-  dissect_write_file_smb,   /* SMBwrite write to a file */
-  dissect_lock_bytes_smb,   /* SMBlock lock a byte range */
-  dissect_unlock_bytes_smb, /* SMBunlock unlock a byte range */
-  dissect_create_temporary_file_smb,/* SMBctemp create a temporary file */
-  dissect_unknown_smb,      /* SMBmknew make a new file */
-  dissect_checkdir_smb,     /* SMBchkpth check a directory path */
-  dissect_process_exit_smb,      /* SMBexit process exit */
-  dissect_unknown_smb,      /* SMBlseek seek */
-  dissect_lock_and_read_smb,/* SMBlockread Lock a range and read it */
-  dissect_write_and_unlock_smb,/* SMBwriteunlock Unlock a range and then write */
-  dissect_unknown_smb,      /* unknown SMB 0x15 */
-  dissect_unknown_smb,      /* unknown SMB 0x16 */
-  dissect_unknown_smb,      /* unknown SMB 0x17 */
-  dissect_unknown_smb,      /* unknown SMB 0x18 */
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* unknown SMB 0x19 */
-  dissect_read_raw_smb,     /* SMBreadBraw read block raw */
-  dissect_read_mpx_smb,     /* SMBreadBmpx read block multiplexed */
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* SMBreadBs read block (secondary response) */
-  dissect_write_raw_smb,    /* SMBwriteBraw write block raw */
-  dissect_write_mpx_smb,    /* SMBwriteBmpx write block multiplexed */
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* SMBwriteBs write block (secondary request) */
-  dissect_unknown_smb,      /* SMBwriteC write complete response */
+
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* unknown SMB 0x21 */
-  dissect_set_info2_smb,    /* SMBsetattrE set file attributes expanded */
-  dissect_query_info2_smb,  /* SMBgetattrE get file attributes expanded */
-  dissect_locking_andx_smb, /* SMBlockingX lock/unlock byte ranges and X */
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_transact_smb,      /* SMBtrans transaction - name, bytes in/out */
-  dissect_unknown_smb,      /* SMBtranss transaction (secondary request/response) */
-  dissect_unknown_smb,      /* SMBioctl IOCTL */
-  dissect_unknown_smb,      /* SMBioctls IOCTL (secondary request/response) */
-  dissect_unknown_smb,      /* SMBcopy copy */
-  dissect_move_smb,      /* SMBmove move */
-  dissect_unknown_smb,      /* SMBecho echo */
-  dissect_unknown_smb,      /* SMBwriteclose write a file and then close it */
-  dissect_open_andx_smb,      /* SMBopenX open and X */
-  dissect_read_andx_smb,    /* SMBreadX read and X */
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* SMBwriteX write and X */
+
   dissect_unknown_smb,      /* unknown SMB 0x30 */
   dissect_unknown_smb,      /* unknown SMB 0x31 */
-  dissect_transact2_smb,    /* unknown SMB 0x32 */
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* unknown SMB 0x33 */
-  dissect_find_close2_smb,  /* unknown SMB 0x34 */
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* unknown SMB 0x35 */
   dissect_unknown_smb,      /* unknown SMB 0x36 */
   dissect_unknown_smb,      /* unknown SMB 0x37 */
@@ -11201,6 +12512,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x3d */
   dissect_unknown_smb,      /* unknown SMB 0x3e */
   dissect_unknown_smb,      /* unknown SMB 0x3f */
+
   dissect_unknown_smb,      /* unknown SMB 0x40 */
   dissect_unknown_smb,      /* unknown SMB 0x41 */
   dissect_unknown_smb,      /* unknown SMB 0x42 */
@@ -11217,6 +12529,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x4d */
   dissect_unknown_smb,      /* unknown SMB 0x4e */
   dissect_unknown_smb,      /* unknown SMB 0x4f */
+
   dissect_unknown_smb,      /* unknown SMB 0x50 */
   dissect_unknown_smb,      /* unknown SMB 0x51 */
   dissect_unknown_smb,      /* unknown SMB 0x52 */
@@ -11233,6 +12546,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x5d */
   dissect_unknown_smb,      /* unknown SMB 0x5e */
   dissect_unknown_smb,      /* unknown SMB 0x5f */
+
   dissect_unknown_smb,      /* unknown SMB 0x60 */
   dissect_unknown_smb,      /* unknown SMB 0x61 */
   dissect_unknown_smb,      /* unknown SMB 0x62 */
@@ -11249,12 +12563,13 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x6d */
   dissect_unknown_smb,      /* unknown SMB 0x6e */
   dissect_unknown_smb,      /* unknown SMB 0x6f */
-  dissect_treecon_smb,      /* SMBtcon tree connect */
-  dissect_tdis_smb,         /* SMBtdis tree disconnect */
-  dissect_negprot_smb,      /* SMBnegprot negotiate a protocol */
-  dissect_ssetup_andx_smb,  /* SMBsesssetupX Session Set Up & X (including User Logon) */
-  dissect_logoff_andx_smb,  /* SMBlogof Logoff & X */
-  dissect_tcon_andx_smb,    /* SMBtconX tree connect and X */
+
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* unknown SMB 0x76 */
   dissect_unknown_smb,      /* unknown SMB 0x77 */
   dissect_unknown_smb,      /* unknown SMB 0x78 */
@@ -11265,8 +12580,9 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x7d */
   dissect_unknown_smb,      /* unknown SMB 0x7e */
   dissect_unknown_smb,      /* unknown SMB 0x7f */
-  dissect_get_disk_attr_smb,/* SMBdskattr get disk attributes */
-  dissect_search_dir_smb,   /* SMBsearch search a directory */
+
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* SMBffirst find first */
   dissect_unknown_smb,      /* SMBfunique find unique */
   dissect_unknown_smb,      /* SMBfclose find close */
@@ -11281,6 +12597,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x8d */
   dissect_unknown_smb,      /* unknown SMB 0x8e */
   dissect_unknown_smb,      /* unknown SMB 0x8f */
+
   dissect_unknown_smb,      /* unknown SMB 0x90 */
   dissect_unknown_smb,      /* unknown SMB 0x91 */
   dissect_unknown_smb,      /* unknown SMB 0x92 */
@@ -11297,6 +12614,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0x9d */
   dissect_unknown_smb,      /* unknown SMB 0x9e */
   dissect_unknown_smb,      /* unknown SMB 0x9f */
+
   dissect_unknown_smb,      /* unknown SMB 0xa0 */
   dissect_unknown_smb,      /* unknown SMB 0xa1 */
   dissect_unknown_smb,      /* unknown SMB 0xa2 */
@@ -11313,6 +12631,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0xad */
   dissect_unknown_smb,      /* unknown SMB 0xae */
   dissect_unknown_smb,      /* unknown SMB 0xaf */
+
   dissect_unknown_smb,      /* unknown SMB 0xb0 */
   dissect_unknown_smb,      /* unknown SMB 0xb1 */
   dissect_unknown_smb,      /* unknown SMB 0xb2 */
@@ -11329,10 +12648,11 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0xbd */
   dissect_unknown_smb,      /* unknown SMB 0xbe */
   dissect_unknown_smb,      /* unknown SMB 0xbf */
-  dissect_unknown_smb,      /* SMBsplopen open a print spool file */
-  dissect_write_print_file_smb,/* SMBsplwr write to a print spool file */
-  dissect_close_print_file_smb,/* SMBsplclose close a print spool file */
-  dissect_get_print_queue_smb, /* SMBsplretq return print queue */
+
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
+  dissect_unknown_smb,
   dissect_unknown_smb,      /* unknown SMB 0xc4 */
   dissect_unknown_smb,      /* unknown SMB 0xc5 */
   dissect_unknown_smb,      /* unknown SMB 0xc6 */
@@ -11345,6 +12665,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0xcd */
   dissect_unknown_smb,      /* unknown SMB 0xce */
   dissect_unknown_smb,      /* unknown SMB 0xcf */
+
   dissect_unknown_smb,      /* SMBsends send a single block message */
   dissect_unknown_smb,      /* SMBsendb send a broadcast message */
   dissect_unknown_smb,      /* SMBfwdname forward user name */
@@ -11361,6 +12682,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0xdd */
   dissect_unknown_smb,      /* unknown SMB 0xde */
   dissect_unknown_smb,      /* unknown SMB 0xdf */
+
   dissect_unknown_smb,      /* unknown SMB 0xe0 */
   dissect_unknown_smb,      /* unknown SMB 0xe1 */
   dissect_unknown_smb,      /* unknown SMB 0xe2 */
@@ -11377,6 +12699,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   dissect_unknown_smb,      /* unknown SMB 0xed */
   dissect_unknown_smb,      /* unknown SMB 0xee */
   dissect_unknown_smb,      /* unknown SMB 0xef */
+
   dissect_unknown_smb,      /* unknown SMB 0xf0 */
   dissect_unknown_smb,      /* unknown SMB 0xf1 */
   dissect_unknown_smb,      /* unknown SMB 0xf2 */
@@ -11405,13 +12728,6 @@ static const value_string errcls_types[] = {
   { 0, NULL }
 };
 
-char *decode_smb_name(unsigned char cmd)
-{
-
-  return(SMB_names[cmd]);
-
-}
-
 static const value_string DOS_errors[] = {
   {SMBE_badfunc, "Invalid function (or system call)"},
   {SMBE_badfile, "File not found (pathname error)"},
@@ -11428,7 +12744,7 @@ static const value_string DOS_errors[] = {
   {SMBE_baddrive, "Invalid drive"},
   {SMBE_remcd, "Attempt to delete current directory"},
   {SMBE_diffdevice, "Rename/move across different filesystems"},
-  {SMBE_nofiles, "no more files found in file search"},
+  {SMBE_nofiles, "No more files found in file search"},
   {SMBE_badshare, "Share mode on file conflict with open mode"},
   {SMBE_lock, "Lock request conflicts with existing lock"},
   {SMBE_unsup, "Request unsupported, returned by Win 95"},
@@ -11491,7 +12807,7 @@ static const value_string SRV_errors[] = {
 /* Error codes for the ERRHRD class */
 
 static const value_string HRD_errors[] = {
-  {SMBE_nowrite, "read only media"},
+  {SMBE_nowrite, "Read only media"},
   {SMBE_badunit, "Unknown device"},
   {SMBE_notready, "Drive not ready"},
   {SMBE_badcmd, "Unknown command"},
@@ -11513,7 +12829,7 @@ static const value_string HRD_errors[] = {
   {0, NULL}
 };
 
-char *decode_smb_error(guint8 errcls, guint16 errcode)
+static char *decode_smb_error(guint8 errcls, guint16 errcode)
 {
 
   switch (errcls) {
@@ -12279,388 +13595,2137 @@ static const value_string NT_errors[] = {
   { 0,          NULL }
 };
 
-#define SMB_FLAGS_DIRN 0x80
 
-static gboolean
-dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-       int             offset = 0;
-       struct          smb_info si;
-       static const char smb_signature[4] = { 0xFF, 'S', 'M', 'B' };
-       proto_tree      *smb_tree = tree, *smb_hdr_tree = NULL, *flags_tree, *flags2_tree;
-       proto_item      *ti, *tf, *th;
-       guint8          cmd, errcls, errcode1, flags;
-       guint16         flags2, errcode, tid, pid, uid, mid;
-       guint32         status;
-       const u_char    *pd;
-       int             SMB_offset;
-
-       /* OK, is this an SMB message? */
-       if (!tvb_bytes_exist(tvb, 0, 4))
-         return FALSE;
-       if (memcmp(tvb_get_ptr(tvb, 0, 4), smb_signature, 4) != 0) {
-         /* No. */
-         return FALSE;
-       }
 
-       /* Yes. */
-       si.unicode = FALSE;
-       si.ddisp = 0;
+static const true_false_string tfs_smb_flags_lock = {
+       "Lock&Read, Write&Unlock are supported",
+       "Lock&Read, Write&Unlock are not supported"
+};
+static const true_false_string tfs_smb_flags_receive_buffer = {
+       "Receive buffer has been posted",
+       "Receive buffer has not been posted"
+};
+static const true_false_string tfs_smb_flags_caseless = {
+       "Path names are caseless",
+       "Path names are case sensitive"
+};
+static const true_false_string tfs_smb_flags_canon = {
+       "Pathnames are canonicalized",
+       "Pathnames are not canonicalized"
+};
+static const true_false_string tfs_smb_flags_oplock = {
+       "OpLock requested/granted",
+       "OpLock not requested/granted"
+};
+static const true_false_string tfs_smb_flags_notify = {
+       "Notify client on all modifications",
+       "Notify client only on open"
+};
+static const true_false_string tfs_smb_flags_response = {
+       "Message is a response to the client/redirector",
+       "Message is a request to the server"
+};
+
+static int
+dissect_smb_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint8 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+
+       mask = tvb_get_guint8(tvb, offset);
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+                       "Flags: 0x%02x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_flags);
+       }
+       proto_tree_add_boolean(tree, hf_smb_flags_response,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags_notify,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags_oplock,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags_canon,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags_caseless,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags_receive_buffer,
+               tvb, offset, 1, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags_lock,
+               tvb, offset, 1, mask);
+       offset += 1;
+       return offset;
+}
+
+
+static const true_false_string tfs_smb_flags2_long_names_allowed = {
+       "Long file names are allowed in the response",
+       "Long file names are not allowed in the response"
+};
+static const true_false_string tfs_smb_flags2_ea = {
+       "Extended attributes are supported",
+       "Extended attributes are not supported"
+};
+static const true_false_string tfs_smb_flags2_sec_sig = {
+       "Security signatures are supported",
+       "Security signatures are not supported"
+};
+static const true_false_string tfs_smb_flags2_long_names_used = {
+       "Path names in request are long file names",
+       "Path names in request are not long file names"
+};
+static const true_false_string tfs_smb_flags2_esn = {
+       "Extended security negotiation is supported",
+       "Extended security negotiation is not supported"
+};
+static const true_false_string tfs_smb_flags2_dfs = {
+       "Resolve pathnames with Dfs",
+       "Don't resolve pathnames with Dfs"
+};
+static const true_false_string tfs_smb_flags2_roe = {
+       "Permit reads if execute-only",
+       "Don't permit reads if execute-only"
+};
+static const true_false_string tfs_smb_flags2_nt_error = {
+       "Error codes are NT error codes",
+       "Error codes are DOS error codes"
+};
+static const true_false_string tfs_smb_flags2_string = {
+       "Strings are Unicode",
+       "Strings are ASCII"
+};
+static int
+dissect_smb_flags2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+       guint16 mask;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+
+       mask = tvb_get_letohs(tvb, offset);
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+                       "Flags2: 0x%04x", mask);
+               tree = proto_item_add_subtree(item, ett_smb_flags2);
+       }
+
+       proto_tree_add_boolean(tree, hf_smb_flags2_string,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_nt_error,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_roe,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_dfs,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_esn,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_long_names_used,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_sec_sig,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_ea,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_flags2_long_names_allowed,
+               tvb, offset, 2, mask);
+
+       offset += 2;
+       return offset;
+}
+
+
+
+#define SMB_FLAGS_DIRN 0x80
+
+
+static gboolean
+dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+       int offset = 0;
+       proto_item *item = NULL, *hitem = NULL;
+       proto_tree *tree = NULL, *htree = NULL;
+       guint8          flags;
+       guint16         flags2;
+       smb_info_t      si;
+       smb_info_t      *sip;
+       proto_item *cmd_item = NULL;
+       proto_tree *cmd_tree = NULL;
+       int (*dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+        guint32 nt_status = 0;
+        guint8 errclass = 0;
+        guint16 errcode = 0;
+
+
+       /* must check that this really is a smb packet */
+       if (!tvb_bytes_exist(tvb, 0, 4))
+         return FALSE;
+       if( (tvb_get_guint8(tvb, 0) != 0xff)
+        || (tvb_get_guint8(tvb, 1) != 'S')
+        || (tvb_get_guint8(tvb, 2) != 'M')
+        || (tvb_get_guint8(tvb, 3) != 'B') ){
+               return FALSE;
+       }
+        
+       if (check_col(pinfo->fd, COL_PROTOCOL)){
+               col_set_str(pinfo->fd, COL_PROTOCOL, "SMB");
+       }
+       if (check_col(pinfo->fd, COL_INFO)){
+               col_clear(pinfo->fd, COL_INFO);
+       }
+
+       /* start off using the local variable, we will allocate a new one if we
+          need to*/
+       sip = &si;
+       sip->frame_req = 0;
+       sip->frame_res = 0;
+       sip->mid = tvb_get_letohs(tvb, offset+30);
+       sip->uid = tvb_get_letohs(tvb, offset+28);
+       sip->pid = tvb_get_letohs(tvb, offset+26);
+       sip->tid = tvb_get_letohs(tvb, offset+24);
+       flags2 = tvb_get_letohs(tvb, offset+10);
+       if(flags2 & 0x8000){
+               sip->unicode = TRUE; /* Mark them as Unicode */
+       } else {
+               sip->unicode = FALSE;
+       }
+       flags = tvb_get_guint8(tvb, offset+9);
+       sip->request = !(flags&SMB_FLAGS_DIRN);
+       sip->cmd = tvb_get_guint8(tvb, offset+4);
+       sip->ddisp = 0;
+
+       if (parent_tree) {
+               item = proto_tree_add_item(parent_tree, proto_smb, tvb, offset, 
+                       tvb_length_remaining(tvb, 0), FALSE);
+               tree = proto_item_add_subtree(item, ett_smb);
+
+               hitem = proto_tree_add_text(tree, tvb, offset, 32, 
+                       "SMB Header");
+
+               htree = proto_item_add_subtree(hitem, ett_smb_hdr);
+       }
+
+       proto_tree_add_text(htree, tvb, offset, 4, "Server Component: SMB");
+       offset += 4;  /* Skip the marker */
+
+       /* store smb_info structure so we can retreive it from the reply */
+       if(sip->request){
+               sip->src = &pinfo->src;
+               sip->dst = &pinfo->dst;
+               if(!pinfo->fd->flags.visited){
+                       if( (sip->mid==0)
+                       &&  (sip->uid==0)
+                       &&  (sip->pid==0)
+                       &&  (sip->tid==0) ){
+                               /* this is a broadcast SMB packet,
+                                  there will not be a reply.
+                                  We dont need to do anything */
+                               sip->unidir=FALSE;
+                       } else {
+                               sip->unidir=TRUE;
+                               sip = g_mem_chunk_alloc(smb_info_chunk);
+                               memcpy(sip, &si, sizeof(smb_info_t));
+                               sip->frame_req = pinfo->fd->num;
+                               sip->frame_res = 0;
+                               sip->src=g_malloc(sizeof(address));
+                               COPY_ADDRESS(sip->src, &pinfo->src);
+                               sip->dst=g_malloc(sizeof(address));
+                               COPY_ADDRESS(sip->dst, &pinfo->dst);
+                               g_hash_table_insert(smb_info_table, sip, sip);
+                       }
+               }
+       } else {
+               sip->src = &pinfo->dst;
+               sip->dst = &pinfo->src;
+       }
+       sip = g_hash_table_lookup(smb_info_table, sip);
+       if(!sip){
+               sip = &si;
+       }
+       /* need to redo these ones, might have changed if we got a new sip */
+       sip->request = !(flags&SMB_FLAGS_DIRN);
+       if(flags2 & 0x8000){
+               sip->unicode = TRUE; /* Mark them as Unicode */
+       } else {
+               sip->unicode = FALSE;
+       }
+
+       if(sip->request){
+               if(sip->frame_res){
+                       proto_tree_add_uint(htree, hf_smb_response_in, tvb, 0, 0, sip->frame_res);
+               }
+       } else {
+               if(!pinfo->fd->flags.visited){
+                       sip->frame_res=pinfo->fd->num;
+               }
+               if(sip->frame_req){
+                       proto_tree_add_uint(htree, hf_smb_response_to, tvb, 0, 0, sip->frame_req);
+               }
+       }
+
+       /* smb command */
+       proto_tree_add_uint_format(htree, hf_smb_cmd, tvb, offset, 1, sip->cmd, "SMB Command: %s (0x%02x)", decode_smb_name(sip->cmd), sip->cmd);
+       offset += 1;
+
+       if(flags2 & 0x4000){
+               /* handle NT 32 bit error code */
+
+                nt_status = tvb_get_letohl(tvb, offset);
+
+               proto_tree_add_item(htree, hf_smb_nt_status, tvb, offset, 4,
+                       TRUE);
+               offset += 4;
+
+       } else {
+               /* handle DOS error code & class */
+               errclass = tvb_get_guint8(tvb, offset);
+               proto_tree_add_uint(htree, hf_smb_error_class, tvb, offset, 1,
+                       errclass);
+               offset += 1;
+
+               /* reserved byte */
+               proto_tree_add_item(htree, hf_smb_reserved, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               /* error code */
+               /* XXX - the type of this field depends on the value of
+                * "errcls", so there is isn't a single value_string array
+                * fo it, so there can't be a single field for it.
+                */
+               errcode = tvb_get_letohs(tvb, offset);
+               proto_tree_add_uint_format(htree, hf_smb_error_code, tvb,
+                       offset, 2, errcode, "Error Code: %s",
+                       decode_smb_error(errclass, errcode));
+               offset += 2;
+       }
+
+       /* flags */
+       offset = dissect_smb_flags(tvb, pinfo, htree, offset);
+
+       /* flags2 */
+       offset = dissect_smb_flags2(tvb, pinfo, htree, offset);
+
+       /*
+        * The document at
+        *
+        *      http://www.samba.org/samba/ftp/specs/smbpub.txt
+        *
+        * (a text version of "Microsoft Networks SMB FILE SHARING
+        * PROTOCOL, Document Version 6.0p") says that:
+        *
+        *      the first 2 bytes of these 12 bytes are, for NT Create and X,
+        *      the "High Part of PID";
+        *
+        *      the next four bytes are reserved;
+        *
+        *      the next four bytes are, for SMB-over-IPX (with no
+        *      NetBIOS involved) two bytes of Session ID and two bytes
+        *      of SequenceNumber.
+        *
+        * If we ever implement SMB-over-IPX (which I suspect goes over
+        * IPX sockets 0x0550, 0x0552, and maybe 0x0554, as per the
+        * document in question), we'd probably want to have some way
+        * to determine whether this is SMB-over-IPX or not (which could
+        * be done by adding a PT_IPXSOCKET port type, having the
+        * IPX dissector set "pinfo->srcport" and "pinfo->destport",
+        * and having the SMB dissector check for a port type of
+        * PT_IPXSOCKET and for "pinfo->match_port" being either
+        * IPX_SOCKET_NWLINK_SMB_SERVER or IPX_SOCKET_NWLINK_SMB_REDIR
+        * or, if it also uses 0x0554, IPX_SOCKET_NWLINK_SMB_MESSENGER).
+        */
+
+       /* 12 reserved bytes */
+       proto_tree_add_item(htree, hf_smb_reserved, tvb, offset, 12, TRUE);
+       offset += 12;
+
+       /* TID */
+       proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2,
+               sip->tid);
+       offset += 2;
+
+       /* PID */
+       proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2,
+               sip->pid);
+       offset += 2;
+
+       /* UID */
+       proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2,
+               sip->uid);
+       offset += 2;
+
+       /* MID */
+       proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2,
+               sip->mid);
+       offset += 2;
+
+       if((sip->request)? smb_dissector[sip->cmd].request :
+                          smb_dissector[sip->cmd].response){ 
+         /* call smb command dissector */
+         pinfo->private_data = sip;
+          dissect_smb_command(tvb, pinfo, parent_tree, offset, tree, sip->cmd);
+       } else {
+         const u_char *pd;
+         int SMB_offset;
+         proto_item *cmd_item;
+         proto_tree *cmd_tree;
+
+         tvb_compat(tvb, &pd, &SMB_offset);
+         offset += SMB_offset;
+         if (check_col(pinfo->fd, COL_INFO)) {
+           col_add_fstr(pinfo->fd, COL_INFO, "%s %s",
+                        decode_smb_name(sip->cmd),
+                        (sip->request)? "Request" : "Response");
+         }
+
+         cmd_item = proto_tree_add_text(tree, NullTVB, offset,
+                       0, "%s %s (0x%02x)",
+                       decode_smb_name(sip->cmd), 
+                       (sip->request)?"Request":"Response",
+                       sip->cmd);
+         tree = proto_item_add_subtree(cmd_item, ett_smb_command);
+
+         (dissect[sip->cmd])(pd, offset, pinfo->fd, parent_tree, tree, si,
+                             tvb_length(tvb), SMB_offset);
+
+       }
+
+       /* Append error info from this packet to info string. */
+       if (!sip->request && check_col(pinfo->fd, COL_INFO)) {
+               if (flags2 & 0x4000) {
+                       /*
+                        * The status is an NT status code; was there
+                        * an error?
+                        */
+                       if (nt_status != 0) {
+                               /*
+                                * Yes.
+                                */
+                               col_append_fstr(
+                                       pinfo->fd, COL_INFO, ", Error: %s",
+                                       val_to_str(nt_status, NT_errors, "%s"));
+                       }
+               } else {
+                       /*
+                        * The status is a DOS error class and code; was
+                        * there an error?
+                        */
+                       if (errclass != SMB_SUCCESS) {
+                               /*
+                                * Yes.
+                                */
+                               col_append_fstr(
+                                       pinfo->fd, COL_INFO, ", Error: %s",
+                                       decode_smb_error(errclass, errcode));
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+
+
+
+
+
+       /* External routines called during the registration process */
+
+extern void register_proto_smb_browse( void);
+extern void register_proto_smb_logon( void);
+extern void register_proto_smb_mailslot( void);
+extern void register_proto_smb_pipe( void);
+extern void register_proto_smb_mailslot( void);
+
+
+void
+proto_register_smb(void)
+{
+       static hf_register_info hf[] = {
+       { &hf_smb_cmd,
+               { "SMB Command", "smb.cmd", FT_UINT8, BASE_HEX,
+               VALS(smb_cmd_vals), 0x0, "SMB Command", HFILL }},
+
+       { &hf_smb_word_count,
+               { "Word Count (WCT)", "smb.wct", FT_UINT8, BASE_DEC,
+               NULL, 0x0, "Word Count, count of parameter words", HFILL }},
+
+       { &hf_smb_byte_count,
+               { "Byte Count (BCC)", "smb.bcc", FT_UINT16, BASE_DEC,
+               NULL, 0x0, "Byte Count, count of data bytes", HFILL }},
+
+       { &hf_smb_response_to,
+               { "Response to", "smb.response_to", FT_UINT32, BASE_DEC,
+               NULL, 0, "This packet is a response to the packet in this frame", HFILL }},
+
+       { &hf_smb_response_in,
+               { "Response in", "smb.response_in", FT_UINT32, BASE_DEC,
+               NULL, 0, "The response to this packet is in this packet", HFILL }},
+
+       { &hf_smb_nt_status,
+               { "NT Status", "smb.nt_status", FT_UINT32, BASE_HEX,
+               VALS(NT_errors), 0, "NT Status code", HFILL }},
+
+       { &hf_smb_error_class,
+               { "Error Class", "smb.error_class", FT_UINT8, BASE_HEX,
+               VALS(errcls_types), 0, "DOS Error Class", HFILL }},
+
+       { &hf_smb_error_code,
+               { "Error Code", "smb.error_code", FT_UINT16, BASE_HEX,
+               NULL, 0, "DOS Error Code", HFILL }},
+
+       { &hf_smb_reserved,
+               { "Reserved", "smb.reserved", FT_BYTES, BASE_HEX,
+               NULL, 0, "Reserved bytes, must be zero", HFILL }},
+
+       { &hf_smb_pid,
+               { "Process ID", "smb.pid", FT_UINT16, BASE_DEC,
+               NULL, 0, "Process ID", HFILL }},
+
+       { &hf_smb_tid,
+               { "Tree ID", "smb.tid", FT_UINT16, BASE_DEC,
+               NULL, 0, "Tree ID", HFILL }},
+
+       { &hf_smb_uid,
+               { "User ID", "smb.uid", FT_UINT16, BASE_DEC,
+               NULL, 0, "User ID", HFILL }},
+
+       { &hf_smb_mid,
+               { "Multiplex ID", "smb.mid", FT_UINT16, BASE_DEC,
+               NULL, 0, "Multiplex ID", HFILL }},
+
+       { &hf_smb_flags_lock,
+               { "Lock and Read", "smb.flags.lock", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_lock), 0x01, "Are Lock&Read and Write&Unlock operations supported?", HFILL }},
+
+       { &hf_smb_flags_receive_buffer,
+               { "Receive Buffer Posted", "smb.flags.receive_buffer", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_receive_buffer), 0x02, "Have receive buffers been reported?", HFILL }},
+
+       { &hf_smb_flags_caseless,
+               { "Case Sensitivity", "smb.flags.caseless", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_caseless), 0x08, "Are pathnames caseless or casesensitive?", HFILL }},
+
+       { &hf_smb_flags_canon,
+               { "Canonicalized Pathnames", "smb.flags.canon", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_canon), 0x10, "Are pathnames canonicalized?", HFILL }},
+
+       { &hf_smb_flags_oplock,
+               { "Oplocks", "smb.flags.oplock", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_oplock), 0x20, "Is an oplock requested/granted?", HFILL }},
+
+       { &hf_smb_flags_notify,
+               { "Notify", "smb.flags.notify", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_notify), 0x40, "Notify on open or all?", HFILL }},
+
+       { &hf_smb_flags_response,
+               { "Request/Response", "smb.flags.response", FT_BOOLEAN, 8,
+               TFS(&tfs_smb_flags_response), 0x80, "Is this a request or a response?", HFILL }},
+
+       { &hf_smb_flags2_long_names_allowed,
+               { "Long Names Allowed", "smb.flags2.long_names_allowed", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_long_names_allowed), 0x0001, "Are long file names allowed in the response?", HFILL }},
+
+       { &hf_smb_flags2_ea,
+               { "Extended Attributes", "smb.flags2.ea", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_ea), 0x0002, "Are extended attributes supported?", HFILL }},
+
+       { &hf_smb_flags2_sec_sig,
+               { "Security Signatures", "smb.flags2.sec_sig", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_sec_sig), 0x0004, "Are security signatures supported?", HFILL }},
+
+       { &hf_smb_flags2_long_names_used,
+               { "Long Names Used", "smb.flags2.long_names_used", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_long_names_used), 0x0040, "Are pathnames in this request long file names?", HFILL }},
+
+       { &hf_smb_flags2_esn,
+               { "Extended Security Negotiation", "smb.flags2.esn", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_esn), 0x0800, "Is extended security negotiation supported?", HFILL }},
+
+       { &hf_smb_flags2_dfs,
+               { "Dfs", "smb.flags2.dfs", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_dfs), 0x1000, "Can pathnames be resolved using Dfs?", HFILL }},
+
+       { &hf_smb_flags2_roe,
+               { "Execute-only Reads", "smb.flags2.roe", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_roe), 0x2000, "Will reads be allowed for execute-only files?", HFILL }},
+
+       { &hf_smb_flags2_nt_error,
+               { "Error Code Type", "smb.flags2.nt_error", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_nt_error), 0x4000, "Are error codes NT or DOS format?", HFILL }},
+
+       { &hf_smb_flags2_string,
+               { "Unicode Strings", "smb.flags2.string", FT_BOOLEAN, 16,
+               TFS(&tfs_smb_flags2_string), 0x8000, "Are strings ASCII or Unicode?", HFILL }},
+
+       { &hf_smb_buffer_format,
+               { "Buffer Format", "smb.buffer_format", FT_UINT8, BASE_DEC,
+               VALS(buffer_format_vals), 0x0, "Buffer Format, type of buffer", HFILL }},
+
+       { &hf_smb_dialect_name,
+               { "Name", "smb.dialect.name", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of dialect", HFILL }},
+
+       { &hf_smb_dialect_index,
+               { "Selected Index", "smb.dialect.index", FT_UINT16, BASE_DEC,
+               NULL, 0, "Index of selected dialect", HFILL }},
+
+       { &hf_smb_max_trans_buf_size,
+               { "Max Buffer Size", "smb.max_bufsize", FT_UINT32, BASE_DEC,
+               NULL, 0, "Maximum transmit buffer size", HFILL }},
+
+       { &hf_smb_max_mpx_count,
+               { "Max Mpx Count", "smb.max_mpx_count", FT_UINT16, BASE_DEC,
+               NULL, 0, "Maximum pending multiplexed requests", HFILL }},
+
+       { &hf_smb_max_vcs_num,
+               { "Max VCs", "smb.max_vcs", FT_UINT16, BASE_DEC,
+               NULL, 0, "Maximum VCs between client and server", HFILL }},
+
+       { &hf_smb_session_key,
+               { "Session Key", "smb.session_key", FT_UINT32, BASE_HEX,
+               NULL, 0, "Unique token identifying this session", HFILL }},
+
+       { &hf_smb_server_timezone,
+               { "Time Zone", "smb.server.timezone", FT_INT16, BASE_DEC,
+               NULL, 0, "Current timezone at server.", HFILL }},
+
+       { &hf_smb_encryption_key_length,
+               { "Key Length", "smb.encryption_key_length", FT_UINT16, BASE_DEC,
+               NULL, 0, "Encryption key length (must be 0 if not LM2.1 dialect)", HFILL }},
+
+       { &hf_smb_encryption_key,
+               { "Encryption Key", "smb.encryption_key", FT_BYTES, BASE_HEX,
+               NULL, 0, "Challenge/Response Encryption Key (for LM2.1 dialect)", HFILL }},
+
+       { &hf_smb_primary_domain,
+               { "Primary Domain", "smb.primary_domain", FT_STRING, BASE_NONE,
+               NULL, 0, "The server's primary domain", HFILL }},
+
+       { &hf_smb_max_raw_buf_size,
+               { "Max Raw Buffer", "smb.max_raw", FT_UINT32, BASE_DEC,
+               NULL, 0, "Maximum raw buffer size", HFILL }},
+
+       { &hf_smb_server_guid,
+               { "Server GUID", "smb.server.guid", FT_BYTES, BASE_HEX,
+               NULL, 0, "Globally unique identifier for this server", HFILL }},
+
+       { &hf_smb_security_blob_len,
+               { "Security Blob Length", "smb.security_blob_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Security blob length", HFILL }},
+
+       { &hf_smb_security_blob,
+               { "Security Blob", "smb.security_blob", FT_BYTES, BASE_HEX,
+               NULL, 0, "Security blob", HFILL }},
+
+       { &hf_smb_sm_mode16,
+               { "Mode", "smb.sm.mode", FT_BOOLEAN, 16,
+               TFS(&tfs_sm_mode), SECURITY_MODE_MODE, "User or Share security mode?", HFILL }},
+
+       { &hf_smb_sm_password16,
+               { "Password", "smb.sm.password", FT_BOOLEAN, 16,
+               TFS(&tfs_sm_password), SECURITY_MODE_PASSWORD, "Encrypted or plaintext passwords?", HFILL }},
+
+       { &hf_smb_sm_mode,
+               { "Mode", "smb.sm.mode", FT_BOOLEAN, 8,
+               TFS(&tfs_sm_mode), SECURITY_MODE_MODE, "User or Share security mode?", HFILL }},
+
+       { &hf_smb_sm_password,
+               { "Password", "smb.sm.password", FT_BOOLEAN, 8,
+               TFS(&tfs_sm_password), SECURITY_MODE_PASSWORD, "Encrypted or plaintext passwords?", HFILL }},
+
+       { &hf_smb_sm_signatures,
+               { "Signatures", "smb.sm.signatures", FT_BOOLEAN, 8,
+               TFS(&tfs_sm_signatures), SECURITY_MODE_SIGNATURES, "Are security signatures enabled?", HFILL }},
+
+       { &hf_smb_sm_sig_required,
+               { "Sig Req", "smb.sm.sig_required", FT_BOOLEAN, 8,
+               TFS(&tfs_sm_sig_required), SECURITY_MODE_SIG_REQUIRED, "Are security signatures required?", HFILL }},
+
+       { &hf_smb_rm_read,
+               { "Read Raw", "smb.rm.read", FT_BOOLEAN, 16,
+               TFS(&tfs_rm_read), RAWMODE_READ, "Is Read Raw supported?", HFILL }},
+
+       { &hf_smb_rm_write,
+               { "Write Raw", "smb.rm.write", FT_BOOLEAN, 16,
+               TFS(&tfs_rm_write), RAWMODE_WRITE, "Is Write Raw supported?", HFILL }},
+
+       { &hf_smb_server_date_time,
+               { "Server Date and Time", "smb.server_date_time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Current date and time at server", HFILL }},
+
+       { &hf_smb_server_smb_date,
+               { "Server Date", "smb.server_date_time.smb_date", FT_UINT16, BASE_HEX,
+               NULL, 0, "Current date at server, SMB_DATE format", HFILL }},
+
+       { &hf_smb_server_smb_time,
+               { "Server Time", "smb.server_date_time.smb_time", FT_UINT16, BASE_HEX,
+               NULL, 0, "Current time at server, SMB_TIME format", HFILL }},
+
+       { &hf_smb_server_cap_raw_mode,
+               { "Raw Mode", "smb.server.cap.raw_mode", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_raw_mode), SERVER_CAP_RAW_MODE, "Are Raw Read and Raw Write supported?", HFILL }},
+
+       { &hf_smb_server_cap_mpx_mode,
+               { "MPX Mode", "smb.server.cap.mpx_mode", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_mpx_mode), SERVER_CAP_MPX_MODE, "Are Read Mpx and Write Mpx supported?", HFILL }},
+
+       { &hf_smb_server_cap_unicode,
+               { "Unicode", "smb.server.cap.unicode", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_unicode), SERVER_CAP_UNICODE, "Are Unicode strings supported?", HFILL }},
+
+       { &hf_smb_server_cap_large_files,
+               { "Large Files", "smb.server.cap.large_files", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_large_files), SERVER_CAP_LARGE_FILES, "Are large files (>4GB) supported?", HFILL }},
+
+       { &hf_smb_server_cap_nt_smbs,
+               { "NT SMBs", "smb.server.cap.nt_smbs", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_nt_smbs), SERVER_CAP_NT_SMBS, "Are NT SMBs supported?", HFILL }},
+
+       { &hf_smb_server_cap_rpc_remote_apis,
+               { "RPC Remote APIs", "smb.server.cap.rpc_remote_apis", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_rpc_remote_apis), SERVER_CAP_RPC_REMOTE_APIS, "Are RPC Remote APIs supported?", HFILL }},
+
+       { &hf_smb_server_cap_nt_status,
+               { "NT Status Codes", "smb.server.cap.nt_status", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_nt_status), SERVER_CAP_STATUS32, "Are NT Status Codes supported?", HFILL }},
+
+       { &hf_smb_server_cap_level_ii_oplocks,
+               { "Level 2 Oplocks", "smb.server.cap.level_2_oplocks", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_level_ii_oplocks), SERVER_CAP_LEVEL_II_OPLOCKS, "Are Level 2 oplocks supported?", HFILL }},
+
+       { &hf_smb_server_cap_lock_and_read,
+               { "Lock and Read", "smb.server.cap.lock_and_read", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_lock_and_read), SERVER_CAP_LOCK_AND_READ, "Is Lock and Read supported?", HFILL }},
+
+       { &hf_smb_server_cap_nt_find,
+               { "NT Find", "smb.server.cap.nt_find", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_nt_find), SERVER_CAP_NT_FIND, "Is NT Find supported?", HFILL }},
+
+       { &hf_smb_server_cap_dfs,
+               { "Dfs", "smb.server.cap.dfs", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_dfs), SERVER_CAP_DFS, "Is Dfs supported?", HFILL }},
+
+       { &hf_smb_server_cap_infolevel_passthru,
+               { "Infolevel Passthru", "smb.server.cap.infolevel_passthru", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_infolevel_passthru), SERVER_CAP_INFOLEVEL_PASSTHRU, "Is NT information level request passthrough supported?", HFILL }},
+
+       { &hf_smb_server_cap_large_readx,
+               { "Large ReadX", "smb.server.cap.large_readx", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_large_readx), SERVER_CAP_LARGE_READX, "Is Large Read andX supported?", HFILL }},
+
+       { &hf_smb_server_cap_large_writex,
+               { "Large WriteX", "smb.server.cap.large_writex", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_large_writex), SERVER_CAP_LARGE_WRITEX, "Is Large Write andX supported?", HFILL }},
+
+       { &hf_smb_server_cap_unix,
+               { "UNIX", "smb.server.cap.unix", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_unix), SERVER_CAP_UNIX , "Are UNIX extensions supported?", HFILL }},
+
+       { &hf_smb_server_cap_reserved,
+               { "Reserved", "smb.server.cap.reserved", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_reserved), SERVER_CAP_RESERVED, "RESERVED", HFILL }},
+
+       { &hf_smb_server_cap_bulk_transfer,
+               { "Bulk Transfer", "smb.server.cap.bulk_transfer", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_bulk_transfer), SERVER_CAP_BULK_TRANSFER, "Are Bulk Read and Bulk Write supported?", HFILL }},
+
+       { &hf_smb_server_cap_compressed_data,
+               { "Compressed Data", "smb.server.cap.compressed_data", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_compressed_data), SERVER_CAP_COMPRESSED_DATA, "Is compressed data transfer supported?", HFILL }},
+
+       { &hf_smb_server_cap_extended_security,
+               { "Extended Security", "smb.server.cap.extended_security", FT_BOOLEAN, 32,
+               TFS(&tfs_server_cap_extended_security), SERVER_CAP_EXTENDED_SECURITY, "Are Extended security exchanges supported?", HFILL }},
+
+       { &hf_smb_system_time,
+               { "System Time", "smb.system.time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "System Time", HFILL }},
+
+       { &hf_smb_unknown,
+               { "Unknown Data", "smb.unknown", FT_BYTES, BASE_HEX,
+               NULL, 0, "Unknown Data. Should be implemented by someone", HFILL }},
+
+       { &hf_smb_dir_name,
+               { "Directory", "smb.dir_name", FT_STRING, BASE_NONE,
+               NULL, 0, "SMB Directory Name", HFILL }},
+
+       { &hf_smb_echo_count,
+               { "Echo Count", "smb.echo.count", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of times to echo data back", HFILL }},
+
+       { &hf_smb_echo_data,
+               { "Echo Data", "smb.echo.data", FT_BYTES, BASE_HEX,
+               NULL, 0, "Data for SMB Echo Request/Response", HFILL }},
+
+       { &hf_smb_echo_seq_num,
+               { "Echo Seq Num", "smb.echo.seq_num", FT_UINT16, BASE_DEC,
+               NULL, 0, "Sequence number for this echo response", HFILL }},
+
+       { &hf_smb_max_buf_size,
+               { "Max Buffer", "smb.max_buf", FT_UINT16, BASE_DEC,
+               NULL, 0, "Max client buffer size", HFILL }},
+
+       { &hf_smb_path,
+               { "Path", "smb.path", FT_STRING, BASE_NONE,
+               NULL, 0, "Path. Server name and share name", HFILL }},
+
+       { &hf_smb_service,
+               { "Service", "smb.service", FT_STRING, BASE_NONE,
+               NULL, 0, "Service name", HFILL }},
+
+       { &hf_smb_password,
+               { "Password", "smb.password", FT_BYTES, BASE_NONE,
+               NULL, 0, "Password", HFILL }},
+
+       { &hf_smb_ansi_password,
+               { "ANSI Password", "smb.ansi_password", FT_BYTES, BASE_NONE,
+               NULL, 0, "ANSI Password", HFILL }},
+
+       { &hf_smb_unicode_password,
+               { "Unicode Password", "smb.unicode_password", FT_BYTES, BASE_NONE,
+               NULL, 0, "Unicode Password", HFILL }},
+
+       { &hf_smb_move_flags_file,
+               { "Must be file", "smb.move.flags.file", FT_BOOLEAN, 16,
+               TFS(&tfs_mf_file), 0x0001, "Must target be a file?", HFILL }},
+
+       { &hf_smb_move_flags_dir,
+               { "Must be directory", "smb.move.flags.dir", FT_BOOLEAN, 16,
+               TFS(&tfs_mf_dir), 0x0002, "Must target be a directory?", HFILL }},
+
+       { &hf_smb_move_flags_verify,
+               { "Verify writes", "smb.move.flags.verify", FT_BOOLEAN, 16,
+               TFS(&tfs_mf_verify), 0x0010, "Verify all writes?", HFILL }},
+
+       { &hf_smb_count,
+               { "Count", "smb.count", FT_UINT32, BASE_DEC,
+               NULL, 0, "Count number of items/bytes", HFILL }},
+
+       { &hf_smb_file_name,
+               { "File Name", "smb.file", FT_STRING, BASE_NONE,
+               NULL, 0, "File Name", HFILL }},
+
+       { &hf_smb_open_function_create,
+               { "Create", "smb.open.function.create", FT_BOOLEAN, 16,
+               TFS(&tfs_of_create), 0x0010, "Create file if it doesn't exist?", HFILL }},
+
+       { &hf_smb_open_function_open,
+               { "Open", "smb.open.function.open", FT_UINT16, BASE_DEC,
+               VALS(of_open), 0x0003, "Action to be taken on open if file exists", HFILL }},
+
+       { &hf_smb_fid,
+               { "FID", "smb.fid", FT_UINT16, BASE_HEX,
+               NULL, 0, "FID: File ID", HFILL }},
+
+       { &hf_smb_file_attr_read_only_16bit,
+               { "Read Only", "smb.file.attribute.read_only", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_read_only), FILE_ATTRIBUTE_READ_ONLY, "READ ONLY file attribute", HFILL }},
+
+       { &hf_smb_file_attr_read_only_8bit,
+               { "Read Only", "smb.file.attribute.read_only", FT_BOOLEAN, 8,
+               TFS(&tfs_file_attribute_read_only), FILE_ATTRIBUTE_READ_ONLY, "READ ONLY file attribute", HFILL }},
+
+       { &hf_smb_file_attr_hidden_16bit,
+               { "Hidden", "smb.file.attribute.hidden", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_hidden), FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+       { &hf_smb_file_attr_hidden_8bit,
+               { "Hidden", "smb.file.attribute.hidden", FT_BOOLEAN, 8,
+               TFS(&tfs_file_attribute_hidden), FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+       { &hf_smb_file_attr_system_16bit,
+               { "System", "smb.file.attribute.system", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_system), FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+       { &hf_smb_file_attr_system_8bit,
+               { "System", "smb.file.attribute.system", FT_BOOLEAN, 8,
+               TFS(&tfs_file_attribute_system), FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+       { &hf_smb_file_attr_volume_16bit,
+               { "Volume ID", "smb.file.attribute.volume", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_volume), FILE_ATTRIBUTE_VOLUME, "VOLUME file attribute", HFILL }},
+
+       { &hf_smb_file_attr_volume_8bit,
+               { "Volume ID", "smb.file.attribute.volume", FT_BOOLEAN, 8,
+               TFS(&tfs_file_attribute_volume), FILE_ATTRIBUTE_VOLUME, "VOLUME ID file attribute", HFILL }},
+
+       { &hf_smb_file_attr_directory_16bit,
+               { "Directory", "smb.file.attribute.directory", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_directory), FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+       { &hf_smb_file_attr_directory_8bit,
+               { "Directory", "smb.file.attribute.directory", FT_BOOLEAN, 8,
+               TFS(&tfs_file_attribute_directory), FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+       { &hf_smb_file_attr_archive_16bit,
+               { "Archive", "smb.file.attribute.archive", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_archive), FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE file attribute", HFILL }},
+
+       { &hf_smb_file_attr_archive_8bit,
+               { "Archive", "smb.file.attribute.archive", FT_BOOLEAN, 8,
+               TFS(&tfs_file_attribute_archive), FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE file attribute", HFILL }},
+
+       { &hf_smb_file_attr_device,
+               { "Device", "smb.file.attribute.device", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_device), FILE_ATTRIBUTE_DEVICE, "Is this file a device?", HFILL }},
+
+       { &hf_smb_file_attr_normal,
+               { "Normal", "smb.file.attribute.normal", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_normal), FILE_ATTRIBUTE_NORMAL, "Is this a normal file?", HFILL }},
+
+       { &hf_smb_file_attr_temporary,
+               { "Temporary", "smb.file.attribute.temporary", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_temporary), FILE_ATTRIBUTE_TEMPORARY, "Is this a temporary file?", HFILL }},
+
+       { &hf_smb_file_attr_sparse,
+               { "Sparse", "smb.file.attribute.sparse", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_sparse), FILE_ATTRIBUTE_SPARSE, "Is this a sparse file?", HFILL }},
+
+       { &hf_smb_file_attr_reparse,
+               { "Reparse Point", "smb.file.attribute.reparse", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_reparse), FILE_ATTRIBUTE_REPARSE, "Does this file have an associated reparse point?", HFILL }},
+
+       { &hf_smb_file_attr_compressed,
+               { "Compressed", "smb.file.attribute.compressed", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_compressed), FILE_ATTRIBUTE_COMPRESSED, "Is this file compressed?", HFILL }},
+
+       { &hf_smb_file_attr_offline,
+               { "Offline", "smb.file.attribute.offline", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_offline), FILE_ATTRIBUTE_OFFLINE, "Is this file offline?", HFILL }},
+
+       { &hf_smb_file_attr_not_content_indexed,
+               { "Content Indexed", "smb.file.attribute.not_content_indexed", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_not_content_indexed), FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, "May this file be indexed by the content indexing service", HFILL }},
+
+       { &hf_smb_file_attr_encrypted,
+               { "Encrypted", "smb.file.attribute.encrypted", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_encrypted), FILE_ATTRIBUTE_ENCRYPTED, "Is this file encrypted?", HFILL }},
+
+       { &hf_smb_file_size,
+               { "File Size", "smb.file.size", FT_UINT32, BASE_DEC,
+               NULL, 0, "File Size", HFILL }},
+
+       { &hf_smb_search_attribute_read_only,
+               { "Read Only", "smb.search.attribute.read_only", FT_BOOLEAN, 16,
+               TFS(&tfs_search_attribute_read_only), FILE_ATTRIBUTE_READ_ONLY, "READ ONLY search attribute", HFILL }},
+
+       { &hf_smb_search_attribute_hidden,
+               { "Hidden", "smb.search.attribute.hidden", FT_BOOLEAN, 16,
+               TFS(&tfs_search_attribute_hidden), FILE_ATTRIBUTE_HIDDEN, "HIDDEN search attribute", HFILL }},
 
-       if (check_col(pinfo->fd, COL_PROTOCOL))
-               col_set_str(pinfo->fd, COL_PROTOCOL, "SMB");
-       if (check_col(pinfo->fd, COL_INFO))
-               col_clear(pinfo->fd, COL_INFO);
+       { &hf_smb_search_attribute_system,
+               { "System", "smb.search.attribute.system", FT_BOOLEAN, 16,
+               TFS(&tfs_search_attribute_system), FILE_ATTRIBUTE_SYSTEM, "SYSTEM search attribute", HFILL }},
 
-       cmd = tvb_get_guint8(tvb, SMB_hdr_com_offset);
-       if (check_col(pinfo->fd, COL_INFO)) {
+       { &hf_smb_search_attribute_volume,
+               { "Volume ID", "smb.search.attribute.volume", FT_BOOLEAN, 16,
+               TFS(&tfs_search_attribute_volume), FILE_ATTRIBUTE_VOLUME, "VOLUME ID search attribute", HFILL }},
 
-         col_add_fstr(pinfo->fd, COL_INFO, "%s", decode_smb_name(cmd));
+       { &hf_smb_search_attribute_directory,
+               { "Directory", "smb.search.attribute.directory", FT_BOOLEAN, 16,
+               TFS(&tfs_search_attribute_directory), FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY search attribute", HFILL }},
 
-       }
+       { &hf_smb_search_attribute_archive,
+               { "Archive", "smb.search.attribute.archive", FT_BOOLEAN, 16,
+               TFS(&tfs_search_attribute_archive), FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE search attribute", HFILL }},
 
-       if (tree) {
+       { &hf_smb_access_mode,
+               { "Access Mode", "smb.access.mode", FT_UINT16, BASE_DEC,
+               VALS(da_access_vals), 0x0007, "Access Mode", HFILL }},
 
-         ti = proto_tree_add_item(tree, proto_smb, tvb, offset, tvb_length(tvb), FALSE);
-         smb_tree = proto_item_add_subtree(ti, ett_smb);
+       { &hf_smb_access_sharing,
+               { "Sharing Mode", "smb.access.sharing", FT_UINT16, BASE_DEC,
+               VALS(da_sharing_vals), 0x0070, "Sharing Mode", HFILL }},
 
-         th = proto_tree_add_text(smb_tree, NullTVB, offset, 32, "SMB Header");
+       { &hf_smb_access_locality,
+               { "Locality", "smb.access.locality", FT_UINT16, BASE_DEC,
+               VALS(da_locality_vals), 0x0700, "Locality of reference", HFILL }},
 
-         smb_hdr_tree = proto_item_add_subtree(th, ett_smb_hdr);
+       { &hf_smb_access_caching,
+               { "Caching", "smb.access.caching", FT_BOOLEAN, 16,
+               TFS(&tfs_da_caching), 0x1000, "Caching mode?", HFILL }},
 
-         /* 0xFFSMB is actually a 1 byte msg type and 3 byte server
-          * component ... SMB is only one used
-          */
+       { &hf_smb_access_writetru,
+               { "Writethrough", "smb.access.writethrough", FT_BOOLEAN, 16,
+               TFS(&tfs_da_writetru), 0x4000, "Writethrough mode?", HFILL }},
 
-         proto_tree_add_text(smb_hdr_tree, tvb, offset, 1, "Message Type: 0xFF");
-         proto_tree_add_text(smb_hdr_tree, tvb, offset+1, 3, "Server Component: SMB");
+       { &hf_smb_create_time,
+               { "Created", "smb.create.time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Creation Time", HFILL }},
 
-       }
+       { &hf_smb_create_dos_date,
+               { "Create Date", "smb.create.smb.date", FT_UINT16, BASE_HEX,
+               NULL, 0, "Create Date, SMB_DATE format", HFILL }},
 
-       offset += 4;  /* Skip the marker */
+       { &hf_smb_create_dos_time,
+               { "Create Time", "smb.create.smb.time", FT_UINT16, BASE_HEX,
+               NULL, 0, "Create Time, SMB_TIME format", HFILL }},
 
-       if (tree) {
+       { &hf_smb_last_write_time,
+               { "Last Write", "smb.last_write.time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Time this file was last written to", HFILL }},
 
-         proto_tree_add_uint(smb_hdr_tree, hf_smb_cmd, tvb, offset, 1, cmd);
+       { &hf_smb_last_write_dos_date,
+               { "Last Write Date", "smb.last_write.smb.date", FT_UINT16, BASE_HEX,
+               NULL, 0, "Last Write Date, SMB_DATE format", HFILL }},
 
-       }
+       { &hf_smb_last_write_dos_time,
+               { "Last Write Time", "smb.last_write.smb.time", FT_UINT16, BASE_HEX,
+               NULL, 0, "Last Write Time, SMB_TIME format", HFILL }},
 
-       offset += 1;
+       { &hf_smb_old_file_name,
+               { "Old File Name", "smb.file", FT_STRING, BASE_NONE,
+               NULL, 0, "Old File Name (When renaming a file)", HFILL }},
 
-       /* Get flags2; we need it to know whether the error code is
-          an NT error code or a DOS error code. */
+       { &hf_smb_offset,
+               { "Offset", "smb.offset", FT_UINT32, BASE_DEC,
+               NULL, 0, "Offset in file", HFILL }},
 
-       flags2 = tvb_get_letohs(tvb, 10);
+       { &hf_smb_remaining,
+               { "Remaining", "smb.remaining", FT_UINT32, BASE_DEC,
+               NULL, 0, "Remaining number of bytes", HFILL }},
 
-       /* Handle error code */
+       { &hf_smb_padding,
+               { "Padding", "smb.padding", FT_BYTES, BASE_HEX,
+               NULL, 0, "Padding or unknown data", HFILL }},
 
-       if (flags2 & 0x4000) {
+       { &hf_smb_file_data,
+               { "File Data", "smb.file.data", FT_BYTES, BASE_HEX,
+               NULL, 0, "Data read/written to the file", HFILL }},
 
-           /* handle NT 32 bit error code */
-           status = tvb_get_letohl(tvb, offset); 
+       { &hf_smb_total_data_len,
+               { "Total Data Length", "smb.total_data_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Total length of data", HFILL }},
 
-           if (tree) {
+       { &hf_smb_data_len,
+               { "Data Length", "smb.data_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Length of data", HFILL }},
 
-               /*
-                * XXX - break the value down into severity code,
-                * customer code, facility, and error?
-                */
-               proto_tree_add_uint(smb_hdr_tree, hf_smb_status,
-                                   tvb, offset, 4, status);
+       { &hf_smb_seek_mode,
+               { "Seek Mode", "smb.seek_mode", FT_UINT16, BASE_DEC,
+               VALS(seek_mode_vals), 0, "Seek Mode, what type of seek", HFILL }},
 
-           }
+       { &hf_smb_access_time,
+               { "Last Access", "smb.access.time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Last Access Time", HFILL }},
 
-           offset += 4;
+       { &hf_smb_access_dos_date,
+               { "Last Access Date", "smb.access.smb.date", FT_UINT16, BASE_HEX,
+               NULL, 0, "Last Access Date, SMB_DATE format", HFILL }},
 
-       }
-       else {
-           /* handle DOS error code & class */
+       { &hf_smb_access_dos_time,
+               { "Last Access Time", "smb.access.smb.time", FT_UINT16, BASE_HEX,
+               NULL, 0, "Last Access Time, SMB_TIME format", HFILL }},
 
-           /* Next, look at the error class, SMB_RETCLASS */
+       { &hf_smb_data_size,
+               { "Data Size", "smb.data_size", FT_UINT32, BASE_DEC,
+               NULL, 0, "Data Size", HFILL }},
 
-           errcls = tvb_get_guint8(tvb, offset);
+       { &hf_smb_alloc_size,
+               { "Allocation Size", "smb.alloc_size", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of bytes to reserve on create or truncate", HFILL }},
 
-           if (tree) {
+       { &hf_smb_max_count,
+               { "Max Count", "smb.maxcount", FT_UINT16, BASE_DEC,
+               NULL, 0, "Maximum Count", HFILL }},
 
-               proto_tree_add_uint(smb_hdr_tree, hf_smb_errcls,
-                                   tvb, offset, 1, errcls);
-           }
+       { &hf_smb_min_count,
+               { "Min Count", "smb.mincount", FT_UINT16, BASE_DEC,
+               NULL, 0, "Minimum Count", HFILL }},
 
-           offset += 1;
+       { &hf_smb_timeout,
+               { "Timeout", "smb.timeout", FT_UINT32, BASE_DEC,
+               NULL, 0, "Timeout in miliseconds", HFILL }},
 
-           /* Error code, SMB_HEINFO ... */
+       { &hf_smb_high_offset,
+               { "High Offset", "smb.offset_high", FT_UINT32, BASE_DEC,
+               NULL, 0, "High 32 Bits Of File Offset", HFILL }},
 
-           errcode1 = tvb_get_guint8(tvb, offset);
+       { &hf_smb_units,
+               { "Total Units", "smb.units", FT_UINT16, BASE_DEC,
+               NULL, 0, "Total number of units at server", HFILL }},
 
-           if (tree) {
+       { &hf_smb_bpu,
+               { "Blocks Per Unit", "smb.bpu", FT_UINT16, BASE_DEC,
+               NULL, 0, "Blocks per unit at server", HFILL }},
 
-               proto_tree_add_text(smb_hdr_tree, tvb, offset, 1, "Reserved: %i", errcode1); 
+       { &hf_smb_blocksize,
+               { "Block Size", "smb.blocksize", FT_UINT16, BASE_DEC,
+               NULL, 0, "Block size (in bytes) at server", HFILL }},
 
-           }
+       { &hf_smb_freeunits,
+               { "Free Units", "smb.free_units", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of free units at server", HFILL }},
 
-           offset += 1;
+       { &hf_smb_data_offset,
+               { "Data Offset", "smb.data_offset", FT_UINT16, BASE_DEC,
+               NULL, 0, "Data Offset", HFILL }},
 
-           errcode = tvb_get_letohs(tvb, offset); 
+       { &hf_smb_dcm,
+               { "Data Compaction Mode", "smb.dcm", FT_UINT16, BASE_DEC,
+               NULL, 0, "Data Compaction Mode", HFILL }},
 
-           if (tree) {
+       { &hf_smb_request_mask,
+               { "Request Mask", "smb.request.mask", FT_UINT32, BASE_HEX,
+               NULL, 0, "Connectionless mode mask", HFILL }},
 
-               /*
-                * XXX - the type of this field depends on the value of
-                * "errcls", so there isn't a single value_string array
-                * for it, so there can't be a single field for it.
-                */
-               proto_tree_add_text(smb_hdr_tree, tvb, offset, 2, "Error Code: %s",
-                                   decode_smb_error(errcls, errcode));
+       { &hf_smb_response_mask,
+               { "Response Mask", "smb.response.mask", FT_UINT32, BASE_HEX,
+               NULL, 0, "Connectionless mode mask", HFILL }},
 
-           }
+       { &hf_smb_sid,
+               { "SID", "smb.sid", FT_UINT16, BASE_HEX,
+               NULL, 0, "SID: Search ID, handle for find operations", HFILL }},
 
-           offset += 2;
-       }
+       { &hf_smb_write_raw_mode_write_through,
+               { "Write Through", "smb.write.mode.write_through", FT_BOOLEAN, 16,
+               TFS(&tfs_write_raw_mode_write_through), 0x0001, "Write through mode requested?", HFILL }},
 
-       /* Now for the flags: Bit 0 = 0 means cmd, 0 = 1 means resp */
+       { &hf_smb_write_raw_mode_return_remaining,
+               { "Return Remaining", "smb.write.mode.return_remaining", FT_BOOLEAN, 16,
+               TFS(&tfs_write_raw_mode_return_remaining), 0x0002, "Return remaining data responses?", HFILL }},
 
-       flags = tvb_get_guint8(tvb, offset);
-       si.request = !(flags&SMB_FLAGS_DIRN);
+       { &hf_smb_write_raw_mode_connectionless,
+               { "Connectionless", "smb.write.mode.connectionless", FT_BOOLEAN, 16,
+               TFS(&tfs_write_raw_mode_connectionless), 0x0080, "Connectionless mode requested?", HFILL }},
 
-       if (check_col(pinfo->fd, COL_INFO)) {
+       { &hf_smb_resume_key_len,
+               { "Resume Key Length", "smb.resume.key_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Resume Key length", HFILL }},
 
-         col_append_fstr(pinfo->fd, COL_INFO, " %s", si.request ? "Request" : "Response");
+       { &hf_smb_resume_server_cookie,
+               { "Server Cookie", "smb.resume.server.cookie", FT_BYTES, BASE_HEX,
+               NULL, 0, "Cookie, must not be modified by the client", HFILL }},
 
-       }
+       { &hf_smb_resume_client_cookie,
+               { "Client Cookie", "smb.resume.client.cookie", FT_BYTES, BASE_HEX,
+               NULL, 0, "Cookie, must not be modified by the server", HFILL }},
 
-       if (tree) {
+       { &hf_smb_andxoffset,
+               { "AndXOffset", "smb.andxoffset", FT_UINT16, BASE_DEC,
+               NULL, 0, "Offset to next command in this SMB packet", HFILL }},
 
-         tf = proto_tree_add_uint(smb_hdr_tree, hf_smb_flags, tvb, offset, 1, flags);
-
-         flags_tree = proto_item_add_subtree(tf, ett_smb_flags);
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, 0x01, 8,
-                                                     "Lock&Read, Write&Unlock supported",
-                                                     "Lock&Read, Write&Unlock not supported"));
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, 0x02, 8,
-                                                     "Receive buffer posted",
-                                                     "Receive buffer not posted"));
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, 0x08, 8, 
-                                                     "Path names caseless",
-                                                     "Path names case sensitive"));
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, 0x10, 8,
-                                                     "Pathnames canonicalized",
-                                                     "Pathnames not canonicalized"));
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, 0x20, 8,
-                                                     "OpLocks requested/granted",
-                                                     "OpLocks not requested/granted"));
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, 0x40, 8, 
-                                                     "Notify all",
-                                                     "Notify open only"));
-
-         proto_tree_add_text(flags_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags, SMB_FLAGS_DIRN,
-                                                     8, "Response to client/redirector", "Request to server"));
+       { &hf_smb_lock_type_large,
+               { "Large Files", "smb.lock.type.large", FT_BOOLEAN, 8,
+               TFS(&tfs_lock_type_large), 0x10, "Large file locking requested?", HFILL }},
 
-       }
+       { &hf_smb_lock_type_cancel,
+               { "Cancel", "smb.lock.type.cancel", FT_BOOLEAN, 8,
+               TFS(&tfs_lock_type_cancel), 0x08, "Cancel outstanding lock requests?", HFILL }},
 
-       offset += 1;
+       { &hf_smb_lock_type_change,
+               { "Change", "smb.lock.type.change", FT_BOOLEAN, 8,
+               TFS(&tfs_lock_type_change), 0x04, "Change type of lock?", HFILL }},
 
-       /* Now put flags2 into the tree */
+       { &hf_smb_lock_type_oplock,
+               { "Oplock Break", "smb.lock.type.oplock_release", FT_BOOLEAN, 8,
+               TFS(&tfs_lock_type_oplock), 0x02, "Is this a notification of, or a response to, an oplock break?", HFILL }},
 
-       if (tree) {
+       { &hf_smb_lock_type_shared,
+               { "Shared", "smb.lock.type.shared", FT_BOOLEAN, 8,
+               TFS(&tfs_lock_type_shared), 0x01, "Shared or exclusive lock requested?", HFILL }},
 
-         tf = proto_tree_add_uint(smb_hdr_tree, hf_smb_flags2, tvb, offset, 2, flags2);
-
-         flags2_tree = proto_item_add_subtree(tf, ett_smb_flags2);
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x0001, 16,
-                                                     "Long file names supported",
-                                                     "Long file names not supported"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x0002, 16,
-                                                     "Extended attributes supported",
-                                                     "Extended attributes not supported"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 1, "%s",
-                             decode_boolean_bitfield(flags2, 0x0004, 16,
-                                                     "Security signatures supported",
-                                                     "Security signatures not supported"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x0800, 16,
-                                                     "Extended security negotiation supported",
-                                                     "Extended security negotiation not supported"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x1000, 16, 
-                                                     "Resolve pathnames with DFS",
-                                                     "Don't resolve pathnames with DFS"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x2000, 16,
-                                                     "Permit reads if execute-only",
-                                                     "Don't permit reads if execute-only"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x4000, 16,
-                                                     "Error codes are NT error codes",
-                                                     "Error codes are DOS error codes"));
-         proto_tree_add_text(flags2_tree, tvb, offset, 2, "%s",
-                             decode_boolean_bitfield(flags2, 0x8000, 16, 
-                                                     "Strings are Unicode",
-                                                     "Strings are ASCII"));
-
-       }
-
-       if (flags2 & 0x8000) si.unicode = TRUE; /* Mark them as Unicode */
+       { &hf_smb_locking_ol,
+               { "Oplock Level", "smb.locking.oplock.level", FT_UINT8, BASE_DEC,
+               VALS(locking_ol_vals), 0, "Level of existing oplock at client (if any)", HFILL }},
 
-       offset += 2;
+       { &hf_smb_number_of_locks,
+               { "Number of Locks", "smb.locking.num_locks", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of lock requests in this request", HFILL }},
 
-       if (tree) {
+       { &hf_smb_number_of_unlocks,
+               { "Number of Unlocks", "smb.locking.num_unlocks", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of unlock requests in this request", HFILL }},
 
-         /*
-          * The document at
-          *
-          *    http://www.samba.org/samba/ftp/specs/smbpub.txt
-          *
-          * (a text version of "Microsoft Networks SMB FILE SHARING
-          * PROTOCOL, Document Version 6.0p") says that:
-          *
-          *    the first 2 bytes of these 12 bytes are, for NT Create and X,
-          *    the "High Part of PID";
-          *
-          *    the next four bytes are reserved;
-          *
-          *    the next four bytes are, for SMB-over-IPX (with no
-          *    NetBIOS involved) two bytes of Session ID and two bytes
-          *    of SequenceNumber.
-          *
-          * If we ever implement SMB-over-IPX (which I suspect goes over
-          * IPX sockets 0x0550, 0x0552, and maybe 0x0554, as per the
-          * document in question), we'd probably want to have some way
-          * to determine whether this is SMB-over-IPX or not (which could
-          * be done by adding a PT_IPXSOCKET port type, having the
-          * IPX dissector set "pinfo->srcport" and "pinfo->destport",
-          * and having the SMB dissector check for a port type of
-          * PT_IPXSOCKET and for "pinfo->match_port" being either
-          * IPX_SOCKET_NWLINK_SMB_SERVER or IPX_SOCKET_NWLINK_SMB_REDIR
-          * or, if it also uses 0x0554, IPX_SOCKET_NWLINK_SMB_MESSENGER).
-          */
-         proto_tree_add_text(smb_hdr_tree, tvb, offset, 12, "Reserved: 6 WORDS");
+       { &hf_smb_lock_long_length,
+               { "Length", "smb.lock.length", FT_UINT64, BASE_DEC,
+               NULL, 0, "Length of lock/unlock region", HFILL }},
 
-       }
+       { &hf_smb_lock_long_offset,
+               { "Offset", "smb.lock.offset", FT_UINT64, BASE_DEC,
+               NULL, 0, "Offset in the file of lock/unlock region", HFILL }},
 
-       offset += 12;
+       { &hf_smb_file_type,
+               { "File Type", "smb.file_type", FT_UINT16, BASE_DEC,
+               VALS(filetype_vals), 0, "Type of file", HFILL }},
 
-       /* Now the TID, tree ID */
+       { &hf_smb_ipc_state_nonblocking,
+               { "Nonblocking", "smb.ipc_state.nonblocking", FT_BOOLEAN, 16,
+               TFS(&tfs_ipc_state_nonblocking), 0x8000, "Is I/O to this pipe nonblocking?", HFILL }},
 
-       tid = tvb_get_letohs(tvb, offset);
-       si.tid = tid;
+       { &hf_smb_ipc_state_endpoint,
+               { "Endpoint", "smb.ipc_state.endpoint", FT_UINT16, BASE_DEC,
+               VALS(ipc_state_endpoint_vals), 0x4000, "Which end of the pipe this is", HFILL }},
 
-       if (tree) {
+       { &hf_smb_ipc_state_pipe_type,
+               { "Pipe Type", "smb.ipc_state.pipe_type", FT_UINT16, BASE_DEC,
+               VALS(ipc_state_pipe_type_vals), 0x0c00, "What type of pipe this is", HFILL }},
 
-         proto_tree_add_uint(smb_hdr_tree, hf_smb_tid, tvb, offset, 2, tid); 
+       { &hf_smb_ipc_state_read_mode,
+               { "Read Mode", "smb.ipc_state.read_mode", FT_UINT16, BASE_DEC,
+               VALS(ipc_state_read_mode_vals), 0x0300, "How this pipe should be read", HFILL }},
 
-       }
+       { &hf_smb_ipc_state_icount,
+               { "Icount", "smb.ipc_state.icount", FT_UINT16, BASE_DEC,
+               NULL, 0x00FF, "Count to control pipe instancing", HFILL }},
 
-       offset += 2;
+       { &hf_smb_server_fid,
+               { "Server FID", "smb.server_fid", FT_UINT32, BASE_HEX,
+               NULL, 0, "Server unique File ID", HFILL }},
 
-       /* Now the PID, Process ID */
+       { &hf_smb_open_flags_add_info,
+               { "Additional Info", "smb.open.flags.add_info", FT_BOOLEAN, 16,
+               TFS(&tfs_open_flags_add_info), 0x0001, "Additional Information Requested?", HFILL }},
 
-       pid = tvb_get_letohs(tvb, offset);
-       si.pid = pid;
+       { &hf_smb_open_flags_ex_oplock,
+               { "Exclusive Oplock", "smb.open.flags.ex_oplock", FT_BOOLEAN, 16,
+               TFS(&tfs_open_flags_ex_oplock), 0x0002, "Exclusive Oplock Requested?", HFILL }},
 
-       if (tree) {
+       { &hf_smb_open_flags_batch_oplock,
+               { "Batch Oplock", "smb.open.flags.batch_oplock", FT_BOOLEAN, 16,
+               TFS(&tfs_open_flags_batch_oplock), 0x0004, "Batch Oplock Requested?", HFILL }},
 
-         proto_tree_add_uint(smb_hdr_tree, hf_smb_pid, tvb, offset, 2, pid); 
+       { &hf_smb_open_flags_ealen,
+               { "Total EA Len", "smb.open.flags.ealen", FT_BOOLEAN, 16,
+               TFS(&tfs_open_flags_ealen), 0x0008, "Total EA Len Requested?", HFILL }},
 
-       }
+       { &hf_smb_open_action_open,
+               { "Open Action", "smb.open.action.open", FT_UINT16, BASE_DEC,
+               VALS(oa_open_vals), 0x0003, "Open Action, how the file was opened", HFILL }},
 
-       offset += 2;
+       { &hf_smb_open_action_lock,
+               { "Exclusive Open", "smb.open.action.lock", FT_BOOLEAN, 16,
+               TFS(&tfs_oa_lock), 0x8000, "Is this file opened by another user?", HFILL }},
 
-       /* Now the UID, User ID */
+       { &hf_smb_vc_num,
+               { "VC Number", "smb.vc", FT_UINT16, BASE_DEC,
+               NULL, 0, "VC Number", HFILL }},
 
-       uid = tvb_get_letohs(tvb, offset);
-       si.uid = uid;
+       { &hf_smb_password_len,
+               { "Password Length", "smb.pwlen", FT_UINT16, BASE_DEC,
+               NULL, 0, "Length of password", HFILL }},
 
-       if (tree) {
+       { &hf_smb_ansi_password_len,
+               { "ANSI Password Length", "smb.ansi_pwlen", FT_UINT16, BASE_DEC,
+               NULL, 0, "Length of ANSI password", HFILL }},
 
-         proto_tree_add_uint(smb_hdr_tree, hf_smb_uid, tvb, offset, 2, uid); 
+       { &hf_smb_unicode_password_len,
+               { "Unicode Password Length", "smb.unicode_pwlen", FT_UINT16, BASE_DEC,
+               NULL, 0, "Length of Unicode password", HFILL }},
 
-       }
-       
-       offset += 2;
+       { &hf_smb_account,
+               { "Account", "smb.account", FT_STRING, BASE_NONE,
+               NULL, 0, "Account, username", HFILL }},
 
-       /* Now the MID, Multiplex ID */
+       { &hf_smb_os,
+               { "Native OS", "smb.native_os", FT_STRING, BASE_NONE,
+               NULL, 0, "Which OS we are running", HFILL }},
 
-       mid = tvb_get_letohs(tvb, offset);
-       si.mid = mid;
+       { &hf_smb_lanman,
+               { "Native LAN Manager", "smb.native_lanman", FT_STRING, BASE_NONE,
+               NULL, 0, "Which LANMAN protocol we are running", HFILL }},
 
-       if (tree) {
+       { &hf_smb_setup_action_guest,
+               { "Guest", "smb.setup.action.guest", FT_BOOLEAN, 16,
+               TFS(&tfs_setup_action_guest), 0x0001, "Client logged in as GUEST?", HFILL }},
 
-         proto_tree_add_uint(smb_hdr_tree, hf_smb_mid, tvb, offset, 2, mid); 
+       { &hf_smb_fs,
+               { "Native File System", "smb.native_fs", FT_STRING, BASE_NONE,
+               NULL, 0, "Native File System", HFILL }},
 
-       }
+       { &hf_smb_connect_flags_dtid,
+               { "Disconnect TID", "smb.connect.flags.dtid", FT_BOOLEAN, 16,
+               TFS(&tfs_disconnect_tid), 0x0001, "Disconnect TID?", HFILL }},
 
-       offset += 2;
+       { &hf_smb_connect_support_search,
+               { "Search Bits", "smb.connect.support.search", FT_BOOLEAN, 16,
+               TFS(&tfs_connect_support_search), 0x0001, "Exclusive Search Bits supported?", HFILL }},
+
+       { &hf_smb_connect_support_in_dfs,
+               { "In Dfs", "smb.connect.support.dfs", FT_BOOLEAN, 16,
+               TFS(&tfs_connect_support_in_dfs), 0x0002, "Is this in a Dfs tree?", HFILL }},
+
+       { &hf_smb_max_setup_count,
+               { "Max Setup Count", "smb.msc", FT_UINT8, BASE_DEC,
+               NULL, 0, "Maximum number of setup words to return", HFILL }},
+
+       { &hf_smb_total_param_count,
+               { "Total Parameter Count", "smb.tpc", FT_UINT32, BASE_DEC,
+               NULL, 0, "Total number of parameter bytes", HFILL }},
+
+       { &hf_smb_total_data_count,
+               { "Total Data Count", "smb.tdc", FT_UINT32, BASE_DEC,
+               NULL, 0, "Total number of data bytes", HFILL }},
+
+       { &hf_smb_max_param_count,
+               { "Max Parameter Count", "smb.mpc", FT_UINT32, BASE_DEC,
+               NULL, 0, "Maximum number of parameter bytes to return", HFILL }},
+
+       { &hf_smb_max_data_count,
+               { "Max Data Count", "smb.mdc", FT_UINT32, BASE_DEC,
+               NULL, 0, "Maximum number of data bytes to return", HFILL }},
+
+       { &hf_smb_param_disp16,
+               { "Parameter Displacement", "smb.pd", FT_UINT16, BASE_DEC,
+               NULL, 0, "Displacement of these parameter bytes", HFILL }},
+
+       { &hf_smb_param_count16,
+               { "Parameter Count", "smb.pc", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of parameter bytes in this buffer", HFILL }},
+
+       { &hf_smb_param_offset16,
+               { "Parameter Offset", "smb.po", FT_UINT16, BASE_DEC,
+               NULL, 0, "Offset (from header start) to parameters", HFILL }},
+
+       { &hf_smb_param_disp32,
+               { "Parameter Displacement", "smb.pd", FT_UINT32, BASE_DEC,
+               NULL, 0, "Displacement of these parameter bytes", HFILL }},
+
+       { &hf_smb_param_count32,
+               { "Parameter Count", "smb.pc", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of parameter bytes in this buffer", HFILL }},
+
+       { &hf_smb_param_offset32,
+               { "Parameter Offset", "smb.po", FT_UINT32, BASE_DEC,
+               NULL, 0, "Offset (from header start) to parameters", HFILL }},
+
+       { &hf_smb_data_count16,
+               { "Data Count", "smb.dc", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of data bytes in this buffer", HFILL }},
+
+       { &hf_smb_data_disp16,
+               { "Data Displacement", "smb.data_disp", FT_UINT16, BASE_DEC,
+               NULL, 0, "Data Displacement", HFILL }},
+
+       { &hf_smb_data_offset16,
+               { "Data Offset", "smb.data_offset", FT_UINT16, BASE_DEC,
+               NULL, 0, "Data Offset", HFILL }},
+
+       { &hf_smb_data_count32,
+               { "Data Count", "smb.dc", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of data bytes in this buffer", HFILL }},
+
+       { &hf_smb_data_disp32,
+               { "Data Displacement", "smb.data_disp", FT_UINT32, BASE_DEC,
+               NULL, 0, "Data Displacement", HFILL }},
+
+       { &hf_smb_data_offset32,
+               { "Data Offset", "smb.data_offset", FT_UINT32, BASE_DEC,
+               NULL, 0, "Data Offset", HFILL }},
+
+       { &hf_smb_setup_count,
+               { "Setup Count", "smb.sc", FT_UINT8, BASE_DEC,
+               NULL, 0, "Number of setup words in this buffer", HFILL }},
+
+       { &hf_smb_nt_trans_subcmd,
+               { "Function", "smb.nt.function", FT_UINT16, BASE_DEC,
+               VALS(nt_cmd_vals), 0, "Function for NT Transaction", HFILL }},
+
+       { &hf_smb_nt_ioctl_function_code,
+               { "Function", "smb.nt.ioctl.function", FT_UINT32, BASE_HEX,
+               NULL, 0, "NT IOCTL function code", HFILL }},
+
+       { &hf_smb_nt_ioctl_isfsctl,
+               { "IsFSctl", "smb.nt.ioctl.isfsctl", FT_UINT8, BASE_DEC,
+               VALS(nt_ioctl_isfsctl_vals), 0, "Is this a device IOCTL (FALSE) or FS Control (TRUE)", HFILL }},
+
+       { &hf_smb_nt_ioctl_flags_root_handle,
+               { "Root Handle", "smb.nt.ioctl.flags.root_handle", FT_BOOLEAN, 8,
+               TFS(&tfs_nt_ioctl_flags_root_handle), NT_IOCTL_FLAGS_ROOT_HANDLE, "Apply to this share or root Dfs share", HFILL }},
+
+       { &hf_smb_nt_ioctl_data,
+               { "IOCTL Data", "smb.nt.ioctl.data", FT_BYTES, BASE_HEX,
+               NULL, 0, "Data for the IOCTL call", HFILL }},
+
+       { &hf_smb_nt_notify_action,
+               { "Action", "smb.nt.notify.action", FT_UINT32, BASE_DEC,
+               VALS(nt_notify_action_vals), 0, "Which action caused this notify response", HFILL }},
+
+       { &hf_smb_nt_notify_watch_tree,
+               { "Watch Tree", "smb.nt.notify.watch_tree", FT_UINT8, BASE_DEC,
+               VALS(watch_tree_vals), 0, "Should Notify watch subdirectories also?", HFILL }},
+
+       { &hf_smb_nt_notify_stream_write,
+               { "Stream Write", "smb.nt.notify.stream_write", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_stream_write), NT_NOTIFY_STREAM_WRITE, "Notify on stream write?", HFILL }},
+
+       { &hf_smb_nt_notify_stream_size,
+               { "Stream Size Change", "smb.nt.notify.stream_size", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_stream_size), NT_NOTIFY_STREAM_SIZE, "Notify on changes of stream size", HFILL }},
+
+       { &hf_smb_nt_notify_stream_name,
+               { "Stream Name Change", "smb.nt.notify.stream_name", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_stream_name), NT_NOTIFY_STREAM_NAME, "Notify on changes to stream name?", HFILL }},
+
+       { &hf_smb_nt_notify_security,
+               { "Security Change", "smb.nt.notify.security", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_security), NT_NOTIFY_SECURITY, "Notify on changes to security settings", HFILL }},
+
+       { &hf_smb_nt_notify_ea,
+               { "EA Change", "smb.nt.notify.ea", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_ea), NT_NOTIFY_EA, "Notify on changes to Extended Attributes", HFILL }},
+
+       { &hf_smb_nt_notify_creation,
+               { "Created Change", "smb.nt.notify.creation", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_creation), NT_NOTIFY_CREATION, "Notify on changes to creation time", HFILL }},
+
+       { &hf_smb_nt_notify_last_access,
+               { "Last Access Change", "smb.nt.notify.last_access", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_last_access), NT_NOTIFY_LAST_ACCESS, "Notify on changes to last access", HFILL }},
+
+       { &hf_smb_nt_notify_last_write,
+               { "Last Write Change", "smb.nt.notify.last_write", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_last_write), NT_NOTIFY_LAST_WRITE, "Notify on changes to last write", HFILL }},
+
+       { &hf_smb_nt_notify_size,
+               { "Size Change", "smb.nt.notify.size", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_size), NT_NOTIFY_SIZE, "Notify on changes to size", HFILL }},
+
+       { &hf_smb_nt_notify_attributes,
+               { "Attribute Change", "smb.nt.notify.attributes", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_attributes), NT_NOTIFY_ATTRIBUTES, "Notify on changes to attributes", HFILL }},
+
+       { &hf_smb_nt_notify_dir_name,
+               { "Directory Name Change", "smb.nt.notify.dir_name", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_dir_name), NT_NOTIFY_DIR_NAME, "Notify on changes to directory name", HFILL }},
+
+       { &hf_smb_nt_notify_file_name,
+               { "File Name Change", "smb.nt.notify.file_name", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_notify_file_name), NT_NOTIFY_FILE_NAME, "Notify on changes to file name", HFILL }},
+
+       { &hf_smb_root_dir_fid,
+               { "Root FID", "smb.rfid", FT_UINT32, BASE_HEX,
+               NULL, 0, "Open is relative to this FID (if nonzero)", HFILL }},
+
+       { &hf_smb_alloc_size64,
+               { "Allocation Size", "smb.alloc_size", FT_UINT64, BASE_DEC,
+               NULL, 0, "Number of bytes to reserve on create or truncate", HFILL }},
+
+       { &hf_smb_nt_create_disposition,
+               { "Disposition", "smb.create.disposition", FT_UINT32, BASE_DEC,
+               VALS(create_disposition_vals), 0, "Create disposition, what to do if the file does/does not exist", HFILL }},
+
+       { &hf_smb_sd_length,
+               { "SD Length", "smb.sd.length", FT_UINT32, BASE_DEC,
+               NULL, 0, "Total length of security descriptor", HFILL }},
+
+       { &hf_smb_ea_length,
+               { "EA Length", "smb.ea.length", FT_UINT32, BASE_DEC,
+               NULL, 0, "Total EA length for opened file", HFILL }},
+
+       { &hf_smb_file_name_len,
+               { "File Name Len", "smb.file_name_len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Length of File Name", HFILL }},
+
+       { &hf_smb_nt_impersonation_level,
+               { "Impersonation", "smb.impersonation.level", FT_UINT32, BASE_DEC,
+               VALS(impersonation_level_vals), 0, "Impersonation level", HFILL }},
+
+       { &hf_smb_nt_security_flags_context_tracking,
+               { "Context Tracking", "smb.security.flags.context_tracking", FT_BOOLEAN, 8,
+               TFS(&tfs_nt_security_flags_context_tracking), 0x01, "Is security tracking static or dynamic?", HFILL }},
+
+       { &hf_smb_nt_security_flags_effective_only,
+               { "Effective Only", "smb.security.flags.effective_only", FT_BOOLEAN, 8,
+               TFS(&tfs_nt_security_flags_effective_only), 0x02, "Are only enabled or all aspects uf the users SID available?", HFILL }},
+
+       { &hf_smb_nt_access_mask_generic_read,
+               { "Generic Read", "smb.access.generic_read", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_generic_read), 0x80000000, "Is generic read allowed for this object?", HFILL }},
+
+       { &hf_smb_nt_access_mask_generic_write,
+               { "Generic Write", "smb.access.generic_write", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_generic_write), 0x40000000, "Is generic write allowed for this object?", HFILL }},
+
+       { &hf_smb_nt_access_mask_generic_execute,
+               { "Generic Execute", "smb.access.generic_execute", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_generic_execute), 0x20000000, "Is generic execute allowed for this object?", HFILL }},
+
+       { &hf_smb_nt_access_mask_generic_all,
+               { "Generic All", "smb.access.generic_all", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_generic_all), 0x10000000, "Is generic all allowed for this attribute", HFILL }},
+
+       { &hf_smb_nt_access_mask_maximum_allowed,
+               { "Maximum Allowed", "smb.access.maximum_allowed", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_maximum_allowed), 0x02000000, "?", HFILL }},
+
+       { &hf_smb_nt_access_mask_system_security,
+               { "System Security", "smb.access.system_security", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_system_security), 0x01000000, "Access to a system ACL?", HFILL }},
+
+       { &hf_smb_nt_access_mask_synchronize,
+               { "Synchronize", "smb.access.synchronize", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_synchronize), 0x00100000, "Windows NT: synchronize access", HFILL }},
+
+       { &hf_smb_nt_access_mask_write_owner,
+               { "Write Owner", "smb.access.write_owner", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_write_owner), 0x00080000, "Can owner write to the object?", HFILL }},
+
+       { &hf_smb_nt_access_mask_write_dac,
+               { "Write DAC", "smb.access.write_dac", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_write_dac), 0x00040000, "Is write allowed to the owner group or ACLs?", HFILL }},
+
+       { &hf_smb_nt_access_mask_read_control,
+               { "Read Control", "smb.access.read_control", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_read_control), 0x00020000, "Are reads allowed of owner, group and ACL data of the SID?", HFILL }},
+
+       { &hf_smb_nt_access_mask_delete,
+               { "Delete", "smb.access.delete", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_delete), 0x00010000, "Can object be deleted", HFILL }},
+
+       { &hf_smb_nt_access_mask_write_attributes,
+               { "Write Attributes", "smb.access.write_attributes", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_write_attributes), 0x00000100, "Can object's attributes be written", HFILL }},
+
+       { &hf_smb_nt_access_mask_read_attributes,
+               { "Read Attributes", "smb.access.read_attributes", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_read_attributes), 0x00000080, "Can object's attributes be read", HFILL }},
+
+       { &hf_smb_nt_access_mask_delete_child,
+               { "Delete Child", "smb.access.delete_child", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_delete_child), 0x00000040, "Can object's subdirectories be deleted", HFILL }},
 
        /*
-        * Get old-style information from the tvbuff we've been handed.
+        * "Execute" for files, "traverse" for directories.
         */
-       tvb_compat(tvb, &pd, &SMB_offset);
-       offset += SMB_offset;
+       { &hf_smb_nt_access_mask_execute,
+               { "Execute", "smb.access.execute", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_execute), 0x00000020, "Can object be executed (if file) or traversed (if directory)", HFILL }},
 
-       /* Now vector through the table to dissect them */
+       { &hf_smb_nt_access_mask_write_ea,
+               { "Write EA", "smb.access.write_ea", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_write_ea), 0x00000010, "Can object's extended attributes be written", HFILL }},
 
-       (dissect[cmd])(pd, offset, pinfo->fd, tree, smb_tree, si,
-                      tvb_length(tvb), SMB_offset);
+       { &hf_smb_nt_access_mask_read_ea,
+               { "Read EA", "smb.access.read_ea", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_read_ea), 0x00000008, "Can object's extended attributes be read", HFILL }},
 
-       return TRUE;
-}
+       /*
+        * "Append data" for files, "add subdirectory" for directories,
+        * "create pipe instance" for named pipes.
+        */
+       { &hf_smb_nt_access_mask_append,
+               { "Append", "smb.access.append", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_append), 0x00000004, "Can object's contents be appended to", HFILL }},
+
+       /*
+        * "Write data" for files and pipes, "add file" for directory.
+        */
+       { &hf_smb_nt_access_mask_write,
+               { "Write", "smb.access.write", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_write), 0x00000002, "Can object's contents be written", HFILL }},
 
-/*** External routines called during the registration process */
+       /*
+        * "Read data" for files and pipes, "list directory" for directory.
+        */
+       { &hf_smb_nt_access_mask_read,
+               { "Read", "smb.access.read", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_access_mask_read), 0x00000001, "Can object's contents be read", HFILL }},
+
+       { &hf_smb_nt_create_bits_oplock,
+               { "Exclusive Oplock", "smb.nt.create.oplock", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_bits_oplock), 0x00000002, "Is an oplock requested", HFILL }},
+
+       { &hf_smb_nt_create_bits_boplock,
+               { "Batch Oplock", "smb.nt.create.batch_oplock", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_bits_boplock), 0x00000004, "Is a batch oplock requested?", HFILL }},
+
+       { &hf_smb_nt_create_bits_dir,
+               { "Create Directory", "smb.nt.create.dir", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_bits_dir), 0x00000008, "Must target of open be a directory?", HFILL }},
+
+       { &hf_smb_nt_create_options_directory_file,
+               { "Directory", "smb.nt.create_options.directory", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_directory), 0x00000001, "Should file being opened/created be a directory?", HFILL }},
+
+       { &hf_smb_nt_create_options_write_through,
+               { "Write Through", "smb.nt.create_options.write_through", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_write_through), 0x00000002, "Should writes to the file write buffered data out before completing?", HFILL }},
+
+       { &hf_smb_nt_create_options_sequential_only,
+               { "Sequential Only", "smb.nt.create_options.sequential_only", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_sequential_only), 0x00000004, "Will accees to thsis file only be sequential?", HFILL }},
+
+       { &hf_smb_nt_create_options_sync_io_alert,
+               { "Sync I/O Alert", "smb.nt.create_options.sync_io_alert", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_sync_io_alert), 0x00000010, "All operations are performed synchronous", HFILL}},
+
+       { &hf_smb_nt_create_options_sync_io_nonalert,
+               { "Sync I/O Nonalert", "smb.nt.create_options.sync_io_nonalert", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_sync_io_nonalert), 0x00000020, "All operations are synchronous and may block", HFILL}},
+
+       { &hf_smb_nt_create_options_non_directory_file,
+               { "Non-Directory", "smb.nt.create_options.non_directory", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_non_directory), 0x00000040, "Should file being opened/created be a non-directory?", HFILL }},
+
+       /* 0x00000080 is "tree connect", at least in "NtCreateFile()"
+          and "NtOpenFile()"; is that sent over the wire?  Network
+          Monitor thinks so, but its author may just have grabbed
+          the flag bits from a system header file. */
+
+       /* 0x00000100 is "complete if oplocked", at least in "NtCreateFile()"
+          and "NtOpenFile()"; is that sent over the wire?  NetMon
+          thinks so, but see previous comment. */
+
+       { &hf_smb_nt_create_options_no_ea_knowledge,
+               { "No EA Knowledge", "smb.nt.create_options.no_ea_knowledge", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_no_ea_knowledge), 0x00000200, "Does the client not understand extended attributes?", HFILL }},
+
+       { &hf_smb_nt_create_options_eight_dot_three_only,
+               { "8.3 Only", "smb.nt.create_options.eight_dot_three_only", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_eight_dot_three_only), 0x00000400, "Does the client understand only 8.3 filenames?", HFILL }},
+
+       { &hf_smb_nt_create_options_random_access,
+               { "Random Access", "smb.nt.create_options.random_access", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_random_access), 0x00000800, "Will the client be accessing the file randomly?", HFILL }},
+
+       { &hf_smb_nt_create_options_delete_on_close,
+               { "Delete On Close", "smb.nt.create_options.delete_on_close", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_create_options_delete_on_close), 0x00001000, "Should the file be deleted when closed?", HFILL }},
+
+       /* 0x00002000 is "open by FID", or something such as that (which
+          I suspect is like "open by inumber" on UNIX), at least in
+          "NtCreateFile()" and "NtOpenFile()"; is that sent over the
+          wire?  NetMon thinks so, but see previous comment. */
 
-extern void register_proto_smb_browse( void);
-extern void register_proto_smb_logon( void);
-extern void register_proto_smb_mailslot( void);
-extern void register_proto_smb_pipe( void);
-extern void register_proto_smb_mailslot( void);
+       /* 0x00004000 is "open for backup", at least in "NtCreateFile()"
+          and "NtOpenFile()"; is that sent over the wire?  NetMon
+          thinks so, but see previous comment. */
+
+       { &hf_smb_nt_share_access_read,
+               { "Read", "smb.share.access.read", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_share_access_read), 0x00000001, "Can the object be shared for reading?", HFILL }},
+
+       { &hf_smb_nt_share_access_write,
+               { "Write", "smb.share.access.write", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_share_access_write), 0x00000002, "Can the object be shared for write?", HFILL }},
+
+       { &hf_smb_nt_share_access_delete,
+               { "Delete", "smb.share.access.delete", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_share_access_delete), 0x00000004, "", HFILL }},
+
+       { &hf_smb_file_eattr_read_only,
+               { "Read Only", "smb.file.attribute.read_only", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_read_only), FILE_ATTRIBUTE_READ_ONLY, "READ ONLY file attribute", HFILL }},
+
+       { &hf_smb_file_eattr_hidden,
+               { "Hidden", "smb.file.attribute.hidden", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_hidden), FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+       { &hf_smb_file_eattr_system,
+               { "System", "smb.file.attribute.system", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_system), FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+       { &hf_smb_file_eattr_volume,
+               { "Volume ID", "smb.file.attribute.volume", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_volume), FILE_ATTRIBUTE_VOLUME, "VOLUME file attribute", HFILL }},
+
+       { &hf_smb_file_eattr_directory,
+               { "Directory", "smb.file.attribute.directory", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_directory), FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+       { &hf_smb_file_eattr_archive,
+               { "Archive", "smb.file.attribute.archive", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_archive), FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE file attribute", HFILL }},
+
+       { &hf_smb_file_eattr_device,
+               { "Device", "smb.file.attribute.device", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_device), FILE_ATTRIBUTE_DEVICE, "Is this file a device?", HFILL }},
+
+       { &hf_smb_file_eattr_normal,
+               { "Normal", "smb.file.attribute.normal", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_normal), FILE_ATTRIBUTE_NORMAL, "Is this a normal file?", HFILL }},
+
+       { &hf_smb_file_eattr_temporary,
+               { "Temporary", "smb.file.attribute.temporary", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_temporary), FILE_ATTRIBUTE_TEMPORARY, "Is this a temporary file?", HFILL }},
+
+       { &hf_smb_file_eattr_sparse,
+               { "Sparse", "smb.file.attribute.sparse", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_sparse), FILE_ATTRIBUTE_SPARSE, "Is this a sparse file?", HFILL }},
+
+       { &hf_smb_file_eattr_reparse,
+               { "Reparse Point", "smb.file.attribute.reparse", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_reparse), FILE_ATTRIBUTE_REPARSE, "Does this file have an associated reparse point?", HFILL }},
+
+       { &hf_smb_file_eattr_compressed,
+               { "Compressed", "smb.file.attribute.compressed", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_compressed), FILE_ATTRIBUTE_COMPRESSED, "Is this file compressed?", HFILL }},
+
+       { &hf_smb_file_eattr_offline,
+               { "Offline", "smb.file.attribute.offline", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_offline), FILE_ATTRIBUTE_OFFLINE, "Is this file offline?", HFILL }},
+
+       { &hf_smb_file_eattr_not_content_indexed,
+               { "Content Indexed", "smb.file.attribute.not_content_indexed", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_not_content_indexed), FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, "May this file be indexed by the content indexing service", HFILL }},
+
+       { &hf_smb_file_eattr_encrypted,
+               { "Encrypted", "smb.file.attribute.encrypted", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_encrypted), FILE_ATTRIBUTE_ENCRYPTED, "Is this file encrypted?", HFILL }},
+
+       { &hf_smb_file_eattr_write_through,
+               { "Write Through", "smb.file.attribute.write_through", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_write_through), FILE_ATTRIBUTE_WRITE_THROUGH, "Does this object need write through?", HFILL }},
+
+       { &hf_smb_file_eattr_no_buffering,
+               { "No Buffering", "smb.file.attribute.no_buffering", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_no_buffering), FILE_ATTRIBUTE_NO_BUFFERING, "May the server buffer this object?", HFILL }},
+
+       { &hf_smb_file_eattr_random_access,
+               { "Random Access", "smb.file.attribute.random_access", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_random_access), FILE_ATTRIBUTE_RANDOM_ACCESS, "Optimize for random access", HFILL }},
+
+       { &hf_smb_file_eattr_sequential_scan,
+               { "Sequential Scan", "smb.file.attribute.sequential_scan", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_sequential_scan), FILE_ATTRIBUTE_SEQUENTIAL_SCAN, "Optimize for sequential scan", HFILL }},
+
+       { &hf_smb_file_eattr_delete_on_close,
+               { "Delete on Close", "smb.file.attribute.delete_on_close", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_delete_on_close), FILE_ATTRIBUTE_DELETE_ON_CLOSE, "Should this object be deleted on close?", HFILL }},
+
+       { &hf_smb_file_eattr_backup_semantics,
+               { "Backup", "smb.file.attribute.backup_semantics", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_backup_semantics), FILE_ATTRIBUTE_BACKUP_SEMANTICS, "Does this object need/support backup semantics", HFILL }},
+
+       { &hf_smb_file_eattr_posix_semantics,
+               { "Posix", "smb.file.attribute.posix_semantics", FT_BOOLEAN, 32,
+               TFS(&tfs_file_attribute_posix_semantics), FILE_ATTRIBUTE_POSIX_SEMANTICS, "Does this object need/support POSIX semantics?", HFILL }},
+
+       { &hf_smb_security_descriptor_len,
+               { "Security Descriptor Length", "smb.sec_desc_len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Security Descriptor Length", HFILL }},
+
+       { &hf_smb_security_descriptor,
+               { "Security Descriptor", "smb.sec_desc", FT_BYTES, BASE_HEX,
+               NULL, 0, "Security Descriptor", HFILL }},
+
+       { &hf_smb_nt_qsd_owner,
+               { "Owner", "smb.nt_qsd.owner", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_qsd_owner), NT_QSD_OWNER, "Is owner security informaton being queried?", HFILL }},
+
+       { &hf_smb_nt_qsd_group,
+               { "Group", "smb.nt_qsd.group", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_qsd_group), NT_QSD_GROUP, "Is group security informaton being queried?", HFILL }},
+
+       { &hf_smb_nt_qsd_dacl,
+               { "DACL", "smb.nt_qsd.dacl", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_qsd_dacl), NT_QSD_DACL, "Is DACL security informaton being queried?", HFILL }},
+
+       { &hf_smb_nt_qsd_sacl,
+               { "SACL", "smb.nt_qsd.sacl", FT_BOOLEAN, 32,
+               TFS(&tfs_nt_qsd_sacl), NT_QSD_SACL, "Is SACL security informaton being queried?", HFILL }},
+
+       { &hf_smb_extended_attributes,
+               { "Extended Attributes", "smb.ext_attr", FT_BYTES, BASE_HEX,
+               NULL, 0, "Extended Attributes", HFILL }},
+
+       { &hf_smb_oplock_level,
+               { "Oplock level", "smb.oplock.level", FT_UINT8, BASE_DEC,
+               VALS(oplock_level_vals), 0, "Level of oplock granted", HFILL }},
+
+       { &hf_smb_create_action,
+               { "Create action", "smb.create.action", FT_UINT32, BASE_DEC,
+               VALS(create_disposition_vals), 0, "Type of action taken", HFILL }},
+
+       { &hf_smb_ea_error_offset,
+               { "EA Error offset", "smb.ea.error_offset", FT_UINT32, BASE_DEC,
+               NULL, 0, "Offset into EA list if EA error", HFILL }},
+
+       { &hf_smb_end_of_file,
+               { "End Of File", "smb.end_of_file", FT_UINT64, BASE_DEC,
+               NULL, 0, "Offset to the first free byte in the file", HFILL }},
+
+       { &hf_smb_device_type,
+               { "Device Type", "smb.device.type", FT_UINT32, BASE_HEX,
+               VALS(device_type_vals), 0, "Type of device", HFILL }},
+
+       { &hf_smb_is_directory,
+               { "Is Directory", "smb.is_directory", FT_UINT8, BASE_DEC,
+               VALS(is_directory_vals), 0, "Is this object a directory?", HFILL }},
+
+       { &hf_smb_next_entry_offset,
+               { "Next Entry Offset", "smb.next_entry_offset", FT_UINT32, BASE_DEC,
+               NULL, 0, "Offset to next entry", HFILL }},
+
+       { &hf_smb_change_time,
+               { "Change", "smb.change.time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Last Change Time", HFILL }},
+
+       { &hf_smb_setup_len,
+               { "Setup Len", "smb.print.setup.len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Length of prionter setup data", HFILL }},
+
+       { &hf_smb_print_mode,
+               { "Mode", "smb.print.mode", FT_UINT16, BASE_DEC,
+               VALS(print_mode_vals), 0, "Text or Graphics mode", HFILL }},
+
+       { &hf_smb_print_identifier,
+               { "Identifier", "smb.print.identifier", FT_STRING, BASE_NONE,
+               NULL, 0, "Identifier string for this print job", HFILL }},
+
+       { &hf_smb_restart_index,
+               { "Restart Index", "smb.print.restart_index", FT_UINT16, BASE_DEC,
+               NULL, 0, "Index of entry after last returned", HFILL }},
+
+       { &hf_smb_print_queue_date,
+               { "Queued", "smb.print.queued.date", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Date when this entry was queued", HFILL }},
+
+       { &hf_smb_print_queue_dos_date,
+               { "Queued Date", "smb.print.queued.smb.date", FT_UINT16, BASE_HEX,
+               NULL, 0, "Date when this print job was queued, SMB_DATE format", HFILL }},
+
+       { &hf_smb_print_queue_dos_time,
+               { "Queued Time", "smb.print.queued.smb.time", FT_UINT16, BASE_HEX,
+               NULL, 0, "Time when this print job was queued, SMB_TIME format", HFILL }},
+
+       { &hf_smb_print_status,
+               { "Status", "smb.print.status", FT_UINT8, BASE_HEX,
+               VALS(print_status_vals), 0, "Status of this entry", HFILL }},
+
+       { &hf_smb_print_spool_file_number,
+               { "Spool File Number", "smb.print.spool.file_number", FT_UINT16, BASE_DEC,
+               NULL, 0, "Spool File Number, assigned by the spooler", HFILL }},
+
+       { &hf_smb_print_spool_file_size,
+               { "Spool File Size", "smb.print.spool.file_size", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of bytes in spool file", HFILL }},
+
+       { &hf_smb_print_spool_file_name,
+               { "Name", "smb.print.spool.name", FT_BYTES, BASE_HEX,
+               NULL, 0, "Name of client that submitted this job", HFILL }},
+
+       { &hf_smb_start_index,
+               { "Start Index", "smb.print.start_index", FT_UINT16, BASE_DEC,
+               NULL, 0, "First queue entry to return", HFILL }},
+
+       { &hf_smb_cancel_to,
+               { "Cancel to", "smb.cancel_to", FT_UINT32, BASE_DEC,
+               NULL, 0, "This packet is a cancellation of the packet in this frame", HFILL }},
+
+       { &hf_smb_trans2_subcmd,
+               { "Subcommand", "smb.trans2.cmd", FT_UINT16, BASE_HEX,
+               VALS(trans2_cmd_vals), 0, "Subcommand for TRANSACTION2", HFILL }},
+
+       { &hf_smb_trans_name,
+               { "Transaction Name", "smb.trans_name", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of transaction", HFILL }},
+
+       { &hf_smb_transaction_flags_dtid,
+               { "Disconnect TID", "smb.transaction.flags.dtid", FT_BOOLEAN, 16,
+               TFS(&tfs_tf_dtid), 0x0001, "Disconnect TID?", HFILL }},
+
+       { &hf_smb_transaction_flags_owt,
+               { "One Way Transaction", "smb.transaction.flags.owt", FT_BOOLEAN, 16,
+               TFS(&tfs_tf_owt), 0x0002, "One Way Transaction (no response)?", HFILL }},
+
+       { &hf_smb_search_count,
+               { "Search Count", "smb.search_count", FT_UINT16, BASE_DEC,
+               NULL, 0, "Maximum number of search entries to return", HFILL }},
+
+       { &hf_smb_search_pattern,
+               { "Search Pattern", "smb.search_pattern", FT_STRING, BASE_NONE,
+               NULL, 0, "Search Pattern", HFILL }},
+
+       { &hf_smb_ff2_backup,
+               { "Backup Intent", "smb.find_first2.flags.backup", FT_BOOLEAN, 16,
+               TFS(&tfs_ff2_backup), 0x0010, "Find with backup intent", HFILL }},
+
+       { &hf_smb_ff2_continue,
+               { "Continue", "smb.find_first2.flags.continue", FT_BOOLEAN, 16,
+               TFS(&tfs_ff2_continue), 0x0008, "Continue search from previous ending place", HFILL }},
+
+       { &hf_smb_ff2_resume,
+               { "Resume", "smb.find_first2.flags.resume", FT_BOOLEAN, 16,
+               TFS(&tfs_ff2_resume), 0x0004, "Return resume keys for each entry found", HFILL }},
+
+       { &hf_smb_ff2_close_eos,
+               { "Close on EOS", "smb.find_first2.flags.eos", FT_BOOLEAN, 16,
+               TFS(&tfs_ff2_close_eos), 0x0002, "Close search if end of search reached", HFILL }},
+
+       { &hf_smb_ff2_close,
+               { "Close", "smb.find_first2.flags.close", FT_BOOLEAN, 16,
+               TFS(&tfs_ff2_close), 0x0001, "Close search after this request", HFILL }},
+
+       { &hf_smb_ff2_information_level,
+               { "Level of Interest", "smb.ff2_loi", FT_UINT16, BASE_DEC,
+               VALS(ff2_il_vals), 0, "Level of interest for FIND_FIRST2 command", HFILL }},
+
+       { &hf_smb_qpi_loi,
+               { "Level of Interest", "smb.loi", FT_UINT16, BASE_DEC,
+               VALS(qpi_loi_vals), 0, "Level of interest for TRANSACTION[2] commands", HFILL }},
+
+       { &hf_smb_storage_type,
+               { "Storage Type", "smb.storage_type", FT_UINT32, BASE_DEC,
+               NULL, 0, "Type of storage", HFILL }},
+
+       { &hf_smb_resume,
+               { "Resume Key", "smb.resume", FT_UINT32, BASE_DEC,
+               NULL, 0, "Resume Key", HFILL }},
+
+       { &hf_smb_max_referral_level,
+               { "Max Referral Level", "smb.max_referral_level", FT_UINT16, BASE_DEC,
+               NULL, 0, "Latest referral version number understood", HFILL }},
+
+       { &hf_smb_qfsi_information_level,
+               { "Level of Interest", "smb.qfi_loi", FT_UINT16, BASE_DEC,
+               VALS(qfsi_vals), 0, "Level of interest for QUERY_FS_INFORMATION2 command", HFILL }},
+
+       { &hf_smb_ea_size,
+               { "EA Size", "smb.ea_size", FT_UINT32, BASE_DEC,
+               NULL, 0, "Size of file's EA information", HFILL }},
+
+       { &hf_smb_list_length,
+               { "ListLength", "smb.list_len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Length of the remaining data", HFILL }},
+
+       { &hf_smb_number_of_links,
+               { "Link Count", "smb.link_count", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of hard links to the file", HFILL }},
+
+       { &hf_smb_delete_pending,
+               { "Delete Pending", "smb.delete_pending", FT_UINT16, BASE_DEC,
+               VALS(delete_pending_vals), 0, "Is this object about to be deleted?", HFILL }},
+
+       { &hf_smb_index_number,
+               { "Index Number", "smb.index_number", FT_UINT64, BASE_DEC,
+               NULL, 0, "File system unique identifier", HFILL }},
+
+       { &hf_smb_current_offset,
+               { "Current Offset", "smb.offset", FT_UINT64, BASE_DEC,
+               NULL, 0, "Current offset in the file", HFILL }},
+
+       { &hf_smb_t2_alignment,
+               { "Alignment", "smb.alignment", FT_UINT32, BASE_DEC,
+               VALS(alignment_vals), 0, "What alignment do we require for buffers", HFILL }},
+
+       { &hf_smb_t2_stream_name_length,
+               { "Stream Name Length", "smb.stream_name_len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Length of stream name", HFILL }},
+
+       { &hf_smb_t2_stream_size,
+               { "Stream Size", "smb.stream_size", FT_UINT64, BASE_DEC,
+               NULL, 0, "Size of the stream in number of bytes", HFILL }},
+
+       { &hf_smb_t2_compressed_file_size,
+               { "Compressed Size", "smb.compressed.file_size", FT_UINT64, BASE_DEC,
+               NULL, 0, "Size of the compressed file", HFILL }},
+
+       { &hf_smb_t2_compressed_format,
+               { "Compression Format", "smb.compressed.format", FT_UINT16, BASE_DEC,
+               NULL, 0, "Compression algorithm used", HFILL }},
+
+       { &hf_smb_t2_compressed_unit_shift,
+               { "Unit Shift", "smb.compressed.unit_shift", FT_UINT8, BASE_DEC,
+               NULL, 0, "Size of the stream in number of bytes", HFILL }},
+
+       { &hf_smb_t2_compressed_chunk_shift,
+               { "Chunk Shift", "smb.compressed.chunk_shift", FT_UINT8, BASE_DEC,
+               NULL, 0, "Allocated size of the stream in number of bytes", HFILL }},
+
+       { &hf_smb_t2_compressed_cluster_shift,
+               { "Cluster Shift", "smb.compressed.cluster_shift", FT_UINT8, BASE_DEC,
+               NULL, 0, "Allocated size of the stream in number of bytes", HFILL }},
+
+       { &hf_smb_dfs_path_consumed,
+               { "Path Consumed", "smb.dfs.path_consumed", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of RequestFilename bytes client", HFILL }},
+
+       { &hf_smb_dfs_num_referrals,
+               { "Num Referrals", "smb.dfs.num_referrals", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of referrals in this pdu", HFILL }},
+
+       { &hf_smb_get_dfs_server_hold_storage,
+               { "Hold Storage", "smb.dfs.flags.server_hold_storage", FT_BOOLEAN, 16,
+               TFS(&tfs_get_dfs_server_hold_storage), 0x02, "The servers in referrals should hold storage for the file", HFILL }},
+
+       { &hf_smb_get_dfs_fielding,
+               { "Fielding", "smb.dfs.flags.fielding", FT_BOOLEAN, 16,
+               TFS(&tfs_get_dfs_fielding), 0x01, "The servers in referrals are capable of fielding", HFILL }},
+
+       { &hf_smb_dfs_referral_version,
+               { "Version", "smb.dfs.referral.version", FT_UINT16, BASE_DEC,
+               NULL, 0, "Version of referral element", HFILL }},
+
+       { &hf_smb_dfs_referral_size,
+               { "Size", "smb.dfs.referral.size", FT_UINT16, BASE_DEC,
+               NULL, 0, "Size of referral element", HFILL }},
+
+       { &hf_smb_dfs_referral_server_type,
+               { "Server Type", "smb.dfs.referral.server.type", FT_UINT16, BASE_DEC,
+               VALS(dfs_referral_server_type_vals), 0, "Type of referral server", HFILL }},
+
+       { &hf_smb_dfs_referral_flags_strip,
+               { "Strip", "smb.dfs.referral.flags.strip", FT_BOOLEAN, 16,
+               TFS(&tfs_dfs_referral_flags_strip), 0x01, "Should we strip off pathconsumed characters before submitting?", HFILL }},
+
+       { &hf_smb_dfs_referral_node_offset,
+               { "Node Offset", "smb.dfs.referral.node_offset", FT_UINT16, BASE_DEC,
+               NULL, 0, "Offset of name of entity to visit next", HFILL }},
+
+       { &hf_smb_dfs_referral_node,
+               { "Node", "smb.dfs.referral.node", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of entity to visit next", HFILL }},
+
+       { &hf_smb_dfs_referral_proximity,
+               { "Proximity", "smb.dfs.referral.proximity", FT_UINT16, BASE_DEC,
+               NULL, 0, "Hint describing proximity of this server to the client", HFILL }},
+
+       { &hf_smb_dfs_referral_ttl,
+               { "TTL", "smb.dfs.referral.ttl", FT_UINT16, BASE_DEC,
+               NULL, 0, "Number of seconds the client can cache this referral", HFILL }},
+
+       { &hf_smb_dfs_referral_path_offset,
+               { "Path Offset", "smb.dfs.referral.path_offset", FT_UINT16, BASE_DEC,
+               NULL, 0, "Offset of Dfs Path that matched pathconsumed", HFILL }},
+
+       { &hf_smb_dfs_referral_path,
+               { "Path", "smb.dfs.referral.path", FT_STRING, BASE_NONE,
+               NULL, 0, "Dfs Path that matched pathconsumed", HFILL }},
+
+       { &hf_smb_dfs_referral_alt_path_offset,
+               { "Alt Path Offset", "smb.dfs.referral.alt_path_offset", FT_UINT16, BASE_DEC,
+               NULL, 0, "Offset of alternative(8.3) Path that matched pathconsumed", HFILL }},
+
+       { &hf_smb_dfs_referral_alt_path,
+               { "Alt Path", "smb.dfs.referral.alt_path", FT_STRING, BASE_NONE,
+               NULL, 0, "Alternative(8.3) Path that matched pathconsumed", HFILL }},
+
+       { &hf_smb_end_of_search,
+               { "End Of Search", "smb.end_of_search", FT_UINT16, BASE_DEC,
+               NULL, 0, "Was last entry returned?", HFILL }},
+
+       { &hf_smb_last_name_offset,
+               { "Last Name Offset", "smb.last_name_offset", FT_UINT16, BASE_DEC,
+               NULL, 0, "If non-0 this is the offset into the datablock for the file name of the last entry", HFILL }},
+
+       { &hf_smb_file_index,
+               { "File Index", "smb.file_index", FT_UINT32, BASE_DEC,
+               NULL, 0, "File index", HFILL }},
+
+       { &hf_smb_short_file_name,
+               { "Short File Name", "smb.short_file", FT_STRING, BASE_NONE,
+               NULL, 0, "Short (8.3) File Name", HFILL }},
+
+       { &hf_smb_short_file_name_len,
+               { "Short File Name Len", "smb.short_file_name_len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Length of Short (8.3) File Name", HFILL }},
+
+       { &hf_smb_fs_id,
+               { "FS Id", "smb.fs.id", FT_UINT32, BASE_DEC,
+               NULL, 0, "File System ID (NT Server always returns 0)", HFILL }},
+
+       { &hf_smb_sector_unit,
+               { "Sectors/Unit", "smb.fs.sector_per_unit", FT_UINT32, BASE_DEC,
+               NULL, 0, "Sectors per allocation unit", HFILL }},
+
+       { &hf_smb_fs_units,
+               { "Total Units", "smb.fs.units", FT_UINT32, BASE_DEC,
+               NULL, 0, "Total number of units on this filesystem", HFILL }},
+
+       { &hf_smb_fs_sector,
+               { "Bytes per Sector", "smb.fs.bytes_per_sector", FT_UINT32, BASE_DEC,
+               NULL, 0, "Bytes per sector", HFILL }},
+
+       { &hf_smb_avail_units,
+               { "Available Units", "smb.avail.units", FT_UINT32, BASE_DEC,
+               NULL, 0, "Total number of available units on this filesystem", HFILL }},
+
+       { &hf_smb_volume_serial_num,
+               { "Volume Serial Number", "smb.volume.serial", FT_UINT32, BASE_HEX,
+               NULL, 0, "Volume serial number", HFILL }},
+
+       { &hf_smb_volume_label_len,
+               { "Label Length", "smb.volume.label.len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Length of volume label", HFILL }},
+
+       { &hf_smb_volume_label,
+               { "Label", "smb.volume.label", FT_STRING, BASE_DEC,
+               NULL, 0, "Volume label", HFILL }},
+
+       { &hf_smb_free_alloc_units64,
+               { "Free Units", "smb.free_alloc_units", FT_UINT64, BASE_DEC,
+               NULL, 0, "Number of free allocation units", HFILL }},
+
+       { &hf_smb_max_name_len,
+               { "Max name length", "smb.fs.max_name_len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Maximum length of each file name component in number of bytes", HFILL }},
+
+       { &hf_smb_fs_name_len,
+               { "Label Length", "smb.fs.name.len", FT_UINT32, BASE_DEC,
+               NULL, 0, "Length of filesystem name in bytes", HFILL }},
+
+       { &hf_smb_fs_name,
+               { "FS Name", "smb.fs.name", FT_STRING, BASE_DEC,
+               NULL, 0, "Name of filesystem", HFILL }},
+
+       { &hf_smb_device_char_removable,
+               { "Removable", "smb.device.removable", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_removable), 0x00000001, "Is this a removable device", HFILL }},
+
+       { &hf_smb_device_char_read_only,
+               { "Read Only", "smb.device.read_only", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_read_only), 0x00000002, "Is this a read-only device", HFILL }},
+
+       { &hf_smb_device_char_floppy,
+               { "Floppy", "smb.device.floppy", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_floppy), 0x00000004, "Is this a floppy disk", HFILL }},
+
+       { &hf_smb_device_char_write_once,
+               { "Write Once", "smb.device.write_once", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_write_once), 0x00000008, "Is this a write-once device", HFILL }},
+
+       { &hf_smb_device_char_remote,
+               { "Remote", "smb.device.remote", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_remote), 0x00000010, "Is this a remote device", HFILL }},
+
+       { &hf_smb_device_char_mounted,
+               { "Mounted", "smb.device.mounted", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_mounted), 0x00000020, "Is this a mounted device", HFILL }},
+
+       { &hf_smb_device_char_virtual,
+               { "Virtual", "smb.device.virtual", FT_BOOLEAN, 32,
+               TFS(&tfs_device_char_virtual), 0x00000040, "Is this a virtual device", HFILL }},
+
+       { &hf_smb_fs_attr_css,
+               { "Case Sensitive Search", "smb.fs.attr.css", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_css), 0x00000001, "Does this FS support Case Sensitive Search?", HFILL }},
+
+       { &hf_smb_fs_attr_cpn,
+               { "Case Preserving", "smb.fs.attr.cpn", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_cpn), 0x00000002, "Will this FS Preserve Name Case?", HFILL }},
+
+       { &hf_smb_fs_attr_pacls,
+               { "Persistent ACLs", "smb.fs.attr.pacls", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_pacls), 0x00000004, "Does this FS support Persistent ACLs?", HFILL }},
+
+       { &hf_smb_fs_attr_fc,
+               { "Compression", "smb.fs.attr.fc", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_fc), 0x00000008, "Does this FS support File Compression?", HFILL }},
+
+       { &hf_smb_fs_attr_vq,
+               { "Volume Quotas", "smb.fs.attr.vq", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_vq), 0x00000010, "Does this FS support Volume Quotas?", HFILL }},
+
+       { &hf_smb_fs_attr_dim,
+               { "Mounted", "smb.fs.attr.dim", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_dim), 0x00000020, "Is this FS a Mounted Device?", HFILL }},
+
+       { &hf_smb_fs_attr_vic,
+               { "Compressed", "smb.fs.attr.vic", FT_BOOLEAN, 32,
+               TFS(&tfs_fs_attr_vic), 0x00008000, "Is this FS Compressed?", HFILL }},
 
 
-void
-proto_register_smb(void)
-{
-       static hf_register_info hf[] = {
-         { &hf_smb_cmd,
-           { "SMB Command", "smb.cmd",
-             FT_UINT8, BASE_HEX, VALS(smb_cmd_vals), 0x0, "", HFILL }},
-         { &hf_smb_status,
-           { "Status", "smb.status",
-             FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, "", HFILL }},
-         { &hf_smb_errcls,
-           { "Error Class", "smb.errcls",
-             FT_UINT8, BASE_HEX, VALS(errcls_types), 0x0, "", HFILL }},
-         { &hf_smb_flags,
-           { "Flags", "smb.flags",
-             FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
-         { &hf_smb_flags2,
-           { "Flags2", "smb.flags2",
-             FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
-         { &hf_smb_tid,
-           { "Network Path/Tree ID (TID)", "smb.tid",
-             FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
-         { &hf_smb_pid,
-           { "Process ID (PID)", "smb.pid",
-             FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
-         { &hf_smb_uid,
-           { "User ID (UID)", "smb.uid",
-             FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
-         { &hf_smb_mid,
-           { "Multiplex ID (MID)", "smb.mid",
-             FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
        };
        static gint *ett[] = {
                &ett_smb,
                &ett_smb_hdr,
+               &ett_smb_command,
                &ett_smb_fileattributes,
                &ett_smb_capabilities,
                &ett_smb_aflags,
+               &ett_smb_dialect,
                &ett_smb_dialects,
                &ett_smb_mode,
                &ett_smb_rawmode,
@@ -12676,6 +15741,43 @@ proto_register_smb(void)
                &ett_smb_lock_type,
                &ett_smb_ssetupandxaction,
                &ett_smb_optionsup,
+               &ett_smb_time_date,
+               &ett_smb_64bit_time,
+               &ett_smb_move_flags,
+               &ett_smb_file_attributes,
+               &ett_smb_search_resume_key,
+               &ett_smb_search_dir_info,
+               &ett_smb_unlocks,
+               &ett_smb_unlock,
+               &ett_smb_locks,
+               &ett_smb_lock,
+               &ett_smb_open_flags,
+               &ett_smb_ipc_state,
+               &ett_smb_open_action,
+               &ett_smb_setup_action,
+               &ett_smb_connect_flags,
+               &ett_smb_connect_support_bits,
+               &ett_smb_nt_access_mask,
+               &ett_smb_nt_create_bits,
+               &ett_smb_nt_create_options,
+               &ett_smb_nt_share_access,
+               &ett_smb_nt_security_flags,
+               &ett_smb_nt_trans_setup,
+               &ett_smb_nt_notify_completion_filter,
+               &ett_smb_nt_ioctl_flags,
+               &ett_smb_security_information_mask,
+               &ett_smb_print_queue_entry,
+               &ett_smb_transaction_flags,
+               &ett_smb_transaction_params,
+               &ett_smb_find_first2_flags,
+               &ett_smb_transaction_data,
+               &ett_smb_dfs_referrals,
+               &ett_smb_dfs_referral,
+               &ett_smb_dfs_referral_flags,
+               &ett_smb_get_dfs_flags,
+               &ett_smb_ff2_data,
+               &ett_smb_device_characteristics,
+               &ett_smb_fs_attributes,
        };
 
        proto_smb = proto_register_protocol("SMB (Server Message Block Protocol)",