Ethereal-dev: [ethereal-dev] Some fixes/mods for packet-smb.c

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Mark Burton <markb@xxxxxxxxxx>
Date: Wed, 24 May 2000 21:54:48 +0100
Hi,

I enclose a patch (from the current CVS) that fixes various problems
and adds a little more functionality to packet-smb.c. I hope someone
will incorporate it into the source.

Regards,

Mark

Index: packet-smb.c
===================================================================
RCS file: /cvsroot/ethereal/packet-smb.c,v
retrieving revision 1.65
diff -c -r1.65 packet-smb.c
*** packet-smb.c	2000/05/11 08:15:46	1.65
--- packet-smb.c	2000/05/24 17:56:45
***************
*** 1084,1089 ****
--- 1084,1098 ----
  
      offset += 2; /* Skip Data Length */
  
+     if (ByteCount > 0 && tree) {
+ 
+ 	if(END_OF_FRAME >= ByteCount)
+ 	    proto_tree_add_text(tree, NullTVB, offset, ByteCount, "Data (%u bytes)", ByteCount);
+ 	else
+ 	    proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (first %u bytes)", END_OF_FRAME);
+ 
+     }
+ 
    }
  
    if (dirn == 0) { /* Response(s) dissect code */
***************
*** 1383,1388 ****
--- 1392,1398 ----
  {
    guint8        WordCount;
    guint8        BufferFormat;
+   guint16       SearchAttributes;
    guint16       ByteCount;
    const char    *FileName;
  
***************
*** 1400,1405 ****
--- 1410,1426 ----
  
      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);
***************
*** 2281,2298 ****
  
        if (ByteCount > 0) {
  
! 	/* Build display for: ANSI Password */
  
! 	ANSIPassword = pd + offset;
  
! 	if (tree) {
  
! 	  proto_tree_add_text(tree, NullTVB, offset, ANSIAccountPasswordLength, "ANSI Password: %s", format_text(ANSIPassword, ANSIAccountPasswordLength));
  
! 	}
  
! 	offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
! 	if (ANSIAccountPasswordLength == 0) offset++;  /* Add 1 */
  
  	/* Build display for: UNICODE Password */
  
--- 2302,2321 ----
  
        if (ByteCount > 0) {
  
! 	  /* Build display for: ANSI Password */
  
! 	  ANSIPassword = pd + offset;
  
! 	  if (ANSIAccountPasswordLength > 0) {
  
! 	      if (tree) {
  
! 		  proto_tree_add_text(tree, NullTVB, offset, ANSIAccountPasswordLength, "ANSI Password: %s", format_text(ANSIPassword, ANSIAccountPasswordLength));
  
! 	      }
! 
! 	      offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
! 	  }
  
  	/* Build display for: UNICODE Password */
  
***************
*** 3426,3431 ****
--- 3449,3455 ----
  
  }
  
+ 
  void
  dissect_checkdir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset, int errcode, int dirn)
  
***************
*** 5278,5283 ****
--- 5302,5644 ----
  }
  
  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, int errcode, int dirn)
