BEGIN {
	push(@INC, "$ENV{SVP_HOME}\\wk\\supervisor\\setup");
}
use strict;

use Win32;
use Win32::API;
use Win32::Service;
use Win32::OLE('in');


require 'MPCServices.pm';

## Macro
use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;


use constant serviceStoppingTimeout => 60;


use constant TRUE => 1;
use constant FALSE => 0;
use constant ENABLE => 1;

use constant FILE_NAME => "stopAllMPCServices";


use constant PERL_EXE => "perl.exe";


use constant STR_STOPPED => "STOPPED";


use constant KEY_SERVICE_NAME => "ServiceName";


use constant KEY_STOP_METHOD => "StopMethod";


use constant KEY_ENABLE_STOP => "EnableStop";


use constant KEY_STOP_BAT => "Stop_bat";




use constant MSG_SUCCESS => "Success";
use constant MSG_FAILED => "Failed";


use constant TYPE_API => 1;
use constant TYPE_BAT => 2;


use constant ID_GET_SUPERVISOR => 0x100;
use constant ID_STOP_BAT => 0x200;
use constant ID_STOP_SERVICE => 0x300;
use constant ID_CHANGE_STARTUP => 0x400;


use constant ERR_ADMIN => 100;
use constant ERR_TIMEOUT => 200;
use constant ERR_PROCESS => 201;
use constant ERR_OTHER => 202;
use constant ERR_NOT_FOUND_FILE => 300;

use constant ERROR_SERVICE_ALREADY_RUNNING => 1056;
use constant ERROR_SERVICE_NOT_ACTIVE => 1062;
use constant ERROR_ACCESS_DENIED => 5;
use constant ERROR_SUCCESS => 0;
use constant ERROR => 1;
my $host = "localhost";

use constant INI_FILE => "$ENV{SVP_HOME}\\wk\\supervisor\\setup\\cnf\\supervisor.ini";
use constant PROC_RESTAPI => "MAPPRestAPIServer";

my $outLog;


my %services; 
my @sectionList;

$MPCServices::mode = 1;

sub getSuperviserIni {
	my $section;
	my $errCode = ERROR_SUCCESS;
	my $iniFile = INI_FILE;

	if(! -f $iniFile) {
		$errCode = ERR_NOT_FOUND_FILE;
		MPCServices::writeLog(ID_GET_SUPERVISOR, $errCode, $iniFile, $outLog);
		MPCServices::printMessage(ERR_NOT_FOUND_FILE);
		exit(ERROR);
	}
	open (IN, $iniFile) or die "$!";
	
	while(<IN>) {
		chomp;
		if(/^\[([\w]+)\].*/) {
			$section = $1;
			push @sectionList, $section;
		}
		if(/^([\w _]+)\s*=\s*\"*([\w \\ \. _]+)\"*/) {
			my $keyword = $1;
			my $value = $2;
			$services{$section}{$keyword} = $value;
		}
	}
	close(IN);
	MPCServices::writeLog(ID_GET_SUPERVISOR, $errCode, $iniFile, $outLog);
	
}


sub isServiceStopped {
	my $serviceName = $_[0];
	my %status;

	Win32::Service::GetStatus($host, $serviceName, \%status);
	
	if(MPCServices::getServiceStatusCodeStr($status{'CurrentState'}) eq STR_STOPPED) {
		return TRUE;
	}
	
	return FALSE;
}


sub stopServices() {
	my $serviceName;
	my $stopMethod;
	my $enableStop;
	my $batFile;
	my $errCode = ERROR_SUCCESS;

	
	print "Waiting for Storage Navigator services to stop...\n";
	foreach my $section (@sectionList) {
		if(!exists($services{$section}->{+KEY_SERVICE_NAME})) {
			next;
		}

		$serviceName = $services{$section}->{+KEY_SERVICE_NAME};
		$stopMethod = $services{$section}->{+KEY_STOP_METHOD};
		$enableStop = $services{$section}->{+KEY_ENABLE_STOP};

		if( PROC_RESTAPI eq $serviceName ){
			 if(FALSE == MPCServices::checkServiceName($serviceName)){
				next;
			}
		}

		if($enableStop == ENABLE) {
			if($stopMethod == TYPE_BAT) {
				$batFile = $ENV{SVP_HOME} . "\\" . $services{$section}->{+KEY_STOP_BAT};
				$errCode = stopServiceByBat($serviceName, $batFile);

			}
			elsif ($stopMethod == TYPE_API){
				$errCode = stopServiceByAPI($serviceName);
			}
			else {
				$errCode = ERR_OTHER;
			}
		}
		else {
			$errCode = ERR_OTHER;
		}
		MPCServices::writeLog(ID_STOP_SERVICE, $errCode, $serviceName, $outLog);
		
		if($errCode != ERROR_SUCCESS && $errCode != ERROR_SERVICE_NOT_ACTIVE){
			return $errCode;
		}
	}
	
	$errCode = checkMappRemainedProcesses();
	
	if($errCode == ERR_PROCESS){
		sleep(60);
		$errCode = checkMappRemainedProcesses();
	}
	
	return $errCode;
}


