/*****************************************************************************/

/*
 *      delservice.c  --  Delete W2k Service.
 *
 *      Copyright (C) 2000
 *          Thomas Sailer (sailer@ife.ee.ethz.ch)
 *
 *      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.
 *
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 *  In order to use the radio, you need a license from the communications
 *  authority of your country.
 *
 *  History:
 *   0.1  19.09.2000  Created
 *
 */

/*****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "trx.h"

#include <stdio.h>
#include <windows.h>

/* --------------------------------------------------------------------- */

static int delete_service(void)
{
        int ret = -1;
        SC_HANDLE hscm, hserv;
        SERVICE_STATUS sstat;
        
        hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
        if (!hscm) {
                fprintf(stderr, "Cannot open SC manager, error %lu\n", GetLastError());
                return -1;
        }
        hserv = OpenService(hscm, SERVICENAME, SERVICE_ALL_ACCESS);
        if (!hserv) {
                fprintf(stderr, "Cannot open service, error %lu\n", GetLastError());
                goto closescm;
        }
        ret = 0;
        if (!ControlService(hserv, SERVICE_CONTROL_STOP, &sstat)) {
                fprintf(stderr, "Cannot delete service, error %lu\n", GetLastError());
                ret = -1;
        }
        if (!DeleteService(hserv)) {
                fprintf(stderr, "Cannot delete service, error %lu\n", GetLastError());
                ret = -1;
        }
        if (!ret)
                fprintf(stderr, "Service %s stopped successfully\n", SERVICENAME);
        if (!CloseServiceHandle(hserv))
                fprintf(stderr, "Cannot close service handle, error %lu\n", GetLastError());
  closescm:
        if (!CloseServiceHandle(hscm))
                fprintf(stderr, "Cannot close service manager handle, error %lu\n", GetLastError());
        return ret;
}

static int create_service(void)
{
        int ret = -1;
        SC_HANDLE hscm, hserv;
        char name[512], cmdname[512], *cp;
        
        if (!GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name))) {
                fprintf(stderr, "Cannot determine executable name\n");
                return -1;
        }
        if ((cp = strrchr(name, '\\')))
                *cp = 0;
        else
                name[0] = 0;
	/*
	 * Database calls (getXbyY) seem to hang for a very looooong time under
	 * w9x if DNS is not or misconfigured. So we set the binding address to
	 * 127.0.0.1, which only accepts connections from 127.0.0.1
	 * and does no database calls
	 */
        //snprintf(cmdname, sizeof(cmdname), "%s\\baycomusbserv.exe -S -v 9 -s -ORBBindAddr=127.0.0.1", name);
        snprintf(cmdname, sizeof(cmdname), "%%SystemRoot%%\\baycomusbserv.exe -S -v 9 -s -ORBBindAddr=127.0.0.1");

        hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
        if (!hscm) {
                fprintf(stderr, "Cannot open SC manager, error %lu\n", GetLastError());
                return -1;
        }
        hserv = CreateService(hscm, SERVICENAME, SERVICEDISPLAYNAME,
                              SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                              SERVICE_AUTO_START/*SERVICE_DEMAND_START*/, SERVICE_ERROR_NORMAL,
                              cmdname, NULL, NULL, NULL, NULL, NULL);
        if (!hserv) {
                fprintf(stderr, "Cannot create service, error %lu\n", GetLastError());
                goto closescm;
        }
        fprintf(stderr, "Service %s created successfully\n", SERVICENAME);
        ret = 0;

        if (!CloseServiceHandle(hserv))
                fprintf(stderr, "Cannot close service handle, error %lu\n", GetLastError());
  closescm:
        if (!CloseServiceHandle(hscm))
                fprintf(stderr, "Cannot close service manager handle, error %lu\n", GetLastError());
        return ret;
}

static int start_service(int recurse)
{
        int ret = -1;
        SC_HANDLE hscm, hserv;
        DWORD err;
        char *args[5] = { "-S", "-v", "9", "-s", "-ORBBindAddr=127.0.0.1" };
        
        hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
        if (!hscm) {
                fprintf(stderr, "Cannot open SC manager, error %lu\n", GetLastError());
                return -1;
        }
        hserv = OpenService(hscm, SERVICENAME, SERVICE_ALL_ACCESS);
        if (!hserv) {
                err = GetLastError();
                fprintf(stderr, "Cannot open service, error %lu\n", err);
                if (recurse && err == ERROR_SERVICE_DOES_NOT_EXIST) {
                        if (!CloseServiceHandle(hscm))
                                fprintf(stderr, "Cannot close service manager handle, error %lu\n", GetLastError());
                        if (create_service())
                                return -1;
                        return start_service(0);
                }
                goto closescm;
        }
        if (!StartService(hserv, 5, args)) {
                err = GetLastError();
                if (err != ERROR_SERVICE_ALREADY_RUNNING)
                        fprintf(stderr, "Cannot start service, error %lu\n", err);
                if (recurse && err == ERROR_PATH_NOT_FOUND) {
                        if (!CloseServiceHandle(hserv))
                                fprintf(stderr, "Cannot close service handle, error %lu\n", GetLastError());
                        if (!CloseServiceHandle(hscm))
                                fprintf(stderr, "Cannot close service manager handle, error %lu\n", GetLastError());
                        if (delete_service())
                                return -1;
                        if (create_service())
                                return -1;
                        return start_service(0);
                }
                goto closeserv;
        }
        fprintf(stderr, "Service %s started successfully\n", SERVICENAME);
        ret = 0;

  closeserv:
        if (!CloseServiceHandle(hserv))
                fprintf(stderr, "Cannot close service handle, error %lu\n", GetLastError());
  closescm:
        if (!CloseServiceHandle(hscm))
                fprintf(stderr, "Cannot close service manager handle, error %lu\n", GetLastError());
        return ret;
}

/* --------------------------------------------------------------------- */

int main(int argc, char *argv[])
{
        if (argc >= 2) {
                switch (argv[1][0]) {
                case 's':
                case 'S':
                        return start_service(0) ? 1 : 0;
        
                case 'c':
                case 'C':
                        return create_service() ? 1 : 0;
                }
        }
        return delete_service() ? 1 : 0;
}
