Index: .bzrignore
===================================================================
--- .bzrignore	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ .bzrignore	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -19,2 +19,3 @@
 coverage
 bitlbee.info
+bitlbee.exe
Index: Makefile
===================================================================
--- Makefile	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ Makefile	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -10,7 +10,17 @@
 
 # Program variables
-objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o
+objects = account.o bitlbee.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
 headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
 subdirs = lib protocols
+
+ifeq ($(TARGET),i586-mingw32msvc)
+objects += win32.o
+LFLAGS+=-lws2_32
+EFLAGS+=-lsecur32
+OUTFILE=bitlbee.exe
+else
+objects += unix.o conf.o log.o
+OUTFILE=bitlbee
+endif
 
 # Expansion of variables
Index: account.c
===================================================================
--- account.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ account.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -79,5 +79,23 @@
 		return NULL;
 	
-	if( strcmp( set->key, "username" ) == 0 )
+	if( strcmp( set->key, "server" ) == 0 )
+	{
+		g_free( acc->server );
+		if( value && *value )
+		{
+			acc->server = g_strdup( value );
+			return value;
+		}
+		else
+		{
+			acc->server = NULL;
+			return g_strdup( set->def );
+		}
+	}
+	else if( value == NULL )
+	{
+		/* Noop, the other three can't be NULL. */
+	}
+	else if( strcmp( set->key, "username" ) == 0 )
 	{
 		g_free( acc->user );
@@ -90,18 +108,4 @@
 		acc->pass = g_strdup( value );
 		return NULL;	/* password shouldn't be visible in plaintext! */
-	}
-	else if( strcmp( set->key, "server" ) == 0 )
-	{
-		g_free( acc->server );
-		if( *value )
-		{
-			acc->server = g_strdup( value );
-			return value;
-		}
-		else
-		{
-			acc->server = NULL;
-			return g_strdup( set->def );
-		}
 	}
 	else if( strcmp( set->key, "auto_connect" ) == 0 )
@@ -234,2 +238,82 @@
 	}
 }
+
+struct account_reconnect_delay
+{
+	int start;
+	char op;
+	int step;
+	int max;
+};
+
+int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p )
+{
+	memset( p, 0, sizeof( *p ) );
+	/* A whole day seems like a sane "maximum maximum". */
+	p->max = 86400;
+	
+	/* Format: /[0-9]+([*+][0-9]+(<[0-9+]))/ */
+	while( *value && isdigit( *value ) )
+		p->start = p->start * 10 + *value++ - '0';
+	
+	/* Sure, call me evil for implementing my own fscanf here, but it's
+	   dead simple and I'm immediately at the next part to parse. */
+	
+	if( *value == 0 )
+		/* If the string ends now, the delay is constant. */
+		return 1;
+	else if( *value != '+' && *value != '*' )
+		/* Otherwise allow either a + or a * */
+		return 0;
+	
+	p->op = *value++;
+	
+	/* + or * the delay by this number every time. */
+	while( *value && isdigit( *value ) )
+		p->step = p->step * 10 + *value++ - '0';
+	
+	if( *value == 0 )
+		/* Use the default maximum (one day). */
+		return 1;
+	else if( *value != '<' )
+		return 0;
+	
+	p->max = 0;
+	value ++;
+	while( *value && isdigit( *value ) )
+		p->max = p->max * 10 + *value++ - '0';
+	
+	return p->max > 0;
+}
+
+char *set_eval_account_reconnect_delay( set_t *set, char *value )
+{
+	struct account_reconnect_delay p;
+	
+	return account_reconnect_delay_parse( value, &p ) ? value : NULL;
+}
+
+int account_reconnect_delay( account_t *a )
+{
+	char *setting = set_getstr( &a->irc->set, "auto_reconnect_delay" );
+	struct account_reconnect_delay p;
+	
+	if( account_reconnect_delay_parse( setting, &p ) )
+	{
+		if( a->auto_reconnect_delay == 0 )
+			a->auto_reconnect_delay = p.start;
+		else if( p.op == '+' )
+			a->auto_reconnect_delay += p.step;
+		else if( p.op == '*' )
+			a->auto_reconnect_delay *= p.step;
+		
+		if( a->auto_reconnect_delay > p.max )
+			a->auto_reconnect_delay = p.max;
+	}
+	else
+	{
+		a->auto_reconnect_delay = 0;
+	}
+	
+	return a->auto_reconnect_delay;
+}
Index: account.h
===================================================================
--- account.h	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ account.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -35,4 +35,5 @@
 	
 	int auto_connect;
+	int auto_reconnect_delay;
 	int reconnect;
 	
@@ -52,4 +53,6 @@
 
 char *set_eval_account( set_t *set, char *value );
+char *set_eval_account_reconnect_delay( set_t *set, char *value );
+int account_reconnect_delay( account_t *a );
 
 #define ACC_SET_NOSAVE		1
Index: bitlbee.c
===================================================================
--- bitlbee.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ bitlbee.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -118,9 +118,10 @@
 	
 	if( global.conf->runmode == RUNMODE_FORKDAEMON )
-		ipc_master_load_state();
+		ipc_master_load_state( getenv( "_BITLBEE_RESTART_STATE" ) );
 
 	if( global.conf->runmode == RUNMODE_DAEMON || global.conf->runmode == RUNMODE_FORKDAEMON )
 		ipc_master_listen_socket();
 	
+#ifndef _WIN32
 	if( ( fp = fopen( global.conf->pidfile, "w" ) ) )
 	{
@@ -132,4 +133,5 @@
 		log_message( LOGLVL_WARNING, "Warning: Couldn't write PID to `%s'", global.conf->pidfile );
 	}
+#endif
 	
 	return( 0 );
@@ -140,7 +142,4 @@
 	if( !irc_new( 0 ) )
 		return( 1 );
-	
-	log_link( LOGLVL_ERROR, LOGOUTPUT_IRC );
-	log_link( LOGLVL_WARNING, LOGOUTPUT_IRC );
 	
 	return( 0 );
