diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 8eb7777774..4b06385c9a 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -4,7 +4,7 @@
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.16 2004/06/11 16:36:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.17 2004/06/24 18:23:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,7 +52,10 @@ typedef enum
 	RESTART_COMMAND,
 	RELOAD_COMMAND,
 	STATUS_COMMAND,
-	KILL_COMMAND
+	KILL_COMMAND,
+	REGISTER_COMMAND,
+	UNREGISTER_COMMAND,
+	RUN_AS_SERVICE_COMMAND
 }	CtlCommand;
 
 
@@ -63,14 +66,20 @@ static bool silence_echo = false;
 static ShutdownMode shutdown_mode = SMART_MODE;
 static int	sig = SIGTERM;	/* default */
 static CtlCommand ctl_command = NO_COMMAND;
-static char *pg_data_opts = NULL;
 static char *pg_data = NULL;
 static char *post_opts = NULL;
 static const char *progname;
 static char *log_file = NULL;
 static char *postgres_path = NULL;
+static char *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */
+static char *register_username = NULL;
+static char *register_password = NULL;
 static char *argv0 = NULL;
 
+static void write_stderr(const char *fmt,...)
+/* This extension allows gcc to check the format string for consistency with
+   the supplied arguments. */
+__attribute__((format(printf, 1, 2)));
 static void *xmalloc(size_t size);
 static char *xstrdup(const char *s);
 static void do_advice(void);
@@ -83,6 +92,16 @@ static void do_restart(void);
 static void do_reload(void);
 static void do_status(void);
 static void do_kill(pgpid_t pid);
+#ifdef WIN32
+static bool  pgwin32_IsInstalled(SC_HANDLE);
+static char* pgwin32_CommandLine(bool);
+static void pgwin32_doRegister();
+static void pgwin32_doUnregister();
+static void pgwin32_SetServiceStatus(DWORD);
+static void WINAPI pgwin32_ServiceHandler(DWORD);
+static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR*);
+static void pgwin32_doRunAsService();
+#endif
 static pgpid_t get_pgpid(void);
 static char **readfile(char *path);
 static int start_postmaster(void);
@@ -93,6 +112,63 @@ static char postopts_file[MAXPGPATH];
 static char pid_file[MAXPGPATH];
 static char conf_file[MAXPGPATH];
 
+
+#ifdef WIN32
+static void
+write_eventlog(int level, const char *line)
+{
+	static HANDLE evtHandle = INVALID_HANDLE_VALUE;
+
+	if (evtHandle == INVALID_HANDLE_VALUE) {
+		evtHandle = RegisterEventSource(NULL,"PostgreSQL");
+		if (evtHandle == NULL) {
+			evtHandle = INVALID_HANDLE_VALUE;
+			return;
+		}
+	}
+
+	ReportEvent(evtHandle,
+				level,
+				0,
+				0, /* All events are Id 0 */
+				NULL,
+				1,
+				0,
+				&line,
+				NULL);
+}
+#endif
+
+/*
+ * Write errors to stderr (or by equal means when stderr is
+ * not available).
+ */
+static void
+write_stderr(const char *fmt,...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+#ifndef WIN32
+	/* On Unix, we just fprintf to stderr */
+	vfprintf(stderr, fmt, ap);
+#else
+	/* On Win32, we print to stderr if running on a console, or write to
+	 * eventlog if running as a service */
+	if (!isatty(fileno(stderr))) /* Running as a service */
+	{
+		char errbuf[2048]; /* Arbitrary size? */
+
+		vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
+
+		write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
+	}
+	else /* Not running as service, write to stderr */
+		vfprintf(stderr, fmt, ap);
+#endif
+	va_end(ap);
+}
+
 /*
  * routines to check memory allocations and fail noisily.
  */
@@ -105,7 +181,7 @@ xmalloc(size_t size)
 	result = malloc(size);
 	if (!result)
 	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
