Index: gtk/menus.c
===================================================================
--- gtk/menus.c	(revision 33225)
+++ gtk/menus.c	(working copy)
@@ -483,7 +483,7 @@
                              0, NULL, NULL,},
     {"/File/Export/_Objects/_HTTP", NULL, GTK_MENU_FUNC(eo_http_cb), 0, NULL, NULL,},
     {"/File/Export/_Objects/_DICOM", NULL, GTK_MENU_FUNC(eo_dicom_cb), 0, NULL, NULL,},
-
+    {"/File/Export/_Objects/_SMB", NULL, GTK_MENU_FUNC(eo_smb_cb), 0, NULL, NULL,},
     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
     {"/File/_Print...", "<control>P", GTK_MENU_FUNC(file_print_cmd_cb),
                              0, "<StockItem>", GTK_STOCK_PRINT,},
Index: gtk/Makefile.common
===================================================================
--- gtk/Makefile.common	(revision 33225)
+++ gtk/Makefile.common	(working copy)
@@ -57,6 +57,7 @@
 	export_object.c	       \
 	export_object_dicom.c	\
 	export_object_http.c   \
+	export_object_smb.c   \
 	filter_autocomplete.c	\
 	file_dlg.c	\
 	fileset_dlg.c	\
Index: gtk/export_object_smb.c
===================================================================
--- gtk/export_object_smb.c	(revision 0)
+++ gtk/export_object_smb.c	(revision 0)
@@ -0,0 +1,452 @@
+/* export_object_smb.c
+ * Routines for tracking & saving objects (files) found in SMB streams
+ * See also: export_object.c / export_object.h for common code
+ * Initial file, prototypes and general structure initially copied 
+ * from export_object_http.c
+ *
+ * Copyright 2010, David Perez & Jose Pico from TADDONG S.L.
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <epan/packet.h>
+#include <epan/dissectors/packet-smb.h>
+#include <epan/tap.h>
+
+#include "gtk/export_object.h"
+
+
+/* These flags show what kind of data the object contains 
+   (designed to be or'ed) */
+#define SMB_EO_CONTAINS_NOTHING		0x00
+#define SMB_EO_CONTAINS_READS		0x01
+#define SMB_EO_CONTAINS_WRITES		0x02
+#define SMB_EO_CONTAINS_READSANDWRITES	0x03
+#define LEGAL_FILENAME_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ1234567890_."
+
+const value_string smb_eo_contains_string[]={
+	{SMB_EO_CONTAINS_NOTHING,     		""},
+	{SMB_EO_CONTAINS_READS,     		"R"},
+	{SMB_EO_CONTAINS_WRITES,     		"W"},
+	{SMB_EO_CONTAINS_READSANDWRITES,     	"R&W"}
+	};
+
+
+/* This struct contains the relationship between 
+   the row# in the export_object window and the file beeing captured;
+   the row# in this GSList will match the row# in the entry list */
+
+typedef struct _active_file {
+        guint16         tid,uid,fid;
+        guint64         file_length;    /* The last free reported offset */
+                                        /* We treat it as the file length */
+        guint64         data_gathered;  /* The actual total of data gathered */
+        guint8          flag_contains;  /* What kind of data it contains */
+        GSList          *free_chunk_list;
+					/* A list of virtual "holes" in the */
+					/* file stream stored in memory */
+	gboolean	is_out_of_memory;
+					/* TRUE if we cannot allocate memory */
+					/* memory for this file */
+        } active_file ;
+
+/* This is the GSList that will contain all the files that we are tracking */
+static GSList	*GSL_active_files;
+
+/* This is the binary tree that will contain all the packets already processed
+   We want to process each smb packet only once */
+static GTree	*btree_visited_packet;
+
+/* The comparison function for the btree_visited_packet */
+gint btree_visited_packet_cmpkey(gconstpointer keya, gconstpointer keyb, gpointer user_data) {
+	gint nop_value;
+	guint32 *a = (guint32 *)keya;
+	guint32 *b = (guint32 *)keyb;
+	gboolean *data = (gboolean *)user_data;
+
+	if (*data == TRUE) nop_value=0;
+
+	if (*a == *b) { return 0; } 
+	else 	if (*a > *b) { return 1; } 
+		else { return -1; }
+}
+
+/* We define a free chunk in a file as an start offset and end offset
+   Consider a free chunk as a "hole" in a file that we are capturing */
+typedef struct _free_chunk {
+        guint64         start_offset;
+        guint64         end_offset;
+} free_chunk;
+
+/* insert_chunk function will recalculate the free_chunk_list, the data_size,
+   the end_of_file, and the data_gathered as appropriate.
+   It will also insert the data chunk that is coming in the right
+   place of the file in memory.
+   HINTS:
+   file->data_gathered 	contains the real data gathered independently 
+	 		from the file length
+   file->file_length 	contains the length of the file in memory, i.e., 
+			the last offset captured. In most cases, the real 
+			file length would be different.
+*/
+void insert_chunk(active_file   *file, export_object_entry_t *entry, const smb_eo_t *eo_info)
+{
+        guint           nfreechunks = g_slist_length(file->free_chunk_list);
+	guint		i;
+        free_chunk      *current_free_chunk;
+        free_chunk      *new_free_chunk;
+	guint64 	chunk_offset=eo_info->smb_file_offset;
+	guint64 	chunk_length=eo_info->payload_len;
+        guint64         chunk_end_offset = chunk_offset+chunk_length-1;
+	/* Size of file in memory */
+        guint64         calculated_size = chunk_offset+chunk_length;	
+	gpointer	dest_memory_addr;
+
+	/* Let's recalculate the file length and data gathered */
+	if (file->data_gathered==0 && nfreechunks==0) {
+		/* If this is the first entry for this file, we first
+		   create an initial free chunk */
+                new_free_chunk=g_malloc(sizeof(free_chunk));
+                new_free_chunk->start_offset=0;
+		new_free_chunk->end_offset=MAX(file->file_length,chunk_end_offset+1)-1;
+		file->free_chunk_list=NULL;
+		file->free_chunk_list=g_slist_append(file->free_chunk_list,new_free_chunk);
+		nfreechunks+=1;
+	} else {
+		if (chunk_end_offset > file->file_length-1) {
+                	new_free_chunk=g_malloc(sizeof(free_chunk));
+                	new_free_chunk->start_offset=file->file_length;
+			new_free_chunk->end_offset=chunk_end_offset;
+			file->free_chunk_list=g_slist_append(file->free_chunk_list,new_free_chunk);
+			nfreechunks+=1;
+			}
+	}
+	file->file_length = MAX(file->file_length,chunk_end_offset+1);
+
+        for (i=0;i<nfreechunks;i++) {
+                current_free_chunk = g_slist_nth_data(file->free_chunk_list,i);
+                if (chunk_offset <= current_free_chunk->start_offset ) {
+                        if (chunk_end_offset >= current_free_chunk->start_offset) {
+                                if (chunk_end_offset < current_free_chunk->end_offset) {
+                                        file->data_gathered+=
+                                                (chunk_end_offset-current_free_chunk->start_offset+1);
+                                        current_free_chunk->start_offset=chunk_end_offset+1;
+                                } else {
+                                        file->data_gathered+=
+                                                (current_free_chunk->end_offset-current_free_chunk->start_offset+1);
+                                        file->free_chunk_list =
+                                                g_slist_remove(file->free_chunk_list,current_free_chunk);
+					nfreechunks-=1;
+					if (nfreechunks==0) { /* The free chunk list is empty */
+						g_slist_free(file->free_chunk_list);
+						file->free_chunk_list=NULL;
+						break;
+					}
+                                }
+                        } else {
+                                break;
+                        }
+                } else {
+			if (chunk_offset <= current_free_chunk->end_offset) {
+                                if (chunk_end_offset < current_free_chunk->end_offset) {
+                                        new_free_chunk=g_malloc(sizeof(free_chunk));
+                                        new_free_chunk->start_offset=chunk_end_offset+1;
+                                        new_free_chunk->end_offset=current_free_chunk->end_offset;
+                                        current_free_chunk->end_offset=chunk_offset-1;
+                                        file->free_chunk_list =
+                                                g_slist_insert(file->free_chunk_list,new_free_chunk,i+1);
+                                        file->data_gathered+=chunk_length;
+                                } else {
+                                        file->data_gathered+=current_free_chunk->end_offset-chunk_offset+1;
+                                        current_free_chunk->end_offset=chunk_offset-1;
+                                }
+                        }
+                }
+        }
+
+	/* Now, let's insert the data chunk into memory
+	   ...first, we shall be able to allocate the memory */
+	if (!entry->payload_data) {
+		/* This is a New file */
+		entry->payload_data = g_try_malloc(calculated_size);
+		if (!entry->payload_data) {
+			/* Memory error */
+			file->is_out_of_memory=TRUE;
+		}
+	} else { 
+		/* This is an existing file in memory */
+		if (calculated_size > (guint64) entry->payload_len &&
+		    !file->is_out_of_memory) { 
+			/* We need more memory */
+			dest_memory_addr=g_try_realloc(
+				entry->payload_data,
+				calculated_size);
+			if(!dest_memory_addr) { 
+				/* Memory error */
+				file->is_out_of_memory=TRUE;
+				/* We don have memory for this file. 
+				   Free the current file content from memory */
+				g_free(entry->payload_data);
+				entry->payload_data=NULL;
+				entry->payload_len=0;
+			} else {
+				entry->payload_data=dest_memory_addr;
+				entry->payload_len=calculated_size;
+			}
+		}
+	}
+	/* ...then, put the chunk of the file in the right place */
+	if(!file->is_out_of_memory) {
+		dest_memory_addr=entry->payload_data+chunk_offset;
+		g_memmove(dest_memory_addr,eo_info->payload_data,eo_info->payload_len);
+	}
+}
+
+/* We use this function to obtain the index in the GSL of a given file */
+int find_incoming_file(GSList *GSL_active_files,active_file *incoming_file)
+{
+	int 	i,row,last;
+	active_file	*in_list_file;
+
+	row=-1;
+	i=0;
+	last=g_slist_length(GSL_active_files)-1;
+	
+	/* We lookup in reverse order because it is more likely that the file
+	   is one of the latest */
+	for (i=last;i>=0;i--) {
+		in_list_file=g_slist_nth_data(GSL_active_files, i);
+		/* The best-working criteria of two identical files is that the file
+  		   that is the same of the file that we are analyzing is the last one
+		   in the list that has the same tid and the same fid */
+		/* note that we have excluded in_list_file->uid == incoming_file->uid
+		   from the comparison, because a file can be opened by different
+		   SMB users and it is still the same file */
+		if (in_list_file->tid == incoming_file->tid &&
+				in_list_file->fid == incoming_file->fid) {
+			row=i;
+			break;
+		}
+	}
+	
+	return row;
+}
+
+/* This is the function answering to the registered tap listener call */
+static int
+eo_smb_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
+	       const void *data)
+{
+	extern GSList	*GSL_active_files;
+	extern GTree	*btree_visited_packet;
+
+	export_object_list_t *object_list = tapdata;
+	const smb_eo_t *eo_info = data;
+
+	export_object_entry_t 	*entry;
+	export_object_entry_t 	*current_entry;
+	active_file		incoming_file;
+	gint			active_row;
+	active_file		*new_file;
+	active_file		*current_file;
+	guint8			contains;
+	gboolean		is_supported_filetype;
+
+	guint32			*packetnum;
+	gboolean		*visited_packet;
+	gboolean		new_packet;
+	gfloat			percent;
+
+	gchar			**aux_string_v;
+
+
+	/* Obtain the packet number that originates the analysis */
+	packetnum=g_malloc(sizeof(guint32));
+	*packetnum=pinfo->fd->num;
+
+	/* Lets look for that packet number */
+	#ifdef SMB_DEBUG
+	printf("\tbtree_visited_packet: Looking for packet %u\n",*packetnum);
+	#endif
+	visited_packet = g_tree_lookup(btree_visited_packet, packetnum);
+	if (visited_packet==NULL) {
+		new_packet=TRUE;
+		visited_packet=g_malloc(sizeof(gboolean));
+		*visited_packet=TRUE;
+		g_tree_insert(btree_visited_packet,packetnum,visited_packet);
+	} else {
+		new_packet=FALSE;
+		}
+
+	if(eo_info && new_packet) { /* We have new data waiting for us */
+		/* Is a eo_smb supported file_type? (right now we only support FILE */
+		is_supported_filetype = (eo_info->fid_type==SMB_FID_TYPE_FILE);
+
+		/* What kind of data this packet contains? */
+		switch(eo_info->cmd) {
+			case SMB_COM_READ_ANDX: 
+				contains=SMB_EO_CONTAINS_READS;
+				break;
+			case SMB_COM_WRITE_ANDX: 
+				contains=SMB_EO_CONTAINS_WRITES;
+				break;
+			default: 
+				contains=SMB_EO_CONTAINS_NOTHING;
+				break;
+			}
+		
+		/* Is this data from an already tracked file or not? */
+		incoming_file.tid=eo_info->tid;
+		incoming_file.uid=eo_info->uid;
+		incoming_file.fid=eo_info->fid;
+		active_row=find_incoming_file(GSL_active_files, &incoming_file);
+
+		if (active_row==-1) { /* This is a new-tracked file */
+			
+			/* Construct the entry in the list of active files */
+			entry = g_malloc(sizeof(export_object_entry_t));
+			entry->payload_data=NULL;
+			entry->payload_len=0;
+			new_file = g_malloc(sizeof(active_file));
+			new_file->tid=incoming_file.tid;
+			new_file->uid=incoming_file.uid;
+			new_file->fid=incoming_file.fid;
+			new_file->file_length = eo_info->end_of_file;
+			new_file->flag_contains=contains;
+                        new_file->free_chunk_list=NULL;
+			new_file->data_gathered=0;
+			new_file->is_out_of_memory=FALSE;
+			entry->pkt_num = pinfo->fd->num;
+			entry->hostname = g_strdup(eo_info->hostname);
+			if (g_str_has_prefix(eo_info->filename,"\\")) {
+				aux_string_v = g_strsplit(eo_info->filename, "\\", -1);
+				entry->filename = g_strdup(aux_string_v[1]);
+				g_strfreev(aux_string_v); 
+			} else {
+				entry->filename = g_strdup(eo_info->filename);
+			}
+
+			/* Insert the first chunk in the chunk list of this file */
+			if (is_supported_filetype) {
+				insert_chunk(new_file, entry, eo_info);
+			} 
+				
+			if(new_file->is_out_of_memory) {
+				entry->content_type = 
+					g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
+					match_strval(eo_info->fid_type, smb_fid_types),
+					new_file->data_gathered,
+					new_file->file_length,
+					match_strval(contains, smb_eo_contains_string));
+			} else {
+				percent=(gfloat) 100*new_file->data_gathered/new_file->file_length;
+				entry->content_type = 
+					g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
+					match_strval(eo_info->fid_type, smb_fid_types),
+					new_file->data_gathered,
+					new_file->file_length,
+					match_strval(contains, smb_eo_contains_string),
+					percent);
+			}
+
+			object_list->entries =
+				g_slist_append(object_list->entries, entry);
+			GSL_active_files = 
+				g_slist_append(GSL_active_files, new_file);
+			}
+		else if (is_supported_filetype) {	
+			current_file=g_slist_nth_data(GSL_active_files,active_row);
+			/* Recalculate the current file flags */
+			current_file->flag_contains=current_file->flag_contains|contains;
+			current_entry=g_slist_nth_data(object_list->entries,active_row);
+
+			insert_chunk(current_file, current_entry, eo_info);
+
+			/* Modify the current_entry object_type string */
+			if(current_file->is_out_of_memory) {
+				current_entry->content_type = 
+					g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
+					match_strval(eo_info->fid_type, smb_fid_types),
+					current_file->data_gathered,
+					current_file->file_length,
+					match_strval(current_file->flag_contains, smb_eo_contains_string));
+			} else {
+				percent=(gfloat) 100*current_file->data_gathered/current_file->file_length;
+				current_entry->content_type = 
+					g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
+					match_strval(eo_info->fid_type, smb_fid_types),
+					current_file->data_gathered,
+					current_file->file_length,
+					match_strval(current_file->flag_contains, smb_eo_contains_string),
+					percent);
+			}
+		}
+		return 1; /* State changed - window should be redrawn */
+	} 
+	else {
+		return 0; /* State unchanged - no window updates needed */
+	}
+}
+
+void
+eo_smb_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+	extern GSList	*GSL_active_files;
+	extern GTree	*btree_visited_packet;
+	int 	i=0,last;
+	active_file	*in_list_file;
+
+	/* Free any previous data structures used in previous invocation to the 
+	   export_object_smb function */
+	last=g_slist_length(GSL_active_files);
+	if (GSL_active_files) {
+		for (i=last-1;i>=0;i--) {
+			in_list_file=g_slist_nth_data(GSL_active_files, i);
+			if (in_list_file->free_chunk_list) {
+				g_slist_free(in_list_file->free_chunk_list);
+                        	in_list_file->free_chunk_list=NULL;
+				}
+			g_free(in_list_file);
+			}
+		g_slist_free(GSL_active_files);
+		GSL_active_files=NULL;
+		i=g_slist_length(GSL_active_files);
+	}
+
+	/* Initialize the tree */
+	if (btree_visited_packet) {
+		g_tree_destroy(btree_visited_packet);
+		btree_visited_packet=NULL;
+	}
+	btree_visited_packet=g_tree_new_full(btree_visited_packet_cmpkey,NULL,g_free,g_free);
+
+	/* Then call the export_object window */
+	export_object_window("smb_eo", "SMB", eo_smb_packet);
+}
Index: gtk/export_object.c
===================================================================
--- gtk/export_object.c	(revision 33225)
+++ gtk/export_object.c	(working copy)
@@ -318,7 +318,9 @@
 
 	object_list->store = gtk_tree_store_new(EO_NUM_COLUMNS,
 						 G_TYPE_INT, G_TYPE_STRING,
-						 G_TYPE_STRING, G_TYPE_INT,
+						 /* we need a UINT64
+                                                    (was G_TYPE_STRING, G_TYPE_INT,) */
+                                                 G_TYPE_STRING, G_TYPE_INT64,
 						 G_TYPE_STRING);
 
 	object_list->tree = tree_view_new(GTK_TREE_MODEL(object_list->store));
