[prev in list] [next in list] [prev in thread] [next in thread] 

List:       clamav-devel
Subject:    [Clamav-devel] win32 services patch
From:       Mark Weaver <mark-clist () npsl ! co ! uk>
Date:       2010-07-31 16:03:41
Message-ID: 4C54495D.8050405 () npsl ! co ! uk
[Download RAW message or body]

The attached patch adds support for running clamd & freshclam as Windows 
services.  freshclam/clamd --install will install the service.

["service.patch" (text/x-diff)]

Index: freshclam/freshclam.c
===================================================================
--- freshclam/freshclam.c	(revision 1255)
+++ freshclam/freshclam.c	(working copy)
@@ -55,6 +55,12 @@
 #include "shared/output.h"
 #include "shared/misc.h"
 
+#ifdef _WIN32 
+#include "shared/w32_service.h"
+w32_service g_service;
+static HANDLE stopEvent;
+#endif
+
 #include "execute.h"
 #include "manager.h"
 #include "mirman.h"
@@ -65,6 +71,20 @@
 static short foreground = 1;
 char updtmpdir[512];
 
+#ifdef _WIN32
+static BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
+{
+	switch (dwCtrlType) 
+	{
+	case CTRL_C_EVENT:
+	case CTRL_BREAK_EVENT:
+		terminate = 1;
+		SetEvent(stopEvent);
+		return TRUE;
+	}
+	return FALSE;
+}
+#else
 static void sighandler(int sig) {
 
     switch(sig) {
@@ -101,6 +121,7 @@
 
     return;
 }
+#endif
 
 static void writepid(const char *pidfile)
 {
@@ -140,6 +161,10 @@
     mprintf("    --pid=FILE           -p FILE         save daemon's pid in FILE\n");
     mprintf("    --user=USER          -u USER         run as USER\n");
 #endif
+#ifdef _WIN32
+	mprintf("    --install                            install windows service\n");
+	mprintf("    --uninstall                          uninstall windows service\n");
+#endif
     mprintf("    --no-dns                             force old non-DNS verification \
                method\n");
     mprintf("    --checks=#n          -c #n           number of checks per day, 1 <= \
                n <= 50\n");
     mprintf("    --datadir=DIRECTORY                  download new databases into \
DIRECTORY\n"); @@ -198,7 +223,11 @@
     return ret;
 }
 
+#ifdef _WIN32
+int normal_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 {
 	int ret = 52, retcl;
 	const char *dbdir, *cfgfile, *arg = NULL, *pidfile = NULL;
@@ -235,6 +264,19 @@
 	return 0;
     }
 
+#ifdef _WIN32
+	if (optget(opts, "install")->enabled) {
+		w32_service_install(&g_service);
+		optfree(opts);
+		return 0;
+	}
+	if (optget(opts, "uninstall")->enabled) {
+		w32_service_uninstall(&g_service);
+		optfree(opts);
+		return 0;
+	}
+#endif
+
     /* parse the config file */
     cfgfile = optget(opts, "config-file")->strarg;
     pt = strdup(cfgfile);
@@ -387,7 +429,8 @@
     *updtmpdir = 0;
 
 #ifdef _WIN32
-    signal(SIGINT, sighandler);
+	SetConsoleCtrlHandler(CtrlHandler, TRUE);
+	stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 #else
     memset(&sigact, 0, sizeof(struct sigaction));
     sigact.sa_handler = sighandler;
@@ -421,17 +464,19 @@
 
 	bigsleep = 24 * 3600 / checks;
 
-#ifndef _WIN32
 	if(!optget(opts, "Foreground")->enabled) {
+#ifdef _WIN32
+	g_service.update_scm(&g_service, SERVICE_RUNNING, 0, 1000);
+#else
 	    if(daemonize() == -1) {
 		logg("!daemonize() failed\n");
 		optfree(opts);
 		return 70; /* FIXME */
 	    }
+#endif
             foreground = 0;
 	    mprintf_disabled = 1;
         }
-#endif
 
 	if((opt = optget(opts, "PidFile"))->enabled) {
 	    pidfile = opt->strarg;
@@ -467,7 +512,7 @@
 #endif
 
 #ifdef	_WIN32
-	    sleep(bigsleep);
+		WaitForSingleObject(stopEvent, bigsleep * 1000);
 #else   
 	    time(&wakeup);
 	    wakeup += bigsleep;
@@ -519,5 +564,62 @@
 
     optfree(opts);
 
+#ifdef _WIN32
+	CloseHandle(stopEvent);
+#endif
+
     return(ret);
 }
+
+#ifdef _WIN32
+
+static int w32_service_main(w32_service *s, DWORD argc, LPTSTR *argv)
+{
+	DWORD i;
+	char **argv2;
+
+	/* Need to force a -d in for freshclam */
+	argv2 = (char **)malloc(sizeof(char *) * (argc + 2));
+	if (!argv2) {
+		return ERROR_OUTOFMEMORY;
+	}
+	for (i = 0; i < argc; ++i) {
+		argv2[i] = argv[i];
+	}
+	argv2[argc++] = "-d";
+	(void)normal_main(argc, argv2);
+	free(argv2);
+	return 0;
+}
+
+static void w32_service_stop(w32_service *s)
+{
+	s->update_scm(s, SERVICE_STOP_PENDING, 0, 60000);
+	terminate = 1;
+	SetEvent(stopEvent);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	if (!w32_service_create(&g_service)) {
+		fprintf(stderr, "Failed to create a win32 service object\n");
+		return 56;
+	}
+	g_service.name = "freshclam";
+	g_service.display_name = "Clam AntiVirus Update Service";
+	g_service.description = "Automatically keeps the virus scanning database up to \
date, downloading new versions as they become available."; +	g_service.main_fn = \
w32_service_main; +	g_service.stop = w32_service_stop;
+
+	for (i = 1; i < argc; ++i) {
+		if (strcasecmp(argv[i], "--service") == 0) {
+			w32_services_start();
+			return 0;
+		}
+	}
+	return normal_main((int)argc, argv);
+}
+
+#endif
Index: shared/w32_service.h
===================================================================
--- shared/w32_service.h	(revision 0)
+++ shared/w32_service.h	(revision 0)
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (C) 2001-2010 Mark Weaver <mark@npsl.co.uk>
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __W32_SERVICE_H
+#define __W32_SERVICE_H
+
+/**
+ * Win32 service wrapper (adapted from OW32)
+ */
+typedef struct w32_service_s
+{
+	/* Service information */
+	/* At a minimum you need to set the name & display_name */
+	LPCTSTR name;
+	LPCTSTR display_name;
+	LPCTSTR description;
+	DWORD desired_access;
+	DWORD service_type;
+	DWORD start_type;
+	DWORD error_control;
+	LPCTSTR binary_path_name;
+	LPCTSTR load_order_group;
+	LPCTSTR dependencies;
+	LPCTSTR start_name;
+	LPCTSTR password;
+
+	/* Main function for service (can be overridden if desired) */
+	DWORD (*main_fn)(struct w32_service_s *s, DWORD argc, LPTSTR *argv);
+
+	/* Service status handle, in case you want to do something */
+	/* special the UpdateSCM doesn't cover. */
+	SERVICE_STATUS_HANDLE service_status;
+
+	/* Helper to update the SCM */
+	void (*update_scm)(struct w32_service_s *s, DWORD state, DWORD check_point, DWORD \
wait_hint); +
+	/* The service handler, override for custom control notifications */
+	/* Call the base handler (w32_service_handler) to dispatch to stop, pause, etc.. */
+	void (*handler)(struct w32_service_s *s, DWORD fdwControl);
+
+	/* Called when the stop signal is received */
+	void (*stop)(struct w32_service_s *s);
+	/* Called on pause */
+	void (*pause)(struct w32_service_s *s);
+	/* Called on continue */
+	void (*continue_)(struct w32_service_s *s);
+	/* Called on system shutdown */
+	void (*shutdown)(struct w32_service_s *s);
+	/* Called on interrogate, defaults to "running" */
+	void (*interrogate)(struct w32_service_s *s);
+} w32_service;
+
+/** Create a service with default options */
+int w32_service_create(w32_service *s);
+/** Install a service */
+void w32_service_install(w32_service *s);
+/** Uninstall a service */
+void w32_service_uninstall(w32_service *s);
+/** Start all services in this process */
+int w32_services_start();
+
+#endif /* __W32_SERVICE_H */

Property changes on: shared\w32_service.h
___________________________________________________________________
Added: svn:eol-style
   + native

Index: shared/optparser.c
===================================================================
--- shared/optparser.c	(revision 1255)
+++ shared/optparser.c	(working copy)
@@ -120,6 +120,12 @@
     { NULL, "non-default", 'n', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMCONF, "", \
                "" },
     { NULL, "generate-config", 'g', TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMCONF, \
"", "" },  
+#ifdef _WIN32
+	/* options for windows services */
+    { NULL, "install", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | \
OPT_CLAMD, "", "" }, +    { NULL, "uninstall", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, \
OPT_FRESHCLAM | OPT_CLAMD, "", "" }, +#endif
+
     { NULL, "force-interpreter", 'f', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, \
                "Force using the interpreter instead of the JIT", "" },
     { NULL, "trust-bytecode", 't', TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMBC, \
                "Trust loaded bytecode (default yes)", ""},
     { NULL, "bytecode-trust-all", 't', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, \
                OPT_CLAMSCAN, "Trust loaded bytecode (default: only if signed)", ""},
Index: shared/w32_service.c
===================================================================
--- shared/w32_service.c	(revision 0)
+++ shared/w32_service.c	(revision 0)
@@ -0,0 +1,468 @@
+/*
+ *  Copyright (C) 2001-2010 Mark Weaver <mark@npsl.co.uk>
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <tchar.h>
+#include "w32_service.h"
+
+static void w32_service_stop(w32_service *s);
+static void w32_service_pause(w32_service *s);
+static void w32_service_shutdown(w32_service *s);
+static void w32_service_continue(w32_service *s);
+static void w32_service_interrogate(w32_service *s);
+static LPTSTR GetErrorMessage(DWORD dwErr);
+static void ReportError(LPCTSTR lpPrefix, DWORD dwErr);
+static void w32_service_handler(w32_service *s, DWORD fdwControl);
+static void w32_service_update_scm(w32_service *s, DWORD state, DWORD check_point, \
DWORD wait_hint); +static DWORD w32_service_main(w32_service *s, DWORD argc, LPTSTR \
*argv); +static void WINAPI w32_api_service_main(DWORD dwArgc, LPTSTR* lpszArgv);
+static void WINAPI w32_api_service_handler(DWORD fdwControl);
+
+extern w32_service g_service;
+
+/**
+ * Make a service object
+ */
+int w32_service_create(w32_service *s)
+{
+	s->name = NULL;
+	s->display_name = NULL;
+	s->description = NULL;
+	s->desired_access = STANDARD_RIGHTS_REQUIRED;
+	s->service_type = SERVICE_WIN32_OWN_PROCESS;
+	s->start_type = SERVICE_AUTO_START;
+	s->error_control = SERVICE_ERROR_NORMAL;
+	s->binary_path_name = NULL;
+	s->load_order_group = NULL;
+	s->dependencies = NULL;
+	s->start_name = NULL;
+	s->password = NULL;
+	s->stop = w32_service_stop;
+	s->pause = w32_service_pause;
+	s->continue_ = w32_service_continue;
+	s->shutdown = w32_service_shutdown;
+	s->interrogate = w32_service_interrogate;
+	s->handler = w32_service_handler;
+	s->main_fn = w32_service_main;
+	s->update_scm = w32_service_update_scm;
+	return 1;
+}
+
+static void w32_service_stop(w32_service *s)
+{
+	s;
+}
+
+static void w32_service_shutdown(w32_service *s)
+{
+	s;
+}
+
+static void w32_service_pause(w32_service *s)
+{
+	s;
+}
+
+static void w32_service_continue(w32_service *s)
+{
+	s;
+}
+
+static void w32_service_interrogate(w32_service *s)
+{
+	s->update_scm(s, SERVICE_RUNNING, 0, 1000);
+}
+
+static DWORD w32_service_main(w32_service *s, DWORD argc, LPTSTR *argv)
+{
+	s;
+	argc;
+	argv;
+	return 0;
+}
+
+static LPTSTR GetErrorMessage(DWORD dwErr)
+{
+	LPVOID lpBuffer;
+	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, /* \
flags */ +				  0, /* source (if hmodule/string) */
+				  dwErr, /* message id */
+				  0, /* lang id */
+				  (LPTSTR)&lpBuffer, /* output buffer */
+				  0, /* max char count */
+				  NULL) == 0) /* args */
+		return NULL;
+	return (LPTSTR)lpBuffer;
+}
+
+static void ReportError(LPCTSTR lpPrefix, DWORD dwErr)
+{
+	LPTSTR msg = GetErrorMessage(dwErr);
+	if (msg == NULL) {
+		_ftprintf(stderr, _T("%s, error code = %d\n"), lpPrefix, dwErr);
+	} else {
+		_ftprintf(stderr, _T("%s: %s\n"), lpPrefix, msg);
+		if (msg) LocalFree(msg);
+	}
+}
+
+void w32_service_install(w32_service *s)
+{
+	TCHAR path[MAX_PATH];
+	SC_HANDLE hSM;
+	SC_HANDLE hService;
+	TCHAR EventLogKeyName[MAX_PATH];
+	HKEY hk;
+	LONG lErr;
+	DWORD dwData;
+	HMODULE hADVAPI;
+
+	hSM = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE);
+	if (hSM == NULL) {
+		ReportError(_T("OpenSCManager"),GetLastError());
+		return;
+	}
+
+	if (!s->binary_path_name)
+	{
+		TCHAR module_path[MAX_PATH];
+		if (!GetModuleFileName(NULL, module_path, MAX_PATH))
+		{
+			ReportError(_T("GetModuleFileName"),GetLastError());
+			CloseServiceHandle(hSM);
+			return;
+		}
+		_sntprintf(path, MAX_PATH, _T("%s --service"), module_path);
+		path[MAX_PATH - 1] = _T('\0');
+	}
+
+	hService = CreateService(
+					hSM,  /* service manager */
+					s->name, /* net stop name */
+					s->display_name, /* friendly name */
+					SERVICE_CHANGE_CONFIG|s->desired_access, /* default access to \
interrogate/start/stop */ +					s->service_type, /* this process runs only 1 service \
*/ +					s->start_type, /* start on boot */
+					s->error_control, /* log error/display message box */
+					s->binary_path_name ? s->binary_path_name : path, /* module path */
+					s->load_order_group, /* load order group */
+					NULL, /* load order tag */
+					s->dependencies, /* dependencies */
+					s->start_name, /* run under local system account */
+					s->password /* no password */
+					);
+	if (!hService) {
+
+		/* If the service already exists, then try and update the settings to
+		   the new ones */
+		if (GetLastError() == ERROR_SERVICE_EXISTS)
+		{
+			hService = OpenService(hSM, s->name, SERVICE_ALL_ACCESS);
+			if (!hService)
+			{
+				ReportError(_T("The service exists, but could not be opened to update the \
settings"),GetLastError()); +			} 
+			else 
+			{
+				BOOL bRet;
+				DWORD dwBytesNeeded;
+				LPBYTE pServiceConfig = (LPBYTE)LocalAlloc(LPTR, \
sizeof(QUERY_SERVICE_CONFIG)+1024); +
+				if (!pServiceConfig)
+				{
+					ReportError(_T("Out of memory"),GetLastError());
+					CloseServiceHandle(hService);
+					CloseServiceHandle(hSM);
+					return;
+				}
+				dwBytesNeeded = 0;
+				bRet = QueryServiceConfig(hService, (LPQUERY_SERVICE_CONFIG)pServiceConfig, 
+											   sizeof(QUERY_SERVICE_CONFIG), &dwBytesNeeded);
+				if (!bRet)
+				{
+					if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+						ReportError(_T("QueryServiceConfig failed"),GetLastError());
+					else
+					{
+						LocalFree(pServiceConfig);
+						pServiceConfig = (LPBYTE)LocalAlloc(LPTR, dwBytesNeeded);
+						if (!pServiceConfig)
+						{
+							ReportError(_T("Out of memory"),GetLastError());
+							CloseServiceHandle(hService);
+							CloseServiceHandle(hSM);
+							return;
+						}
+					}
+					bRet = QueryServiceConfig(hService, (LPQUERY_SERVICE_CONFIG)pServiceConfig,
+											  dwBytesNeeded, &dwBytesNeeded);
+				}
+
+				if (bRet)
+				{
+					LPQUERY_SERVICE_CONFIG pTheConfig = (LPQUERY_SERVICE_CONFIG)pServiceConfig;
+
+					if (!ChangeServiceConfig(hService, s->service_type, pTheConfig->dwStartType, \
s->error_control,  +						s->binary_path_name ? s->binary_path_name : path, \
s->load_order_group, NULL,  +						s->dependencies, s->start_name, s->password, \
s->display_name)) +					{
+						ReportError(_T("The service exists, but the configuration could not be \
updated"),GetLastError()); +					}
+				}
+				if (pServiceConfig)
+					LocalFree(pServiceConfig);
+			}
+		}
+		else
+		{
+			ReportError(_T("CreateService failed"),GetLastError());
+		}
+	}
+	
+	/* Set the long description if possible (NT5+) */
+	hADVAPI = LoadLibrary(_T("advapi32.dll"));
+	if (hADVAPI)
+	{
+		typedef BOOL (WINAPI *ChangeServiceConfig2_fn)(SC_HANDLE hService, DWORD \
dwInfoLevel, LPVOID lpInfo); +		ChangeServiceConfig2_fn pChangeServiceConfig2;
+		SERVICE_DESCRIPTION desc;
+
+
+		pChangeServiceConfig2 = (ChangeServiceConfig2_fn)GetProcAddress(hADVAPI, 
+#ifdef _UNICODE
+			"ChangeServiceConfig2W"
+#else
+			"ChangeServiceConfig2A"
+#endif
+			);
+
+		if (pChangeServiceConfig2) 
+		{
+			desc.lpDescription = _tcsdup(s->description ? s->description : "");
+			if (desc.lpDescription == NULL) 
+			{
+				ReportError(_T("Couldn't copy description string"), ERROR_OUTOFMEMORY);
+				/* continue anyway */
+			} 
+			else 
+			{
+				if (!pChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &desc))
+				{
+					ReportError(_T("ChangeServiceConfig2 failed, ignoring"), GetLastError());
+				}
+				free(desc.lpDescription);
+			}
+		}
+		FreeLibrary(hADVAPI);
+	}
+
+	CloseServiceHandle(hSM);
+	CloseServiceHandle(hService);
+
+	_sntprintf(EventLogKeyName, MAX_PATH, \
_T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"), s->name); \
+	EventLogKeyName[MAX_PATH - 1] = _T('\0'); +
+	/* register the app as an event source */
+	if ((lErr=RegCreateKey(HKEY_LOCAL_MACHINE,
+			EventLogKeyName,
+			&hk)) != ERROR_SUCCESS) {
+		ReportError(_T("RegCreateKey for event source"),lErr);
+		return;
+	}
+
+	/* set the name of the message file */
+	if ((lErr=RegSetValueEx(hk, _T("EventMessageFile"), 0, REG_EXPAND_SZ, 
+			(const BYTE *)(s->binary_path_name ? s->binary_path_name : path), 
+			(DWORD)((_tcslen(path)+1)*sizeof(TCHAR)))) != ERROR_SUCCESS) 
+	{
+		ReportError(_T("RegSetValueEx for EventMessageFile"),lErr);
+		RegCloseKey(hk);
+		return;
+	}
+
+	/* set the supported event types in the TypesSupported value */
+	dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+	if ((lErr=RegSetValueEx(hk, _T("TypesSupported"), 0, REG_DWORD, (LPBYTE)&dwData, \
sizeof(DWORD))) != +		ERROR_SUCCESS) {
+		ReportError(_T("RegSetValueEx for TypesSupported"),lErr);
+		RegCloseKey(hk);
+		return;
+	}
+	RegCloseKey(hk);
+}
+
+void w32_service_uninstall(w32_service *s)
+{
+	SC_HANDLE hSM;
+	SC_HANDLE hService;
+	LONG lErr;
+	TCHAR EventLogKeyName[MAX_PATH];
+	
+	hSM = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
+	if (hSM == NULL) {
+		ReportError(_T("OpenSCManager for deletion"),GetLastError());
+		return;
+	}
+	hService = OpenService(hSM, s->name, STANDARD_RIGHTS_REQUIRED);
+	if (hService == NULL) {
+		ReportError(_T("OpenService for deletion"),GetLastError());
+		CloseServiceHandle(hSM);
+		return;
+	}
+	if (!DeleteService(hService)) {
+		ReportError(_T("DeleteService"),GetLastError());
+		CloseServiceHandle(hService);
+		CloseServiceHandle(hSM);
+		return;
+	}
+	CloseServiceHandle(hService);
+	CloseServiceHandle(hSM);
+
+	/* work out the name of the event log key */
+	_sntprintf(EventLogKeyName, MAX_PATH, \
_T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"), s->name); \
+	EventLogKeyName[MAX_PATH - 1] = _T('\0'); +
+	/* delete registry key for event source */
+	if ((lErr=RegDeleteKey(HKEY_LOCAL_MACHINE, EventLogKeyName)) != ERROR_SUCCESS) {
+		ReportError(_T("RegDeleteKey for event viewer source"),lErr);
+		return;
+	}
+}
+
+int w32_services_start()
+{
+	int					ret = 0;
+	SERVICE_TABLE_ENTRY dispatchTable[2] = {0};
+
+	/* Check the service is registered */
+	if (!g_service.name)
+		goto err;
+
+	/* Make a dispatch table.  Need to copy service names (broken API?) */
+	dispatchTable[0].lpServiceName = _tcsdup(g_service.name);
+	if (dispatchTable[0].lpServiceName == NULL) {
+		SetLastError(ERROR_OUTOFMEMORY);
+		goto err;
+	}
+	dispatchTable[0].lpServiceProc = w32_api_service_main;
+
+	dispatchTable[1].lpServiceName = NULL;
+	dispatchTable[1].lpServiceProc = NULL;
+
+	/* Kick them off */
+	if (StartServiceCtrlDispatcher(dispatchTable))
+		ret = 1;
+
+err:
+	free(dispatchTable[0].lpServiceName);
+
+	if (!ret) {
+		ReportError(_T("Starting services failed"), GetLastError());
+	}
+	return ret;
+}
+
+/*
+ * Tell the Service Control Manager the state of the service
+ */
+static void w32_service_update_scm(w32_service *s, DWORD state, DWORD check_point, \
DWORD wait_hint) +{
+	SERVICE_STATUS ss;
+
+	if (s->service_status)
+	{
+		memset(&ss, 0, sizeof(SERVICE_STATUS));
+		ss.dwServiceType = s->service_type;
+		ss.dwCurrentState = state;
+		ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+		ss.dwCheckPoint = check_point;
+		ss.dwServiceSpecificExitCode = 0;
+		ss.dwWin32ExitCode = NO_ERROR;
+		ss.dwWaitHint = wait_hint;
+
+		if (!SetServiceStatus(s->service_status, &ss))
+		{
+			ss.dwCurrentState = SERVICE_STOPPED;
+			SetServiceStatus(s->service_status, &ss);
+		}
+	}
+}
+
+static void w32_service_handler(w32_service *s, DWORD fdwControl)
+{
+	switch (fdwControl) {
+	case SERVICE_CONTROL_STOP:
+		s->stop(s);
+		break;
+
+	case SERVICE_CONTROL_PAUSE:
+		s->pause(s);
+		break;
+
+	case SERVICE_CONTROL_CONTINUE:
+		s->continue_(s);
+		break;
+
+	case SERVICE_CONTROL_SHUTDOWN:
+		s->shutdown(s);
+		break;
+
+	case SERVICE_CONTROL_INTERROGATE:
+		s->interrogate(s);
+		break;
+	}
+}
+
+
+/* Win32 callbacks */
+static void WINAPI w32_api_service_handler(DWORD fdwControl)
+{
+	w32_service *s = &g_service;
+	s->handler(s, fdwControl);
+}
+
+static void WINAPI w32_api_service_main(DWORD argc, LPTSTR* argv)
+{
+	w32_service *s = &g_service;
+
+	/* Register the callback */
+	s->service_status = RegisterServiceCtrlHandler(s->name, w32_api_service_handler);
+
+	/* Initialise the status object */
+	if (s->service_status)
+	{
+		SERVICE_STATUS ss;
+
+		memset(&ss, 0, sizeof(SERVICE_STATUS));
+		ss.dwServiceType = s->service_type;
+		ss.dwCurrentState = SERVICE_START_PENDING;
+		ss.dwControlsAccepted = 0;
+		ss.dwCheckPoint = 0;
+		ss.dwServiceSpecificExitCode = 0;
+		ss.dwWin32ExitCode = 0;
+		ss.dwWaitHint = 60000;
+
+		(void)SetServiceStatus(s->service_status, &ss);
+		ss.dwWin32ExitCode = s->main_fn(s, argc, argv);
+		ss.dwWaitHint = 0;
+		ss.dwCurrentState = SERVICE_STOPPED;
+		(void)SetServiceStatus(s->service_status, &ss);
+	}
+}

Property changes on: shared\w32_service.c
___________________________________________________________________
Added: svn:eol-style
   + native

Index: clamd/server-th.c
===================================================================
--- clamd/server-th.c	(revision 1255)
+++ clamd/server-th.c	(working copy)
@@ -692,10 +692,10 @@
 	struct sigaction sigact;
 	sigset_t sigset;
 	struct rlimit rlim;
+	char buff[BUFFSIZE + 1];
 #endif
 	mode_t old_umask;
 	const struct optstruct *opt;
-	char buff[BUFFSIZE + 1];
 	pid_t mainpid;
 	int idletimeout;
 	unsigned long long val;
@@ -1064,10 +1064,7 @@
 	    cl_engine_free(engine);
 	    return 1;
 	}