+		write_stderr(_("%s: out of memory\n"), progname);
 		exit(1);
 	}
 	return result;
@@ -121,7 +197,7 @@ xstrdup(const char *s)
 	result = strdup(s);
 	if (!result)
 	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
+		write_stderr(_("%s: out of memory\n"), progname);
 		exit(1);
 	}
 	return result;
@@ -352,10 +428,9 @@ do_start(void)
 	{
 		old_pid = get_pgpid();
 		if (old_pid != 0)
-			fprintf(stderr,
-					_("%s: Another postmaster may be running. "
-					"Trying to start postmaster anyway.\n"),
-					progname);
+			write_stderr(_("%s: Another postmaster may be running. "
+						   "Trying to start postmaster anyway.\n"),
+						 progname);
 	}
 
 	if (post_opts == NULL)
@@ -371,13 +446,13 @@ do_start(void)
 				post_opts = "";
 			else
 			{
-				fprintf(stderr, _("%s: cannot read %s\n"), progname, postopts_file);
+				write_stderr(_("%s: cannot read %s\n"), progname, postopts_file);
 				exit(1);
 			}
 		}
 		else if (optlines[0] == NULL || optlines[1] != NULL)
 		{
-			fprintf(stderr, _("%s: option file %s must have exactly 1 line\n"),
+			write_stderr(_("%s: option file %s must have exactly 1 line\n"),
 					progname, ctl_command == RESTART_COMMAND ?
 					postopts_file : def_postopts_file);
 			exit(1);
@@ -419,18 +494,16 @@ do_start(void)
 								   postmaster_path)) < 0)
 		{
 			if (ret == -1)
-				fprintf(stderr,
-						_("The program \"postmaster\" is needed by %s "
-						  "but was not found in the same directory as "
-						  "\"%s\".\n"
-						  "Check your installation.\n"),
-						progname, progname);
+				write_stderr(_("The program \"postmaster\" is needed by %s "
+							   "but was not found in the same directory as "
+							   "\"%s\".\n"
+							   "Check your installation.\n"),
+							 progname, progname);
 			else
-				fprintf(stderr,
-						_("The program \"postmaster\" was found by %s "
-						  "but was not the same version as \"%s\".\n"
-						  "Check your installation.\n"),
-						progname, progname);
+				write_stderr(_("The program \"postmaster\" was found by %s "
+							   "but was not the same version as \"%s\".\n"
+							   "Check your installation.\n"),
+							 progname, progname);
 			exit(1);
 		}
 		postgres_path = postmaster_path;
@@ -438,7 +511,7 @@ do_start(void)
 
 	if (start_postmaster() != 0)
 	{
-		fprintf(stderr, _("Unable to run the postmaster binary\n"));
+		write_stderr(_("Unable to run the postmaster binary\n"));
 		exit(1);
 	}
 
@@ -448,10 +521,9 @@ do_start(void)
 		pid = get_pgpid();
 		if (pid == old_pid)
 		{
-			fprintf(stderr,
-					_("%s: cannot start postmaster\n"
-					"Examine the log output\n"),
-					progname);
+			write_stderr(_("%s: cannot start postmaster\n"
+						   "Examine the log output\n"),
+						 progname);
 			exit(1);
 		}
 	}
@@ -485,23 +557,22 @@ do_stop(void)
 
 	if (pid == 0)				/* no pid file */
 	{
-		fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file);
-		fprintf(stderr, _("Is postmaster running?\n"));
+		write_stderr(_("%s: could not find %s\n"), progname, pid_file);
+		write_stderr(_("Is postmaster running?\n"));
 		exit(1);
 	}
 	else if (pid < 0)			/* standalone backend, not postmaster */
 	{
 		pid = -pid;
-		fprintf(stderr,
-				_("%s: cannot stop postmaster; "
-				"postgres is running (PID: %ld)\n"),
-				progname, pid);
+		write_stderr(_("%s: cannot stop postmaster; "
+					   "postgres is running (PID: %ld)\n"),
+					 progname, pid);
 		exit(1);
 	}
 
 	if (kill((pid_t) pid, sig) != 0)
 	{
-		fprintf(stderr, _("stop signal failed (PID: %ld): %s\n"), pid,
+		write_stderr(_("stop signal failed (PID: %ld): %s\n"), pid,
 				strerror(errno));
 		exit(1);
 	}
@@ -540,7 +611,7 @@ do_stop(void)
 			if (!silence_echo)
 				printf(_(" failed\n"));
 	
-			fprintf(stderr, _("%s: postmaster does not shut down\n"), progname);
+			write_stderr(_("%s: postmaster does not shut down\n"), progname);
 			exit(1);
 		}
 		if (!silence_echo)