@@ -254,5 +253,4 @@
 	struct sockaddr_in conn_info;
 	int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
-	pid_t client_pid = 0;
 	
 	if( new_socket == -1 )
@@ -262,6 +260,8 @@
 	}
 	
+#ifndef _WIN32
 	if( global.conf->runmode == RUNMODE_FORKDAEMON )
 	{
+		pid_t client_pid = 0;
 		int fds[2];
 		
@@ -320,4 +320,5 @@
 	}
 	else
+#endif
 	{
 		log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
Index: bitlbee.h
===================================================================
--- bitlbee.h	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ bitlbee.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -29,4 +29,7 @@
 #define _GNU_SOURCE /* Stupid GNU :-P */
 
+/* Depend on Windows 2000 for now since we need getaddrinfo() */
+#define _WIN32_WINNT 0x0501
+
 #define PACKAGE "BitlBee"
 #define BITLBEE_VERSION "1.2.1"
@@ -48,7 +51,8 @@
 #include <stdio.h>
 #include <ctype.h>
+#include <errno.h>
+
 #ifndef _WIN32
 #include <syslog.h>
-#include <errno.h>
 #endif
 
Index: conf.c
===================================================================
--- conf.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ conf.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -148,9 +148,8 @@
 		else if( opt == 'R' )
 		{
-			/* We can't load the statefile yet (and should make very sure we do this
-			   only once), so set the filename here and load the state information
-			   when initializing ForkDaemon. (This option only makes sense in that
-			   mode anyway!) */
-			ipc_master_set_statefile( optarg );
+			/* Backward compatibility; older BitlBees passed this
+			   info using a command-line flag. Allow people to
+			   upgrade from such a version for now. */
+			setenv( "_BITLBEE_RESTART_STATE", optarg, 0 );
 		}
 		else if( opt == 'u' )
Index: configure
===================================================================
--- configure	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ configure	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -20,4 +20,5 @@
 ipcsocket='/var/run/bitlbee.sock'
 pcdir='$prefix/lib/pkgconfig'
+systemlibdirs="/lib /usr/lib /usr/local/lib"
 
 msn=1
@@ -109,7 +110,7 @@
 PCDIR=$pcdir
 
+TARGET=$target
 ARCH=$arch
 CPU=$cpu
-OUTFILE=bitlbee
 
 DESTDIR=
@@ -134,10 +135,15 @@
 EOF
 
+
+
 if [ -n "$target" ]; then
-	PKG_CONFIG_PATH=/usr/$target/lib/pkgconfig
+	PKG_CONFIG_LIBDIR=/usr/$target/lib/pkgconfig
+	export PKG_CONFIG_LIBDIR
 	PATH=/usr/$target/bin:$PATH
 	CC=$target-cc
 	LD=$target-ld
-fi
+	systemlibdirs="/usr/$target/lib"
+fi
+
 
 if [ "$debug" = "1" ]; then
@@ -285,4 +291,6 @@
 elif [ "$ssl" = "nss" ]; then
 	detect_nss
+elif [ "$ssl" = "sspi" ]; then
+	echo
 elif [ "$ssl" = "openssl" ]; then
 	echo
@@ -341,5 +349,5 @@
 echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings
 
-for i in /lib /usr/lib /usr/local/lib; do
+for i in $systemlibdirs; do
 	if [ -f $i/libresolv.a ]; then
 		echo '#define HAVE_RESOLV_A' >> config.h
@@ -501,4 +509,6 @@
 	echo 'Cygwin is not officially supported.'
 ;;
+Windows )
+;;
 * )
 	echo 'We haven'\''t tested BitlBee on many platforms yet, yours is untested. YMMV.'
Index: doc/BUILD.win32
===================================================================
--- doc/BUILD.win32	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ doc/BUILD.win32	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -0,0 +1,10 @@
+Instructions for building BitlBee for Windows
+=============================================
+
+1) Install the mingw32 compiler
+
+2) Compile GLib2 for the target i586-mingw32msvc
+
+3) Cross-compile BitlBee:
+
+$ ./configure --target=i586-mingw32msvc --ssl=bogus --arch=Windows
Index: doc/user-guide/commands.xml
===================================================================
--- doc/user-guide/commands.xml	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ doc/user-guide/commands.xml	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -321,10 +321,14 @@
 	</bitlbee-setting>
 
-	<bitlbee-setting name="auto_reconnect_delay" type="integer" scope="global">
-		<default>300</default>
-
-		<description>
-			<para>
-				Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours.
+	<bitlbee-setting name="auto_reconnect_delay" type="string" scope="global">
+		<default>5*3&lt;900</default>
+
+		<description>
+			<para>
+				Tell BitlBee after how many seconds it should attempt to bring a broken IM-connection back up.
+			</para>
+
+			<para>
+				This can be one integer, for a constant delay. One can also set it to something like &quot;10*10&quot;, which means wait for ten seconds on the first reconnect, multiply it by ten on every failure. Once successfully connected, this delay is re-set to the initial value. With &lt; you can give a maximum delay.
 			</para>
 
Index: ipc.c
===================================================================
--- ipc.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ ipc.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -33,5 +33,4 @@
 
 GSList *child_list = NULL;
-static char *statefile = NULL;
 
 static void ipc_master_cmd_client( irc_t *data, char **cmd )
@@ -63,4 +62,23 @@
 }
 
+static void ipc_master_cmd_deaf( irc_t *data, char **cmd )
+{
+	if( global.conf->runmode == RUNMODE_DAEMON )
+	{
+		b_event_remove( global.listen_watch_source_id );
+		close( global.listen_socket );
+		
+		global.listen_socket = global.listen_watch_source_id = -1;
+	
+		ipc_to_children_str( "OPERMSG :Closed listening socket, waiting "
+		                     "for all users to disconnect." );
+	}
+	else
+	{
+		ipc_to_children_str( "OPERMSG :The DEAF command only works in "
+		                     "normal daemon mode. Try DIE instead." );
+	}
+}
+
 void ipc_master_cmd_rehash( irc_t *data, char **cmd )
 {
@@ -98,4 +116,5 @@
 	{ "hello",      0, ipc_master_cmd_client,     0 },
 	{ "die",        0, ipc_master_cmd_die,        0 },
+	{ "deaf",       0, ipc_master_cmd_deaf,       0 },
 	{ "wallops",    1, NULL,                      IPC_CMD_TO_CHILDREN },
 	{ "wall",       1, NULL,                      IPC_CMD_TO_CHILDREN },
@@ -441,4 +460,5 @@
 }
 
