#! perl -w

# ############################################################################ #
#
# FILE          : ServiceConfig.pl
#
# PURPOSE       : Change or Query a service's "General", "Logon", or 
#                 "Dependency" properties for one or more installed service(s).
#
# LAST MODIFIED : 26th August 2000
#
# AUTHOR        : Basil Dias.
#
# Maintained By : K.P.Harihara Subramanian.
#
# ############################################################################ #

use strict;
BEGIN
{
	if( &IsWmiModuleInstalled() )
	{
		require W2RK::WMI; import W2RK::WMI; # WMI library
	}
	else
	{
		print STDERR "ERROR: Wmi.pm is required to run the script.\n       Copy Wmi.pm from the Resource Kit directory to /Perl/site/lib/W2RK.\n";
		exit( 0 );
	}

	sub IsWmiModuleInstalled
	{
		foreach ( @INC )
		{
			my $dir = $_."/W2RK/Wmi.pm";
			if( -e $dir )
			{
				require W2RK::WMI; import W2RK::WMI; # WMI library
				return 1;
			}
		}
		return 0;
	}
}


# General Constants
use constant MAX_SIZE          => 5;
use constant IFLAG             => 48;

# Error Constants

# Syntax Errors.
use constant USAGE_MAIN         => "The syntax of the command is incorrect.\n".
                                   "Type \"ServiceConfig.pl -?\" for usage information.\n"; # Error No 8
use constant USAGE_GENERAL      => "The syntax of the command is incorrect.\n".
                                   "Type \"ServiceConfig.pl -general -?\" for usage information.\n"; # Error No 8
use constant USAGE_LOGON        => "The syntax of the command is incorrect.\n".
                                   "Type \"ServiceConfig.pl -logon -?\" for usage information.\n"; # Error No 8
use constant USAGE_DEPENDENCIES => "The syntax of the command is incorrect.\n".
                                   "Type \"ServiceConfig.pl -dependencies -?\" for usage information.\n"; # Error No 8

# Invalid Error Messages.
use constant ERROR_INVALID_PATH      => "ERROR: Invalid file path '%s' specified for service.\n"; # Error No 4
use constant ERROR_INVALID_OPTION    => "ERROR: Invalid value '%s' specified for the '%s' option.\n"; # Error No 7
use constant ERROR_DISPLAY_EXISTS    => "ERROR: A service with display name '%s' already exists.\n"; # Error No 20
use constant ERROR_NOT_CHANGED       => "ERROR: Unable to change '%s' service '%s' Settings.\n"; # Error No 254
use constant ERROR_NO_MATCHES        => "ERROR: Service '%s' does not exist.\n"; # Error No 2302
use constant ERROR_INVALID_FORMAT    => "ERROR: Invalid user format '%s' specified for '%s' option.\n"; # Error No 7
use constant ERROR_NOINFO            => "ERROR: Unable to retreive Service Information.\n"; # Error No 19
use constant ERROR_NOINFO_FILTER     => "ERROR: No Information retrieved after filter operation. \n"; # Error No 30
use constant ERROR_INVALID_USER      => "ERROR: Invalid user '%s' specified with 'runas' option.\n"; # Error No 24
use constant ERROR_INVALID_LOADORDER => "ERROR: Invalid load order group '%s' specified with 'loadorder' option.\n"; # Error No 24

# Skipping/Warning Messages.
use constant WARN_NOT_UNIQUE         => "SKIPPING: '%s' service '%s' settings not unique.\n"; # Error No 100
use constant WARN_NODESKTOP_INTERACT => "ERROR: Desktop interact not applicable to '%s' service.\n".
                                        "This service is set to run under a non-local system Account.\n"; # Error No 2303
use constant WARN_PASSWORD_NA        => "ERROR: Password not applicable for '%s' service.\n".
                                        "This service is set to run under LocalSystem Account.\n"; # Error No 2304

# Success Messages.
use constant MSG_CHANGED          => "SUCCESS: '%s' service '%s' settings changed.\n"; # Error No 0
use constant MSG_RESTART          => "INFO: The new logon name will take effect only on restarting the service.\n";