@@ -565,25 +636,24 @@ do_restart(void)
 
 	if (pid == 0)				/* no pid file */
 	{
-		fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file);
-		fprintf(stderr, _("Is postmaster running?\nstarting postmaster anyway\n"));
+		write_stderr(_("%s: could not find %s\n"), progname, pid_file);
+		write_stderr(_("Is postmaster running?\nstarting postmaster anyway\n"));
 		do_start();
 		return;
 	}
 	else if (pid < 0)			/* standalone backend, not postmaster */
 	{
 		pid = -pid;
-		fprintf(stderr,
-				_("%s: cannot restart postmaster; "
-				"postgres is running (PID: %ld)\n"),
-				progname, pid);
-		fprintf(stderr, _("Please terminate postgres and try again.\n"));
+		write_stderr(_("%s: cannot restart postmaster; "
+					   "postgres is running (PID: %ld)\n"),
+					 progname, pid);
+		write_stderr(_("Please terminate postgres and try again.\n"));
 		exit(1);
 	}
 
 	if (kill((pid_t) pid, sig) != 0)
 	{
-		fprintf(stderr, _("stop signal failed (PID: %ld): %s\n"), pid,
+		write_stderr(_("stop signal failed (PID: %ld): %s\n"), pid,
 				strerror(errno));
 		exit(1);
 	}
@@ -616,7 +686,7 @@ do_restart(void)
 		if (!silence_echo)
 			printf(_(" failed\n"));
 
-		fprintf(stderr, _("%s: postmaster does not shut down\n"), progname);
+		write_stderr(_("%s: postmaster does not shut down\n"), progname);
 		exit(1);
 	}
 
