Further tvbuffication, from Ronnie Sahlberg.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 4 Nov 2001 12:44:02 +0000 (12:44 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 4 Nov 2001 12:44:02 +0000 (12:44 +0000)
Make it possible for a non-tvbuffied dissector for an andX SMB to call a
tvbuffified dissector for the andX command, and fix the non-tvbuffified
dissectors in question to do so.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@4154 f5534014-38df-0310-8fa8-9805f1628bb7

packet-smb.c

index 674a25791b53f4197cb7ac68afa473d7e256bdfb..918a99d7c63e4f623335174f91d60dc8fefe0c85 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.128 2001/11/04 00:53:46 guy Exp $
+ * $Id: packet-smb.c,v 1.129 2001/11/04 12:44:02 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -143,6 +143,46 @@ 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 = -1;
+static int hf_smb_file_attr_hidden = -1;
+static int hf_smb_file_attr_system = -1;
+static int hf_smb_file_attr_volume = -1;
+static int hf_smb_file_attr_directory = -1;
+static int hf_smb_file_attr_archive = -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_last_write_time = -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_last_write_date = -1;
+static int hf_smb_last_write_dos_date = -1;
+static int hf_smb_last_write_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_data_len = -1;
+static int hf_smb_seek_mode = -1;
 
 
 static gint ett_smb = -1;
@@ -170,6 +210,7 @@ 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 char *decode_smb_name(unsigned char);
@@ -291,6 +332,213 @@ static const value_string buffer_format_vals[] = {
        {0,     NULL}
 };
 
+/*
+ * 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
+ */
+
+/*
+ * 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)
+{
+       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;
+}
+
+/*
+ * Return the UTC offset in seconds west of UTC, or 0 if it cannot be
+ * determined.
+ */
+static int
+TimeZone(time_t t)
+{
+       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);
+}
+
+/*
+ * 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>
+ */
+#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 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;
+       }
+
+       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;
+}
+
+/*
+ * 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 int
+LocTimeDiff(time_t lt)
+{
+       int d = TimeZoneFaster(lt);
+       time_t t = lt + d;
+
+       /* 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);
+}
+
+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;
+       }
+
+       /*
+        * We add the local time offset.
+        */
+       ts.secs = timeval + LocTimeDiff(timeval);
+       ts.nsecs = 0;
+
+       proto_tree_add_time(tree, hf_date, tvb, offset, 4, &ts);
+       offset += 4;
+       return offset;
+}
+
 static int
 dissect_smb_64bit_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, char *str, int hf_date)
 {
@@ -359,6 +607,299 @@ dissect_smb_timedate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
        return offset;
 }
 
+
+static const value_string da_access_vals[] = {
+       { 0x00,         "Open for reading"},
+       { 0x01,         "Open for writing"},
+       { 0x02,         "Open for reading and writing"},
+       { 0x03,         "Open for execute"},
+       {0, NULL}
+};
+static const value_string da_sharing_vals[] = {
+       { 0x00,         "Compatibility mode"},
+       { 0x01,         "Deny read/write/execute (exclusive)"},
+       { 0x02,         "Deny write"},
+       { 0x03,         "Deny read/execute"},
+       { 0x04,         "Deny none"},
+       {0, NULL}
+};
+static const value_string da_locality_vals[] = {
+       { 0x00,         "Locality of reference unknown"},
+       { 0x01,         "Mainly sequential access"},
+       { 0x02,         "Mainly random access"},
+       { 0x03,         "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 = {
+       "Writethrough ENABLED",
+       "Writethrough 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;
+
+       mask = tvb_get_letohs(tvb, offset);
+
+       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;
+
+       return offset;
+}
+
+#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
+
+/*
+ * 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;
+
+       mask = tvb_get_letohs(tvb, offset);
+
+       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,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_hidden,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_system,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_volume,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_directory,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_archive,
+               tvb, offset, 2, mask);
+
+       offset += 2;
+
+       return offset;
+}
+
+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);
+
+       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);
+       }
+
+       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);
+
+       offset += 2;
+       return offset;
+}
+
+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;
+
+       mask = tvb_get_letohl(tvb, offset);
+
+       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,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_hidden,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_system,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_volume,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_directory,
+               tvb, offset, 2, mask);
+       proto_tree_add_boolean(tree, hf_smb_file_attr_archive,
+               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);
+
+       offset += 2;
+
+       return offset;
+}
+
+
 #define SERVER_CAP_RAW_MODE            0x00000001
 #define SERVER_CAP_MPX_MODE            0x00000002
 #define SERVER_CAP_UNICODE             0x00000004
@@ -1076,7 +1617,7 @@ dissect_open_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree
 
        if(parent_tree){
                item = proto_tree_add_text(parent_tree, tvb, offset, 2,
-                       "Open Function: 0x%04x ", mask);
+                       "Open Function: 0x%04x", mask);
                tree = proto_item_add_subtree(item, ett_smb_openfunction);
        }
 
@@ -1114,7 +1655,7 @@ dissect_move_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, i
 
        if(parent_tree){
                item = proto_tree_add_text(parent_tree, tvb, offset, 2,
-                       "Flags: 0x%04x ", mask);
+                       "Flags: 0x%04x", mask);
                tree = proto_item_add_subtree(item, ett_smb_move_flags);
        }
  
@@ -1218,3239 +1759,2041 @@ dissect_move_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int o
 
        return offset;
 }
+
+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;
+
+       WORD_COUNT;
+
+       /* desired access */
+       offset = dissect_access(tvb, pinfo, tree, offset, "Desired");
+
+       /* Search Attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
+
+       BYTE_COUNT;
+
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
+
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
+
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
+
+       END_OF_SMB
+
+       return offset;
+}
  
+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;
 
+       WORD_COUNT;
 
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-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;
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
+       
+       /* File Size */
+       proto_tree_add_uint(tree, hf_smb_file_size, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
 
-smb_function smb_dissector[256] = {
-  /* 0x00 Create Dir*/  {dissect_old_dir_request, dissect_empty},
-  /* 0x01 Delete Dir*/  {dissect_old_dir_request, dissect_empty},
-  /* 0x02 */  {NULL, NULL},
-  /* 0x03 */  {NULL, NULL},
-  /* 0x04 */  {NULL, NULL},
-  /* 0x05 */  {NULL, NULL},
-  /* 0x06 */  {NULL, NULL},
-  /* 0x07 */  {NULL, NULL},
-  /* 0x08 */  {NULL, NULL},
-  /* 0x09 */  {NULL, NULL},
-  /* 0x0a */  {NULL, NULL},
-  /* 0x0b */  {NULL, NULL},
-  /* 0x0c */  {NULL, NULL},
-  /* 0x0d */  {NULL, NULL},
-  /* 0x0e */  {NULL, NULL},
-  /* 0x0f */  {NULL, NULL},
-  /* 0x10 Check Dir*/  {dissect_old_dir_request, dissect_empty},
-  /* 0x11 Process Exit*/  {dissect_empty, dissect_empty},
-  /* 0x12 */  {NULL, NULL},
-  /* 0x13 */  {NULL, NULL},
-  /* 0x14 */  {NULL, NULL},
-  /* 0x15 */  {NULL, NULL},
-  /* 0x16 */  {NULL, NULL},
-  /* 0x17 */  {NULL, NULL},
-  /* 0x18 */  {NULL, NULL},
-  /* 0x19 */  {NULL, NULL},
-  /* 0x1a */  {NULL, NULL},
-  /* 0x1b */  {NULL, NULL},
-  /* 0x1c */  {NULL, NULL},
-  /* 0x1d */  {NULL, NULL},
-  /* 0x1e */  {NULL, NULL},
-  /* 0x1f */  {NULL, NULL},
-  /* 0x20 */  {NULL, NULL},
-  /* 0x21 */  {NULL, NULL},
-  /* 0x22 */  {NULL, NULL},
-  /* 0x23 */  {NULL, NULL},
-  /* 0x24 */  {NULL, NULL},
-  /* 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 */  {NULL, NULL},
-  /* 0x2d */  {NULL, NULL},
-  /* 0x2e */  {NULL, NULL},
-  /* 0x2f */  {NULL, NULL},
-  /* 0x30 */  {NULL, NULL},
-  /* 0x31 */  {NULL, NULL},
-  /* 0x32 */  {NULL, NULL},
-  /* 0x33 */  {NULL, NULL},
-  /* 0x34 */  {NULL, NULL},
-  /* 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 */  {NULL, NULL},
-  /* 0x74 */  {NULL, NULL},
-  /* 0x75 */  {NULL, NULL},
-  /* 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 */  {NULL, NULL},
-  /* 0x81 */  {NULL, NULL},
-  /* 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 */  {NULL, NULL},
-  /* 0xa1 */  {NULL, NULL},
-  /* 0xa2 */  {NULL, NULL},
-  /* 0xa3 */  {NULL, NULL},
-  /* 0xa4 */  {NULL, NULL},
-  /* 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 */  {NULL, NULL},
-  /* 0xc1 */  {NULL, NULL},
-  /* 0xc2 */  {NULL, NULL},
-  /* 0xc3 */  {NULL, NULL},
-  /* 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},
-};
+       /* granted access */
+       offset = dissect_access(tvb, pinfo, tree, offset, "Granted");
+
+       BYTE_COUNT;
 
+       END_OF_SMB
+
+       return offset;
+}
 
 static int
-dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree, int offset, proto_tree *smb_tree, guint8 cmd)
+dissect_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-       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);
+       guint8 wc;
+       guint16 bc;
 
-               if (check_col(pinfo->fd, COL_INFO)) {
-                       col_add_fstr(pinfo->fd, COL_INFO, "%s %s",
-                               decode_smb_name(cmd),
-                               (si->request)? "Request" : "Response");
-               }
+       WORD_COUNT;
 
-               cmd_item = proto_tree_add_text(smb_tree, tvb, offset,
-                       0, "%s %s (0x%02x)",
-                       decode_smb_name(cmd), 
-                       (si->request)?"Request":"Response",
-                       cmd);
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-               cmd_tree = proto_item_add_subtree(cmd_item, ett_smb_command);
+       BYTE_COUNT;
 
-               dissector = (si->request)?
-                       smb_dissector[cmd].request:smb_dissector[cmd].response;
+       END_OF_SMB
 
-               if(dissector){
-                       offset = (*dissector)(tvb, pinfo, cmd_tree, offset, smb_tree);
-               }
-               proto_item_set_len(cmd_item, offset-old_offset);
+       return offset;
+}
+
+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;
+
+       WORD_COUNT;
+
+       /* file attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
+
+       /* creation time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
+
+       BYTE_COUNT;
+
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
+
+       /* File Name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
+
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
        }
+
+       END_OF_SMB
+
        return offset;
 }
 
+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;
 
-/* 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 },
-};
+       WORD_COUNT;
 
-static char *decode_smb_name(unsigned char cmd)
-{
-  return(smb_cmd_vals[cmd].strptr);
-}
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
 
-/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- * Everything TVBUFFIFIED above this line
- * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+       BYTE_COUNT;
 
+       END_OF_SMB
 
-/*
- * Struct passed to each SMB decode routine of info it may need
- */
+       return offset;
+}
 
+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;
 
-int smb_packet_init_count = 200;
+       WORD_COUNT;
 
-/*
- * This is a hash table matching transaction requests and replies.
- *
- * Unfortunately, the MID is not a transaction ID in, say, the ONC RPC
- * sense; instead, it's a "multiplex ID" used when there's more than one
- * request *currently* in flight, to distinguish replies.
- *
- * This means that the MID and PID don't uniquely identify a request in
- * a conversation.
- *
- * Therefore, we have to use some other value to distinguish between
- * requests with the same MID and PID.
- *
- * On the first pass through the capture, when we first see a request,
- * we hash it by conversation, MID, and PID.
- *
- * When we first see a reply to it, we add it to a new hash table,
- * hashing it by conversation, MID, PID, and frame number of the reply.
- *
- * This works as long as
- *
- *     1) a client doesn't screw up and have multiple requests outstanding
- *        with the same MID and PID
- *
- * and
- *
- *     2) we don't have, within the same frame, replies to multiple
- *        requests with the same MID and PID.
- *
- * 2) should happen only if the server screws up and puts the wrong MID or
- * PID into a reply (in which case not only can we not handle this, the
- * client can't handle it either) or if the client has screwed up as per
- * 1) and the server's dutifully replied to both of the requests with the
- * same MID and PID (in which case, again, neither we nor the client can
- * handle this).
- *
- * We don't have to correctly dissect screwups; we just have to keep from
- * dumping core on them.
- *
- * XXX - in addition, we need to keep a hash table of replies, so that we
- * can associate continuations with the reply to which they're a continuation.
- */
-struct smb_request_key {
-  guint32 conversation;
-  guint16 mid;
-  guint16 pid;
-  guint32 frame_num;
-};
+       /* search attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-static GHashTable *smb_request_hash = NULL;
-static GMemChunk *smb_request_keys = NULL;
-static GMemChunk *smb_request_vals = NULL;
+       BYTE_COUNT;
 
-/*
- * This is a hash table matching continued transation replies and their
- * continuations.
- *
- * It works similarly to the request/reply hash table.
- */
-static GHashTable *smb_continuation_hash = NULL;
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-static GMemChunk *smb_continuation_vals = NULL;
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
-/* Hash Functions */
-static gint
-smb_equal(gconstpointer v, gconstpointer w)
-{
-  struct smb_request_key *v1 = (struct smb_request_key *)v;
-  struct smb_request_key *v2 = (struct smb_request_key *)w;
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-#if defined(DEBUG_SMB_HASH)
-  printf("Comparing %08X:%u:%u:%u\n      and %08X:%u:%u:%u\n",
-        v1 -> conversation, v1 -> mid, v1 -> pid, v1 -> frame_num,
-        v2 -> conversation, v2 -> mid, v2 -> pid, v2 -> frame_num);
-#endif
+       END_OF_SMB
 
-  if (v1 -> conversation == v2 -> conversation &&
-      v1 -> mid          == v2 -> mid &&
-      v1 -> pid          == v2 -> pid &&
-      v1 -> frame_num    == v2 -> frame_num) {
+       return offset;
+}
 
-    return 1;
+static int
+dissect_rename_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;
 
-  return 0;
-}
+       /* file attributes */
+       offset = dissect_search_attributes(tvb, pinfo, tree, offset);
 
-static guint
-smb_hash (gconstpointer v)
-{
-  struct smb_request_key *key = (struct smb_request_key *)v;
-  guint val;
+       BYTE_COUNT;
 
-  val = (key -> conversation) + (key -> mid) + (key -> pid) +
-       (key -> frame_num);
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-#if defined(DEBUG_SMB_HASH)
-  printf("SMB Hash calculated as %u\n", val);
-#endif
+       /* old file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
-  return val;
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Old Name: %s", fn);
+       }
 
-}
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-/*
- * Free up any state information we've saved, and re-initialize the
- * tables of state information.
- */
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
-/*
- * For a hash table entry, free the address data to which the key refers
- * and the fragment data to which the value refers.
- * (The actual key and value structures get freed by "reassemble_init()".)
- */
-static gboolean
-free_request_val_data(gpointer key, gpointer value, gpointer user_data)
-{
-  struct smb_request_val *request_val = value;
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", New Name: %s", fn);
+       }
 
-  if (request_val->last_transact_command != NULL)
-    g_free(request_val->last_transact_command);
-  if (request_val->last_param_descrip != NULL)
-    g_free(request_val->last_param_descrip);
-  if (request_val->last_data_descrip != NULL)
-    g_free(request_val->last_data_descrip);
-  if (request_val->last_aux_data_descrip != NULL)
-    g_free(request_val->last_aux_data_descrip);
-  return TRUE;
+       END_OF_SMB
+
+       return offset;
 }
 
-static struct smb_request_val *
-do_transaction_hashing(conversation_t *conversation, struct smb_info si,
-                      frame_data *fd)
+static int
+dissect_query_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  struct smb_request_key request_key, *new_request_key;
-  struct smb_request_val *request_val = NULL;
-  gpointer               new_request_key_ret, request_val_ret;
+       guint16 bc;
+       guint8 wc;
+       const char *fn;
+       int fn_len;
 
-  if (si.request) {
-    /*
-     * This is a request.
-     *
-     * If this is the first time the frame has been seen, check for
-     * an entry for the request in the hash table.  If it's not found,
-     * insert an entry for it.
-     *
-     * If it's the first time it's been seen, then we can't have seen
-     * the reply yet, so the reply frame number should be 0, for
-     * "unknown".
-     */
-    if (!fd->flags.visited) {
-      request_key.conversation = conversation->index;
-      request_key.mid          = si.mid;
-      request_key.pid          = si.pid;
-      request_key.frame_num    = 0;
+       WORD_COUNT;
 
-      request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key);
+       BYTE_COUNT;
 
-      if (request_val == NULL) {
-       /*
-        * Not found.
-        */
-       new_request_key = g_mem_chunk_alloc(smb_request_keys);
-       new_request_key -> conversation = conversation->index;
-       new_request_key -> mid          = si.mid;
-       new_request_key -> pid          = si.pid;
-       new_request_key -> frame_num    = 0;
+       /* Buffer Format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1,
+               tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-       request_val = g_mem_chunk_alloc(smb_request_vals);
-       request_val -> frame = fd->num;
-       request_val -> last_transact2_command = -1;             /* unknown */
-       request_val -> last_transact_command = NULL;
-       request_val -> last_param_descrip = NULL;
-       request_val -> last_data_descrip = NULL;
-       request_val -> last_aux_data_descrip = NULL;
+       /* File Name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
-       g_hash_table_insert(smb_request_hash, new_request_key, request_val);
-      } else {
-       /*
-        * This means that we've seen another request in this conversation
-        * with the same request and reply, and without an intervening
-        * reply to that first request, and thus won't be using this
-        * "request_val" structure for that request (as we'd use it only
-        * for the reply).
-        *
-        * Clean out the structure, and set it to refer to this frame.
-        */
-       request_val -> frame = fd->num;
-       request_val -> last_transact2_command = -1;             /* unknown */
-       if (request_val -> last_transact_command)
-         g_free(request_val -> last_transact_command);
-       request_val -> last_transact_command = NULL;
-       if (request_val -> last_param_descrip)
-         g_free(request_val -> last_param_descrip);
-       request_val -> last_param_descrip = NULL;
-       if (request_val -> last_data_descrip)
-         g_free(request_val -> last_data_descrip);
-       request_val -> last_data_descrip = NULL;
-       if (request_val -> last_aux_data_descrip)
-         g_free(request_val -> last_aux_data_descrip);
-       request_val -> last_aux_data_descrip = NULL;
-      }
-    }
-  } else {
-    /*
-     * This is a reply.
-     */
-    if (!fd->flags.visited) {
-      /*
-       * This is the first time the frame has been seen; check for
-       * an entry for a matching request, with an unknown reply frame
-       * number, in the hash table.
-       *
-       * If we find it, re-hash it with this frame's number as the
-       * reply frame number.
-       */
-      request_key.conversation = conversation->index;
-      request_key.mid          = si.mid;
-      request_key.pid          = si.pid;
-      request_key.frame_num    = 0;
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-      /*
-       * Look it up - and, if we find it, get pointers to the key and
-       * value structures for it.
-       */
-      if (g_hash_table_lookup_extended(smb_request_hash, &request_key,
-                                      &new_request_key_ret,
-                                      &request_val_ret)) {
-       new_request_key = new_request_key_ret;
-       request_val = request_val_ret;
+       END_OF_SMB
 
-       /*
-        * We found it.
-        * Remove the old entry.
-        */
-       g_hash_table_remove(smb_request_hash, &request_key);
+       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;
 
-       /*
-        * Now update the key, and put it back into the hash table with
-        * the new key.
-        */
-       new_request_key->frame_num = fd->num;
-       g_hash_table_insert(smb_request_hash, new_request_key, request_val);
-      }
-    } else {
-      /*
-       * This is not the first time the frame has been seen; check for
-       * an entry for a matching request, with this frame's frame
-       * number as the reply frame number, in the hash table.
-       */
-      request_key.conversation = conversation->index;
-      request_key.mid          = si.mid;
-      request_key.pid          = si.pid;
-      request_key.frame_num    = fd->num;
+       WORD_COUNT;
 
-      request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key);
-    }
-  }
+       /* File Attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-  return request_val;
+       /* Last Write Time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
+
+       /* File Size */
+       proto_tree_add_uint(tree, hf_smb_file_size, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
+
+       /* 10 reserved bytes */
+       proto_tree_add_bytes(tree, hf_smb_reserved, tvb, offset, 10, tvb_get_ptr(tvb, offset, 10));
+       offset += 10;
+
+       BYTE_COUNT;
+
+       END_OF_SMB
+
+       return offset;
 }
 