-#ifdef _WIN32
-	event_wake_accept = CreateEvent(NULL, TRUE, FALSE, NULL);
-	event_wake_recv = CreateEvent(NULL, TRUE, FALSE, NULL);
-#else
+#ifndef _WIN32
     if (pipe(acceptdata.syncpipe_wake_recv) == -1 ||
 	(pipe(acceptdata.syncpipe_wake_accept) == -1)) {
 
@@ -1340,10 +1337,7 @@
 
     pthread_join(accept_th, NULL);
     fds_free(fds);
-#ifdef _WIN32
-    CloseHandle(event_wake_accept);
-    CloseHandle(event_wake_recv);
-#else
+#ifndef _WIN32
     close(acceptdata.syncpipe_wake_accept[1]);
     close(acceptdata.syncpipe_wake_recv[1]);
 #endif
Index: clamd/clamd.c
===================================================================
--- clamd/clamd.c	(revision 1255)
+++ clamd/clamd.c	(working copy)
@@ -68,6 +68,11 @@
 #include "others.h"
 #include "shared.h"
 
+#ifdef _WIN32
+#include "shared/w32_service.h"
+w32_service g_service;
+#endif
+
 short debug_mode = 0, logok = 0;
 short foreground = 0;
 
@@ -82,6 +87,10 @@
     printf("    --version                -V             Show version number.\n");
     printf("    --debug                                 Enable debug mode.\n");
     printf("    --config-file=FILE       -c FILE        Read configuration from \
FILE.\n\n"); +#ifdef _WIN32
+	printf("    --install                               Install windows service.\n");
+	printf("    --uninstall                             Uninstall windows service.\n");
+#endif
 }
 
 static struct optstruct *opts;
