---------------------
PatchSet 3727 
Date: 2006/09/11 19:27:05
Author: serassio
Branch: nt
Tag: (none) 
Log:
Split Windows service code from win32.cc to WinSvc.cc

Members: 
	port/win32/squid/squid.vcproj:1.1.2.13->1.1.2.14 
	src/WinSvc.cc:1.1->1.1.2.1 
	src/win32.cc:1.4.2.25->1.4.2.26 

Index: squid3/port/win32/squid/squid.vcproj
===================================================================
RCS file: /cvsroot/squid-sf//squid3/port/win32/squid/Attic/squid.vcproj,v
retrieving revision 1.1.2.13
retrieving revision 1.1.2.14
diff -u -r1.1.2.13 -r1.1.2.14
--- squid3/port/win32/squid/squid.vcproj	11 Sep 2006 16:55:14 -0000	1.1.2.13
+++ squid3/port/win32/squid/squid.vcproj	11 Sep 2006 19:27:05 -0000	1.1.2.14
@@ -748,6 +748,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\WinSvc.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\wordlist.cc"
 				>
 			</File>
@@ -1097,6 +1101,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\globals.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\include\profiling.h"
 				>
 			</File>
--- /dev/null	Wed Feb 14 13:37:19 2007
+++ squid3/src/WinSvc.cc	Wed Feb 14 13:37:53 2007
@@ -0,0 +1,981 @@
+
+/*
+ * $Id: WinSvc.cc,v 1.1.2.1 2006/09/11 19:27:07 serassio Exp $
+ *
+ * Windows support
+ * AUTHOR: Guido Serassio <serassio@squid-cache.org>
+ * inspired by previous work by Romeo Anghelache & Eric Stern.
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  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
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "squid_windows.h"
+
+#ifdef _SQUID_MSWIN_
+#ifndef _MSWSOCK_
+#include <mswsock.h>
+#endif
+#include <process.h>
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+#include <crtdbg.h>
+#endif
+#endif
+
+static unsigned int GetOSVersion();
+void WIN32_svcstatusupdate(DWORD, DWORD);
+void WINAPI WIN32_svcHandler(DWORD);
+#if USE_WIN32_SERVICE
+static int WIN32_StoreKey(const char *, DWORD, unsigned char *, int);
+static int WIN32_create_key(void);
+static void WIN32_build_argv (char *);
+#endif
+extern "C" void WINAPI SquidWinSvcMain(DWORD, char **);
+
+#if defined(_SQUID_MSWIN_)
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+void Squid_Win32InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t);
+#endif
+static int Win32SockInit(void);
+static void Win32SockCleanup(void);
+SQUIDCEXTERN LPCRITICAL_SECTION dbg_mutex;
+void WIN32_ExceptionHandlerCleanup(void);
+static LPTOP_LEVEL_EXCEPTION_FILTER Win32_Old_ExceptionHandler = NULL;
+static int s_iInitCount = 0;
+#endif
+
+static int Squid_Aborting = 0;
+
+#if USE_WIN32_SERVICE
+static SERVICE_STATUS svcStatus;
+static SERVICE_STATUS_HANDLE svcHandle;
+static int WIN32_argc;
+static char ** WIN32_argv;
+static char * WIN32_module_name;
+
+#define VENDOR "GNU"
+static char VENDORString[] = VENDOR;
+#define SOFTWARENAME "Squid"
+static char SOFTWARENAMEString[] = SOFTWARENAME;
+#define WIN32_VERSION "3.0"
+static char WIN32_VERSIONString[] = WIN32_VERSION;
+#define SOFTWARE "SOFTWARE"
+static char SOFTWAREString[] = SOFTWARE;
+#define COMMANDLINE "CommandLine"
+#define CONFIGFILE  "ConfigFile"
+#undef ChangeServiceConfig2
+typedef BOOL (WINAPI * PFChangeServiceConfig2) (SC_HANDLE, DWORD, LPVOID);
+#ifdef UNICODE
+#define CHANGESERVICECONFIG2 "ChangeServiceConfig2W"
+#else
+#define CHANGESERVICECONFIG2 "ChangeServiceConfig2A"
+#endif
+static SC_ACTION Squid_SCAction[] = { { SC_ACTION_RESTART, 60000 } };
+static char Squid_ServiceDescriptionString[] = SOFTWARENAME " " VERSION " WWW Proxy Server";
+static SERVICE_DESCRIPTION Squid_ServiceDescription = { Squid_ServiceDescriptionString };
+static SERVICE_FAILURE_ACTIONS Squid_ServiceFailureActions = { INFINITE, NULL, NULL, 1, Squid_SCAction };
+static char REGKEY[256]=SOFTWARE"\\"VENDOR"\\"SOFTWARENAME"\\"WIN32_VERSION"\\";
+static char *keys[] = {
+                          SOFTWAREString,	    /* key[0] */
+                          VENDORString,	    /* key[1] */
+                          SOFTWARENAMEString,   /* key[2] */
+                          WIN32_VERSIONString,  /* key[3] */
+                          NULL,	    /* key[4] */
+                          NULL	    /* key[5] */
+                      };
+#endif
+
+/* ====================================================================== */
+/* LOCAL FUNCTIONS */
+/* ====================================================================== */
+
+#if USE_WIN32_SERVICE
+static int
+WIN32_create_key(void)
+{
+    int index;
+    HKEY hKey;
+    HKEY hKeyNext;
+    int retval;
+    LONG rv;
+
+    hKey = HKEY_LOCAL_MACHINE;
+    index = 0;
+    retval = 0;
+
+    /* Walk the tree, creating at each stage if necessary */
+
+    while (keys[index]) {
+        unsigned long result;
+        rv = RegCreateKeyEx(hKey, keys[index],	/* subkey */
+                            0,			/* reserved */
+                            NULL,		/* class */
+                            REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyNext, &result);
+
+        if (rv != ERROR_SUCCESS) {
+            fprintf(stderr, "RegCreateKeyEx(%s),%d\n", keys[index], (int) rv);
+            retval = -4;
+        }
+
+        /* Close the old key */
+        rv = RegCloseKey(hKey);
+
+        if (rv != ERROR_SUCCESS) {
+            fprintf(stderr, "RegCloseKey %d\n", (int) rv);
+
+            if (retval == 0) {
+                /* Keep error status from RegCreateKeyEx, if any */
+                retval = -4;
+            }
+        }
+
+        if (retval) {
+            break;
+        }
+
+        hKey = hKeyNext;
+        index++;
+    }
+
+    if (keys[index] == NULL) {
+        /* Close the final key we opened, if we walked the entire
+         * tree
+         */
+        rv = RegCloseKey(hKey);
+
+        if (rv != ERROR_SUCCESS) {
+            fprintf(stderr, "RegCloseKey %d\n", (int) rv);
+
+            if (retval == 0) {
+                /* Keep error status from RegCreateKeyEx, if any */
+                retval = -4;
+            }
+        }
+    }
+
+    return retval;
+}
+
+static int
+WIN32_StoreKey(const char *key, DWORD type, unsigned char *value,
+               int value_size)
+{
+    LONG rv;
+    HKEY hKey;
+    int retval;
+
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_WRITE, &hKey);
+
+    if (rv == ERROR_FILE_NOT_FOUND) {
+        /* Key could not be opened -- try to create it
+         */
+
+        if (WIN32_create_key() < 0) {
+            /* Creation failed (error already reported) */
+            return -4;
+        }
+
+        /* Now it has been created we should be able to open it
+         */
+        rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_WRITE, &hKey);
+
+        if (rv == ERROR_FILE_NOT_FOUND) {
+            fprintf(stderr, "Registry does not contain key %s after creation\n",
+                    REGKEY);
+            return -1;
+        }
+    }
+
+    if (rv != ERROR_SUCCESS) {
+        fprintf(stderr, "RegOpenKeyEx HKLM\\%s, %d\n", REGKEY, (int) rv);
+        return -4;
+    }
+
+    /* Now set the value and data */
+    rv = RegSetValueEx(hKey, key,	/* value key name */
+                       0,			/* reserved */
+                       type,			/* type */
+                       value,			/* value data */
+                       (DWORD) value_size);	/* for size of "value" */
+
+    retval = 0;			/* Return value */
+
+    if (rv != ERROR_SUCCESS) {
+        fprintf(stderr, "RegQueryValueEx(key %s),%d\n", key, (int) rv);
+        retval = -4;
+    } else {
+        fprintf(stderr, "Registry stored HKLM\\%s\\%s value %s\n",
+                REGKEY,
+                key,
+                type == REG_SZ ? value : (unsigned char *) "(not displayable)");
+    }
+
+    /* Make sure we close the key even if there was an error storing
+     * the data
+     */
+    rv = RegCloseKey(hKey);
+
+    if (rv != ERROR_SUCCESS) {
+        fprintf(stderr, "RegCloseKey HKLM\\%s, %d\n", REGKEY, (int) rv);
+
+        if (retval == 0) {
+            /* Keep error status from RegQueryValueEx, if any */
+            retval = -4;
+        }
+    }
+
+    return retval;
+}
+
+/* Build argv, argc from string passed from Windows.  */
+static void WIN32_build_argv(char *cmd)
+{
+    int argvlen = 0;
+    char *word;
+
+    WIN32_argc = 1;
+    WIN32_argv = (char **) xmalloc ((WIN32_argc+1) * sizeof (char *));
+    WIN32_argv[0]=xstrdup(WIN32_module_name);
+    /* Scan command line until there is nothing left. */
+
+    while (*cmd) {
+        /* Ignore spaces */
+
+        if (xisspace(*cmd)) {
+            cmd++;
+            continue;
+        }
+
+        /* Found the beginning of an argument. */
+        word = cmd;
+
+        while (*cmd) {
+            cmd++;		/* Skip over this character */
+
+            if (xisspace(*cmd))	/* End of argument if space */
+                break;
+        }
+
+        if (*cmd)
+            *cmd++ = '\0';		/* Terminate `word' */
+
+        /* See if we need to allocate more space for argv */
+        if (WIN32_argc >= argvlen) {
+            argvlen = WIN32_argc + 1;
+            WIN32_argv = (char **) xrealloc (WIN32_argv, (1 + argvlen) * sizeof (char *));
+        }
+
+        /* Add word to argv file. */
+        WIN32_argv[WIN32_argc++] = word;
+    }
+
+    WIN32_argv[WIN32_argc] = NULL;
+}
+
+#endif /* USE_WIN32_SERVICE */
+
+static unsigned int
+GetOSVersion()
+{
+    OSVERSIONINFO osvi;
+
+    safe_free(WIN32_OS_string);
+    memset(&osvi, '\0', sizeof(OSVERSIONINFO));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx((OSVERSIONINFO *) & osvi);
+
+    switch (osvi.dwPlatformId) {
+
+    case VER_PLATFORM_WIN32_NT:
+
+        if (osvi.dwMajorVersion <= 4) {
+            WIN32_OS_string = xstrdup("Windows NT");
+            return _WIN_OS_WINNT;
+        }
+
+        if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) {
+            WIN32_OS_string = xstrdup("Windows 2000");
+            return _WIN_OS_WIN2K;
+        }
+
+        if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) {
+            WIN32_OS_string = xstrdup("Windows XP");
+            return _WIN_OS_WINXP;
+        }
+
+        if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) {
+            WIN32_OS_string = xstrdup("Windows Server 2003");
+            return _WIN_OS_WINNET;
+        }
+
+        if ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 0)) {
+            WIN32_OS_string = xstrdup("Windows code name \"Longhorn\"");
+            return _WIN_OS_WINLON;
+        }
+
+        break;
+
+    case VER_PLATFORM_WIN32_WINDOWS:
+
+        if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)) {
+            WIN32_OS_string = xstrdup("Windows 95");
+            return _WIN_OS_WIN95;
+        }
+
+        if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10)) {
+            WIN32_OS_string = xstrdup("Windows 98");
+            return _WIN_OS_WIN98;
+        }
+
+        if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90)) {
+            WIN32_OS_string = xstrdup("Windows Me");
+            return _WIN_OS_WINME;
+        }
+
+        break;
+
+    case VER_PLATFORM_WIN32s:
+        WIN32_OS_string = xstrdup("Windows 3.1 with WIN32S");
+        return _WIN_OS_WIN32S;
+        break;
+
+    default:
+        break;
+    }
+
+    WIN32_OS_string = xstrdup("Unknown Windows system");
+    return _WIN_OS_UNKNOWN;
+}
+
+/* ====================================================================== */
+/* PUBLIC FUNCTIONS */
+/* ====================================================================== */
+
+void
+WIN32_Abort(int sig)
+{
+#if USE_WIN32_SERVICE
+    svcStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+    svcStatus.dwServiceSpecificExitCode = 1;
+#endif
+
+    Squid_Aborting = 1;
+    WIN32_Exit();
+}
+
+void
+WIN32_Exit()
+{
+#ifdef _SQUID_MSWIN_
+    Win32SockCleanup();
+#endif
+#if USE_WIN32_SERVICE
+
+    if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
+        if (!Squid_Aborting) {
+            svcStatus.dwCurrentState = SERVICE_STOPPED;
+            SetServiceStatus(svcHandle, &svcStatus);
+        }
+    }
+
+#endif
+#ifdef _SQUID_MSWIN_
+    if (dbg_mutex)
+        DeleteCriticalSection(dbg_mutex);
+
+    WIN32_ExceptionHandlerCleanup();
+
+#endif
+
+    _exit(0);
+}
+
+int WIN32_Subsystem_Init(int * argc, char *** argv)
+{
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+    _invalid_parameter_handler oldHandler, newHandler;
+#endif
+
+    WIN32_OS_version = GetOSVersion();
+
+    if ((WIN32_OS_version == _WIN_OS_UNKNOWN) || (WIN32_OS_version == _WIN_OS_WIN32S))
+        return 1;
+
+    if (atexit(WIN32_Exit) != 0)
+        return 1;
+
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+
+    newHandler = Squid_Win32InvalidParameterHandler;
+
+    oldHandler = _set_invalid_parameter_handler(newHandler);
+
+    _CrtSetReportMode(_CRT_ASSERT, 0);
+
+#endif
+#if USE_WIN32_SERVICE
+
+    if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
+        char path[512];
+        HKEY hndKey;
+
+        if (signal(SIGABRT, WIN32_Abort) == SIG_ERR)
+            return 1;
+
+        /* Register the service Handler function */
+        svcHandle =
+            RegisterServiceCtrlHandler(WIN32_Service_name,
+                                       WIN32_svcHandler);
+
+        if (svcHandle == 0)
+            return 1;
+
+        /* Set Process work dir to directory cointaining squid.exe */
+        GetModuleFileName(NULL, path, 512);
+
+        WIN32_module_name=xstrdup(path);
+
+        path[strlen(path) - 10] = '\0';
+
+        if (SetCurrentDirectory(path) == 0)
+            return 1;
+
+        safe_free(ConfigFile);
+
+        /* get config file from Windows Registry */
+        if (RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY, &hndKey) == ERROR_SUCCESS) {
+            DWORD Type = 0;
+            DWORD Size = 0;
+            LONG Result;
+            Result =
+                RegQueryValueEx(hndKey, CONFIGFILE, NULL, &Type, NULL, &Size);
+
+            if (Result == ERROR_SUCCESS && Size) {
+                ConfigFile = static_cast<char *>(xmalloc(Size));
+                RegQueryValueEx(hndKey, CONFIGFILE, NULL, &Type, (unsigned char *)ConfigFile,
+                                &Size);
+            } else
+                ConfigFile = xstrdup(DefaultConfigFile);
+
+            Size = 0;
+
+            Type = 0;
+
+            Result =
+                RegQueryValueEx(hndKey, COMMANDLINE, NULL, &Type, NULL, &Size);
+
+            if (Result == ERROR_SUCCESS && Size) {
+                WIN32_Service_Command_Line = static_cast<char *>(xmalloc(Size));
+                RegQueryValueEx(hndKey, COMMANDLINE, NULL, &Type, (unsigned char *)WIN32_Service_Command_Line,
+                                &Size);
+            } else
+                WIN32_Service_Command_Line = xstrdup("");
+
+            RegCloseKey(hndKey);
+        } else {
+            ConfigFile = xstrdup(DefaultConfigFile);
+            WIN32_Service_Command_Line = xstrdup("");
+        }
+
+        WIN32_build_argv(WIN32_Service_Command_Line);
+        *argc = WIN32_argc;
+        *argv = WIN32_argv;
+        /* Set Service Status to SERVICE_START_PENDING */
+        svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+        svcStatus.dwCurrentState = SERVICE_START_PENDING;
+        svcStatus.dwControlsAccepted =
+            SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+        svcStatus.dwWin32ExitCode = 0;
+        svcStatus.dwServiceSpecificExitCode = 0;
+        svcStatus.dwCheckPoint = 0;
+        svcStatus.dwWaitHint = 10000;
+        SetServiceStatus(svcHandle, &svcStatus);
+#ifdef _SQUID_MSWIN_
+
+        _setmaxstdio(Squid_MaxFD);
+#endif
+    }
+
+#endif /* USE_WIN32_SERVICE */
+#ifdef _SQUID_MSWIN_
+    if (Win32SockInit() < 0)
+        return 1;
+
+#endif
+
+    return 0;
+}
+
+#if USE_WIN32_SERVICE
+void
+WIN32_svcstatusupdate(DWORD svcstate, DWORD WaitHint)
+{
+    if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
+        svcStatus.dwCheckPoint++;
+        svcStatus.dwWaitHint = WaitHint;
+        svcStatus.dwCurrentState = svcstate;
+        SetServiceStatus(svcHandle, &svcStatus);
+    }
+}
+
+VOID WINAPI
+WIN32_svcHandler(DWORD Opcode)
+{
+    DWORD status;
+
+    switch (Opcode) {
+
+    case _WIN_SQUID_SERVICE_CONTROL_STOP:
+
+    case _WIN_SQUID_SERVICE_CONTROL_SHUTDOWN:
+        /* Do whatever it takes to stop here. */
+        svcStatus.dwWin32ExitCode = 0;
+        svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
+        svcStatus.dwCheckPoint = 0;
+        svcStatus.dwWaitHint = 10000;
+        shut_down(SIGTERM);
+
+        if (!SetServiceStatus(svcHandle, &svcStatus)) {
+            status = GetLastError();
+            debug(1, 1) ("SetServiceStatus error %ld\n", status);
+        }
+
+        debug(1, 1) ("Leaving Squid service\n");
+        return;
+
+    case _WIN_SQUID_SERVICE_CONTROL_INTERROGATE:
+        /* Fall through to send current status. */
+
+        if (!SetServiceStatus(svcHandle, &svcStatus)) {
+            status = GetLastError();
+            debug(1, 1) ("SetServiceStatus error %ld\n", status);
+        }
+
+        break;
+
+    case _WIN_SQUID_SERVICE_CONTROL_ROTATE:
+        rotate_logs(SIGUSR1);
+        break;
+
+    case _WIN_SQUID_SERVICE_CONTROL_RECONFIGURE:
+        reconfigure(SIGHUP);
+        break;
+
+    case _WIN_SQUID_SERVICE_CONTROL_DEBUG:
+        sigusr2_handle(SIGUSR2);
+        break;
+
+    case _WIN_SQUID_SERVICE_CONTROL_INTERRUPT:
+        /* Do whatever it takes to stop here. */
+        svcStatus.dwWin32ExitCode = 0;
+        svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
+        svcStatus.dwCheckPoint = 0;
+        svcStatus.dwWaitHint = 10000;
+        shut_down(SIGINT);
+
+        if (!SetServiceStatus(svcHandle, &svcStatus)) {
+            status = GetLastError();
+            debug(1, 1) ("SetServiceStatus error %ld\n", status);
+        }
+
+        debug(1, 1) ("Leaving Squid service\n");
+        break;
+
+    default:
+        debug(1, 1) ("Unrecognized opcode %ld\n", Opcode);
+    }
+
+    return;
+}
+
+void
+WIN32_RemoveService()
+{
+    SC_HANDLE schService;
+    SC_HANDLE schSCManager;
+
+    if (!WIN32_Service_name)
+        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
+
+    strcat(REGKEY, WIN32_Service_name);
+
+    keys[4] = WIN32_Service_name;
+
+    schSCManager = OpenSCManager(NULL,	/* machine (NULL == local)    */
+                                 NULL,			/* database (NULL == default) */
+                                 SC_MANAGER_ALL_ACCESS	/* access required            */
+                                );
+
+    if (!schSCManager)
+        fprintf(stderr, "OpenSCManager failed\n");
+    else {
+        schService = OpenService(schSCManager, WIN32_Service_name, SERVICE_ALL_ACCESS);
+
+        if (schService == NULL)
+            fprintf(stderr, "OpenService failed\n");
+
+        /* Could not open the service */
+        else {
+            /* try to stop the service */
+
+            if (ControlService(schService, _WIN_SQUID_SERVICE_CONTROL_STOP,
+                               &svcStatus)) {
+                sleep(1);
+
+                while (QueryServiceStatus(schService, &svcStatus)) {
+                    if (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)
+                        sleep(1);
+                    else
+                        break;
+                }
+            }
+
+            /* now remove the service */
+            if (DeleteService(schService) == 0)
+                fprintf(stderr, "DeleteService failed.\n");
+            else
+                printf("Service %s deleted successfully.\n",
+                       WIN32_Service_name);
+
+            CloseServiceHandle(schService);
+        }
+
+        CloseServiceHandle(schSCManager);
+    }
+}
+
+void
+WIN32_SetServiceCommandLine()
+{
+    if (!WIN32_Service_name)
+        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
+
+    strcat(REGKEY, WIN32_Service_name);
+
+    keys[4] = WIN32_Service_name;
+
+    /* Now store the Service Command Line in the registry */
+    WIN32_StoreKey(COMMANDLINE, REG_SZ, (unsigned char *) WIN32_Command_Line, strlen(WIN32_Command_Line) + 1);
+}
+
+void
+WIN32_InstallService()
+{
+    SC_HANDLE schService;
+    SC_HANDLE schSCManager;
+    char ServicePath[512];
+    char szPath[512];
+    int lenpath;
+
+    if (!WIN32_Service_name)
+        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
+
+    strcat(REGKEY, WIN32_Service_name);
+
+    keys[4] = WIN32_Service_name;
+
+    if ((lenpath = GetModuleFileName(NULL, ServicePath, 512)) == 0) {
+        fprintf(stderr, "Can't get executable path\n");
+        exit(1);
+    }
+
+    snprintf(szPath, sizeof(szPath), "%s %s:%s", ServicePath, _WIN_SQUID_SERVICE_OPTION, WIN32_Service_name);
+    schSCManager = OpenSCManager(NULL,	/* machine (NULL == local)    */
+                                 NULL,			/* database (NULL == default) */
+                                 SC_MANAGER_ALL_ACCESS	/* access required            */
+                                );
+
+    if (!schSCManager) {
+        fprintf(stderr, "OpenSCManager failed\n");
+        exit(1);
+    } else {
+        schService = CreateService(schSCManager,    /* SCManager database     */
+                                   WIN32_Service_name,			    /* name of service        */
+                                   WIN32_Service_name,			    /* name to display        */
+                                   SERVICE_ALL_ACCESS,			    /* desired access         */
+                                   SERVICE_WIN32_OWN_PROCESS,		    /* service type           */
+                                   SERVICE_AUTO_START,			    /* start type             */
+                                   SERVICE_ERROR_NORMAL,		    /* error control type     */
+                                   (const char *) szPath,		    /* service's binary       */
+                                   NULL,				    /* no load ordering group */
+                                   NULL,				    /* no tag identifier      */
+                                   "Tcpip\0AFD\0",			    /* dependencies           */
+                                   NULL,				    /* LocalSystem account    */
+                                   NULL);				    /* no password            */
+
+        if (schService) {
+            if (WIN32_OS_version > _WIN_OS_WINNT) {
+                HMODULE ADVAPI32Handle;
+                PFChangeServiceConfig2 ChangeServiceConfig2;
+                DWORD dwInfoLevel = SERVICE_CONFIG_DESCRIPTION;
+
+                ADVAPI32Handle = GetModuleHandle("advapi32");
+                ChangeServiceConfig2 = (PFChangeServiceConfig2) GetProcAddress(ADVAPI32Handle, CHANGESERVICECONFIG2);
+                ChangeServiceConfig2(schService, dwInfoLevel, &Squid_ServiceDescription);
+                dwInfoLevel = SERVICE_CONFIG_FAILURE_ACTIONS;
+                ChangeServiceConfig2(schService, dwInfoLevel, &Squid_ServiceFailureActions);
+            }
+
+            CloseServiceHandle(schService);
+            /* Now store the config file location in the registry */
+
+            if (!ConfigFile)
+                ConfigFile = xstrdup(DefaultConfigFile);
+
+            WIN32_StoreKey(CONFIGFILE, REG_SZ, (unsigned char *) ConfigFile, strlen(ConfigFile) + 1);
+
+            printf("Squid Cache version %s for %s\n", version_string,
+                   CONFIG_HOST_TYPE);
+
+            printf("installed successfully as %s Windows System Service.\n",
+                   WIN32_Service_name);
+
+            printf
+            ("To run, start it from the Services Applet of Control Panel.\n");
+
+            printf("Don't forget to edit squid.conf before starting it.\n\n");
+        } else {
+            fprintf(stderr, "CreateService failed\n");
+            exit(1);
+        }
+
+        CloseServiceHandle(schSCManager);
+    }
+}
+
+void
+WIN32_sendSignal(int WIN32_signal)
+{
+    SERVICE_STATUS ssStatus;
+    DWORD fdwAccess, fdwControl;
+    SC_HANDLE schService;
+    SC_HANDLE schSCManager;
+
+    if (!WIN32_Service_name)
+        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
+
+    schSCManager = OpenSCManager(NULL,	/* machine (NULL == local)    */
+                                 NULL,			/* database (NULL == default) */
+                                 SC_MANAGER_ALL_ACCESS	/* access required            */
+                                );
+
+    if (!schSCManager) {
+        fprintf(stderr, "OpenSCManager failed\n");
+        exit(1);
+    }
+
+    /* The required service object access depends on the control. */
+    switch (WIN32_signal) {
+
+    case 0:			/* SIGNULL */
+        fdwAccess = SERVICE_INTERROGATE;
+        fdwControl = _WIN_SQUID_SERVICE_CONTROL_INTERROGATE;
+        break;
+
+    case SIGUSR1:
+        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
+        fdwControl = _WIN_SQUID_SERVICE_CONTROL_ROTATE;
+        break;
+
+    case SIGUSR2:
+        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
+        fdwControl = _WIN_SQUID_SERVICE_CONTROL_DEBUG;
+        break;
+
+    case SIGHUP:
+        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
+        fdwControl = _WIN_SQUID_SERVICE_CONTROL_RECONFIGURE;
+        break;
+
+    case SIGTERM:
+        fdwAccess = SERVICE_STOP;
+        fdwControl = _WIN_SQUID_SERVICE_CONTROL_STOP;
+        break;
+
+    case SIGINT:
+
+    case SIGKILL:
+        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
+        fdwControl = _WIN_SQUID_SERVICE_CONTROL_INTERRUPT;
+        break;
+
+    default:
+        exit(1);
+    }
+
+    /* Open a handle to the service. */
+    schService = OpenService(schSCManager,	/* SCManager database */
+                             WIN32_Service_name,	/* name of service    */
+                             fdwAccess);		/* specify access     */
+
+    if (schService == NULL) {
+        fprintf(stderr, "%s: ERROR: Could not open Service %s\n", appname,
+                WIN32_Service_name);
+        exit(1);
+    } else {
+        /* Send a control value to the service. */
+
+        if (!ControlService(schService,	/* handle of service      */
+                            fdwControl,	/* control value to send  */
+                            &ssStatus)) {	/* address of status info */
+            fprintf(stderr, "%s: ERROR: Could not Control Service %s\n",
+                    appname, WIN32_Service_name);
+            exit(1);
+        } else {
+            /* Print the service status. */
+            printf("\nStatus of %s Service:\n", WIN32_Service_name);
+            printf("  Service Type: 0x%lx\n", ssStatus.dwServiceType);
+            printf("  Current State: 0x%lx\n", ssStatus.dwCurrentState);
+            printf("  Controls Accepted: 0x%lx\n", ssStatus.dwControlsAccepted);
+            printf("  Exit Code: %ld\n", ssStatus.dwWin32ExitCode);
+            printf("  Service Specific Exit Code: %ld\n",
+                   ssStatus.dwServiceSpecificExitCode);
+            printf("  Check Point: %ld\n", ssStatus.dwCheckPoint);
+            printf("  Wait Hint: %ld\n", ssStatus.dwWaitHint);
+        }
+
+        CloseServiceHandle(schService);
+    }
+
+    CloseServiceHandle(schSCManager);
+}
+
+int main(int argc, char **argv)
+{
+    SERVICE_TABLE_ENTRY DispatchTable[] = {
+                                              {NULL, SquidWinSvcMain},
+                                              {NULL, NULL}
+                                          };
+    char *c;
+    char stderr_path[256];
+
+    if ((argc == 2) && strstr(argv[1], _WIN_SQUID_SERVICE_OPTION)) {
+        strcpy(stderr_path, argv[0]);
+        strcat(stderr_path,".log");
+        freopen(stderr_path, "w", stderr);
+        setmode(fileno(stderr), O_TEXT);
+        WIN32_run_mode = _WIN_SQUID_RUN_MODE_SERVICE;
+        opt_no_daemon = 1;
+
+        if (!(c=strchr(argv[1],':'))) {
+            fprintf(stderr, "Bad Service Parameter: %s\n", argv[1]);
+            return 1;
+        }
+
+        WIN32_Service_name = xstrdup(c+1);
+        DispatchTable[0].lpServiceName=WIN32_Service_name;
+        strcat(REGKEY, WIN32_Service_name);
+        keys[4] = WIN32_Service_name;
+
+        if (!StartServiceCtrlDispatcher(DispatchTable)) {
+            fprintf(stderr, "StartServiceCtrlDispatcher error = %ld\n",
+                    GetLastError());
+            return 1;
+        }
+    } else {
+        WIN32_run_mode = _WIN_SQUID_RUN_MODE_INTERACTIVE;
+#ifdef _SQUID_MSWIN_
+
+        opt_no_daemon = 1;
+
+#endif
+
+        return SquidMain(argc, argv);
+    }
+
+    return 0;
+}
+
+#endif /* USE_WIN32_SERVICE */
+
+#if defined(_SQUID_MSWIN_)
+static int Win32SockInit(void)
+{
+    int iVersionRequested;
+    WSADATA wsaData;
+    int err, opt;
+    int optlen = sizeof(opt);
+
+    if (s_iInitCount > 0) {
+        s_iInitCount++;
+        return (0);
+    } else if (s_iInitCount < 0)
+        return (s_iInitCount);
+
+    /* s_iInitCount == 0. Do the initailization */
+    iVersionRequested = MAKEWORD(2, 0);
+
+    err = WSAStartup((WORD) iVersionRequested, &wsaData);
+
+    if (err) {
+        s_iInitCount = -1;
+        return (s_iInitCount);
+    }
+
+    if (LOBYTE(wsaData.wVersion) != 2 ||
+            HIBYTE(wsaData.wVersion) != 0) {
+        s_iInitCount = -2;
+        WSACleanup();
+        return (s_iInitCount);
+    }
+
+    if (WIN32_OS_version !=_WIN_OS_WINNT) {
+        if (::getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&opt, &optlen)) {
+            s_iInitCount = -3;
+            WSACleanup();
+            return (s_iInitCount);
+        } else {
+            opt = opt | SO_SYNCHRONOUS_NONALERT;
+
+            if (::setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen)) {
+                s_iInitCount = -3;
+                WSACleanup();
+                return (s_iInitCount);
+            }
+        }
+    }
+
+    WIN32_Socks_initialized = 1;
+    s_iInitCount++;
+    return (s_iInitCount);
+}
+
+static void Win32SockCleanup(void)
+{
+    if (--s_iInitCount == 0)
+        WSACleanup();
+
+    return;
+}
+
+void Squid_Win32InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
+{
+    return;
+}
+
+#endif /* SQUID_MSWIN_ */
Index: squid3/src/win32.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/win32.cc,v
retrieving revision 1.4.2.25
retrieving revision 1.4.2.26
diff -u -r1.4.2.25 -r1.4.2.26
--- squid3/src/win32.cc	10 Sep 2006 08:27:38 -0000	1.4.2.25
+++ squid3/src/win32.cc	11 Sep 2006 19:27:07 -0000	1.4.2.26
@@ -1,6 +1,6 @@
 
 /*
- * $Id: win32.cc,v 1.4.2.25 2006/09/10 08:27:38 serassio Exp $
+ * $Id: win32.cc,v 1.4.2.26 2006/09/11 19:27:07 serassio Exp $
  *
  * Windows support
  * AUTHOR: Guido Serassio <serassio@squid-cache.org>
@@ -34,8 +34,6 @@
  *
  */
 