-static struct smb_continuation_val *
-do_continuation_hashing(conversation_t *conversation, struct smb_info si,
-                      frame_data *fd, guint16 TotalDataCount,
-                      guint16 DataCount, const char **TransactName)
+static int
+dissect_set_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  struct smb_request_key request_key, *new_request_key;
-  struct smb_continuation_val *continuation_val, *new_continuation_val;
-  gpointer               new_request_key_ret, continuation_val_ret;
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-  continuation_val = NULL;
-  if (si.ddisp != 0) {
-    /*
-     * This reply isn't the first in the series; there should be a
-     * reply of which it is a continuation.
-     */
-    if (!fd->flags.visited) {
-      /*
-       * This is the first time the frame has been seen; check for
-       * an entry for a matching continued message, with an unknown
-       * continuation frame number, in the hash table.
-       *
-       * If we find it, re-hash it with this frame's number as the
-       * continuation frame number.
-       */
-      request_key.conversation = conversation->index;
-      request_key.mid          = si.mid;
-      request_key.pid          = si.pid;
-      request_key.frame_num    = 0;
+       WORD_COUNT;
 
-      /*
-       * Look it up - and, if we find it, get pointers to the key and
-       * value structures for it.
-       */
-      if (g_hash_table_lookup_extended(smb_continuation_hash, &request_key,
-                                      &new_request_key_ret,
-                                      &continuation_val_ret)) {
-       new_request_key = new_request_key_ret;
-       continuation_val = continuation_val_ret;
+       /* file attributes */
+       offset = dissect_file_attributes(tvb, pinfo, tree, offset);
 
-       /*
-        * We found it.
-        * Remove the old entry.
-        */
-       g_hash_table_remove(smb_continuation_hash, &request_key);
+       /* last write time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
 
-       /*
-        * Now update the key, and put it back into the hash table with
-        * the new key.
-        */
-       new_request_key->frame_num = fd->num;
-       g_hash_table_insert(smb_continuation_hash, new_request_key,
-                           continuation_val);
-      }
-    } else {
-      /*
-       * This is not the first time the frame has been seen; check for
-       * an entry for a matching request, with this frame's frame
-       * number as the continuation frame number, in the hash table.
-       */
-      request_key.conversation = conversation->index;
-      request_key.mid          = si.mid;
-      request_key.pid          = si.pid;
-      request_key.frame_num    = fd->num;
+       /* 10 reserved bytes */
+       proto_tree_add_bytes(tree, hf_smb_reserved, tvb, offset, 10, tvb_get_ptr(tvb, offset, 10));
+       offset += 10;
 
-      continuation_val = (struct smb_continuation_val *)
-               g_hash_table_lookup(smb_continuation_hash, &request_key);
-    }
-  }
+       BYTE_COUNT;
 
-  /*
-   * If we found the entry for the message of which this is a continuation,
-   * and our caller cares, get the transaction name for that message, as
-   * it's the transaction name for this message as well.
-   */
-  if (continuation_val != NULL && TransactName != NULL)
-    *TransactName = continuation_val -> transact_name;
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-  if (TotalDataCount > DataCount + si.ddisp) {
-    /*
-     * This reply isn't the last in the series; there should be a
-     * continuation for it later in the capture.
-     *
-     * If this is the first time the frame has been seen, check for
-     * an entry for the reply in the hash table.  If it's not found,
-     * insert an entry for it.
-     *
-     * If it's the first time it's been seen, then we can't have seen
-     * the continuation yet, so the continuation frame number should
-     * be 0, for "unknown".
-     */
-    if (!fd->flags.visited) {
-      request_key.conversation = conversation->index;
-      request_key.mid          = si.mid;
-      request_key.pid          = si.pid;
-      request_key.frame_num    = 0;
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
-      new_continuation_val = (struct smb_continuation_val *)
-               g_hash_table_lookup(smb_continuation_hash, &request_key);
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-      if (new_continuation_val == NULL) {
-       /*
-        * Not found.
-        */
-       new_request_key = g_mem_chunk_alloc(smb_request_keys);
-       new_request_key -> conversation = conversation->index;
-       new_request_key -> mid          = si.mid;
-       new_request_key -> pid          = si.pid;
-       new_request_key -> frame_num    = 0;
+       END_OF_SMB
 
-       new_continuation_val = g_mem_chunk_alloc(smb_continuation_vals);
-       new_continuation_val -> frame = fd->num;
-       if (TransactName != NULL)
-         new_continuation_val -> transact_name = *TransactName;
-       else
-         new_continuation_val -> transact_name = NULL;
+       return offset;
+}
 
-       g_hash_table_insert(smb_continuation_hash, new_request_key,
-                           new_continuation_val);
-      } else {
-       /*
-        * This presumably means we never saw the continuation of
-        * the message we found, and this is a reply to a different
-        * request; as we never saw the continuation of that message,
-        * we won't be using this "request_val" structure for that
-        * message (as we'd use it only for the continuation).
-        *
-        * Clean out the structure, and set it to refer to this frame.
-        */
-       new_continuation_val -> frame = fd->num;
-      }
-    }
-  }
+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;
 
-  return continuation_val;
+       WORD_COUNT;
+
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       /* read count */
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       /* offset */
+       proto_tree_add_uint(tree, hf_smb_offset, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
+
+       /* remaining */
+       proto_tree_add_uint(tree, hf_smb_remaining, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       BYTE_COUNT;
+
+       END_OF_SMB
+
+       return offset;
 }
 
-static void
-smb_init_protocol(void)
+static int
+dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-#if defined(DEBUG_SMB_HASH)
-  printf("Initializing SMB hashtable area\n");
-#endif
+       guint16 cnt=0, bc;
+       guint8 wc;
 
-  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);
+       WORD_COUNT;
 
-  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);
-}
+       /* read count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info si, int, int);
+       /* 8 reserved bytes */
+       proto_tree_add_bytes(tree, hf_smb_reserved, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8));
+       offset += 8;
 
-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)
-{
+       BYTE_COUNT;
 
-  if (tree) {
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
+       bc -= 1;
 
-    proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (%u bytes)", 
-                       END_OF_FRAME); 
+       /* data len */
+       if (bc < 2)
+               return offset;
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+       bc -= 2;
 
-  }
+       if (bc != 0) {
+               /* file data */
+               if(bc>tvb_length_remaining(tvb, offset)){
+                       int len;
+                       len = tvb_length_remaining(tvb, offset);
+                       proto_tree_add_bytes_format(tree, hf_smb_file_data, tvb, offset, len, tvb_get_ptr(tvb, offset, len),"File Data: Incomplete. Only %u of %u bytes", len, bc);
+                       offset += len;
+               } else {
+                       proto_tree_add_bytes(tree, hf_smb_file_data, tvb, offset, bc, tvb_get_ptr(tvb, offset, bc));
+                       offset += bc;
+               }
+       }
 
+       END_OF_SMB
+
+       return offset;
 }
 
-/* 
- * Dissect a UNIX like date ...
- */
+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;
 
-struct tm *_gtime; /* Add leading underscore ("_") to prevent symbol
-                      conflict with /usr/include/time.h on some NetBSD
-                      systems */
+       WORD_COUNT;
 
-static char *
-dissect_smbu_date(guint16 date, guint16 time)
+       /* read count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-{
-  static char         datebuf[4+2+2+2+1+10];
-  time_t              ltime = (date << 16) + time;
+       /* 8 reserved bytes */
+       proto_tree_add_bytes(tree, hf_smb_reserved, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8));
+       offset += 8;
 
-  _gtime = gmtime(&ltime);
+       BYTE_COUNT;
 
-  if (_gtime)
-    sprintf(datebuf, "%04d-%02d-%02d",
-           1900 + (_gtime -> tm_year), 1 + (_gtime -> tm_mon), _gtime -> tm_mday);
-  else 
-    sprintf(datebuf, "Bad date format");
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
+       bc -= 1;
 
-  return datebuf;
+       /* data len */
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       END_OF_SMB
 
+       return offset;
 }
 
-/*
- * Relies on time
- */
-static char *
-dissect_smbu_time(guint16 date, guint16 time)
 
+static int
+dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  static char timebuf[2+2+2+2+1+10];
+       guint16 cnt=0, bc;
+       guint8 wc;
 
-  if (_gtime)
-    sprintf(timebuf, "%02d:%02d:%02d",
-           _gtime -> tm_hour, _gtime -> tm_min, _gtime -> tm_sec);
-  else
-    sprintf(timebuf, "Bad time format");
+       WORD_COUNT;
 
-  return timebuf;
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-}
+       /* write count */
+       cnt = tvb_get_letohs(tvb, offset);
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+       offset += 2;
 
-/*
- * Dissect a DOS-format date.
- */
-static char *
-dissect_dos_date(guint16 date)
+       /* offset */
+       proto_tree_add_uint(tree, hf_smb_offset, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
+
+       /* remaining */
+       proto_tree_add_uint(tree, hf_smb_remaining, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       BYTE_COUNT;
+
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
+       bc -= 1;
+
+       /* data len */
+       if (bc < 2)
+               return offset;
+       proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+       bc -= 2;
+
+       if (bc != 0) {
+               /* file data */
+               if(bc>tvb_length_remaining(tvb, offset)){
+                       int len;
+                       len = tvb_length_remaining(tvb, offset);
+                       proto_tree_add_bytes_format(tree, hf_smb_file_data, tvb, offset, len, tvb_get_ptr(tvb, offset, len),"File Data: Incomplete. Only %d of %d bytes", len, bc);
+                       offset += len;
+               } else {
+                       proto_tree_add_bytes(tree, hf_smb_file_data, tvb, offset, bc, tvb_get_ptr(tvb, offset, bc));
+                       offset += bc;
+               }
+       }
+
+       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)
 {
-       static char datebuf[4+2+2+1];
+       guint8 wc;
+       guint16 bc;
 
-       sprintf(datebuf, "%04d-%02d-%02d",
-           ((date>>9)&0x7F) + 1980, (date>>5)&0x0F, date&0x1F);
-       return datebuf;
+       WORD_COUNT;
+
+       /* write count */
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       BYTE_COUNT;
+
+       END_OF_SMB
+
+       return offset;
 }
 
-/*
- * Dissect a DOS-format time.
- */
-static char *
-dissect_dos_time(guint16 time)
+static int
+dissect_lock_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-       static char timebuf[2+2+2+1];
+       guint8 wc;
+       guint16 bc;
 
-       sprintf(timebuf, "%02d:%02d:%02d",
-           (time>>11)&0x1F, (time>>5)&0x3F, (time&0x1F)*2);
-       return timebuf;
+       WORD_COUNT;
+
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
+
+       /* lock count */
+       proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
+
+       /* offset */
+       proto_tree_add_uint(tree, hf_smb_offset, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
+
+       BYTE_COUNT;
+
+       END_OF_SMB
+
+       return offset;
 }
 
-/* Max string length for displaying Unicode strings.  */
-#define        MAX_UNICODE_STR_LEN     256
+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;
 
-/* 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;
+       WORD_COUNT;
 
-  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 !
-*/
-static gchar *
-unicode_to_str_tvb(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen) {
-  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;
-  while ((uchar = tvb_get_letohs(tvb, offset)) != 0) {
-    if (len > 0) {
-      if ((uchar & 0xFF00) == 0)
-        *p++ = uchar;  /* ISO 8859-1 */
-      else
-        *p++ = '?';    /* not 8859-1 */
-      len--;
-    } else
-      overflow = 1;
-    offset += 2;
-    us_len += 2;
-    if(exactlen){
-      if(us_len>= *us_lenp){
-        break;
-      }
-    }
-  }
-  if (overflow) {
-    /* Note that we're not showing the full string.  */
-    *p++ = '.';
-    *p++ = '.';
-    *p++ = '.';
-  }
-  *p = '\0';
-  *us_lenp = us_len;
-  return cur;
-}
+       /* 2 reserved bytes */
+       proto_tree_add_bytes(tree, hf_smb_reserved, tvb, offset, 2, tvb_get_ptr(tvb, offset, 2));
+       offset += 2;
 
-/* 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;
+       /* Creation time */
+       offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
 
-  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;
-}
+       BYTE_COUNT;
 
-/* nopad == TRUE : Do not add any padding before this string
- * exactlen == TRUE : len contains the exact len of the string in bytes.
- */
-static const gchar *
-get_unicode_or_ascii_string_tvb(tvbuff_t *tvb, int *offsetp, packet_info *pinfo, int *len, gboolean nopad, gboolean exactlen)
-{
-  int offset = *offsetp;
-  const gchar *string;
-  int string_len;
-  smb_info_t *si;
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-  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 */
-    }
-    if(exactlen){
-      string_len = *len;
-      string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen);
-    } else {
-      string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen);
-      string_len += 2;
-    }
-  } else {
-    if(exactlen){
-      string = tvb_get_ptr(tvb, *offsetp, *len);
-      string_len = *len;
-    } else {
-      string_len = tvb_strsize(tvb, *offsetp);
-      string = tvb_get_ptr(tvb, *offsetp, string_len);
-    }
-  }
-  *len = string_len;
-  return string;
-}
+       /* directory name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_append_fstr(pinfo->fd, COL_INFO, ", Path: %s", fn);
+       }
 
-/*
- * Each dissect routine is passed an offset to wct and works from there 
- */
+       END_OF_SMB
 
-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)
+       return offset;
+}
 
+static int
+dissect_create_temporary_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
-  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) */
+       int fn_len;
+       const char *fn;
+       guint8 wc;
+       guint16 bc;
 
-    /* Build display for: FID */
+       WORD_COUNT;
 
-    FID = GSHORT(pd, offset);
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-    if (tree) {
+       BYTE_COUNT;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       /* buffer format */
+       proto_tree_add_uint(tree, hf_smb_buffer_format, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+       offset += 1;
 
-    }
+       /* file name */
+       fn = get_unicode_or_ascii_string_tvb(tvb, &offset, pinfo, &fn_len, FALSE, FALSE);
+       proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+               fn);
+       offset += fn_len;
 
-    offset += 2; /* Skip FID */
+       END_OF_SMB
 
-    /* Build display for: Byte Count */
+       return offset;
+}
 
-    ByteCount = GSHORT(pd, offset);
+static const value_string seek_mode_vals[] = {
+       {0,     "From Start Of File"},
+       {1,     "From Current Position"},
+       {2,     "From End Of File"},
+       {0,     NULL}
+};
 
-    if (tree) {
+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;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+       WORD_COUNT;
 
-    }
+       /* fid */
+       proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-    offset += 2; /* Skip Byte Count */
+       /* Seek Mode */
+       proto_tree_add_uint(tree, hf_smb_seek_mode, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+       offset += 2;
 
-  } else {
-    /* Response(s) dissect code */
+       /* offset */
+       proto_tree_add_uint(tree, hf_smb_offset, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
 
-    /* Build display for: Word Count (WCT) */
+       BYTE_COUNT;
 
-    WordCount = GBYTE(pd, offset);
+       END_OF_SMB
 
-    if (tree) {
+       return offset;
+}
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+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;
 
-    }
+       WORD_COUNT;
 
-    offset += 1; /* Skip Word Count (WCT) */
+       /* offset */
+       proto_tree_add_uint(tree, hf_smb_offset, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+       offset += 4;
 
-    /* Build display for: Byte Count (BCC) */
+       BYTE_COUNT;
 
-    ByteCount = GSHORT(pd, offset);
+       END_OF_SMB
 
-    if (tree) {
+       return offset;
+}
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-    }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+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;
 
-  }
-
-}
-
-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)
-
-{
-  guint8        WordCount;
-  guint16       TotalUnits;
-  guint16       Reserved;
-  guint16       FreeUnits;
-  guint16       ByteCount;
-  guint16       BlocksPerUnit;
-  guint16       BlockSize;
-
-  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) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Total Units */
-
-      TotalUnits = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Total Units: %u", TotalUnits);
-
-      }
-
-      offset += 2; /* Skip Total Units */
-
-      /* Build display for: Blocks Per Unit */
-
-      BlocksPerUnit = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Blocks Per Unit: %u", BlocksPerUnit);
-
-      }
-
-      offset += 2; /* Skip Blocks Per Unit */
-
-      /* Build display for: Block Size */
-
-      BlockSize = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Block Size: %u", BlockSize);
-
-      }
-
-      offset += 2; /* Skip Block Size */
-
-      /* Build display for: Free Units */
-
-      FreeUnits = GSHORT(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Free Units: %u", FreeUnits);
-
-      }
-
-      offset += 2; /* Skip Free Units */
-
-      /* 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) */
-
-  }
-
-}
-
-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)
-
-{
-  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;
-
-  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) */
-
-    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) {
-
-       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: 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) */
-
-    /* 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) */
-
-    /* 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) */
-
-  }
-
-}
-
-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)
-
-{
-  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 */
-
-    if (DataLength > 0 && tree) {
-
-       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);
-
-    }
-
-  } 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_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)
-
-{
-  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 */
-
-    /* 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: Reserved 1 */
-
-    Reserved1 = GWORD(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 1: %u", Reserved1);
-
-    }
-
-    offset += 4; /* 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: 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 */
-
-    if (WordCount != 0) {
-
-      /* 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: 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 */
-
-      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 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: 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 */
-
-  }
-
-}
-
-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)
-
-{
-  guint8        WordCount;
-  guint8        BufferFormat;
-  guint16       SearchAttributes;
-  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: SearchAttributes */
-
-    SearchAttributes = GSHORT(pd, offset);
-
-    if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
-    }
-
-    offset += 2; /* Skip SearchAttributes */
-
-    /* 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) */
-
-    /* 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_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)
-
-{
-  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 */
-
-    /* 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 */
-
-    ByteCount = GSHORT(pd, offset);
-
-    if (tree) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
-
-    }
-
-    offset += 2; /* Skip Byte Count */
-
-  } 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: 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: File Data Size */
-
-      FileDataSize = GWORD(pd, offset);
-
-      if (tree) {
-       
-       proto_tree_add_text(tree, NullTVB, offset, 4, "File Data Size: %u", FileDataSize);
-
-      }
-
-      offset += 4; /* Skip File Data Size */
-
-      /* Build display for: File Allocation Size */
-
-      FileAllocationSize = GWORD(pd, offset);
-
-      if (tree) {
-
-       proto_tree_add_text(tree, NullTVB, offset, 4, "File Allocation Size: %u", FileAllocationSize);
-
-      }
-
-      offset += 4; /* Skip File Allocation Size */
-
-      /* 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: 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 */
-
-  }
-
-}
-
-/* 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)
-
-{
-  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) {
-
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
-
-    }
-
-    offset += 1; /* Skip Word Count (WCT) */
-
-    switch (WordCount) {
-
-    case 10:
-
-      /* 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: MaxBufferSize */
-
-      MaxBufferSize = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
-
-      }
-
-      offset += 2; /* Skip MaxBufferSize */
-
-      /* Build display for: MaxMpxCount */
-
-      MaxMpxCount = GSHORT(pd, offset);
-
-      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);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
-
-      }
-
-      offset += 2; /* Skip VcNumber */
-
-      /* Build display for: SessionKey */
-
-      SessionKey = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
-
-      }
-
-      offset += 4; /* Skip SessionKey */
-
-      /* Build display for: PasswordLen */
-
-      PasswordLen = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "PasswordLen: %u", PasswordLen);
-
-      }
-
-      offset += 2; /* Skip PasswordLen */
-
-      /* 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: 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 (ByteCount > 0) {
-
-       /* Build display for: Password */
-
-        Password = pd + offset;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, strlen(Password) + 1, "Password: %s", Password);
-
-       }
-
-       offset += PasswordLen;
-
-       /* Build display for: AccountName */
-
-       AccountName = pd + offset;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, strlen(AccountName) + 1, "AccountName: %s", AccountName);
-
-       }
-
-       offset += strlen(AccountName) + 1; /* Skip AccountName */
-
-       /* Build display for: PrimaryDomain */
-
-       PrimaryDomain = pd + offset;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
-
-       }
-
-       offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
-
-       /* Build display for: NativeOS */
-
-       NativeOS = pd + offset;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
-
-       }
-
-       offset += strlen(NativeOS) + 1; /* Skip NativeOS */
-
-       /* Build display for: NativeLanMan */
-
-       NativeLanMan = pd + offset;
-
-       if (tree) {
-
-         proto_tree_add_text(tree, NullTVB, offset, strlen(NativeLanMan) + 1, "Native Lan Manager: %s", NativeLanMan);
-
-       }
-
-       offset += strlen(NativeLanMan) + 1; /* Skip NativeLanMan */
-
-      }
-
-      break;
-
-    case 12:
-
-      /* 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: MaxBufferSize */
-
-      MaxBufferSize = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
-
-      }
-
-      offset += 2; /* Skip MaxBufferSize */
-
-      /* Build display for: MaxMpxCount */
-
-      MaxMpxCount = GSHORT(pd, offset);
-
-      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);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
-
-      }
-
-      offset += 2; /* Skip VcNumber */
-
-      /* Build display for: SessionKey */
-
-      SessionKey = GWORD(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
-
-      }
-
-      offset += 4; /* Skip SessionKey */
-
-      /* Build display for: Security Blob Length */
-
-      SecurityBlobLength = GSHORT(pd, offset);
-
-      if (tree) {
-
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Security Blob Length: %u", SecurityBlobLength);
-
-      }
-
-      offset += 2; /* Skip Security Blob Length */
-
-      /* 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: Capabilities */
-
-      Capabilities = GWORD(pd, offset);
-
-      if (tree) {
-
-        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"));
-
-      }
-
-      offset += 4; /* Skip Capabilities */
-
-      /* 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 (ByteCount > 0) {
-
-        /* Build display for: Security Blob */
-
-        SecurityBlob = pd + offset;
-
-        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? */
-
-          if (tree) {
-
-            proto_tree_add_text(tree, NullTVB, offset, SecurityBlobLength, "Security Blob: %s",
-                                bytes_to_str(SecurityBlob, SecurityBlobLength));
-
-          }
-
-          offset += SecurityBlobLength; /* Skip Security Blob */
-
-        }
-
-        /* Build display for: Native OS */
-
-        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, "Native OS: %s", NativeOS);
-
-        }
-
-        offset += string_len; /* Skip Native OS */
-
-        /* Build display for: Native LanMan Type */
-
-        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);
-
-        }
-
-        offset += string_len; /* Skip Native LanMan Type */
-
-        /* Build display for: Primary Domain */
-
-        PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-        if (tree) {
-
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "Primary Domain: %s", PrimaryDomain);
-
-        }
-
-        offset += string_len; /* Skip Primary Domain */
-
-      }
-
-      break;
-
-    case 13:
-
-      /* 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);
+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 */  {NULL, NULL},
+  /* 0x1b */  {NULL, NULL},
+  /* 0x1c */  {NULL, NULL},
+  /* 0x1d */  {NULL, NULL},
+  /* 0x1e */  {NULL, NULL},
+  /* 0x1f */  {NULL, NULL},
+  /* 0x20 */  {NULL, NULL},
+  /* 0x21 */  {NULL, NULL},
+  /* 0x22 */  {NULL, NULL},
+  /* 0x23 */  {NULL, NULL},
+  /* 0x24 */  {NULL, NULL},
+  /* 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 */  {NULL, NULL},
+  /* 0x2d */  {NULL, NULL},
+  /* 0x2e */  {NULL, NULL},
+  /* 0x2f */  {NULL, NULL},
+  /* 0x30 */  {NULL, NULL},
+  /* 0x31 */  {NULL, NULL},
+  /* 0x32 */  {NULL, NULL},
+  /* 0x33 */  {NULL, NULL},
+  /* 0x34 */  {NULL, NULL},
+  /* 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 */  {NULL, NULL},
+  /* 0x74 */  {NULL, NULL},
+  /* 0x75 */  {NULL, NULL},
+  /* 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 */  {NULL, NULL},
+  /* 0x81 */  {NULL, NULL},
+  /* 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 */  {NULL, NULL},
+  /* 0xa1 */  {NULL, NULL},
+  /* 0xa2 */  {NULL, NULL},
+  /* 0xa3 */  {NULL, NULL},
+  /* 0xa4 */  {NULL, NULL},
+  /* 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 */  {NULL, NULL},
+  /* 0xc1 */  {NULL, NULL},
+  /* 0xc2 Close Print File*/  {dissect_fid, dissect_empty},
+  /* 0xc3 */  {NULL, NULL},
+  /* 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},
+};
 
-      }
+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);
 
-      offset += 1; /* Skip AndXReserved */
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_add_fstr(pinfo->fd, COL_INFO, "%s %s",
+                               decode_smb_name(cmd),
+                               (si->request)? "Request" : "Response");
+               }
 