+#ifndef _WIN32
 char *ipc_master_save_state()
 {
@@ -481,9 +501,4 @@
 }
 
-void ipc_master_set_statefile( char *fn )
-{
-	statefile = g_strdup( fn );
-}
-
 
 static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond )
@@ -506,5 +521,4 @@
 }
 
-#ifndef _WIN32
 int ipc_master_listen_socket()
 {
@@ -543,8 +557,12 @@
 }
 #else
+int ipc_master_listen_socket()
+{
 	/* FIXME: Open named pipe \\.\BITLBEE */
+	return 0;
+}
 #endif
 
-int ipc_master_load_state()
+int ipc_master_load_state( char *statefile )
 {
 	struct bitlbee_child *child;
@@ -554,4 +572,5 @@
 	if( statefile == NULL )
 		return 0;
+	
 	fp = fopen( statefile, "r" );
 	unlink( statefile );	/* Why do it later? :-) */
Index: ipc.h
===================================================================
--- ipc.h	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ ipc.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -58,6 +58,5 @@
 
 char *ipc_master_save_state();
-void ipc_master_set_statefile( char *fn );
-int ipc_master_load_state();
+int ipc_master_load_state( char *statefile );
 int ipc_master_listen_socket();
 
Index: irc.c
===================================================================
--- irc.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ irc.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -26,4 +26,5 @@
 #define BITLBEE_CORE
 #include "bitlbee.h"
+#include "sock.h"
 #include "crypting.h"
 #include "ipc.h"
@@ -138,5 +139,5 @@
 	set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
 	set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );
-	set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc );
+	set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
 	set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
 	set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
@@ -314,5 +315,9 @@
 	g_free( irc );
 	
-	if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )
+	if( global.conf->runmode == RUNMODE_INETD ||
+	    global.conf->runmode == RUNMODE_FORKDAEMON ||
+	    ( global.conf->runmode == RUNMODE_DAEMON &&
+	      global.listen_socket == -1 &&
+	      irc_connection_list == NULL ) )
 		b_main_quit();
 }
