Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision 6acc0332708b8c844f721dbda9c7ecb94b8dd232)
+++ protocols/msn/msn.c	(revision 1c8e5f7fba87b6096a7fd86508ca1821876abb54)
@@ -104,4 +104,13 @@
 		g_free( md->grouplist );
 		
+		while( md->grpq )
+		{
+			struct msn_groupadd *ga = md->grpq->data;
+			g_free( ga->group );
+			g_free( ga->who );
+			g_free( ga );
+			md->grpq = g_slist_remove( md->grpq, ga );
+		}
+		
 		g_free( md );
 	}
@@ -122,4 +131,12 @@
 	struct msn_switchboard *sb;
 	
+#ifdef DEBUG
+	if( strcmp( who, "raw" ) == 0 )
+	{
+		msn_write( ic, message, strlen( message ) );
+		msn_write( ic, "\r\n", 2 );
+	}
+	else
+#endif
 	if( ( sb = msn_sb_by_handle( ic, who ) ) )
 	{
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision 6acc0332708b8c844f721dbda9c7ecb94b8dd232)
+++ protocols/msn/msn.h	(revision 1c8e5f7fba87b6096a7fd86508ca1821876abb54)
@@ -70,5 +70,5 @@
 	int trId;
 	
-	GSList *msgq;
+	GSList *msgq, *grpq;
 	GSList *switchboards;
 	int sb_failures;
@@ -119,4 +119,10 @@
 	char *who;
 	char *text;
+};
+
+struct msn_groupadd
+{
+	char *who;
+	char *group;
 };
 
Index: protocols/msn/msn_util.c
===================================================================
--- protocols/msn/msn_util.c	(revision 6acc0332708b8c844f721dbda9c7ecb94b8dd232)
+++ protocols/msn/msn_util.c	(revision 1c8e5f7fba87b6096a7fd86508ca1821876abb54)
@@ -55,6 +55,4 @@
 	struct msn_data *md = ic->proto_data;
 	char buf[1024], *realname, groupid[8];
-	
-	realname = msn_http_encode( realname_ );
 	
 	*groupid = '\0';
@@ -68,17 +66,45 @@
 				break;
 			}
-	}
-	
+		
+		if( *groupid == '\0' )
+		{
+			/* Have to create this group, it doesn't exist yet. */
+			struct msn_groupadd *ga;
+			GSList *l;
+			
+			for( l = md->grpq; l; l = l->next )
+			{
+				ga = l->data;
+				if( g_strcasecmp( ga->group, group ) == 0 )
+					break;
+			}
+			
+			ga = g_new0( struct msn_groupadd, 1 );
+			ga->who = g_strdup( who );
+			ga->group = g_strdup( group );
+			md->grpq = g_slist_prepend( md->grpq, ga );
+			
+			if( l == NULL )
+			{
+				char *groupname = msn_http_encode( group );
+				g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 );
+				g_free( groupname );
+				return msn_write( ic, buf, strlen( buf ) );
+			}
+			else
+			{
+				/* This can happen if the user's doing lots of adds to a
+				   new group at once; we're still waiting for the server
+				   to confirm group creation. */
+				return 1;
+			}
+		}
+	}
+	
+	realname = msn_http_encode( realname_ );
 	g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid );
-	if( msn_write( ic, buf, strlen( buf ) ) )
-	{
-		g_free( realname );
-		
-		return( 1 );
-	}
-	
 	g_free( realname );
 	
-	return( 0 );
+	return msn_write( ic, buf, strlen( buf ) );
 }
 
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 6acc0332708b8c844f721dbda9c7ecb94b8dd232)
+++ protocols/msn/ns.c	(revision 1c8e5f7fba87b6096a7fd86508ca1821876abb54)
@@ -612,4 +612,48 @@
 		}
 	}
+	else if( strcmp( cmd[0], "ADG" ) == 0 )
+	{
+		char *group = g_strdup( cmd[3] );
+		int groupnum, i;
+		GSList *l, *next;
+		
+		http_decode( group );
+		if( sscanf( cmd[4], "%d", &groupnum ) == 1 )
+		{
+			if( groupnum >= md->groupcount )
+			{
+				md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 );
+				for( i = md->groupcount; i <= groupnum; i ++ )
+					md->grouplist[i] = NULL;
+				md->groupcount = groupnum + 1;
+			}
+			g_free( md->grouplist[groupnum] );
+			md->grouplist[groupnum] = group;
+		}
+		else
+		{
+			/* Shouldn't happen, but if it does, give up on the group. */
+			g_free( group );
+			imcb_error( ic, "Syntax error" );
+			imc_logout( ic, TRUE );
+			return 0;
+		}
+		
+		for( l = md->grpq; l; l = next )
+		{
+			struct msn_groupadd *ga = l->data;
+			next = l->next;
+			if( g_strcasecmp( ga->group, group ) == 0 )
+			{
+				if( !msn_buddy_list_add( ic, "FL", ga->who, ga->who, group ) )
+					return 0;
+				
+				g_free( ga->group );
+				g_free( ga->who );
+				g_free( ga );
+				md->grpq = g_slist_remove( md->grpq, ga );
+			}
+		}
+	}
 	else if( isdigit( cmd[0][0] ) )
 	{
