= Description
   An interface for MS Windows Services.
    
= Prerequisites
   Ruby 1.8.0 or later.
	
   This package is only supported for the Windows NT family of operating
   systems, e.g. NT 4, 2000, XP, 2003, etc.  It is NOT supported (and won't
   work) for any version of DOS or Windows 95/98/ME. It should work on Windows
   XP Home, but is not officially supported for that platform.
    
= Synopsis
   require "win32/service"
   include Win32
    
   s = Service.new("some_machine")
    
   # Create a new service
   s.create_service{ |s|
      s.service_name        = "foo"
      s.binary_path_name    = "C:\\some_dir\\foo.exe"
      s.display_name        = "My Foo Service"
      s.service_description = "Greatest Service Ever"
   }
    
   # Configure a service that already exists
   s.configure_service{ |s|
      s.display_name = "My Bar Service"
   }
    
   s.close
    
   Service.start("foo")
   Service.pause("foo")
   Service.resume("foo")
   Service.stop("foo")
    
   Service.delete("foo")
    
   Service.getdisplayname("Schedule") # "Task Scheduler"
   Service.getservicename("ClipBook") # "ClipSrv"
    
   s = Service.status("ClipSrv")
    
   # Enumerate over all services, inspecting each struct  
   Service.services{ |s|
      p s
      puts
   }
    
= Class Methods
Service.new(host=nil, desired_access=nil){ ... }
   Creates and returns a new Win32::Service handle on +host+ with the
   +desired_access+.  If no host is specified, your local machine is
   used.  If no desired access is specified, then
   Service::MANAGER_CREATE_SERVICE is used.
   
   If a block is provided the Win32::Service object is yielded to the
   block and *closed* at the end of the block.
    
   See the "Desired Access Constants" section for a list of valid
   desired access levels and their meanings.
    
Service.delete(service, host=nil)
   Deletes the specified +service+ on +host+.  If no host is given,
   then it deletes it on the local machine.
    
Service.exists?(service)
   Returns true if the specified service exists, false otherwise.
   
Service.open(service, host=nil, desired_access=nil){ ... }
   Creates and returns a new Win32::Service handle on +host+ with the
   +desired_access+ for the given +service+.  If no host is specified
   then your local machine is used.  If no +desired_access+ is specified,
   then Service::SERVICE_QUERY_CONFIG is used.
	
   If a block is provided the Win32::Service object is yielded to the
   block and *closed* at the end of the block.
	
   Note that you will probably need to change the desired access in
   order to configure or delete an existing service using the returned object.
    
Service.pause(service, host=nil)
   Pauses the specified +service+ on +host+, or the local machine if
   no host is provided.
    
Service.resume(service, host=nil)
   Resumes the specified +service+ on +host+, or the local machine if
   no host is specified.
    
Service.services(host=nil, group=nil){ |struct| ... }
   Enumerates over a list of service types on host, or the local
   machine if no host is specified, yielding a Win32Service struct for each
   service.
	
   If a 'group' is specified, then only those services that belong to
   that group are enumerated.  If an empty string is provided, then only
   services that do not belong to any group are enumerated. If this parameter
   is nil, group membership is ignored and all services are enumerated.
	
   The 'group' option is only available on Windows 2000 or later, and only
   if compiled with VC++ 7.0 or later, or the .NET SDK.  The Win32Service
   struct contains the following members:
	
   * service_name
   * display_name
   * service_type
   * current_state
   * controls_accepted
   * win32_exit_code
   * service_specific_exit_code
   * check_point
   * wait_hint
   * binary_path_name
   * start_type
   * error_control
   * load_order_group
   * tag_id
   * start_name
   * dependencies
   * description
   * interactive?
   * pid             (Win2k or later)
   * service_flags   (Win2k or later)
	
   Note that the 'pid' and 'service_flags' members are only available on
   Windows 2000 or later, and only if built with VC++ 7.0 or later (or the
   .NET SDK).
	
Service.start(service, host=nil, *args)
    Starts the specified +service+ on +host+, or the local machine if no
    host is specified.  Any +args+ passed here are passed as start parameters
    to the service.
    
Service.status(service)
    Returns a Win32ServiceStatus struct for the specified service (or
    raises a Win32::ServiceError if not found).  The Win32ServiceStatus
    struct contains the following members.
    
    * service_type
    * current_state
    * controls_accepted
    * win32_exit_code
    * service_specific_exit_code
    * check_point
    * wait_hint
    * interactive?
    
Service.stop(service, host=nil)
    Stops the specified +service+ on +host+, or the local machine if no
    host is specified.	
    
= Instance Methods
Service#binary_path_name=(path_to_executable)
    Sets the binary to be used for the service.  The path must be the fully
    qualified path name.  A path that contains a space must be quoted so that
    it is correctly interpreted.  The path may also include arguments to the
    service entry point (typically the 'main' function).
    
    This option must be set before you can call Service#create_service.
    
Service#close
    Closes the service handle.  This is the polite way to do things, although
    the service handle should automatically be closed when it goes out of
    scope.
    
Service#configure_service{ |service| ... }
   Configures the service object.  Valid methods for the service object are
   as follows:
	
   * desired_access= 
   * service_name=
   * display_name=
   * service_description=
   * service_type=
   * start_type=
   * error_control=
   * tag_id=   
   * binary_path_name= 
   * load_order_group= 
   * start_name= 
   * password=
   * dependencies=
   * failure_action=
   	
   See the docs for individual instance methods for more details.
    
Service#create_service{ |service| ... }
   Creates the specified service.  In order for this to work, the
   'service_name' and 'binary_path_name' attributes must be defined
   or a Win32::ServiceError will be raised.
    
   See the Service#configure_service method for a list of valid methods to
   pass to the service object.  See the individual methods for more
   information, including default values.
        