my %Error;
my $errorlevel = 0;
MAIN:
{
	my ($general, $logon, $dependencies);
	my ($display, $path, $errorcontrol, $type, $startmode);
	my ($runas, $runaspw, $interact);
	my ($service, $clear, $loadorder);
	my ($format, $verbose, $help, $wmi);
	my @filter;

	$wmi = W2RK::WMI->new;
	$wmi->ProcessOptions( 'general'       => \$general,
	                      'logon'         => \$logon,
	                      'dependencies'  => \$dependencies,
	                      'displayname=s' => \$display,
	                      'path=s'        => \$path,
	                      'errorcontrol=s'=> \$errorcontrol,
	                      'type=s'        => \$type,
	                      'startmode=s'   => \$startmode,
	                      'runas=s'       => \$runas,
	                      'runaspw=s'     => \$runaspw,
	                      'interact=s'    => \$interact,
	                      'service=s'     => \$service,
	                      'clear'         => \$clear,
	                      'loadorder=s'   => \$loadorder,
	                      'filter=s'      => \@filter,
	                      'format=s'      => \$format,
	                      'verbose'       => \$verbose,
	                      'h|?'           => \$help,
	                    );

	%Error =    (2  => 'The user did not have the necessary access.',
	             3  => 'The service cannot be stopped because other services that are running are dependent on it.',
	             4  => 'The requested control code is not valid, or it is unacceptable to the service.',
	             5  => 'The requested control code cannot be sent to the service because the state of the service (Win32_BaseService:State) is equal to 0, 1, or 2.',
	             6  => 'The service has not been started.',
	             7  => 'The service did not respond to the start request in a timely fashion.',
	             8  => 'Unknown failure when starting the service.',
	             9  => 'The directory path to the service executable was not found.',
	             10 => 'The service is already running.',
	             11 => 'The database to add a new service is locked.',
	             12 => 'A dependency for which this service relies on has been removed from the system.',
	             13 => 'The service failed to find the service needed from a dependent service.',
	             14 => 'The service has been disabled from the system.',
	             15 => 'The service does not have the correct authentication to run on the system.',
	             16 => 'This service is being removed from the system.',
	             17 => 'There is no execution thread for the service.',
	             18 => 'There are circular dependencies when starting the service.',
	             19 => 'There is a service running under the same name.',
	             20 => 'There are invalid characters in the name of the service.',
	             21 => 'Invalid parameters have been passed to the service.',
	             22 => 'The account which this service is to run under is either invalid or lacks the permissions to run the service.',
	             23 => 'The service exists in the database of services available from the system.',
	             24 => 'The service is currently paused in the system.'
	            );

	###### GENERAL OPTION #############
	if($general && !$logon && !$dependencies)
	{
		my $rest = 0;
		$rest = 1
			if (defined $runas || defined $runaspw || defined $interact || 
			    defined $service || defined $clear || defined $loadorder);

		fail ( USAGE_GENERAL, 8 )
			if( ( !defined $wmi->{server} and defined $wmi->{username} ) or
				( !defined $wmi->{username} and defined $wmi->{password} ) );

		if( $help )
		{
			if( $rest or defined $display or defined $path or defined $errorcontrol or defined $type or
			    defined $startmode or @filter or defined $format or defined $verbose or @ARGV 
			    or defined $wmi->{server} or defined $wmi->{username} or defined $wmi->{password} )
			{
				fail( USAGE_GENERAL, 8 );
			}
			else
			{
				&GeneralHelp;
			}
		}
		fail ( USAGE_GENERAL, 8 ) if( $rest );
		fail ( USAGE_GENERAL, 8 ) if( @ARGV == 0 );

		###### GENERAL CHANGE OPTION #############
		if ( defined $display || defined $path || defined $errorcontrol ||
		     defined $type || defined $startmode)
		{
			fail ( USAGE_GENERAL, 8 )
				if(defined @filter || defined $format || defined $verbose );

			eval { $wmi->Connect(); };
			fail ( $@, 9 ) if($@);

			&ChangeGeneral( $wmi, \$display, \$path, \$errorcontrol,
			                \$type, \$startmode, \@ARGV);
		}
		###### GENERAL QUERY OPTION #############
		else
		{
			&CheckFormat(\$format);
			my %FilterCfg = ( 
			                  "Name"          => { Operators  => ['!', '='] },
			                  "State"         => { Operators  => ['!', '='],
			                                       ValueType => ['RUNNING', 'PAUSED', 'STOPPED'] },
			                  "DisplayName"   => { Operators  => ['!', '='] },
			                  "ErrorControl"  => { Operators  => ['!', '='],
			                                       ValueType => ['IGNORE', 'NORMAL', 'SEVERE', 'CRITICAL'] },
			                  "AcceptPause"   => { Operators  => ['!', '='],
			                                       ValueType => ['YES', 'NO'] },
			                  "AcceptStop"    => { Operators  => ['!', '='],
			                                       ValueType => ['YES', 'NO'] },
			                  "StartMode"     => { Operators  => ['!', '='],
			                                       ValueType => ['AUTO', 'MANUAL', 'DISABLED', 'BOOT', 'DRIVER'] },
			                  "Path"          => { Operators  => ['!', '='] },
			                  "Type"          => { Operators  => ['!', '='],
			                                       ValueType => ['OWNPROC', 'SHAREDPROC'] }
			                );

			if( @filter )
			{
				my $errfilter = W2RK::WMI->ValidateFilter( \@filter, \%FilterCfg );
				if( defined $errfilter )
				{
					fail( sprintf(ERROR_INVALID_OPTION,$errfilter, 'filter' ), 7 );
				}
			}

			eval { $wmi->Connect(); };
			fail ($@, 9 ) if($@);

			&GeneralQuery($wmi, \@filter, \$format, \$verbose, \@ARGV, \%FilterCfg);
		}
	}
	###### LOGON OPTION #############
	elsif(!$general && $logon && !$dependencies)
	{
		my $rest = 0;
		$rest = 1
			if (defined $display || defined $path || defined $errorcontrol ||
			    defined $type || defined $startmode || defined $service ||
			    defined $clear || defined $loadorder || defined $verbose );

		fail ( USAGE_LOGON, 8 )
			if( ( !defined $wmi->{server} and defined $wmi->{username} ) or
				( !defined $wmi->{username} and defined $wmi->{password} ) );

		if( $help )
		{
			fail( USAGE_LOGON, 8 )
				if( $rest or defined $runas or defined $runaspw or defined $interact or 
				    @ARGV or @filter or defined $format or defined $wmi->{server}
				    or defined $wmi->{username} or defined $wmi->{password} );
			&LogonHelp;
		}
		fail ( USAGE_LOGON , 8 ) if( $rest );
		fail ( USAGE_LOGON, 8 ) if( @ARGV == 0 );

		###### LOGON CHANGE OPTION #############
		if (defined $runas || defined $runaspw || defined $interact)
		{
			fail ( USAGE_LOGON, 8 )
				if( defined @filter || defined $format );
			
			eval { $wmi->Connect(); };
			fail ($@, 9 ) if($@);

			&ChangeLogon( $wmi, \$runas, \$runaspw, \$interact, \@ARGV);
		}
		###### LOGON QUERY OPTION #############
		else
		{
			&CheckFormat(\$format);
			my %FilterCfg = (
			                  "Name"        => { Operators  => ['!','='] },
			                  "State"       => { Operators  => ['!','='],
			                                     ValueType  => ['RUNNING', 'PAUSED', 'STOPPED']},
			                  "DisplayName" => { Operators  => ['!','='] },
			                  "RunAs"       => { Operators  => ['!','='] },
			                  "Interact"    => { Operators  => ['!','='],
			                                     ValueType => ['ON', 'OFF'] }
			                );

			if( @filter )
			{
				my $errfilter = W2RK::WMI->ValidateFilter( \@filter, \%FilterCfg );
				if( defined $errfilter )
				{
					fail( sprintf( ERROR_INVALID_OPTION, $errfilter, 'filter' ) , 7 );
				}
			}
			eval { $wmi->Connect(); };
			fail ($@, 9 ) if($@);

			&LogonQuery($wmi, \@filter, \$format, \@ARGV, \%FilterCfg);
		}
	}
	######## DEPENDENCY OPTION ##########
	elsif(!$general && !$logon && $dependencies)
	{
		fail ( USAGE_DEPENDENCIES, 8 )
			if( ( !defined $wmi->{server} and defined $wmi->{username} ) or
			    ( !defined $wmi->{username} and defined $wmi->{password} ) );

		my $rest = 0;
		$rest = 1 
			if (defined $display || defined $path || defined $errorcontrol || defined $type ||
			    defined $startmode || defined $runas || defined $runaspw || defined $interact ||
			    defined $verbose);

		if($help)
		{
			fail( USAGE_DEPENDENCIES, 8 )
				if( $rest or @filter or @ARGV or defined $format or defined $service or 
				    defined $clear or defined $loadorder or defined $wmi->{server} or
				    defined $wmi->{username} or defined $wmi->{password} );

			&DependenciesHelp();
		}
		fail( USAGE_DEPENDENCIES, 8 ) if( $rest );
		fail( USAGE_DEPENDENCIES, 8 ) if( !defined $service );

		######### DEPENDENCY CHANGE OPTION ##########
		if (defined $clear || defined $loadorder || @ARGV > 0)
		{
			fail( USAGE_DEPENDENCIES, 8 )
				if( @filter || defined $format );

			eval { $wmi->Connect(); };
			fail ($@, 9 ) if($@);

			&ChangeDependencies($wmi, \$service, \$clear, \$loadorder, \@ARGV);
		}
		######### DEPENDENCY QUERY OPTION ##########
		else
		{
			&CheckFormat(\$format);

			my %FilterCfg = (
			                 "Name"          => { Operators  => ['!','='] },
			                 "State"         => { Operators  => ['!','='],
			                                      ValueType => ['RUNNING', 'PAUSED', 'STOPPED'] },
			                 "DisplayName"   => { Operators  => ['!','='] },
			                 "LoadOrderGroup"=> { Operators  => ['!','='] },
			                 "LoadOrderNum"  => { ValueType  => 'Number',
			                                      Operators  => ['!','=', '<', '>'] },
			                 "Dependencies"  => { Operators  => ['!','='] }
			                );

			# Here Checking is to be done for the condition which should give syntax error
			# when ARGV is defined since Dependency  Query does not requires ARGV.
			if( @filter )
			{
				my $errfilter = W2RK::WMI->ValidateFilter( \@filter, \%FilterCfg );
				if( defined $errfilter ) 
				{
					fail( sprintf( ERROR_INVALID_OPTION, $errfilter, 'filter' ) , 7 );
				}
			}

			eval { $wmi->Connect(); };
			fail ($@, 9 ) if($@);

			&DependencyQuery($wmi, \@filter, \$format, \$service, \%FilterCfg);
		}
	}
	elsif( !defined $general and !defined $logon and !defined $dependencies )
	{
		fail( USAGE_MAIN, 8 ) if( !$help );

		if( defined $display, or defined $path or defined $type or defined $startmode or 
		    defined $runas or defined $runaspw or defined $interact or defined $service or 
		    defined $clear or defined $loadorder or @filter or defined $format or
		    defined $verbose or @ARGV or defined $wmi->{server} or defined $wmi->{username} 
		    or defined $wmi->{password})
		{
			fail( USAGE_MAIN, 8 );
		}
		else
		{
			&usage();
		}
	}
	else
	{
		fail( USAGE_MAIN, 8 );
	}
	exit( $errorlevel );
}

