Index: configure.in
===================================================================
--- configure.in	(revision 165)
+++ configure.in	(working copy)
@@ -86,7 +86,7 @@ AM_CONDITIONAL(ENABLE_NAUTILUS_EXTENSION
 GLIB_REQUIRED=2.15.0
 NAUTILUS_REQUIRED=2.21.2
 
-PKG_CHECK_MODULES(GNOME_MOUNT, gconf-2.0 gnome-keyring-1 >= 0.4 dbus-glib-1 >= 0.31 hal-storage >= 0.5.8.1 gtk+-2.0 >= 2.8.0)
+PKG_CHECK_MODULES(GNOME_MOUNT, gconf-2.0 gnome-keyring-1 >= 0.4 dbus-glib-1 >= 0.31 hal-storage >= 0.5.8.1 gtk+-2.0 >= 2.8.0 gio-unix-2.0 >= 2.10)
 AC_SUBST(GNOME_MOUNT_CFLAGS)
 AC_SUBST(GNOME_MOUNT_LIBS)
 
Index: src/gnome-mount.c
===================================================================
--- src/gnome-mount.c	(revision 165)
+++ src/gnome-mount.c	(working copy)
@@ -37,6 +37,10 @@
 #include <libhal-storage.h>
 
 #include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <glib.h>
+#include <gtk/gtk.h>
 #include <gconf/gconf-client.h>
 #include <gdk/gdkx.h>
 #include "copy-paste/gnome-password-dialog.h"
@@ -78,8 +82,167 @@ static gboolean opt_block = FALSE;
 static gboolean opt_nodisplay = FALSE;
 static gboolean opt_verbose = FALSE;
 
+
+static const char *
+get_dev_file (LibHalVolume *volume, LibHalDrive *drive);
+
 #define DBUS_TIMEOUT G_MAXINT
 
+static GdkPixbuf *
+get_pixbuf_for_icon (GIcon *icon)
+{
+	GdkPixbuf  *pixbuf;
+	char *filename;
+
+	pixbuf = NULL;
+	if (G_IS_FILE_ICON (icon)) {
+		filename = g_file_get_path (g_file_icon_get_file (G_FILE_ICON (icon)));
+		if (filename) {
+			pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 24, 24, NULL);
+		}
+		g_free (filename);
+	} else if (G_IS_THEMED_ICON (icon)) {
+		const char * const *names;
+		char *icon_no_extension;
+		char *p;
+		
+		names = g_themed_icon_get_names (G_THEMED_ICON (icon));
+		
+		if (names != NULL && names[0] != NULL) {
+			icon_no_extension = g_strdup (names[0]);
+			p = strrchr (icon_no_extension, '.');
+			if (p &&
+			    (strcmp (p, ".png") == 0 ||
+			     strcmp (p, ".xpm") == 0 ||
+			     strcmp (p, ".svg") == 0)) {
+				*p = 0;
+			}
+			pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+							   icon_no_extension, 24, 0, NULL);
+			g_free (icon_no_extension);
+		}
+	}
+	return pixbuf;
+}
+
+enum 
+{
+	COL_ICON,
+	COL_NAME,
+	N_COL
+};
+	
+static GtkWidget *
+get_tree_view_for_busy_dev (const char *dev)
+{
+	char *commandline;
+	gchar **argv_spawn = NULL;
+	gint argc_spawn;
+	
+	int outputfd;
+	GIOChannel *io;
+	char *readline;
+	
+	gboolean exists;
+	char *file;
+	GIcon *icon;
+	GDesktopAppInfo *app;  
+	GtkTreeIter toplevel;
+	GdkPixbuf *pixbuf; 
+
+	GtkWidget *sw;
+	GtkTreeViewColumn *tvc;
+	GtkTreeModel *model;
+	GtkTreeView *view;
+	GtkCellRenderer *cell;
+	GtkTreeStore *store;
+	
+	commandline = g_strdup_printf("lsof -Fc %s", dev);
+	g_shell_parse_argv(commandline, &argc_spawn, &argv_spawn, NULL);
+	
+	g_free(commandline);
+
+	g_spawn_async_with_pipes(NULL, //working dir 
+				argv_spawn, //argv
+				NULL, //envp
+				G_SPAWN_SEARCH_PATH, //flags
+				NULL, //setup_func
+				NULL, //user_data
+				NULL, //child_pid
+				NULL, //input
+				&outputfd, //output
+				NULL, //error
+				NULL);
+
+	g_strfreev(argv_spawn);
+	io = g_io_channel_unix_new(outputfd);
+	
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	
+	view = GTK_TREE_VIEW (gtk_tree_view_new ());
+	gtk_tree_view_set_headers_visible (view, FALSE);
+	
+	tvc = gtk_tree_view_column_new ();
+	gtk_tree_view_append_column (view, tvc);
+	cell = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(tvc, cell, TRUE);
+	gtk_tree_view_column_add_attribute(tvc, cell, "pixbuf", COL_ICON);
+	
+	tvc = gtk_tree_view_column_new ();
+	gtk_tree_view_append_column (view, tvc);
+	cell = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(tvc, cell, TRUE);
+	gtk_tree_view_column_add_attribute(tvc, cell, "text", COL_NAME);
+	
+	store = gtk_tree_store_new(N_COL,
+				GDK_TYPE_PIXBUF,
+				G_TYPE_STRING);
+	
+	while (g_io_channel_read_line(io, &readline, NULL, NULL, NULL) == G_IO_STATUS_NORMAL)
+	{
+		if (readline && readline[0] != 'p')
+		{
+			++readline;
+			g_strchomp(readline);
+
+			// FIXME: need the actual data dir? should search in more paths? is there a xdg 
+			// thing for this?
+			file = g_strdup_printf("/usr/share/applications/%s.desktop", readline);
+
+			exists = g_file_test(file, G_FILE_TEST_EXISTS);
+
+			if (exists)
+			{
+				app = g_desktop_app_info_new_from_filename(file);
+				icon = g_app_info_get_icon(G_APP_INFO (app));
+		
+				pixbuf = get_pixbuf_for_icon (icon);
+			}
+
+			gtk_tree_store_append(store, &toplevel, NULL);
+			gtk_tree_store_set(store, &toplevel,
+				COL_ICON, (exists) ? pixbuf : NULL,
+				COL_NAME, (exists) ? g_app_info_get_name(G_APP_INFO (app)) : readline,
+				-1);
+
+			if (exists)
+			{
+				g_object_unref (pixbuf);
+				g_object_unref (app);
+			}
+			g_free (file);
+		}
+	
+	}
+	g_io_channel_unref(io);
+
+	gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
+	gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET(view));
+	
+	return sw;
+}
+
 static gboolean
 attempt_to_gain_privilege (const char *error_detail)
 {
@@ -231,12 +394,22 @@ show_error_dialog_eject (const char *udi
 		} else if (strcmp (error_name, "org.freedesktop.Hal.Device.Volume.Busy") == 0) {
 			/* TODO: figure out exactly which application and find localized name and icon via
 			 * desktop files */
+			g_print ("volume_name: %s; dev: %s; \n", volume_name, get_dev_file(volume, NULL));
 			gtk_message_dialog_format_secondary_text (
 				GTK_MESSAGE_DIALOG (w),
 				volume_name != NULL ? 
-				_("An application is preventing the volume '%s' from being ejected.") :
+				_("These applications are currently using '%s', close them before ejecting this volume.") :
 				_("An application is preventing the volume from being ejected."),
 				volume_name);
+
+			GtkWidget *sw;
+
+			sw = get_tree_view_for_busy_dev (get_dev_file (volume, NULL));
+
+			gtk_container_add (GTK_CONTAINER (GTK_DIALOG(w)->vbox), sw);
+			gtk_widget_show_all(sw);
+			gtk_window_set_resizable (GTK_WINDOW (w), TRUE);
+
 			/* TODO: could add 'Lazy Unmount' button */
 		} else if (strcmp (error_name, "org.freedesktop.Hal.Device.Volume.InvalidUnmountOption") == 0 ||
 			   strcmp (error_name, "org.freedesktop.Hal.Device.Volume.UnsupportedEjectOption") == 0 ||
@@ -249,6 +422,7 @@ show_error_dialog_eject (const char *udi
 				volume_name);
 		}
 
+                g_debug ("error was: %s; volume_name: %s;\n", error_name, volume_name);
 		gtk_dialog_add_buttons (GTK_DIALOG (w),
 					GTK_STOCK_OK,
 					GTK_RESPONSE_NONE,
