File gnome-vfs2-2.12.2-smb-method-fixes.patch of Package gnome-vfs2

This patch was prompted by https://bugzilla.novell.com/show_bug.cgi?id=222662 .

It contains the upstream differences in smb-method.c from version 2.12 to 2.18.
It also contains the old patches to smb-method.c, including:

gnome-vfs2-net-usershare.diff                      (Only the smb-method.c part)
gnome-vfs2-195269-smb-method-sniff-mime-type.diff  (Part of upstream)
gnome-vfs2-smb-bufsize.patch

An additional patch from Federico:

gnome-vfs2-222662-smb-uri-explicit-username.diff

An additional patch from Dan Winship:

gnome-vfs2-203737-smb-lock.diff

Plus changes to use the local user's login instead of "guest" or anonymous
logins, and avoid reusing the first-known-good login to a share if a login
isn't specified - again substituting the local user.

Index: gnome-vfs-2.24.0/libgnomevfs/gnome-vfs-handle.h
===================================================================
--- gnome-vfs-2.24.0.orig/libgnomevfs/gnome-vfs-handle.h
+++ gnome-vfs-2.24.0/libgnomevfs/gnome-vfs-handle.h
@@ -89,6 +89,7 @@ typedef struct GnomeVFSHandle GnomeVFSHa
  * @GNOME_VFS_OPEN_WRITE: Write access.
  * @GNOME_VFS_OPEN_RANDOM: Random access.
  * @GNOME_VFS_OPEN_TRUNCATE: Truncate file before accessing it, i.e. delete its contents.
+ * @GNOME_VFS_OPEN_LOCKED: Lock file when opening it
  *
  * Mode in which files are opened. If GNOME_VFS_OPEN_RANDOM is not used, the
  * file will be have to be accessed sequentially.
@@ -98,7 +99,8 @@ typedef enum {
         GNOME_VFS_OPEN_READ = 1 << 0,
         GNOME_VFS_OPEN_WRITE = 1 << 1,
         GNOME_VFS_OPEN_RANDOM = 1 << 2,
-	GNOME_VFS_OPEN_TRUNCATE = 1 << 3
+	GNOME_VFS_OPEN_TRUNCATE = 1 << 3,
+	GNOME_VFS_OPEN_LOCKED = 1 << 4
 } GnomeVFSOpenMode;
 
 /**
Index: gnome-vfs-2.24.0/modules/smb-method.c
===================================================================
--- gnome-vfs-2.24.0.orig/modules/smb-method.c
+++ gnome-vfs-2.24.0/modules/smb-method.c
@@ -37,6 +37,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include <gconf/gconf-client.h>
 #include <libgnomevfs/gnome-vfs.h>
@@ -90,6 +91,17 @@ static GHashTable *server_cache = NULL;
 
 static GHashTable *user_cache = NULL;
 
+/* smbcctx->readdir() can give us a struct smbc_dirent that identifies a
+ * printer, but you cannot perform a smbcctx->stat() on a path to know if that
+ * path refers to a printer.  So, when doing readdir(), we must remember the
+ * URIs of the printers we have found.  Later in our own do_get_file_info(), we
+ * will match the passed URI to this hash table and return a magic "it is a
+ * printer" datum if appropriate.
+ */
+static GHashTable *printer_hash = NULL;
+
+static FILE *debug_file;
+
 #define SMB_BLOCK_SIZE (32*1024)
 
 /* Reap unused server connections and user cache after 30 minutes */
@@ -105,6 +117,9 @@ static guint cache_reap_timeout = 0;
 /* Guest logins use: */
 #define GUEST_LOGIN "guest"
 
+/* Guest logins use: */
+#define GUEST_LOGIN "guest"
+
 /* 5 minutes before we re-read the workgroup cache again */
 #define WORKGROUP_CACHE_TIMEOUT (5*60)
 