@@ -376,7 +378,6 @@
 	selection = gtk_tree_view_get_selection(object_list->tree_view);
 	g_signal_connect(selection, "changed", G_CALLBACK(eo_remember_row_num), object_list);
 
-
 	bbox = dlg_button_row_new(GTK_STOCK_HELP, WIRESHARK_STOCK_SAVE_ALL, GTK_STOCK_SAVE_AS, GTK_STOCK_CANCEL, NULL);
 
 	/* Help button */
Index: gtk/export_object.h
===================================================================
--- gtk/export_object.h	(revision 33225)
+++ gtk/export_object.h	(working copy)
@@ -42,7 +42,9 @@
 	gchar *hostname;
 	gchar *content_type;
 	gchar *filename;
-	guint payload_len;
+        /* We need to store a 64 bit integer to hold a file length
+           (was guint payload_len;) */
+        gint64 payload_len;
 	guint8 *payload_data;
 } export_object_entry_t;
 
@@ -52,5 +54,6 @@
 /* Protocol specific */
 void eo_http_cb(GtkWidget *widget _U_, gpointer data _U_);
 void eo_dicom_cb(GtkWidget *widget _U_, gpointer data _U_);
+void eo_smb_cb(GtkWidget *widget _U_, gpointer data _U_);
 
 #endif /* __EXPORT_OBJECT_H__ */