Index: irc_commands.c
===================================================================
--- irc_commands.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ irc_commands.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -626,4 +626,5 @@
 	{ "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
 	{ "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
+	{ "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
 	{ "wallops",     1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
 	{ "wall",        1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
Index: lib/misc.c
===================================================================
--- lib/misc.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ lib/misc.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -373,4 +373,5 @@
 void random_bytes( unsigned char *buf, int count )
 {
+#ifndef _WIN32
 	static int use_dev = -1;
 	
@@ -422,4 +423,5 @@
 	
 	if( !use_dev )
+#endif
 	{
 		int i;
@@ -582,11 +584,7 @@
 	md5_byte_t pass_md5[16];
 	md5_state_t md5_state;
-	int ret, i;
-	
-	if( base64_decode( hash, &pass_dec ) != 21 )
-	{
-		ret = -1;
-	}
-	else
+	int ret = -1, i;
+	
+	if( base64_decode( hash, &pass_dec ) == 21 )
 	{
 		md5_init( &md5_state );
Index: lib/ssl_bogus.c
===================================================================
--- lib/ssl_bogus.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ lib/ssl_bogus.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -61,2 +61,7 @@
 	return GAIM_INPUT_READ;
 }
+
+int ssl_pending( void *conn )
+{
+	return 0;
+}
Index: lib/ssl_sspi.c
===================================================================
--- lib/ssl_sspi.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ lib/ssl_sspi.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -0,0 +1,278 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* SSL module - SSPI backend */
+
+/* Copyright (C) 2005 Jelmer Vernooij <jelmer@samba.org> */
+
+/*
+  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 with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "ssl_client.h"
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <sspi.h>
+#include <schannel.h>
+#include "sock.h"
+
+static gboolean initialized = FALSE;
+int ssl_errno;
+
+struct scd
+{
+	int fd;
+	ssl_input_function func;
+	gpointer data;
+	gboolean established;
+  	CredHandle cred;		/* SSL credentials */
+	CtxtHandle context;		/* SSL context */
+	SecPkgContext_StreamSizes sizes;
+
+	char *host;
+
+	char *pending_raw_data;
+	gsize pending_raw_data_len;
+	char *pending_data;
+	gsize pending_data_len;
+};
+
+static void ssl_connected(gpointer, gint, GaimInputCondition);
+
+void sspi_global_init(void)
+{
+	/* FIXME */
+}
+
+void sspi_global_deinit(void)
+{
+	/* FIXME */
+}
+
+void *ssl_connect(char *host, int port, ssl_input_function func, gpointer data)
+{
+	struct scd *conn = g_new0(struct scd, 1);
+		
+	conn->fd = proxy_connect(host, port, ssl_connected, conn);
+	sock_make_nonblocking(conn->fd);
+	conn->func = func;
+	conn->data = data;
+	conn->host = g_strdup(host);
+	
+	if (conn->fd < 0)
+	{
+		g_free(conn);
+		return NULL;
+	}
+	
+	if (!initialized)
+	{
+		sspi_global_init();
+		initialized = TRUE;
+		atexit(sspi_global_deinit);
+	}
+
+	return conn;
+}
+
+static void ssl_connected(gpointer _conn, gint fd, GaimInputCondition cond)
+{
+	struct scd *conn = _conn;
+	SCHANNEL_CRED ssl_cred;
+	TimeStamp timestamp;
+	SecBuffer ibuf[2],obuf[1];
+	SecBufferDesc ibufs,obufs;
+	ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
+    	ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY |
+      	ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR |
+		ISC_REQ_MANUAL_CRED_VALIDATION;
+	ULONG a;
+	gsize size = 0;
+	gchar *data = NULL;
+
+	memset(&ssl_cred, 0, sizeof(SCHANNEL_CRED));
+	ssl_cred.dwVersion = SCHANNEL_CRED_VERSION;
+	ssl_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
+
+	SECURITY_STATUS st = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ssl_cred, NULL, NULL, &conn->cred, &timestamp);
+
+	if (st != SEC_E_OK) {
+		conn->func(conn->data, NULL, cond);
+		return;
+	}
+	
+	do {
+		/* initialize buffers */
+	    ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = data;
+	    ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NULL;
+	    obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NULL;
+    	ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
+	    ibuf[1].BufferType = SECBUFFER_EMPTY;
+
+		/* initialize buffer descriptors */
+	    ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
+	    ibufs.cBuffers = 2; obufs.cBuffers = 1;
+	    ibufs.pBuffers = ibuf; obufs.pBuffers = obuf;
+
+		st = InitializeSecurityContext(&conn->cred, size?&conn->context:NULL, conn->host, req, 0, SECURITY_NETWORK_DREP, size?&ibufs:NULL, 0, &conn->context, &obufs, &a, &timestamp);  
+    	if (obuf[0].pvBuffer && obuf[0].cbBuffer) {
+			/* FIXME: Check return value */
+			send(conn->fd, obuf[0].pvBuffer, obuf[0].cbBuffer, 0);
+		}
+
+		switch (st) {
+		case SEC_I_INCOMPLETE_CREDENTIALS:
+			break;
+		case SEC_I_CONTINUE_NEEDED:
+			break;
+		case SEC_E_INCOMPLETE_MESSAGE:
+			break;
+		case SEC_E_OK:
+			break;
+		}
+	
+		QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->sizes);
+	} while (1);
+
+	conn->func(conn->data, conn, cond);
+}
+
+int ssl_read(void *conn, char *retdata, int len)
+{
+	struct scd *scd = conn;
+	SecBufferDesc msg;
+	SecBuffer buf[4];
+	int ret = -1, i;
+	char *data = g_malloc(scd->sizes.cbHeader + scd->sizes.cbMaximumMessage + scd->sizes.cbTrailer);
+
+	/* FIXME: Try to read some data */
+
+  	msg.ulVersion = SECBUFFER_VERSION;
+	msg.cBuffers = 4;
+	msg.pBuffers = buf;
+	
+	buf[0].BufferType = SECBUFFER_DATA;
+	buf[0].cbBuffer = len;
+	buf[0].pvBuffer = data;
+
+	buf[1].BufferType = SECBUFFER_EMPTY;
+	buf[2].BufferType = SECBUFFER_EMPTY;
+	buf[3].BufferType = SECBUFFER_EMPTY;
+
+	SECURITY_STATUS st = DecryptMessage(&scd->context, &msg, 0, NULL);
+
+	if (st != SEC_E_OK) {
+		/* FIXME */
+		return -1;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (buf[i].BufferType == SECBUFFER_DATA) {
+			memcpy(retdata, buf[i].pvBuffer, len);
+			ret = len;
+		}	
+	}
+
+	g_free(data);
+	return -1;
+}
+
+int ssl_write(void *conn, const char *userdata, int len)
+{
+	struct scd *scd = conn;
+	SecBuffer buf[4];
+	SecBufferDesc msg;
+	char *data;
+	int ret;
+
+	msg.ulVersion = SECBUFFER_VERSION;
+	msg.cBuffers = 4;
+	msg.pBuffers = buf;
+
+	data = g_malloc(scd->sizes.cbHeader + scd->sizes.cbMaximumMessage + scd->sizes.cbTrailer);
+	memcpy(data + scd->sizes.cbHeader, userdata, len);
+
+	buf[0].BufferType = SECBUFFER_STREAM_HEADER;
+	buf[0].cbBuffer = scd->sizes.cbHeader;
+	buf[0].pvBuffer = data;
+
+	buf[1].BufferType = SECBUFFER_DATA;
+	buf[1].cbBuffer = len;
+	buf[1].pvBuffer = data + scd->sizes.cbHeader;
+
+	buf[2].BufferType = SECBUFFER_STREAM_TRAILER;
+	buf[2].cbBuffer = scd->sizes.cbTrailer;
+	buf[2].pvBuffer = data + scd->sizes.cbHeader + len;
+	buf[3].BufferType = SECBUFFER_EMPTY;
+
+	SECURITY_STATUS st = EncryptMessage(&scd->context, 0, &msg, 0);
+
+	ret = send(scd->fd, data, 
+				buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer, 0);
+
+	g_free(data);
+
+	return ret;
+}
+
+void ssl_disconnect(void *conn)
+{
+	struct scd *scd = conn;
+
+	SecBufferDesc msg;
+	SecBuffer buf;
+	DWORD dw;
+
+	dw = SCHANNEL_SHUTDOWN;
+	buf.cbBuffer = sizeof(dw);
+	buf.BufferType = SECBUFFER_TOKEN;
+	buf.pvBuffer = &dw;
+	
+	msg.ulVersion = SECBUFFER_VERSION;
+	msg.cBuffers = 1;
+	msg.pBuffers = &buf;
+
+	SECURITY_STATUS st = ApplyControlToken(&scd->context, &msg);
+
+	if (st != SEC_E_OK) {
+		/* FIXME */
+	}
+	
+	/* FIXME: call InitializeSecurityContext(Schannel), passing 
+	 * in empty buffers*/
+
+	DeleteSecurityContext(&scd->context);
+
+	FreeCredentialsHandle(&scd->cred);
+
+	closesocket(scd->fd);
+	g_free(scd->host);
+	g_free(scd);
+}
+
+int ssl_getfd(void *conn)
+{
+	return ((struct scd*)conn)->fd;
+}
+
+GaimInputCondition ssl_getdirection( void *conn )
+{
+	return GAIM_INPUT_WRITE; /* FIXME: or GAIM_INPUT_READ */
+}
Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/msn/msn.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -113,5 +113,4 @@
 {
 	struct msn_switchboard *sb;
-	struct msn_data *md = ic->proto_data;
 	
 	if( ( sb = msn_sb_by_handle( ic, who ) ) )
@@ -122,5 +121,4 @@
 	{
 		struct msn_message *m;
-		char buf[1024];
 		
 		/* Create a message. We have to arrange a usable switchboard, and send the message later. */
@@ -129,38 +127,5 @@
 		m->text = g_strdup( message );
 		
-		/* FIXME: *CHECK* the reliability of using spare sb's! */
-		if( ( sb = msn_sb_spare( ic ) ) )
-		{
-			debug( "Trying to use a spare switchboard to message %s", who );
-			
-			sb->who = g_strdup( who );
-			g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who );
-			if( msn_sb_write( sb, buf, strlen( buf ) ) )
-			{
-				/* He/She should join the switchboard soon, let's queue the message. */
-				sb->msgq = g_slist_append( sb->msgq, m );
-				return( 1 );
-			}
-		}
-		
-		debug( "Creating a new switchboard to message %s", who );
-		
-		/* If we reach this line, there was no spare switchboard, so let's make one. */
-		g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
-		if( !msn_write( ic, buf, strlen( buf ) ) )
-		{
-			g_free( m->who );
-			g_free( m->text );
-			g_free( m );
-			
-			return( 0 );
-		}
-		
-		/* And queue the message to md. We'll pick it up when the switchboard comes up. */
-		md->msgq = g_slist_append( md->msgq, m );
-		
-		/* FIXME: If the switchboard creation fails, the message will not be sent. */
-		
-		return( 1 );
+		return msn_sb_write_msg( ic, m );
 	}
 	
@@ -252,6 +217,4 @@
 {
 	struct msn_switchboard *sb;
-	struct msn_data *md = ic->proto_data;
-	char buf[1024];
 	
 	if( ( sb = msn_sb_by_handle( ic, who ) ) )
@@ -263,20 +226,4 @@
 	{
 		struct msn_message *m;
-		
-		if( ( sb = msn_sb_spare( ic ) ) )
-		{
-			debug( "Trying to reuse an existing switchboard as a groupchat with %s", who );
-			g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who );
-			if( msn_sb_write( sb, buf, strlen( buf ) ) )
-				return msn_sb_to_chat( sb );
-		}
-		
-		/* If the stuff above failed for some reason: */
-		debug( "Creating a new switchboard to groupchat with %s", who );
-		
-		/* Request a new switchboard. */
-		g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
-		if( !msn_write( ic, buf, strlen( buf ) ) )
-			return( 0 );
 		
 		/* Create a magic message. This is quite hackish, but who cares? :-P */
@@ -285,8 +232,6 @@
 		m->text = g_strdup( GROUPCHAT_SWITCHBOARD_MESSAGE );
 		
-		/* Queue the magic message and cross your fingers. */
-		md->msgq = g_slist_append( md->msgq, m );
-		
-		/* FIXME: Can I try to return something here already? */
+		msn_sb_write_msg( ic, m );
+
 		return NULL;
 	}
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/msn/msn.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -23,4 +23,7 @@
   Suite 330, Boston, MA  02111-1307  USA
 */
+
+#ifndef _MSN_H
+#define _MSN_H
 
 /* Some hackish magicstrings to make special-purpose messages/switchboards.
@@ -176,2 +179,5 @@
 void msn_sb_destroy( struct msn_switchboard *sb );
 gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond );
+int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m );
+
+#endif //_MSN_H
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/msn/ns.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -278,9 +278,23 @@
 		if( num_parts == 5 )
 		{
+			int i, groupcount;
+			
+			groupcount = atoi( cmd[4] );
+			if( groupcount > 0 )
+			{
+				/* valgrind says this is leaking memory, I'm guessing
+				   that this happens during server redirects. */
+				if( md->grouplist )
+				{
+					for( i = 0; i < md->groupcount; i ++ )
+						g_free( md->grouplist[i] );
+					g_free( md->grouplist );
+				}
+				
+				md->groupcount = groupcount;
+				md->grouplist = g_new0( char *, md->groupcount );
+			}
+			
 			md->buddycount = atoi( cmd[3] );
-			md->groupcount = atoi( cmd[4] );
-			if( md->groupcount > 0 )
-				md->grouplist = g_new0( char *, md->groupcount );
-			
 			if( !*cmd[3] || md->buddycount == 0 )
 				msn_logged_in( ic );
@@ -665,4 +679,7 @@
 					imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );
 				}
+				
+				g_free( inbox );
+				g_free( folders );
 			}
 			else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )
Index: protocols/msn/sb.c
===================================================================
--- protocols/msn/sb.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/msn/sb.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -44,4 +44,46 @@
 		return( 0 );
 	}
+	
+	return( 1 );
+}
+
+int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m )
+{
+	struct msn_data *md = ic->proto_data;
+	struct msn_switchboard *sb;
+	char buf[1024];
+
+	/* FIXME: *CHECK* the reliability of using spare sb's! */
+	if( ( sb = msn_sb_spare( ic ) ) )
+	{
+		debug( "Trying to use a spare switchboard to message %s", m->who );
+		
+		sb->who = g_strdup( m->who );
+		g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, m->who );
+		if( msn_sb_write( sb, buf, strlen( buf ) ) )
+		{
+			/* He/She should join the switchboard soon, let's queue the message. */
+			sb->msgq = g_slist_append( sb->msgq, m );
+			return( 1 );
+		}
+	}
+	
+	debug( "Creating a new switchboard to message %s", m->who );
+	
+	/* If we reach this line, there was no spare switchboard, so let's make one. */
+	g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
+	if( !msn_write( ic, buf, strlen( buf ) ) )
+	{
+		g_free( m->who );
+		g_free( m->text );
+		g_free( m );
+		
+		return( 0 );
+	}
+	
+	/* And queue the message to md. We'll pick it up when the switchboard comes up. */
+	md->msgq = g_slist_append( md->msgq, m );
+	
+	/* FIXME: If the switchboard creation fails, the message will not be sent. */
 	
 	return( 1 );
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/nogaim.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -267,4 +267,8 @@
 	   protocols. */
 	imc_set_away( ic, u->away );