@@ -636,24 +706,23 @@ do_reload(void)
 	pid = get_pgpid();
 	if (pid == 0)				/* no pid file */
 	{
-		fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file);
-		fprintf(stderr, _("Is postmaster running?\n"));
+		write_stderr(_("%s: could not find %s\n"), progname, pid_file);
+		write_stderr(_("Is postmaster running?\n"));
 		exit(1);
 	}
 	else if (pid < 0)			/* standalone backend, not postmaster */
 	{
 		pid = -pid;
-		fprintf(stderr,
-				_("%s: cannot reload postmaster; "
-				"postgres is running (PID: %ld)\n"),
-				progname, pid);
-		fprintf(stderr, _("Please terminate postgres and try again.\n"));
+		write_stderr(_("%s: cannot reload postmaster; "
+					   "postgres is running (PID: %ld)\n"),
+					 progname, pid);
+		write_stderr(_("Please terminate postgres and try again.\n"));
 		exit(1);
 	}
 
 	if (kill((pid_t) pid, sig) != 0)
 	{
-		fprintf(stderr, _("reload signal failed (PID: %ld): %s\n"), pid,
+		write_stderr(_("reload signal failed (PID: %ld): %s\n"), pid,
 				strerror(errno));
 		exit(1);
 	}
@@ -674,7 +743,7 @@ do_status(void)
 	pid = get_pgpid();
 	if (pid == 0)				/* no pid file */
 	{
-		fprintf(stderr, _("%s: postmaster or postgres not running\n"), progname);
+		write_stderr(_("%s: postmaster or postgres not running\n"), progname);
 		exit(1);
 	}
 	else if (pid < 0)			/* standalone backend */
@@ -702,18 +771,244 @@ do_kill(pgpid_t pid)
 {
 	if (kill((pid_t) pid, sig) != 0)
 	{
-		fprintf(stderr, _("signal %d failed (PID: %ld): %s\n"), sig, pid,
+		write_stderr(_("signal %d failed (PID: %ld): %s\n"), sig, pid,
 				strerror(errno));
 		exit(1);
 	}
 }
 
+#ifdef WIN32
 
+static bool pgwin32_IsInstalled(SC_HANDLE hSCM)
+{
+	SC_HANDLE hService = OpenService(hSCM, register_servicename, SERVICE_QUERY_CONFIG);
+	bool bResult = (hService != NULL);
+	if (bResult)
+		CloseServiceHandle(hService);
+	return bResult;
+}
+
+static char* pgwin32_CommandLine(bool registration)
+{
+	static char cmdLine[MAXPGPATH];
+	int ret;
+	if (registration)
+		ret = find_my_exec(argv0, cmdLine);
+	else
+		ret = find_other_exec(argv0, "postmaster", PM_VERSIONSTR, cmdLine);
+	if (ret != 0)
+	{
+		write_stderr(_("Unable to find exe"));
+		exit(1);
+	}
+
+	if (registration)
+	{
+		if (strcasecmp(cmdLine+strlen(cmdLine)-4,".exe"))
+		{
+			/* If commandline does not end in .exe, append it */
+			strcat(cmdLine,".exe");
+		}
+		strcat(cmdLine," runservice -N \"");
+		strcat(cmdLine,register_servicename);
+		strcat(cmdLine,"\"");
+	}
+
+	if (pg_data)
+	{
+		strcat(cmdLine," -D \"");
+		strcat(cmdLine,pg_data);
+		strcat(cmdLine,"\"");
+	}
+
+	if (post_opts)
+	{
+		strcat(cmdLine," ");
+		if (registration)
+			strcat(cmdLine," -o \"");
+		strcat(cmdLine,post_opts);
+		if (registration)
+			strcat(cmdLine,"\"");
+	}
+
+	return cmdLine;
+}
+
+static void
+pgwin32_doRegister()
+{
+	SC_HANDLE hService;
+	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+	if (hSCM == NULL)
+	{
+		write_stderr(_("Unable to open service manager\n"));
+		exit(1);
+	}
+	if (pgwin32_IsInstalled(hSCM))
+	{
+		CloseServiceHandle(hSCM);
+		write_stderr(_("Service \"%s\" already registered\n"),register_servicename);
+		exit(1);
+	}
+
+	if ((hService = CreateService(hSCM, register_servicename, register_servicename,
+								  SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
+								  SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
+								  pgwin32_CommandLine(true),
+								  NULL, NULL, "RPCSS\0", register_username, register_password)) == NULL)
+	{
+		CloseServiceHandle(hSCM);
+		write_stderr(_("Unable to register service \"%s\" [%d]\n"), register_servicename, (int)GetLastError());
+		exit(1);
+	}
+	CloseServiceHandle(hService);
+	CloseServiceHandle(hSCM);
+}
+
+static void
+pgwin32_doUnregister()
+{
+	SC_HANDLE hService;
+	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+	if (hSCM == NULL)
+	{
+		write_stderr(_("Unable to open service manager\n"));
+		exit(1);
+	}
+	if (!pgwin32_IsInstalled(hSCM))
+	{
+		CloseServiceHandle(hSCM);
+		write_stderr(_("Service \"%s\" not registered\n"),register_servicename);
+		exit(1);
+	}
+
+	if ((hService = OpenService(hSCM, register_servicename, DELETE)) == NULL)
+	{
+		CloseServiceHandle(hSCM);
+		write_stderr(_("Unable to open service \"%s\" [%d]\n"), register_servicename, (int)GetLastError());
+		exit(1);
+	}
+	if (!DeleteService(hService)) {
+		CloseServiceHandle(hService);
+		CloseServiceHandle(hSCM);
+		write_stderr(_("Unable to unregister service \"%s\" [%d]\n"), register_servicename, (int)GetLastError());
+		exit(1);
+	}
+	CloseServiceHandle(hService);
+	CloseServiceHandle(hSCM);
+}
+
+
+static SERVICE_STATUS status;
+static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE)0;
+static HANDLE shutdownHandles[2];
+static pid_t postmasterPID = -1;
+#define shutdownEvent     shutdownHandles[0]
+#define postmasterProcess shutdownHandles[1]
+
+static void pgwin32_SetServiceStatus(DWORD currentState)
+{
+	status.dwCurrentState = currentState;
+	SetServiceStatus(hStatus, (LPSERVICE_STATUS)&status);
+}
+
+static void WINAPI pgwin32_ServiceHandler(DWORD request)
+{
+	switch (request)
+	{
+		case SERVICE_CONTROL_STOP:
+		case SERVICE_CONTROL_SHUTDOWN:
+			pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
+			SetEvent(shutdownEvent);
+			return;
+
+		case SERVICE_CONTROL_PAUSE:
+			/* Win32 config reloading */
+			kill(postmasterPID,SIGHUP);
+			return;
+
+		/* FIXME: These could be used to replace other signals etc */
+		case SERVICE_CONTROL_CONTINUE:
+		case SERVICE_CONTROL_INTERROGATE:
+		default:
+			break;
+	}
+}
+
+static void WINAPI pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
+{
+	STARTUPINFO si;
+	PROCESS_INFORMATION pi;
+	DWORD ret;
+
+	/* Initialize variables */
+	status.dwWin32ExitCode	= S_OK;
+	status.dwCheckPoint		= 0;
+	status.dwWaitHint		= 0;
+	status.dwServiceType	= SERVICE_WIN32_OWN_PROCESS;
+	status.dwControlsAccepted			= SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;
+	status.dwServiceSpecificExitCode	= 0;
+	status.dwCurrentState = SERVICE_START_PENDING;
+
+	memset(&pi,0,sizeof(pi));
+	memset(&si,0,sizeof(si));
+	si.cb = sizeof(si);
+
+	/* Register the control request handler */
+	if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE)0)
+		return;
+
+	if ((shutdownEvent = CreateEvent(NULL,true,false,NULL)) == NULL)
+		return;
+
+	/* Start the postmaster */
+	pgwin32_SetServiceStatus(SERVICE_START_PENDING);
+	if (!CreateProcess(NULL,pgwin32_CommandLine(false),NULL,NULL,TRUE,0,NULL,NULL,&si,&pi))
+	{
+		pgwin32_SetServiceStatus(SERVICE_STOPPED);
+		return;
+	}
+	postmasterPID		= pi.dwProcessId;
+	postmasterProcess	= pi.hProcess;
+	CloseHandle(pi.hThread);
+	pgwin32_SetServiceStatus(SERVICE_RUNNING);
+
+	/* Wait for quit... */
+	ret = WaitForMultipleObjects(2,shutdownHandles,FALSE,INFINITE);
+	pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
+	switch (ret)
+	{
+		case WAIT_OBJECT_0: /* shutdown event */
+			kill(postmasterPID,SIGINT);
+			WaitForSingleObject(postmasterProcess,INFINITE);
+			break;
+
+		case (WAIT_OBJECT_0+1): /* postmaster went down */
+			break;
+
+		default:
+			/* assert(false); */
+	}
+
+	CloseHandle(shutdownEvent);
+	CloseHandle(postmasterProcess);
+
+	pgwin32_SetServiceStatus(SERVICE_STOPPED);
+}
+
+static void pgwin32_doRunAsService()
+{
+	SERVICE_TABLE_ENTRY st[] = {{ register_servicename, pgwin32_ServiceMain },
+								{ NULL, NULL }};
+	StartServiceCtrlDispatcher(st);
+}
+
+#endif
 
 static void
 do_advice(void)
 {
-	fprintf(stderr, _("\nTry \"%s --help\" for more information.\n"), progname);
+	write_stderr(_("\nTry \"%s --help\" for more information.\n"), progname);
 }
 
 