@@ -149,32 +164,106 @@ typedef struct _SmbAuthContext {
 static void init_authentication (SmbAuthContext *actx, GnomeVFSURI *uri);
 static int  perform_authentication (SmbAuthContext *actx);
 
+static gboolean is_printer (GnomeVFSURI *uri);
+
 static SmbAuthContext *current_auth_context = NULL;
 
 static void auth_callback (const char *server_name, const char *share_name,
 		     	   char *domain, int domainmaxlen,
 		     	   char *username, int unmaxlen,
 		     	   char *password, int pwmaxlen);
+
+static void debug_print (const char *format, ...);
+static void debug_indent (int amount);
+static int debug_indentation;
 		     	   
-#if 0
+#if 1
 #define DEBUG_SMB_ENABLE
 #define DEBUG_SMB_LOCKS
 #endif
 
 #ifdef DEBUG_SMB_ENABLE
-#define DEBUG_SMB(x) g_print x
+#define DEBUG_SMB(x) debug_print x
+#define DEBUG_IN() debug_print ("%s() {\n", G_STRFUNC); debug_indent(1)
+#define DEBUG_OUT() debug_indent(-1); debug_print ("} %s()\n", G_STRFUNC)
 #else
-#define DEBUG_SMB(x) 
+#define DEBUG_SMB(x)
+#define DEBUG_IN()
+#define DEBUG_OUT()
 #endif
 
 #ifdef DEBUG_SMB_LOCKS
-#define LOCK_SMB() 	{g_mutex_lock (smb_lock); g_print ("LOCK %s\n", G_STRFUNC);}
-#define UNLOCK_SMB() 	{g_print ("UNLOCK %s\n", G_STRFUNC); g_mutex_unlock (smb_lock);}
+#define LOCK_SMB() 	{g_mutex_lock (smb_lock); debug_print ("LOCK %s\n", G_STRFUNC);}
+#define UNLOCK_SMB() 	{debug_print ("UNLOCK %s\n", G_STRFUNC); g_mutex_unlock (smb_lock);}
 #else
 #define LOCK_SMB() 	g_mutex_lock (smb_lock)
 #define UNLOCK_SMB() 	g_mutex_unlock (smb_lock)
 #endif
 
+static void
+debug_print (const char *format, ...)
+{
+	va_list args;
+	char *str;
+	int i;
+
+	if (!debug_file)
+		return;
+
+	va_start (args, format);
+	str = g_strdup_vprintf (format, args);
+	va_end (args);
+
+	fprintf (debug_file, "%p: ", g_thread_self ());
+
+	for (i = 0; i < debug_indentation * 4; i++)
+		fputc (' ', debug_file);
+
+	fputs (str, debug_file);
+	g_free (str);
+	fflush (debug_file);
+}
+
+static void
+debug_indent (int amount)
+{
+	debug_indentation += amount;
+	if (debug_indentation < 0)
+		g_error ("You fucked up your indentation");
+}
+
+static void
+DEBUG_DUMP_AUTH_CONTEXT (SmbAuthContext *actx)
+{
+	char *str_uri;
+
+	if (actx->uri)
+		str_uri = gnome_vfs_uri_to_string (actx->uri, 0);
+	else
+		str_uri = g_strdup ("(null)");
+
+	debug_print ("AUTH CONTEXT %p {\n", actx);
+	debug_print ("             uri: %s\n", str_uri);
+	debug_print ("      vfs_result: %d\n", (int) actx->res);
+	debug_print ("          passes: %d\n", actx->passes);
+	debug_print ("           state: %x\n", actx->state);
+	debug_print ("       save_auth: %d\n", actx->save_auth);
+	debug_print ("         keyring: %s\n", actx->keyring);
+	debug_print ("     auth_called: %d\n", actx->auth_called);
+	debug_print ("      for_server: %s\n", actx->for_server);
+	debug_print ("       for_share: %s\n", actx->for_share);
+	debug_print ("        use_user: %s\n", actx->use_user);
+	debug_print ("      use_domain: %s\n", actx->use_domain);
+	debug_print ("    use_password: %s\n", actx->use_password);
+	debug_print ("     cache_added: %d\n", actx->cache_added);
+	debug_print ("      cache_used: %d\n", actx->cache_used);
+	debug_print ("    prompt_flags: %x\n", actx->prompt_flags);
+	debug_print ("}\n");
+
+	g_free (str_uri);
+}
+
+
 static gchar*
 string_dup_nzero (const gchar *s)
 {
@@ -279,6 +368,22 @@ user_free (SmbCachedUser *user)
         g_free (user);
 }
 
+const gchar *
+get_unix_username (void)
+{
+	const gchar *unix_username;
+	const gchar *backslash;
+
+	/* Strip the domainname if present in "domainname\username" form. */
+
+	unix_username = g_get_user_name ();
+	backslash = strchr (unix_username, '\\');
+	if (backslash)
+		unix_username = (char *) backslash + 1;
+
+	return unix_username;
+}
+
 static void
 add_old_servers (gpointer key,
 		gpointer value,
@@ -319,6 +424,7 @@ cache_reap_cb (void)
          * sure when we'll be called */
         if (!g_mutex_trylock (smb_lock))
                 return TRUE;
+	DEBUG_IN ();
         DEBUG_SMB(("LOCK %s\n", G_STRFUNC));
 
 	size = g_hash_table_size (server_cache);
@@ -342,6 +448,7 @@ cache_reap_cb (void)
         if (!ret)
                 cache_reap_timeout = 0;
 
+	DEBUG_OUT ();
         UNLOCK_SMB();
 
         return ret;        
@@ -363,6 +470,7 @@ add_cached_server (SMBCCTX *context, SMB
 {
 	SmbServerCacheEntry *entry = NULL;
 
+	DEBUG_IN ();
 	DEBUG_SMB(("[auth] adding cached server: server: %s, share: %s, domain: %s, user: %s\n",
 		   server_name ? server_name : "", 
 		   share_name ? share_name : "",
@@ -383,6 +491,8 @@ add_cached_server (SMBCCTX *context, SMB
 
 	g_hash_table_insert (server_cache, entry, entry);
 	current_auth_context->cache_added = TRUE;
+
+	DEBUG_OUT ();
 	return 0;
 }
 
@@ -393,6 +503,7 @@ find_cached_server (const char *server_n
 	SmbServerCacheEntry entry;
 	SmbServerCacheEntry *res;
 
+	DEBUG_IN ();
 	DEBUG_SMB(("find_cached_server: server: %s, share: %s, domain: %s, user: %s\n", 
 		   server_name ? server_name : "", 
 		   share_name ? share_name : "",
@@ -409,9 +520,13 @@ find_cached_server (const char *server_n
 
 	if (res != NULL) {
 		res->last_time = time (NULL);
+ 		DEBUG_OUT ();
+ 		DEBUG_SMB (("found server %p\n", res->server));
 		return res->server;
 	} 
 
+ 	DEBUG_SMB (("found nothing; returning NULL\n"));
+ 	DEBUG_OUT ();
 	return NULL;
 }
 
@@ -421,6 +536,8 @@ get_cached_server (SMBCCTX * context,
 		   const char *domain, const char *username)
 {
 	SMBCSRV *srv;
+
+	DEBUG_IN ();
 	
 	srv = find_cached_server (server_name, share_name, domain, username);
 	if (srv != NULL) {
@@ -430,8 +547,12 @@ get_cached_server (SMBCCTX * context,
 			   domain ? domain : "", 
 			   username ? username : ""));
 		current_auth_context->cache_used = TRUE;
+
+		DEBUG_OUT ();
 		return srv;
 	}
+
+	DEBUG_OUT ();
 	return NULL;
 }
 
@@ -454,9 +575,13 @@ remove_server  (gpointer key,
 static int remove_cached_server(SMBCCTX * context, SMBCSRV * server)
 {
 	int removed;
+
+	DEBUG_IN ();
 	
 	removed = g_hash_table_foreach_remove (server_cache, remove_server, server);
 
+	DEBUG_OUT ();
+
 	/* return 1 if failed */
 	return removed == 0;
 }
@@ -483,6 +608,8 @@ purge_cached(SMBCCTX * context)
 	gboolean could_not_purge_all;
 	int i;
 
+	DEBUG_IN ();
+
 	size = g_hash_table_size (server_cache);
 	servers = g_ptr_array_sized_new (size);
 
@@ -499,6 +626,10 @@ purge_cached(SMBCCTX * context)
 	}
 
 	g_ptr_array_free (servers, TRUE);
+
+	DEBUG_SMB (("returning could_not_purge_all = %d\n", could_not_purge_all));
+
+	DEBUG_OUT ();
 	
 	return could_not_purge_all;
 }
@@ -519,6 +650,8 @@ update_workgroup_cache (void)
 	SMBCFILE *dir = NULL;
 	time_t t;
 	struct smbc_dirent *dirent;
+
+	DEBUG_IN ();
 	
 	t = time (NULL);
 
@@ -526,6 +659,7 @@ update_workgroup_cache (void)
 	    workgroups_timestamp < t &&
 	    t < workgroups_timestamp + WORKGROUP_CACHE_TIMEOUT) {
 		/* Up to date */
+		DEBUG_OUT ();
 		return;
 	}
 	workgroups_timestamp = t;
@@ -537,15 +671,20 @@ update_workgroup_cache (void)
 	LOCK_SMB();
 	
 	init_authentication (&actx, NULL);
+	DEBUG_DUMP_AUTH_CONTEXT (&actx);
 	
 	/* Important: perform_authentication leaves and re-enters the lock! */
 	while (perform_authentication (&actx) > 0) {
+		DEBUG_SMB (("calling ctx->opendir (\"smb://\")\n"));
 		dir = smb_context->opendir (smb_context, "smb://");
 		actx.res = (dir != NULL) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB (("it returned %d\n", (int) actx.res));
 	}
 
 	if (dir != NULL) {
+		DEBUG_SMB (("calling ctx->readdir() in a loop\n"));
 		while ((dirent = smb_context->readdir (smb_context, dir)) != NULL) {
+			DEBUG_SMB (("got dirent '%s' of type %d\n", dirent->name, dirent->smbc_type));
 			if (dirent->smbc_type == SMBC_WORKGROUP &&
 			    dirent->name != NULL &&
 			    strlen (dirent->name) > 0) {
@@ -557,9 +696,13 @@ update_workgroup_cache (void)
 			}
 		}
 
+		DEBUG_SMB (("calling ctx->closedir()\n"));
 		smb_context->closedir (smb_context, dir);
 	}
+	DEBUG_DUMP_AUTH_CONTEXT (&actx);
 	UNLOCK_SMB();
+
+	DEBUG_OUT ();
 }
 
 static SmbUriType
@@ -568,6 +711,9 @@ smb_uri_type (GnomeVFSURI *uri)
 	GnomeVFSToplevelURI *toplevel;
 	char *first_slash;
 	char *host_name;
+ 	SmbUriType type;
+ 
+ 	DEBUG_IN ();
 
 	toplevel = (GnomeVFSToplevelURI *)uri;
 
@@ -576,12 +722,16 @@ smb_uri_type (GnomeVFSURI *uri)
 		if (uri->text == NULL ||
 		    uri->text[0] == 0 ||
 		    strcmp (uri->text, "/") == 0) {
-			return SMB_URI_WHOLE_NETWORK;
+			type = SMB_URI_WHOLE_NETWORK;
+			goto out;
 		}
 		if (strchr (uri->text + 1, '/')) {
-			return SMB_URI_ERROR;
+			type = SMB_URI_ERROR;
+			goto out;
 		}
-		return SMB_URI_WORKGROUP_LINK;
+
+		type = SMB_URI_WORKGROUP_LINK;
+		goto out;
 	}
 	if (uri->text == NULL ||
 	    uri->text[0] == 0 ||
@@ -596,10 +746,12 @@ smb_uri_type (GnomeVFSURI *uri)
 					DEFAULT_WORKGROUP_NAME) ||
 		    g_hash_table_lookup (workgroups, host_name)) {
 			g_free (host_name);
-			return SMB_URI_WORKGROUP;
+ 			type = SMB_URI_WORKGROUP;
+ 			goto out;
 		} else {
 			g_free (host_name);
-			return SMB_URI_SERVER;
+ 			type = SMB_URI_SERVER;
+ 			goto out;
 		}
 	}
 	first_slash = strchr (uri->text + 1, '/');
@@ -620,8 +772,14 @@ smb_uri_type (GnomeVFSURI *uri)
 			return SMB_URI_SHARE;
 		}
 	}
-	
-	return SMB_URI_SHARE_FILE;
+
+ 	type = SMB_URI_SHARE_FILE;
+ 
+out:
+ 
+ 	DEBUG_OUT ();
+ 
+ 	return type;	
 }
 
 
@@ -678,42 +836,56 @@ try_init (void)
 	g_free (path);
 
 	smb_context = smbc_new_context ();
-	if (smb_context != NULL) {
-		smb_context->debug = 0;
-		smb_context->callbacks.auth_fn 		    = auth_callback;
-		smb_context->callbacks.add_cached_srv_fn    = add_cached_server;
-		smb_context->callbacks.get_cached_srv_fn    = get_cached_server;
-		smb_context->callbacks.remove_cached_srv_fn = remove_cached_server;
-		smb_context->callbacks.purge_cached_fn      = purge_cached;
-
-		gclient = gconf_client_get_default ();
-		if (gclient) {
-			workgroup = gconf_client_get_string (gclient, 
-					PATH_GCONF_GNOME_VFS_SMB_WORKGROUP, NULL);
-
-			/* libsmbclient frees this on it's own, so make sure 
-			 * to use simple system malloc */
-			if (workgroup && workgroup[0])
-				smb_context->workgroup = strdup (workgroup);
-			
-			g_free (workgroup);
-			g_object_unref (gclient);
-		}
+	if (smb_context == NULL)
+		goto out;
 
-		if (!smbc_init_context (smb_context)) {
-			smbc_free_context (smb_context, FALSE);
-			smb_context = NULL;
-		}
+	smb_context->debug = 0;
+	smb_context->callbacks.auth_fn 		    = auth_callback;
+	smb_context->callbacks.add_cached_srv_fn    = add_cached_server;
+	smb_context->callbacks.get_cached_srv_fn    = get_cached_server;
+	smb_context->callbacks.remove_cached_srv_fn = remove_cached_server;
+	smb_context->callbacks.purge_cached_fn      = purge_cached;
+
+	DEBUG_SMB (("created the SMBCCTX; it has smbcctx->workgroup=\"%s\"\n",
+		    smb_context->workgroup ? smb_context->workgroup : "(null)"));
+	
+	gclient = gconf_client_get_default ();
+	if (gclient) {
+		workgroup = gconf_client_get_string (gclient, 
+						     PATH_GCONF_GNOME_VFS_SMB_WORKGROUP, NULL);
+		
+		/* libsmbclient frees this on it's own, so make sure 
+		 * to use simple system malloc */
+		if (workgroup && workgroup[0])
+			smb_context->workgroup = strdup (workgroup);
+		
+		g_free (workgroup);
+		g_object_unref (gclient);
+	}
+	
+	DEBUG_SMB (("after reading from gconf, we have smbcctx->workgroup=\"%s\"\n",
+		    smb_context->workgroup ? smb_context->workgroup : "(null)"));
 
+	if (!smbc_init_context (smb_context)) {
+		smbc_free_context (smb_context, FALSE);
+		smb_context = NULL;
+		DEBUG_SMB (("smbc_init_context() failed!\n"));
+		goto out;
+	}
+
+	DEBUG_SMB (("called smbc_init_context(); we have smbcctx->workgroup=\"%s\"\n",
+		    smb_context->workgroup ? smb_context->workgroup : "(null)"));
+	
 #if defined(HAVE_SAMBA_FLAGS) 
 #if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
-		smb_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS;
+	smb_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS;
 #endif
-#if defined(SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON)
-		smb_context->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON;
+#  if 0
+#    if defined(SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON)
+   	smb_context->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON;
+#    endif
+#  endif
 #endif
-#endif		
-	}
 
 	server_cache = g_hash_table_new_full (server_hash, server_equal,
 					      (GDestroyNotify)server_free, NULL);