+	
+	/* Apparently we're connected successfully, so reset the
+	   exponential backoff timer. */
+	ic->acc->auto_reconnect_delay = 0;
 }
 
@@ -290,4 +294,5 @@
 	user_t *t, *u;
 	account_t *a;
+	int delay;
 	
 	/* Nested calls might happen sometimes, this is probably the best
@@ -329,8 +334,7 @@
 	}
 	else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) &&
-	         set_getbool( &a->set, "auto_reconnect" ) )
-	{
-		int delay = set_getint( &irc->set, "auto_reconnect_delay" );
-		
+	         set_getbool( &a->set, "auto_reconnect" ) &&
+	         ( delay = account_reconnect_delay( a ) ) > 0 )
+	{
 		imcb_log( ic, "Reconnecting in %d seconds..", delay );
 		a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a );
Index: protocols/yahoo/libyahoo2.c
===================================================================
--- protocols/yahoo/libyahoo2.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/yahoo/libyahoo2.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -69,6 +69,4 @@
 #ifdef __MINGW32__
 # include <winsock2.h>
-# define write(a,b,c) send(a,b,c,0)
-# define read(a,b,c)  recv(a,b,c,0)
 #endif
 
Index: protocols/yahoo/yahoo.c
===================================================================
--- protocols/yahoo/yahoo.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/yahoo/yahoo.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -665,7 +665,4 @@
 	
 	imcb_error( ic, "%s", err );
-	
-	if( fatal )
-		imc_logout( ic, TRUE );
 }
 
Index: protocols/yahoo/yahoo_httplib.c
===================================================================
--- protocols/yahoo/yahoo_httplib.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ protocols/yahoo/yahoo_httplib.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -51,6 +51,4 @@
 #ifdef __MINGW32__
 # include <winsock2.h>
-# define write(a,b,c) send(a,b,c,0)
-# define read(a,b,c)  recv(a,b,c,0)
 # define snprintf _snprintf
 #endif
Index: sock.h
===================================================================
--- sock.h	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ sock.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -16,15 +16,9 @@
 #else
 # include <winsock2.h>
-# ifndef _MSC_VER
-#  include <ws2tcpip.h>
-# endif
+# include <ws2tcpip.h>
 # if !defined(BITLBEE_CORE) && defined(_MSC_VER)
 #   pragma comment(lib,"bitlbee.lib")
 # endif
 # include <io.h>
-# define read(a,b,c) recv(a,b,c,0)
-# define write(a,b,c) send(a,b,c,0)
-# define umask _umask
-# define mode_t int
 # define sock_make_nonblocking(fd) { int non_block = 1; ioctlsocket(fd, FIONBIO, &non_block); }
 # define sock_make_blocking(fd) { int non_block = 0; ioctlsocket(fd, FIONBIO, &non_block); }
Index: storage_text.c
===================================================================
--- storage_text.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ storage_text.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -27,4 +27,12 @@
 #include "bitlbee.h"
 #include "crypting.h"
+#ifdef _WIN32
+# define umask _umask
+# define mode_t int
+#endif
+
+#ifndef F_OK
+#define F_OK 0
+#endif
 
 static void text_init (void)
Index: storage_xml.c
===================================================================
--- storage_xml.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ storage_xml.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -30,4 +30,12 @@
 #include "md5.h"
 #include <glib/gstdio.h>
+
+#if GLIB_CHECK_VERSION(2,8,0)
+#include <glib/gstdio.h>
+#else
+/* GLib < 2.8.0 doesn't have g_access, so just use the system access(). */
+#include <unistd.h>
+#define g_access access
+#endif
 
 typedef enum