@@ -730,9 +1025,18 @@ do_help(void)
 	printf(_("  %s reload  [-D DATADIR] [-s]\n"), progname);
 	printf(_("  %s status  [-D DATADIR]\n"), progname);
 	printf(_("  %s kill    SIGNALNAME PROCESSID\n"), progname);
+#ifdef WIN32
+	printf(_("  %s register   [-N servicename] [-U username] [-P password] [-D DATADIR] [-o \"OPTIONS\"]\n"), progname);
+	printf(_("  %s unregister [-N servicename]\n"), progname);
+#endif
 	printf(_("Common options:\n"));
 	printf(_("  -D, --pgdata DATADIR   location of the database storage area\n"));
 	printf(_("  -s, --silent only print errors, no informational messages\n"));
+#ifdef WIN32
+	printf(_("  -N       service name with which to register PostgreSQL server\n"));
+	printf(_("  -P       user name of account to register PostgreSQL server\n"));
+	printf(_("  -U       password  of account to register PostgreSQL server\n"));
+#endif
 	printf(_("  -w           wait until operation completes\n"));
 	printf(_("  -W           do not wait until operation completes\n"));
 	printf(_("  --help       show this help, then exit\n"));
@@ -778,7 +1082,7 @@ set_mode(char *modeopt)
 	}
 	else
 	{
-		fprintf(stderr, _("%s: invalid shutdown mode %s\n"), progname, modeopt);
+		write_stderr(_("%s: invalid shutdown mode %s\n"), progname, modeopt);
 		do_advice();
 		exit(1);
 	}
