3 * $Id: win32.cc,v 1.12 2004/12/20 14:52:28 robertc Exp $
5 * * * * * * * * Legal stuff * * * * * * *
7 * (C) 2001 Guido Serassio <serassio@libero.it>,
8 * inspired by previous work by Romeo Anghelache & Eric Stern.
10 * SQUID Web Proxy Cache http://www.squid-cache.org/
11 * ----------------------------------------------------------
13 * Squid is the result of efforts by numerous individuals from
14 * the Internet community; see the CONTRIBUTORS file for full
15 * details. Many organizations have provided support for Squid's
16 * development; see the SPONSORS file for full details. Squid is
17 * Copyrighted (C) 2001 by the Regents of the University of
18 * California; see the COPYRIGHT file for full details. Squid
19 * incorporates software developed and/or copyrighted by other
20 * sources; see the CREDITS file for full details.
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
43 #include "squid_windows.h"
45 static unsigned int GetOSVersion();
46 void WIN32_svcstatusupdate(DWORD
, DWORD
);
47 void WINAPI
WIN32_svcHandler(DWORD
);
49 static int WIN32_StoreKey(const char *, DWORD
, unsigned char *, int);
50 static int WIN32_create_key(void);
51 static void WIN32_build_argv (char *);
53 extern "C" void WINAPI
SquidMain(DWORD
, char **);
55 static int Squid_Aborting
= 0;
57 static SERVICE_STATUS svcStatus
;
58 static SERVICE_STATUS_HANDLE svcHandle
;
59 static int WIN32_argc
;
60 static char ** WIN32_argv
;
61 static char * WIN32_module_name
;
64 static char VENDORString
[] = VENDOR
;
65 #define SOFTWARENAME "Squid"
66 static char SOFTWARENAMEString
[] = SOFTWARENAME
;
67 #define WIN32_VERSION "3.0"
68 static char WIN32_VERSIONString
[] = WIN32_VERSION
;
69 #define SOFTWARE "SOFTWARE"
70 static char SOFTWAREString
[] = SOFTWARE
;
71 #define COMMANDLINE "CommandLine"
72 #define CONFIGFILE "ConfigFile"
73 #undef ChangeServiceConfig2
74 typedef BOOL (WINAPI
* PFChangeServiceConfig2
) (SC_HANDLE
, DWORD
, LPVOID
);
76 #define CHANGESERVICECONFIG2 "ChangeServiceConfig2W"
78 #define CHANGESERVICECONFIG2 "ChangeServiceConfig2A"
80 static SC_ACTION Squid_SCAction
[] = { { SC_ACTION_RESTART
, 60000 } };
81 static char Squid_ServiceDescriptionString
[] = SOFTWARENAME
" " VERSION
" WWW Proxy Server";
82 static SERVICE_DESCRIPTION Squid_ServiceDescription
= { Squid_ServiceDescriptionString
};
83 static SERVICE_FAILURE_ACTIONS Squid_ServiceFailureActions
= { INFINITE
, NULL
, NULL
, 1, Squid_SCAction
};
84 static char REGKEY
[256]=SOFTWARE
"\\"VENDOR
"\\"SOFTWARENAME
"\\"WIN32_VERSION
"\\";
85 static char *keys
[] = {
86 SOFTWAREString
, /* key[0] */
87 VENDORString
, /* key[1] */
88 SOFTWARENAMEString
, /* key[2] */
89 WIN32_VERSIONString
, /* key[3] */
95 /* ====================================================================== */
97 /* ====================================================================== */
101 WIN32_create_key(void)
109 hKey
= HKEY_LOCAL_MACHINE
;
113 /* Walk the tree, creating at each stage if necessary */
115 while (keys
[index
]) {
116 unsigned long result
;
117 rv
= RegCreateKeyEx(hKey
, keys
[index
], /* subkey */
120 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKeyNext
, &result
);
122 if (rv
!= ERROR_SUCCESS
) {
123 fprintf(stderr
, "RegCreateKeyEx(%s),%d\n", keys
[index
], (int) rv
);
127 /* Close the old key */
128 rv
= RegCloseKey(hKey
);
130 if (rv
!= ERROR_SUCCESS
) {
131 fprintf(stderr
, "RegCloseKey %d\n", (int) rv
);
134 /* Keep error status from RegCreateKeyEx, if any */
147 if (keys
[index
] == NULL
) {
148 /* Close the final key we opened, if we walked the entire
151 rv
= RegCloseKey(hKey
);
153 if (rv
!= ERROR_SUCCESS
) {
154 fprintf(stderr
, "RegCloseKey %d\n", (int) rv
);
157 /* Keep error status from RegCreateKeyEx, if any */
167 WIN32_StoreKey(const char *key
, DWORD type
, unsigned char *value
,
174 rv
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, REGKEY
, 0, KEY_WRITE
, &hKey
);
176 if (rv
== ERROR_FILE_NOT_FOUND
) {
177 /* Key could not be opened -- try to create it
180 if (WIN32_create_key() < 0) {
181 /* Creation failed (error already reported) */
185 /* Now it has been created we should be able to open it
187 rv
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, REGKEY
, 0, KEY_WRITE
, &hKey
);
189 if (rv
== ERROR_FILE_NOT_FOUND
) {
190 fprintf(stderr
, "Registry does not contain key %s after creation\n",
196 if (rv
!= ERROR_SUCCESS
) {
197 fprintf(stderr
, "RegOpenKeyEx HKLM\\%s, %d\n", REGKEY
, (int) rv
);
201 /* Now set the value and data */
202 rv
= RegSetValueEx(hKey
, key
, /* value key name */
205 value
, /* value data */
206 (DWORD
) value_size
); /* for size of "value" */
208 retval
= 0; /* Return value */
210 if (rv
!= ERROR_SUCCESS
) {
211 fprintf(stderr
, "RegQueryValueEx(key %s),%d\n", key
, (int) rv
);
214 fprintf(stderr
, "Registry stored HKLM\\%s\\%s value %s\n",
217 type
== REG_SZ
? value
: (unsigned char *) "(not displayable)");
220 /* Make sure we close the key even if there was an error storing
223 rv
= RegCloseKey(hKey
);
225 if (rv
!= ERROR_SUCCESS
) {
226 fprintf(stderr
, "RegCloseKey HKLM\\%s, %d\n", REGKEY
, (int) rv
);
229 /* Keep error status from RegQueryValueEx, if any */
244 safe_free(WIN32_OS_string
);
245 memset(&osvi
, '\0', sizeof(OSVERSIONINFO
));
246 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
247 GetVersionEx((OSVERSIONINFO
*) & osvi
);
249 switch (osvi
.dwPlatformId
) {
251 case VER_PLATFORM_WIN32_NT
:
253 if (osvi
.dwMajorVersion
<= 4) {
254 WIN32_OS_string
= xstrdup("Windows NT");
255 return _WIN_OS_WINNT
;
258 if ((osvi
.dwMajorVersion
== 5) && (osvi
.dwMinorVersion
== 0)) {
259 WIN32_OS_string
= xstrdup("Windows 2000");
260 return _WIN_OS_WIN2K
;
263 if ((osvi
.dwMajorVersion
== 5) && (osvi
.dwMinorVersion
== 1)) {
264 WIN32_OS_string
= xstrdup("Windows XP");
265 return _WIN_OS_WINXP
;
268 if ((osvi
.dwMajorVersion
== 5) && (osvi
.dwMinorVersion
== 2)) {
269 WIN32_OS_string
= xstrdup("Windows Server 2003");
270 return _WIN_OS_WINNET
;
275 case VER_PLATFORM_WIN32_WINDOWS
:
277 if ((osvi
.dwMajorVersion
== 4) && (osvi
.dwMinorVersion
== 0)) {
278 WIN32_OS_string
= xstrdup("Windows 95");
279 return _WIN_OS_WIN95
;
282 if ((osvi
.dwMajorVersion
== 4) && (osvi
.dwMinorVersion
== 10)) {
283 WIN32_OS_string
= xstrdup("Windows 98");
284 return _WIN_OS_WIN98
;
287 if ((osvi
.dwMajorVersion
== 4) && (osvi
.dwMinorVersion
== 90)) {
288 WIN32_OS_string
= xstrdup("Windows Me");
289 return _WIN_OS_WINME
;
294 case VER_PLATFORM_WIN32s
:
295 WIN32_OS_string
= xstrdup("Windows 3.1 with WIN32S");
296 return _WIN_OS_WIN32S
;
303 WIN32_OS_string
= xstrdup("Unknown Windows system");
304 return _WIN_OS_UNKNOWN
;
307 #if USE_WIN32_SERVICE
308 /* Build argv, argc from string passed from Windows. */
309 static void WIN32_build_argv(char *cmd
)
315 WIN32_argv
= (char **) xmalloc ((WIN32_argc
+1) * sizeof (char *));
316 WIN32_argv
[0]=xstrdup(WIN32_module_name
);
317 /* Scan command line until there is nothing left. */
322 if (xisspace(*cmd
)) {
327 /* Found the beginning of an argument. */
331 cmd
++; /* Skip over this character */
333 if (xisspace(*cmd
)) /* End of argument if space */
338 *cmd
++ = '\0'; /* Terminate `word' */
340 /* See if we need to allocate more space for argv */
341 if (WIN32_argc
>= argvlen
) {
342 argvlen
= WIN32_argc
+ 1;
343 WIN32_argv
= (char **) xrealloc (WIN32_argv
, (1 + argvlen
) * sizeof (char *));
346 /* Add word to argv file. */
347 WIN32_argv
[WIN32_argc
++] = word
;
350 WIN32_argv
[WIN32_argc
] = NULL
;
355 /* ====================================================================== */
356 /* PUBLIC FUNCTIONS */
357 /* ====================================================================== */
362 #if USE_WIN32_SERVICE
363 svcStatus
.dwWin32ExitCode
= ERROR_SERVICE_SPECIFIC_ERROR
;
364 svcStatus
.dwServiceSpecificExitCode
= 1;
374 #if USE_WIN32_SERVICE
376 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
) {
377 if (!Squid_Aborting
) {
378 svcStatus
.dwCurrentState
= SERVICE_STOPPED
;
379 SetServiceStatus(svcHandle
, &svcStatus
);
388 #if USE_WIN32_SERVICE
389 int WIN32_Subsystem_Init(int * argc
, char *** argv
)
392 WIN32_Subsystem_Init()
395 WIN32_OS_version
= GetOSVersion();
397 if ((WIN32_OS_version
== _WIN_OS_UNKNOWN
) || (WIN32_OS_version
== _WIN_OS_WIN32S
))
400 if (atexit(WIN32_Exit
) != 0)
403 #if USE_WIN32_SERVICE
405 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
)
410 if (signal(SIGABRT
, WIN32_Abort
) == SIG_ERR
)
413 /* Register the service Handler function */
415 RegisterServiceCtrlHandler(WIN32_Service_name
,
421 /* Set Process work dir to directory cointaining squid.exe */
422 GetModuleFileName(NULL
, path
, 512);
424 WIN32_module_name
=xstrdup(path
);
426 path
[strlen(path
) - 10] = '\0';
428 if (SetCurrentDirectory(path
) == 0)
431 safe_free(ConfigFile
);
433 /* get config file from Windows Registry */
434 if (RegOpenKey(HKEY_LOCAL_MACHINE
, REGKEY
, &hndKey
) == ERROR_SUCCESS
) {
439 RegQueryValueEx(hndKey
, CONFIGFILE
, NULL
, &Type
, NULL
, &Size
);
441 if (Result
== ERROR_SUCCESS
&& Size
) {
442 ConfigFile
= static_cast<char *>(xmalloc(Size
));
443 RegQueryValueEx(hndKey
, CONFIGFILE
, NULL
, &Type
, (unsigned char *)ConfigFile
,
446 ConfigFile
= xstrdup(DefaultConfigFile
);
453 RegQueryValueEx(hndKey
, COMMANDLINE
, NULL
, &Type
, NULL
, &Size
);
455 if (Result
== ERROR_SUCCESS
&& Size
) {
456 WIN32_Service_Command_Line
= static_cast<char *>(xmalloc(Size
));
457 RegQueryValueEx(hndKey
, COMMANDLINE
, NULL
, &Type
, (unsigned char *)WIN32_Service_Command_Line
,
460 WIN32_Service_Command_Line
= xstrdup("");
464 ConfigFile
= xstrdup(DefaultConfigFile
);
465 WIN32_Service_Command_Line
= xstrdup("");
468 WIN32_build_argv(WIN32_Service_Command_Line
);
471 /* Set Service Status to SERVICE_START_PENDING */
472 svcStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
473 svcStatus
.dwCurrentState
= SERVICE_START_PENDING
;
474 svcStatus
.dwControlsAccepted
=
475 SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
;
476 svcStatus
.dwWin32ExitCode
= 0;
477 svcStatus
.dwServiceSpecificExitCode
= 0;
478 svcStatus
.dwCheckPoint
= 0;
479 svcStatus
.dwWaitHint
= 10000;
480 SetServiceStatus(svcHandle
, &svcStatus
);
489 #if USE_WIN32_SERVICE
491 WIN32_svcstatusupdate(DWORD svcstate
, DWORD WaitHint
)
493 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
) {
494 svcStatus
.dwCheckPoint
++;
495 svcStatus
.dwWaitHint
= WaitHint
;
496 svcStatus
.dwCurrentState
= svcstate
;
497 SetServiceStatus(svcHandle
, &svcStatus
);
502 WIN32_svcHandler(DWORD Opcode
)
508 case _WIN_SQUID_SERVICE_CONTROL_STOP
:
510 case _WIN_SQUID_SERVICE_CONTROL_SHUTDOWN
:
511 /* Do whatever it takes to stop here. */
512 svcStatus
.dwWin32ExitCode
= 0;
513 svcStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
514 svcStatus
.dwCheckPoint
= 0;
515 svcStatus
.dwWaitHint
= 10000;
518 if (!SetServiceStatus(svcHandle
, &svcStatus
)) {
519 status
= GetLastError();
520 debug(1, 1) ("SetServiceStatus error %ld\n", status
);
523 debug(1, 1) ("Leaving Squid service\n");
526 case _WIN_SQUID_SERVICE_CONTROL_INTERROGATE
:
527 /* Fall through to send current status. */
529 if (!SetServiceStatus(svcHandle
, &svcStatus
)) {
530 status
= GetLastError();
531 debug(1, 1) ("SetServiceStatus error %ld\n", status
);
536 case _WIN_SQUID_SERVICE_CONTROL_ROTATE
:
537 rotate_logs(SIGUSR1
);
540 case _WIN_SQUID_SERVICE_CONTROL_RECONFIGURE
:
544 case _WIN_SQUID_SERVICE_CONTROL_DEBUG
:
545 sigusr2_handle(SIGUSR2
);
548 case _WIN_SQUID_SERVICE_CONTROL_INTERRUPT
:
549 /* Do whatever it takes to stop here. */
550 svcStatus
.dwWin32ExitCode
= 0;
551 svcStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
552 svcStatus
.dwCheckPoint
= 0;
553 svcStatus
.dwWaitHint
= 10000;
556 if (!SetServiceStatus(svcHandle
, &svcStatus
)) {
557 status
= GetLastError();
558 debug(1, 1) ("SetServiceStatus error %ld\n", status
);
561 debug(1, 1) ("Leaving Squid service\n");
565 debug(1, 1) ("Unrecognized opcode %ld\n", Opcode
);
572 WIN32_RemoveService()
574 SC_HANDLE schService
;
575 SC_HANDLE schSCManager
;
577 if (!WIN32_Service_name
)
578 WIN32_Service_name
= xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME
);
580 strcat(REGKEY
, WIN32_Service_name
);
582 keys
[4] = WIN32_Service_name
;
584 schSCManager
= OpenSCManager(NULL
, /* machine (NULL == local) */
585 NULL
, /* database (NULL == default) */
586 SC_MANAGER_ALL_ACCESS
/* access required */
590 fprintf(stderr
, "OpenSCManager failed\n");
592 schService
= OpenService(schSCManager
, WIN32_Service_name
, SERVICE_ALL_ACCESS
);
594 if (schService
== NULL
)
595 fprintf(stderr
, "OpenService failed\n");
597 /* Could not open the service */
599 /* try to stop the service */
601 if (ControlService(schService
, _WIN_SQUID_SERVICE_CONTROL_STOP
,
605 while (QueryServiceStatus(schService
, &svcStatus
)) {
606 if (svcStatus
.dwCurrentState
== SERVICE_STOP_PENDING
)
613 /* now remove the service */
614 if (DeleteService(schService
) == 0)
615 fprintf(stderr
, "DeleteService failed.\n");
617 printf("Service %s deleted successfully.\n",
620 CloseServiceHandle(schService
);
623 CloseServiceHandle(schSCManager
);
628 WIN32_SetServiceCommandLine()
630 if (!WIN32_Service_name
)
631 WIN32_Service_name
= xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME
);
633 strcat(REGKEY
, WIN32_Service_name
);
635 keys
[4] = WIN32_Service_name
;
637 /* Now store the Service Command Line in the registry */
638 WIN32_StoreKey(COMMANDLINE
, REG_SZ
, (unsigned char *) WIN32_Command_Line
, strlen(WIN32_Command_Line
) + 1);
642 WIN32_InstallService()
644 SC_HANDLE schService
;
645 SC_HANDLE schSCManager
;
646 char ServicePath
[512];
650 if (!WIN32_Service_name
)
651 WIN32_Service_name
= xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME
);
653 strcat(REGKEY
, WIN32_Service_name
);
655 keys
[4] = WIN32_Service_name
;
657 if ((lenpath
= GetModuleFileName(NULL
, ServicePath
, 512)) == 0) {
658 fprintf(stderr
, "Can't get executable path\n");
662 snprintf(szPath
, sizeof(szPath
), "%s %s:%s", ServicePath
, _WIN_SQUID_SERVICE_OPTION
, WIN32_Service_name
);
663 schSCManager
= OpenSCManager(NULL
, /* machine (NULL == local) */
664 NULL
, /* database (NULL == default) */
665 SC_MANAGER_ALL_ACCESS
/* access required */
669 fprintf(stderr
, "OpenSCManager failed\n");
672 schService
= CreateService(schSCManager
, /* SCManager database */
673 WIN32_Service_name
, /* name of service */
674 WIN32_Service_name
, /* name to display */
675 SERVICE_ALL_ACCESS
, /* desired access */
676 SERVICE_WIN32_OWN_PROCESS
, /* service type */
677 SERVICE_AUTO_START
, /* start type */
678 SERVICE_ERROR_NORMAL
, /* error control type */
679 (const char *) szPath
, /* service's binary */
680 NULL
, /* no load ordering group */
681 NULL
, /* no tag identifier */
682 "Tcpip\0AFD\0", /* dependencies */
683 NULL
, /* LocalSystem account */
684 NULL
); /* no password */
687 if ((WIN32_OS_version
== _WIN_OS_WIN2K
) || (WIN32_OS_version
== _WIN_OS_WINXP
)
688 || (WIN32_OS_version
== _WIN_OS_WINNET
)) {
689 HMODULE ADVAPI32Handle
;
690 PFChangeServiceConfig2 ChangeServiceConfig2
;
691 DWORD dwInfoLevel
= SERVICE_CONFIG_DESCRIPTION
;
693 ADVAPI32Handle
= GetModuleHandle("advapi32");
694 ChangeServiceConfig2
= (PFChangeServiceConfig2
) GetProcAddress(ADVAPI32Handle
, CHANGESERVICECONFIG2
);
695 ChangeServiceConfig2(schService
, dwInfoLevel
, &Squid_ServiceDescription
);
696 dwInfoLevel
= SERVICE_CONFIG_FAILURE_ACTIONS
;
697 ChangeServiceConfig2(schService
, dwInfoLevel
, &Squid_ServiceFailureActions
);
700 CloseServiceHandle(schService
);
701 /* Now store the config file location in the registry */
704 ConfigFile
= xstrdup(DefaultConfigFile
);
706 WIN32_StoreKey(CONFIGFILE
, REG_SZ
, (unsigned char *) ConfigFile
, strlen(ConfigFile
) + 1);
708 printf("Squid Cache version %s for %s\n", version_string
,
711 printf("installed successfully as %s Windows System Service.\n",
715 ("To run, start it from the Services Applet of Control Panel.\n");
717 printf("Don't forget to edit squid.conf before starting it.\n\n");
719 fprintf(stderr
, "CreateService failed\n");
723 CloseServiceHandle(schSCManager
);
728 WIN32_sendSignal(int WIN32_signal
)
730 SERVICE_STATUS ssStatus
;
731 DWORD fdwAccess
, fdwControl
;
732 SC_HANDLE schService
;
733 SC_HANDLE schSCManager
;
735 if (!WIN32_Service_name
)
736 WIN32_Service_name
= xstrdup(_WIN_SQUID_DEFAULT_SERVICE_NAME
);
738 schSCManager
= OpenSCManager(NULL
, /* machine (NULL == local) */
739 NULL
, /* database (NULL == default) */
740 SC_MANAGER_ALL_ACCESS
/* access required */
744 fprintf(stderr
, "OpenSCManager failed\n");
748 /* The required service object access depends on the control. */
749 switch (WIN32_signal
) {
751 case 0: /* SIGNULL */
752 fdwAccess
= SERVICE_INTERROGATE
;
753 fdwControl
= _WIN_SQUID_SERVICE_CONTROL_INTERROGATE
;
757 fdwAccess
= SERVICE_USER_DEFINED_CONTROL
;
758 fdwControl
= _WIN_SQUID_SERVICE_CONTROL_ROTATE
;
762 fdwAccess
= SERVICE_USER_DEFINED_CONTROL
;
763 fdwControl
= _WIN_SQUID_SERVICE_CONTROL_DEBUG
;
767 fdwAccess
= SERVICE_USER_DEFINED_CONTROL
;
768 fdwControl
= _WIN_SQUID_SERVICE_CONTROL_RECONFIGURE
;
772 fdwAccess
= SERVICE_STOP
;
773 fdwControl
= _WIN_SQUID_SERVICE_CONTROL_STOP
;
779 fdwAccess
= SERVICE_USER_DEFINED_CONTROL
;
780 fdwControl
= _WIN_SQUID_SERVICE_CONTROL_INTERRUPT
;
787 /* Open a handle to the service. */
788 schService
= OpenService(schSCManager
, /* SCManager database */
789 WIN32_Service_name
, /* name of service */
790 fdwAccess
); /* specify access */
792 if (schService
== NULL
) {
793 fprintf(stderr
, "%s: ERROR: Could not open Service %s\n", appname
,
797 /* Send a control value to the service. */
799 if (!ControlService(schService
, /* handle of service */
800 fdwControl
, /* control value to send */
801 &ssStatus
)) { /* address of status info */
802 fprintf(stderr
, "%s: ERROR: Could not Control Service %s\n",
803 appname
, WIN32_Service_name
);
806 /* Print the service status. */
807 printf("\nStatus of %s Service:\n", WIN32_Service_name
);
808 printf(" Service Type: 0x%lx\n", ssStatus
.dwServiceType
);
809 printf(" Current State: 0x%lx\n", ssStatus
.dwCurrentState
);
810 printf(" Controls Accepted: 0x%lx\n", ssStatus
.dwControlsAccepted
);
811 printf(" Exit Code: %ld\n", ssStatus
.dwWin32ExitCode
);
812 printf(" Service Specific Exit Code: %ld\n",
813 ssStatus
.dwServiceSpecificExitCode
);
814 printf(" Check Point: %ld\n", ssStatus
.dwCheckPoint
);
815 printf(" Wait Hint: %ld\n", ssStatus
.dwWaitHint
);
818 CloseServiceHandle(schService
);
821 CloseServiceHandle(schSCManager
);
824 int main(int argc
, char **argv
)
826 SERVICE_TABLE_ENTRY DispatchTable
[] = {
832 if ((argc
== 2) && strstr(argv
[1], _WIN_SQUID_SERVICE_OPTION
)) {
833 WIN32_run_mode
= _WIN_SQUID_RUN_MODE_SERVICE
;
836 if (!(c
=strchr(argv
[1],':'))) {
837 fprintf(stderr
, "Bad Service Parameter: %s\n", argv
[1]);
841 WIN32_Service_name
= xstrdup(c
+1);
842 DispatchTable
[0].lpServiceName
=WIN32_Service_name
;
843 strcat(REGKEY
, WIN32_Service_name
);
844 keys
[4] = WIN32_Service_name
;
846 if (!StartServiceCtrlDispatcher(DispatchTable
)) {
847 fprintf(stderr
, "StartServiceCtrlDispatcher error = %ld\n",
852 WIN32_run_mode
= _WIN_SQUID_RUN_MODE_INTERACTIVE
;
853 SquidMain(argc
, argv
);
859 #endif /* USE_WIN32_SERVICE */