Index: gtk/CMakeLists.txt
===================================================================
--- gtk/CMakeLists.txt	(revision 33225)
+++ gtk/CMakeLists.txt	(working copy)
@@ -45,6 +45,7 @@
 	export_object.c
 	export_object_dicom.c
 	export_object_http.c
+	export_object_smb.c
 	filter_autocomplete.c
 	file_dlg.c
 	fileset_dlg.c
Index: epan/dissectors/packet-smb.c
===================================================================
--- epan/dissectors/packet-smb.c	(revision 33225)
+++ epan/dissectors/packet-smb.c	(working copy)
@@ -30,6 +30,8 @@
 # include "config.h"
 #endif
 
+#include <inttypes.h>
+
 #include <time.h>
 #include <string.h>
 #include <glib.h>
@@ -765,6 +767,7 @@
 static gint ett_smb_posix_ace_perms = -1;
 
 static int smb_tap = -1;
+static int smb_eo_tap = -1;
 
 static dissector_handle_t gssapi_handle;
 static dissector_handle_t ntlmssp_handle;
@@ -884,6 +887,13 @@
 
 gboolean sid_name_snooping = FALSE;
 
+/* Compare funtion to maintain the GSL_fid_info ordered
+   Order criteria: packet where the fid was opened */
+gint fid_cmp(smb_fid_info_t *fida, smb_fid_info_t *fidb)
+{
+        return (fida->opened_in - fidb->opened_in);
+}
+
 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