-      /* Build display for: AndXOffset */
+               cmd_item = proto_tree_add_text(smb_tree, tvb, offset,
+                       0, "%s %s (0x%02x)",
+                       decode_smb_name(cmd), 
+                       (si->request)?"Request":"Response",
+                       cmd);
 
-      AndXOffset = GSHORT(pd, offset);
+               cmd_tree = proto_item_add_subtree(cmd_item, ett_smb_command);
 
-      if (tree) {
+               dissector = (si->request)?
+                       smb_dissector[cmd].request:smb_dissector[cmd].response;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+               if(dissector){
+                       offset = (*dissector)(tvb, pinfo, cmd_tree, offset, smb_tree);
+               }
+               proto_item_set_len(cmd_item, offset-old_offset);
+       }
+       return offset;
+}
 
-      }
 
-      offset += 2; /* Skip AndXOffset */
+/* 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 },
+};
 
-      /* Build display for: MaxBufferSize */
+static char *decode_smb_name(unsigned char cmd)
+{
+  return(smb_cmd_vals[cmd].strptr);
+}
 
-      MaxBufferSize = GSHORT(pd, offset);
 
-      if (tree) {
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ * Everything TVBUFFIFIED above this line
+ * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
 
-      }
+/*
+ * Struct passed to each SMB decode routine of info it may need
+ */
 
-      offset += 2; /* Skip MaxBufferSize */
 
-      /* Build display for: MaxMpxCount */
+int smb_packet_init_count = 200;
 
-      MaxMpxCount = GSHORT(pd, offset);
+/*
+ * This is a hash table matching transaction requests and replies.
+ *
+ * Unfortunately, the MID is not a transaction ID in, say, the ONC RPC
+ * sense; instead, it's a "multiplex ID" used when there's more than one
+ * request *currently* in flight, to distinguish replies.
+ *
+ * This means that the MID and PID don't uniquely identify a request in
+ * a conversation.
+ *
+ * Therefore, we have to use some other value to distinguish between
+ * requests with the same MID and PID.
+ *
+ * On the first pass through the capture, when we first see a request,
+ * we hash it by conversation, MID, and PID.
+ *
+ * When we first see a reply to it, we add it to a new hash table,
+ * hashing it by conversation, MID, PID, and frame number of the reply.
+ *
+ * This works as long as
+ *
+ *     1) a client doesn't screw up and have multiple requests outstanding
+ *        with the same MID and PID
+ *
+ * and
+ *
+ *     2) we don't have, within the same frame, replies to multiple
+ *        requests with the same MID and PID.
+ *
+ * 2) should happen only if the server screws up and puts the wrong MID or
+ * PID into a reply (in which case not only can we not handle this, the
+ * client can't handle it either) or if the client has screwed up as per
+ * 1) and the server's dutifully replied to both of the requests with the
+ * same MID and PID (in which case, again, neither we nor the client can
+ * handle this).
+ *
+ * We don't have to correctly dissect screwups; we just have to keep from
+ * dumping core on them.
+ *
+ * XXX - in addition, we need to keep a hash table of replies, so that we
+ * can associate continuations with the reply to which they're a continuation.
+ */
+struct smb_request_key {
+  guint32 conversation;
+  guint16 mid;
+  guint16 pid;
+  guint32 frame_num;
+};
 
-      if (tree) {
+static GHashTable *smb_request_hash = NULL;
+static GMemChunk *smb_request_keys = NULL;
+static GMemChunk *smb_request_vals = NULL;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
+/*
+ * This is a hash table matching continued transation replies and their
+ * continuations.
+ *
+ * It works similarly to the request/reply hash table.
+ */
+static GHashTable *smb_continuation_hash = NULL;
 
-      }
+static GMemChunk *smb_continuation_vals = NULL;
 
-      offset += 2; /* Skip MaxMpxCount */
+/* Hash Functions */
+static gint
+smb_equal(gconstpointer v, gconstpointer w)
+{
+  struct smb_request_key *v1 = (struct smb_request_key *)v;
+  struct smb_request_key *v2 = (struct smb_request_key *)w;
 
-      /* Build display for: VcNumber */
+#if defined(DEBUG_SMB_HASH)
+  printf("Comparing %08X:%u:%u:%u\n      and %08X:%u:%u:%u\n",
+        v1 -> conversation, v1 -> mid, v1 -> pid, v1 -> frame_num,
+        v2 -> conversation, v2 -> mid, v2 -> pid, v2 -> frame_num);
+#endif
 
-      VcNumber = GSHORT(pd, offset);
+  if (v1 -> conversation == v2 -> conversation &&
+      v1 -> mid          == v2 -> mid &&
+      v1 -> pid          == v2 -> pid &&
+      v1 -> frame_num    == v2 -> frame_num) {
 
-      if (tree) {
+    return 1;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
+  }
 
-      }
+  return 0;
+}
 
-      offset += 2; /* Skip VcNumber */
+static guint
+smb_hash (gconstpointer v)
+{
+  struct smb_request_key *key = (struct smb_request_key *)v;
+  guint val;
 
-      /* Build display for: SessionKey */
+  val = (key -> conversation) + (key -> mid) + (key -> pid) +
+       (key -> frame_num);
 
-      SessionKey = GWORD(pd, offset);
+#if defined(DEBUG_SMB_HASH)
+  printf("SMB Hash calculated as %u\n", val);
+#endif
 
-      if (tree) {
+  return val;
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
+}
 
-      }
+/*
+ * Free up any state information we've saved, and re-initialize the
+ * tables of state information.
+ */
 
-      offset += 4; /* Skip SessionKey */
+/*
+ * For a hash table entry, free the address data to which the key refers
+ * and the fragment data to which the value refers.
+ * (The actual key and value structures get freed by "reassemble_init()".)
+ */
+static gboolean
+free_request_val_data(gpointer key, gpointer value, gpointer user_data)
+{
+  struct smb_request_val *request_val = value;
 
-      /* Build display for: ANSI Account Password Length */
+  if (request_val->last_transact_command != NULL)
+    g_free(request_val->last_transact_command);
+  if (request_val->last_param_descrip != NULL)
+    g_free(request_val->last_param_descrip);
+  if (request_val->last_data_descrip != NULL)
+    g_free(request_val->last_data_descrip);
+  if (request_val->last_aux_data_descrip != NULL)
+    g_free(request_val->last_aux_data_descrip);
+  return TRUE;
+}
 
-      ANSIAccountPasswordLength = GSHORT(pd, offset);
+static struct smb_request_val *
+do_transaction_hashing(conversation_t *conversation, struct smb_info si,
+                      frame_data *fd)
+{
+  struct smb_request_key request_key, *new_request_key;
+  struct smb_request_val *request_val = NULL;
+  gpointer               new_request_key_ret, request_val_ret;
 
-      if (tree) {
+  if (si.request) {
+    /*
+     * This is a request.
+     *
+     * If this is the first time the frame has been seen, check for
+     * an entry for the request in the hash table.  If it's not found,
+     * insert an entry for it.
+     *
+     * If it's the first time it's been seen, then we can't have seen
+     * the reply yet, so the reply frame number should be 0, for
+     * "unknown".
+     */
+    if (!fd->flags.visited) {
+      request_key.conversation = conversation->index;
+      request_key.mid          = si.mid;
+      request_key.pid          = si.pid;
+      request_key.frame_num    = 0;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "ANSI Account Password Length: %u", ANSIAccountPasswordLength);
+      request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key);
 
-      }
+      if (request_val == NULL) {
+       /*
+        * Not found.
+        */
+       new_request_key = g_mem_chunk_alloc(smb_request_keys);
+       new_request_key -> conversation = conversation->index;
+       new_request_key -> mid          = si.mid;
+       new_request_key -> pid          = si.pid;
+       new_request_key -> frame_num    = 0;
 
-      offset += 2; /* Skip ANSI Account Password Length */
+       request_val = g_mem_chunk_alloc(smb_request_vals);
+       request_val -> frame = fd->num;
+       request_val -> last_transact2_command = -1;             /* unknown */
+       request_val -> last_transact_command = NULL;
+       request_val -> last_param_descrip = NULL;
+       request_val -> last_data_descrip = NULL;
+       request_val -> last_aux_data_descrip = NULL;
 
-      /* Build display for: UNICODE Account Password Length */
+       g_hash_table_insert(smb_request_hash, new_request_key, request_val);
+      } else {
+       /*
+        * This means that we've seen another request in this conversation
+        * with the same request and reply, and without an intervening
+        * reply to that first request, and thus won't be using this
+        * "request_val" structure for that request (as we'd use it only
+        * for the reply).
+        *
+        * Clean out the structure, and set it to refer to this frame.
+        */
+       request_val -> frame = fd->num;
+       request_val -> last_transact2_command = -1;             /* unknown */
+       if (request_val -> last_transact_command)
+         g_free(request_val -> last_transact_command);
+       request_val -> last_transact_command = NULL;
+       if (request_val -> last_param_descrip)
+         g_free(request_val -> last_param_descrip);
+       request_val -> last_param_descrip = NULL;
+       if (request_val -> last_data_descrip)
+         g_free(request_val -> last_data_descrip);
+       request_val -> last_data_descrip = NULL;
+       if (request_val -> last_aux_data_descrip)
+         g_free(request_val -> last_aux_data_descrip);
+       request_val -> last_aux_data_descrip = NULL;
+      }
+    }
+  } else {
+    /*
+     * This is a reply.
+     */
+    if (!fd->flags.visited) {
+      /*
+       * This is the first time the frame has been seen; check for
+       * an entry for a matching request, with an unknown reply frame
+       * number, in the hash table.
+       *
+       * If we find it, re-hash it with this frame's number as the
+       * reply frame number.
+       */
+      request_key.conversation = conversation->index;
+      request_key.mid          = si.mid;
+      request_key.pid          = si.pid;
+      request_key.frame_num    = 0;
 
-      UNICODEAccountPasswordLength = GSHORT(pd, offset);
+      /*
+       * Look it up - and, if we find it, get pointers to the key and
+       * value structures for it.
+       */
+      if (g_hash_table_lookup_extended(smb_request_hash, &request_key,
+                                      &new_request_key_ret,
+                                      &request_val_ret)) {
+       new_request_key = new_request_key_ret;
+       request_val = request_val_ret;
 
-      if (tree) {
+       /*
+        * We found it.
+        * Remove the old entry.
+        */
+       g_hash_table_remove(smb_request_hash, &request_key);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "UNICODE Account Password Length: %u", UNICODEAccountPasswordLength);
+       /*
+        * Now update the key, and put it back into the hash table with
+        * the new key.
+        */
+       new_request_key->frame_num = fd->num;
+       g_hash_table_insert(smb_request_hash, new_request_key, request_val);
+      }
+    } else {
+      /*
+       * This is not the first time the frame has been seen; check for
+       * an entry for a matching request, with this frame's frame
+       * number as the reply frame number, in the hash table.
+       */
+      request_key.conversation = conversation->index;
+      request_key.mid          = si.mid;
+      request_key.pid          = si.pid;
+      request_key.frame_num    = fd->num;
 
-      }
+      request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key);
+    }
+  }
 
-      offset += 2; /* Skip UNICODE Account Password Length */
+  return request_val;
+}
 
-      /* Build display for: Reserved */
+static struct smb_continuation_val *
+do_continuation_hashing(conversation_t *conversation, struct smb_info si,
+                      frame_data *fd, guint16 TotalDataCount,
+                      guint16 DataCount, const char **TransactName)
+{
+  struct smb_request_key request_key, *new_request_key;
+  struct smb_continuation_val *continuation_val, *new_continuation_val;
+  gpointer               new_request_key_ret, continuation_val_ret;
 
-      Reserved = GWORD(pd, offset);
+  continuation_val = NULL;
+  if (si.ddisp != 0) {
+    /*
+     * This reply isn't the first in the series; there should be a
+     * reply of which it is a continuation.
+     */
+    if (!fd->flags.visited) {
+      /*
+       * This is the first time the frame has been seen; check for
+       * an entry for a matching continued message, with an unknown
+       * continuation frame number, in the hash table.
+       *
+       * If we find it, re-hash it with this frame's number as the
+       * continuation frame number.
+       */
+      request_key.conversation = conversation->index;
+      request_key.mid          = si.mid;
+      request_key.pid          = si.pid;
+      request_key.frame_num    = 0;
 
-      if (tree) {
+      /*
+       * Look it up - and, if we find it, get pointers to the key and
+       * value structures for it.
+       */
+      if (g_hash_table_lookup_extended(smb_continuation_hash, &request_key,
+                                      &new_request_key_ret,
+                                      &continuation_val_ret)) {
+       new_request_key = new_request_key_ret;
+       continuation_val = continuation_val_ret;
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
+       /*
+        * We found it.
+        * Remove the old entry.
+        */
+       g_hash_table_remove(smb_continuation_hash, &request_key);
 
+       /*
+        * Now update the key, and put it back into the hash table with
+        * the new key.
+        */
+       new_request_key->frame_num = fd->num;
+       g_hash_table_insert(smb_continuation_hash, new_request_key,
+                           continuation_val);
       }
+    } else {
+      /*
+       * This is not the first time the frame has been seen; check for
+       * an entry for a matching request, with this frame's frame
+       * number as the continuation frame number, in the hash table.
+       */
+      request_key.conversation = conversation->index;
+      request_key.mid          = si.mid;
+      request_key.pid          = si.pid;
+      request_key.frame_num    = fd->num;
 
-      offset += 4; /* Skip Reserved */
-
-      /* Build display for: Capabilities */
-
-      Capabilities = GWORD(pd, offset);
-
-      if (tree) {
-
-        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"));
-      
-      }
+      continuation_val = (struct smb_continuation_val *)
+               g_hash_table_lookup(smb_continuation_hash, &request_key);
+    }
+  }
 
-      offset += 4; /* Skip Capabilities */
+  /*
+   * If we found the entry for the message of which this is a continuation,
+   * and our caller cares, get the transaction name for that message, as
+   * it's the transaction name for this message as well.
+   */
+  if (continuation_val != NULL && TransactName != NULL)
+    *TransactName = continuation_val -> transact_name;
 
-      /* Build display for: Byte Count */
+  if (TotalDataCount > DataCount + si.ddisp) {
+    /*
+     * This reply isn't the last in the series; there should be a
+     * continuation for it later in the capture.
+     *
+     * If this is the first time the frame has been seen, check for
+     * an entry for the reply in the hash table.  If it's not found,
+     * insert an entry for it.
+     *
+     * If it's the first time it's been seen, then we can't have seen
+     * the continuation yet, so the continuation frame number should
+     * be 0, for "unknown".
+     */
+    if (!fd->flags.visited) {
+      request_key.conversation = conversation->index;
+      request_key.mid          = si.mid;
+      request_key.pid          = si.pid;
+      request_key.frame_num    = 0;
 
-      ByteCount = GSHORT(pd, offset);
+      new_continuation_val = (struct smb_continuation_val *)
+               g_hash_table_lookup(smb_continuation_hash, &request_key);
 
-      if (tree) {
+      if (new_continuation_val == NULL) {
+       /*
+        * Not found.
+        */
+       new_request_key = g_mem_chunk_alloc(smb_request_keys);
+       new_request_key -> conversation = conversation->index;
+       new_request_key -> mid          = si.mid;
+       new_request_key -> pid          = si.pid;
+       new_request_key -> frame_num    = 0;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+       new_continuation_val = g_mem_chunk_alloc(smb_continuation_vals);
+       new_continuation_val -> frame = fd->num;
+       if (TransactName != NULL)
+         new_continuation_val -> transact_name = *TransactName;
+       else
+         new_continuation_val -> transact_name = NULL;
 
+       g_hash_table_insert(smb_continuation_hash, new_request_key,
+                           new_continuation_val);
+      } else {
+       /*
+        * This presumably means we never saw the continuation of
+        * the message we found, and this is a reply to a different
+        * request; as we never saw the continuation of that message,
+        * we won't be using this "request_val" structure for that
+        * message (as we'd use it only for the continuation).
+        *
+        * Clean out the structure, and set it to refer to this frame.
+        */
+       new_continuation_val -> frame = fd->num;
       }
+    }
+  }
 
-      offset += 2; /* Skip Byte Count */
-
-      if (ByteCount > 0) {
-
-       /* Build display for: ANSI Password */
+  return continuation_val;
+}
 
-       ANSIPassword = pd + offset;
+static void
+smb_init_protocol(void)
+{
+#if defined(DEBUG_SMB_HASH)
+  printf("Initializing SMB hashtable area\n");
+#endif
 
-       if (ANSIAccountPasswordLength > 0) {
+  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 (tree) {
+  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);
+}
 
-               proto_tree_add_text(tree, NullTVB, offset, ANSIAccountPasswordLength, "ANSI Password: %s", format_text(ANSIPassword, ANSIAccountPasswordLength));
+static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info si, int, int);
 
-           }
+/*
+ * XXX - global required to avoid changing the calling sequence of old-style
+ * dissectors.
+ */
+static tvbuff_t *our_tvb;
+static packet_info *our_pinfo;
 
-           offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
+static void
+wrap_dissect_smb_command(proto_tree *top_tree, const guint8 *pd, int offset,
+   proto_tree *smb_tree, guint8 cmd, struct smb_info *si, int max_data,
+   int SMB_offset)
+{
+       if(smb_dissector[cmd].request){ 
+         /* call smb command dissector */
+         our_pinfo->private_data = si;
+         dissect_smb_command(our_tvb, our_pinfo, top_tree, offset, smb_tree, cmd);
+       } else {
+         offset += SMB_offset;
+         if (check_col(our_pinfo->fd, COL_INFO)) {
+           col_add_fstr(our_pinfo->fd, COL_INFO, "%s %s",
+                        decode_smb_name(cmd),
+                        (si->request)? "Request" : "Response");
+         }
+         (dissect[cmd])(pd, offset, our_pinfo->fd, top_tree, smb_tree, *si,
+                             max_data, SMB_offset);
        }
+}
 
-       /* Build display for: UNICODE Password */
-
-       UNICODEPassword = pd + offset;
+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 (UNICODEAccountPasswordLength > 0) {
+  if (tree) {
 
-         if (tree) {
+    proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (%u bytes)", 
+                       END_OF_FRAME); 
 
-           proto_tree_add_text(tree, NullTVB, offset, UNICODEAccountPasswordLength, "UNICODE Password: %s", format_text(UNICODEPassword, UNICODEAccountPasswordLength));
+  }
 
-         }
+}
 
-         offset += UNICODEAccountPasswordLength; /* Skip UNICODE Password */
+/* 
+ * Dissect a UNIX like date ...
+ */
 
-       }
+struct tm *_gtime; /* Add leading underscore ("_") to prevent symbol
+                      conflict with /usr/include/time.h on some NetBSD
+                      systems */
 
-       /* Build display for: Account Name */
+static char *
+dissect_smbu_date(guint16 date, guint16 time)
 