@@ -721,7 +893,10 @@ try_init (void)
 					    g_free, NULL);
 	user_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
                                             g_free, (GDestroyNotify)user_free);
-	
+	printer_hash = g_hash_table_new_full (gnome_vfs_uri_hash, gnome_vfs_uri_hequal,
+					      (GDestroyNotify) gnome_vfs_uri_unref, NULL);
+
+ out:
 	UNLOCK_SMB();
 
 	if (smb_context == NULL) {
@@ -762,7 +937,9 @@ update_user_cache (SmbAuthContext *actx,
 {
         SmbCachedUser *user;
         gchar *key;
-        
+
+	DEBUG_IN ();
+
         g_return_if_fail (actx->for_server != NULL);
         
         key = g_strdup_printf ("%s/%s", actx->for_server, with_share ? actx->for_share : "");
@@ -785,6 +962,8 @@ update_user_cache (SmbAuthContext *actx,
         user->username = string_realloc (user->username, actx->use_user);
         user->password = string_realloc (user->password, actx->use_password);
         user->stamp = time (NULL);
+
+	DEBUG_OUT ();
 }
 
 static gboolean
@@ -792,9 +971,13 @@ lookup_user_cache (SmbAuthContext *actx,
 {
         SmbCachedUser *user;
         gchar *key;
-       
+	gboolean retval;
+
         g_return_val_if_fail (actx->for_server != NULL, FALSE);
        
+	DEBUG_IN ();
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
+       
         key = g_strdup_printf ("%s/%s", actx->for_server, with_share ? actx->for_share : "");
         user = (SmbCachedUser*)g_hash_table_lookup (user_cache, key);
         g_free (key);
@@ -802,12 +985,17 @@ lookup_user_cache (SmbAuthContext *actx,
         if (user) {
                 /* If we already have a user name or domain double check that... */
 		if (!(actx->prompt_flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME) &&
-		    !string_compare(user->username, actx->use_user))
-			return FALSE;
+		    !string_compare(user->username, actx->use_user)) {
+			retval = FALSE;
+			goto out;
+		}
+		
 		if (!(actx->prompt_flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN) &&
-		    !string_compare(user->domain, actx->use_domain))
-			return FALSE;
-
+		    !string_compare(user->domain, actx->use_domain)) {
+			retval = FALSE;
+			goto out;
+		}
+		
                 actx->use_user = string_realloc (actx->use_user, user->username);
                 actx->use_domain = string_realloc (actx->use_domain, user->domain);
                 actx->use_password = string_realloc (actx->use_password, user->password);
@@ -815,12 +1003,40 @@ lookup_user_cache (SmbAuthContext *actx,
 			   actx->use_user ? actx->use_user : "",
 			   actx->use_domain ? actx->use_domain : "",
 			   actx->use_password ? actx->use_password : ""));
-                return TRUE;
+		retval = TRUE;
+		goto out;
         }
-        
-        return FALSE;
+
+	retval = FALSE;
+
+out:
+ 
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
+ 	DEBUG_OUT ();
+ 	return retval;
 }      
 
+static void
+update_kerberos_settings_for_auth (SmbAuthContext *actx)
+{
+	if (!actx)
+		return;
+
+#if defined(HAVE_SAMBA_FLAGS) 
+# if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
+
+	/* Don't use local user's kerberos tickets if we are authenticating a non-local user. */
+
+	if (string_compare (actx->use_user, get_unix_username ()))
+		smb_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS;
+	else
+		smb_context->flags &= ~(SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS);
+
+# endif
+#endif
+}
+
+
 static gboolean
 initial_authentication (SmbAuthContext *actx)
 {
@@ -832,8 +1048,12 @@ initial_authentication (SmbAuthContext *
         gboolean found_user = FALSE;
 	char *tmp;
 
+	DEBUG_IN ();
+	
 	DEBUG_SMB(("[auth] Initial authentication lookups\n"));
 
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
+
 	toplevel_uri =	(GnomeVFSToplevelURI*)actx->uri;
 	actx->prompt_flags = GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME |
 		    	     GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN;
@@ -870,6 +1090,14 @@ initial_authentication (SmbAuthContext *
 		}
 	} 
 
+ 	if (actx->use_user == NULL) {
+ 		actx->use_user = g_strdup (get_unix_username ());
+#if 0
+ 		actx->preset_user = TRUE;
+#endif
+ 		actx->prompt_flags &= ~GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME;
+ 	}
+
         if (lookup_user_cache (actx, TRUE) ||
             lookup_user_cache (actx, FALSE))
                 found_user = TRUE;
@@ -882,6 +1110,7 @@ initial_authentication (SmbAuthContext *
         	server_lookup.domain = (char*)actx->use_domain;
         		
         	server = g_hash_table_lookup (server_cache, &server_lookup);
+#if 0
         	if (server == NULL) {
                  
                         /* If a blank user, try looking up 'guest' */
@@ -891,6 +1120,7 @@ initial_authentication (SmbAuthContext *
                                 server = g_hash_table_lookup (server_cache, &server_lookup);
                         }
                 }
+#endif
                 
                 /* Server is in cache already */
                 if (server != NULL) {
@@ -898,9 +1128,16 @@ initial_authentication (SmbAuthContext *
 				   actx->use_user ? actx->use_user : "", 
 				   actx->use_domain ? actx->use_domain : ""));
                         found_user = TRUE;
-        	}
+        	} else {
+ 			/* We have a connection to the server, but not as the user specified. */
+ 			found_user = FALSE;
+ 		}
         }
 
+ 	update_kerberos_settings_for_auth (actx);
+ 
+ 	DEBUG_OUT ();
+
 	return found_user;
 }
 