sub changeStartup {
	my $serviceName;
	my $errCode = ERROR_SUCCESS;
	my $command;

	foreach my $section (@sectionList) {
		if(!exists($services{$section}->{+KEY_SERVICE_NAME})) {
			next;
		}
		$serviceName = $services{$section}->{+KEY_SERVICE_NAME};

		if( PROC_RESTAPI eq $serviceName ){
			 if(FALSE == MPCServices::checkServiceName($serviceName)){
				next;
			}
		}

		$command = "sc config " . $serviceName . " start= demand >nul 2>&1";
		$errCode = system($command);
		$errCode = $errCode >> 8;

		MPCServices::writeLog(ID_CHANGE_STARTUP, $errCode, $serviceName, $outLog);
	}
	
	if($errCode == ERROR_ACCESS_DENIED)
	{
		MPCServices::printMessage(ERR_ADMIN);
		exit(ERROR);
	}
}


sub stopServiceByAPI() {
	my $serviceName = $_[0];
	my $errCode = ERROR_SUCCESS;
	my $numWaiting = 0;

	Win32::Service::StopService($host, $serviceName);
	$errCode = Win32::GetLastError();

	if($errCode != ERROR_SUCCESS && $errCode != ERROR_SERVICE_NOT_ACTIVE) {
		$errCode = ERR_OTHER;
		return $errCode;
	}
	
	while(! isServiceStopped($serviceName)) {
		sleep(1);
		if($numWaiting++ >= serviceStoppingTimeout) {
			$errCode = ERR_TIMEOUT;
			last;
		}
	}
	return $errCode;
}


sub stopServiceByBat() {
	my ($serviceName, $fileName) = @_;
	my $errCode = ERROR_SUCCESS;
	my $numWaiting = 0;
	if(-f $fileName) {
		$errCode =  system($fileName . ">nul 2>&1"); 
		$errCode = $errCode >> 8;
		if($errCode > 0) {
			$errCode = ERR_OTHER;
		}
		while(! isServiceStopped($serviceName)) {
			sleep(1);
			if($numWaiting++ >= serviceStoppingTimeout) {
				$errCode = ERR_TIMEOUT;
				last;
			}
		}
	}else {
		$errCode = ERR_NOT_FOUND_FILE;
		MPCServices::writeLog(ID_STOP_BAT, $errCode, $fileName, $outLog);	
	}
	return $errCode;
	
}


sub checkMappRemainedProcesses {
	my $objWMIService = Win32::OLE->GetObject("winmgmts:\\\\$host\\root\\CIMV2") or die "WMI connection failed.\n";
	my $colItems = $objWMIService->ExecQuery("SELECT * FROM Win32_Process", "WQL", wbemFlagReturnImmediately | wbemFlagForwardOnly);
	my $name;
	my $commandLine;
	my $obj;
	
	foreach my $objItem  (in $colItems) {
		$name = $objItem->{Name};
		$commandLine = $objItem->{CommandLine};
		if($name ne PERL_EXE){
			if ($commandLine =~ /^\Q$ENV{SVP_HOME}/) {
				return ERR_PROCESS;
			}
		}
	}
	
	return ERROR_SUCCESS;
}


my $err;

print "Stopping Storage Navigator services...\n";
$outLog = MPCServices::openLog(FILE_NAME);

getSuperviserIni();

changeStartup();

$err = stopServices();

MPCServices::closeLog($outLog);

$err = MPCServices::printMessage($err);

exit($err);