@@ -100,7 +109,11 @@
     }
 }
 
+#ifdef _WIN32
+int normal_main(int argc, char **argv)
+#else
 int main(int argc, char **argv)
+#endif
 {
         static struct cl_engine *engine = NULL;
 	const struct optstruct *opt;
@@ -140,6 +153,19 @@
 	return 0;
     }
 
+#ifdef _WIN32
+	if (optget(opts, "install")->enabled) {
+		w32_service_install(&g_service);
+		optfree(opts);
+		return 0;
+	}
+	if (optget(opts, "uninstall")->enabled) {
+		w32_service_uninstall(&g_service);
+		optfree(opts);
+		return 0;
+	}
+#endif
+
     if(optget(opts, "debug")->enabled) {
 #if defined(C_LINUX)
 	    /* njh@bandsman.co.uk: create a dump if needed */
@@ -516,6 +542,7 @@
 
 	nlsockets++;
     }
+#endif
 
     /* fork into background */
     if(!optget(opts, "Foreground")->enabled) {
@@ -527,11 +554,15 @@
 #endif
 	gengine = engine;
 	atexit(free_engine);
+#ifndef _WIN32
 	if(daemonize() == -1) {
 	    logg("!daemonize() failed\n");
 	    ret = 1;
 	    break;
 	}
+#else
+	g_service.update_scm(&g_service, SERVICE_RUNNING, 0, 1000);
+#endif
 	gengine = NULL;
 #ifdef C_BSD
 	for(ret=0;ret<nlsockets;ret++) {
@@ -544,7 +575,6 @@
 
     } else
         foreground = 1;
-#endif
 
     ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);
 