-       AccountName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+{
+  static char         datebuf[4+2+2+2+1+10];
+  time_t              ltime = (date << 16) + time;
 
-       if (tree) {
+  _gtime = gmtime(&ltime);
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Account Name: %s", AccountName);
+  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;
 
-       offset += string_len; /* Skip Account Name */
+}
 
-       /* Build display for: Primary Domain */
+/*
+ * Relies on time
+ */
+static char *
+dissect_smbu_time(guint16 date, guint16 time)
 
-       /*
-        * 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 char timebuf[2+2+2+2+1+10];
 
-       PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+  if (_gtime)
+    sprintf(timebuf, "%02d:%02d:%02d",
+           _gtime -> tm_hour, _gtime -> tm_min, _gtime -> tm_sec);
+  else
+    sprintf(timebuf, "Bad time format");
 
-       if (tree) {
+  return timebuf;
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Primary Domain: %s", PrimaryDomain);
+}
 
-       }
+/*
+ * Dissect a DOS-format date.
+ */
+static char *
+dissect_dos_date(guint16 date)
+{
+       static char datebuf[4+2+2+1];
 
-       offset += string_len; /* Skip Primary Domain */
+       sprintf(datebuf, "%04d-%02d-%02d",
+           ((date>>9)&0x7F) + 1980, (date>>5)&0x0F, date&0x1F);
+       return datebuf;
+}
 
-       /* Build display for: Native OS */
+/*
+ * Dissect a DOS-format time.
+ */
+static char *
+dissect_dos_time(guint16 time)
+{
+       static char timebuf[2+2+2+1];
 
-       NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       sprintf(timebuf, "%02d:%02d:%02d",
+           (time>>11)&0x1F, (time>>5)&0x3F, (time&0x1F)*2);
+       return timebuf;
+}
 
-       if (tree) {
+/* Max string length for displaying Unicode strings.  */
+#define        MAX_UNICODE_STR_LEN     256
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Native OS: %s", NativeOS);
+/* 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;
 
-       }
+  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 !
+*/
+static gchar *
+unicode_to_str_tvb(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen) {
+  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;
 
-       offset += string_len; /* Skip Native OS */
+  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 ((uchar = tvb_get_letohs(tvb, offset)) != 0) {
+    if (len > 0) {
+      if ((uchar & 0xFF00) == 0)
+        *p++ = uchar;  /* ISO 8859-1 */
+      else
+        *p++ = '?';    /* not 8859-1 */
+      len--;
+    } else
+      overflow = 1;
+    offset += 2;
+    us_len += 2;
+    if(exactlen){
+      if(us_len>= *us_lenp){
+        break;
+      }
+    }
+  }
+  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: Native LanMan Type */
+/* 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;
 
-       /*
-        * 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....
-        */
+  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;
+}
 
-       NativeLanManType = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+/* nopad == TRUE : Do not add any padding before this string
+ * exactlen == TRUE : len contains the exact len of the string in bytes.
+ */
+static const gchar *
+get_unicode_or_ascii_string_tvb(tvbuff_t *tvb, int *offsetp, packet_info *pinfo, int *len, gboolean nopad, gboolean exactlen)
+{
+  int offset = *offsetp;
+  const gchar *string;
+  int string_len;
+  smb_info_t *si;
 
-       if (tree) {
+  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 */
+    }
+    if(exactlen){
+      string_len = *len;
+      string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen);
+    } else {
+      string = unicode_to_str_tvb(tvb, *offsetp, &string_len, exactlen);
+      string_len += 2;
+    }
+  } else {
+    if(exactlen){
+      string = tvb_get_ptr(tvb, *offsetp, *len);
+      string_len = *len;
+    } else {
+      string_len = tvb_strsize(tvb, *offsetp);
+      string = tvb_get_ptr(tvb, *offsetp, string_len);
+    }
+  }
+  *len = string_len;
+  return string;
+}
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "Native LanMan Type: %s", NativeLanManType);
 
-       }
+/*
+ * Each dissect routine is passed an offset to wct and works from there 
+ */
 
-       offset += string_len; /* Skip Native LanMan Type */
+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)
 
-      }
+{
+  guint8        WordCount;
+  guint16       TotalUnits;
+  guint16       Reserved;
+  guint16       FreeUnits;
+  guint16       ByteCount;
+  guint16       BlocksPerUnit;
+  guint16       BlockSize;
 
-      break;
+  if (si.request) {
+    /* Request(s) dissect code */
 
-    default:
+    /* Build display for: Word Count (WCT) */
 
-      /* XXX - dump the parameter words, one word at a time? */
+    WordCount = GBYTE(pd, offset);
 
-      offset += WordCount;
+    if (tree) {
 
-      /* Build display for: Byte Count (BCC) */
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
-      ByteCount = GSHORT(pd, offset);
+    }
 
-      if (tree) {
+    offset += 1; /* Skip Word Count (WCT) */
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+    /* Build display for: Byte Count (BCC) */
 
-      }
+    ByteCount = GSHORT(pd, offset);
 
-      offset += 2; /* Skip Byte Count (BCC) */
+    if (tree) {
 
-      break;
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    if (AndXCommand != 0xFF) {
-
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
-
-    }
+    offset += 2; /* Skip Byte Count (BCC) */
 
   } else {
     /* Response(s) dissect code */
@@ -4467,622 +3810,353 @@ dissect_ssetup_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    switch (WordCount) {
-
-    case 3:
-
-      /* 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: Action */
-
-      Action = GSHORT(pd, 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"));
-
-      }
-
-      offset += 2; /* Skip Action */
-
-      /* 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 (ByteCount > 0) {
-
-        /* 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);
-
-        }
-
-        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);
-
-        }
-
-        offset += string_len; /* Skip NativeLanMan */
-
-        /* Build display for: PrimaryDomain */
-
-        PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
-
-        if (tree) {
-
-          proto_tree_add_text(tree, NullTVB, offset, string_len, "PrimaryDomain: %s", PrimaryDomain);
-
-        }
-
-        offset += string_len; /* Skip PrimaryDomain */
-
-      }
-
-      break;
-
-    case 4:
-
-      /* 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: Action */
-
-      Action = GSHORT(pd, 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"));
-
-      }
-
-      offset += 2; /* Skip Action */
+    if (WordCount != 0) {
 
-      /* Build display for: Security Blob Length */
+      /* Build display for: Total Units */
 
-      SecurityBlobLength = GSHORT(pd, offset);
+      TotalUnits = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Security Blob Length: %u", SecurityBlobLength);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Total Units: %u", TotalUnits);
 
       }
 
-      offset += 2; /* Skip Security Blob Length */
+      offset += 2; /* Skip Total Units */
 
-      /* Build display for: Byte Count (BCC) */
+      /* Build display for: Blocks Per Unit */
 
-      ByteCount = GSHORT(pd, offset);
+      BlocksPerUnit = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Blocks Per Unit: %u", BlocksPerUnit);
 
       }
 
-      offset += 2; /* Skip Byte Count (BCC) */
-
-      if (ByteCount > 0) {
-
-       SecurityBlob = pd + offset;
-
-       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? */
-
-         if (tree) {
-
-           proto_tree_add_text(tree, NullTVB, offset, SecurityBlobLength, "Security Blob: %s",
-                               bytes_to_str(SecurityBlob, SecurityBlobLength));
-
-         }
-
-         offset += SecurityBlobLength; /* Skip Security Blob */
-
-       }
-
-       /* 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);
-
-       }
+      offset += 2; /* Skip Blocks Per Unit */
 
-       offset += string_len; /* Skip NativeOS */
+      /* Build display for: Block Size */
 
-       /* Build display for: NativeLanMan */
+      BlockSize = GSHORT(pd, offset);
 
-       NativeLanMan = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+      if (tree) {
 
-       if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Block Size: %u", BlockSize);
 
-         proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeLanMan: %s", NativeLanMan);
+      }
 
-       }
+      offset += 2; /* Skip Block Size */
 
-       offset += string_len; /* Skip NativeLanMan */
+      /* Build display for: Free Units */
 
-      }
+      FreeUnits = GSHORT(pd, offset);
 
-      break;
+      if (tree) {
 
-    default:
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Free Units: %u", FreeUnits);
 
-      /* XXX - dump the parameter words, one word at a time? */
+      }
 
-      offset += WordCount;
+      offset += 2; /* Skip Free Units */
 
-      /* Build display for: Byte Count (BCC) */
+      /* Build display for: Reserved */
 
-      ByteCount = GSHORT(pd, offset);
+      Reserved = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
 
       }
 
-      offset += 2; /* Skip Byte Count (BCC) */
-
-      break;
+      offset += 2; /* Skip Reserved */
 
     }
 
-    if (AndXCommand != 0xFF) {
+    /* Build display for: Byte Count (BCC) */
+
+    ByteCount = GSHORT(pd, offset);
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+    if (tree) {
+
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
+    offset += 2; /* Skip Byte Count (BCC) */
+
   }
 
 }
 
 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)
+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)
 
 {
-  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;
+  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;
 
-  wct = pd[offset];
+  if (si.request) {
+    /* Request(s) dissect code */
 
-  /* Now figure out what format we are talking about, 2, 3, or 4 response
-   * words ...
-   */
+    /* Build display for: Word Count (WCT) */
 
-  if (!(si.request && (wct == 4)) && !(!si.request && (wct == 2)) &&
-      !(!si.request && (wct == 3)) && !(wct == 0)) {
+    WordCount = GBYTE(pd, offset);
 
     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, 1, "Word Count (WCT): %u", WordCount);
 
-      proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data");
+    }
 
-      return;
+    offset += 1; /* Skip Word Count (WCT) */
 
-    }
-    
-  }
+    /* Build display for: FID */
 
-  if (tree) {
+    FID = GSHORT(pd, offset);
 
-    proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", wct);
+    if (tree) {
 
-  }
+      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
-  offset += 1;
+    }
 
-  if (wct > 0) {
+    offset += 2; /* Skip FID */
 
-    andxcmd = pd[offset];
+    /* Build display for: Offset */
+
+    Offset = GWORD(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]);
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
     }
 
-    offset += 2;
+    offset += 4; /* Skip Offset */
 
-    andxoffs = GSHORT(pd, offset);
+    /* Build display for: Max Count */
+
+    MaxCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Offset to next command: %u", andxoffs);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
 
     }
 
-    offset += 2;
-
-  }
-
-  switch (wct) {
+    offset += 2; /* Skip Max Count */
 
-  case 0:
+    /* Build display for: Min Count */
 
-    bcc = GSHORT(pd, offset);
+    MinCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
 
     }
 
-    break;
+    offset += 2; /* Skip Min Count */
 
-  case 4:
+    /* Build display for: Reserved 1 */
 
-    flags = GSHORT(pd, offset);
+    Reserved1 = GWORD(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"));
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 1: %u", Reserved1);
 
     }
 
-    offset += 2;
+    offset += 4; /* Skip Reserved 1 */
 
-    passwdlen = GSHORT(pd, offset);
+    /* Build display for: Reserved 2 */
+
+    Reserved2 = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Password Length: %u", passwdlen);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
 
     }
 
-    offset += 2;
+    offset += 2; /* Skip Reserved 2 */
 
-    bcc = GSHORT(pd, 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", bcc);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    offset += 2;
+    offset += 2; /* Skip Byte Count (BCC) */
 
-    str = pd + offset;
+  } else {
+    /* Response(s) dissect code */
+
+    /* Build display for: Word Count */
+
+    WordCount = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Password: %s", format_text(str, passwdlen));
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
 
     }
 
-    offset += passwdlen;
+    offset += 1; /* Skip Word Count */
 
-    str = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+    if (WordCount != 0) {
 
-    if (tree) {
+      /* Build display for: Offset */
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Path: %s", str);
+      Offset = GWORD(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += string_len;
+       proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
-    str = pd + offset;
+      }
 
-    if (tree) {
+      offset += 4; /* Skip Offset */
 
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service: %s", str);
+      /* Build display for: Count */
 
-    }
+      Count = GSHORT(pd, offset);
 
-    break;
+      if (tree) {
 
-  case 2:
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
 
-    bcc = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Count */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
+      /* Build display for: Reserved */
 
-    }
+      Reserved = GSHORT(pd, offset);
 
-    offset += 2;
+      if (tree) {
 
-    str = pd + offset;
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service Type: %s",
-                         str);
+      offset += 2; /* Skip Reserved */
 
-    }
+      /* Build display for: Data Compaction Mode */
 
-    offset += strlen(str) + 1;
+      DataCompactionMode = GSHORT(pd, offset);
 
-    break;
+      if (tree) {
 
-  case 3:
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
 
-    optionsup = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Data Compaction Mode */
 
-      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"));
-      
-    }
+      /* 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);
 
-    offset += 2;
+      if (tree) {
 
-    bcc = GSHORT(pd, offset);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
+      offset += 2; /* Skip Data Offset */
 
     }
 
-    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.
-     */
+    /* Build display for: Byte Count (BCC) */
 
-    str = pd + offset;
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service: %s", str);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    offset += strlen(str) + 1;
+    offset += 2; /* Skip Byte Count (BCC) */
 
-    str = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+    /* Build display for: Pad */
+
+    Pad = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Native File System: %s", str);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
 
     }
 
-    offset += string_len;
-
-    
-    break;
+    offset += 1; /* Skip Pad */
 
-  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_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)
+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 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_tree    *Attributes_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;
+  guint32       FileDataSize;
+  guint32       FileAllocationSize;
   guint16       LastWriteTime;
   guint16       LastWriteDate;
-  guint16       GrantedAccess;
-  guint16       Flags;
-  guint16       FileType;
-  guint16       FileAttributes;
-  guint16       File;
+  guint16       LastAccessTime;
+  guint16       LastAccessDate;
   guint16       FID;
-  guint16       DeviceState;
-  guint16       DesiredAccess;
   guint16       CreationTime;
   guint16       CreationDate;
   guint16       ByteCount;
-  guint16       AndXOffset = 0;
-  guint16       Action;
-  const char    *FileName;
-  int           string_len;
+  guint16       Attributes;
 
   if (si.request) {
     /* Request(s) dissect code */
@@ -5099,245 +4173,223 @@ dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: AndXCommand */
+    /* Build display for: FID */
 
-    AndXCommand = GBYTE(pd, offset);
+    FID = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                         (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
     }
 
-    offset += 1; /* Skip AndXCommand */
+    offset += 2; /* Skip FID */
 
-    /* Build display for: AndXReserved */
+    /* Build display for: Byte Count */
 
-    AndXReserved = GBYTE(pd, offset);
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
     }
 
-    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 Byte Count */
 
-    offset += 2; /* Skip AndXOffset */
+  } else {
+    /* Response(s) dissect code */
 
-    /* Build display for: Flags */
+    /* Build display for: Word Count (WCT) */
 
-    Flags = GSHORT(pd, offset);
+    WordCount = GBYTE(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) {
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
-      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);
+    offset += 1; /* Skip Word Count (WCT) */
 
-    if (tree) {
+    if (WordCount != 0) {
 
-      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"));
-    
-    }
+      /* Build display for: Creation Date */
 
-    offset += 2; /* Skip Search */
+      CreationDate = GSHORT(pd, offset);
 
-    /* Build display for: File */
+      if (tree) {
 
-    File = GSHORT(pd, offset);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
 
-    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 Creation Date */
 
-    offset += 2; /* Skip File */
+      /* Build display for: Creation Time */
 
-    /* Build display for: Creation Time */
+      CreationTime = GSHORT(pd, offset);
 
-    CreationTime = GSHORT(pd, offset);
+      if (tree) {
 
-    if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
 
+      }
 
-    }
+      offset += 2; /* Skip Creation Time */
 
-    offset += 2; /* Skip Creation Time */
+      /* Build display for: Last Access Date */
 
-    /* Build display for: Creation Date */
+      LastAccessDate = GSHORT(pd, offset);
 
-    CreationDate = GSHORT(pd, offset);
+      if (tree) {
 
-    if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Date: %s", dissect_dos_date(LastAccessDate));
 
-      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 Last Access Date */
 
-    offset += 2; /* Skip Creation Date */
+      /* Build display for: Last Access Time */
 
-    /* Build display for: Open Function */
+      LastAccessTime = GSHORT(pd, offset);
 
-    OpenFunction = GSHORT(pd, offset);
+      if (tree) {
 
-    if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Time: %s", dissect_dos_time(LastAccessTime));
 
-      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 */
+      offset += 2; /* Skip Last Access Time */
 
-    /* Build display for: Allocated Size */
+      /* Build display for: Last Write Date */
 
-    AllocatedSize = GWORD(pd, offset);
+      LastWriteDate = GSHORT(pd, offset);
 
-    if (tree) {
+      if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Allocated Size: %u", AllocatedSize);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
 
-    }
+      }
 
-    offset += 4; /* Skip Allocated Size */
+      offset += 2; /* Skip Last Write Date */
 
-    /* Build display for: Reserved1 */
+      /* Build display for: Last Write Time */
 
-    Reserved1 = GWORD(pd, offset);
+      LastWriteTime = GSHORT(pd, offset);
 
-    if (tree) {
+      if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved1: %u", Reserved1);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
 
-    }
+      }
 
-    offset += 4; /* Skip Reserved1 */
+      offset += 2; /* Skip Last Write Time */
 
-    /* Build display for: Reserved2 */
+      /* Build display for: File Data Size */
 
-    Reserved2 = GWORD(pd, offset);
+      FileDataSize = GWORD(pd, offset);
 
-    if (tree) {
+      if (tree) {
+       
+       proto_tree_add_text(tree, NullTVB, offset, 4, "File Data Size: %u", FileDataSize);
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved2: %u", Reserved2);
+      }
 
-    }
+      offset += 4; /* Skip File Data Size */
 
-    offset += 4; /* Skip Reserved2 */
+      /* Build display for: File Allocation Size */
 
-    /* Build display for: Byte Count */
+      FileAllocationSize = GWORD(pd, offset);
 
-    ByteCount = GSHORT(pd, offset);
+      if (tree) {
 
-    if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 4, "File Allocation Size: %u", FileAllocationSize);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+      }
 
-    }
+      offset += 4; /* Skip File Allocation Size */
 
-    offset += 2; /* Skip Byte Count */
+      /* Build display for: Attributes */
 
-    /* Build display for: File Name */
+      Attributes = GSHORT(pd, offset);
+      
+      if (tree) {
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+       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: Byte Count */
+
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
     }
 
-    offset += string_len; /* Skip File Name */
+    offset += 2; /* Skip Byte Count */
 
+  }
 
-    if (AndXCommand != 0xFF) {
+}
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+/* 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)
 
-    }
+{
+  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;
 
-  } else {
-    /* Response(s) dissect code */
+  if (si.request) {
+    /* Request(s) dissect code */
 
     /* Build display for: Word Count (WCT) */
 
@@ -5351,7 +4403,9 @@ dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    if (WordCount != 0) {
+    switch (WordCount) {
+
+    case 10:
 
       /* Build display for: AndXCommand */
 
@@ -5359,7 +4413,7 @@ dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
                            (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
       }
@@ -5372,7 +4426,7 @@ dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
       }
 
@@ -5384,795 +4438,692 @@ dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+        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 */
+      /* Build display for: MaxBufferSize */
 
-      DataSize = GWORD(pd, offset);
+      MaxBufferSize = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 4, "Data Size: %u", DataSize);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
 
       }
 
-      offset += 4; /* Skip Data Size */
+      offset += 2; /* Skip MaxBufferSize */
 
-      /* Build display for: Granted Access */
+      /* Build display for: MaxMpxCount */
 
-      GrantedAccess = GSHORT(pd, offset);
+      MaxMpxCount = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Granted Access: %u", GrantedAccess);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
 
       }
 
-      offset += 2; /* Skip Granted Access */
+      offset += 2; /* Skip MaxMpxCount */
 
-      /* Build display for: File Type */
+      /* Build display for: VcNumber */
 
-      FileType = GSHORT(pd, offset);
+      VcNumber = 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"));
-    
+        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
+
       }
 
-      offset += 2; /* Skip File Type */
+      offset += 2; /* Skip VcNumber */
 
-      /* Build display for: Device State */
+      /* Build display for: SessionKey */
 
-      DeviceState = GSHORT(pd, offset);
+      SessionKey = GWORD(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Device State: %u", DeviceState);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
 
       }
 
-      offset += 2; /* Skip Device State */
+      offset += 4; /* Skip SessionKey */
 
-      /* Build display for: Action */
+      /* Build display for: PasswordLen */
 
-      Action = GSHORT(pd, offset);
+      PasswordLen = 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"));
-       
+        proto_tree_add_text(tree, NullTVB, offset, 2, "PasswordLen: %u", PasswordLen);
+
       }
-      
-      offset += 2; /* Skip Action */
 
-      /* Build display for: Server FID */
-      
-      ServerFID = GWORD(pd, offset);
+      offset += 2; /* Skip PasswordLen */
+
+      /* Build display for: Reserved */
+
+      Reserved = GWORD(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 4, "Server FID: %u", ServerFID);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
 
       }
 
-      offset += 4; /* Skip Server FID */
+      offset += 4; /* Skip Reserved */
 
-      /* Build display for: Reserved */
+      /* Build display for: Byte Count (BCC) */
 
-      Reserved = GSHORT(pd, offset);
+      ByteCount = GSHORT(pd, offset);
 
       if (tree) {
-       
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
       }
 
-      offset += 2; /* Skip Reserved */
+      offset += 2; /* Skip Byte Count (BCC) */
 
-    }
+      if (ByteCount > 0) {
 
-    /* Build display for: Byte Count */
+       /* Build display for: Password */
 
-    ByteCount = GSHORT(pd, offset);
+        Password = pd + offset;
 
-    if (tree) {
+       if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+         proto_tree_add_text(tree, NullTVB, offset, strlen(Password) + 1, "Password: %s", Password);
 
-    }
+       }
 
-    offset += 2; /* Skip Byte Count */
+       offset += PasswordLen;
 
+       /* Build display for: AccountName */
 
-    if (AndXCommand != 0xFF) {
+       AccountName = pd + offset;
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+       if (tree) {
 
-    }
+         proto_tree_add_text(tree, NullTVB, offset, strlen(AccountName) + 1, "AccountName: %s", AccountName);
 
-  }
+       }
 