@@ -244,7 +252,8 @@
 static void xml_init( void )
 {
-	if( ! g_file_test( global.conf->configdir, G_FILE_TEST_EXISTS ) )
+	if( g_access( global.conf->configdir, F_OK ) != 0 )
 		log_message( LOGLVL_WARNING, "The configuration directory `%s' does not exist. Configuration won't be saved.", global.conf->configdir );
-	else if( ! g_file_test( global.conf->configdir, G_FILE_TEST_EXISTS ) || g_access( global.conf->configdir, W_OK ) != 0 )
+	else if( g_access( global.conf->configdir, F_OK ) != 0 || 
+	         g_access( global.conf->configdir, W_OK ) != 0 )
 		log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to `%s'.", global.conf->configdir );
 }
@@ -373,5 +382,5 @@
 	g_free( path2 );
 	
-	if( !overwrite && g_file_test( path, G_FILE_TEST_EXISTS ) )
+	if( !overwrite && g_access( path, F_OK ) == 0 )
 		return STORAGE_ALREADY_EXISTS;
 	
@@ -481,5 +490,5 @@
 static storage_status_t xml_remove( const char *nick, const char *password )
 {
-	char s[512];
+	char s[512], *lc;
 	storage_status_t status;
 
@@ -488,5 +497,9 @@
 		return status;
 
-	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".xml" );
+	lc = g_strdup( nick );
+	nick_lc( lc );
+	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, lc, ".xml" );
+	g_free( lc );
+	
 	if( unlink( s ) == -1 )
 		return STORAGE_OTHER_ERROR;
Index: unix.c
===================================================================
--- unix.c	(revision d301872cbf032a56c946cb92fa11b511aff3f243)
+++ unix.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -40,5 +40,5 @@
 static void sighandler( int signal );
 
-int main( int argc, char *argv[], char **envp )
+int main( int argc, char *argv[] )
 {
 	int i = 0;
@@ -60,4 +60,7 @@
 	if( global.conf->runmode == RUNMODE_INETD )
 	{
+		log_link( LOGLVL_ERROR, LOGOUTPUT_IRC );
+		log_link( LOGLVL_WARNING, LOGOUTPUT_IRC );
+	
 		i = bitlbee_inetd_init();
 		log_message( LOGLVL_INFO, "Bitlbee %s starting in inetd mode.", BITLBEE_VERSION );
@@ -66,4 +69,7 @@
 	else if( global.conf->runmode == RUNMODE_DAEMON )
 	{
+		log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG );
+		log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG );
+
 		i = bitlbee_daemon_init();
 		log_message( LOGLVL_INFO, "Bitlbee %s starting in daemon mode.", BITLBEE_VERSION );
@@ -135,28 +141,17 @@
 	{
 		char *fn = ipc_master_save_state();
-		char **args;
-		int n, i;
 		
 		chdir( old_cwd );
 		
-		n = 0;
-		args = g_new0( char *, argc + 3 );
-		args[n++] = argv[0];
-		if( fn )
-		{
-			args[n++] = "-R";
-			args[n++] = fn;
-		}
-		for( i = 1; argv[i] && i < argc; i ++ )
-		{
-			if( strcmp( argv[i], "-R" ) == 0 )
-				i += 2;
-			
-			args[n++] = argv[i];
-		}
+		setenv( "_BITLBEE_RESTART_STATE", fn, 1 );
+		g_free( fn );
 		
 		close( global.listen_socket );
 		
-		execve( args[0], args, envp );
+		if( execv( argv[0], argv ) == -1 )
+			/* Apparently the execve() failed, so let's just
+			   jump back into our own/current main(). */
+			/* Need more cleanup code to make this work. */
+			return 1; /* main( argc, argv ); */
 	}
 	
@@ -219,2 +214,4 @@
 	return( (double) time->tv_sec + (double) time->tv_usec / 1000000 );
 }
+
+
Index: win32.c
===================================================================
--- win32.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ win32.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
@@ -0,0 +1,332 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway					 *
+  *																	*
+  * Copyright 2002-2004 Wilmer van der Gaast and others				*
+  \********************************************************************/
+
+/* Main file (Windows specific part)								   */
+
+/*
+  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 with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define BITLBEE_CORE
+#include "bitlbee.h"
+#include "commands.h"
+#include "crypting.h"
+#include "protocols/nogaim.h"
+#include "help.h"
+#include <signal.h>
+#include <windows.h>
+
+global_t global;	/* Against global namespace pollution */
+
+static void WINAPI service_ctrl (DWORD dwControl)
+{
+	switch (dwControl)
+	{
+		case SERVICE_CONTROL_STOP:
+			/* FIXME */
+			break;
+
+		case SERVICE_CONTROL_INTERROGATE:
+			break;
+
+		default:
+			break;
+
+	}
+}
+
+static void bitlbee_init(int argc, char **argv)
+{
+	int i = -1;
+	memset( &global, 0, sizeof( global_t ) );
+
+	b_main_init();
+	
+	global.conf = conf_load( argc, argv );
+	if( global.conf == NULL )
+		return;
+	
+	if( global.conf->runmode == RUNMODE_INETD )
+	{
+		i = bitlbee_inetd_init();
+		log_message( LOGLVL_INFO, "Bitlbee %s starting in inetd mode.", BITLBEE_VERSION );
+
+	}
+	else if( global.conf->runmode == RUNMODE_DAEMON )
+	{
+		i = bitlbee_daemon_init();
+		log_message( LOGLVL_INFO, "Bitlbee %s starting in daemon mode.", BITLBEE_VERSION );
+	} 
+	else 
+	{
+		log_message( LOGLVL_INFO, "No bitlbee mode specified...");
+	}
+	
+	if( i != 0 )
+		return;
+ 	
+	if( access( global.conf->configdir, F_OK ) != 0 )
+		log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", global.conf->configdir );
+	else if( access( global.conf->configdir, 06 ) != 0 )
+		log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
+	if( help_init( &(global.help), HELP_FILE ) == NULL )
+		log_message( LOGLVL_WARNING, "Error opening helpfile %s.", global.helpfile );
+}
+
+void service_main (DWORD argc, LPTSTR *argv)
+{
+	SERVICE_STATUS_HANDLE handle;
+	SERVICE_STATUS status;
+
+	handle = RegisterServiceCtrlHandler("bitlbee", service_ctrl);
+
+	if (!handle)
+		return;
+
+	status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+	status.dwServiceSpecificExitCode = 0;
+
+	bitlbee_init(argc, argv);
+
+	SetServiceStatus(handle, &status);
+	
+	b_main_run( );
+}
+
+SERVICE_TABLE_ENTRY dispatch_table[] =
+{
+   { TEXT("bitlbee"), (LPSERVICE_MAIN_FUNCTION)service_main },
+   { NULL, NULL }
+};
+
+static int debug = 0;
+
+static void usage()
+{
+	printf("Options:\n");
+	printf("-h   Show this help message\n");
+	printf("-d   Debug mode (simple console program)\n");
+}
+
+int main( int argc, char **argv)
+{	
+	int i;
+	WSADATA WSAData;
+
+	nogaim_init( );
+
+	for (i = 1; i < argc; i++) {
+		if (!strcmp(argv[i], "-d")) debug = 1;
+		if (!strcmp(argv[i], "-h")) {
+			usage();
+			return 0;
+		}
+	}
+
+	WSAStartup(MAKEWORD(1,1), &WSAData);
+
+	if (!debug) {
+		if (!StartServiceCtrlDispatcher(dispatch_table))
+			log_message( LOGLVL_ERROR, "StartServiceCtrlDispatcher failed.");
+	} else {
+			bitlbee_init(argc, argv);
+ 			b_main_run();
+	}
+	
+	return 0;
+}
+
+double gettime()
+{
+	return (GetTickCount() / 1000);
+}
+
+void conf_get_string(HKEY section, const char *name, const char *def, char **dest)
+{
+	char buf[4096];
+	long x;
+	if (RegQueryValue(section, name, buf, &x) == ERROR_SUCCESS) {
+		*dest = g_strdup(buf);
+	} else if (!def) {
+		*dest = NULL;
+	} else {
+		*dest = g_strdup(def);
+	}
+}
+
+
+void conf_get_int(HKEY section, const char *name, int def, int *dest)
+{
+	char buf[20];
+	long x;
+	DWORD y;
+	if (RegQueryValue(section, name, buf, &x) == ERROR_SUCCESS) {
+		memcpy(&y, buf, sizeof(DWORD));
+		*dest = y;
+	} else {
+		*dest = def;
+	}
+}
+
+conf_t *conf_load( int argc, char *argv[] ) 
+{
+	conf_t *conf;
+	HKEY key, key_main, key_proxy;
+	char *tmp;
+
+	RegOpenKey(HKEY_CURRENT_USER, "SOFTWARE\\Bitlbee", &key);
+	RegOpenKey(key, "main", &key_main);
+	RegOpenKey(key, "proxy", &key_proxy);
+	
+	memset( &global, 0, sizeof( global_t ) );
+	b_main_init();
+
+	conf = g_new0( conf_t,1 );
+	global.conf = conf;
+	conf_get_string(key_main, "interface_in", "0.0.0.0", &global.conf->iface_in);
+	conf_get_string(key_main, "interface_out", "0.0.0.0", &global.conf->iface_out);
+	conf_get_string(key_main, "port", "6667", &global.conf->port);
+	conf_get_int(key_main, "verbose", 0, &global.conf->verbose);
+	conf_get_string(key_main, "auth_pass", "", &global.conf->auth_pass);
+	conf_get_string(key_main, "oper_pass", "", &global.conf->oper_pass);
+	conf_get_int(key_main, "ping_interval_timeout", 60, &global.conf->ping_interval);
+	conf_get_string(key_main, "hostname", "localhost", &global.conf->hostname);
+	conf_get_string(key_main, "configdir", NULL, &global.conf->configdir);
+	conf_get_string(key_main, "motdfile", NULL, &global.conf->motdfile);
+	conf_get_string(key_main, "helpfile", NULL, &global.helpfile);
+	global.conf->runmode = RUNMODE_DAEMON;
+	conf_get_int(key_main, "AuthMode", AUTHMODE_OPEN, (int *)&global.conf->authmode);
+	conf_get_string(key_proxy, "host", "", &tmp); strcpy(proxyhost, tmp);
+	conf_get_string(key_proxy, "user", "", &tmp); strcpy(proxyuser, tmp);
+	conf_get_string(key_proxy, "password", "", &tmp); strcpy(proxypass, tmp);
+	conf_get_int(key_proxy, "type", PROXY_NONE, &proxytype);
+	conf_get_int(key_proxy, "port", 3128, &proxyport);
+
+	RegCloseKey(key);
+	RegCloseKey(key_main);
+	RegCloseKey(key_proxy);
+
+	return conf;
+}
+
+void conf_loaddefaults( irc_t *irc )
+{
+	HKEY key_defaults;
+	int i;
+	char name[4096], data[4096];
+	DWORD namelen = sizeof(name), datalen = sizeof(data);
+	DWORD type;
+	if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Bitlbee\\defaults", &key_defaults) != ERROR_SUCCESS) {
+		return;
+	}
+
+	for (i = 0; RegEnumValue(key_defaults, i, name, &namelen, NULL, &type, data, &datalen) == ERROR_SUCCESS; i++) {
+		set_t *s = set_find( &irc->set, name );
+			
+		if( s )
+		{
+			if( s->def ) g_free( s->def );
+			s->def = g_strdup( data );
+		}
+
+		namelen = sizeof(name);
+		datalen = sizeof(data);
+	}
+
+	RegCloseKey(key_defaults);
+}
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+  addr->s_addr = inet_addr(cp);
+  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+}
+
+void log_error(char *msg)
+{
+	log_message(LOGLVL_ERROR, "%s", msg);
+}
+
+void log_message(int level, char *message, ...)
+{
+	HANDLE  hEventSource;
+	LPTSTR  lpszStrings[2];
+	WORD elevel;
+	va_list ap;
+
+	va_start(ap, message);
+
+	if (debug) {
+		vprintf(message, ap);
+		putchar('\n');
+		va_end(ap);
+		return;
+	}
+
+	hEventSource = RegisterEventSource(NULL, TEXT("bitlbee"));
+
+	lpszStrings[0] = TEXT("bitlbee");
+	lpszStrings[1] = g_strdup_vprintf(message, ap);
+	va_end(ap);
+
+	switch (level) {
+	case LOGLVL_ERROR: elevel = EVENTLOG_ERROR_TYPE; break;
+	case LOGLVL_WARNING: elevel = EVENTLOG_WARNING_TYPE; break;
+	case LOGLVL_INFO: elevel = EVENTLOG_INFORMATION_TYPE; break;
+#ifdef DEBUG
+	case LOGLVL_DEBUG: elevel = EVENTLOG_AUDIT_SUCCESS; break;
+#endif
+	}
+
+	if (hEventSource != NULL) {
+		ReportEvent(hEventSource, 
+		elevel,
+		0,					
+		0,					
+		NULL,				 
+		2,					
+		0,					
+		lpszStrings,		  
+		NULL);				
+
+		DeregisterEventSource(hEventSource);
+	}
+
+	g_free(lpszStrings[1]);
+}
+
+void log_link(int level, int output) { /* FIXME */ }
+
+struct tm *
+gmtime_r (const time_t *timer, struct tm *result)
+{
+	struct tm *local_result;
+	local_result = gmtime (timer);
+
+	if (local_result == NULL || result == NULL)
+		return NULL;
+
+	memcpy (result, local_result, sizeof (result));
+	return result;
+} 