-#define WIN32_C
-
 #include "squid.h"
 #include "squid_windows.h"
 
@@ -46,880 +44,13 @@
 #ifndef _MSWSOCK_
 #include <mswsock.h>
 #endif
-#include <process.h>
-#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
-#include <crtdbg.h>
-#endif
-#endif
 #include <fde.h>
 
-static unsigned int GetOSVersion();
-void WIN32_svcstatusupdate(DWORD, DWORD);
-void WINAPI WIN32_svcHandler(DWORD);
-#if USE_WIN32_SERVICE
-static int WIN32_StoreKey(const char *, DWORD, unsigned char *, int);
-static int WIN32_create_key(void);
-static void WIN32_build_argv (char *);
-#endif
-extern "C" void WINAPI SquidWinSvcMain(DWORD, char **);
-
-#if defined(_SQUID_MSWIN_)
-#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
-void Squid_Win32InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t);
-#endif
-static int Win32SockInit(void);
-static void Win32SockCleanup(void);
 SQUIDCEXTERN LPCRITICAL_SECTION dbg_mutex;
 void WIN32_ExceptionHandlerCleanup(void);
 static LPTOP_LEVEL_EXCEPTION_FILTER Win32_Old_ExceptionHandler = NULL;
-static int s_iInitCount = 0;
-#endif
-
-static int Squid_Aborting = 0;
-
-#if USE_WIN32_SERVICE
-static SERVICE_STATUS svcStatus;
-static SERVICE_STATUS_HANDLE svcHandle;
-static int WIN32_argc;
-static char ** WIN32_argv;
-static char * WIN32_module_name;
-
-#define VENDOR "GNU"
-static char VENDORString[] = VENDOR;
-#define SOFTWARENAME "Squid"
-static char SOFTWARENAMEString[] = SOFTWARENAME;
-#define WIN32_VERSION "3.0"
-static char WIN32_VERSIONString[] = WIN32_VERSION;
-#define SOFTWARE "SOFTWARE"
-static char SOFTWAREString[] = SOFTWARE;
-#define COMMANDLINE "CommandLine"
-#define CONFIGFILE  "ConfigFile"
-#undef ChangeServiceConfig2
-typedef BOOL (WINAPI * PFChangeServiceConfig2) (SC_HANDLE, DWORD, LPVOID);
-#ifdef UNICODE
-#define CHANGESERVICECONFIG2 "ChangeServiceConfig2W"
-#else
-#define CHANGESERVICECONFIG2 "ChangeServiceConfig2A"
-#endif
-static SC_ACTION Squid_SCAction[] = { { SC_ACTION_RESTART, 60000 } };
-static char Squid_ServiceDescriptionString[] = SOFTWARENAME " " VERSION " WWW Proxy Server";
-static SERVICE_DESCRIPTION Squid_ServiceDescription = { Squid_ServiceDescriptionString };
-static SERVICE_FAILURE_ACTIONS Squid_ServiceFailureActions = { INFINITE, NULL, NULL, 1, Squid_SCAction };
-static char REGKEY[256]=SOFTWARE"\\"VENDOR"\\"SOFTWARENAME"\\"WIN32_VERSION"\\";
-static char *keys[] = {
-                          SOFTWAREString,	    /* key[0] */
-                          VENDORString,	    /* key[1] */
-                          SOFTWARENAMEString,   /* key[2] */
-                          WIN32_VERSIONString,  /* key[3] */
-                          NULL,	    /* key[4] */
-                          NULL	    /* key[5] */
-                      };
-#endif
-
-/* ====================================================================== */
-/* LOCAL FUNCTIONS */
-/* ====================================================================== */
-
-#if USE_WIN32_SERVICE
-static int
-WIN32_create_key(void)
-{
-    int index;
-    HKEY hKey;
-    HKEY hKeyNext;
-    int retval;
-    LONG rv;
-
-    hKey = HKEY_LOCAL_MACHINE;
-    index = 0;
-    retval = 0;
-
-    /* Walk the tree, creating at each stage if necessary */
-
-    while (keys[index]) {
-        unsigned long result;
-        rv = RegCreateKeyEx(hKey, keys[index],	/* subkey */
-                            0,			/* reserved */
-                            NULL,		/* class */
-                            REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyNext, &result);
-
-        if (rv != ERROR_SUCCESS) {
-            fprintf(stderr, "RegCreateKeyEx(%s),%d\n", keys[index], (int) rv);
-            retval = -4;
-        }
-
-        /* Close the old key */
-        rv = RegCloseKey(hKey);
-
-        if (rv != ERROR_SUCCESS) {
-            fprintf(stderr, "RegCloseKey %d\n", (int) rv);
-
-            if (retval == 0) {
-                /* Keep error status from RegCreateKeyEx, if any */
-                retval = -4;
-            }
-        }
-
-        if (retval) {
-            break;
-        }
-
-        hKey = hKeyNext;
-        index++;
-    }
-
-    if (keys[index] == NULL) {
-        /* Close the final key we opened, if we walked the entire
-         * tree
-         */
-        rv = RegCloseKey(hKey);
-
-        if (rv != ERROR_SUCCESS) {
-            fprintf(stderr, "RegCloseKey %d\n", (int) rv);
-
-            if (retval == 0) {
-                /* Keep error status from RegCreateKeyEx, if any */
-                retval = -4;
-            }
-        }
-    }
-
-    return retval;
-}
-
-static int
-WIN32_StoreKey(const char *key, DWORD type, unsigned char *value,
-               int value_size)
-{
-    LONG rv;
-    HKEY hKey;
-    int retval;
-
-    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_WRITE, &hKey);
-
-    if (rv == ERROR_FILE_NOT_FOUND) {
-        /* Key could not be opened -- try to create it
-         */
-
-        if (WIN32_create_key() < 0) {
-            /* Creation failed (error already reported) */
-            return -4;
-        }
-
-        /* Now it has been created we should be able to open it
-         */
-        rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_WRITE, &hKey);
-
-        if (rv == ERROR_FILE_NOT_FOUND) {
-            fprintf(stderr, "Registry does not contain key %s after creation\n",
-                    REGKEY);
-            return -1;
-        }
-    }
-
-    if (rv != ERROR_SUCCESS) {
-        fprintf(stderr, "RegOpenKeyEx HKLM\\%s, %d\n", REGKEY, (int) rv);
-        return -4;
-    }
-
-    /* Now set the value and data */
-    rv = RegSetValueEx(hKey, key,	/* value key name */
-                       0,			/* reserved */
-                       type,			/* type */
-                       value,			/* value data */
-                       (DWORD) value_size);	/* for size of "value" */
-
-    retval = 0;			/* Return value */
-
-    if (rv != ERROR_SUCCESS) {
-        fprintf(stderr, "RegQueryValueEx(key %s),%d\n", key, (int) rv);
-        retval = -4;
-    } else {
-        fprintf(stderr, "Registry stored HKLM\\%s\\%s value %s\n",
-                REGKEY,
-                key,
-                type == REG_SZ ? value : (unsigned char *) "(not displayable)");
-    }
-
-    /* Make sure we close the key even if there was an error storing
-     * the data
-     */
-    rv = RegCloseKey(hKey);
-
-    if (rv != ERROR_SUCCESS) {
-        fprintf(stderr, "RegCloseKey HKLM\\%s, %d\n", REGKEY, (int) rv);
-
-        if (retval == 0) {
-            /* Keep error status from RegQueryValueEx, if any */
-            retval = -4;
-        }
-    }
-
-    return retval;
-}
-
-/* Build argv, argc from string passed from Windows.  */
-static void WIN32_build_argv(char *cmd)
-{
-    int argvlen = 0;
-    char *word;
-
-    WIN32_argc = 1;
-    WIN32_argv = (char **) xmalloc ((WIN32_argc+1) * sizeof (char *));
-    WIN32_argv[0]=xstrdup(WIN32_module_name);
-    /* Scan command line until there is nothing left. */
-
-    while (*cmd) {
-        /* Ignore spaces */
-
-        if (xisspace(*cmd)) {
-            cmd++;
-            continue;
-        }
-
-        /* Found the beginning of an argument. */
-        word = cmd;
-
-        while (*cmd) {
-            cmd++;		/* Skip over this character */
-
-            if (xisspace(*cmd))	/* End of argument if space */
-                break;
-        }
-
-        if (*cmd)
-            *cmd++ = '\0';		/* Terminate `word' */
-
-        /* See if we need to allocate more space for argv */
-        if (WIN32_argc >= argvlen) {
-            argvlen = WIN32_argc + 1;
-            WIN32_argv = (char **) xrealloc (WIN32_argv, (1 + argvlen) * sizeof (char *));
-        }
-
-        /* Add word to argv file. */
-        WIN32_argv[WIN32_argc++] = word;
-    }
-
-    WIN32_argv[WIN32_argc] = NULL;
-}
-
-#endif /* USE_WIN32_SERVICE */
-
-static unsigned int
-GetOSVersion()
-{
-    OSVERSIONINFO osvi;
-
-    safe_free(WIN32_OS_string);
-    memset(&osvi, '\0', sizeof(OSVERSIONINFO));
-    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-    GetVersionEx((OSVERSIONINFO *) & osvi);
-
-    switch (osvi.dwPlatformId) {
-
-    case VER_PLATFORM_WIN32_NT:
-
-        if (osvi.dwMajorVersion <= 4) {
-            WIN32_OS_string = xstrdup("Windows NT");
-            return _WIN_OS_WINNT;
-        }
-
-        if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) {
-            WIN32_OS_string = xstrdup("Windows 2000");
-            return _WIN_OS_WIN2K;
-        }
-
-        if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) {
-            WIN32_OS_string = xstrdup("Windows XP");
-            return _WIN_OS_WINXP;
-        }
-
-        if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) {
-            WIN32_OS_string = xstrdup("Windows Server 2003");
-            return _WIN_OS_WINNET;
-        }
-
-        if ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 0)) {
-            WIN32_OS_string = xstrdup("Windows code name \"Longhorn\"");
-            return _WIN_OS_WINLON;
-        }
-
-        break;
-
-    case VER_PLATFORM_WIN32_WINDOWS:
-
-        if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)) {
-            WIN32_OS_string = xstrdup("Windows 95");
-            return _WIN_OS_WIN95;
-        }
-
-        if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10)) {
-            WIN32_OS_string = xstrdup("Windows 98");
-            return _WIN_OS_WIN98;
-        }
-
-        if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90)) {
-            WIN32_OS_string = xstrdup("Windows Me");
-            return _WIN_OS_WINME;
-        }
-
-        break;
-
-    case VER_PLATFORM_WIN32s:
-        WIN32_OS_string = xstrdup("Windows 3.1 with WIN32S");
-        return _WIN_OS_WIN32S;
-        break;
-
-    default:
-        break;
-    }
-
-    WIN32_OS_string = xstrdup("Unknown Windows system");
-    return _WIN_OS_UNKNOWN;
-}
-
-/* ====================================================================== */
-/* PUBLIC FUNCTIONS */
-/* ====================================================================== */
-
-void
-WIN32_Abort(int sig)
-{
-#if USE_WIN32_SERVICE
-    svcStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
-    svcStatus.dwServiceSpecificExitCode = 1;
-#endif
-
-    Squid_Aborting = 1;
-    WIN32_Exit();
-}
-
-void
-WIN32_Exit()
-{
-#ifdef _SQUID_MSWIN_
-    Win32SockCleanup();
-#endif
-#if USE_WIN32_SERVICE
-
-    if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
-        if (!Squid_Aborting) {
-            svcStatus.dwCurrentState = SERVICE_STOPPED;
-            SetServiceStatus(svcHandle, &svcStatus);
-        }
-    }
-
-#endif
-#ifdef _SQUID_MSWIN_
-    if (dbg_mutex)
-        DeleteCriticalSection(dbg_mutex);
-
-    WIN32_ExceptionHandlerCleanup();
-
-#endif
-
-    _exit(0);
-}
-
-int WIN32_Subsystem_Init(int * argc, char *** argv)
-{
-#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
-    _invalid_parameter_handler oldHandler, newHandler;
-#endif
-
-    WIN32_OS_version = GetOSVersion();
-
-    if ((WIN32_OS_version == _WIN_OS_UNKNOWN) || (WIN32_OS_version == _WIN_OS_WIN32S))
-        return 1;
-
-    if (atexit(WIN32_Exit) != 0)
-        return 1;
-
-#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
-
-    newHandler = Squid_Win32InvalidParameterHandler;
-
-    oldHandler = _set_invalid_parameter_handler(newHandler);
-
-    _CrtSetReportMode(_CRT_ASSERT, 0);
-
-#endif
-#if USE_WIN32_SERVICE
-
-    if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
-        char path[512];
-        HKEY hndKey;
-
-        if (signal(SIGABRT, WIN32_Abort) == SIG_ERR)
-            return 1;
-
-        /* Register the service Handler function */
-        svcHandle =
-            RegisterServiceCtrlHandler(WIN32_Service_name,
-                                       WIN32_svcHandler);
-
-        if (svcHandle == 0)
-            return 1;
-
-        /* Set Process work dir to directory cointaining squid.exe */
-        GetModuleFileName(NULL, path, 512);
-
-        WIN32_module_name=xstrdup(path);
-
-        path[strlen(path) - 10] = '\0';
-
-        if (SetCurrentDirectory(path) == 0)
-            return 1;
-
-        safe_free(ConfigFile);
-
-        /* get config file from Windows Registry */
-        if (RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY, &hndKey) == ERROR_SUCCESS) {
-            DWORD Type = 0;
-            DWORD Size = 0;
-            LONG Result;
-            Result =
-                RegQueryValueEx(hndKey, CONFIGFILE, NULL, &Type, NULL, &Size);
-
-            if (Result == ERROR_SUCCESS && Size) {
-                ConfigFile = static_cast<char *>(xmalloc(Size));
-                RegQueryValueEx(hndKey, CONFIGFILE, NULL, &Type, (unsigned char *)ConfigFile,
-                                &Size);
-            } else
-                ConfigFile = xstrdup(DefaultConfigFile);
-
-            Size = 0;
-
-            Type = 0;
-
-            Result =
-                RegQueryValueEx(hndKey, COMMANDLINE, NULL, &Type, NULL, &Size);
 
-            if (Result == ERROR_SUCCESS && Size) {
-                WIN32_Service_Command_Line = static_cast<char *>(xmalloc(Size));
-                RegQueryValueEx(hndKey, COMMANDLINE, NULL, &Type, (unsigned char *)WIN32_Service_Command_Line,
-                                &Size);
-            } else
-                WIN32_Service_Command_Line = xstrdup("");
 
-            RegCloseKey(hndKey);
-        } else {
-            ConfigFile = xstrdup(DefaultConfigFile);
-            WIN32_Service_Command_Line = xstrdup("");
-        }
-
-        WIN32_build_argv(WIN32_Service_Command_Line);
-        *argc = WIN32_argc;
-        *argv = WIN32_argv;
-        /* Set Service Status to SERVICE_START_PENDING */
-        svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-        svcStatus.dwCurrentState = SERVICE_START_PENDING;
-        svcStatus.dwControlsAccepted =
-            SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
-        svcStatus.dwWin32ExitCode = 0;
-        svcStatus.dwServiceSpecificExitCode = 0;
-        svcStatus.dwCheckPoint = 0;
-        svcStatus.dwWaitHint = 10000;
-        SetServiceStatus(svcHandle, &svcStatus);
-#ifdef _SQUID_MSWIN_
-
-        _setmaxstdio(Squid_MaxFD);
-#endif
-    }
-
-#endif /* USE_WIN32_SERVICE */
-#ifdef _SQUID_MSWIN_
-    if (Win32SockInit() < 0)
-        return 1;
-
-#endif
-
-    return 0;
-}
-
-#if USE_WIN32_SERVICE
-void
-WIN32_svcstatusupdate(DWORD svcstate, DWORD WaitHint)
-{
-    if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
-        svcStatus.dwCheckPoint++;
-        svcStatus.dwWaitHint = WaitHint;
-        svcStatus.dwCurrentState = svcstate;
-        SetServiceStatus(svcHandle, &svcStatus);
-    }
-}
-
-VOID WINAPI
-WIN32_svcHandler(DWORD Opcode)
-{
-    DWORD status;
-
-    switch (Opcode) {
-
-    case _WIN_SQUID_SERVICE_CONTROL_STOP:
-
-    case _WIN_SQUID_SERVICE_CONTROL_SHUTDOWN:
-        /* Do whatever it takes to stop here. */
-        svcStatus.dwWin32ExitCode = 0;
-        svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
-        svcStatus.dwCheckPoint = 0;
-        svcStatus.dwWaitHint = 10000;
-        shut_down(SIGTERM);
-
-        if (!SetServiceStatus(svcHandle, &svcStatus)) {
-            status = GetLastError();
-            debug(1, 1) ("SetServiceStatus error %ld\n", status);
-        }
-
-        debug(1, 1) ("Leaving Squid service\n");
-        return;
-
-    case _WIN_SQUID_SERVICE_CONTROL_INTERROGATE:
-        /* Fall through to send current status. */
-
-        if (!SetServiceStatus(svcHandle, &svcStatus)) {
-            status = GetLastError();
-            debug(1, 1) ("SetServiceStatus error %ld\n", status);
-        }
-
-        break;
-
-    case _WIN_SQUID_SERVICE_CONTROL_ROTATE:
-        rotate_logs(SIGUSR1);
-        break;
-
-    case _WIN_SQUID_SERVICE_CONTROL_RECONFIGURE:
-        reconfigure(SIGHUP);
-        break;
-
-    case _WIN_SQUID_SERVICE_CONTROL_DEBUG:
-        sigusr2_handle(SIGUSR2);
-        break;
-
-    case _WIN_SQUID_SERVICE_CONTROL_INTERRUPT:
-        /* Do whatever it takes to stop here. */
-        svcStatus.dwWin32ExitCode = 0;
-        svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
-        svcStatus.dwCheckPoint = 0;
-        svcStatus.dwWaitHint = 10000;
-        shut_down(SIGINT);
-
-        if (!SetServiceStatus(svcHandle, &svcStatus)) {
-            status = GetLastError();
-            debug(1, 1) ("SetServiceStatus error %ld\n", status);
-        }
-
-        debug(1, 1) ("Leaving Squid service\n");
-        break;
-
-    default:
-        debug(1, 1) ("Unrecognized opcode %ld\n", Opcode);
-    }
-
-    return;
-}
-
-void
-WIN32_RemoveService()
-{
-    SC_HANDLE schService;
-    SC_HANDLE schSCManager;
-
-    if (!WIN32_Service_name)
-        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
-
-    strcat(REGKEY, WIN32_Service_name);
-
-    keys[4] = WIN32_Service_name;
-
-    schSCManager = OpenSCManager(NULL,	/* machine (NULL == local)    */
-                                 NULL,			/* database (NULL == default) */
-                                 SC_MANAGER_ALL_ACCESS	/* access required            */
-                                );
-
-    if (!schSCManager)
-        fprintf(stderr, "OpenSCManager failed\n");
-    else {
-        schService = OpenService(schSCManager, WIN32_Service_name, SERVICE_ALL_ACCESS);
-
-        if (schService == NULL)
-            fprintf(stderr, "OpenService failed\n");
-
-        /* Could not open the service */
-        else {
-            /* try to stop the service */
-
-            if (ControlService(schService, _WIN_SQUID_SERVICE_CONTROL_STOP,
-                               &svcStatus)) {
-                sleep(1);
-
-                while (QueryServiceStatus(schService, &svcStatus)) {
-                    if (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)
-                        sleep(1);
-                    else
-                        break;
-                }
-            }
-
-            /* now remove the service */
-            if (DeleteService(schService) == 0)
-                fprintf(stderr, "DeleteService failed.\n");
-            else
-                printf("Service %s deleted successfully.\n",
-                       WIN32_Service_name);
-
-            CloseServiceHandle(schService);
-        }
-
-        CloseServiceHandle(schSCManager);
-    }
-}
-
-void
-WIN32_SetServiceCommandLine()
-{
-    if (!WIN32_Service_name)
-        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
-
-    strcat(REGKEY, WIN32_Service_name);
-
-    keys[4] = WIN32_Service_name;
-
-    /* Now store the Service Command Line in the registry */
-    WIN32_StoreKey(COMMANDLINE, REG_SZ, (unsigned char *) WIN32_Command_Line, strlen(WIN32_Command_Line) + 1);
-}
-
-void
-WIN32_InstallService()
-{
-    SC_HANDLE schService;
-    SC_HANDLE schSCManager;
-    char ServicePath[512];
-    char szPath[512];
-    int lenpath;
-
-    if (!WIN32_Service_name)
-        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
-
-    strcat(REGKEY, WIN32_Service_name);
-
-    keys[4] = WIN32_Service_name;
-
-    if ((lenpath = GetModuleFileName(NULL, ServicePath, 512)) == 0) {
-        fprintf(stderr, "Can't get executable path\n");
-        exit(1);
-    }
-
-    snprintf(szPath, sizeof(szPath), "%s %s:%s", ServicePath, _WIN_SQUID_SERVICE_OPTION, WIN32_Service_name);
-    schSCManager = OpenSCManager(NULL,	/* machine (NULL == local)    */
-                                 NULL,			/* database (NULL == default) */
-                                 SC_MANAGER_ALL_ACCESS	/* access required            */
-                                );
-
-    if (!schSCManager) {
-        fprintf(stderr, "OpenSCManager failed\n");
-        exit(1);
-    } else {
-        schService = CreateService(schSCManager,    /* SCManager database     */
-                                   WIN32_Service_name,			    /* name of service        */
-                                   WIN32_Service_name,			    /* name to display        */
-                                   SERVICE_ALL_ACCESS,			    /* desired access         */
-                                   SERVICE_WIN32_OWN_PROCESS,		    /* service type           */
-                                   SERVICE_AUTO_START,			    /* start type             */
-                                   SERVICE_ERROR_NORMAL,		    /* error control type     */
-                                   (const char *) szPath,		    /* service's binary       */
-                                   NULL,				    /* no load ordering group */
-                                   NULL,				    /* no tag identifier      */
-                                   "Tcpip\0AFD\0",			    /* dependencies           */
-                                   NULL,				    /* LocalSystem account    */
-                                   NULL);				    /* no password            */
-
-        if (schService) {
-            if (WIN32_OS_version > _WIN_OS_WINNT) {
-                HMODULE ADVAPI32Handle;
-                PFChangeServiceConfig2 ChangeServiceConfig2;
-                DWORD dwInfoLevel = SERVICE_CONFIG_DESCRIPTION;
-
-                ADVAPI32Handle = GetModuleHandle("advapi32");
-                ChangeServiceConfig2 = (PFChangeServiceConfig2) GetProcAddress(ADVAPI32Handle, CHANGESERVICECONFIG2);
-                ChangeServiceConfig2(schService, dwInfoLevel, &Squid_ServiceDescription);
-                dwInfoLevel = SERVICE_CONFIG_FAILURE_ACTIONS;
-                ChangeServiceConfig2(schService, dwInfoLevel, &Squid_ServiceFailureActions);
-            }
-
-            CloseServiceHandle(schService);
-            /* Now store the config file location in the registry */
-
-            if (!ConfigFile)
-                ConfigFile = xstrdup(DefaultConfigFile);
-
-            WIN32_StoreKey(CONFIGFILE, REG_SZ, (unsigned char *) ConfigFile, strlen(ConfigFile) + 1);
-
-            printf("Squid Cache version %s for %s\n", version_string,
-                   CONFIG_HOST_TYPE);
-
-            printf("installed successfully as %s Windows System Service.\n",
-                   WIN32_Service_name);
-
-            printf
-            ("To run, start it from the Services Applet of Control Panel.\n");
-
-            printf("Don't forget to edit squid.conf before starting it.\n\n");
-        } else {
-            fprintf(stderr, "CreateService failed\n");
-            exit(1);
-        }
-
-        CloseServiceHandle(schSCManager);
-    }
-}
-
-void
-WIN32_sendSignal(int WIN32_signal)
-{
-    SERVICE_STATUS ssStatus;
-    DWORD fdwAccess, fdwControl;
-    SC_HANDLE schService;
-    SC_HANDLE schSCManager;
-
-    if (!WIN32_Service_name)
-        WIN32_Service_name = xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME);
-
-    schSCManager = OpenSCManager(NULL,	/* machine (NULL == local)    */
-                                 NULL,			/* database (NULL == default) */
-                                 SC_MANAGER_ALL_ACCESS	/* access required            */
-                                );
-
-    if (!schSCManager) {
-        fprintf(stderr, "OpenSCManager failed\n");
-        exit(1);
-    }
-
-    /* The required service object access depends on the control. */
-    switch (WIN32_signal) {
-
-    case 0:			/* SIGNULL */
-        fdwAccess = SERVICE_INTERROGATE;
-        fdwControl = _WIN_SQUID_SERVICE_CONTROL_INTERROGATE;
-        break;
-
-    case SIGUSR1:
-        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
-        fdwControl = _WIN_SQUID_SERVICE_CONTROL_ROTATE;
-        break;
-
-    case SIGUSR2:
-        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
-        fdwControl = _WIN_SQUID_SERVICE_CONTROL_DEBUG;
-        break;
-
-    case SIGHUP:
-        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
-        fdwControl = _WIN_SQUID_SERVICE_CONTROL_RECONFIGURE;
-        break;
-
-    case SIGTERM:
-        fdwAccess = SERVICE_STOP;
-        fdwControl = _WIN_SQUID_SERVICE_CONTROL_STOP;
-        break;
-
-    case SIGINT:
-
-    case SIGKILL:
-        fdwAccess = SERVICE_USER_DEFINED_CONTROL;
-        fdwControl = _WIN_SQUID_SERVICE_CONTROL_INTERRUPT;
-        break;
-
-    default:
-        exit(1);
-    }
-
-    /* Open a handle to the service. */
-    schService = OpenService(schSCManager,	/* SCManager database */
-                             WIN32_Service_name,	/* name of service    */
-                             fdwAccess);		/* specify access     */
-
-    if (schService == NULL) {
-        fprintf(stderr, "%s: ERROR: Could not open Service %s\n", appname,
-                WIN32_Service_name);
-        exit(1);
-    } else {
-        /* Send a control value to the service. */
-
-        if (!ControlService(schService,	/* handle of service      */
-                            fdwControl,	/* control value to send  */
-                            &ssStatus)) {	/* address of status info */
-            fprintf(stderr, "%s: ERROR: Could not Control Service %s\n",
-                    appname, WIN32_Service_name);
-            exit(1);
-        } else {
-            /* Print the service status. */
-            printf("\nStatus of %s Service:\n", WIN32_Service_name);
-            printf("  Service Type: 0x%lx\n", ssStatus.dwServiceType);
-            printf("  Current State: 0x%lx\n", ssStatus.dwCurrentState);
-            printf("  Controls Accepted: 0x%lx\n", ssStatus.dwControlsAccepted);
-            printf("  Exit Code: %ld\n", ssStatus.dwWin32ExitCode);
-            printf("  Service Specific Exit Code: %ld\n",
-                   ssStatus.dwServiceSpecificExitCode);
-            printf("  Check Point: %ld\n", ssStatus.dwCheckPoint);
-            printf("  Wait Hint: %ld\n", ssStatus.dwWaitHint);
-        }
-
-        CloseServiceHandle(schService);
-    }
-
-    CloseServiceHandle(schSCManager);
-}
-
-int main(int argc, char **argv)
-{
-    SERVICE_TABLE_ENTRY DispatchTable[] = {
-                                              {NULL, SquidWinSvcMain},
-                                              {NULL, NULL}
-                                          };
-    char *c;
-    char stderr_path[256];
-
-    if ((argc == 2) && strstr(argv[1], _WIN_SQUID_SERVICE_OPTION)) {
-        strcpy(stderr_path, argv[0]);
-        strcat(stderr_path,".log");
-        freopen(stderr_path, "w", stderr);
-        setmode(fileno(stderr), O_TEXT);
-        WIN32_run_mode = _WIN_SQUID_RUN_MODE_SERVICE;
-        opt_no_daemon = 1;
-
-        if (!(c=strchr(argv[1],':'))) {
-            fprintf(stderr, "Bad Service Parameter: %s\n", argv[1]);
-            return 1;
-        }
-
-        WIN32_Service_name = xstrdup(c+1);
-        DispatchTable[0].lpServiceName=WIN32_Service_name;
-        strcat(REGKEY, WIN32_Service_name);
-        keys[4] = WIN32_Service_name;
-
-        if (!StartServiceCtrlDispatcher(DispatchTable)) {
-            fprintf(stderr, "StartServiceCtrlDispatcher error = %ld\n",
-                    GetLastError());
-            return 1;
-        }
-    } else {
-        WIN32_run_mode = _WIN_SQUID_RUN_MODE_INTERACTIVE;
-#ifdef _SQUID_MSWIN_
-
-        opt_no_daemon = 1;
-
-#endif
-
-        return SquidMain(argc, argv);
-    }
-
-    return 0;
-}
-
-#endif /* USE_WIN32_SERVICE */
-
-#if defined(_SQUID_MSWIN_)
 int WIN32_pipe(int handles[2])
 {
     int new_socket;
@@ -1022,64 +153,6 @@
     return 0;
 }
 