@@ -571,3 +601,73 @@
 
     return ret;
 }
+
+#ifdef _WIN32
+
+extern void *event_wake_recv;
+extern void *event_wake_accept;
+
+BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
+{
+    switch (dwCtrlType) 
+    {
+    case CTRL_C_EVENT:
+    case CTRL_BREAK_EVENT:
+	progexit = 1;
+	if (!SetEvent(event_wake_recv)) {
+	    logg("$Failed to wake recv thread with %lu\n", GetLastError());
+	}
+	return TRUE;
+    }
+    return FALSE;
+}
+
+static int w32_service_main(w32_service *s, DWORD argc, LPTSTR *argv)
+{
+    return normal_main(argc, argv);
+}
+
+static void w32_service_stop(w32_service *s)
+{
+    s->update_scm(s, SERVICE_STOP_PENDING, 0, 60000);
+    progexit = 1;
+    SetEvent(event_wake_recv);
+}
+
+int main(int argc, char **argv)
+{
+    int i, ret;
+
+    event_wake_recv = CreateEvent(NULL, TRUE, FALSE, NULL);
+	event_wake_accept = CreateEvent(NULL, TRUE, FALSE, NULL);
+    if (!event_wake_recv || !event_wake_accept) {
+	if (event_wake_accept) CloseHandle(event_wake_accept);
+	if (event_wake_recv) CloseHandle(event_wake_recv);
+	fprintf(stderr, "Failed to create an event with %lu\n", GetLastError());
+	return 56;
+    }
+    SetConsoleCtrlHandler(CtrlHandler, TRUE);
+
+    if (!w32_service_create(&g_service)) {
+	fprintf(stderr, "Failed to create a win32 service object\n");
+	return 56;
+    }
+    g_service.name = "clamd";
+    g_service.display_name = "Clam AntiVirus Scanner Service";
+    g_service.description = "Provides virus scanning services for the local \
machine."; +    g_service.main_fn = w32_service_main;
+    g_service.stop = w32_service_stop;
+
+    for (i = 1; i < argc; ++i) {
+        if (strcasecmp(argv[i], "--service") == 0) {
+	    w32_services_start();
+	    return 0;
+	}
+    }
+
+    ret = normal_main((int)argc, argv);
+    CloseHandle(event_wake_recv);
+	CloseHandle(event_wake_accept);
+    return ret;
+}
+#endif