@@ -3444,6 +3454,10 @@
 	proto_item *it;
 	proto_tree *tr;
 	smb_fid_info_t *fid_info=NULL;
+        smb_fid_info_t *suspect_fid_info=NULL;
+        /* We need this to use an array-accessed tree */
+        GSList          *GSL_iterator;
+        int             found=0;
 
 	DISSECTOR_ASSERT(si);
 
@@ -3460,17 +3474,38 @@
 		fid_info->opened_in=pinfo->fd->num;
 		fid_info->closed_in=0;
 		fid_info->type=SMB_FID_TYPE_UNKNOWN;
+                fid_info->fid=fid;
+                fid_info->tid=si->tid;
 		if(si->sip && (si->sip->extra_info_type==SMB_EI_FILEDATA)){
 			fid_info->fsi=si->sip->extra_info;
 		} else {
 			fid_info->fsi=NULL;
 		}
-
-		se_tree_insert32(si->ct->fid_tree, fid, fid_info);
+                /* We don't use the fid_tree anymore to access and
+                   maintain the fid information of analized files.
+                   (was se_tree_insert32(si->ct->fid_tree, fid, fid_info);)
+                   We'll use a single list instead to keep track of the
+                   files (fid) opened.
+                   Note that the insert_sorted function allows to insert duplicates
+                   but being inside this if section should prevent it */
+                si->ct->GSL_fid_info=g_slist_insert_sorted(
+                                        si->ct->GSL_fid_info,
+                                        fid_info,
+                                        (GCompareFunc)fid_cmp);
 	}
 
 	if(!fid_info){
-		fid_info=se_tree_lookup32(si->ct->fid_tree, fid);
+                /* we use the single linked list to access this fid_info
+                   (was fid_info=se_tree_lookup32(si->ct->fid_tree, fid);) */
+                GSL_iterator = si->ct->GSL_fid_info;
+                while (GSL_iterator) {
+                        suspect_fid_info=GSL_iterator->data;
+                        if(suspect_fid_info->opened_in > pinfo->fd->num) break;
+                        if(suspect_fid_info->tid==si->tid && suspect_fid_info->fid==fid)
+                                fid_info=suspect_fid_info;
+                        GSL_iterator=g_slist_next(GSL_iterator);
+                        found+=1;
+                }
 	}
 	if(!fid_info){
 		return NULL;
@@ -6014,6 +6049,18 @@
 		fn);
 	COUNT_BYTES(fn_len);
 