@@ -811,7 +1115,7 @@ set_sig(char *signame)
 		sig = SIGUSR2;
 	else
 	{
-		fprintf(stderr, _("%s: invalid signal \"%s\"\n"), progname, signame);
+		write_stderr(_("%s: invalid signal \"%s\"\n"), progname, signame);
 		do_advice();
 		exit(1);
 	}
@@ -879,19 +1183,17 @@ main(int argc, char **argv)
 	/* process command-line options */
 	while (optind < argc)
 	{
-		while ((c = getopt_long(argc, argv, "D:l:m:o:p:swW", long_options, &option_index)) != -1)
+		while ((c = getopt_long(argc, argv, "D:l:m:N:o:p:P:sU:wW", long_options, &option_index)) != -1)
 		{
 			switch (c)
 			{
 				case 'D':
 				{
-					int			len = strlen(optarg) + 4;
+					int			len = strlen(optarg);
 					char	   *env_var;
 		
-					pg_data_opts = xmalloc(len);
-					snprintf(pg_data_opts, len, "-D %s", optarg);
-					env_var = xmalloc(len + sizeof("PGDATA="));
-					snprintf(env_var, len + sizeof("PGDATA="), "PGDATA=%s", optarg);
+					env_var = xmalloc(len + 8);
+					snprintf(env_var, len + 8, "PGDATA=%s", optarg);
 					putenv(env_var);
 					break;
 				}
@@ -901,15 +1203,36 @@ main(int argc, char **argv)
 				case 'm':
 					set_mode(optarg);
 					break;
+				case 'N':
+					register_servicename = xstrdup(optarg);
+					break;
 				case 'o':
 					post_opts = xstrdup(optarg);
 					break;
 				case 'p':
 					postgres_path = xstrdup(optarg);
 					break;
+				case 'P':
+					register_password  = xstrdup(optarg);
+					break;
 				case 's':
 					silence_echo = true;
 					break;
+				case 'U':
+					if (strchr(optarg,'\\'))
+						register_username  = xstrdup(optarg);
+					else /* Prepend .\ for local accounts */
+					{
+						register_username = malloc(strlen(optarg)+3);
+						if (!register_username)
+						{
+							write_stderr(_("%s: out of memory\n"), progname);
+							exit(1);
+						}
+						strcpy(register_username,".\\");
+						strcat(register_username,optarg);
+					}
+					break;
 				case 'w':
 					do_wait = true;
 					wait_set = true;
@@ -919,7 +1242,7 @@ main(int argc, char **argv)
 					wait_set = true;
 					break;
 				default:
-					fprintf(stderr, _("%s: invalid option %s\n"), progname, optarg);
+					write_stderr(_("%s: invalid option %s\n"), progname, optarg);
 					do_advice();
 					exit(1);
 			}
@@ -930,7 +1253,7 @@ main(int argc, char **argv)
 		{
 			if (ctl_command != NO_COMMAND)
 			{
-				fprintf(stderr, _("%s: extra operation mode %s\n"), progname, argv[optind]);
+				write_stderr(_("%s: extra operation mode %s\n"), progname, argv[optind]);
 				do_advice();
 				exit(1);
 			}
@@ -949,7 +1272,7 @@ main(int argc, char **argv)
 			{
 				if (argc - optind < 3)
 				{
-					fprintf(stderr, _("%s: invalid kill syntax\n"), progname);
+					write_stderr(_("%s: invalid kill syntax\n"), progname);
 					do_advice();
 					exit(1);
 				}
@@ -957,32 +1280,45 @@ main(int argc, char **argv)
 				set_sig(argv[++optind]);
 				killproc = atol(argv[++optind]);
 			}
+#ifdef WIN32
+			else if (strcmp(argv[optind], "register") == 0)
+				ctl_command = REGISTER_COMMAND;
+			else if (strcmp(argv[optind], "unregister") == 0)
+				ctl_command = UNREGISTER_COMMAND;
+			else if (strcmp(argv[optind], "runservice") == 0)
+				ctl_command = RUN_AS_SERVICE_COMMAND;
+#endif
 			else
 			{
-				fprintf(stderr, _("%s: invalid operation mode %s\n"), progname, argv[optind]);
+				write_stderr(_("%s: invalid operation mode %s\n"), progname, argv[optind]);
 				do_advice();
 				exit(1);
 			}
 			optind++;
 		}
 	}
-	
+
 	if (ctl_command == NO_COMMAND)
 	{
-		fprintf(stderr, _("%s: no operation specified\n"), progname);
+		write_stderr(_("%s: no operation specified\n"), progname);
 		do_advice();
 		exit(1);
 	}
 
+	/* Note we put any -D switch into the env var above */
 	pg_data = getenv("PGDATA");
-	canonicalize_path(pg_data);
-
-	if (pg_data == NULL && ctl_command != KILL_COMMAND)
+	if (pg_data)
 	{
-		fprintf(stderr,
-				_("%s: no database directory specified "
-				"and environment variable PGDATA unset\n"),
-				progname);
+		/* XXX modifies environment var in-place ... ugly ... */
+		canonicalize_path(pg_data);
+	}
+
+	if (pg_data == NULL &&
+		ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
+	{
+		write_stderr(_("%s: no database directory specified "
+					   "and environment variable PGDATA unset\n"),
+					 progname);
 		do_advice();
 		exit(1);
 	}
@@ -1034,6 +1370,17 @@ main(int argc, char **argv)
 		case KILL_COMMAND:
 			do_kill(killproc);
 			break;
+#ifdef WIN32
+ 		case REGISTER_COMMAND:
+ 			pgwin32_doRegister();
+ 			break;
+ 		case UNREGISTER_COMMAND:
+ 			pgwin32_doUnregister();
+ 			break;
+ 		case RUN_AS_SERVICE_COMMAND:
+ 			pgwin32_doRunAsService();
+ 			break;
+#endif
 		default:
 			break;
 	}