Property changes on: win32
___________________________________________________________________
Added: svn:ignore
   + build


Index: win32/freshclam.vcproj
===================================================================
--- win32/freshclam.vcproj	(revision 1255)
+++ win32/freshclam.vcproj	(working copy)
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
-	Keyword="Win32Proj"
+	ProjectType="Visual C++"
+	Version="9.00"
 	Name="freshclam"
 	ProjectGUID="{CEA52DD8-0418-42AD-B640-F33CC7C600CE}"
-	ProjectType="Visual C++"
 	RootNamespace="freshclam"
+	Keyword="Win32Proj"
 	TargetFrameworkVersion="196613"
-	Version="9,00"
 	>
 	<Platforms>
 		<Platform
@@ -17,11 +17,11 @@
 	</ToolFiles>
 	<Configurations>
 		<Configuration
-			CharacterSet="2"
-			ConfigurationType="1"
-			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
 			Name="Debug|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -39,18 +39,18 @@
 				Name="VCMIDLTool"
 			/>
 			<Tool
-				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
-				BasicRuntimeChecks="3"
-				CompileAs="1"
-				DebugInformationFormat="3"
-				DisableSpecificWarnings="4996;4244;4018;4090;4333;4101;4146;4102"
-				MinimalRebuild="true"
 				Name="VCCLCompilerTool"
 				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
 				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H;_BIND_TO_CURRENT_VCLIBS_VERSION=1"
 +				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