-}
+       offset += strlen(AccountName) + 1; /* Skip AccountName */
 
-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)
+       /* Build display for: PrimaryDomain */
 
-{
-  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;
+       PrimaryDomain = pd + offset;
 
-  if (si.request) {
-    /* Request(s) dissect code */
+       if (tree) {
 
-    WordCount = GBYTE(pd, offset);
+         proto_tree_add_text(tree, NullTVB, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
 
-    switch (WordCount) {
+       }
 
-    case 12:
+       offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
 
-      /* Build display for: Word Count (WCT) */
+       /* Build display for: NativeOS */
 
-      WordCount = GBYTE(pd, offset);
+       NativeOS = pd + offset;
 
-      if (tree) {
+       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+         proto_tree_add_text(tree, NullTVB, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
 
-      }
+       }
 
-      offset += 1; /* Skip Word Count (WCT) */
+       offset += strlen(NativeOS) + 1; /* Skip NativeOS */
 
-      /* Build display for: FID */
+       /* Build display for: NativeLanMan */
 
-      FID = GSHORT(pd, offset);
+       NativeLanMan = pd + offset;
 
-      if (tree) {
+       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+         proto_tree_add_text(tree, NullTVB, offset, strlen(NativeLanMan) + 1, "Native Lan Manager: %s", NativeLanMan);
+
+       }
+
+       offset += strlen(NativeLanMan) + 1; /* Skip NativeLanMan */
 
       }
 
-      offset += 2; /* Skip FID */
+      break;
 
-      /* Build display for: Count */
+    case 12:
 
-      Count = GSHORT(pd, offset);
+      /* Build display for: AndXCommand */
+
+      AndXCommand = GBYTE(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+                            (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
       }
 
-      offset += 2; /* Skip Count */
+      offset += 1; /* Skip AndXCommand */
 
-      /* Build display for: Reserved 1 */
+      /* Build display for: AndXReserved */
 
-      Reserved1 = GSHORT(pd, offset);
+      AndXReserved = GBYTE(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
       }
 
-      offset += 2; /* Skip Reserved 1 */
+      offset += 1; /* Skip AndXReserved */
 
-      /* Build display for: Offset */
+      /* Build display for: AndXOffset */
 
-      Offset = GWORD(pd, offset);
+      AndXOffset = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
       }
 
-      offset += 4; /* Skip Offset */
+      offset += 2; /* Skip AndXOffset */
 
-      /* Build display for: Timeout */
+      /* Build display for: MaxBufferSize */
 
-      Timeout = GWORD(pd, offset);
+      MaxBufferSize = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
 
       }
 
-      offset += 4; /* Skip Timeout */
+      offset += 2; /* Skip MaxBufferSize */
 
-      /* Build display for: WriteMode */
+      /* Build display for: MaxMpxCount */
 
-      WriteMode = GSHORT(pd, offset);
+      MaxMpxCount = 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)"));
-      
+        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
+
       }
 
-      offset += 2; /* Skip WriteMode */
+      offset += 2; /* Skip MaxMpxCount */
 
-      /* Build display for: Reserved 2 */
+      /* Build display for: VcNumber */
 
-      Reserved2 = GWORD(pd, offset);
+      VcNumber = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 2: %u", Reserved2);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
 
       }
 
-      offset += 4; /* Skip Reserved 2 */
+      offset += 2; /* Skip VcNumber */
 
-      /* Build display for: Data Length */
+      /* Build display for: SessionKey */
 
-      DataLength = GSHORT(pd, offset);
+      SessionKey = GWORD(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
 
       }
 
-      offset += 2; /* Skip Data Length */
+      offset += 4; /* Skip SessionKey */
 
-      /* Build display for: Data Offset */
+      /* Build display for: Security Blob Length */
 
-      DataOffset = GSHORT(pd, offset);
+      SecurityBlobLength = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Security Blob Length: %u", SecurityBlobLength);
 
       }
 
-      offset += 2; /* Skip Data Offset */
+      offset += 2; /* Skip Security Blob Length */
 
-      /* Build display for: Byte Count (BCC) */
+      /* Build display for: Reserved */
 
-      ByteCount = GSHORT(pd, offset);
+      Reserved = GWORD(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
 
       }
 
-      offset += 2; /* Skip Byte Count (BCC) */
+      offset += 4; /* Skip Reserved */
 
-      /* Build display for: Pad */
+      /* Build display for: Capabilities */
 
-      Pad = GBYTE(pd, offset);
+      Capabilities = GWORD(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
-
-      }
-
-      offset += 1; /* Skip Pad */
+        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"));
 
-    break;
+      }
 
-    case 14:
+      offset += 4; /* Skip Capabilities */
 
-      /* Build display for: Word Count (WCT) */
+      /* Build display for: Byte Count */
 
-      WordCount = GBYTE(pd, offset);
+      ByteCount = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
       }
 
-      offset += 1; /* Skip Word Count (WCT) */
+      offset += 2; /* Skip Byte Count */
 
-      /* Build display for: FID */
+      if (ByteCount > 0) {
 
-      FID = GSHORT(pd, offset);
+        /* Build display for: Security Blob */
 
-      if (tree) {
+        SecurityBlob = pd + offset;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+        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? */
 
-      offset += 2; /* Skip FID */
+          if (tree) {
 
-      /* Build display for: Count */
+            proto_tree_add_text(tree, NullTVB, offset, SecurityBlobLength, "Security Blob: %s",
+                                bytes_to_str(SecurityBlob, SecurityBlobLength));
 
-      Count = GSHORT(pd, offset);
+          }
 
-      if (tree) {
+          offset += SecurityBlobLength; /* Skip Security Blob */
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+        }
 
-      }
+        /* Build display for: Native OS */
 
-      offset += 2; /* Skip Count */
+        NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-      /* Build display for: Reserved 1 */
+        if (tree) {
 
-      Reserved1 = GSHORT(pd, offset);
+          proto_tree_add_text(tree, NullTVB, offset, string_len, "Native OS: %s", NativeOS);
 
-      if (tree) {
+        }
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
+        offset += string_len; /* Skip Native OS */
 
-      }
+        /* Build display for: Native LanMan Type */
 
-      offset += 2; /* Skip Reserved 1 */
+        NativeLanManType = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-      /* Build display for: Timeout */
+        if (tree) {
 
-      Timeout = GWORD(pd, offset);
+          proto_tree_add_text(tree, NullTVB, offset, string_len, "Native LanMan Type: %s", NativeLanManType);
 
-      if (tree) {
+        }
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
+        offset += string_len; /* Skip Native LanMan Type */
 
-      }
+        /* Build display for: Primary Domain */
 
-      offset += 4; /* Skip Timeout */
+        PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-      /* Build display for: WriteMode */
+        if (tree) {
 
-      WriteMode = GSHORT(pd, offset);
+          proto_tree_add_text(tree, NullTVB, offset, string_len, "Primary Domain: %s", PrimaryDomain);
 
-      if (tree) {
+        }
+
+        offset += string_len; /* Skip Primary Domain */
 
-        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 */
+      break;
 
-      /* Build display for: Reserved 2 */
+    case 13:
 
-      Reserved2 = GWORD(pd, offset);
+      /* Build display for: AndXCommand */
+
+      AndXCommand = GBYTE(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 2: %u", Reserved2);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
       }
 
-      offset += 4; /* Skip Reserved 2 */
+      offset += 1; /* Skip AndXCommand */
 
-      /* Build display for: Data Length */
+      /* Build display for: AndXReserved */
 
-      DataLength = GSHORT(pd, offset);
+      AndXReserved = GBYTE(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
       }
 
-      offset += 2; /* Skip Data Length */
+      offset += 1; /* Skip AndXReserved */
 
-      /* Build display for: Data Offset */
+      /* Build display for: AndXOffset */
 
-      DataOffset = GSHORT(pd, offset);
+      AndXOffset = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
       }
 
-      offset += 2; /* Skip Data Offset */
+      offset += 2; /* Skip AndXOffset */
 
-      /* Build display for: Byte Count (BCC) */
+      /* Build display for: MaxBufferSize */
 
-      ByteCount = GSHORT(pd, offset);
+      MaxBufferSize = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
 
       }
 
-      offset += 2; /* Skip Byte Count (BCC) */
+      offset += 2; /* Skip MaxBufferSize */
 
-      /* Build display for: Pad */
+      /* Build display for: MaxMpxCount */
 
-      Pad = GBYTE(pd, offset);
+      MaxMpxCount = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
 
       }
 
-      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) {
+      offset += 2; /* Skip MaxMpxCount */
 
-      /* Build display for: Remaining */
+      /* Build display for: VcNumber */
 
-      Remaining = GSHORT(pd, offset);
+      VcNumber = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "VcNumber: %u", VcNumber);
 
       }
 
-      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_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)
+      offset += 2; /* Skip VcNumber */
 
-{
-  guint8        WordCount;
-  guint8        BufferFormat2;
-  guint8        BufferFormat1;
-  guint16       SearchAttributes;
-  guint16       ByteCount;
-  const char    *OldFileName;
-  const char    *NewFileName;
-  int           string_len;
+      /* Build display for: SessionKey */
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      SessionKey = GWORD(pd, offset);
 
-    /* Build display for: Word Count (WCT) */
+      if (tree) {
 
-    WordCount = GBYTE(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "SessionKey: %u", SessionKey);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      offset += 4; /* Skip SessionKey */
 
-    }
+      /* Build display for: ANSI Account Password Length */
 
-    offset += 1; /* Skip Word Count (WCT) */
+      ANSIAccountPasswordLength = GSHORT(pd, offset);
 
-    /* Build display for: Search Attributes */
+      if (tree) {
 
-    SearchAttributes = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "ANSI Account Password Length: %u", ANSIAccountPasswordLength);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
+      offset += 2; /* Skip ANSI Account Password Length */
 
-    }
+      /* Build display for: UNICODE Account Password Length */
 
-    offset += 2; /* Skip Search Attributes */
+      UNICODEAccountPasswordLength = GSHORT(pd, offset);
 
-    /* Build display for: Byte Count */
+      if (tree) {
 
-    ByteCount = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "UNICODE Account Password Length: %u", UNICODEAccountPasswordLength);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+      offset += 2; /* Skip UNICODE Account Password Length */
 
-    }
+      /* Build display for: Reserved */
 
-    offset += 2; /* Skip Byte Count */
+      Reserved = GWORD(pd, offset);
 
-    /* Build display for: Buffer Format 1 */
+      if (tree) {
 
-    BufferFormat1 = GBYTE(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
 
-    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 += 4; /* Skip Reserved */
 
-    }
+      /* Build display for: Capabilities */
 
-    offset += 1; /* Skip Buffer Format 1 */
+      Capabilities = GWORD(pd, offset);
 
-    /* Build display for: Old File Name */
+      if (tree) {
 
-    OldFileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_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 (tree) {
+      offset += 4; /* Skip Capabilities */
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Old File Name: %s", OldFileName);
+      /* Build display for: Byte Count */
 
-    }
+      ByteCount = GSHORT(pd, offset);
 
-    offset += string_len; /* Skip Old File Name */
+      if (tree) {
 
-    /* Build display for: Buffer Format 2 */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
-    BufferFormat2 = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Byte Count */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 2: %s (%u)",
-                         val_to_str(BufferFormat2, buffer_format_vals, "Unknown"),
-                         BufferFormat2);
+      if (ByteCount > 0) {
 
-    }
+       /* Build display for: ANSI Password */
 
-    offset += 1; /* Skip Buffer Format 2 */
+       ANSIPassword = pd + offset;
 
-    /* Build display for: New File Name */
+       if (ANSIAccountPasswordLength > 0) {
 
-    NewFileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+           if (tree) {
 
-    if (tree) {
+               proto_tree_add_text(tree, NullTVB, offset, ANSIAccountPasswordLength, "ANSI Password: %s", format_text(ANSIPassword, ANSIAccountPasswordLength));
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "New File Name: %s", NewFileName);
+           }
 
-    }
+           offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
+       }
 
-    offset += string_len; /* Skip New File Name */
+       /* Build display for: UNICODE Password */
 
-  } else {
-    /* Response(s) dissect code */
+       UNICODEPassword = pd + offset;
 
-    /* Build display for: Word Count (WCT) */
+       if (UNICODEAccountPasswordLength > 0) {
 
-    WordCount = GBYTE(pd, offset);
+         if (tree) {
 
-    if (tree) {
+           proto_tree_add_text(tree, NullTVB, offset, UNICODEAccountPasswordLength, "UNICODE Password: %s", format_text(UNICODEPassword, UNICODEAccountPasswordLength));
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+         }
 
-    }
+         offset += UNICODEAccountPasswordLength; /* Skip UNICODE Password */
 
-    offset += 1; /* Skip Word Count (WCT) */
+       }
 
-    /* Build display for: Byte Count (BCC) */
+       /* Build display for: Account Name */
 
-    ByteCount = GSHORT(pd, offset);
+       AccountName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-    if (tree) {
+       if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+         proto_tree_add_text(tree, NullTVB, offset, string_len, "Account Name: %s", AccountName);
 
-    }
+       }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+       offset += string_len; /* Skip Account Name */
 
-  }
+       /* Build display for: 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?
+        */
 
-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)
+       PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-{
-  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 (tree) {
 
-  if (si.request) {
-    /* Request(s) dissect code */
+         proto_tree_add_text(tree, NullTVB, offset, string_len, "Primary Domain: %s", PrimaryDomain);
 
-    /* Build display for: Word Count (WCT) */
+       }
 
-    WordCount = GBYTE(pd, offset);
+       offset += string_len; /* Skip Primary Domain */
 
-    if (tree) {
+       /* Build display for: Native OS */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-    }
+       if (tree) {
 
-    offset += 1; /* Skip Word Count (WCT) */
+         proto_tree_add_text(tree, NullTVB, offset, string_len, "Native OS: %s", NativeOS);
 
-    /* Build display for: Setup Length */
+       }
 
-    SetupLength = GSHORT(pd, offset);
+       offset += string_len; /* Skip Native OS */
 
-    if (tree) {
+       /* Build display for: Native LanMan Type */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Setup Length: %u", SetupLength);
+       /*
+        * 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....
+        */
 
-    }
+       NativeLanManType = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-    offset += 2; /* Skip Setup Length */
+       if (tree) {
 
-    /* Build display for: Mode */
+         proto_tree_add_text(tree, NullTVB, offset, string_len, "Native LanMan Type: %s", NativeLanManType);
 
-    Mode = GSHORT(pd, offset);
+       }
 
-    if (tree) {
+       offset += string_len; /* Skip Native LanMan Type */
 
-      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 */
+      break;
 
-    /* Build display for: Byte Count (BCC) */
+    default:
 
-    ByteCount = GSHORT(pd, offset);
+      /* XXX - dump the parameter words, one word at a time? */
 
-    if (tree) {
+      offset += WordCount;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      /* Build display for: Byte Count (BCC) */
 
-    }
+      ByteCount = GSHORT(pd, offset);
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      if (tree) {
 
-    /* Build display for: Buffer Format */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-    BufferFormat = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Byte Count (BCC) */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+      break;
 
     }
 
-    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) {
+    if (AndXCommand != 0xFF) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Identifier String: %s", IdentifierString);
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
     }
 
-    offset += string_len; /* Skip Identifier String */
-
   } else {
     /* Response(s) dissect code */
 
@@ -6188,534 +5139,626 @@ dissect_open_print_file_smb(const u_char *pd, int offset, frame_data *fd, proto_
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: FID */
-
-    FID = GSHORT(pd, offset);
-
-    if (tree) {
+    switch (WordCount) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+    case 3:
 
-    }
+      /* Build display for: AndXCommand */
 
-    offset += 2; /* Skip FID */
+      AndXCommand = GBYTE(pd, offset);
 
-    /* Build display for: Byte Count (BCC) */
+      if (tree) {
 
-    ByteCount = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s",
+                            (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      offset += 1; /* Skip AndXCommand */
 
-    }
+      /* Build display for: AndXReserved */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      AndXReserved = GBYTE(pd, offset);
 
-  }
+      if (tree) {
 
-}
+        proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
-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;
+      offset += 1; /* Skip AndXReserved */
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      /* Build display for: AndXOffset */
 
-    /* Build display for: Word Count (WCT) */
+      AndXOffset = GSHORT(pd, offset);
 
-    WordCount = GBYTE(pd, offset);
+      if (tree) {
 
-    if (tree) {
+        proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      }
 
-    }
+      offset += 2; /* Skip AndXOffset */
 
-    offset += 1; /* Skip Word Count (WCT) */
+      /* Build display for: Action */
 
-    /* Build display for: FID */
+      Action = GSHORT(pd, offset);
 
-    FID = GSHORT(pd, offset);
+      if (tree) {
 
-    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"));
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      }
 
-    }
+      offset += 2; /* Skip Action */
 
-    offset += 2; /* Skip FID */
+      /* Build display for: Byte Count (BCC) */
 
-    /* Build display for: Byte Count (BCC) */
+      ByteCount = GSHORT(pd, offset);
 
-    ByteCount = GSHORT(pd, offset);
+      if (tree) {
 
-    if (tree) {
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      }
 
-    }
+      offset += 2; /* Skip Byte Count (BCC) */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      if (ByteCount > 0) {
 
-  } else {
-    /* Response(s) dissect code */
+        /* Build display for: NativeOS */
 
-    /* Build display for: Word Count */
+        NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-    WordCount = GBYTE(pd, offset);
+        if (tree) {
 
-    if (tree) {
+          proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeOS: %s", NativeOS);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
+        }
 
-    }
+        offset += string_len; /* Skip NativeOS */
 
-    offset += 1; /* Skip Word Count */
+        /* Build display for: NativeLanMan */
 
-    /* Build display for: Byte Count (BCC) */
+        NativeLanMan = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-    ByteCount = GSHORT(pd, offset);
+        if (tree) {
 
-    if (tree) {
+          proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeLanMan: %s", NativeLanMan);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+        }
 
-    }
+        offset += string_len; /* Skip NativeLanMan */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+        /* Build display for: PrimaryDomain */
 
-  }
+        PrimaryDomain = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-}
+        if (tree) {
 
-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)
+          proto_tree_add_text(tree, NullTVB, offset, string_len, "PrimaryDomain: %s", PrimaryDomain);
 
-{
-  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 */
+        offset += string_len; /* Skip PrimaryDomain */
 
-    WordCount = GBYTE(pd, offset);
+      }
 
-    switch (WordCount) {
+      break;
 
-    case 8:
+    case 4:
 
-      /* Build display for: Word Count (WCT) */
+      /* Build display for: AndXCommand */
 
-      WordCount = GBYTE(pd, offset);
+      AndXCommand = GBYTE(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s",
+                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
       }
 
-      offset += 1; /* Skip Word Count (WCT) */
+      offset += 1; /* Skip AndXCommand */
 
-      /* Build display for: FID */
+      /* Build display for: AndXReserved */
 
-      FID = GSHORT(pd, offset);
+      AndXReserved = GBYTE(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
       }
 
-      offset += 2; /* Skip FID */
+      offset += 1; /* Skip AndXReserved */
 
-      /* Build display for: Offset */
+      /* Build display for: AndXOffset */
 
-      Offset = GWORD(pd, offset);
+      AndXOffset = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
       }
 
-      offset += 4; /* Skip Offset */
 
-      /* Build display for: Max Count */
+      offset += 2; /* Skip AndXOffset */
 
-      MaxCount = GSHORT(pd, offset);
+      /* Build display for: Action */
+
+      Action = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+       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"));
 
       }
 
-      offset += 2; /* Skip Max Count */
+      offset += 2; /* Skip Action */
 
-      /* Build display for: Min Count */
+      /* Build display for: Security Blob Length */
 
-      MinCount = GSHORT(pd, offset);
+      SecurityBlobLength = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Security Blob Length: %u", SecurityBlobLength);
 
       }
 
-      offset += 2; /* Skip Min Count */
+      offset += 2; /* Skip Security Blob Length */
 
-      /* Build display for: Timeout */
+      /* Build display for: Byte Count (BCC) */
 
-      Timeout = GWORD(pd, offset);
+      ByteCount = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
       }
 
-      offset += 4; /* Skip Timeout */
+      offset += 2; /* Skip Byte Count (BCC) */
 
-      /* Build display for: Reserved */
+      if (ByteCount > 0) {
 
-      Reserved = GSHORT(pd, offset);
+       SecurityBlob = pd + offset;
 
-      if (tree) {
+       if (SecurityBlobLength > 0) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+         /* XXX - is this ASN.1-encoded?  Is it a Kerberos data structure,
+            at least in NT 5.0-and-later server replies? */
 
-      }
+         if (tree) {
 
-      offset += 2; /* Skip Reserved */
+           proto_tree_add_text(tree, NullTVB, offset, SecurityBlobLength, "Security Blob: %s",
+                               bytes_to_str(SecurityBlob, SecurityBlobLength));
 
-      /* Build display for: Byte Count (BCC) */
+         }
 
-      ByteCount = GSHORT(pd, offset);
+         offset += SecurityBlobLength; /* Skip Security Blob */
 
-      if (tree) {
+       }
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       /* Build display for: NativeOS */
 
-      }
+       NativeOS = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-      offset += 2; /* Skip Byte Count (BCC) */
+       if (tree) {
 
-    break;
+         proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeOS: %s", NativeOS);
 
-    case 10:
+       }
 
-      /* Build display for: Word Count (WCT) */
+       offset += string_len; /* Skip NativeOS */
 