Service#display_name=(name)
   The display name to be used by user interface programs to identify the
   service.  The string has a maximum length of 256 characters.  Case
   sensitivity is preserved.
    
   The default is to set the display name to the same string as the
   service name.
   
Service#error_control=(type)
   Sets the error control for the service.  The default is
   Service::ERROR_NORMAL.
    
   See the "Error Control Contants" section for available options and their
   meanings.
    
Service#load_order_group=(order_group)
   Sets the load order group, where +order_group+ is a string that names
   the load ordering group of which this service is a member.  The default
   is nil.
    
Service#machine_name=(name)
   Sets the name of the machine on which the service will be created.  By
   default, this is set to nil.  That is, it will be created on your
   local machine.
    
Service#password=(password)
   Sets the passsword to the account name specified in the Service#start_name
   method.  By default, this value is set to nil, which is appropriate if
   the account has no password or if the service runs in the
   'LocalService', 'NetworkService', or 'LocalSystem' account.
    
   Note that passwords are ignored for driver services.
    
Service#service_name=(name)
   Sets the service name for the service.  This value must be set in order
   to create a service.  The string has a maximum length of 256 characters.
    
Service#service_type=(type)
   Sets the service type for the service.  The default is
   Service::WIN32_OWN_PROCESS | Service::INTERACTIVE_PROCESS.

   See the "Service Type Contants" section for available options and their
   meanings.
    
Service#start_name=(name)
   Sets the name of the account under which the service should run.
   By default the 'LocalSystem' account is used.
    
Service#start_type=(type)
   Sets the start type for the service.  The default is Service::DEMAND_START.
    
   See the "Start Type Contants" section for available options and their
   meanings.
    
= Constants

=== Standard Constants
VERSION
    The current version number of this package, returned as a string.
    
=== Desired Access Constants
Service::MANAGER_ALL_ACCESS
    Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights 
    in the table.
    
Service::MANAGER_CREATE_SERVICE
    Required to call the CreateService function to create a service object
    and add it to the database.
    
Service::MANAGER_CONNECT
    Required to connect to the service control manager.
    
Service::MANAGER_ENUMERATE_SERVICE
    Required to call the EnumServicesStatus function to list the services
    that are in the database.
    
Service::MANAGER_LOCK
    Required to call the LockServiceDatabase function to acquire a lock on the
    database.
    
Service::MANAGER_BOOT_CONFIG
    Required to call the NotifyBootConfigStatus() (internal) function.  Not
    defined with all compilers.
    
Service::MANAGER_QUERY_LOCK_STATUS
    Required to call the QueryServiceLockStatus() (internal) function to
    retrieve the lock status information for the database.
       
=== Service Type Constants
Service::FILE_SYSTEM_DRIVER
    File system driver service.
    
Service::KERNEL_DRIVER
    Driver service.
    
Service::WIN32_OWN_PROCESS
    Service that runs in its own process.
    
Service::WIN32_SHARE_PROCESS
    Service that shares a process with one or more other services.
    
Service::INTERACTIVE_PROCESS
    The service can interact with the desktop.  This can only be used if
    either SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS is
    specified as well, and the service is running in the context of the
    LocalSystem account (which is the default for this module, btw).
    
=== Start Type Constants
Service::AUTO_START
    A service started automatically by the service control manager during
    system startup.
    
Service::BOOT_START
    A device driver started by the system loader.  This value is valid only
    for driver services.
    
Service::DEMAND_START
    A service started by the service control manager when a process calls
    the StartService() function.
    
Service::DISABLED
    A service that cannot be started.  Attempts to start the service result
    in an error.
    
Service::SYSTEM_START
    A device driver started by the IoInitSystem() function.  This value is
    valid only for driver services.
    
=== Error Control Constants
Service::ERROR_IGNORE
    The startup program logs the error but continues the startup operation.
    
Service::ERROR_NORMAL
    The startup program logs the error and puts up a message box pop-up but
    continues the startup operation.
    
Service::ERROR_SEVERE
    The startup program logs the error.  If the last-known-good configuration
    is being started, the startup operation continues.  Otherwise, the system
    is restarted with the last-known-good configuration.
    
Service::ERROR_CRITICAL
    The startup program logs the error, if possible.  If the last-known-good
    configuration is being started the startup operation fails.  Otherwise,
    the system is restarted with the last-known-good configuration.
    
= Notes
   See the MSDN API with regards to CreateService(), etc at
   http://www.msdn.com
    
   Some API ideas taken (or not) from both Python's win32serviceutil.py and
   Perl's Win32::Service module.
   
   I don't truly understand how to allow a tag_id in the create_service()
   method, so for now it's set to NULL automatically.  Suggestions welcome.
    
= Known Bugs
   There may be a failure in the test suite if the W32Time dependency is
   not started.

   If you find any bugs please log them on the bug tracker.  You can find it
   on the project page at http://www.rubyforge.org/projects/win32utils.
   
= Acknowledgements
   Many thanks go to Patrick Hurley for providing the fix for the thread
   blocking issue.
    
= Future Plans
   Add Tag_ID support.
   Add ability to create or modify service failure actions.
   Use RegisterServiceCtrlHandlerEx().
    
= Copyright
   (C) 2003-2006, Daniel J. Berger, All Rights Reserved
    
= License
   Ruby's
    
= Warranty
   This package is provided "as is" and without any express or
   implied warranties, including, without limitation, the implied
   warranties of merchantability and fitness for a particular purpose.
    
== Author(s)
* Daniel J. Berger   
* Park Heesob