+				DebugInformationFormat="3"
+				CompileAs="1"
+				DisableSpecificWarnings="4996;4244;4018;4090;4333;4101;4146;4102"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -62,10 +62,10 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
+				Name="VCLinkerTool"
 				AdditionalDependencies="dnsapi.lib"
+				LinkIncremental="1"
 				GenerateDebugInformation="true"
-				LinkIncremental="1"
-				Name="VCLinkerTool"
 				SubSystem="1"
 				TargetMachine="1"
 			/>
@@ -92,11 +92,11 @@
 			/>
 		</Configuration>
 		<Configuration
-			CharacterSet="2"
-			ConfigurationType="1"
-			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
 			WholeProgramOptimization="1"
 			>
 			<Tool
@@ -115,19 +115,19 @@
 				Name="VCMIDLTool"
 			/>
 			<Tool
-				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
-				BufferSecurityCheck="false"
-				CompileAs="1"
-				DebugInformationFormat="3"
-				DisableSpecificWarnings="4996;4244;4018;4090;4333;4101;4146;4102"
-				EnableFunctionLevelLinking="true"
-				EnableIntrinsicFunctions="true"
 				Name="VCCLCompilerTool"
 				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
 				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H;_BIND_TO_CURRENT_VCLIBS_VERSION=1"
  RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