@@ -917,6 +1154,9 @@ prefill_authentication (SmbAuthContext *
 	g_return_val_if_fail (actx != NULL, FALSE);
 	g_return_val_if_fail (actx->for_server != NULL, FALSE);	
 
+ 	DEBUG_IN ();
+ 	DEBUG_DUMP_AUTH_CONTEXT (actx);
+
 	memset (&in_args, 0, sizeof (in_args));
 	in_args.uri = get_auth_display_uri (actx, FALSE);
 	in_args.protocol = "smb";
@@ -936,6 +1176,8 @@ prefill_authentication (SmbAuthContext *
 		              &in_args, sizeof (in_args),
 		              &out_args, sizeof (out_args));
 
+ 	DEBUG_SMB(("[auth] vfs module callback for FILL_AUTHENTICATION returned invoked=%d\n", invoked));
+
         g_free (in_args.uri);
                
         /* If that didn't work then try without the share name */
@@ -988,6 +1230,9 @@ prefill_authentication (SmbAuthContext *
 	g_free (out_args.domain);
 	g_free (out_args.password);
 
+ 	DEBUG_DUMP_AUTH_CONTEXT (actx);
+ 	DEBUG_OUT ();
+ 
 	return filled;
 }
 
@@ -1003,6 +1248,9 @@ prompt_authentication (SmbAuthContext *a
 	
 	g_return_val_if_fail (actx != NULL, FALSE);
 	g_return_val_if_fail (actx->for_server != NULL, FALSE);
+
+	DEBUG_IN ();
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
 	
 	memset (&in_args, 0, sizeof (in_args));
 	
@@ -1020,17 +1268,32 @@ prompt_authentication (SmbAuthContext *a
 	in_args.port = actx->uri ? ((GnomeVFSToplevelURI*)actx->uri)->host_port : 0;
 
 	in_args.default_user = actx->use_user;
+#if 0
 	if (string_compare (in_args.default_user, GUEST_LOGIN))
 		in_args.default_user = NULL;
-	if (!in_args.default_user)
-		in_args.default_user = (char*)g_get_user_name ();
+#endif
+	if (!in_args.default_user) {
+		/* If we are logged into an Active Directory domain,
+		 * smb_context->workgroup will already have given us the name of the
+		 * domain.  However, g_get_user_name() will give us
+		 * "DOMAINNAME\username".  We need to remove the "DOMAINNAME\" prefix.
+		 */
+
+		in_args.default_user = (gchar *) get_unix_username ();
+	}
 	
 	in_args.default_domain = actx->use_domain ? actx->use_domain : smb_context->workgroup;
 	
 	memset (&out_args, 0, sizeof (out_args));
 
-	DEBUG_SMB(("[auth] Prompting credentials for: %s\n", 
-		   in_args.uri ? in_args.uri : ""));
+	DEBUG_SMB (("[auth] Prompting credentials for: uri=%s, server=%s, object=%s, username=%s, domain=%s, default_user=%s, default_domain=%s\n",
+		    in_args.uri,
+		    in_args.server,
+		    in_args.object,
+		    in_args.username,
+		    in_args.domain,
+		    in_args.default_user,
+		    in_args.default_domain));
 
 	invoked = gnome_vfs_module_callback_invoke
 		(GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION,
@@ -1051,10 +1314,11 @@ prompt_authentication (SmbAuthContext *a
 		g_free (actx->keyring);
 		actx->save_auth = out_args.save_password;
 		actx->keyring = actx->save_auth && out_args.keyring ? g_strdup (out_args.keyring) : NULL;
-		DEBUG_SMB(("[auth] Prompted credentials: %s@%s:%s\n", 
+		DEBUG_SMB(("[auth] Prompted credentials: %s@%s:%s keyring=%s\n", 
 			    actx->use_user ? actx->use_user : "", 
 			    actx->use_domain ? actx->use_domain : "",
-			    actx->use_password ? actx->use_password : ""));
+			    actx->use_password ? actx->use_password : "",
+			    actx->keyring ? actx->keyring : ""));
 	} 
 
 	*cancelled = out_args.abort_auth;
@@ -1068,6 +1332,9 @@ prompt_authentication (SmbAuthContext *a
 
 	g_free (in_args.uri);
 
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
+	DEBUG_OUT ();
+
 	return invoked && !*cancelled;
 }
 
@@ -1078,14 +1345,19 @@ save_authentication (SmbAuthContext *act
 	GnomeVFSModuleCallbackSaveAuthenticationOut out_args;
 	gboolean invoked;
 
+	DEBUG_IN ();
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
+
         /* Add to the user cache both with and without shares */
         if (actx->for_server) {
                 update_user_cache (actx, TRUE);
                 update_user_cache (actx, FALSE);
         }
 
-        if (!actx->save_auth)
+        if (!actx->save_auth) {
+		DEBUG_OUT ();
                 return;
+	}
       
         /* Save with the domain name */
 	memset (&in_args, 0, sizeof (in_args));
@@ -1114,6 +1386,8 @@ save_authentication (SmbAuthContext *act
 		                &in_args, sizeof (in_args),
 		                &out_args, sizeof (out_args));
         
+ 	DEBUG_SMB(("[auth] vfs module callback for SAVE_AUTHENTICATION returned invoked=%d\n", invoked));
+
         g_free (in_args.uri);
               
         /* Save without the domain name */
@@ -1142,15 +1416,19 @@ save_authentication (SmbAuthContext *act
                                 (GNOME_VFS_MODULE_CALLBACK_SAVE_AUTHENTICATION,
                                 &in_args, sizeof (in_args),
                                 &out_args, sizeof (out_args));
+
+ 	DEBUG_SMB(("[auth] vfs module callback for SAVE_AUTHENTICATION returned invoked=%d\n", invoked));
         
 	g_free (in_args.uri);
+
+	DEBUG_OUT ();
 }
 	
 static void
 cleanup_authentication (SmbAuthContext *actx)
 {
 	/* IMPORTANT: We are IN the lock at this point */
-	
+	DEBUG_IN ();
 	DEBUG_SMB(("[auth] Cleaning up Authentication\n"));
 	g_return_if_fail (actx != NULL);
 	
@@ -1174,6 +1452,9 @@ cleanup_authentication (SmbAuthContext *
 	
 	g_return_if_fail (current_auth_context == actx);
 	current_auth_context = NULL;
+
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
+	DEBUG_OUT ();
 }
 
 /* 
@@ -1218,9 +1499,12 @@ perform_authentication (SmbAuthContext *
 {
 	gboolean cont, auth_failed = FALSE, auth_cancelled = FALSE;
 	int ret = -1;
+
+	DEBUG_IN ();
 	
 	/* IMPORTANT: We are IN the lock at this point */
 	DEBUG_SMB(("[auth] perform_authentication called.\n"));
+	DEBUG_DUMP_AUTH_CONTEXT (actx);
 	
 	switch (actx->res) {
 	case GNOME_VFS_OK:
@@ -1236,8 +1520,9 @@ perform_authentication (SmbAuthContext *
 	
 	/* Other errors mean we're done */
 	default:
-		DEBUG_SMB(("[auth] Non-authentication error. Leaving auth loop.\n"));
+		DEBUG_SMB(("[auth] Non-authentication VFS error %d. Leaving auth loop.\n", (int) actx->res));
 		cleanup_authentication (actx);
+		DEBUG_OUT ();
 		return -1;
 	}
 	
@@ -1278,7 +1563,7 @@ perform_authentication (SmbAuthContext *
 
 		/* A failed authentication */
 		} else if (actx->auth_called) {
-			
+
 			/* We need a server to perform any authentication */
 			g_return_val_if_fail (actx->for_server != NULL, GNOME_VFS_ERROR_INTERNAL);
 			
@@ -1290,10 +1575,14 @@ perform_authentication (SmbAuthContext *
 			
 				/* Do we have gnome-keyring credentials for this? */
 				if (!(actx->state & SMB_AUTH_STATE_PREFILLED)) {
+					DEBUG_SMB (("[auth] failed authentication; will prefill from the vfs callback\n"));
 					actx->state |= SMB_AUTH_STATE_PREFILLED;
 					cont = prefill_authentication (actx);
-				}
+				} else {
+ 					DEBUG_SMB (("[auth] failed authentication; will prompt the user for authentication\n"));
+  				}
 
+#if 0
 				/* Then we try a guest credentials... */
 				if (!cont && !actx->preset_user && !(actx->state & SMB_AUTH_STATE_GUEST)) {
 					g_free (actx->use_user);
@@ -1305,6 +1594,7 @@ perform_authentication (SmbAuthContext *
 					actx->state |= SMB_AUTH_STATE_GUEST;
 					cont = TRUE;
 				}
+#endif
 
 				/* And as a last step, prompt */
 				if (!cont)
@@ -1315,10 +1605,13 @@ perform_authentication (SmbAuthContext *
 			/* Claim the global context back */
 			g_return_val_if_fail (current_auth_context == NULL, GNOME_VFS_ERROR_INTERNAL);
 			current_auth_context = actx;
-			
-			if (cont)
+
+			update_kerberos_settings_for_auth (actx);
+
+			if (cont) {
+				DEBUG_SMB(("[auth] prefill or prompt returned 1\n"));
 				ret = 1;
-			else {
+			} else {
 				ret = -1;
 
 				if (auth_cancelled) {
@@ -1333,12 +1626,15 @@ perform_authentication (SmbAuthContext *
 					
 		/* Weird, don't want authentication, but failed */
 		} else {
+			DEBUG_SMB(("[auth] don't want authentication, but failed\n"));
 			ret = -1;
 		}
 	}
 
 	if (ret <= 0)
 		cleanup_authentication (actx);
+
+	DEBUG_OUT ();
 	return ret;
 
 	/* IMPORTANT: We need to still be in the lock when returning from this func */
@@ -1353,18 +1649,23 @@ auth_callback (const char *server_name,
 	/* IMPORTANT: We are IN the global lock */
 	SmbAuthContext *actx;
 	SMBCSRV *server;
-	
-	DEBUG_SMB (("[auth] auth_callback called: server: %s share: %s\n",
-		    server_name ? server_name : "", 
-		    share_name ? share_name : ""));
+
+	DEBUG_IN ();
+
+ 	DEBUG_SMB (("[auth] auth_callback called: server=%s, share=%s, domain_out=%s, username_out=%s, password_out=%s\n",
+ 		    server_name, share_name, domain_out, username_out, password_out));
 
 	g_return_if_fail (current_auth_context != NULL);
 	actx = current_auth_context;
+
+ 	DEBUG_DUMP_AUTH_CONTEXT (actx);
 	
 	/* We never authenticate for the toplevel (enumerating workgroups) */
-	if (!server_name || !server_name[0])
+	if (!server_name || !server_name[0]) {
+		DEBUG_OUT ();
 		return;
-
+	}
+	
 	actx->auth_called = TRUE;	
 		
 	/* The authentication location */
@@ -1374,9 +1675,13 @@ auth_callback (const char *server_name,
 	actx->for_share = string_dup_nzero (share_name);
 
 	/* The first pass, try the cache, fill in anything we know */
-	if (actx->passes == 1)
+	if (actx->passes == 1) {
+		DEBUG_SMB(("[auth] first pass; call initial_authentication()\n"));
 		initial_authentication (actx);
+	}
 	
+	update_kerberos_settings_for_auth (actx);
+
 	/* If we have a valid user then go for it */
 	if (actx->use_user) {
 		strncpy (username_out, actx->use_user, unmaxlen);
@@ -1411,15 +1716,30 @@ auth_callback (const char *server_name,
 	 * this doesn't make much sense, but such is life with libsmbclient.
 	 */
 	if ((actx->state & SMB_AUTH_STATE_PROMPTED) && actx->res != GNOME_VFS_OK) {
+		DEBUG_SMB(("[auth] we had prompted already but auth failed.  Calling find_cached_server() again\n"));
 		server = find_cached_server (server_name, share_name, domain_out, username_out);
 		if (server) {
 			DEBUG_SMB (("[auth] auth_callback. Remove the wrong server entry from server_cache.\n"));
 			g_hash_table_foreach_remove (server_cache, remove_server, server);
 		}
 	}
+
+	DEBUG_OUT ();
 }
 
 static char *
+get_printer_data (const char *display_name, const char *path)
+{
+	return g_strdup_printf ("[Desktop Entry]\n"
+			"Encoding=UTF-8\n"
+			"Name=%s\n"
+			"Type=Application\n"
+			"Exec=gnome-cups-add --printer=%s\n"
+			"Icon=printer-remote\n", /* per the freedesktop.org icon naming spec */
+			display_name, path);
+}
+                                                                                
+static char *
 get_workgroup_data (const char *display_name, const char *name)
 {
 	return g_strdup_printf ("[Desktop Entry]\n"
@@ -1466,6 +1786,21 @@ typedef struct {
 	GnomeVFSFileOffset file_size;
 } FileHandle;
 
+/* Takes ownership of desktop_file_contents */
+static FileHandle *
+file_handle_new_from_desktop_file_contents (char *desktop_file_contents)
+{
+	FileHandle *handle;
+
+	handle = g_new (FileHandle, 1);
+	handle->is_data = TRUE;
+	handle->offset = 0;
+	handle->file_data = desktop_file_contents;
+	handle->file_size = strlen (handle->file_data);
+
+	return handle;
+}
+
 static GnomeVFSResult
 do_open (GnomeVFSMethod *method,
 	 GnomeVFSMethodHandle **method_handle,
@@ -1479,59 +1814,84 @@ do_open (GnomeVFSMethod *method,
 	int type;
 	mode_t unix_mode;
 	SMBCFILE *file = NULL;
-	
+	GnomeVFSResult result;
+
+	DEBUG_IN ();
 	DEBUG_SMB(("do_open() %s mode %d\n",
 				gnome_vfs_uri_to_string (uri, 0), mode));
 
 	type = smb_uri_type (uri);
 
 	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
+
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+
+	if (is_printer (uri)) {
+		if (mode & GNOME_VFS_OPEN_WRITE) {
+			result = GNOME_VFS_ERROR_READ_ONLY;
+			goto out;
+		}
+
+		unescaped_name = get_base_from_uri (uri);
+		name = gnome_vfs_uri_extract_short_path_name (uri);
+
+		handle = file_handle_new_from_desktop_file_contents (get_printer_data (unescaped_name, path));
+		*method_handle = (GnomeVFSMethodHandle *)handle;
+
+		g_free (unescaped_name);
+		g_free (name);
+
+		result = GNOME_VFS_OK;
+		goto out;
+	}
 	
 	if (type == SMB_URI_WHOLE_NETWORK ||
 	    type == SMB_URI_WORKGROUP ||
 	    type == SMB_URI_SERVER ||
 	    type == SMB_URI_SHARE) {
-		return GNOME_VFS_ERROR_IS_DIRECTORY;
+		result = GNOME_VFS_ERROR_IS_DIRECTORY;
+		goto out;
 	}
 
 	if (type == SMB_URI_WORKGROUP_LINK) {
 		if (mode & GNOME_VFS_OPEN_WRITE) {
-			return GNOME_VFS_ERROR_READ_ONLY;
+			result = GNOME_VFS_ERROR_READ_ONLY;
+			goto out;
 		}
-		handle = g_new (FileHandle, 1);
-		handle->is_data = TRUE;
-		handle->offset = 0;
+
 		unescaped_name = get_base_from_uri (uri);
 		name = gnome_vfs_uri_extract_short_path_name (uri);
-		handle->file_data = get_workgroup_data (unescaped_name, name);
-		handle->file_size = strlen (handle->file_data);
+
+		handle = file_handle_new_from_desktop_file_contents (get_workgroup_data (unescaped_name, name));
+		*method_handle = (GnomeVFSMethodHandle *)handle;
+
 		g_free (unescaped_name);
 		g_free (name);
 		
-		*method_handle = (GnomeVFSMethodHandle *)handle;
-		
-		return GNOME_VFS_OK;
+		result = GNOME_VFS_OK;
+		goto out;
 	}
 
 	if (type == SMB_URI_SERVER_LINK) {
 		if (mode & GNOME_VFS_OPEN_WRITE) {
-			return GNOME_VFS_ERROR_READ_ONLY;
+			result = GNOME_VFS_ERROR_READ_ONLY;
+			goto out;
 		}
-		handle = g_new (FileHandle, 1);
-		handle->is_data = TRUE;
-		handle->offset = 0;
+
 		unescaped_name = get_base_from_uri (uri);
 		name = gnome_vfs_uri_extract_short_path_name (uri);
-		handle->file_data = get_computer_data (unescaped_name, name);
-		handle->file_size = strlen (handle->file_data);
+
+		handle = file_handle_new_from_desktop_file_contents (get_computer_data (unescaped_name, name));
+		*method_handle = (GnomeVFSMethodHandle *)handle;
+
 		g_free (unescaped_name);
 		g_free (name);
 		
-		*method_handle = (GnomeVFSMethodHandle *)handle;
-		
-		return GNOME_VFS_OK;
+		result = GNOME_VFS_OK;
+		goto out;
 	}
 
 	g_assert (type == SMB_URI_SHARE_FILE);
@@ -1544,31 +1904,48 @@ do_open (GnomeVFSMethod *method,
 	} else {
 		if (mode & GNOME_VFS_OPEN_WRITE)
 			unix_mode = O_WRONLY;
-		else
-			return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
+ 		else {
+ 			result = GNOME_VFS_ERROR_INVALID_OPEN_MODE;
+ 			goto out;
+ 		}
 	}
 
 	if ((mode & GNOME_VFS_OPEN_TRUNCATE) ||
 	    (!(mode & GNOME_VFS_OPEN_RANDOM) && (mode & GNOME_VFS_OPEN_WRITE)))
 		unix_mode |= O_TRUNC;
 	
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
-	
 	LOCK_SMB();
 	init_authentication (&actx, uri);
 
+ 	if (mode & GNOME_VFS_OPEN_LOCKED) {
+ 		smbc_option_set (smb_context, "open_share_mode",
+ 				 SMBC_SHAREMODE_DENY_WRITE);
+ 	}
+
 	/* Important: perform_authentication leaves and re-enters the lock! */
 	while (perform_authentication (&actx) > 0) {
 		file = (smb_context->open) (smb_context, path, unix_mode, 0666);
 		actx.res = (file != NULL) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->open(\"%s\") returned file %p and error %d\n", path, file, (int) actx.res));
 	}
 
+ 	if (mode & GNOME_VFS_OPEN_LOCKED) {
+ 		smbc_option_set (smb_context, "open_share_mode",
+ 				 SMBC_SHAREMODE_DENY_NONE);
+ 	}
 	UNLOCK_SMB();
 
-	g_free (path);
-	
-	if (file == NULL)
-		return actx.res;
+	if (file == NULL) {
+		/* samba returns EBUSY if we failed because of a DENY
+		 * mode. gnome_vfs_result_from_errno() translates that
+		 * to the wrong value.
+		 */
+		if (actx.res == GNOME_VFS_ERROR_DIRECTORY_BUSY)
+			result = GNOME_VFS_ERROR_LOCKED;
+		else
+			result = actx.res;
+		goto out;
+	}
 	
 	handle = g_new (FileHandle, 1);
 	handle->is_data = FALSE;
@@ -1576,7 +1953,14 @@ do_open (GnomeVFSMethod *method,
 
 	*method_handle = (GnomeVFSMethodHandle *)handle;
 
-	return GNOME_VFS_OK;
+	result = GNOME_VFS_OK;
+
+ out:
+
+	g_free (path);
+
+	DEBUG_OUT ();
+	return result;
 }
 
 static GnomeVFSResult
@@ -1590,6 +1974,7 @@ do_close (GnomeVFSMethod *method,
 	GnomeVFSResult res;
 	int r;
 
+	DEBUG_IN ();
 	DEBUG_SMB(("do_close()\n"));
 
 	res = GNOME_VFS_OK;
@@ -1608,6 +1993,7 @@ do_close (GnomeVFSMethod *method,
 			r = smb_context->close_fn (smb_context, handle->file);
 #endif
 			actx.res = (r >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+			DEBUG_SMB(("ctx->close(%p) returned error %d\n", handle->file, (int) actx.res));
 		}
 
 		res = actx.res;		
@@ -1615,6 +2001,7 @@ do_close (GnomeVFSMethod *method,
 	}
 
 	g_free (handle);
+	DEBUG_OUT ();
 	return res;
 }
 
@@ -1631,6 +2018,7 @@ do_read (GnomeVFSMethod *method,
 	SmbAuthContext actx;
 	ssize_t n = 0;
 
+	DEBUG_IN ();
 	DEBUG_SMB(("do_read() %Lu bytes\n", num_bytes));
 
 	if (handle->is_data) {
@@ -1656,11 +2044,14 @@ do_read (GnomeVFSMethod *method,
 
 	*bytes_read = (n < 0) ? 0 : n;
 
-	if (n == 0) 
+	if (n == 0) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_EOF;
+	}
 
 	handle->offset += n;
 
+	DEBUG_OUT ();
 	return res;
 }
 
@@ -1678,10 +2069,13 @@ do_write (GnomeVFSMethod *method,
 	SmbAuthContext actx;
 	ssize_t written = 0;
 
+	DEBUG_IN ();
 	DEBUG_SMB (("do_write() %p\n", method_handle));
 
-	if (handle->is_data)
+	if (handle->is_data) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_READ_ONLY;
+	}
 
 	LOCK_SMB();
 	init_authentication (&actx, NULL);
@@ -1695,6 +2089,7 @@ do_write (GnomeVFSMethod *method,
 	UNLOCK_SMB();
 
 	*bytes_written = (written < 0) ? 0 : written;
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -1713,30 +2108,39 @@ do_create (GnomeVFSMethod *method,
 	SMBCFILE *file = NULL;
 	FileHandle *handle;
 	SmbAuthContext actx;
-	
+
+	DEBUG_IN ();
 	DEBUG_SMB (("do_create() %s mode %d\n",
 				gnome_vfs_uri_to_string (uri, 0), mode));
 
 	
 	type = smb_uri_type (uri);
 
-	if (type == SMB_URI_ERROR)
+	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
+	}
 
 	if (type == SMB_URI_WHOLE_NETWORK ||
 	    type == SMB_URI_WORKGROUP ||
 	    type == SMB_URI_SERVER ||
-	    type == SMB_URI_SHARE)
+	    type == SMB_URI_SHARE) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_IS_DIRECTORY;
+	}
 
 	if (type == SMB_URI_WORKGROUP_LINK ||
-	    type == SMB_URI_SERVER_LINK) 
+	    type == SMB_URI_SERVER_LINK) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
+	}
 	
 	unix_mode = O_CREAT | O_TRUNC;
 	
-	if (!(mode & GNOME_VFS_OPEN_WRITE))
+	if (!(mode & GNOME_VFS_OPEN_WRITE)) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
+	}
 
 	if (mode & GNOME_VFS_OPEN_READ)
 		unix_mode |= O_RDWR;
@@ -1746,7 +2150,7 @@ do_create (GnomeVFSMethod *method,
 	if (exclusive)
 		unix_mode |= O_EXCL;
 
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
 
 	LOCK_SMB();
 	init_authentication (&actx, uri);
@@ -1755,24 +2159,44 @@ do_create (GnomeVFSMethod *method,
 	while (perform_authentication (&actx) > 0) {
 		file = (smb_context->open) (smb_context, path, unix_mode, perm);
 		actx.res = (file != NULL) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->open(\"%s\") returned file %p and error %d\n", path, file, (int) actx.res));
 	}
 
 	UNLOCK_SMB();
 
 	g_free (path);
 
-	if (file == NULL)
+	if (file == NULL) {
+		DEBUG_OUT ();
 		return actx.res;
+	}
 	
 	handle = g_new (FileHandle, 1);
 	handle->is_data = FALSE;
 	handle->file = file;
 
 	*method_handle = (GnomeVFSMethodHandle *)handle;
-	
+
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
+static void
+set_file_info_to_readonly_desktop_file (GnomeVFSFileInfo *file_info, GnomeVFSURI *uri)
+{
+	file_info->name = get_base_from_uri (uri);
+	file_info->valid_fields = file_info->valid_fields
+		| GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
+		| GNOME_VFS_FILE_INFO_FIELDS_TYPE
+		| GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
+	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
+	file_info->mime_type = g_strdup ("application/x-desktop");
+	file_info->permissions =
+		GNOME_VFS_PERM_USER_READ |
+		GNOME_VFS_PERM_OTHER_READ |
+		GNOME_VFS_PERM_GROUP_READ;
+}
+
 static GnomeVFSResult
 do_get_file_info (GnomeVFSMethod *method,
 		  GnomeVFSURI *uri,
@@ -1787,19 +2211,34 @@ do_get_file_info (GnomeVFSMethod *method
 	const char *mime_type;
 	SmbAuthContext actx;
 
+	DEBUG_IN ();
 	DEBUG_SMB (("do_get_file_info() %s\n",
 				gnome_vfs_uri_to_string (uri, 0)));
 
 	type = smb_uri_type (uri);
 
 	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
+
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+
+	if (is_printer (uri)) {
+		DEBUG_SMB (("is a printer we already saw; will fill in info\n"));
+
+		set_file_info_to_readonly_desktop_file (file_info, uri);
+		g_free (path);
+
+		DEBUG_OUT ();
+		return GNOME_VFS_OK;
+	}
 	
 	if (type == SMB_URI_WHOLE_NETWORK ||
 	    type == SMB_URI_WORKGROUP ||
 	    type == SMB_URI_SERVER ||
 	    type == SMB_URI_SHARE) {
+		DEBUG_SMB (("is whole network, workgroup, server, or share\n"));
 		file_info->name = get_base_from_uri (uri);
 		file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
 			GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
@@ -1820,29 +2259,22 @@ do_get_file_info (GnomeVFSMethod *method
  				GNOME_VFS_PERM_OTHER_READ |
  				GNOME_VFS_PERM_GROUP_READ;
 		}
+		DEBUG_OUT();
 		return GNOME_VFS_OK;
 	}
 
 	if (type == SMB_URI_WORKGROUP_LINK ||
 	    type == SMB_URI_SERVER_LINK) {
-		file_info->name = get_base_from_uri (uri);
-		file_info->valid_fields = file_info->valid_fields
-			| GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
-			| GNOME_VFS_FILE_INFO_FIELDS_TYPE
-			| GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
-		file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
-		file_info->mime_type = g_strdup ("application/x-desktop");
-		file_info->permissions =
-			GNOME_VFS_PERM_USER_READ |
-			GNOME_VFS_PERM_OTHER_READ |
-			GNOME_VFS_PERM_GROUP_READ;
+		DEBUG_SMB (("is workgroup link, or server link\n"));
+		set_file_info_to_readonly_desktop_file (file_info, uri);
+		DEBUG_OUT ();
 		return GNOME_VFS_OK;
 	}
 
 	g_assert (type == SMB_URI_SHARE_FILE);
-	    
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
 
+	DEBUG_SMB (("is share file\n"));
+	    
 	LOCK_SMB();
 	init_authentication (&actx, uri);
 
@@ -1850,14 +2282,17 @@ do_get_file_info (GnomeVFSMethod *method
 	while (perform_authentication (&actx) > 0) {
 		err = smb_context->stat (smb_context, path, &st);
 		actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->stat(\"%s\") returned error %d\n", path, (int) actx.res));
 	}
 
 	UNLOCK_SMB();
 
 	g_free (path);
 
-	if (err < 0)
+	if (err < 0) {
+		DEBUG_OUT ();
 		return actx.res;
+	}
 	
 	gnome_vfs_stat_to_file_info (file_info, &st);
 	file_info->name = get_base_from_uri (uri);
@@ -1885,6 +2320,7 @@ do_get_file_info (GnomeVFSMethod *method
 				file_info->name, type,
 				file_info->mime_type, file_info->type));
 
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
@@ -1900,6 +2336,7 @@ do_get_file_info_from_handle (GnomeVFSMe
 	struct stat st;
 	int err = -1;
 
+	DEBUG_IN ();
 	LOCK_SMB();
 	init_authentication (&actx, NULL);
 	
@@ -1907,17 +2344,22 @@ do_get_file_info_from_handle (GnomeVFSMe
 	while (perform_authentication (&actx) > 0) {
 		err = smb_context->fstat (smb_context, handle->file, &st);
 		actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->fstat(%p) returned error %d\n", handle->file, (int) actx.res));
 	}
 	
 	UNLOCK_SMB();
 	
-	if (err < 0) 
+	if (err < 0) {
+		DEBUG_OUT ();
 		return actx.res;
+	}
 	
 	gnome_vfs_stat_to_file_info (file_info, &st);
 
 	file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
 	file_info->io_block_size = SMB_BLOCK_SIZE;
+
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
@@ -1925,7 +2367,16 @@ static gboolean
 do_is_local (GnomeVFSMethod *method,
 	     const GnomeVFSURI *uri)
 {
-	return FALSE;
+	gboolean is_local;
+
+	/* FIXME: This is a hack.  In get_printer_data(), we generate data for a desktop item.  This item
+	 * is a "Type=Application" launcher, which launches gnome-cups-add.  However, since we can't execute
+	 * .desktop files from remote sites, we only advertise that printers "are local files".
+	 */
+
+	is_local = is_printer ((GnomeVFSURI *) uri);
+	
+	return is_local;
 }
 
 typedef struct {
@@ -1963,6 +2414,7 @@ do_open_directory (GnomeVFSMethod *metho
 	SMBCFILE *dir = NULL;
 	SmbAuthContext actx;
 
+	DEBUG_IN ();
 	DEBUG_SMB(("do_open_directory() %s\n",
 		gnome_vfs_uri_to_string (uri, 0)));
 
@@ -1974,12 +2426,14 @@ do_open_directory (GnomeVFSMethod *metho
 		directory_handle = g_new0 (DirectoryHandle, 1);
 		g_hash_table_foreach (workgroups, add_workgroup, directory_handle);
 		*method_handle = (GnomeVFSMethodHandle *) directory_handle;
+		DEBUG_OUT ();
 		return GNOME_VFS_OK;
 	}
 
 	if (type == SMB_URI_ERROR ||
 	    type == SMB_URI_WORKGROUP_LINK ||
 	    type == SMB_URI_SERVER_LINK) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_A_DIRECTORY;
 	}
 
@@ -1988,15 +2442,26 @@ do_open_directory (GnomeVFSMethod *metho
 	host_name = gnome_vfs_uri_get_host_name (uri);
 	if (type == SMB_URI_WORKGROUP && host_name != NULL &&
 	    !g_ascii_strcasecmp(host_name, DEFAULT_WORKGROUP_NAME)) {
+		char *new_workgroup;
+
 		new_uri = gnome_vfs_uri_dup (uri);
-		gnome_vfs_uri_set_host_name (new_uri,
-					     smb_context->workgroup
-					     ? smb_context->workgroup
-					     : "WORKGROUP");
+		if (smb_context->workgroup)
+			new_workgroup = smb_context->workgroup;
+		else
+			new_workgroup = "WORKGROUP";
+
+		DEBUG_SMB (("we are being asked for %s; substituting it for workgroup \"%s\"%s\n",
+			    DEFAULT_WORKGROUP_NAME,
+			    new_workgroup,
+			    (smb_context->workgroup
+			     ? " because that is what was in the smbcctx->workgroup"
+			     : " because smbcctx->workgroup=NULL, so we use this as a last resort")));
+
+		gnome_vfs_uri_set_host_name (new_uri, new_workgroup);
 		uri = new_uri;
 	}
 		
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
 
 	DEBUG_SMB(("do_open_directory() path %s\n", path));
 
@@ -2007,6 +2472,7 @@ do_open_directory (GnomeVFSMethod *metho
 	while (perform_authentication (&actx) > 0) {
 		dir = smb_context->opendir (smb_context, path);
 		actx.res = (dir != NULL) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->opendir(\"%s\") returned dir %p and error %d\n", path, dir, (int) actx.res));
 	}
 
 	UNLOCK_SMB();
@@ -2016,6 +2482,7 @@ do_open_directory (GnomeVFSMethod *metho
 	
 	if (dir == NULL) {
 		g_free (path);
+		DEBUG_OUT ();
 		return actx.res;
 	}
 	
@@ -2025,6 +2492,7 @@ do_open_directory (GnomeVFSMethod *metho
 	directory_handle->path = path;
 	*method_handle = (GnomeVFSMethodHandle *) directory_handle;
 
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
@@ -2039,10 +2507,13 @@ do_close_directory (GnomeVFSMethod *meth
 	GList *l;
 	int err = -1;
 
+	DEBUG_IN ();
 	DEBUG_SMB(("do_close_directory: %p\n", directory_handle));
 
-	if (directory_handle == NULL)
+	if (directory_handle == NULL) {
+		DEBUG_OUT ();
 		return GNOME_VFS_OK;
+	}
 
 	if (directory_handle->workgroups != NULL) {
 		for (l = directory_handle->workgroups; l != NULL; l = l->next) {
@@ -2061,6 +2532,7 @@ do_close_directory (GnomeVFSMethod *meth
 		while (perform_authentication (&actx) > 0) {
 			err = smb_context->closedir (smb_context, directory_handle->dir);
 			actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+			DEBUG_SMB(("ctx->closedir(%p) returned error %d\n", directory_handle->dir, (int) actx.res));
 		}
 		
 		res = actx.res;
@@ -2069,9 +2541,68 @@ do_close_directory (GnomeVFSMethod *meth
 	g_free (directory_handle->path);
 	g_free (directory_handle);
 
+	DEBUG_OUT ();
 	return res;
 }
 
+static char *
+make_path_from_uri_and_name (const char *path, const char *name)
+{
+	char *escaped_name;
+	char *new_path;
+
+	escaped_name = gnome_vfs_escape_string (name);
+
+	if (path[strlen(path) - 1] == '/') {
+		new_path = g_strconcat (path, escaped_name, NULL);
+	} else {
+		new_path = g_strconcat (path, "/", escaped_name, NULL);
+	}
+
+	g_free (escaped_name);
+
+	return new_path;
+}
+
+static void
+add_printer_to_hash (DirectoryHandle *dh,
+		     GnomeVFSFileInfo *file_info)
+{
+	char *path;
+	GnomeVFSURI *uri;
+
+	/* See is_printer() below.  This will generate a URI without username/password */
+	path = make_path_from_uri_and_name (dh->path, file_info->name);
+
+	uri = gnome_vfs_uri_new (path);
+	g_assert (uri != NULL);
+	g_free (path);
+
+	g_hash_table_replace (printer_hash, uri, uri);
+}
+
+static gboolean
+is_printer (GnomeVFSURI *uri)
+{
+	char *tmp_str;
+	GnomeVFSURI *tmp_uri;
+	gboolean result;
+
+	/* See add_printer_to_hash() above.  It doesn't store username/password
+	 * in the URIs, so we have to hide them here.
+	 */
+	tmp_str = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	tmp_uri = gnome_vfs_uri_new (tmp_str);
+	g_assert (tmp_uri != NULL);
+	g_free (tmp_str);
+
+	result = (g_hash_table_lookup (printer_hash, tmp_uri) != NULL);
+
+	gnome_vfs_uri_unref (tmp_uri);
+
+	return result;
+}
+
 static GnomeVFSResult
 do_read_directory (GnomeVFSMethod *method,
 		   GnomeVFSMethodHandle *method_handle,
@@ -2083,15 +2614,16 @@ do_read_directory (GnomeVFSMethod *metho
 	SmbAuthContext actx;
 	struct stat st;
 	char *statpath;
-	char *path;
 	char *escaped;
 	int r = -1;
 	GList *l;
 
+	DEBUG_IN ();
 	DEBUG_SMB (("do_read_directory()\n"));
 
 	if (dh->dir == NULL) {
 		if (dh->workgroups == NULL) {
+			DEBUG_OUT ();
 			return GNOME_VFS_ERROR_EOF;
 		} else {
 			/* workgroup link */
@@ -2105,6 +2637,7 @@ do_read_directory (GnomeVFSMethod *metho
 				| GNOME_VFS_FILE_INFO_FIELDS_TYPE;
 			file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
 			file_info->mime_type = g_strdup ("application/x-desktop");
+			DEBUG_OUT ();
 			return GNOME_VFS_OK;
 		}
 	}
@@ -2128,16 +2661,20 @@ do_read_directory (GnomeVFSMethod *metho
 			} else {
 				actx.res = GNOME_VFS_OK;
 			}
+			DEBUG_SMB(("ctx->readdir(%p) returned entry %p and error %d\n", dh->dir, entry, (int) actx.res));
 		}
 		
 		if (entry == NULL) {
 			UNLOCK_SMB();
+			DEBUG_OUT ();
 			return actx.res;
 		}
 		
 	} while (entry->smbc_type == SMBC_COMMS_SHARE ||
 		 entry->smbc_type == SMBC_IPC_SHARE ||
+#if 0
 		 entry->smbc_type == SMBC_PRINTER_SHARE ||
+#endif
 		 entry->name == NULL ||
 		 strlen (entry->name) == 0 ||
 		 (entry->smbc_type == SMBC_FILE_SHARE &&
@@ -2167,31 +2704,23 @@ do_read_directory (GnomeVFSMethod *metho
 		file_info->mime_type = g_strdup ("application/x-desktop");
 		break;
 	case SMBC_PRINTER_SHARE:
+#if 0
 		/* Ignored above for now */
+#endif
 		file_info->valid_fields = file_info->valid_fields
 			| GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
 			| GNOME_VFS_FILE_INFO_FIELDS_TYPE;
 		file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
-		file_info->mime_type = g_strdup ("application/x-smb-printer");
+ 		file_info->mime_type = g_strdup ("application/x-desktop"); /* we'll generate the fake .desktop in do_open() */
+ 		add_printer_to_hash (dh, file_info);
+ 		debug_print ("GOT PRINTER: \"%s\"", file_info->name);
+ 		break;
 	case SMBC_COMMS_SHARE:
 	case SMBC_IPC_SHARE:
 		break;
 	case SMBC_DIR:
 	case SMBC_FILE:
-		path = dh->path;
-		escaped = gnome_vfs_escape_string (file_info->name);
-
-		if (path[strlen(path)-1] == '/') {
-			statpath = g_strconcat (path, 
-						escaped,
-						NULL);
-		} else {
-			statpath = g_strconcat (path,
-						"/",
-						escaped,
-						NULL);
-		}
-		g_free (escaped);
+		statpath = make_path_from_uri_and_name (dh->path, file_info->name);
 
 		/* TODO: might give an auth error, but should be rare due
 		   to the succeeding opendir. If this happens and we can't
@@ -2206,6 +2735,7 @@ do_read_directory (GnomeVFSMethod *metho
 		while (perform_authentication (&actx) > 0) {
 			r = smb_context->stat (smb_context, statpath, &st);
 			actx.res = (r == 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+			DEBUG_SMB(("ctx->stat(\"%s\") returned error %d\n", statpath, (int) actx.res));
 		}
 		UNLOCK_SMB();
 		
@@ -2240,6 +2770,7 @@ do_read_directory (GnomeVFSMethod *metho
 		g_assert_not_reached ();
 	}
 
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
@@ -2255,6 +2786,8 @@ do_seek (GnomeVFSMethod *method,
 	int meth_whence;
 	off_t ret = (off_t) -1;
 
+	DEBUG_IN ();
+
 	if (handle->is_data) {
 		switch (whence) {
 		case GNOME_VFS_SEEK_START:
@@ -2271,8 +2804,11 @@ do_seek (GnomeVFSMethod *method,
 			}
 			break;
 		default:
+			DEBUG_OUT ();
 			return GNOME_VFS_ERROR_NOT_SUPPORTED;
 		}
+
+		DEBUG_OUT ();
 		return GNOME_VFS_OK;
 	}
 	
@@ -2287,6 +2823,7 @@ do_seek (GnomeVFSMethod *method,
 		meth_whence = SEEK_END;
 		break;
 	default:
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_SUPPORTED;
 	}
 
@@ -2299,7 +2836,8 @@ do_seek (GnomeVFSMethod *method,
 		actx.res = (ret != (off_t) -1) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
 	}
 	UNLOCK_SMB();
-	
+
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -2312,8 +2850,11 @@ do_tell (GnomeVFSMethod *method,
 	SmbAuthContext actx;
 	off_t ret = (off_t) -1;
 
+	DEBUG_IN ();
+
 	if (handle->is_data) {
 		*offset_return = handle->offset;
+		DEBUG_OUT ();
 		return GNOME_VFS_OK;
 	}
 	
@@ -2328,6 +2869,8 @@ do_tell (GnomeVFSMethod *method,
 	UNLOCK_SMB();
 	
 	*offset_return = (ret == (off_t) -1) ? 0 : (GnomeVFSFileOffset) ret;
+
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -2340,12 +2883,14 @@ do_unlink (GnomeVFSMethod *method,
 	SmbAuthContext actx;
 	int type, err = -1;
 
+	DEBUG_IN ();
 	DEBUG_SMB (("do_unlink() %s\n",
 				gnome_vfs_uri_to_string (uri, 0)));
 
 	type = smb_uri_type (uri);
 
 	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
 
@@ -2355,10 +2900,11 @@ do_unlink (GnomeVFSMethod *method,
 	    type == SMB_URI_SHARE ||
 	    type == SMB_URI_WORKGROUP_LINK ||
 	    type == SMB_URI_SERVER_LINK) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
 
 	LOCK_SMB();
 	init_authentication (&actx, uri);
@@ -2367,12 +2913,14 @@ do_unlink (GnomeVFSMethod *method,
 	while (perform_authentication (&actx) > 0) {
 		err = smb_context->unlink (smb_context, path);
 		actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->unlink(\"%s\") returned error %d\n", path, (int) actx.res));
 	}
 	
 	UNLOCK_SMB();
 
 	g_free (path);
-	
+
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -2389,6 +2937,7 @@ do_check_same_fs (GnomeVFSMethod *method
 	char *path2;
 	char *p1, *p2;
 
+	DEBUG_IN ();
 	DEBUG_SMB (("do_check_same_fs()\n"));
 
 	server1 =
@@ -2409,6 +2958,7 @@ do_check_same_fs (GnomeVFSMethod *method
 		g_free (path1);
 		g_free (path2);
 		*same_fs_return = FALSE;
+		DEBUG_OUT ();
 		return GNOME_VFS_OK;
 	}
                              
@@ -2437,6 +2987,7 @@ do_check_same_fs (GnomeVFSMethod *method
 	g_free (path1);
 	g_free (path2);
 
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
@@ -2453,7 +3004,7 @@ do_move (GnomeVFSMethod *method,
 	SmbAuthContext actx;
 	int old_type, new_type;
 	
-	
+	DEBUG_IN ();
 	DEBUG_SMB (("do_move() %s %s\n",
 				gnome_vfs_uri_to_string (old_uri, 0),
 				gnome_vfs_uri_to_string (new_uri, 0)));
@@ -2463,12 +3014,13 @@ do_move (GnomeVFSMethod *method,
 
 	if (old_type != SMB_URI_SHARE_FILE ||
 	    new_type != SMB_URI_SHARE_FILE) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
 	/* Transform the URI into a completely unescaped string */
-	old_path = gnome_vfs_uri_to_string (old_uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
-	new_path = gnome_vfs_uri_to_string (new_uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	old_path = gnome_vfs_uri_to_string (old_uri, GNOME_VFS_URI_HIDE_NONE);
+	new_path = gnome_vfs_uri_to_string (new_uri, GNOME_VFS_URI_HIDE_NONE);
 
 	tried_once = FALSE;
  retry:
@@ -2480,6 +3032,7 @@ do_move (GnomeVFSMethod *method,
 		err = smb_context->rename (smb_context, old_path, smb_context, new_path);
 		errnox = errno;
 		actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->rename(\"%s\", \"%s\") returned error %d\n", old_path, new_path, (int) actx.res));
 	}
 	UNLOCK_SMB();
 	
@@ -2496,6 +3049,7 @@ do_move (GnomeVFSMethod *method,
 			while (perform_authentication (&actx) > 0) {			
 				err = smb_context->unlink (smb_context, new_path);
 				actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+				DEBUG_SMB(("ctx->unlink(\"%s\") returned error %d\n", new_path, (int) actx.res));
 			}
 			UNLOCK_SMB();
 
@@ -2512,6 +3066,7 @@ do_move (GnomeVFSMethod *method,
 	g_free (old_path);
 	g_free (new_path);
 
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -2536,9 +3091,11 @@ do_make_directory (GnomeVFSMethod *metho
 	int type, err = -1;
 	SmbAuthContext actx;
 
+	DEBUG_IN ();
 	type = smb_uri_type (uri);
 
 	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
 
@@ -2548,11 +3105,12 @@ do_make_directory (GnomeVFSMethod *metho
 	    type == SMB_URI_SHARE ||
 	    type == SMB_URI_WORKGROUP_LINK ||
 	    type == SMB_URI_SERVER_LINK) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
 	/* Transform the URI into a completely unescaped string */
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
 
 	LOCK_SMB();
 	init_authentication (&actx, uri);
@@ -2561,12 +3119,14 @@ do_make_directory (GnomeVFSMethod *metho
 	while (perform_authentication (&actx) > 0) {
 		err = smb_context->mkdir (smb_context, path, perm);
 		actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->mkdir(\"%s\") returned error %d\n", path, (int) actx.res));
 	}
 
 	UNLOCK_SMB();
 
 	g_free (path);
 
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -2579,9 +3139,11 @@ do_remove_directory (GnomeVFSMethod *met
 	int err = -1, type;
 	SmbAuthContext actx;
 
+	DEBUG_IN ();
 	type = smb_uri_type (uri);
 
 	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
 
@@ -2591,11 +3153,12 @@ do_remove_directory (GnomeVFSMethod *met
 	    type == SMB_URI_SHARE ||
 	    type == SMB_URI_WORKGROUP_LINK ||
 	    type == SMB_URI_SERVER_LINK) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
 	/* Transform the URI into a completely unescaped string */
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
 
 	LOCK_SMB();
 	init_authentication (&actx, uri);
@@ -2603,11 +3166,13 @@ do_remove_directory (GnomeVFSMethod *met
 	while (perform_authentication (&actx) > 0) {
 		err = smb_context->rmdir (smb_context, path);
 		actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+		DEBUG_SMB(("ctx->rmdir(\"%s\") returned error %d\n", path, (int) actx.res));
 	}
 	UNLOCK_SMB();
 
 	g_free (path);
 
+	DEBUG_OUT ();
 	return actx.res;
 }
 
@@ -2622,11 +3187,13 @@ do_set_file_info (GnomeVFSMethod *method
 	int err = -1, errnox = 0, type;
 	SmbAuthContext actx;	
 
+	DEBUG_IN ();
 	DEBUG_SMB (("do_set_file_info: mask %x\n", mask));
 
 	type = smb_uri_type (uri);
 
 	if (type == SMB_URI_ERROR) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
 
@@ -2636,10 +3203,11 @@ do_set_file_info (GnomeVFSMethod *method
 	    type == SMB_URI_SHARE ||
 	    type == SMB_URI_WORKGROUP_LINK ||
 	    type == SMB_URI_SERVER_LINK) {
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
-	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+	path = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
 	
 	if (mask & GNOME_VFS_SET_FILE_INFO_NAME) {
 		GnomeVFSURI *parent, *new_uri;
@@ -2648,7 +3216,7 @@ do_set_file_info (GnomeVFSMethod *method
 		parent = gnome_vfs_uri_get_parent (uri);
 		new_uri = gnome_vfs_uri_append_file_name (parent, info->name);
 		gnome_vfs_uri_unref (parent);
-		new_path = gnome_vfs_uri_to_string (new_uri, GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
+		new_path = gnome_vfs_uri_to_string (new_uri, GNOME_VFS_URI_HIDE_NONE);
 		gnome_vfs_uri_unref (new_uri);
 
 
@@ -2659,6 +3227,7 @@ do_set_file_info (GnomeVFSMethod *method
 			err = smb_context->rename (smb_context, path, smb_context, new_path);
 			errnox = errno;
 			actx.res = (err >= 0) ? GNOME_VFS_OK : gnome_vfs_result_from_errno ();
+			DEBUG_SMB(("ctx->rename(\"%s\", \"%s\") returned error %d\n", path, new_path, (int) actx.res));
 		}
 		
 		UNLOCK_SMB();
@@ -2671,31 +3240,37 @@ do_set_file_info (GnomeVFSMethod *method
 
 		if (actx.res != GNOME_VFS_OK) {
 			g_free (path);
+			DEBUG_OUT ();
 			return actx.res;
 		}
 	}
 
 	if (gnome_vfs_context_check_cancellation (context)) {
 		g_free (path);
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_CANCELLED;
 	}
 
 	if (mask & GNOME_VFS_SET_FILE_INFO_PERMISSIONS) {
 		g_free (path);
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_SUPPORTED;
 	}
 
 	if (mask & GNOME_VFS_SET_FILE_INFO_OWNER) {
 		g_free (path);
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_SUPPORTED;
 	}
 	
 	if (mask & GNOME_VFS_SET_FILE_INFO_TIME) {
 		g_free (path);
+		DEBUG_OUT ();
 		return GNOME_VFS_ERROR_NOT_SUPPORTED;
 	}
 
 	g_free (path);
+	DEBUG_OUT ();
 	return GNOME_VFS_OK;
 }
 
@@ -2727,11 +3302,50 @@ static GnomeVFSMethod method = {
 	NULL  /* do_create_symbolic_link */
 };
 
+static void
+debug_init (void)
+{
+	char *debug_flag_path;
+	struct stat st;
+
+	LOCK_SMB ();
+
+	debug_flag_path = g_build_filename (g_get_home_dir (), ".debug-gnome-vfs-smb", NULL);
+
+	if (stat (debug_flag_path, &st) == 0) {
+		char *debug_filename;
+
+		debug_filename = g_build_filename (g_get_home_dir (), "debug-gnome-vfs-smb.log", NULL);
+		debug_file = fopen (debug_filename, "w");
+		g_free (debug_filename);
+	} else
+		debug_file = NULL;
+
+	g_free (debug_flag_path);
+
+	UNLOCK_SMB ();
+}
+
+static void
+debug_shutdown (void)
+{
+	LOCK_SMB ();
+
+	if (debug_file) {
+		fclose (debug_file);
+		debug_file = NULL;
+	}
+
+	UNLOCK_SMB ();
+}
+
 GnomeVFSMethod *
 vfs_module_init (const char *method_name, const char *args)
 {
 	smb_lock = g_mutex_new ();
 
+	debug_init ();
+
 	DEBUG_SMB (("<-- smb module init called -->\n"));
 
 	if (try_init ()) {
@@ -2754,9 +3368,12 @@ vfs_module_shutdown (GnomeVFSMethod *met
 	g_hash_table_destroy (server_cache);
 	g_hash_table_destroy (workgroups);
         g_hash_table_destroy (user_cache);
+	g_hash_table_destroy (printer_hash);
 	
 	g_mutex_free (smb_lock);
 
 	DEBUG_SMB (("<-- smb module shutdown called -->\n"));
+
+	debug_shutdown ();
 }