-      WordCount = GBYTE(pd, offset);
+       /* Build display for: NativeLanMan */
 
-      if (tree) {
+       NativeLanMan = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       if (tree) {
 
-      }
+         proto_tree_add_text(tree, NullTVB, offset, string_len, "NativeLanMan: %s", NativeLanMan);
 
-      offset += 1; /* Skip Word Count (WCT) */
+       }
 
-      /* Build display for: FID */
+       offset += string_len; /* Skip NativeLanMan */
 
-      FID = GSHORT(pd, offset);
+      }
 
-      if (tree) {
+      break;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+    default:
 
-      }
+      /* XXX - dump the parameter words, one word at a time? */
 
-      offset += 2; /* Skip FID */
+      offset += WordCount;
 
-      /* Build display for: Offset */
+      /* Build display for: Byte Count (BCC) */
 
-      Offset = GWORD(pd, offset);
+      ByteCount = GSHORT(pd, offset);
 
       if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
       }
 
-      offset += 4; /* Skip Offset */
+      offset += 2; /* Skip Byte Count (BCC) */
 
-      /* Build display for: Max Count */
+      break;
 
-      MaxCount = GSHORT(pd, offset);
+    }
 
-      if (tree) {
+    if (AndXCommand != 0xFF) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
-      }
+    }
 
-      offset += 2; /* Skip Max Count */
+  }
 
-      /* Build display for: Min Count */
+}
 
-      MinCount = GSHORT(pd, 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)
 
-      if (tree) {
+{
+  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;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
+  wct = pd[offset];
 
-      }
+  /* Now figure out what format we are talking about, 2, 3, or 4 response
+   * words ...
+   */
 
-      offset += 2; /* Skip Min Count */
+  if (!(si.request && (wct == 4)) && !(!si.request && (wct == 2)) &&
+      !(!si.request && (wct == 3)) && !(wct == 0)) {
 
-      /* Build display for: Timeout */
+    if (tree) {
 
-      Timeout = GWORD(pd, offset);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Invalid TCON_ANDX format. WCT should be 0, 2, 3, or 4 ..., not %u", wct);
 
-      if (tree) {
+      proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data");
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
+      return;
 
-      }
+    }
+    
+  }
 
-      offset += 4; /* Skip Timeout */
+  if (tree) {
 
-      /* Build display for: Reserved */
+    proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", wct);
 
-      Reserved = GSHORT(pd, offset);
+  }
 
-      if (tree) {
+  offset += 1;
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+  if (wct > 0) {
 
-      }
+    andxcmd = pd[offset];
 
-      offset += 2; /* Skip Reserved */
+    if (tree) {
 
-      /* Build display for: Offset High */
+      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]);
 
-      OffsetHigh = GWORD(pd, offset);
+    }
 
-      if (tree) {
+    offset += 2;
 
-        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
+    andxoffs = GSHORT(pd, offset);
 
-      }
+    if (tree) {
 
-      offset += 4; /* Skip Offset High */
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Offset to next command: %u", andxoffs);
 
-      /* Build display for: Byte Count (BCC) */
+    }
 
-      ByteCount = GSHORT(pd, offset);
+    offset += 2;
 
-      if (tree) {
+  }
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+  switch (wct) {
 
-      }
+  case 0:
 
-      offset += 2; /* Skip Byte Count (BCC) */
+    bcc = GSHORT(pd, offset);
+
+    if (tree) {
 
-    break;
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
 
     }
 
-  } else {
-    /* Response(s) dissect code */
+    break;
 
-  }
+  case 4:
 
-}
+    flags = GSHORT(pd, offset);
 
-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)
+    if (tree) {
 
-{
-  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;
+      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"));
 
-  if (si.request) {
-    /* Request(s) dissect code */
+    }
 
-    /* Build display for: Word Count (WCT) */
+    offset += 2;
 
-    WordCount = GBYTE(pd, offset);
+    passwdlen = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Password Length: %u", passwdlen);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: AndXCommand */
+    offset += 2;
 
-    AndXCommand = GBYTE(pd, offset);
+    bcc = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
 
     }
 
-    offset += 1; /* Skip AndXCommand */
-
-    /* Build display for: AndXReserved */
+    offset += 2;
 
-    AndXReserved = GBYTE(pd, offset);
+    str = pd + offset;
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Password: %s", format_text(str, passwdlen));
 
     }
 
-    offset += 1; /* Skip AndXReserved */
-
-    /* Build display for: AndXOffset */
+    offset += passwdlen;
 
-    AndXOffset = GSHORT(pd, offset);
+    str = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+      proto_tree_add_text(tree, NullTVB, offset, string_len, "Path: %s", str);
 
     }
 
-    offset += 2; /* Skip AndXOffset */
-
-    /* Build display for: FID */
+    offset += string_len;
 
-    FID = GSHORT(pd, offset);
+    str = pd + offset;
 
     if (tree) {
-       
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
-       
+
+      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service: %s", str);
+
     }
 
-    offset += 2; /* Skip FID */
+    break;
 
-    /* Build display for: Offset */
+  case 2:
 
-    Offset = GWORD(pd, offset);
+    bcc = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
 
     }
 
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Max Count */
+    offset += 2;
 
-    MaxCount = GSHORT(pd, offset);
+    str = pd + offset;
 
     if (tree) {
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service Type: %s",
+                         str);
 
     }
 
-    offset += 2; /* Skip Max Count */
+    offset += strlen(str) + 1;
 
-    /* Build display for: Min Count */
+    break;
 
-    MinCount = GSHORT(pd, offset);
+  case 3:
 
-    if (tree) {
+    optionsup = GSHORT(pd, offset);
 
-        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
+    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; /* Skip Min Count */
-
-    /* Build display for: Reserved */
+    offset += 2;
 
-    Reserved = GWORD(pd, offset);
+    bcc = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", bcc);
 
     }
 
-    offset += 4; /* Skip Reserved */
+    offset += 2;
 
-    /* Build display for: Remaining */
+    /*
+     * NOTE: the Service string is always ASCII, even if the "strings are
+     * Unicode" bit is set in the flags2 field of the SMB.
+     */
 
-    Remaining = GSHORT(pd, offset);
+    str = pd + offset;
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+      proto_tree_add_text(tree, NullTVB, offset, strlen(str) + 1, "Service: %s", str);
 
     }
 
-    offset += 2; /* Skip Remaining */
-
-    if (WordCount == 12) {
-
-       /* Build display for: Offset High */
-
-       OffsetHigh = GWORD(pd, offset);
+    offset += strlen(str) + 1;
 
-       if (tree) {
+    str = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
-           proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
+    if (tree) {
 
-       }
+      proto_tree_add_text(tree, NullTVB, offset, string_len, "Native File System: %s", str);
 
-       offset += 4; /* Skip Offset High */
     }
 
-    /* Build display for: Byte Count (BCC) */
+    offset += string_len;
 
-    ByteCount = GSHORT(pd, offset);
+    
+    break;
 
-    if (tree) {
+  default:
+       ; /* nothing */
+       break;
+  }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+  if (andxcmd != 0xFF) /* Process that next command ... ??? */
 
-    }
+    (dissect[andxcmd])(pd, SMB_offset + andxoffs, fd, parent, tree, si, max_data - offset, SMB_offset);
 
-    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_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;
 
-  } else {
-    /* Response(s) dissect code */
+  if (si.request) {
+    /* Request(s) dissect code */
 
     /* Build display for: Word Count (WCT) */
 
@@ -6735,7 +5778,8 @@ dissect_read_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+                         (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
     }
 
@@ -6765,195 +5809,204 @@ dissect_read_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     offset += 2; /* Skip AndXOffset */
 
-    /* Build display for: Remaining */
+    /* Build display for: Flags */
 
-    Remaining = GSHORT(pd, offset);
+    Flags = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
-
+      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 Remaining */
+    offset += 2; /* Skip Flags */
 
-    /* Build display for: Data Compaction Mode */
+    /* Build display for: Desired Access */
 
-    DataCompactionMode = GSHORT(pd, offset);
+    DesiredAccess = GSHORT(pd, offset);
 
     if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
-
+      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 Data Compaction Mode */
+    offset += 2; /* Skip Desired Access */
 
-    /* Build display for: Reserved */
+    /* Build display for: Search */
 
-    Reserved = GSHORT(pd, offset);
+    Search = GSHORT(pd, offset);
 
     if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
-
+      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 Reserved */
+    offset += 2; /* Skip Search */
 
-    /* Build display for: Data Length */
+    /* Build display for: File */
 
-    DataLength = GSHORT(pd, offset);
+    File = GSHORT(pd, offset);
 
     if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
-
+      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 Data Length */
+    offset += 2; /* Skip File */
 
-    /* Build display for: Data Offset */
+    /* Build display for: Creation Time */
 
-    DataOffset = GSHORT(pd, offset);
+    CreationTime = 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;
-    }
+    offset += 2; /* Skip Creation Time */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: Creation Date */
 
-    ByteCount = GSHORT(pd, offset);
+    CreationDate = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      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 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);
+    offset += 2; /* Skip Creation Date */
 
-    }
+    /* Build display for: Open Function */
 
-    if (AndXCommand != 0xFF) {
+    OpenFunction = GSHORT(pd, offset);
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_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"));
+    
     }
 
-  }
-
-}
-
-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 */
+    offset += 2; /* Skip Open Function */
 
-    /* Build display for: Word Count (WCT) */
+    /* Build display for: Allocated Size */
 
-    WordCount = GBYTE(pd, offset);
+    AllocatedSize = GWORD(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Allocated Size: %u", AllocatedSize);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: AndXCommand */
-
-      AndXCommand = GBYTE(pd, offset);
+    offset += 4; /* Skip Allocated Size */
 
-      if (tree) {
+    /* Build display for: Reserved1 */
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+    Reserved1 = GWORD(pd, offset);
 
-      }
+    if (tree) {
 
-      offset += 1; /* Skip AndXCommand */
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved1: %u", Reserved1);
 
-      /* Build display for: AndXReserved */
+    }
 
-      AndXReserved = GBYTE(pd, offset);
+    offset += 4; /* Skip Reserved1 */
 
-      if (tree) {
+    /* Build display for: Reserved2 */
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+    Reserved2 = GWORD(pd, offset);
 
-      }
+    if (tree) {
 
-      offset += 1; /* Skip AndXReserved */
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved2: %u", Reserved2);
 
-      /* Build display for: AndXOffset */
+    }
 
-      AndXOffset = GSHORT(pd, offset);
+    offset += 4; /* Skip Reserved2 */
 
-      if (tree) {
+    /* Build display for: Byte Count */
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+    ByteCount = GSHORT(pd, offset);
 
-      }
+    if (tree) {
 
-      offset += 2; /* Skip AndXOffset */
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
     }
 
-    /* Build display for: Byte Count (BCC) */
+    offset += 2; /* Skip Byte Count */
 
-    ByteCount = GSHORT(pd, offset);
+    /* 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, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += string_len; /* Skip File Name */
 
 
     if (AndXCommand != 0xFF) {
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
     }
 
@@ -6980,7 +6033,8 @@ dissect_logoff_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
       }
 
@@ -6996,181 +6050,215 @@ dissect_logoff_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
       }
 
-      offset += 1; /* Skip 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: AndXOffset */
+      /* Build display for: FileAttributes */
 
-      AndXOffset = GSHORT(pd, offset);
+      FileAttributes = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
-
+       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 AndXOffset */
-
-    }
+      offset += 2; /* Skip FileAttributes */
 
-    /* Build display for: Byte Count (BCC) */
+      /* Build display for: Last Write Time */
 
-    ByteCount = GSHORT(pd, offset);
+      LastWriteTime = GSHORT(pd, offset);
 
-    if (tree) {
+      if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      }
 
-    }
+      offset += 2; /* Skip Last Write Time */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      /* Build display for: Last Write Date */
 
+      LastWriteDate = GSHORT(pd, offset);
 