+				DebugInformationFormat="3"
+				CompileAs="1"
+				DisableSpecificWarnings="4996;4244;4018;4090;4333;4101;4146;4102"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -139,13 +139,13 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
+				Name="VCLinkerTool"
 				AdditionalDependencies="dnsapi.lib"
-				EnableCOMDATFolding="2"
+				LinkIncremental="1"
 				GenerateDebugInformation="true"
-				LinkIncremental="1"
-				Name="VCLinkerTool"
+				SubSystem="1"
 				OptimizeReferences="2"
-				SubSystem="1"
+				EnableCOMDATFolding="2"
 				TargetMachine="1"
 			/>
 			<Tool
@@ -175,8 +175,8 @@
 	</References>
 	<Files>
 		<Filter
+			Name="Source Files"
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			Name="Source Files"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
 			<File
@@ -226,6 +226,10 @@
 					RelativePath="..\shared\tar.c"
 					>
 				</File>
+				<File
+					RelativePath="..\shared\w32_service.c"
+					>
+				</File>
 			</Filter>
 			<Filter
 				Name="compat"
@@ -241,14 +245,14 @@
 			</Filter>
 		</Filter>
 		<Filter
+			Name="Header Files"
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			Name="Header Files"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
 		</Filter>
 		<Filter
+			Name="Resource Files"
 			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
                