+        /* Copied this portion of code from create_andx_request
+           to guarantee that fsi and si->sip are always correctly filled out */
+        if((!pinfo->fd->flags.visited) && si->sip && fn){
+                smb_fid_saved_info_t *fsi;
+
+                fsi=se_alloc(sizeof(smb_fid_saved_info_t));
+                fsi->filename=se_strdup(fn);
+
+                si->sip->extra_info_type=SMB_EI_FILEDATA;
+                si->sip->extra_info=fsi;
+        }
+
 	if (check_col(pinfo->cinfo, COL_INFO)) {
 		col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
 		    format_text(fn, strlen(fn)));
@@ -6092,6 +6139,10 @@
 	guint8	wc, cmd=0xff;
 	guint16 andxoffset=0, bc;
 	guint16 fid;
+        guint16 ftype;
+        guint16 fattr;
+        smb_fid_info_t *fid_info=NULL;
+        gboolean        isdir=FALSE;
 
 	WORD_COUNT;
 
@@ -6115,16 +6166,22 @@
 
 	/* fid */
 	fid = tvb_get_letohs(tvb, offset);
-	dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE);
+        /* we add fid_info= to this call so that we save the result */
+        fid_info=dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE);
+
 	offset += 2;
 
 	/* File Attributes */
+        fattr = tvb_get_letohs(tvb, offset);
+        isdir = fattr & 0x10;
 	offset = dissect_file_attributes(tvb, tree, offset, 2);
 
 	/* last write time */
 	offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
 
 	/* File Size */