-    if (AndXCommand != 0xFF) {
+      if (tree) {
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+       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 */
 
-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)
+      /* Build display for: Data Size */
 
-{
-  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;
+      DataSize = GWORD(pd, offset);
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      if (tree) {
 
-    /* Build display for: Word Count (WCT) */
+       proto_tree_add_text(tree, NullTVB, offset, 4, "Data Size: %u", DataSize);
 
-    WordCount = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 4; /* Skip Data Size */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      /* Build display for: Granted Access */
 
-    }
+      GrantedAccess = GSHORT(pd, offset);
 
-    offset += 1; /* Skip Word Count (WCT) */
+      if (tree) {
 
-    /* Build display for: FID */
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Granted Access: %u", GrantedAccess);
 
-    FID = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Granted Access */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      /* Build display for: File Type */
 
-    }
+      FileType = GSHORT(pd, offset);
 
-    offset += 2; /* Skip FID */
+      if (tree) {
 
-    /* Build display for: Mode */
+       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"));
+    
+      }
 
-    Mode = GSHORT(pd, offset);
+      offset += 2; /* Skip File Type */
 
-    if (tree) {
+      /* Build display for: Device State */
 
-      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"));
-    
-    }
+      DeviceState = GSHORT(pd, offset);
 
-    offset += 2; /* Skip Mode */
+      if (tree) {
 
-    /* Build display for: Offset */
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Device State: %u", DeviceState);
 
-    Offset = GWORD(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Device State */
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+      /* Build display for: Action */
 
-    }
+      Action = GSHORT(pd, offset);
 
-    offset += 4; /* Skip Offset */
+      if (tree) {
 
-    /* Build display for: Byte Count (BCC) */
+       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 */
 
-    ByteCount = GSHORT(pd, offset);
+      /* Build display for: Server FID */
+      
+      ServerFID = GWORD(pd, offset);
 
-    if (tree) {
+      if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+       proto_tree_add_text(tree, NullTVB, offset, 4, "Server FID: %u", ServerFID);
 
-    }
+      }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      offset += 4; /* Skip Server FID */
 
-  } else {
-    /* Response(s) dissect code */
+      /* Build display for: Reserved */
 
-    /* Build display for: Word Count (WCT) */
+      Reserved = GSHORT(pd, offset);
 
-    WordCount = GBYTE(pd, offset);
+      if (tree) {
+       
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      offset += 2; /* Skip Reserved */
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: Offset */
+    /* Build display for: Byte Count */
 
-    Offset = GWORD(pd, offset);
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
     }
 
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Byte Count (BCC) */
+    offset += 2; /* Skip Byte Count */
 
-    ByteCount = GSHORT(pd, offset);
 
-    if (tree) {
+    if (AndXCommand != 0xFF) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
     }
 
-    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)
+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        BufferFormat;
+  guint8        Pad;
+  guint32       Timeout;
+  guint32       Reserved2;
   guint32       Offset;
+  guint16       WriteMode;
+  guint16       Reserved1;
   guint16       Remaining;
   guint16       FID;
+  guint16       DataOffset;
   guint16       DataLength;
   guint16       Count;
   guint16       ByteCount;
@@ -7178,376 +6266,306 @@ dissect_write_and_unlock_smb(const u_char *pd, int offset, frame_data *fd, proto
   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);
+    switch (WordCount) {
 
-    if (tree) {
+    case 12:
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      /* Build display for: Word Count (WCT) */
 
-    }
+      WordCount = GBYTE(pd, offset);
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      if (tree) {
 
-    /* Build display for: Buffer Format */
+        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
-    BufferFormat = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 1; /* Skip Word Count (WCT) */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+      /* Build display for: FID */
 
-    }
+      FID = GSHORT(pd, offset);
 
-    offset += 1; /* Skip Buffer Format */
+      if (tree) {
 
-    /* Build display for: Data Length */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
-    DataLength = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip FID */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+      /* Build display for: Count */
 
-    }
+      Count = GSHORT(pd, offset);
 
-    offset += 2; /* Skip Data Length */
+      if (tree) {
 
-  } else {
-    /* Response(s) dissect code */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
 
-    /* Build display for: Word Count (WCT) */
+      }
 
-    WordCount = GBYTE(pd, offset);
+      offset += 2; /* Skip Count */
 
-    if (tree) {
+      /* Build display for: Reserved 1 */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      Reserved1 = GSHORT(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 1; /* Skip Word Count (WCT) */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
 
-    /* Build display for: Count */
+      }
 
-    Count = GSHORT(pd, offset);
+      offset += 2; /* Skip Reserved 1 */
 
-    if (tree) {
+      /* Build display for: Offset */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+      Offset = GWORD(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 2; /* Skip Count */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
-    /* Build display for: Byte Count (BCC) */
+      }
 
-    ByteCount = GSHORT(pd, offset);
+      offset += 4; /* Skip Offset */
 
-    if (tree) {
+      /* Build display for: Timeout */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      Timeout = GWORD(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 2; /* Skip Byte Count (BCC) */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
 
-  }
+      }
 
-}
+      offset += 4; /* Skip Timeout */
 
-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)
+      /* Build display for: WriteMode */
 
-{
-  guint8        WordCount;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
-  guint16       LastAccessTime;
-  guint16       LastAccessDate;
-  guint16       FID;
-  guint16       CreationTime;
-  guint16       CreationDate;
-  guint16       ByteCount;
+      WriteMode = GSHORT(pd, offset);
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      if (tree) {
 
-    /* Build display for: Word Count */
+        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)"));
+      
+      }
 
-    WordCount = GBYTE(pd, offset);
+      offset += 2; /* Skip WriteMode */
 
-    if (tree) {
+      /* Build display for: Reserved 2 */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
+      Reserved2 = GWORD(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 1; /* Skip Word Count */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 2: %u", Reserved2);
 
-    /* Build display for: FID */
+      }
 
-    FID = GSHORT(pd, offset);
+      offset += 4; /* Skip Reserved 2 */
 
-    if (tree) {
+      /* Build display for: Data Length */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      DataLength = GSHORT(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 2; /* Skip FID */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
 
-    /* Build display for: Creation Date */
+      }
 
-    CreationDate = GSHORT(pd, offset);
+      offset += 2; /* Skip Data Length */
 
-    if (tree) {
+      /* Build display for: Data Offset */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
+      DataOffset = GSHORT(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 2; /* Skip Creation Date */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
 
-    /* Build display for: Creation Time */
+      }
 
-    CreationTime = GSHORT(pd, offset);
+      offset += 2; /* Skip Data Offset */
 
-    if (tree) {
+      /* Build display for: Byte Count (BCC) */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
+      ByteCount = GSHORT(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 2; /* Skip Creation Time */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-    /* Build display for: Last Access Date */
+      }
 
-    LastAccessDate = GSHORT(pd, offset);
+      offset += 2; /* Skip Byte Count (BCC) */
 
-    if (tree) {
+      /* Build display for: Pad */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Date: %s", dissect_dos_date(LastAccessDate));
+      Pad = GBYTE(pd, offset);
 
-    }
+      if (tree) {
 
-    offset += 2; /* Skip Last Access Date */
+        proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
 
-    /* Build display for: Last Access Time */
+      }
 
-    LastAccessTime = GSHORT(pd, offset);
+      offset += 1; /* Skip Pad */
 
-    if (tree) {
+    break;
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Time: %s", dissect_dos_time(LastAccessTime));
+    case 14:
 
-    }
+      /* Build display for: Word Count (WCT) */
 
-    offset += 2; /* Skip Last Access Time */
+      WordCount = GBYTE(pd, offset);
 
-    /* Build display for: Last Write Date */
+      if (tree) {
 
-    LastWriteDate = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
+      offset += 1; /* Skip Word Count (WCT) */
 
-    }
+      /* Build display for: FID */
 
-    offset += 2; /* Skip Last Write Date */
+      FID = GSHORT(pd, offset);
 
-    /* Build display for: Last Write Time */
+      if (tree) {
 
-    LastWriteTime = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
+      offset += 2; /* Skip FID */
 
-    }
+      /* Build display for: Count */
 
-    offset += 2; /* Skip Last Write Time */
+      Count = GSHORT(pd, offset);
 
-    /* Build display for: Byte Count (BCC) */
+      if (tree) {
 
-    ByteCount = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      offset += 2; /* Skip Count */
 
-    }
+      /* Build display for: Reserved 1 */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      Reserved1 = GSHORT(pd, offset);
 
-  } else {
-    /* Response(s) dissect code */
+      if (tree) {
 
-    /* Build display for: Word Count (WCC) */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
 
-    WordCount = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Reserved 1 */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCC): %u", WordCount);
+      /* Build display for: Timeout */
 
-    }
+      Timeout = GWORD(pd, offset);
 
-    offset += 1; /* Skip Word Count (WCC) */
+      if (tree) {
 
-    /* Build display for: Byte Count (BCC) */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
 
-    ByteCount = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 4; /* Skip Timeout */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      /* Build display for: WriteMode */
 
-    }
+      WriteMode = GSHORT(pd, offset);
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      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 */
 
-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)
+      /* Build display for: Reserved 2 */
 
-{
-  guint8        WordCount;
-  guint32       Offset;
-  guint32       Count;
-  guint16       FID;
-  guint16       ByteCount;
+      Reserved2 = GWORD(pd, offset);
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      if (tree) {
 
-    /* Build display for: Word Count (WCT) */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved 2: %u", Reserved2);
 
-    WordCount = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 4; /* Skip Reserved 2 */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      /* Build display for: Data Length */
 
-    }
+      DataLength = GSHORT(pd, offset);
 
-    offset += 1; /* Skip Word Count (WCT) */
+      if (tree) {
 
-    /* Build display for: FID */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
 
-    FID = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Data Length */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      /* Build display for: Data Offset */
 
-    }
+      DataOffset = GSHORT(pd, offset);
 
-    offset += 2; /* Skip FID */
+      if (tree) {
 
-    /* Build display for: Count */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
 
-    Count = GWORD(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Data Offset */
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Count: %u", Count);
+      /* Build display for: Byte Count (BCC) */
 
-    }
+      ByteCount = GSHORT(pd, offset);
 
-    offset += 4; /* Skip Count */
+      if (tree) {
 
-    /* Build display for: Offset */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-    Offset = GWORD(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Byte Count (BCC) */
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+      /* Build display for: Pad */
 
-    }
+      Pad = GBYTE(pd, offset);
 
-    offset += 4; /* Skip Offset */
+      if (tree) {
 
-    /* Build display for: Byte Count (BCC) */
+        proto_tree_add_text(tree, NullTVB, offset, 1, "Pad: %u", Pad);
 
-    ByteCount = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 1; /* Skip Pad */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+    break;
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
-
   } else {
     /* Response(s) dissect code */
 
@@ -7563,73 +6581,100 @@ dissect_lock_bytes_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Byte Count (BCC) */
+    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 (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 2; /* Skip Byte Count */
 
   }
 
 }
 
+
 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)
+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       StartIndex;
-  guint16       RestartIndex;
-  guint16       MaxCount;
-  guint16       DataLength;
-  guint16       Count;
+  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 */
+    /* Build display for: Word Count (WCT) */
 
     WordCount = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
     }
 
-    offset += 1; /* Skip Word Count */
+    offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Max Count */
+    /* Build display for: Setup Length */
 
-    MaxCount = GSHORT(pd, offset);
+    SetupLength = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Setup Length: %u", SetupLength);
 
     }
 
-    offset += 2; /* Skip Max Count */
+    offset += 2; /* Skip Setup Length */
 
-    /* Build display for: Start Index */
+    /* Build display for: Mode */
 
-    StartIndex = GSHORT(pd, offset);
+    Mode = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Start Index: %u", StartIndex);
-
+      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 Start Index */
+    offset += 2; /* Skip Mode */
 
     /* Build display for: Byte Count (BCC) */
 
@@ -7643,61 +6688,6 @@ dissect_get_print_queue_smb(const u_char *pd, int offset, frame_data *fd, proto_
 
     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);
@@ -7712,43 +6702,20 @@ dissect_get_print_queue_smb(const u_char *pd, int offset, frame_data *fd, proto_
 
     offset += 1; /* Skip Buffer Format */
 
-    /* Build display for: Data Length */
+    /* Build display for: Identifier String */
 
-    DataLength = GSHORT(pd, offset);
+    IdentifierString = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+      proto_tree_add_text(tree, NullTVB, offset, string_len, "Identifier String: %s", IdentifierString);
 
     }
 
-    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;
+    offset += string_len; /* Skip Identifier String */
 
-  if (si.request) {
-    /* Request(s) dissect code */
+  } else {
+    /* Response(s) dissect code */
 
     /* Build display for: Word Count (WCT) */
 
@@ -7762,299 +6729,300 @@ dissect_locking_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tre
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: AndXCommand */
+    /* Build display for: FID */
 
-    AndXCommand = GBYTE(pd, offset);
+    FID = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                         (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
     }
 
-    offset += 1; /* Skip AndXCommand */
+    offset += 2; /* Skip FID */
 
-    /* Build display for: AndXReserved */
+    /* Build display for: Byte Count (BCC) */
 
-    AndXReserved = GBYTE(pd, offset);
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    offset += 1; /* Skip AndXReserved */
+    offset += 2; /* Skip Byte Count (BCC) */
 
-    /* Build display for: AndXOffset */
+  }
 
-    AndXOffset = GSHORT(pd, offset);
+}
 
-    if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+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;
 
-    offset += 2; /* Skip AndXOffset */
+  if (si.request) {
+    /* Request(s) dissect code */
 
-    /* Build display for: FID */
+    WordCount = GBYTE(pd, offset);
 
-    FID = GSHORT(pd, offset);
+    switch (WordCount) {
 
-    if (tree) {
+    case 8:
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      /* Build display for: Word Count (WCT) */
 
-    }
+      WordCount = GBYTE(pd, offset);
 
-    offset += 2; /* Skip FID */
+      if (tree) {
 
-    /* Build display for: Lock Type */
+        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
-    LockType = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 1; /* Skip Word Count (WCT) */
 
-      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"));
-    
-    }
+      /* Build display for: FID */
 
-    offset += 1; /* Skip Lock Type */
+      FID = GSHORT(pd, offset);
 
-    /* Build display for: OplockLevel */
+      if (tree) {
 
-    OplockLevel = GBYTE(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "OplockLevel: %u", OplockLevel);
+      offset += 2; /* Skip FID */
 
-    }
+      /* Build display for: Offset */
 
-    offset += 1; /* Skip OplockLevel */
+      Offset = GWORD(pd, offset);
 
-    /* Build display for: Timeout */
+      if (tree) {
 
-    Timeout = GWORD(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
+      offset += 4; /* Skip Offset */
 
-    }
+      /* Build display for: Max Count */
 
-    offset += 4; /* Skip Timeout */
+      MaxCount = GSHORT(pd, offset);
 
-    /* Build display for: Number Of Unlocks */
+      if (tree) {
 
-    NumberOfUnlocks = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Number Of Unlocks: %u", NumberOfUnlocks);
+      offset += 2; /* Skip Max Count */
 
-    }
+      /* Build display for: Min Count */
 
-    offset += 2; /* Skip Number Of Unlocks */
+      MinCount = GSHORT(pd, offset);
 
-    /* Build display for: Number of Locks */
+      if (tree) {
 
-    NumberofLocks = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Number of Locks: %u", NumberofLocks);
+      offset += 2; /* Skip Min Count */
 
-    }
+      /* Build display for: Timeout */
 
-    offset += 2; /* Skip Number of Locks */
+      Timeout = GWORD(pd, offset);
 
-    /* Build display for: Byte Count (BCC) */
+      if (tree) {
 
-    ByteCount = GSHORT(pd, offset);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      offset += 4; /* Skip Timeout */
 
-    }
+      /* Build display for: Reserved */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      Reserved = GSHORT(pd, offset);
 
+      if (tree) {
 
-    if (AndXCommand != 0xFF) {
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+      }
 
-    }
+      offset += 2; /* Skip Reserved */
 
-  } else {
-    /* Response(s) dissect code */
+      /* Build display for: Byte Count (BCC) */
 
-    /* Build display for: Word Count (WCT) */
+      ByteCount = GSHORT(pd, offset);
 
-    WordCount = GBYTE(pd, offset);
+      if (tree) {
 
-    if (tree) {
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      }
 
-    }
+      offset += 2; /* Skip Byte Count (BCC) */
 
-    offset += 1; /* Skip Word Count (WCT) */
+    break;
 
-    if (WordCount != 0) {
+    case 10:
 
-      /* Build display for: AndXCommand */
+      /* Build display for: Word Count (WCT) */
 
-      AndXCommand = GBYTE(pd, offset);
+      WordCount = GBYTE(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
-                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
+        proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
       }
 
-      offset += 1; /* Skip AndXCommand */
+      offset += 1; /* Skip Word Count (WCT) */
 
-      /* Build display for: AndXReserved */
+      /* Build display for: FID */
 
-      AndXReserved = GBYTE(pd, offset);
+      FID = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
 
       }
 
-      offset += 1; /* Skip AndXReserved */
+      offset += 2; /* Skip FID */
 
-      /* Build display for: AndXoffset */
+      /* Build display for: Offset */
 
-      AndXoffset = GSHORT(pd, offset);
+      Offset = GWORD(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXoffset: %u", AndXoffset);
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
       }
 
-      offset += 2; /* Skip AndXoffset */
-
-    }
+      offset += 4; /* Skip Offset */
 
-    /* Build display for: Byte Count */
+      /* Build display for: Max Count */
 
-    ByteCount = GSHORT(pd, offset);
+      MaxCount = GSHORT(pd, offset);
 
-    if (tree) {
+      if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
 
-    }
+      }
 
-    offset += 2; /* Skip Byte Count */
+      offset += 2; /* Skip Max Count */
 
+      /* Build display for: Min Count */
 
-    if (AndXCommand != 0xFF) {
+      MinCount = GSHORT(pd, offset);
 
-      (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset);
+      if (tree) {
 
-    }
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
 
-  }
+      }
 
-}
+      offset += 2; /* Skip Min Count */
 
-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)
+      /* Build display for: Timeout */
 
-{
-  guint8        WordCount;
-  guint32       Offset;
-  guint32       Count;
-  guint16       FID;
-  guint16       ByteCount;
+      Timeout = GWORD(pd, offset);
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      if (tree) {
 
-    /* Build display for: Word Count (WCT) */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
 
-    WordCount = GBYTE(pd, offset);
+      }
 
-    if (tree) {
+      offset += 4; /* Skip Timeout */
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      /* Build display for: Reserved */
 
-    }
+      Reserved = GSHORT(pd, offset);
 
-    offset += 1; /* Skip Word Count (WCT) */
+      if (tree) {
 
-    /* Build display for: FID */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
 
-    FID = GSHORT(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Reserved */
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      /* Build display for: Offset High */
 
-    }
+      OffsetHigh = GWORD(pd, offset);
 
-    offset += 2; /* Skip FID */
+      if (tree) {
 
-    /* Build display for: Count */
+        proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
 
-    Count = GWORD(pd, offset);
+      }
 
-    if (tree) {
+      offset += 4; /* Skip Offset High */
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Count: %u", Count);
+      /* Build display for: Byte Count (BCC) */
 
-    }
+      ByteCount = GSHORT(pd, offset);
 
-    offset += 4; /* Skip Count */
+      if (tree) {
 
-    /* Build display for: Offset */
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-    Offset = GWORD(pd, offset);
+      }
 
-    if (tree) {
+      offset += 2; /* Skip Byte Count (BCC) */
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+    break;
 
     }
 
-    offset += 4; /* Skip Offset */
-
-    /* Build display for: Byte Count (BCC) */
-
-    ByteCount = GSHORT(pd, offset);
+  } else {
+    /* Response(s) dissect code */
 
-    if (tree) {
+  }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+}
 
-    }
+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)
 
-    offset += 2; /* Skip Byte Count (BCC) */
+{
+  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;
 
-  } else {
-    /* Response(s) dissect code */
+  if (si.request) {
+    /* Request(s) dissect code */
 
     /* Build display for: Word Count (WCT) */
 
@@ -8068,158 +7036,129 @@ dissect_unlock_bytes_smb(const u_char *pd, int offset, frame_data *fd, proto_tre
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: AndXCommand */
 
-    ByteCount = GSHORT(pd, offset);
+    AndXCommand = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 1; /* Skip AndXCommand */
 
-  }
+    /* Build display for: AndXReserved */
+
+    AndXReserved = GBYTE(pd, offset);
 
-}
+    if (tree) {
 
-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_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
-{
-  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 */
+    offset += 1; /* Skip AndXReserved */
 
-    /* Build display for: Word Count (WCT) */
+    /* Build display for: AndXOffset */
 
-    WordCount = GBYTE(pd, offset);
+    AndXOffset = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
+    offset += 2; /* Skip AndXOffset */
 
-    /* Build display for: Attributes */
+    /* Build display for: FID */
 
-    Attributes = GSHORT(pd, offset);
+    FID = 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"));
-    
+       
+      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       
     }
 
-    offset += 2; /* Skip Attributes */
+    offset += 2; /* Skip FID */
 
-    /* Build display for: Creation Time */
+    /* Build display for: Offset */
 
-    CreationTime = GSHORT(pd, offset);
+    Offset = GWORD(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
     }
 
-    offset += 2; /* Skip Creation Time */
+    offset += 4; /* Skip Offset */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: Max Count */
 
-    ByteCount = GSHORT(pd, offset);
+    MaxCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 2; /* Skip Max Count */
 
-    /* Build display for: Buffer Format */
+    /* Build display for: Min Count */
 
-    BufferFormat = GBYTE(pd, offset);
+    MinCount = GSHORT(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);
+        proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
 
     }
 
-    offset += 1; /* Skip Buffer Format */
+    offset += 2; /* Skip Min Count */
 
-    /* Build display for: File Name */
+    /* Build display for: Reserved */
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+    Reserved = GWORD(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
 
     }
 
-    offset += string_len; /* Skip File Name */
-
-  } else {
-    /* Response(s) dissect code */
+    offset += 4; /* Skip Reserved */
 
-    /* Build display for: Word Count (WCT) */
+    /* Build display for: Remaining */
 
-    WordCount = GBYTE(pd, offset);
+    Remaining = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
+    offset += 2; /* Skip Remaining */
 
-    if (WordCount != 0) {
+    if (WordCount == 12) {
 
-      /* Build display for: FID */
+       /* Build display for: Offset High */
 
-      FID = GSHORT(pd, offset);
+       OffsetHigh = GWORD(pd, offset);
 
-      if (tree) {
+       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+           proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
 
-      }
+       }
 
-      offset += 2; /* Skip FID */
-      
+       offset += 4; /* Skip Offset High */
     }
-    
+
     /* Build display for: Byte Count (BCC) */
 
     ByteCount = GSHORT(pd, offset);
@@ -8232,29 +7171,16 @@ dissect_create_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
     offset += 2; /* Skip Byte Count (BCC) */
 
-  }
 
-}
+    if (AndXCommand != 0xFF) {
 
-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)
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, 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 */
+  } else {
+    /* Response(s) dissect code */
 
     /* Build display for: Word Count (WCT) */
 
@@ -8268,123 +7194,114 @@ dissect_search_dir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Max Count */
+    /* Build display for: AndXCommand */
 
-    MaxCount = GSHORT(pd, offset);
+    AndXCommand = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
 
     }
 
-    offset += 2; /* Skip Max Count */
+    offset += 1; /* Skip AndXCommand */
 
-    /* Build display for: Search Attributes */
+    /* Build display for: AndXReserved */
 
-    SearchAttributes = GSHORT(pd, offset);
+    AndXReserved = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
     }
 
-    offset += 2; /* Skip Search Attributes */
+    offset += 1; /* Skip AndXReserved */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: AndXOffset */
 
-    ByteCount = GSHORT(pd, offset);
+    AndXOffset = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 2; /* Skip AndXOffset */
 
-    /* Build display for: Buffer Format 1 */
+    /* Build display for: Remaining */
 
-    BufferFormat1 = GBYTE(pd, offset);
+    Remaining = GSHORT(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);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
 
     }
 
-    offset += 1; /* Skip Buffer Format 1 */
+    offset += 2; /* Skip Remaining */
 
-    /* Build display for: File Name */
+    /* Build display for: Data Compaction Mode */
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+    DataCompactionMode = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
 
     }
 
-    offset += string_len; /* Skip File Name */
+    offset += 2; /* Skip Data Compaction Mode */
 
-    /* Build display for: Buffer Format 2 */
+    /* Build display for: Reserved */
 
-    BufferFormat2 = GBYTE(pd, offset);
+    Reserved = GSHORT(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);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
 
     }
 
-    offset += 1; /* Skip Buffer Format 2 */
+    offset += 2; /* Skip Reserved */
 
-    /* Build display for: Resume Key Length */
+    /* Build display for: Data Length */
 
-    ResumeKeyLength = GSHORT(pd, offset);
+    DataLength = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Resume Key Length: %u", ResumeKeyLength);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
 
     }
 
-    offset += 2; /* Skip Resume Key Length */
-
-  } else {
-    /* Response(s) dissect code */
+    offset += 2; /* Skip Data Length */
 
-    /* Build display for: Word Count (WCT) */
+    /* Build display for: Data Offset */
 
-    WordCount = GBYTE(pd, offset);
+    DataOffset = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
-
-    if (WordCount != 0) {
-
-      /* Build display for: Count */
-
-      Count = GSHORT(pd, offset);
+    offset += 2; /* Skip Data Offset */
 
-      if (tree) {
+    /* Build display for: Reserved[5] */
+    for(i = 1; i <= 5; ++i) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+       Reserved = GSHORT(pd, offset);
 
-      }
+       if (tree) {
 
-      offset += 2; /* Skip Count */
+           proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved%u: %u", i, Reserved);
 
+       }
+       offset += 2;
     }
 
     /* Build display for: Byte Count (BCC) */
@@ -8399,50 +7316,38 @@ dissect_search_dir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree
 
     offset += 2; /* Skip Byte Count (BCC) */
 
-    /* Build display for: Buffer Format */
-
-    BufferFormat = GBYTE(pd, offset);
+    /* Build display for data */
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+       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);
 
     }
 
-    offset += 1; /* Skip Buffer Format */
-
-    /* Build display for: Data Length */
-
-    DataLength = GSHORT(pd, offset);
-
-    if (tree) {
+    if (AndXCommand != 0xFF) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
     }
 
-    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)
+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        BufferFormat;
-  guint16       Reserved;
-  guint16       FID;
-  guint16       CreationTime;
-  guint16       CreationDate;
+  guint8        AndXReserved;
+  guint8        AndXCommand = 0xFF;
   guint16       ByteCount;
-  const char    *FileName;
-  const char    *DirectoryName;
-  int           string_len;
+  guint16       AndXOffset = 0;
 
   if (si.request) {
     /* Request(s) dissect code */
@@ -8459,42 +7364,46 @@ dissect_create_temporary_file_smb(const u_char *pd, int offset, frame_data *fd,
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Reserved */
+    if (WordCount != 0) {
 
-    Reserved = GSHORT(pd, offset);
+      /* Build display for: AndXCommand */
 
-    if (tree) {
+      AndXCommand = GBYTE(pd, offset);
+
+      if (tree) {
+
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+      offset += 1; /* Skip AndXCommand */
 
-    }
+      /* Build display for: AndXReserved */
 
-    offset += 2; /* Skip Reserved */
+      AndXReserved = GBYTE(pd, offset);
 
-    /* Build display for: Creation Time */
+      if (tree) {
 
-    CreationTime = GSHORT(pd, offset);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
+      offset += 1; /* Skip AndXReserved */
 
-    }
+      /* Build display for: AndXOffset */
 
-    offset += 2; /* Skip Creation Time */
+      AndXOffset = GSHORT(pd, offset);
 
-    /* Build display for: Creation Date */
+      if (tree) {
 
-    CreationDate = GSHORT(pd, offset);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
-    if (tree) {
+      }
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
+      offset += 2; /* Skip AndXOffset */
 
     }
 
-    offset += 2; /* Skip Creation Date */
-
     /* Build display for: Byte Count (BCC) */
 
     ByteCount = GSHORT(pd, offset);
@@ -8507,32 +7416,14 @@ dissect_create_temporary_file_smb(const u_char *pd, int offset, frame_data *fd,
 
     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) {
+    if (AndXCommand != 0xFF) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "Directory Name: %s", DirectoryName);
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
     }
 
-    offset += string_len; /* Skip Directory Name */
-
   } else {
     /* Response(s) dissect code */
 
@@ -8550,69 +7441,83 @@ dissect_create_temporary_file_smb(const u_char *pd, int offset, frame_data *fd,
 
     if (WordCount != 0) {
 
-      /* Build display for: FID */
+      /* Build display for: AndXCommand */
 
-      FID = GSHORT(pd, offset);
+      AndXCommand = GBYTE(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
 
       }
 
-      offset += 2; /* Skip FID */
+      offset += 1; /* Skip AndXCommand */
 
-    }
+      /* Build display for: AndXReserved */
 
-    /* Build display for: Byte Count (BCC) */
+      AndXReserved = GBYTE(pd, offset);
 
-    ByteCount = GSHORT(pd, offset);
+      if (tree) {
 
-    if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      }
 
-    }
+      offset += 1; /* Skip AndXReserved */
 
-    offset += 2; /* Skip Byte Count (BCC) */
+      /* Build display for: AndXOffset */
 
-    /* Build display for: Buffer Format */
+      AndXOffset = GSHORT(pd, offset);
 
-    BufferFormat = GBYTE(pd, offset);
+      if (tree) {
 
-    if (tree) {
+       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
-                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
-                         BufferFormat);
+      }
 
-    }
+      offset += 2; /* Skip AndXOffset */
 
-    offset += 1; /* Skip Buffer Format */
+    }
 
-    /* Build display for: File Name */
+    /* Build display for: Byte Count (BCC) */
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    offset += string_len; /* Skip File Name */
+    offset += 2; /* Skip Byte Count (BCC) */
+
+
+    if (AndXCommand != 0xFF) {
+
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
+
+    }
 
   }
 
 }
 
 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)
+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;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
+  guint32       Offset;
+  guint16       Mode;
   guint16       FID;
   guint16       ByteCount;
 
@@ -8643,29 +7548,32 @@ dissect_close_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *pare
 
     offset += 2; /* Skip FID */
 
-    /* Build display for: Last Write Time */
+    /* Build display for: Mode */
 
-    LastWriteTime = GSHORT(pd, offset);
+    Mode = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
-
+      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 Last Write Time */
+    offset += 2; /* Skip Mode */
 
-    /* Build display for: Last Write Date */
+    /* Build display for: Offset */
 
-    LastWriteDate = GSHORT(pd, offset);
+    Offset = GWORD(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
 
     }
 
-    offset += 2; /* Skip Last Write Date */
+    offset += 4; /* Skip Offset */
 
     /* Build display for: Byte Count (BCC) */
 
@@ -8694,6 +7602,18 @@ dissect_close_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *pare
 
     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);
@@ -8711,29 +7631,33 @@ dissect_close_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *pare
 }
 
 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)
+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;
-  guint8        BufferFormat;
+  guint16       LastWriteTime;
+  guint16       LastWriteDate;
+  guint16       LastAccessTime;
+  guint16       LastAccessDate;
   guint16       FID;