-			Name="Resource Files"
 			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
 			>
 			<File
Index: win32/platform.h
===================================================================
--- win32/platform.h	(revision 1255)
+++ win32/platform.h	(working copy)
@@ -53,7 +53,7 @@
 #define closesocket w32_closesocket
 #define getservbyname w32_getservbyname
 #define getaddrinfo w32_getaddrinfo
-#define gai_strerror w32_strerror
+//#define gai_strerror w32_strerror
 #define freeaddrinfo w32_freeaddrinfo
 #define inet_ntop w32_inet_ntop
 #define gethostbyname w32_gethostbyname
Index: win32/clamd.vcproj
===================================================================
--- win32/clamd.vcproj	(revision 1255)
+++ win32/clamd.vcproj	(working copy)
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
-	Keyword="Win32Proj"
+	ProjectType="Visual C++"
+	Version="9.00"
 	Name="clamd"
 	ProjectGUID="{B3CA73CF-E71E-42F3-95DE-43797A86C798}"
-	ProjectType="Visual C++"
 	RootNamespace="clamd"
+	Keyword="Win32Proj"
 	TargetFrameworkVersion="196613"
-	Version="9,00"
 	>
 	<Platforms>
 		<Platform
@@ -17,11 +17,11 @@
 	</ToolFiles>
 	<Configurations>
 		<Configuration
-			CharacterSet="2"
-			ConfigurationType="1"
-			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
 			Name="Debug|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -39,18 +39,18 @@
 				Name="VCMIDLTool"
 			/>
 			<Tool
-				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
-				BasicRuntimeChecks="3"
-				CompileAs="1"
-				DebugInformationFormat="3"
-				DisableSpecificWarnings="4996;4244;4090;4018"
-				MinimalRebuild="true"
 				Name="VCCLCompilerTool"
 				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
 				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H;_BIND_TO_CURRENT_VCLIBS_VERSION=1"
 +				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
+				DebugInformationFormat="3"
+				CompileAs="1"
+				DisableSpecificWarnings="4996;4244;4090;4018"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -62,9 +62,9 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
 				GenerateDebugInformation="true"
-				LinkIncremental="1"
-				Name="VCLinkerTool"
 				SubSystem="1"
 				TargetMachine="1"
 			/>
@@ -91,11 +91,11 @@
 			/>
 		</Configuration>
 		<Configuration
-			CharacterSet="2"
-			ConfigurationType="1"
-			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(SolutionDir)build\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
 			WholeProgramOptimization="1"
 			>
 			<Tool
@@ -114,18 +114,18 @@
 				Name="VCMIDLTool"
 			/>
 			<Tool
-				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
-				CompileAs="1"
-				DebugInformationFormat="3"
-				DisableSpecificWarnings="4996;4244;4090;4018"
-				EnableFunctionLevelLinking="true"
-				EnableIntrinsicFunctions="true"
 				Name="VCCLCompilerTool"
 				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\l \
ibclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot \
;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
                
 				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H;_BIND_TO_CURRENT_VCLIBS_VERSION=1"
  RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
+				DebugInformationFormat="3"
+				CompileAs="1"
+				DisableSpecificWarnings="4996;4244;4090;4018"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -137,12 +137,12 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
-				EnableCOMDATFolding="2"
+				Name="VCLinkerTool"
+				LinkIncremental="1"
 				GenerateDebugInformation="true"
-				LinkIncremental="1"
-				Name="VCLinkerTool"
+				SubSystem="1"
 				OptimizeReferences="2"
-				SubSystem="1"
+				EnableCOMDATFolding="2"
 				TargetMachine="1"
 			/>
 			<Tool
@@ -172,8 +172,8 @@
 	</References>
 	<Files>
 		<Filter
+			Name="Source Files"
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			Name="Source Files"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
 			<File
@@ -219,17 +219,21 @@
 					RelativePath="..\shared\output.c"
 					>
 				</File>
+				<File
+					RelativePath="..\shared\w32_service.c"
+					>
+				</File>
 			</Filter>
 		</Filter>
 		<Filter
+			Name="Header Files"
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			Name="Header Files"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
 		</Filter>
 		<Filter
+			Name="Resource Files"
 			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
                
-			Name="Resource Files"
 			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
 			>
 			<File



_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html
Please submit your patches to our Bugzilla: http://bugs.clamav.net

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic