// Copyright (C) 2009,2010,2011,2012 GlavSoft LLC.
// All rights reserved.
//
//-------------------------------------------------------------------------
// This file is part of the TightVNC software.  Please visit our Web site:
//
//                       http://www.tightvnc.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; 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.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//-------------------------------------------------------------------------
//

#ifndef _SCM_CLIENT_H_
#define _SCM_CLIENT_H_

#include "util/CommonHeader.h"
#include "util/Exception.h"

#include "SystemException.h"

/**
 * SCMClient own exception that can be generated by
 * some of SCMClient methods.
 */
class SCMClientException : public SystemException {
public:
  /**
   * Service already stopped and cannot be stopped.
   */
  const static int ERROR_ALREADY_STOPPED = 0;
  /**
   * Timeout expired while waiting for service to stop.
   */
  const static int ERROR_STOP_TIMEOUT = 1;
  /**
   * Service alreadying running and cannot be started.
   */
  const static int ERROR_ALREADY_RUNNING = 2;
  /**
   * Timeout expired while waiting for service to start.
   */
  const static int ERROR_START_TIMEOUT = 3;
public:
  /**
   * Creates new SCMClient exception.
   * @param scmErrCode service client manager client own error code,
   * see SCMClientException public constants for information.
   */
  SCMClientException(int scmErrCode);
  /**
   * Returns scm error code.
   */
  int getSCMErrorCode() const;
private:
  /**
   * scm own error code.
   */
  int m_scmErrCode;
};

/**
 * Service client manager client.
 *
 * Gives access to install, remove, start, stop services and queries status
 * of service.
 */
class SCMClient
{
public:
  /**
   * Creates new SCMClient.
   * @param desiredAccess desired acess (see OpenSCManager WinAPI function description
   * for details).
   * @throws SystemException on fail.
   */
  SCMClient(DWORD desiredAccess = SC_MANAGER_ALL_ACCESS) throw(SystemException);
  /**
   * Destructor, closes SCMClient.
   */
  virtual ~SCMClient();
  /**
   * Registers new service in system.
   * @param name name of service.
   * @param nameToDisplay name to display in services list.
   * @param binPath full path to service binary.
   * @param dependencies [optional] service dependencies.
   * @throws SystemException on fail.
   */
  void installService(const TCHAR *name, const TCHAR *nameToDisplay,
                      const TCHAR *binPath, const TCHAR *dependencies = _T("")) throw(SystemException);
  /**
   * Unregisters existing service from services.
   * @param name name of service to unregister.
   * @throws SystemException on fail.
   */
  void removeService(const TCHAR *name) throw(SystemException);
  /**
   * Starts existing service.
   * @param name name of service to start.
   * @param waitCompletion if true, wait until the status becomes
   *   SERVICE_RUNNING.
   * @throws SystemException, SCMClientException on fail.
   */
  void startService(const TCHAR *name, bool waitCompletion = false)
    throw(SystemException, SCMClientException);
  /**
   * Stops running service execution.
   * @param name name of service to stop.
   * @param waitCompletion if true, wait until the status becomes
   *   SERVICE_STOPPED.
   * @throws SystemException, SCMClientException on fail.
   */
  void stopService(const TCHAR *name, bool waitCompletion = false)
    throw(SystemException, SCMClientException);

private:
  /**
   * Gets current state of existing service specified by handle.
   * @param hService handle of the service.
   * @return current service state.
   * @throws SystemException on failure.
   */
  DWORD getServiceState(SC_HANDLE hService) const throw(SystemException);

private:
  /** Service client manager handle. */
  SC_HANDLE m_managerHandle;
};

#endif