+        /* We store the file_size in the fid_info */
+        fid_info->end_of_file=(guint64) tvb_get_letohl(tvb, offset);
 	proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
 	offset += 4;
 
@@ -6132,8 +6189,30 @@
 	offset = dissect_access(tvb, tree, offset, "Granted");
 
 	/* File Type */
+        ftype=tvb_get_letohs(tvb, offset);
 	proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
 	offset += 2;
+        /* Copied from dissect_nt_create_andx_response
+           Try to remember the type of this fid so that we can dissect
+           any future security descriptor (access mask) properly
+         */
+        fid_info->type=SMB_FID_TYPE_UNKNOWN;
+        if(ftype==0){
+                if(isdir==0){
+                        if(fid_info){
+                                fid_info->type=SMB_FID_TYPE_FILE;
+                        }
+                } else {
+                        if(fid_info){
+                                fid_info->type=SMB_FID_TYPE_DIR;
+                        }
+                }
+        }
+        if(ftype==2 || ftype==1){
+                if(fid_info){
+                        fid_info->type=SMB_FID_TYPE_PIPE;
+                }
+        }
 
 	/* IPC State */
 	offset = dissect_ipc_state(tvb, tree, offset, FALSE);
@@ -6303,6 +6382,14 @@
 	return offset;
 }
 