-  guint16       DataLength;
+  guint16       CreationTime;
+  guint16       CreationDate;
   guint16       ByteCount;
 
   if (si.request) {
     /* Request(s) dissect code */
 
-    /* Build display for: Word Count (WCT) */
+    /* Build display for: Word Count */
 
     WordCount = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
+    offset += 1; /* Skip Word Count */
 
     /* Build display for: FID */
 
@@ -8747,58 +7671,77 @@ dissect_write_print_file_smb(const u_char *pd, int offset, frame_data *fd, proto
 
     offset += 2; /* Skip FID */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: Creation Date */
 
-    ByteCount = GSHORT(pd, offset);
+    CreationDate = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 2; /* Skip Creation Date */
 
-    /* Build display for: Buffer Format */
+    /* Build display for: Creation Time */
 
-    BufferFormat = GBYTE(pd, offset);
+    CreationTime = GSHORT(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);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
 
     }
 
-    offset += 1; /* Skip Buffer Format */
+    offset += 2; /* Skip Creation Time */
 
-    /* Build display for: Data Length */
+    /* Build display for: Last Access Date */
 
-    DataLength = GSHORT(pd, offset);
+    LastAccessDate = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Access Date: %s", dissect_dos_date(LastAccessDate));
 
     }
 
-    offset += 2; /* Skip Data Length */
+    offset += 2; /* Skip Last Access Date */
 
-  } else {
-    /* Response(s) dissect code */
+    /* Build display for: Last Access Time */
 
-    /* Build display for: Word Count (WCT) */
+    LastAccessTime = GSHORT(pd, offset);
 
-    WordCount = GBYTE(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, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
+    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) */
 
@@ -8812,89 +7755,88 @@ dissect_write_print_file_smb(const u_char *pd, int offset, frame_data *fd, proto
 
     offset += 2; /* Skip Byte Count (BCC) */
 
-  }
+  } else {
+    /* Response(s) dissect code */
 
-}
+    /* Build display for: Word Count (WCC) */
 
-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)
+    WordCount = GBYTE(pd, 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 (tree) {
 
-  if (si.request) {
-    /* Request(s) dissect code */
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCC): %u", WordCount);
 
-    /* Build display for: Word Count (WCT) */
+    }
 
-    WordCount = GBYTE(pd, offset);
+    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, 1, "Word Count (WCT): %u", WordCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    offset += 1; /* Skip Word Count (WCT) */
-
-    /* Build display for: FID */
+    offset += 2; /* Skip Byte Count (BCC) */
 
-    FID = GSHORT(pd, offset);
+  }
 
-    if (tree) {
+}
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+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;
 
-    offset += 2; /* Skip FID */
+  if (si.request) {
+    /* Request(s) dissect code */
 
-    /* Build display for: Count */
+    /* Build display for: Word Count */
 
-    Count = GSHORT(pd, offset);
+    WordCount = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count: %u", WordCount);
 
     }
 
-    offset += 2; /* Skip Count */
+    offset += 1; /* Skip Word Count */
 
-    /* Build display for: Offset */
+    /* Build display for: Max Count */
 
-    Offset = GWORD(pd, offset);
+    MaxCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
 
     }
 
-    offset += 4; /* Skip Offset */
+    offset += 2; /* Skip Max Count */
 
-    /* Build display for: Remaining */
+    /* Build display for: Start Index */
 
-    Remaining = GSHORT(pd, offset);
+    StartIndex = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Start Index: %u", StartIndex);
 
     }
 
-    offset += 2; /* Skip Remaining */
+    offset += 2; /* Skip Start Index */
 
     /* Build display for: Byte Count (BCC) */
 
@@ -8937,58 +7879,22 @@ dissect_lock_and_read_smb(const u_char *pd, int offset, frame_data *fd, proto_tr
 
       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 */
+      /* Build display for: Restart Index */
 
-      Reserved3 = GSHORT(pd, offset);
+      RestartIndex = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Restart Index: %u", RestartIndex);
 
       }
 
-      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 Restart Index */
 
-      offset += 2; /* Skip Reserved 4 */
+      /* Build display for: Byte Count (BCC) */
 
     }
 
-    /* Build display for: Byte Count (BCC) */
-
     ByteCount = GSHORT(pd, offset);
 
     if (tree) {
@@ -9029,27 +7935,23 @@ dissect_lock_and_read_smb(const u_char *pd, int offset, frame_data *fd, proto_tr
 
 }
 
-
 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)
+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    *Attributes_tree;
+  proto_tree    *LockType_tree;
   proto_item    *ti;
+  guint8        LockType;
   guint8        WordCount;
-  guint8        BufferFormat;
-  guint32       FileSize;
-  guint16       Reserved5;
-  guint16       Reserved4;
-  guint16       Reserved3;
-  guint16       Reserved2;
-  guint16       Reserved1;
-  guint16       LastWriteTime;
-  guint16       LastWriteDate;
+  guint8        OplockLevel;
+  guint8        AndXReserved;
+  guint8        AndXCommand = 0xFF;
+  guint32       Timeout;
+  guint16       NumberofLocks;
+  guint16       NumberOfUnlocks;
+  guint16       FID;
   guint16       ByteCount;
-  guint16       Attributes;
-  const char    *FileName;
-  int           string_len;
+  guint16       AndXOffset = 0;
 
   if (si.request) {
     /* Request(s) dissect code */
@@ -9066,216 +7968,242 @@ dissect_get_file_attr_smb(const u_char *pd, int offset, frame_data *fd, proto_tr
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: AndXCommand */
 
-    ByteCount = GSHORT(pd, offset);
+    AndXCommand = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+                         (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 1; /* Skip AndXCommand */
 
-    /* Build display for: Buffer Format */
+    /* Build display for: AndXReserved */
 
-    BufferFormat = GBYTE(pd, offset);
+    AndXReserved = 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);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
     }
 
-    offset += 1; /* Skip Buffer Format */
+    offset += 1; /* Skip AndXReserved */
 
-    /* Build display for: File Name */
+    /* Build display for: AndXOffset */
 
-    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
+    AndXOffset = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
     }
 
-    offset += string_len; /* Skip File Name */
+    offset += 2; /* Skip AndXOffset */
 
-  } else {
-    /* Response(s) dissect code */
+    /* Build display for: FID */
 
-    /* Build display for: Word Count (WCT) */
+    FID = GSHORT(pd, offset);
 
-    WordCount = GBYTE(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) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+      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 Word Count (WCT) */
+    offset += 1; /* Skip OplockLevel */
 
-    if (WordCount != 0) {
+    /* Build display for: Timeout */
 
-      /* Build display for: Attributes */
+    Timeout = GWORD(pd, offset);
 
-      Attributes = GSHORT(pd, offset);
+    if (tree) {
 
-      if (tree) {
+      proto_tree_add_text(tree, NullTVB, offset, 4, "Timeout: %u", Timeout);
 
-       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 */
+    offset += 4; /* Skip Timeout */
 
-      /* Build display for: Last Write Time */
+    /* Build display for: Number Of Unlocks */
 
-      LastWriteTime = GSHORT(pd, offset);
+    NumberOfUnlocks = GSHORT(pd, offset);
 
-      if (tree) {
+    if (tree) {
 
-      }
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Number Of Unlocks: %u", NumberOfUnlocks);
 
-      offset += 2; /* Skip Last Write Time */
+    }
 
-      /* Build display for: Last Write Date */
+    offset += 2; /* Skip Number Of Unlocks */
 
-      LastWriteDate = GSHORT(pd, offset);
+    /* Build display for: Number of Locks */
 
-      if (tree) {
+    NumberofLocks = GSHORT(pd, offset);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Last Write Date: %s", dissect_smbu_date(LastWriteDate, LastWriteTime));
+    if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset - 2, 2, "Last Write Time: %s", dissect_smbu_time(LastWriteDate, LastWriteTime));
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Number of Locks: %u", NumberofLocks);
 
-      }
+    }
 
-      offset += 2; /* Skip Last Write Date */
+    offset += 2; /* Skip Number of Locks */
 
-      /* Build display for: File Size */
+    /* Build display for: Byte Count (BCC) */
 
-      FileSize = GWORD(pd, offset);
+    ByteCount = GSHORT(pd, offset);
 
-      if (tree) {
+    if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 4, "File Size: %u", FileSize);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-      }
+    }
 
-      offset += 4; /* Skip File Size */
+    offset += 2; /* Skip Byte Count (BCC) */
 
-      /* Build display for: Reserved 1 */
 
-      Reserved1 = GSHORT(pd, offset);
+    if (AndXCommand != 0xFF) {
 
-      if (tree) {
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
+    }
 
-      }
+  } else {
+    /* Response(s) dissect code */
 
-      offset += 2; /* Skip Reserved 1 */
+    /* Build display for: Word Count (WCT) */
 
-      /* Build display for: Reserved 2 */
+    WordCount = GBYTE(pd, offset);
 
-      Reserved2 = GSHORT(pd, offset);
+    if (tree) {
 
-      if (tree) {
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
+    }
 
-      }
+    offset += 1; /* Skip Word Count (WCT) */
 
-      offset += 2; /* Skip Reserved 2 */
+    if (WordCount != 0) {
 
-      /* Build display for: Reserved 3 */
+      /* Build display for: AndXCommand */
 
-      Reserved3 = GSHORT(pd, offset);
+      AndXCommand = GBYTE(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %s", 
+                           (AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
 
       }
 
-      offset += 2; /* Skip Reserved 3 */
+      offset += 1; /* Skip AndXCommand */
 
-      /* Build display for: Reserved 4 */
+      /* Build display for: AndXReserved */
 
-      Reserved4 = GSHORT(pd, offset);
+      AndXReserved = GBYTE(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 4: %u", Reserved4);
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
 
       }
 
-      offset += 2; /* Skip Reserved 4 */
+      offset += 1; /* Skip AndXReserved */
 
-      /* Build display for: Reserved 5 */
+      /* Build display for: AndXOffset */
 
-      Reserved5 = GSHORT(pd, offset);
+      AndXOffset = GSHORT(pd, offset);
 
       if (tree) {
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 5: %u", Reserved5);
+       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
 
       }
 
-      offset += 2; /* Skip Reserved 5 */
+      offset += 2; /* Skip AndXOffset */
 
     }
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: Byte Count */
 
     ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count: %u", ByteCount);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    offset += 2; /* Skip Byte Count */
+
+
+    if (AndXCommand != 0xFF) {
+
+      wrap_dissect_smb_command(parent, pd, AndXOffset, tree, AndXCommand,
+          &si, max_data, SMB_offset);
+
+    }
 
   }
 
 }
 
 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)
+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;
-  guint32       Offset;
-  guint16       Reserved4;
-  guint16       Reserved3;
-  guint16       Reserved2;
-  guint16       Reserved1;
-  guint16       Remaining;
-  guint16       FID;
+  guint8        BufferFormat2;
+  guint8        BufferFormat1;
+  guint8        BufferFormat;
+  guint16       SearchAttributes;
+  guint16       ResumeKeyLength;
+  guint16       MaxCount;
   guint16       DataLength;
   guint16       Count;
   guint16       ByteCount;
-  guint16       BufferFormat;
+  const char    *FileName;
+  int           string_len;
 
   if (si.request) {
     /* Request(s) dissect code */
@@ -9292,65 +8220,93 @@ dissect_read_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     offset += 1; /* Skip Word Count (WCT) */
 
-    /* Build display for: FID */
+    /* Build display for: Max Count */
 
-    FID = GSHORT(pd, offset);
+    MaxCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
 
     }
 
-    offset += 2; /* Skip FID */
+    offset += 2; /* Skip Max Count */
 
-    /* Build display for: Count */
+    /* Build display for: Search Attributes */
 
-    Count = GSHORT(pd, offset);
+    SearchAttributes = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Count: %u", Count);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Search Attributes: %u", SearchAttributes);
 
     }
 
-    offset += 2; /* Skip Count */
+    offset += 2; /* Skip Search Attributes */
 
-    /* Build display for: Offset */
+    /* Build display for: Byte Count (BCC) */
 
-    Offset = GWORD(pd, offset);
+    ByteCount = GSHORT(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
     }
 
-    offset += 4; /* Skip Offset */
+    offset += 2; /* Skip Byte Count (BCC) */
 
-    /* Build display for: Remaining */
+    /* Build display for: Buffer Format 1 */
 
-    Remaining = GSHORT(pd, offset);
+    BufferFormat1 = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format 1: %s (%u)",
+                         val_to_str(BufferFormat1, buffer_format_vals, "Unknown"),
+                         BufferFormat1);
 
     }
 
-    offset += 2; /* Skip Remaining */
+    offset += 1; /* Skip Buffer Format 1 */
 
-    /* Build display for: Byte Count (BCC) */
+    /* Build display for: File Name */
 
-    ByteCount = GSHORT(pd, offset);
+    FileName = get_unicode_or_ascii_string(pd, &offset, SMB_offset, si.unicode, &string_len);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+      proto_tree_add_text(tree, NullTVB, offset, string_len, "File Name: %s", FileName);
 
     }
 
-    offset += 2; /* Skip Byte Count (BCC) */
+    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 */
@@ -9381,60 +8337,92 @@ dissect_read_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
       offset += 2; /* Skip Count */
 
-      /* Build display for: Reserved 1 */
+    }
 
-      Reserved1 = GSHORT(pd, offset);
+    /* Build display for: Byte Count (BCC) */
 
-      if (tree) {
+    ByteCount = GSHORT(pd, offset);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 1: %u", Reserved1);
+    if (tree) {
 
-      }
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
 
-      offset += 2; /* Skip Reserved 1 */
+    }
 
-      /* Build display for: Reserved 2 */
+    offset += 2; /* Skip Byte Count (BCC) */
 
-      Reserved2 = GSHORT(pd, offset);
+    /* Build display for: Buffer Format */
 
-      if (tree) {
+    BufferFormat = GBYTE(pd, offset);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 2: %u", Reserved2);
+    if (tree) {
 
-      }
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
+                         val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
+                         BufferFormat);
 
-      offset += 2; /* Skip Reserved 2 */
+    }
 
-      /* Build display for: Reserved 3 */
+    offset += 1; /* Skip Buffer Format */
 
-      Reserved3 = GSHORT(pd, offset);
+    /* Build display for: Data Length */
 
-      if (tree) {
+    DataLength = GSHORT(pd, offset);
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 3: %u", Reserved3);
+    if (tree) {
 
-      }
+      proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
 
-      offset += 2; /* Skip Reserved 3 */
+    }
 
-      /* Build display for: Reserved 4 */
+    offset += 2; /* Skip Data Length */
 
-      Reserved4 = GSHORT(pd, offset);
+  }
 
-      if (tree) {
+}
 
-       proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved 4: %u", Reserved4);
 
-      }
+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) {
 
-      offset += 2; /* Skip Reserved 4 */
+      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);
@@ -9445,17 +8433,17 @@ dissect_read_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     /* Build display for: Buffer Format */
 
-    BufferFormat = GSHORT(pd, offset);
+    BufferFormat = GBYTE(pd, offset);
 
     if (tree) {
 
-      proto_tree_add_text(tree, NullTVB, offset, 2, "Buffer Format: %s (%u)",
+      proto_tree_add_text(tree, NullTVB, offset, 1, "Buffer Format: %s (%u)",
                          val_to_str(BufferFormat, buffer_format_vals, "Unknown"),
                          BufferFormat);
 
     }
 
-    offset += 2; /* Skip Buffer Format */
+    offset += 1; /* Skip Buffer Format */
 
     /* Build display for: Data Length */
 
@@ -9469,6 +8457,33 @@ dissect_read_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *
 
     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) */
+
   }
 
 }
@@ -11316,25 +10331,25 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
 
   dissect_unknown_smb,
   dissect_unknown_smb,
-  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_unknown_smb,
   dissect_unknown_smb,
-  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,
+  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 0x15 */
   dissect_unknown_smb,      /* unknown SMB 0x16 */
   dissect_unknown_smb,      /* unknown SMB 0x17 */
@@ -11508,7 +10523,7 @@ static void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, pro
   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_unknown_smb,
   dissect_get_print_queue_smb, /* SMBsplretq return print queue */
   dissect_unknown_smb,      /* unknown SMB 0xc4 */
   dissect_unknown_smb,      /* unknown SMB 0xc5 */
@@ -12809,10 +11824,12 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
                sip->mid);
        offset += 2;
 
+       our_tvb = tvb;
+       our_pinfo = pinfo;
        if(smb_dissector[sip->cmd].request){ 
          /* call smb command dissector */
          pinfo->private_data = sip;
-         dissect_smb_command(tvb, pinfo, parent_tree, offset, tree, sip->cmd);
+          dissect_smb_command(tvb, pinfo, parent_tree, offset, tree, sip->cmd);
        } else {
          const u_char *pd;
          int SMB_offset;
@@ -13208,6 +12225,166 @@ proto_register_smb(void)
                { "Open", "smb.open.function.open", FT_UINT16, BASE_HEX,
                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: FileID", HFILL }},
+
+       { &hf_smb_file_attr_read_only,
+               { "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_hidden,
+               { "Hidden", "smb.file.attribute.hidden", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_hidden), FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+       { &hf_smb_file_attr_system,
+               { "System", "smb.file.attribute.system", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_system), FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+       { &hf_smb_file_attr_volume,
+               { "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_directory,
+               { "Directory", "smb.file.attribute.directory", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_directory), FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+       { &hf_smb_file_attr_archive,
+               { "Archive", "smb.file.attribute.archive", FT_BOOLEAN, 16,
+               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_last_write_time,
+               { "Last Write Time", "smb.last_write.time", FT_ABSOLUTE_TIME, BASE_HEX,
+               NULL, 0, "Last time this file was written to", HFILL }},
+
+       { &hf_smb_search_attribute_read_only,
+               { "Read Only", "smb.search.attribute.read_only", FT_BOOLEAN, 16,
+               TFS(&tfs_file_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_file_attribute_hidden), FILE_ATTRIBUTE_HIDDEN, "HIDDEN search attribute", HFILL }},
+
+       { &hf_smb_search_attribute_system,
+               { "System", "smb.search.attribute.system", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_system), FILE_ATTRIBUTE_SYSTEM, "SYSTEM search attribute", HFILL }},
+
+       { &hf_smb_search_attribute_volume,
+               { "Volume ID", "smb.search.attribute.volume", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_volume), FILE_ATTRIBUTE_VOLUME, "VOLUME search attribute", HFILL }},
+
+       { &hf_smb_search_attribute_directory,
+               { "Directory", "smb.search.attribute.directory", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_directory), FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY search attribute", HFILL }},
+
+       { &hf_smb_search_attribute_archive,
+               { "Archive", "smb.search.attribute.archive", FT_BOOLEAN, 16,
+               TFS(&tfs_file_attribute_archive), FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE search attribute", HFILL }},
+
+       { &hf_smb_access_mode,
+               { "Access Mode", "smb.access.mode", FT_UINT16, BASE_HEX,
+               VALS(da_access_vals), 0x0007, "Access Mode", HFILL }},
+
+       { &hf_smb_access_sharing,
+               { "Sharing Mode", "smb.access.sharing", FT_UINT16, BASE_HEX,
+               VALS(da_sharing_vals), 0x0070, "Sharing Mode", HFILL }},
+
+       { &hf_smb_access_locality,
+               { "Locality", "smb.access.locality", FT_UINT16, BASE_HEX,
+               VALS(da_locality_vals), 0x0700, "Locality of reference", HFILL }},
+
+       { &hf_smb_access_caching,
+               { "Caching", "smb.access.caching", FT_BOOLEAN, 16,
+               TFS(&tfs_da_caching), 0x1000, "Caching mode?", HFILL }},
+
+       { &hf_smb_access_writetru,
+               { "Writethrough", "smb.access.writethrough", FT_BOOLEAN, 16,
+               TFS(&tfs_da_writetru), 0x4000, "Writethrough mode?", HFILL }},
+
+       { &hf_smb_create_time,
+               { "Created", "smb.create.time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Creation Time", HFILL }},
+
+       { &hf_smb_last_write_date,
+               { "Last Write", "smb.last_write.date", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Last Write", HFILL }},
+
+       { &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 }},
+
+       { &hf_smb_old_file_name,
+               { "Old File Name", "smb.file", FT_STRING, BASE_NONE,
+               NULL, 0, "Old File Name (When renaming a file)", HFILL }},
+
+       { &hf_smb_offset,
+               { "Offset", "smb.offset", FT_UINT32, BASE_DEC,
+               NULL, 0, "Offset in file", HFILL }},
+
+       { &hf_smb_remaining,
+               { "Remaining", "smb.remaining", FT_UINT32, BASE_DEC,
+               NULL, 0, "Remaining number of bytes", HFILL }},
+
+       { &hf_smb_padding,
+               { "Padding", "smb.padding", FT_BYTES, BASE_HEX,
+               NULL, 0, "Padding or unknown data", HFILL }},
+
+       { &hf_smb_file_data,
+               { "File Data", "smb.file.data", FT_BYTES, BASE_HEX,
+               NULL, 0, "Data read/written to the file", HFILL }},
+
+       { &hf_smb_data_len,
+               { "Data Length", "smb.data_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Length of data", HFILL }},
+
+       { &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 }},
+
 
        };
        static gint *ett[] = {
@@ -13236,6 +12413,7 @@ proto_register_smb(void)
                &ett_smb_time_date,
                &ett_smb_64bit_time,
                &ett_smb_move_flags,
+               &ett_smb_file_attributes,
        };
 
        proto_smb = proto_register_protocol("SMB (Server Message Block Protocol)",