# ######################################################################### #
#
# PURPOSE   : Validates the format for Query criteria.
#
# INPUTS    : $format - Reference of the format string
#
# RETURN VALUE  : None.
#
# ######################################################################### #
sub CheckFormat
{
	my $format = $_[0];
	if(defined $$format)
	{
		fail( sprintf( ERROR_INVALID_OPTION, $$format, 'format' ) , 7 )
			if($$format !~ /^TABLE$|^LIST$|^CSV$/i);
		$$format = lc($$format);
		$$format = 'normal' if($$format eq 'table');
	}
	else
	{
		$$format = 'normal';
	}
}

# ######################################################################### #
#
# PURPOSE   : Retrieves the instances of a specified class.
#
# INPUTS    : $wmi   - Reference to WMI object.
#             $class - Class name for whcih to retrieve instances of.
#
# RETURN VALUE  : $instances - Instances of the specified class.
#
# ######################################################################### #
sub GetInstances
{
	my ($wmi, $class) = @_;
	my $instances;
	eval { $instances = $wmi->InstancesOf($class, IFLAG); };
	return undef if( $@ or !defined $instances );
	return $instances;
}


# ######################################################################### #
#
# PURPOSE   : Checks for valid service names as entered through
#             command line.
#
# INPUTS    : $services - Reference to services array.
#             $instances - Instances of Win32_Services.
#
# RETURN VALUE  : Array @newservices containing matched services instances.
#
# ######################################################################### #
sub CheckService
{
	my ($services, $instances) = @_;
	my @newservices;
	my $dumy;

	my $servicelist = "";
	foreach (@$services)
	{
		$dumy = $_;
		$dumy =~ s/\*+/\*/g;  $dumy =~ s/\[/\\\[/g;
		$dumy =~ s/\(/\\\(/g; $dumy =~ s/\)/\\\)/g;
		$dumy =~ s/\$/\\\$/g; $dumy =~ s/\|/\\\|/g;
		$dumy =~ s/\+/\\\+/g; $dumy =~ s/\./\\./g;
		$dumy =~ s/\^/\\^/g;  $dumy =~ s/\?/\\?/g;
		$dumy =~ s/\*/.\*/g;
		$servicelist .= "^$dumy\$|";
	}
	chop($servicelist);
	foreach (in $instances )
	{
		if( $_->{Name}    =~ /$servicelist/i || $_->{DisplayName} =~ /$servicelist/i )
		{
			my @temp = ($_, $&);
			push(@newservices,\@temp);
			&ValidateEntry($services, $&) if(@$services > 0);
		}
	}
	foreach ( @$services )
	{
		printf STDERR ERROR_NO_MATCHES, $_;
		$errorlevel = 2302;
	}
		
	return @newservices;
}


# ############################################################################ #
#
# PURPOSE	: To check whether an entry was matched in the service list
#
# INPUTS	: $Array - Reference of an array in which to match.
#		  $Value - The entry value to match.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub ValidateEntry
{
	my ($Array, $Value) = @_;
	my $temp;
	for(my $i=0; $i < @$Array; $i++ )
	{
		$temp = $$Array[$i];
		$temp =~ s/\*+/\*/g;	$temp =~ s/\[/\\\[/g;
		$temp =~ s/\(/\\\(/g;	$temp =~ s/\)/\\\)/g;
		$temp =~ s/\$/\\\$/g;	$temp =~ s/\|/\\\|/g;
		$temp =~ s/\+/\\\+/g;	$temp =~ s/\./\\./g;
		$temp =~ s/\^/\\^/g;	$temp =~ s/\?/\\?/g;
		$temp =~ s/\*/.\*/g;
		if($Value =~ /^$temp$/i)
		{
			splice(@$Array, $i, 1);
			$i--;
		}
	}
}


# ############################################################################ #
#
# PURPOSE   : Changes "General" service settings.
#
# INPUTS    : $wmi      - WMI object.
#             $display  - Reference to the new display name.
#             $path     - Reference to the new path.
#             $errorcontrol - Reference to the new errorcontrol.
#             $type     - Reference to the new service type.
#             $startmode    - Reference to the new start mode.
#             $args     - Reference to the default arguments.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub ChangeGeneral
{
	my ($wmi, $display, $path, $errorcontrol, $type, $startmode, $args) = @_;
	my ($error, $stype, $start);

	if(defined $$path)
	{
		my $temp = $wmi->ValidateABSPath($$path, 1)
			or fail( ( sprintf(ERROR_INVALID_PATH, $$path) ) , 4);
		$$path = $temp;
	}
	
	if(defined $$errorcontrol)
	{
		fail ( sprintf(ERROR_INVALID_OPTION, $$errorcontrol, 'errorcontrol' ) , 7)
			if($$errorcontrol !~ /^IGNORE$|^NORMAL$|^SEVERE$|^CRITICAL$/i);
		if($$errorcontrol =~ /^IGNORE$/i)
		{
			$error = 0;
		}
		elsif($$errorcontrol =~ /^NORMAL$/i)
		{
			$error = 1;
		}
		elsif($$errorcontrol =~ /^SEVERE$/i)
		{
			$error = 2;
		}
		elsif($$errorcontrol =~ /^CRITICAL$/i)
		{
			$error = 3;
		}
	}

	if(defined $$type)
	{
		fail ( sprintf(ERROR_INVALID_OPTION, $$type, 'type' ), 7 )
			if($$type !~ /^OWNPROC$|^SHAREDPROC$/i);
		$stype = ($$type =~ /^OWNPROC$/i) ? 16 : 32;
		$$type = ($$type =~ /^OWNPROC$/i) ? "Own Process" : "Share Process";	
	}

	if(defined $$startmode)
	{
		fail ( sprintf(ERROR_INVALID_OPTION, $$startmode, 'startmode' ) , 7)
			if($$startmode !~ /^AUTO$|^MANUAL$|^DISABLED$/i);
		$start = lc($$startmode);
		$start = "automatic" if($$startmode =~ /^AUTO$/i);
	}

	my $instances = &GetInstances($wmi, "Win32_Service");
	fail ( ERROR_NOINFO, 19 ) if( !defined $instances );

	@$args = &CheckService($args, $instances);
	exit($errorlevel) unless(@$args);

	foreach ( @$args )
	{
		my $skip = 1;
		$skip = 0 if(defined $$display && uc($$_[0]->{DisplayName}) ne uc($$display));
		$skip = 0 if(defined $$path && uc($$_[0]->{PathName}) ne uc($$path));
		$skip = 0 if(defined $$errorcontrol && uc($$_[0]->{ErrorControl}) ne uc($$errorcontrol));
		$skip = 0 if(defined $$type && uc($$_[0]->{ServiceType}) ne uc($$type));
		$skip = 0 if(defined $$startmode && uc($$_[0]->{StartMode}) ne uc($$startmode));

		if($skip)
		{
			printf STDERR WARN_NOT_UNIQUE, $$_[1], "General";
			$errorlevel = 100;
			next;
		}

		if(defined $$display)
		{
			my $coll;
			eval{ $coll = $wmi->ExecQuery("SELECT * FROM Win32_Service WHERE DisplayName='$$display'", IFLAG); };
			if(!$@ and defined $coll )
			{
				fail( sprintf( ERROR_DISPLAY_EXISTS, $$display ), 20 );
				next;
			}
		}
		my $Ret = $$_[0]->Change($$display,
		                         $$path,
		                         $stype,
		                         $error,
		                         $start);

		if(defined $Ret && $Ret == 0)
		{
			printf MSG_CHANGED, $$_[1], "General";
		}
		else
		{
			printf STDERR ERROR_NOT_CHANGED, $$_[1], "General";
			print STDERR "       ",$Error{$Ret},"\n" if(defined $Ret && defined $Error{$Ret});
			$errorlevel = 254;
		}
	}
}


# ############################################################################ #
#
# PURPOSE   : Changes "Logon" service settings.
#
# INPUTS    : $wmi      - WMI object.
#             $runas    - Reference to the new startname(Username).
#             $runaspw  - Reference to the new password.
#             $interact - Reference to the new desktop interact flag.
#             $args     - Reference to the default arguments.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub ChangeLogon
{
	my($wmi, $runas, $runaspw, $interact, $args) = @_;

	if(defined $$runas)
	{
		fail( sprintf( ERROR_INVALID_FORMAT, $$runas, 'runas' ) , 7)
			if($$runas !~ /\w+\\?\w+/i);
		my $temp = $$runas;
		if($$runas =~ /^LOCALSYSTEM$/i)
		{
			$$runas = "LOCALSYSTEM";
		}
		else
		{
			my ($domain, $user);
			if($$runas =~ /\\/)
			{
				($domain, $user) = split /\\/, $$runas;
			}
			else
			{
				$domain = ".";
				$user = $$runas;
			}
			if($domain eq ".")
			{
				my $CSInstances = $wmi->InstancesOf("Win32_ComputerSystem", IFLAG);
				my @CS = in $CSInstances;
				$domain = $CS[0]->{Name};
				$$runas = ".\\$user";
			}
			my $obj;
			eval{ $obj = $wmi->services->Get("Win32_UserAccount.Domain='$domain',Name='$user'"); };
			fail( sprintf( ERROR_INVALID_USER, $temp ), 24 ) if( $@ or !defined $obj );
		}
	}

	if(defined $$interact)
	{
		fail( sprintf( ERROR_INVALID_OPTION, $$interact, 'interact' ) , 7 )
			if($$interact !~ /^ON$|^OFF$/i);
		$$interact = ($$interact =~ /^ON$/i) ? 1 : 0;
	}

	my $instances = &GetInstances($wmi, "Win32_Service");
	fail( ERROR_NOINFO, 19) if( !defined $instances );

	@$args = &CheckService($args, $instances);
	exit($errorlevel) unless(@$args);

	foreach ( @$args )
	{
		my $password;
		my $dskint;
		my $skip=1;
		if(defined $$interact)
		{
			if( (defined $$runas && $$runas ne "LOCALSYSTEM") ||
			    (!defined $$runas && uc($$_[0]->{StartName}) ne "LOCALSYSTEM") )
			{
				printf STDERR WARN_NODESKTOP_INTERACT, $$_[1];
				$errorlevel = 2303;
				next;
			}
			elsif($$interact != $$_[0]->{DesktopInteract})
			{
				$dskint = $$interact;
				$skip = 0;
			}
		}

		if(defined $$runaspw)
		{
			if( (defined $$runas && $$runas eq "LOCALSYSTEM") ||
			    (!defined $$runas && uc($$_[0]->{StartName}) eq "LOCALSYSTEM"))
			{
				printf STDERR WARN_PASSWORD_NA, $$_[1];
				$errorlevel = 2304;
				next;
			}
			$password = $$runaspw;
			$skip = 0;
		}
		else
		{
			$password = "" unless(defined $$runaspw);
		}
		if(defined $$runas && uc($$runas) ne uc($$_[0]->{StartName}))
		{
			$skip = 0;
			$dskint = 0 if($$runas ne "LOCALSYSTEM");
		}

		if($skip)
		{
			printf STDERR WARN_NOT_UNIQUE, $$_[1], "Logon";
			$errorlevel = 100;
			next;
		}
		else
		{
			if( defined $$runas and $$runas =~ /^LocalSystem$/i )
			{
				$$runas = 'LocalSystem' ; $password = undef;
			}
			my $Ret = $$_[0]->Change( undef,
			                          undef,
			                          undef,
			                          undef,
			                          undef,
			                          $dskint,
			                          $$runas,
			                          $password);

			if(defined $Ret && $Ret == 0)
			{
				printf MSG_CHANGED, $$_[1], "Logon" ;
				printf MSG_RESTART
					if(uc($$_[0]->{State}) eq "RUNNING" && (defined $$runas || defined $$runaspw));
			}
			else
			{
				printf STDERR ERROR_NOT_CHANGED, $$_[1], "Logon";
				print STDERR "       ",$Error{$Ret},"\n" if(defined $Ret && defined $Error{$Ret});
				$errorlevel = 254;
			}
		}
	}
}

# ############################################################################ #
#
# PURPOSE   : Changes "Dependency" service settings.
#
# INPUTS    : $wmi       - WMI object.
#             $service   - Reference to the service name.
#             $clear     - Reference to the clear flag.
#             $loadorder - Reference to the new loadorder group.
#             $args      - Reference to the default arguments.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub ChangeDependencies
{
	my($wmi, $service, $clear, $loadorder, $args) = @_;

#	my $instance = $wmi->services->Get("Win32_Service.Name='$$service'")
#		or fail "ERROR: No matches found for \'$$service\' in existing services.\n";
	my $Qcoll;
	eval{ $Qcoll = $wmi->ExecQuery("SELECT * FROM Win32_Service WHERE Name=\"$$service\" OR DisplayName=\"$$service\"", IFLAG); };
	fail( sprintf( ERROR_NO_MATCHES, $$service ), 2302 )
		if($@ or !defined $Qcoll);

	foreach my $instance ( in $Qcoll )
	{
		my @dservice = ();
		my $skip = 1;
	
		if(defined $$loadorder)
		{
			my $LDGrp;
			eval{ $LDGrp = $instance->Associators_("", "Win32_LoadOrderGroup", "", "", undef, undef,"", "", IFLAG, undef); };
			if(!$@ and defined $LDGrp )
			{
				my @InLDGrp = in $LDGrp;
				$skip = 0 if(uc($InLDGrp[0]->{Name}) ne uc($$loadorder));
			}
			else
			{
				$skip = 0;
			}
			my $obj;
			eval{ $obj = $wmi->services->Get("Win32_LoadOrderGroup.Name='$$loadorder'"); };
			fail ( sprintf( ERROR_INVALID_LOADORDER, $$loadorder ), 24 )
				if( $@ or !defined $obj);
			$$loadorder = $obj->{Name};
		}

		if($$clear)
		{
			push(@dservice, "");
			$skip = 0;
		}
		if(defined @$args && @$args > 0)
		{
			my $count = 0;
			@dservice = ();

			my $instances = &GetInstances($wmi, "Win32_Service");
			fail( ERROR_NOINFO, 19 ) if( !defined $instances );

			my $cnt = @$args;
			@$args = &CheckService($args, $instances);
			exit($errorlevel) if(@$args < $cnt);

			unless($$clear)
			{
				my $path = $instance->Path_()->{Path};
				$path =~ s/\\/\\\\/g;
				$path =~ s/\"/\\\"/g;
				my $coll;
				eval{ $coll = $wmi->ExecQuery("SELECT * FROM Win32_DependentService WHERE Dependent = \"$path\"", IFLAG); };
				if(!$@ or defined $coll)
				{
					foreach (in $coll)
					{
						my $depend;
						eval{ $depend = $wmi->services->Get($_->{Antecedent}); };
						push (@dservice, $depend->{Name}) if(defined $depend);
					}
				}
			}
			foreach my $entry ( @$args )
			{
				my $flag = 1;
				foreach ( @dservice )
				{
					if($_ =~ /^$$entry[0]->{Name}$/i)
					{
						$flag = 0;
						last;
					}
				}
				push (@dservice, $$entry[0]->{Name}) if($flag);
			}
			if($count != @dservice)
			{
				$skip = 0;
			}
			else
			{
				@dservice = ();
			}
		}

		if($skip)
		{
			printf STDERR WARN_NOT_UNIQUE, $$service, "Dependency";
			$errorlevel = 100;
			return;
		}
		else
		{
			my $Ret = $instance->Change( undef,
			                             undef,
			                             undef,
			                             undef,
			                             undef,
			                             undef,
			                             undef,
			                             undef,
			                             $$loadorder,
			                             undef,
			                             \@dservice );

			if(defined $Ret && $Ret == 0)
			{
				printf MSG_CHANGED, $$service, "Dependency";
			}
			else
			{
				printf STDERR ERROR_NOT_CHANGED, $$service, "Dependency";
				print STDERR "       ",$Error{$Ret},"\n" if(defined $Ret && defined $Error{$Ret});
				$errorlevel = 254;
			}
		}
	}
}


# ############################################################################ #
#
# PURPOSE   : Queries and displays "General" service settings.
#
# INPUTS    : $wmi      - WMI object.
#             $filter   - Reference to the filter array.
#             $format   - Reference to the format type.
#             $verbose  - Reference to the verbose flag.
#             $args     - Reference to the default arguments.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub GeneralQuery
{
	my ($wmi, $filter, $format, $verbose, $args, $FilterCfg) =@_;

	my $instances = &GetInstances($wmi, "Win32_Service");
	fail( ERROR_NOINFO, 19 ) if( !defined $instances );

	push(@$args, "*") if(@$args == 0);
	@$args = &CheckService($args, $instances);
	exit( $errorlevel ) unless(@$args);

	my @table;
	my @temp = ( 'Name', 'State', 'DisplayName', 'StartMode', 'StartName',
	             'DesktopInteract', 'ErrorControl', 'Type',
	             'AcceptStop', 'AcceptPause', 'Path');
	push(@table, \@temp);

	foreach ( @$args )
	{
		my @temp = ( 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A' );

		$temp[0] = $$_[0]->{Name}          if( defined $$_[0]->{Name} );
		$temp[1] = $$_[0]->{State}         if( defined $$_[0]->{State} );
		$temp[2] = $$_[0]->{DisplayName}   if( defined $$_[0]->{DisplayName} );
		$temp[3] = $$_[0]->{StartMode}     if( defined $$_[0]->{StartMode} );
		$temp[4] = $$_[0]->{StartName}     if( defined $$_[0]->{StartName} );
		$temp[5] = $$_[0]->{DesktopInteract} ? "ON" : "OFF"  if( defined $$_[0]->{DesktopInteract} );
		$temp[6] = $$_[0]->{ErrorControl}  if( defined $$_[0]->{ErrorControl} );
		$temp[7] = $$_[0]->{ServiceType} =~ /^Own Process$/i ? "OWNPROC" : "SHAREDPROC" if( defined $$_[0]->{ServiceType} );
		$temp[8] = $$_[0]->{AcceptStop} ? "YES" : "NO"   if( defined $$_[0]->{AcceptStop} );
		$temp[9] =  $$_[0]->{AcceptPause} ? "YES" : "NO" if( defined $$_[0]->{AcceptPause} );
		$temp[10]= $$_[0]->{PathName}      if( defined $$_[0]->{PathName} );

		push(@table, \@temp);
	}

	if(@$filter > 0)
	{
		$wmi->FilterResults( \@table,$filter,$FilterCfg );
		if( @table <= 1 )
		{
			fail( ERROR_NOINFO_FILTER, 30 );
		}
	}

	if(@table > 1)
	{
	    $wmi->ShowTable(
	                    \@table,
	                    { Format => $$format,
	                      HeaderDashes => (@table > 1) ? 1 : 0,
	                      NoHeader => (@table > 1) ? 0 : 1},
	                    Name            => { Name => 'Name', Align => 'left' },
	                    State           => { Name => 'State', Align => 'left' },
	                    DisplayName     => { Name => 'Display Name', Align => 'left' },
	                    StartMode       => { Name => 'Start Mode', Align => 'left'},
	                    StartName       => { Name => 'Log On As', Align => 'left' },
	                    DesktopInteract => { Name => 'Interactive', Align => 'left'},
	                    ErrorControl    => { Name => 'Error Control', Align => 'left',
	                                         Hide => ($$verbose ? 0 : 1) },
	                    Type            => { Name => 'Service Type', Align => 'left',
	                                         Hide => ($$verbose ? 0 : 1),
	                                         Formatter => sub { ($_[0] eq "OWNPROC") ? "Own Process" : "Share Process" } },
	                    AcceptStop      => { Name => 'Accept Stop', Align => 'left',
	                                         Hide => ($$verbose ? 0 : 1) },
	                    AcceptPause     => { Name => 'Accept Pause', Align => 'left',
	                                         Hide => ($$verbose ? 0 : 1) },
	                    Path            => { Name => 'Path Name', Align => 'left',
	                                         Hide => ($$verbose ? 0 : 1) }
	                  );
	}
	else
	{
		fail( ERROR_NOINFO, 19 )
	}
}


# ############################################################################ #
#
# PURPOSE   : Queries and displays "Logon" service settings.
#
# INPUTS    : $wmi      - WMI object.
#             $filter   - Reference to the filter array.
#             $format   - Reference to the format type.
#             $args     - Reference to the default arguments.
#             $FilterCfg - Reference to Filter Configruation arguments.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub LogonQuery
{
	my ($wmi, $filter, $format, $args, $FilterCfg) =@_;

	my $instances = &GetInstances($wmi, "Win32_Service");
	fail( ERROR_NOINFO, 19 ) if( !defined $instances );

	push(@$args, "*") if(@$args == 0);
	@$args = &CheckService($args, $instances);
	exit($errorlevel) unless(@$args);

	my @table;
	my @temp = ('Name', 'State', 'DisplayName', 'RunAs', 'Interact');
	push(@table, \@temp);
	foreach ( @$args )
	{
		my @temp = ( 'N/A', 'N/A', 'N/A', 'N/A', 'N/A' );
		$temp[0] = $$_[0]->{Name}        if( defined $$_[0]->{Name} );
		$temp[1] = $$_[0]->{State}       if( defined $$_[0]->{State} );
		$temp[2] = $$_[0]->{DisplayName} if( defined $$_[0]->{DisplayName} );
		$temp[3] = $$_[0]->{StartName}   if( defined $$_[0]->{StartName} );
		$temp[4] = $$_[0]->{DesktopInteract} ? "ON" : "OFF";

		if( lc( $temp[3] ) ne 'localsystem' )
		{
			$temp[4] = 'N/A';
		}
		push(@table, \@temp);
	}
	if(@$filter > 0)
	{
		$wmi->FilterResults(\@table, $filter, $FilterCfg );
		fail( ERROR_NOINFO_FILTER, 30 ) if( @table <= 1 );
	}

	if(@table > 1)
	{
		$wmi->ShowTable( \@table,
		                 { Format => $$format,
		                   HeaderDashes => (@table > 1) ? 1 : 0,
		                   NoHeader => (@table > 1) ? 0 : 1},
		                 Name => { Name => 'Name', Align => 'left' },
		                 State => { Name => 'State', Align => 'left'},
		                 DisplayName => { Name => 'Display Name', Align => 'left' },
		                 RunAs => { Name => 'Log On As', Align => 'left' },
		                 Interact => { Name => 'Interactive', Align => 'left'}
		               );
	}
	else
	{
		fail( ERROR_NOINFO, 19 );
	}

}


# ############################################################################ #
#
# PURPOSE   : Queries and displays "Dependency" service settings.
#
# INPUTS    : $wmi      - WMI object.
#             $filter   - Reference to the filter array.
#             $format   - Reference to the format type.
#             $service  - Reference to the service name.
#
# RETURN VALUES : None.
#
# ############################################################################ #
sub DependencyQuery
{
	my ($wmi, $filter, $format, $service, $FilterCfg ) =@_;
	my @args = ($$service);

	my $instances = &GetInstances($wmi, "Win32_Service");
	fail( ERROR_NOINFO, 19 ) if( !defined $instances );

	@args = &CheckService(\@args, $instances);
	exit($errorlevel) unless(@args);

	my @table;
	my @temp = ( 'Name', 'State', 'DisplayName', 'LoadOrderGroup', 
	             'LoadOrderNum', 'Dependencies');
	push(@table, \@temp);
	my $size = 0;
	my $displayed = 0;

	foreach ( @args )
	{
		my @temp = ( 'N/A', 'N/A', 'N/A', 'N/A', 'N/A' );
		$temp[0] = $$_[0]->{Name}        if( defined $$_[0]->{Name} );
		$temp[1] = $$_[0]->{State}       if( defined $$_[0]->{State} );
		$temp[2] = $$_[0]->{DisplayName} if( defined $$_[0]->{DisplayName} );

		my $path = $$_[0]->Path_()->{Path};
		$path =~ s/\\/\\\\/g;
		$path =~ s/\"/\\\"/g;

		my $LDGrp;
		eval{ $LDGrp = $$_[0]->Associators_("", "Win32_LoadOrderGroup", "", "", undef, undef, "", "", IFLAG, undef); };
		if(!$@ and defined $LDGrp )
		{
			my @InLDGrp = in $LDGrp;
			$temp[3] = $InLDGrp[0]->{Name}       if( defined( $InLDGrp[0]->{Name} ) );
			$temp[4] = $InLDGrp[0]->{GroupOrder} if( defined( $InLDGrp[0]->{GroupOrder} ) );
		}

		my @depservices = ();
		my $coll;
		eval{ $coll = $wmi->ExecQuery("SELECT * FROM Win32_DependentService WHERE Dependent = \"$path\"", IFLAG); };
		if(!$@ and defined $coll )
		{
			foreach (in $coll)
			{
				my $depend;
				eval{ $depend = $wmi->services->Get($_->{Antecedent}); };
				push( @depservices, $depend->{Name}) if(defined $depend);
			}
		}
		$temp[5] = \@depservices if( $#depservices > -1 );
		push(@table, \@temp);

		if( $size == MAX_SIZE )
		{
			$size = 0;
			if(@$filter > 0)
			{
				$wmi->FilterResults(\@table,$filter,$FilterCfg );
			}

			if(@table > 1)
			{
				$wmi->ShowTable( \@table,
				                 { Format => $$format,
				                   HeaderDashes => ( $displayed == 0 ) ? 1 : 0,
				                   NoHeader => ( $displayed ) ? 1 : 0}, 
				                 Name  => { Name => 'Name', Align => 'left' ,MinWidth => 20},
				                 State => { Name => 'State', Align => 'left',MinWidth => 8},
				                 DisplayName => { Name => 'Display Name', Align => 'left' ,MinWidth => 35},
				                 LoadOrderGroup => { Name => 'Load Order Group', Align => 'left',MinWidth => 35},
				                 LoadOrderNum => { Name => 'Load Order Number', Align => 'left',MinWidth => 20},
				                 Dependencies => { Name => 'Dependencies', Align => 'left',
				                                   Formatter => sub { $_[0] ? ( @{$_[0]} > 0 ? join(",", @{$_[0]}) : "N/A" ) : 'N/A' } }
				              );
				@table = $table[0];
				$displayed = 1;
			}
		}
		else
		{
			$size++;
		}
	}

	if( @$filter && @table > 1 )
	{
		$wmi->FilterResults(\@table,$filter,$FilterCfg );
	}

	if(@table > 1)
	{
		$wmi->ShowTable( \@table,
		                 { Format => $$format,
		                   HeaderDashes => $displayed == 0 ? 1 : 0,
		                   NoHeader => ($displayed) ? 1 : 0}, 
		                 Name  => { Name => 'Name', Align => 'left', MinWidth => 20 },
		                 State => { Name => 'State', Align => 'left',MinWidth => 8},
		                 DisplayName => { Name => 'Display Name', Align => 'left',MinWidth => 35 },
		                 LoadOrderGroup => { Name => 'Load Order Group', Align => 'left',MinWidth => 35},
		                 LoadOrderNum => { Name => 'Load Order Number', Align => 'left',MinWidth => 20},
		                 Dependencies => { Name => 'Dependencies', Align => 'left',
		                                   Formatter => sub { $_[0] ? ( @{$_[0]} > 0 ? join(",", @{$_[0]}) : "N/A" ) : 'N/A' } }
		              );
		$displayed = 1;
	}

	fail( ERROR_NOINFO_FILTER, 30 ) if(@$filter && $displayed == 0 );
	fail( ERROR_NOINFO, 19 ) if( $displayed == 0 );
}

# ######################################################################### #
#
# PURPOSE	: Prints usage to STDOUT and exits.
#
# ######################################################################### #
sub usage
{
print <<EOF;

ServiceConfig.pl -Operation [Arguments]

Description:
    Change or query General, Logon or Dependency properties
    for one or more installed service(s).

Operation List:
    -general         Specifies the General service properties
                     to be queried and/or changed.

    -logon           Specifies the Logon service properties
                     to be queried and/or changed.

    -dependencies    Specifies the Dependency service properties
                     to be queried and/or changed.

For detailed usage:
    ServiceConfig.pl -general      -?
    ServiceConfig.pl -logon        -?
    ServiceConfig.pl -dependencies -?
EOF
exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -general option to STDOUT and exits.
#
# ######################################################################### #
sub GeneralHelp
{
print <<EOF;

ServiceConfig.pl -general [-s machine [-u user [-p password ] ] ]
                 [ 
                   [-displayname displayname]
                   [-path path]
                   [-errorcontrol errorcontrol]
                   [-type type]
                   [-startmode startmode] 
                 ] | 
                 [ [-filter filter]
                   [-format format] 
                   [-verbose] 
                 ] servicename...

Description:
    Change or query the General properties and settings
    for one or more installed service(s).

Parameter List:
    -s              machine      Specifies the remote System to connect to.

    -u              user         Specifies the username (user context)
                                 to run the script's commands under.

    -p              password     Specifies the user password.

    -displayname    displayname  Specifies the new "Display Name"
                                 to use for the service(s) specified.

    -path           path         Specifies the new "Path to Executable"
                                 to use for the service(s) specified.

    -errorcontrol   errorcontrol Specifies the severity of the error
                                 if the service(s) fails to start during
                                 startup. Valid values are IGNORE,
                                 NORMAL, SEVERE or CRITICAL.

    -type           type         Specifies the new "Service Type" to use
                                 for the service(s) specified.
                                 Valid values are OWNPROC or
                                 SHAREDPROC.

    -startmode      startmode    Specifies the new "Startup Type" to use
                                 for the service(s) specified.
                                 Valid values are AUTO, MANUAL or
                                 DISABLED.

    -filter         filter       Specifies the service(s) to filter in
                                 or out of the query based on the 
                                 specified criteria.

    -format         format       Specifies the type of output to
                                 display. Valid values are TABLE, LIST
                                 or CSV.

    -verbose                     Display verbose service(s) properties and
                                 settings.

    default                      Specifies the service(s) by Name
                                 or "Display Name", whose "General"
                                 properties or settings are to be
                                 changed/queried.

Note:

1. Following are the valid filters that are applicable.

    FilterName    Valid Operators  Valid Value types
    ----------    ---------------  -----------------
    NAME          '!' , '='        String 
    STATE         '!' , '='        RUNNING | PAUSED | STOPPED
    DISPLAYNAME   '!' , '='        String
    ERRORCONTROL  '!' , '='        IGNORE | NORMAL | SEVERE | CRITICAL
    ACCEPTPAUSE   '!' , '='        YES | NO
    ACCEPTSTOP    '!' , '='        YES | NO
    STARTMODE     '!' , '='        AUTO | MANUAL | DISABLED | BOOT | DRIVER
    PATH          '!' , '='        String
    TYPE          '!' , '='        OWNPROC | SHAREDPROC

Examples:
    ServiceConfig.pl -general *
    ServiceConfig.pl -general -format List -v "Dns Server"
    ServiceConfig.pl -general -format csv -filter "state=stopped" Net*
    ServiceConfig.pl -general -s server -u user -p password
                     -filter "Path=C:\\WINNT\\System32\\services.exe" 
                      Dhcp dmserver clipsrv -v
    ServiceConfig.pl -general -startmode AUTO Messenger EventLog Dns*
    ServiceConfig.pl -general -displayname "Test Dns Server" 
                     -path "c:\\Winnt\\system32\\dns.exe" Dns
    ServiceConfig.pl -general -s server -u user -p password 
                     -errorcontrol NORMAL -type SHAREDPROC
                      Messenger EventLog

EOF
exit(0);
}


# ######################################################################### #
#
# PURPOSE	: Prints usage for -logon option to STDOUT and exits.
#
# ######################################################################### #
sub LogonHelp
{
print <<EOF;

ServiceConfig.pl -logon [-s machine [-u user [-p password ] ] ] 
                 [
                   [-runas username ]
                   [-runaspw password]
                   [-interact type]
                 ] | 
                 [
                   [-filter filter]
                   [-format format]
                 ] servicename...

Description:
    Change or query the Logon properties and settings
    for one or more installed services.

Parameter List:
    -s          machine     Specifies the remote System to connect to.

    -u          user        Specifies the username (user context)
                            to run the script's commands under.

    -p          password    Specifies the user password.

    -runas      username    Specifies a new user context for
                            the service to run under.

    -runaspw    password    Specifies the password of the new
                            user specified in runas option.

    -interact   type        Specifies whether the service(s)
                            should interact with the Desktop 
                            or not. Valid values are ON or OFF.

    -filter     filter      Specifies the service(s) to filter 
                            in or out of the query based
                            on the specified criteria.

    -format     format      Specifies the type of output to
                            display. Valid values are TABLE, LIST
                            or CSV.

    default                 Specifies the service(s) by Name
                            or "Display Name", whose "Logon"
                            properties or settings are to be
                            changed/queried.

Note:
1. Following are the valid filters that are applicable.

    FilterName    Valid Operators  Valid Value types
    ----------    ---------------  -----------------
    NAME          '!' , '='        String
    STATE         '!' , '='        RUNNING | PAUSED | STOPPED
    DISPLAYNAME   '!' , '='        String
    RUNAS         '!' , '='        String
    INTERACT      '!' , '='        ON | OFF

Examples:
    ServiceConfig.pl -logon *
    ServiceConfig.pl -logon -interact ON Dn*
    ServiceConfig.pl -logon -format List DNS Messenger 
    ServiceConfig.pl -logon -format csv -filter "state=running" Net*
    ServiceConfig.pl -logon -format table -filter "interact=off" Net*
    ServiceConfig.pl -logon -s server -u user -p password -format LIST
                      Alerter Messenger EventLog
    ServiceConfig.pl -logon -runas user1 -runaspw password1
                      Alerter Messenger EventLog

EOF
exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -dependencies option to STDOUT and exits.
#
# ######################################################################### #
sub DependenciesHelp
{

print <<EOF;

ServiceConfig.pl -dependencies [-s machine [-u user [-p password] ] ]
                 -service servicename
                 [
                    [-clear]
                    [-loadorder loadorder]
                    [dependencies...]
                 ]|
                 [
                    [-filter filter]
                    [-format format]
                 ]

Description:
    Change or query the Dependency properties and settings
    for one or more installed services.

Parameter List:
    -s          machine         Specifies the remote System to connect to.

    -u          user            Specifies the username (user context)
                                to run the script's commands under.

    -p          password        Specifies the user password.

    -service    servicename     Specifies the name of the service(s) to
                                change the dependency list on.
                                When query option is followed
                                "Service Name" or "Display Name" can
                                be specified.

    -clear                      Specified to clear the specified 
                                service's dependency list.

    -loadorder  loadorder       Specifies a new "Load Order Group"
                                that the specified service is a part of.

    -filter     filter          Specifies the service(s) to filter 
                                in or out of the query based
                                on the specified criteria.

    -format     format          Specifies the type of output to
                                display. Valid values are TABLE, LIST
                                or CSV.

    default                     Specifies the list of dependencies that
                                the service(s) specified with -service switch
                                require. Default behavior is to append 
                                to the current dependency list.

Note:

1. Following are the valid filters that are applicable.

    FilterName      Valid Operators         Valid Value types
    ----------     ---------------          -----------------
    NAME            '!' , '='               String
    STATE           '!' , '='               RUNNING | PAUSED | STOPPED
    DISPLAYNAME     '!' , '='               String
    LOADORDERGROUP  '!' , '='               String
    LOADORDERNUM    '!' , '=' , '<' , '>'   Number
    DEPENDENCIES    '!' , '='               String

Examples:
    ServiceConfig.pl -dependencies -service *
    ServiceConfig.pl -dependencies -service dns* -format list
    ServiceConfig.pl -dependencies -format csv -filter "state=running"
                     -service Net*
    ServiceConfig.pl -dependencies -service dns* -filter loadordernum=25
    ServiceConfig.pl -dependencies -service EventLog
    ServiceConfig.pl -dependencies -s server -u user -p password -format CSV
                     -service A*
    ServiceConfig.pl -dependencies -service Dfs -clear -loadorder Dfs
                      lanmanserver lanmanworkstation

EOF
exit(0);
}