123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /**
- * saop: smtp authentication over pop3
- * Copyright (C) 2007 Juan José Gutiérrez de Quevedo <juanjo@iteisa.com>
- *
- * 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; version 2 of the License
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * @author Juan José Gutiérrez de Quevedo <juanjo@iteisa.com>
- */
- #include <stdio.h>
- #include <windows.h>
- #define SERVICE_NAME "saop: smtp authentication over pop3"
- #define SERVICE_SHORT_NAME "saop"
- #define SERVICE_DESCRIPTION_TEXT "Adds LOGIN authentication to an SMTP server. Users are authenticated against a pop3 server, an imap4 server or a file"
- /* macros */
- #define ChangeServiceStatus(x,y,z) y.dwCurrentState=z; SetServiceStatus(x,&y);
- #define MIN(x,y) (((x)<(y))?(x):(y))
- #define cmp(x,y) strncmp(x,y,strlen(y))
- #define msgbox(x,y) MessageBox(NULL,x,"Error from " SERVICE_NAME,MB_OK|y)
- #define winerror(x) msgbox(x,MB_ICONERROR)
- #define winmessage(x) msgbox(x,MB_ICONINFORMATION)
- #define _(x) x
- /**
- * The docs on microsoft's web don't seem very clear, so I have
- * looked at the stunnel source code to understand how this thing
- * works. What you see here is still original source, but is
- * "inspired" by stunnel's source code (gui.c mainly).
- * It's the real minimum needed to install, start and stop services
- */
- extern int quit;
- extern int saop_main(int,char **);
- SERVICE_STATUS service_status;
- SERVICE_STATUS_HANDLE service_status_handle;
- int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int);
- static void WINAPI service_main(DWORD,LPTSTR*);
- static void WINAPI handler(DWORD);
- static int service_install();
- static int service_uninstall();
- int WINAPI WinMain(HINSTANCE instance,HINSTANCE previous_instance,LPSTR cmdline,int cmdshow)
- {
- if(!cmp(cmdline,"-service"))
- {
- SERVICE_TABLE_ENTRY service_table[]={
- {SERVICE_NAME,service_main},
- {NULL,NULL}
- };
- if(0==StartServiceCtrlDispatcher(service_table))
- {
- winerror("Error starting service dispatcher.");
- return -1;
- }
- }
- else if(!cmp(cmdline,"-install"))
- service_install();
- else if(!cmp(cmdline,"-uninstall"))
- service_uninstall();
- else
- saop_main(0,NULL);
- return 0;
- }
- static int service_install()
- {
- SC_HANDLE scm,service_handle;
- SERVICE_DESCRIPTION sd;
- char filename[1024];
- char exepath[2048];
- if(NULL==(scm=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE)))
- {
- winerror(_("Error opening connection to the Service Manager."));
- exit(-1);
- }
- if(0==GetModuleFileName(NULL,filename,sizeof(filename)))
- {
- winerror(_("Error getting the file name of the process."));
- exit(-1);
- }
- snprintf(exepath,sizeof(exepath),"\"%s\" -service",filename);
- service_handle=CreateService(
- scm, /* scm handle */
- SERVICE_SHORT_NAME, /* service name */
- SERVICE_NAME, /* display name */
- SERVICE_ALL_ACCESS, /* desired access */
- SERVICE_WIN32_OWN_PROCESS, /* service type */
- SERVICE_AUTO_START, /* start type */
- SERVICE_ERROR_NORMAL, /* error control */
- exepath, /* executable path with arguments */
- NULL, /* load group */
- NULL, /* tag for group id */
- NULL, /* dependencies */
- NULL, /* user name */
- NULL); /* password */
- if(NULL==service_handle)
- {
- winerror("Error creating service. Already installed?");
- exit(-1);
- }
- else
- winmessage("Service successfully installed.");
- /*
- * createservice doesn't have a field for description
- * so we use ChangeServiceConfig2
- */
- sd.lpDescription=SERVICE_DESCRIPTION_TEXT;
- ChangeServiceConfig2(service_handle,SERVICE_CONFIG_DESCRIPTION,(void *)&sd);
- CloseServiceHandle(service_handle);
- CloseServiceHandle(scm);
- return 0;
- }
- static int service_uninstall()
- {
- SC_HANDLE scm,service_handle;
- SERVICE_STATUS status;
- if(NULL==(scm=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE)))
- {
- winerror(_("Error opening connection to the Service Manager."));
- exit(-1);
- }
- if(NULL==(service_handle=OpenService(scm,SERVICE_SHORT_NAME,SERVICE_QUERY_STATUS|DELETE)))
- {
- winerror(_("Error opening service."));
- CloseServiceHandle(scm);
- exit(-1);
- }
- if(0==QueryServiceStatus(service_handle,&status))
- {
- winerror(_("Error querying service."));
- CloseServiceHandle(scm);
- CloseServiceHandle(service_handle);
- exit(-1);
- }
- if(SERVICE_STOPPED!=status.dwCurrentState)
- {
- winerror(SERVICE_NAME _(" is still running. Stop it before trying to uninstall it."));
- CloseServiceHandle(scm);
- CloseServiceHandle(service_handle);
- exit(-1);
- }
- if(0==DeleteService(service_handle))
- {
- winerror(_("Error deleting service."));
- CloseServiceHandle(scm);
- CloseServiceHandle(service_handle);
- exit(-1);
- }
- CloseServiceHandle(scm);
- CloseServiceHandle(service_handle);
- winmessage(_("Service successfully uninstalled."));
- return 0;
- }
- static void WINAPI service_main(DWORD argc,LPTSTR *argv)
- {
- /* configure service_status structure */
- service_status.dwServiceType=SERVICE_WIN32;
- service_status.dwControlsAccepted=0;
- service_status.dwWin32ExitCode=NO_ERROR;
- service_status.dwServiceSpecificExitCode=NO_ERROR;
- service_status.dwCheckPoint=0;
- service_status.dwWaitHint=0;
- service_status.dwControlsAccepted|=SERVICE_ACCEPT_STOP;
- service_status_handle=RegisterServiceCtrlHandler(SERVICE_NAME,handler);
- if(0!=service_status_handle)
- {
- /* set service status */
- ChangeServiceStatus(service_status_handle,service_status,SERVICE_RUNNING);
- /* now start our main program */
- quit=0;
- saop_main(argc,argv);
- /* when we are here, we have been stopped */
- ChangeServiceStatus(service_status_handle,service_status,SERVICE_STOP_PENDING);
- ChangeServiceStatus(service_status_handle,service_status,SERVICE_STOPPED);
- }
- }
- static void WINAPI handler(DWORD code)
- {
- if(SERVICE_CONTROL_STOP==code)
- {
- quit=1;
- ChangeServiceStatus(service_status_handle,service_status,SERVICE_STOP_PENDING);
- }
- }
|