+ 
+ {
+   guint8        WordCount;
+   guint8        AndXReserved;
+   guint8        AndXCommand = 0xFF;
+   guint16       ByteCount;
+   guint16       AndXOffset = 0;
+   guint16       FID;
+   guint16       DataCompactionMode;
+   guint16       DataLength;
+   guint16       DataOffset;
+   guint16       Remaining;
+   guint16       MaxCount;
+   guint16       MinCount;
+   guint16       Reserved;
+   guint32       Offset;
+   guint32       OffsetHigh;
+   int           i;
+ 
+   if (dirn == 1) { /* Request(s) dissect code */
+ 
+     /* Build display for: Word Count (WCT) */
+ 
+     WordCount = GBYTE(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+ 
+     }
+ 
+     offset += 1; /* Skip Word Count (WCT) */
+ 
+     /* Build display for: AndXCommand */
+ 
+     AndXCommand = GBYTE(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+ 
+     }
+ 
+     offset += 1; /* Skip AndXCommand */
+ 
+     /* Build display for: AndXReserved */
+ 
+     AndXReserved = GBYTE(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+ 
+     }
+ 
+     offset += 1; /* Skip AndXReserved */
+ 
+     /* Build display for: AndXOffset */
+ 
+     AndXOffset = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+ 
+     }
+ 
+     offset += 2; /* Skip AndXOffset */
+ 
+     /* Build display for: FID */
+ 
+     FID = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 	
+       proto_tree_add_text(tree, NullTVB, offset, 2, "FID: %u", FID);
+ 	
+     }
+ 
+     offset += 2; /* Skip FID */
+ 
+     /* Build display for: Offset */
+ 
+     Offset = GWORD(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 4, "Offset: %u", Offset);
+ 
+     }
+ 
+     offset += 4; /* Skip Offset */
+ 
+     /* Build display for: Max Count */
+ 
+     MaxCount = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+         proto_tree_add_text(tree, NullTVB, offset, 2, "Max Count: %u", MaxCount);
+ 
+     }
+ 
+     offset += 2; /* Skip Max Count */
+ 
+     /* Build display for: Min Count */
+ 
+     MinCount = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+         proto_tree_add_text(tree, NullTVB, offset, 2, "Min Count: %u", MinCount);
+ 
+     }
+ 
+     offset += 2; /* Skip Min Count */
+ 
+     /* Build display for: Reserved */
+ 
+     Reserved = GWORD(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 4, "Reserved: %u", Reserved);
+ 
+     }
+ 
+     offset += 4; /* Skip Reserved */
+ 
+     /* Build display for: Remaining */
+ 
+     Remaining = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+ 
+     }
+ 
+     offset += 2; /* Skip Remaining */
+ 
+     if (WordCount == 12) {
+ 
+ 	/* Build display for: Offset High */
+ 
+ 	OffsetHigh = GWORD(pd, offset);
+ 
+ 	if (tree) {
+ 
+ 	    proto_tree_add_text(tree, NullTVB, offset, 4, "Offset High: %u", OffsetHigh);
+ 
+ 	}
+ 
+ 	offset += 4; /* Skip Offset High */
+     }
+ 
+     /* Build display for: Byte Count (BCC) */
+ 
+     ByteCount = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+ 
+     }
+ 
+     offset += 2; /* Skip Byte Count (BCC) */
+ 
+ 
+     if (AndXCommand != 0xFF) {
+ 
+       (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
+ 
+     }
+ 
+   }
+ 
+   if (dirn == 0) { /* Response(s) dissect code */
+ 
+     /* Build display for: Word Count (WCT) */
+ 
+     WordCount = GBYTE(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 1, "Word Count (WCT): %u", WordCount);
+ 
+     }
+ 
+     offset += 1; /* Skip Word Count (WCT) */
+ 
+     /* Build display for: AndXCommand */
+ 
+     AndXCommand = GBYTE(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXCommand: %u", AndXCommand);
+ 
+     }
+ 
+     offset += 1; /* Skip AndXCommand */
+ 
+     /* Build display for: AndXReserved */
+ 
+     AndXReserved = GBYTE(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 1, "AndXReserved: %u", AndXReserved);
+ 
+     }
+ 
+     offset += 1; /* Skip AndXReserved */
+ 
+     /* Build display for: AndXOffset */
+ 
+     AndXOffset = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 2, "AndXOffset: %u", AndXOffset);
+ 
+     }
+ 
+     offset += 2; /* Skip AndXOffset */
+ 
+     /* Build display for: Remaining */
+ 
+     Remaining = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining: %u", Remaining);
+ 
+     }
+ 
+     offset += 2; /* Skip Remaining */
+ 
+     /* Build display for: Data Compaction Mode */
+ 
+     DataCompactionMode = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+ 	proto_tree_add_text(tree, NullTVB, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
+ 
+     }
+ 
+     offset += 2; /* Skip Data Compaction Mode */
+ 
+     /* Build display for: Reserved */
+ 
+     Reserved = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+ 	proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved: %u", Reserved);
+ 
+     }
+ 
+     offset += 2; /* Skip Reserved */
+ 
+     /* Build display for: Data Length */
+ 
+     DataLength = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+ 	proto_tree_add_text(tree, NullTVB, offset, 2, "Data Length: %u", DataLength);
+ 
+     }
+ 
+     offset += 2; /* Skip Data Length */
+ 
+     /* Build display for: Data Offset */
+ 
+     DataOffset = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+ 	proto_tree_add_text(tree, NullTVB, offset, 2, "Data Offset: %u", DataOffset);
+ 
+     }
+ 
+     offset += 2; /* Skip Data Offset */
+ 
+     /* Build display for: Reserved[5] */
+  
+     for(i = 1; i <= 5; ++i) {
+ 
+ 	Reserved = GSHORT(pd, offset);
+ 
+ 	if (tree) {
+ 
+ 	    proto_tree_add_text(tree, NullTVB, offset, 2, "Reserved%u: %u", i, Reserved);
+ 
+ 	}
+ 	offset += 2;
+     }
+ 
+     /* Build display for: Byte Count (BCC) */
+ 
+     ByteCount = GSHORT(pd, offset);
+ 
+     if (tree) {
+ 
+       proto_tree_add_text(tree, NullTVB, offset, 2, "Byte Count (BCC): %u", ByteCount);
+ 
+     }
+ 
+     offset += 2; /* Skip Byte Count (BCC) */
+ 
+     /* Build display for data */
+ 
+     if (tree) {
+ 
+ 	offset = SMB_offset + DataOffset;
+ 	if(END_OF_FRAME >= DataLength)
+ 	    proto_tree_add_text(tree, NullTVB, offset, DataLength, "Data (%u bytes)", DataLength);
+ 	else
+ 	    proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Data (first %u bytes)", END_OF_FRAME);
+ 
+     }
+ 
+     if (AndXCommand != 0xFF) {
+ 
+       (dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
+ 
+     }
+ 
+   }
+ 
+ }
+ 
+ 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, int errcode, int dirn)
  
  {
***************
*** 8195,8200 ****
--- 8556,8562 ----
    "TRANS2_FIND_FIRST2",
    "TRANS2_FIND_NEXT2",
    "TRANS2_QUERY_FS_INFORMATION",
+   "no such command",
    "TRANS2_QUERY_PATH_INFORMATION",
    "TRANS2_SET_PATH_INFORMATION",
    "TRANS2_QUERY_FILE_INFORMATION",
***************
*** 8233,8240 ****
    guint8        SetupCount;
    guint8        Reserved3;
    guint8        Reserved1;
-   guint8        Pad2;
-   guint8        Pad1;
    guint8        MaxSetupCount;
    guint8        Data;
    guint32       Timeout;
--- 8595,8600 ----
***************
*** 8561,8579 ****
  
      }
  
!     if (offset % 2) {
  
!       /* Build display for: Pad1 */
  
!       Pad1 = GBYTE(pd, offset);
  
        if (tree) {
- 
- 	proto_tree_add_text(tree, NullTVB, offset, 1, "Pad1: %u", Pad1);
  
        }
!     
!       offset += 1; /* Skip Pad1 */
  
      }
  
--- 8921,8938 ----
  
      }
  
!     if (offset < (SMB_offset + ParameterOffset)) {
  
!       int pad1Count = SMB_offset + ParameterOffset - offset;
  
!       /* Build display for: Pad1 */
  
        if (tree) {
  
+ 	proto_tree_add_text(tree, NullTVB, offset, pad1Count, "Pad1: %s", format_text(pd + offset, pad1Count));
        }
! 
!       offset += pad1Count; /* Skip Pad1 */
  
      }
  
***************
*** 8591,8609 ****
  
      }
  
!     if (offset % 2) {
  	
        /* Build display for: Pad2 */
  
-       Pad2 = GBYTE(pd, offset);
- 
        if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, 1, "Pad2: %u", Pad2);
  
        }
  
!       offset += 1; /* Skip Pad2 */
  
      }
  
--- 8950,8968 ----
  
      }
  
!     if (DataCount > 0 && offset < (SMB_offset + DataOffset)) {
! 
!       int pad2Count = SMB_offset + DataOffset - offset;
  	
        /* Build display for: Pad2 */
  
        if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, pad2Count, "Pad2: %s", format_text(pd + offset, pad2Count));
  
        }
  
!       offset += pad2Count; /* Skip Pad2 */
  
      }
  
***************
*** 8778,8795 ****
  
      offset += 1; /* Skip Reserved3 */
  
!     /* Build display for: Setup */
  
!     Setup = GSHORT(pd, offset);
  
!     if (tree) {
  
!       proto_tree_add_text(tree, NullTVB, offset, 2, "Setup: %u", Setup);
  
!     }
  
!     offset += 2; /* Skip Setup */
  
      /* Build display for: Byte Count (BCC) */
  
      ByteCount = GSHORT(pd, offset);
--- 9137,9163 ----
  
      offset += 1; /* Skip Reserved3 */
  
!     if (SetupCount > 0) {
  
!       int i = SetupCount;
  
!       Setup = GSHORT(pd, offset);
  
!       for (i = 1; i <= SetupCount; i++) {
! 	
! 	Setup = GSHORT(pd, offset);
  
! 	if (tree) {
! 
! 	  proto_tree_add_text(tree, NullTVB, offset, 2, "Setup%i: %u", i, Setup);
  
! 	}
  
+ 	offset += 2; /* Skip Setup */
+ 
+       }
+     }
+ 
      /* Build display for: Byte Count (BCC) */
  
      ByteCount = GSHORT(pd, offset);
***************
*** 8802,8818 ****
  
      offset += 2; /* Skip Byte Count (BCC) */
  
!     /* Build display for: Pad1 */
  
!     Pad1 = GBYTE(pd, offset);
  
!     if (tree) {
  
!       proto_tree_add_text(tree, NullTVB, offset, 1, "Pad1: %u", Pad1);
  
!     }
  
!     offset += 1; /* Skip Pad1 */
  
      /* Build display for: Parameter */
  
--- 9170,9189 ----
  
      offset += 2; /* Skip Byte Count (BCC) */
  
!     if (offset < (SMB_offset + ParameterOffset)) {
  
!       int pad1Count = SMB_offset + ParameterOffset - offset;
  
!       /* Build display for: Pad1 */
  
!       if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, pad1Count, "Pad1: %s", format_text(pd + offset, pad1Count));
!       }
  
!       offset += pad1Count; /* Skip Pad1 */
! 
!     }
  
      /* Build display for: Parameter */
  
***************
*** 8828,8845 ****
  
      }
  
!     /* Build display for: Pad2 */
  
!     Pad2 = GBYTE(pd, offset);
  
!     if (tree) {
  
!       proto_tree_add_text(tree, NullTVB, offset, 1, "Pad2: %u", Pad2);
  
!     }
  
!     offset += 1; /* Skip Pad2 */
  
      /* Build display for: Data */
  
      if (DataCount > 0) {
--- 9199,9220 ----
  
      }
  
!     if (DataCount > 0 && offset < (SMB_offset + DataOffset)) {
  
!       int pad2Count = SMB_offset + DataOffset - offset;
! 	
!       /* Build display for: Pad2 */
  
!       if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, pad2Count, "Pad2: %s", format_text(pd + offset, pad2Count));
  
!       }
  
!       offset += pad2Count; /* Skip Pad2 */
  
+     }
+ 
      /* Build display for: Data */
  
      if (DataCount > 0) {
***************
*** 8865,8871 ****
    char             *TransactNameCopy;
    char             *trans_type = NULL, *trans_cmd, *loc_of_slash = NULL;
    int              index;
-   guint8           Pad2;
    const gchar      *Data;
  
    if (!TransactName)
--- 9240,9245 ----
***************
*** 8908,8927 ****
        offset = SMB_offset + ParameterOffset + ParameterCount; /* Skip Parameters */
  
      }
  
!     if (offset % 2) {
  	
        /* Build display for: Pad2 */
  
-       Pad2 = GBYTE(pd, offset);
- 
        if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, 1, "Pad2: %u: %u", Pad2, offset);
  
        }
  
!       offset += 1; /* Skip Pad2 */
  
      }
  
--- 9282,9301 ----
        offset = SMB_offset + ParameterOffset + ParameterCount; /* Skip Parameters */
  
      }
+ 
+     if (DataCount > 0 && offset < (SMB_offset + DataOffset)) {
  
!       int pad2Count = SMB_offset + DataOffset - offset;
  	
        /* Build display for: Pad2 */
  
        if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, pad2Count, "Pad2: %s", format_text(pd + offset, pad2Count));
  
        }
  
!       offset += pad2Count; /* Skip Pad2 */
  
      }
  
***************
*** 8954,8960 ****
    guint8        SetupCount;
    guint8        Reserved3;
    guint8        Reserved1;
-   guint8        Pad1;
    guint8        MaxSetupCount;
    guint32       Timeout;
    guint16       TotalParameterCount;
--- 9328,9333 ----
***************
*** 9297,9315 ****
      offset += TNlen; /* Skip Transact Name */
      if (si.unicode) offset += 2;   /* There are two more extraneous bytes there*/
  
!     if (offset % 2) {
  
!       /* Build display for: Pad1 */
  
!       Pad1 = GBYTE(pd, offset);
  
        if (tree) {
- 
- 	proto_tree_add_text(tree, NullTVB, offset, 1, "Pad1: %u", Pad1);
  
        }
!     
!       offset += 1; /* Skip Pad1 */
  
      }
  
--- 9670,9687 ----
      offset += TNlen; /* Skip Transact Name */
      if (si.unicode) offset += 2;   /* There are two more extraneous bytes there*/
  
!     if (offset < (SMB_offset + ParameterOffset)) {
  
!       int pad1Count = SMB_offset + ParameterOffset - offset;
  
!       /* Build display for: Pad1 */
  
        if (tree) {
  
+ 	proto_tree_add_text(tree, NullTVB, offset, pad1Count, "Pad1: %s", format_text(pd + offset, pad1Count));
        }
! 
!       offset += pad1Count; /* Skip Pad1 */
  
      }
  
***************
*** 9480,9497 ****
  
      if (SetupCount > 0) {
  
!       /* Hmmm, should code for all setup words ... */
  
        Setup = GSHORT(pd, offset);
  
!       if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, 2, "Setup: %u", Setup);
  
!       }
  
!     offset += 2; /* Skip Setup */
  
      }
  
      /* Build display for: Byte Count (BCC) */
--- 9852,9875 ----
  
      if (SetupCount > 0) {
  
!       int i = SetupCount;
  
        Setup = GSHORT(pd, offset);
  
!       for (i = 1; i <= SetupCount; i++) {
! 	
! 	Setup = GSHORT(pd, offset);
  
! 	if (tree) {
  
! 	  proto_tree_add_text(tree, NullTVB, offset, 2, "Setup%i: %u", i, Setup);
! 
! 	}
  
! 	offset += 2; /* Skip Setup */
  
+       }
+ 
      }
  
      /* Build display for: Byte Count (BCC) */
***************
*** 9508,9524 ****
  
      /* Build display for: Pad1 */
  
!     if (offset % 2) {
  
!       Pad1 = GBYTE(pd, offset);
  
!       if (tree) {
  
! 	proto_tree_add_text(tree, NullTVB, offset, 1, "Pad1: %u", Pad1);
  
        }
  
!       offset += 1; /* Skip Pad1 */
  
      }
  
--- 9886,9903 ----
  
      /* Build display for: Pad1 */
  
!     if (offset < (SMB_offset + ParameterOffset)) {
  
!       int pad1Count = SMB_offset + ParameterOffset - offset;
  
!       /* Build display for: Pad1 */
  
!       if (tree) {
  
+ 	proto_tree_add_text(tree, NullTVB, offset, pad1Count, "Pad1: %s", format_text(pd + offset, pad1Count));
        }
  
!       offset += pad1Count; /* Skip Pad1 */
  
      }
  
***************
*** 9534,9541 ****
  
  void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info, int, int, int, int) = {
  
!   dissect_unknown_smb,      /* unknown SMB 0x00 */
!   dissect_unknown_smb,      /* unknown SMB 0x01 */
    dissect_unknown_smb,      /* SMBopen open a file */
    dissect_create_file_smb,  /* SMBcreate create a file */
    dissect_close_smb,        /* SMBclose close a file */
--- 9913,9920 ----
  
  void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info, int, int, int, int) = {
  
!   dissect_createdir_smb,    /* unknown SMB 0x00 */
!   dissect_deletedir_smb,    /* unknown SMB 0x01 */
    dissect_unknown_smb,      /* SMBopen open a file */
    dissect_create_file_smb,  /* SMBcreate create a file */
    dissect_close_smb,        /* SMBclose close a file */
***************
*** 9580,9586 ****
    dissect_unknown_smb,      /* SMBecho echo */
    dissect_unknown_smb,      /* SMBwriteclose write a file and then close it */
    dissect_open_andx_smb,      /* SMBopenX open and X */
!   dissect_unknown_smb,      /* SMBreadX read and X */
    dissect_unknown_smb,      /* SMBwriteX write and X */
    dissect_unknown_smb,      /* unknown SMB 0x30 */
    dissect_unknown_smb,      /* unknown SMB 0x31 */
--- 9959,9965 ----
    dissect_unknown_smb,      /* SMBecho echo */
    dissect_unknown_smb,      /* SMBwriteclose write a file and then close it */
    dissect_open_andx_smb,      /* SMBopenX open and X */
!   dissect_read_andx_smb,    /* SMBreadX read and X */
    dissect_unknown_smb,      /* SMBwriteX write and X */
    dissect_unknown_smb,      /* unknown SMB 0x30 */
    dissect_unknown_smb,      /* unknown SMB 0x31 */
***************
*** 9880,9886 ****
    {SMBE_useSTD, "Temporarily unable to use raw mode, use standard mode"},
    {SMBE_contMPX, "Resume MPX mode"},
    {SMBE_badPW, "Bad Password???"},
!   {SMBE_nosupport, "Operation not supported???"},
    { 0, 0}
  };
  
--- 10259,10265 ----
    {SMBE_useSTD, "Temporarily unable to use raw mode, use standard mode"},
    {SMBE_contMPX, "Resume MPX mode"},
    {SMBE_badPW, "Bad Password???"},
!   {SMBE_nosupport, "Operation not supported"},
    { 0, 0}
  };
  
***************
*** 9909,9915 ****
    {0, 0}
  };
  
! char *decode_smb_error(guint8 errcls, guint8 errcode)
  {
  
    switch (errcls) {
--- 10288,10294 ----
    {0, 0}
  };
  
! char *decode_smb_error(guint8 errcls, guint16 errcode)
  {
  
    switch (errcls) {
***************
*** 9951,9956 ****
--- 10330,10336 ----
  	proto_item      *ti, *tf;
  	guint8          cmd, errcls, errcode1, flags;
  	guint16         flags2, errcode, tid, pid, uid, mid;
+ 	guint32         status;
  	int             SMB_offset = offset;
  	struct smb_info si;
  
***************
*** 9993,10032 ****
  
  	offset += 1;
  
! 	/* Next, look at the error class, SMB_RETCLASS */
  
! 	errcls = pd[offset];
  
! 	if (tree) {
  
- 	  proto_tree_add_text(smb_tree, NullTVB, offset, 1, "Error Class: %s", 
- 			      val_to_str((guint8)pd[offset], errcls_types, "Unknown Error Class (%x)"));
  	}
  
! 	offset += 1;
  
! 	/* Error code, SMB_HEINFO ... */
  
! 	errcode1 = pd[offset];
  
! 	if (tree) {
  
! 	  proto_tree_add_text(smb_tree, NullTVB, offset, 1, "Reserved: %i", errcode1); 
  
! 	}
  
! 	offset += 1;
  
! 	errcode = GSHORT(pd, offset); 
  
! 	if (tree) {
  
! 	  proto_tree_add_text(smb_tree, NullTVB, offset, 2, "Error Code: %s",
! 			      decode_smb_error(errcls, errcode));
  
! 	}
  
! 	offset += 2;
  
  	/* Now for the flags: Bit 0 = 0 means cmd, 0 = 1 means resp */
  
--- 10373,10433 ----
  
  	offset += 1;
  
! 	/* Handle error code */
  
! 	if (GSHORT(pd, SMB_offset + 10) & 0x4000) {
! 	    /* handle NT 32 bit error code */
! 	    errcode = 0;	/* better than a random number */
! 	    status = GWORD(pd, offset); 
  
! 	    if (tree) {
! 
! 		proto_tree_add_text(smb_tree, NullTVB, offset, 4, "Status: 0x%08x",
! 				    status);
! 
! 	    }
! 
! 	    offset += 4;
  
  	}
+ 	else {
+ 	    /* handle DOS error code & class */
  
! 	    /* Next, look at the error class, SMB_RETCLASS */
  
! 	    errcls = pd[offset];
  
! 	    if (tree) {
  
! 		proto_tree_add_text(smb_tree, NullTVB, offset, 1, "Error Class: %s", 
! 				    val_to_str((guint8)pd[offset], errcls_types, "Unknown Error Class (%x)"));
! 	    }
  
! 	    offset += 1;
  
! 	    /* Error code, SMB_HEINFO ... */
  
! 	    errcode1 = pd[offset];
  
! 	    if (tree) {
  
! 		proto_tree_add_text(smb_tree, NullTVB, offset, 1, "Reserved: %i", errcode1); 
  
! 	    }
  
! 	    offset += 1;
  
! 	    errcode = GSHORT(pd, offset); 
! 
! 	    if (tree) {
! 
! 		proto_tree_add_text(smb_tree, NullTVB, offset, 2, "Error Code: %s",
! 				    decode_smb_error(errcls, errcode));
! 
! 	    }
! 
! 	    offset += 2;
! 	}
  
  	/* Now for the flags: Bit 0 = 0 means cmd, 0 = 1 means resp */