+/* Strings that describes the SMB object type */
+const value_string smb_fid_types[] = {
+        {SMB_FID_TYPE_UNKNOWN,"UNKNOWN"},
+        {SMB_FID_TYPE_FILE,"FILE"},
+        {SMB_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
+        {SMB_FID_TYPE_PIPE,"PIPE (Not Implemented)"}
+};
+
 static int
 dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
 {
@@ -6310,9 +6397,19 @@
 	guint16 andxoffset=0, bc, datalen_low, dataoffset=0;
 	guint32 datalen=0, datalen_high;
 	smb_info_t *si = (smb_info_t *)pinfo->private_data;
-	int fid=0;
 	rw_info_t *rwi=NULL;
+        guint16 fid=0; /* was int fid=0; */
 
+        smb_eo_t        *eo_info; /* eo_info variable to pass info. to
+                                     export object and aux */
+        smb_tid_info_t  *tid_info=NULL;
+        smb_fid_info_t  *fid_info=NULL;
+        smb_fid_info_t  *suspect_fid_info=NULL;
+        guint32 tvblen,packet_number;
+        tvbuff_t        *data_tvb;
+        GSList          *GSL_iterator;
+        int             found=0;
+
 	DISSECTOR_ASSERT(si);
 
 	WORD_COUNT;
@@ -6413,6 +6510,51 @@
 		bc = 0;
 	}
 
+        /* feed the export object tap listener */
+        tvblen = tvb_length_remaining(tvb, dataoffset);
+        if(have_tap_listener(smb_eo_tap) && datalen==tvblen && rwi) {
+                packet_number=pinfo->fd->num;
+                /* Create a new tvb to point to the payload data */
+                data_tvb = tvb_new_subset(tvb, dataoffset, datalen, tvblen);
+                /* Create the eo_info to pass to the listener */
+                eo_info = ep_alloc(sizeof(smb_eo_t));
+
+                /* Try to get fid_info and tid_info */
+                if (fid_info==NULL) {
+                        GSL_iterator = si->ct->GSL_fid_info;
+                        while (GSL_iterator) {
+                                suspect_fid_info=GSL_iterator->data;
+                                if(suspect_fid_info->opened_in > pinfo->fd->num) break;
+                                if(suspect_fid_info->tid==si->tid && suspect_fid_info->fid==fid)
+                                        fid_info=suspect_fid_info;
+                                GSL_iterator=g_slist_next(GSL_iterator);
+                                found+=1;
+                        }
+                }
+                tid_info = se_tree_lookup32(si->ct->tid_tree, si->tid);
+
+                /* Construct the eo_info structure */
+                if (tid_info)   eo_info->hostname = tid_info->filename;
+                else            eo_info->hostname = ep_strdup_printf("\\\\TREEID_%i",si->tid);
+                if (fid_info) {
+                        eo_info->filename=NULL;
+                        if (fid_info->fsi)
+                                if (fid_info->fsi->filename)
+                                        eo_info->filename = (gchar *) fid_info->fsi->filename;
+                        if(!eo_info->filename) eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
+                        eo_info->fid_type = fid_info->type;                                             eo_info->end_of_file = fid_info->end_of_file;
+                } else {                                                                                eo_info->fid_type=SMB_FID_TYPE_UNKNOWN;
+                        eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);                        eo_info->end_of_file = 0;
+                }                                                                               eo_info->fid=fid;
+                eo_info->tid=si->tid;                                                           eo_info->uid=si->uid;
+                eo_info->payload_len = datalen;                                                 eo_info->payload_data = data_tvb->real_data;
+                eo_info->smb_file_offset=rwi->offset;                                           eo_info->smb_chunk_len=rwi->len;
+                eo_info->cmd=SMB_COM_READ_ANDX;
+                /* Queue data to the listener */
+
+                tap_queue_packet(smb_eo_tap, pinfo, eo_info);
+        }
+
 	END_OF_SMB
 
 	if (cmd != 0xff) { 	/* there is an andX command */
@@ -6432,11 +6574,20 @@
 	guint16 andxoffset=0, bc, dataoffset=0, datalen_low, datalen_high;
 	guint32 datalen=0;
 	smb_info_t *si = (smb_info_t *)pinfo->private_data;
-	unsigned int fid=0;
+        guint16 fid=0; /* was unsigned int fid=0; */
 	guint16 mode = 0;
 	rw_info_t *rwi=NULL;
+        /* eo_info variables to pass info. to export object and
+           other aux */
+        smb_eo_t        *eo_info;
+        smb_tid_info_t  *tid_info=NULL;
+        smb_fid_info_t  *fid_info=NULL;
+        smb_fid_info_t  *suspect_fid_info=NULL;
+        guint32 tvblen,packet_number;
+        tvbuff_t        *data_tvb;
+        GSList          *GSL_iterator;
+        int             found=0;
 
-
 	DISSECTOR_ASSERT(si);
 
 	WORD_COUNT;
@@ -6575,6 +6726,65 @@
 		bc = 0;
 	}
 