-static int Win32SockInit(void)
-{
-    int iVersionRequested;
-    WSADATA wsaData;
-    int err, opt;
-    int optlen = sizeof(opt);
-
-    if (s_iInitCount > 0) {
-        s_iInitCount++;
-        return (0);
-    } else if (s_iInitCount < 0)
-        return (s_iInitCount);
-
-    /* s_iInitCount == 0. Do the initailization */
-    iVersionRequested = MAKEWORD(2, 0);
-
-    err = WSAStartup((WORD) iVersionRequested, &wsaData);
-
-    if (err) {
-        s_iInitCount = -1;
-        return (s_iInitCount);
-    }
-
-    if (LOBYTE(wsaData.wVersion) != 2 ||
-            HIBYTE(wsaData.wVersion) != 0) {
-        s_iInitCount = -2;
-        WSACleanup();
-        return (s_iInitCount);
-    }
-
-    if (WIN32_OS_version !=_WIN_OS_WINNT) {
-        if (::getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&opt, &optlen)) {
-            s_iInitCount = -3;
-            WSACleanup();
-            return (s_iInitCount);
-        } else {
-            opt = opt | SO_SYNCHRONOUS_NONALERT;
-
-            if (::setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen)) {
-                s_iInitCount = -3;
-                WSACleanup();
-                return (s_iInitCount);
-            }
-        }
-    }
-
-    WIN32_Socks_initialized = 1;
-    s_iInitCount++;
-    return (s_iInitCount);
-}
-
-static void Win32SockCleanup(void)
-{
-    if (--s_iInitCount == 0)
-        WSACleanup();
-
-    return;
-}
 
 int Win32__WSAFDIsSet(int fd, fd_set FAR * set
                          )
@@ -1091,11 +164,6 @@
                            );
 }
 
-void Squid_Win32InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
-{
-    return;
-}
-
 LONG CALLBACK WIN32_ExceptionHandler(EXCEPTION_POINTERS* ep)
 {
     EXCEPTION_RECORD* er;