+        /* feed the export object tap listener */
+        tvblen = tvb_length_remaining(tvb, dataoffset);
+        if(have_tap_listener(smb_eo_tap) && datalen==tvblen && rwi) {
+                packet_number=pinfo->fd->num;
+                /* Create a new tvb to point to the payload data */
+                data_tvb = tvb_new_subset(tvb, dataoffset, datalen, tvblen);
+                /* Create the eo_info to pass to the listener */
+                eo_info = ep_alloc(sizeof(smb_eo_t));
+
+                /* Try to get fid_info and tid_info */
+                if (fid_info==NULL) {
+                        /* We'll use a GSL instead */
+                        /* (was fid_info = se_tree_lookup32(si->ct->fid_tree, fi
+d);) */
+                        GSL_iterator = si->ct->GSL_fid_info;
+                        while (GSL_iterator) {
+                                suspect_fid_info=GSL_iterator->data;
+                                if(suspect_fid_info->opened_in > pinfo->fd->num)
+ break;
+                                if(suspect_fid_info->tid==si->tid && suspect_fid_info->fid==fid)
+                                        fid_info=suspect_fid_info;
+                                GSL_iterator=g_slist_next(GSL_iterator);
+                                found+=1;
+                        }
+                }
+                tid_info = se_tree_lookup32(si->ct->tid_tree, si->tid);
+
+                /* Construct the eo_info structure */
+                if (tid_info)   eo_info->hostname = tid_info->filename;
+                else            eo_info->hostname = ep_strdup_printf("\\\\TREEID_%i",si->tid);
+                if (fid_info) {
+                        eo_info->filename=NULL;
+                        if (fid_info->fsi) {
+                                if (fid_info->fsi->filename) {
+                                        eo_info->filename = (gchar *) fid_info->fsi->filename;
+                                        }
+                                }
+                        if(!eo_info->filename) eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
+                        eo_info->fid_type = fid_info->type;
+                        eo_info->end_of_file = fid_info->end_of_file;
+                } else {
+                        eo_info->fid_type=SMB_FID_TYPE_UNKNOWN;
+                        eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
+                        eo_info->end_of_file = 0;
+                }
+                eo_info->fid=fid;
+                eo_info->tid=si->tid;
+                eo_info->uid=si->uid;
+                eo_info->payload_len = datalen;
+                eo_info->payload_data = data_tvb->real_data;
+                eo_info->smb_file_offset=rwi->offset;
+                eo_info->smb_chunk_len=rwi->len;
+                eo_info->cmd=SMB_COM_WRITE_ANDX;
+
+                /* Queue data to the listener */
+
+                tap_queue_packet(smb_eo_tap, pinfo, eo_info);
+        }
+
 	END_OF_SMB
 
 	if (cmd != 0xff) { 	/* there is an andX command */
@@ -9911,6 +10121,8 @@
 	offset += 8;
 
 	/* end of file */
+        /* We store the end of file */
+        fid_info->end_of_file=tvb_get_letoh64(tvb, offset);
 	proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
 	offset += 8;
 
@@ -16735,6 +16947,8 @@
 		si->ct->fid_tree=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "SMB fid_tree");
 		si->ct->tid_tree=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "SMB tid_tree");
 		si->ct->uid_tree=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "SMB uid_tree");
+                /* Initialize the GSL_fid_info for this ct */
+                si->ct->GSL_fid_info=NULL;
 		conversation_add_proto_data(conversation, proto_smb, si->ct);
 	}
 
@@ -19650,6 +19864,9 @@
 	register_init_routine(smb_trans_reassembly_init);
 	smb_tap = register_tap("smb");
 
+        /* Register the tap for the "Export Object" function */
+        smb_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
+
 	register_dissector("smb", dissect_smb, proto_smb);
 }
 
Index: epan/dissectors/packet-smb.h
===================================================================
--- epan/dissectors/packet-smb.h	(revision 33225)
+++ epan/dissectors/packet-smb.h	(working copy)
@@ -177,6 +177,25 @@
 #define SMBE_sharebufexc 36 /* A sharing buffer has been exceeded */
 #define SMBE_diskfull 39
 
+/* Used for SMB Export Object feature */
+typedef struct _smb_eo_t {
+        guint8 cmd;
+        int     tid,uid,fid;
+        guint32  pkt_num;
+        gchar   *hostname;
+        gchar   *filename;
+        int fid_type;
+        gint64  end_of_file;
+        gchar   *content_type;
+        guint32  payload_len;
+        const guint8 *payload_data;
+        guint64 smb_file_offset;
+        guint32 smb_chunk_len;
+} smb_eo_t;
+
+/* Strings that describes the SMB object type */
+WS_VAR_IMPORT const value_string smb_fid_types[];
+
 /* the information we need to keep around for NT transatcion commands */
 typedef struct {
 	int subcmd;
@@ -238,7 +257,8 @@
 	int subcmd;
 	int trans_subcmd;
 	int function;
-	int fid;
+        /* Unification of fid variable type (was int) */
+        guint16 fid;
 	guint16 lanman_cmd;
 	guchar *param_descrip;  /* Keep these descriptors around */
 	guchar *data_descrip;
@@ -269,6 +289,8 @@
 
 	/* track fid to fidstruct (filename/openframe/closeframe */
 	emem_tree_t *fid_tree;
+        /* We'll use a GSL list instead */
+        GSList  *GSL_fid_info;
 
 	/* track tid to fidstruct (sharename/shareframe/unshareframe */
 	emem_tree_t *tid_tree;
@@ -334,8 +356,13 @@
 	guint32 create_disposition;
 } smb_fid_saved_info_t;
 struct _smb_fid_into_t {
-	int opened_in;
-	int closed_in;
+        guint16 tid,fid;
+        /* The end_of_file will store the last registered offset or
+           the reported end_of_file from the SMB protocol */
+        gint64  end_of_file;
+        /* These two were int */
+	guint opened_in;
+	guint closed_in;
 	int type;
 	smb_fid_saved_info_t *fsi;
 };
