windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/restart/cmdline/iisrsta.cxx

1278 lines
38 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*
IisRsta.cxx
Command line utility for access to IIisServiceControl
FILE HISTORY:
Phillich 06-Oct-1998 Created
*/
#define INITGUID
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <ole2.h>
#include <locale.h>
#include "iisrsta.h"
#include "iisrstam.h"
typedef BOOL (*PFNQUERYSERVICECONFIG2)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD) ;
typedef BOOL (*PFNCHANGESERVICECONFIG2)(SC_HANDLE,DWORD,LPVOID);
//
// HRESULTTOWIN32() maps an HRESULT to a Win32 error. If the facility code
// of the HRESULT is FACILITY_WIN32, then the code portion (i.e. the
// original Win32 error) is returned. Otherwise, the original HRESULT is
// returned unchagned.
//
#define HRESULTTOWIN32(hres) \
((HRESULT_FACILITY(hres) == FACILITY_WIN32) \
? HRESULT_CODE(hres) \
: (hres))
//
// RETURNCODETOHRESULT() maps a return code to an HRESULT. If the return
// code is a Win32 error (identified by a zero high word) then it is mapped
// using the standard HRESULT_FROM_WIN32() macro. Otherwise, the return
// code is assumed to already be an HRESULT and is returned unchanged.
//
#define RETURNCODETOHRESULT(rc) \
(((rc) < 0x10000) \
? HRESULT_FROM_WIN32(rc) \
: (rc))
//
// Helper functions
//
VOID
DisplayErrorMessage(
DWORD dwErr
)
/*++
DisplayErrorMessage
Display error message associated with error code
Arguments:
dwErr - Win32 error code
Returns:
Nothing
--*/
{
LPTSTR pErr;
if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pErr,
0,
NULL ) )
{
LPTSTR p;
if ( p = _tcschr( pErr, TEXT('\r') ) )
{
*p = TEXT('\0');
}
_fputts( pErr, stdout );
LocalFree( pErr );
}
}
VOID
PrintMessage(
DWORD dwId,
DWORD dwParams,
LPVOID* pParams
)
/*++
PrintMessage
Print message ( from message file ) with optional parameters
Arguments:
dwId - message ID
dwParams - # of params in pParams
pParams - ptr to array of parameters
Returns:
Nothing
--*/
{
LPTSTR pBuf;
if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID)NULL, //GetModuleHandle(NULL),
dwId,
0,
(LPTSTR)&pBuf,
dwParams,
(va_list *)pParams ) )
{
_fputts( pBuf, stdout );
LocalFree( pBuf );
}
}
VOID
CmdError(
DWORD dwId,
HRESULT hRes
)
/*++
CmdError
Display message followed by error description ( error message + numerical code )
Arguments:
dwId - message ID
hRes - error code
Returns:
Nothing
--*/
{
TCHAR achBuf[128];
PrintMessage( dwId, 0, NULL );
if ( hRes == RETURNCODETOHRESULT( ERROR_RESOURCE_DISABLED ) )
{
PrintMessage( IRSTASTR_REMOTE_DISABLED, 0, NULL );
}
else if ( hRes == RETURNCODETOHRESULT( ERROR_ACCESS_DENIED ) )
{
PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL );
}
else if ( hRes == RETURNCODETOHRESULT( ERROR_SERVICE_NOT_ACTIVE ) )
{
PrintMessage( IRSTASTR_IISADMIN_DISABLED, 0, NULL );
}
else
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
wsprintf( achBuf, _T(" (%u, %x)\n"), (DWORD)hRes, (DWORD)hRes );
_fputts( achBuf, stdout );
}
}
LPTSTR
GetString(
DWORD dwId
)
/*++
GetString
Retrieve message content
Arguments:
dwId - message ID
Returns:
Ptr to message. Must be freed using LocalFree()
--*/
{
#if 0
TCHAR aBuf[32];
aBuf[0] = TEXT('#');
_ultot( dwId, aBuf + 1, 10 );
return (LPTSTR)LoadResource( NULL, FindResourceEx( NULL, RT_MESSAGETABLE, aBuf, MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL) ) );
#else
LPTSTR pBuf;
if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE,
(LPCVOID)NULL,
dwId,
0,
(LPTSTR)&pBuf,
0,
NULL ) )
{
LPTSTR p;
if ( p = _tcschr( pBuf, TEXT('\r') ) )
{
*p = TEXT('\0');
}
return pBuf;
}
return NULL;
#endif
}
HRESULT
DeserializeEnumServiceBuffer(
LPBYTE pbInBuffer,
DWORD dwNumServices,
LPBYTE pbBuffer,
DWORD dwBufferSize,
LPDWORD pdwMDRequiredBufferSize
)
/*++
DeserializeEnumServiceBuffer
Deserialize array of SERIALIZED_ENUM_SERVICE_STATUS to buffer,
replacing offset in buffer by ptr
Arguments:
pbInBuffer - buffer containing serialized status as array of SERIALIZED_ENUM_SERVICE_STATUS
dwNumServices - # of entries in pbInBuffer
pbBuffer - buffer filled with deserialized status as array of ENUM_SERVICE_STATUS
dwBufferSize - maximum size of pbBuffer
pdwMDRequiredBufferSize - updated with required size if dwBufferSize too small
Returns:
ERROR_INSUFFICIENT_BUFFER if dwBufferSize too small
otherwise COM status
--*/
{
HRESULT hresReturn = S_OK;
DWORD dwMinSize = 0;
UINT i;
SERIALIZED_ENUM_SERVICE_STATUS* pessDependentServices = (SERIALIZED_ENUM_SERVICE_STATUS*)pbInBuffer;
if ( !pbBuffer )
{
dwBufferSize = 0;
}
dwMinSize = sizeof(ENUM_SERVICE_STATUS) * dwNumServices;
for ( i = 0 ;
i < dwNumServices ;
++i )
{
UINT cServiceName = _tcslen( (TCHAR*)(pbInBuffer + pessDependentServices[i].iServiceName) ) + 1;
UINT cDisplayName = _tcslen( (TCHAR*)(pbInBuffer + pessDependentServices[i].iDisplayName) ) + 1;
if ( dwBufferSize >= dwMinSize + ( cServiceName + cDisplayName ) * sizeof(TCHAR) )
{
((LPENUM_SERVICE_STATUS)pbBuffer)[i].ServiceStatus =
pessDependentServices[i].ServiceStatus;
memcpy( pbBuffer + dwMinSize, pbInBuffer + pessDependentServices[i].iServiceName, cServiceName * sizeof(TCHAR) );
((LPENUM_SERVICE_STATUS)pbBuffer)[i].lpServiceName = (TCHAR*)(pbBuffer + dwMinSize);
memcpy( pbBuffer + dwMinSize + cServiceName * sizeof(TCHAR), pbInBuffer + pessDependentServices[i].iDisplayName, cDisplayName * sizeof(TCHAR) );
((LPENUM_SERVICE_STATUS)pbBuffer)[i].lpDisplayName = (TCHAR*)(pbBuffer + dwMinSize) + cServiceName;
}
dwMinSize += ( cServiceName + cDisplayName ) * sizeof(TCHAR);
}
if ( dwBufferSize < dwMinSize )
{
*pdwMDRequiredBufferSize = dwMinSize;
hresReturn = RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER );
}
return hresReturn;
}
HRESULT
SetEnableRemote(
DWORD dwValue
)
/*++
SetEnableRemote
set restart I/F enabled flag in registry
( HKLM\SOFTWARE\Microsoft\INetStp::EnableRestart::REG_DWORD )
Arguments:
dwValue - 0 to disable I/F, !0 to enable
Returns:
status
--*/
{
DWORD dwSt = NO_ERROR;
HKEY hKey;
//
// Check admin privilege by accessing IISADMIN key for write
//
if ( ( dwSt = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("SYSTEM\\CurrentControlSet\\Services\\IISADMIN"),
0,
KEY_WRITE,
&hKey ) ) == ERROR_SUCCESS )
{
RegCloseKey( hKey );
//
// Set IISCTL interface access flag in registry
//
if ( ( dwSt = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\INetStp"),
0,
KEY_WRITE,
&hKey ) ) == ERROR_SUCCESS )
{
if ( ( dwSt = RegSetValueEx( hKey,
TEXT("EnableRestart"),
0,
REG_DWORD,
(const BYTE*)&dwValue,
sizeof(DWORD) ) ) == ERROR_SUCCESS )
{
}
RegCloseKey( hKey );
}
}
return RETURNCODETOHRESULT( dwSt );
}
BOOL
GetNumeric(
LPSTR pszNumArg,
LPDWORD pdwVal
)
{
if ( !isdigit( (UCHAR)(*pszNumArg) ) )
{
return FALSE;
}
*pdwVal = atoi( pszNumArg );
return TRUE;
}
BOOL
IsIIS6orGreater(
)
/*++
IsIIS6orGreater
According to Aaron we are guaranteed to have
the appropriate keys in the registry by the
time iisreset /scm is called.
Arguments:
None
Returns:
TRUE = IIS 6 or greater;
FALSE = anything below IIS 6;
--*/
{
// Assume it is not IIS 6.
BOOL IsIIS6 = FALSE;
HKEY hKey;
DWORD dwValue;
DWORD dwType;
DWORD dwSize;
// Check the registry of the major version setup number.
// If it is not there we assume it is not a 6.0 machine,
// since it's better to setup a 6.0 machine in 5.0 state
// instead of a 5.0 machine in 6.0 state.
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("System\\CurrentControlSet\\Services\\W3SVC\\Parameters"),
0,
KEY_READ,
&hKey ) == ERROR_SUCCESS )
{
if ( RegQueryValueEx( hKey,
TEXT("MajorVersion"),
0,
&dwType,
(LPBYTE)&dwValue,
&dwSize ) == ERROR_SUCCESS )
{
if ( dwType == REG_DWORD )
{
if ( dwValue >= 6 )
{
// were are running on a system that does not
// have atleast IIS 6 on it
IsIIS6 = TRUE;
}
}
}
RegCloseKey( hKey );
}
return IsIIS6;
}
HRESULT
SetSCM(
LPCTSTR pszCmdline,
BOOL fEnable
)
/*++
SetSCM
set SCM Recovery configuration for IISADMIN service.
Does nothing on pre Windows 2000 systems.
Arguments:
pszCmdline - command line to invoke on service failure ( for IISAdmin ), can be NULL to invoke current EXE ( i.e. IISRESET )
fEnable - TRUE to enable IISRESET invocation on service failure, FALSE to disable
Returns:
status
--*/
{
PFNQUERYSERVICECONFIG2 pfnQueryServiceConfig2 = NULL;
PFNCHANGESERVICECONFIG2 pfnChangeServiceConfig2 = NULL;
SERVICE_FAILURE_ACTIONS sfaAction;
SC_ACTION saCmdline[3];
SC_HANDLE schSCM;
SC_HANDLE schSrv;
HRESULT hres = S_OK;
TCHAR achModuleName[MAX_PATH];
TCHAR achFailureCommand[MAX_PATH+32];
HINSTANCE hAdvapi;
if ( hAdvapi = LoadLibrary(_T("ADVAPI32.DLL")) )
{
pfnQueryServiceConfig2 = (PFNQUERYSERVICECONFIG2)GetProcAddress( hAdvapi, "QueryServiceConfig2W" );
pfnChangeServiceConfig2 = (PFNCHANGESERVICECONFIG2)GetProcAddress( hAdvapi, "ChangeServiceConfig2W" );
}
if ( pfnQueryServiceConfig2
&& pfnChangeServiceConfig2 )
{
if ( pszCmdline == NULL )
{
if ( !GetModuleFileName( NULL,
achModuleName,
sizeof(achModuleName)/sizeof(TCHAR) ) )
{
hres = RETURNCODETOHRESULT( GetLastError() );
}
else
{
pszCmdline = achModuleName;
}
}
if ( SUCCEEDED( hres ) )
{
schSCM = OpenSCManager(NULL,
NULL,
SC_MANAGER_ALL_ACCESS);
if ( schSCM == NULL )
{
hres = RETURNCODETOHRESULT( GetLastError() );
}
else
{
// We need to determine what IIS version we are running on
// in order to know the correct way to setup the server.
BOOL fIIS6orGreater = IsIIS6orGreater();
//
// In IIS 5.1 we want to use the default /restart
// setting of iisreset. In IIS 6 or greater we
// want to use the /start option. A customer
// can configure it to use the /restart option, but
// that is not the default for the scm.
//
if ( fIIS6orGreater )
{
wsprintf( achFailureCommand, _T("\"%s\" /start /fail=%%1%%"), pszCmdline );
}
else
{
wsprintf( achFailureCommand, _T("\"%s\" /fail=%%1%%"), pszCmdline );
}
sfaAction.lpCommand = achFailureCommand;
sfaAction.lpRebootMsg = _T("");
sfaAction.dwResetPeriod = 24 * 60 * 60;
if ( fEnable )
{
sfaAction.cActions = 3;
sfaAction.lpsaActions = saCmdline;
saCmdline[0].Type = SC_ACTION_RUN_COMMAND;
saCmdline[0].Delay = 1;
saCmdline[1].Type = SC_ACTION_RUN_COMMAND;
saCmdline[1].Delay = 1;
saCmdline[2].Type = SC_ACTION_RUN_COMMAND;
saCmdline[2].Delay = 1;
}
else
{
sfaAction.cActions = 3;
sfaAction.lpsaActions = saCmdline;
saCmdline[0].Type = SC_ACTION_NONE;
saCmdline[0].Delay = 0;
saCmdline[1].Type = SC_ACTION_NONE;
saCmdline[1].Delay = 0;
saCmdline[2].Type = SC_ACTION_NONE;
saCmdline[2].Delay = 0;
}
schSrv = OpenService( schSCM,
_T("IISADMIN"),
SERVICE_ALL_ACCESS);
if ( schSrv )
{
if ( !pfnChangeServiceConfig2( schSrv,
SERVICE_CONFIG_FAILURE_ACTIONS,
&sfaAction ) )
{
hres = RETURNCODETOHRESULT( GetLastError() );
}
CloseServiceHandle( schSrv );
}
else
{
hres = RETURNCODETOHRESULT( GetLastError() );
}
//
// Now that we have configured IISAdmin correctly, we also need to
// configure W3SVC.
//
if ( fIIS6orGreater )
{
sfaAction.lpCommand = NULL;
sfaAction.lpRebootMsg = _T("");
sfaAction.dwResetPeriod = 24 * 60 * 60;
if ( fEnable )
{
sfaAction.cActions = 3;
sfaAction.lpsaActions = saCmdline;
saCmdline[0].Type = SC_ACTION_RESTART;
saCmdline[0].Delay = 1;
saCmdline[1].Type = SC_ACTION_RESTART;
saCmdline[1].Delay = 1;
saCmdline[2].Type = SC_ACTION_RESTART;
saCmdline[2].Delay = 1;
}
else
{
sfaAction.cActions = 3;
sfaAction.lpsaActions = saCmdline;
saCmdline[0].Type = SC_ACTION_NONE;
saCmdline[0].Delay = 0;
saCmdline[1].Type = SC_ACTION_NONE;
saCmdline[1].Delay = 0;
saCmdline[2].Type = SC_ACTION_NONE;
saCmdline[2].Delay = 0;
}
schSrv = OpenService( schSCM,
_T("W3SVC"),
SERVICE_ALL_ACCESS);
if ( schSrv )
{
if ( !pfnChangeServiceConfig2( schSrv,
SERVICE_CONFIG_FAILURE_ACTIONS,
&sfaAction ) )
{
hres = RETURNCODETOHRESULT( GetLastError() );
}
CloseServiceHandle( schSrv );
}
else
{
hres = RETURNCODETOHRESULT( GetLastError() );
}
} // end of setting up restart on w3svc.
CloseServiceHandle( schSCM );
}
}
}
if ( hAdvapi )
{
FreeLibrary( hAdvapi );
}
return hres;
}
enum CMDS { CMD_NONE, CMD_START, CMD_STOP, CMD_REBOOT, CMD_RESTART, CMD_KILL };
int __cdecl
main(
int argc,
char*argv[]
)
/*++
main
main function
Arguments:
argc
argv
Returns:
0 if no error, otherwise error code
--*/
{
IIisServiceControl* pIf;
int iA;
int Status = 0;
HRESULT hRes;
CMDS iCmd = CMD_NONE;
DWORD dwStopTimeout = 60 * 1000;
DWORD dwRestartTimeout = 20 * 1000;
DWORD dwStartTimeout = 60 * 1000;
LPBYTE pbBuffer;
BYTE abBuffer[4096];
LPBYTE pbOutBuffer;
BYTE abOutBuffer[4096];
DWORD dwRequired;
DWORD dwNumServices;
LPVOID apvParams[8];
UINT i;
BOOL fNoCmd = FALSE;
BOOL fRebootOnError = FALSE;
BOOL fKillOnError = TRUE;
BOOL fForce = TRUE;
BOOL fRebootRestart = FALSE;
BOOL fStatus = FALSE;
COSERVERINFO csiMachineName;
MULTI_QI rgmq;
WCHAR awchComputer[64];
LPSTR pszMachineName = NULL;
BOOL fErrDisplayed = FALSE;
DWORD dwFailCount;
//
// Make sure international versions display text ok - RonaldM
//
_tsetlocale( LC_ALL, _T(".OCP") );
_fputts( _T("\n"), stdout );
//
// scan command line
//
for ( iA = 1 ;
iA < argc ;
++iA )
{
if ( argv[iA][0] == '-' || argv[iA][0] == '/' )
{
if ( !lstrcmpiA( argv[iA]+1, "ENABLE" ) )
{
hRes = SetEnableRemote( 1 );
if ( FAILED( hRes ) )
{
if ( hRes == RETURNCODETOHRESULT( ERROR_ACCESS_DENIED ) )
{
PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL );
}
else
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
}
Status = HRESULTTOWIN32( hRes );
}
else
{
PrintMessage( IRSTASTR_ENABLED, 0, NULL );
}
fNoCmd = TRUE;
}
else if ( !lstrcmpiA( argv[iA]+1, "DISABLE" ) )
{
hRes = SetEnableRemote( 0 );
if ( FAILED( hRes ) )
{
if ( hRes == RETURNCODETOHRESULT( ERROR_ACCESS_DENIED ) )
{
PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL );
}
else
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
}
Status = HRESULTTOWIN32( hRes );
}
else
{
PrintMessage( IRSTASTR_DISABLED, 0, NULL );
}
fNoCmd = TRUE;
}
else if ( !_strnicmp( argv[iA]+1, "SCM", sizeof("SCM")-1 ) )
{
if ( FAILED( hRes = SetSCM( NULL, TRUE ) ) )
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
Status = HRESULTTOWIN32( hRes );
}
goto Exit;
}
else if ( !_strnicmp( argv[iA]+1, "NOSCM", sizeof("NOSCM")-1 ) )
{
if ( FAILED( hRes = SetSCM( NULL, FALSE ) ) )
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
Status = HRESULTTOWIN32( hRes );
}
goto Exit;
}
else if ( !_strnicmp( argv[iA]+1, "STOPTIMEOUT:", sizeof("STOPTIMEOUT:")-1 ) )
{
if ( !GetNumeric( argv[iA]+ 1 + sizeof("STOPTIMEOUT:") - 1, &dwStopTimeout ) )
{
goto invalid_param;
}
dwStopTimeout *= 1000;
}
else if ( !_strnicmp( argv[iA]+1, "TIMEOUT:", sizeof("TIMEOUT:")-1 ) )
{
if ( !GetNumeric( argv[iA]+ 1 + sizeof("TIMEOUT:") - 1, &dwStopTimeout ) )
{
goto invalid_param;
}
dwStopTimeout *= 1000;
dwRestartTimeout = dwStopTimeout;
}
else if ( !_strnicmp( argv[iA]+1, "STARTTIMEOUT:", sizeof("STARTTIMEOUT:")-1 ) )
{
if ( !GetNumeric( argv[iA]+ 1 + sizeof("STARTTIMEOUT:") - 1, &dwStartTimeout ) )
{
goto invalid_param;
}
dwStartTimeout *= 1000;
}
else if ( !_strnicmp( argv[iA]+1, "RESTARTTIMEOUT:", sizeof("RESTARTTIMEOUT:")-1 ) )
{
if ( !GetNumeric( argv[iA]+ 1 + sizeof("RESTARTTIMEOUT:") - 1, &dwRestartTimeout ) )
{
goto invalid_param;
}
dwRestartTimeout *= 1000;
}
else if ( !_strnicmp( argv[iA]+1, "fail=", sizeof("fail=")-1 ) )
{
//
// SCM flag to control restart threshold. We restart only
// 50 times per SCM restart period.
//
// ... The SCM UI already has a way to address this: they add
// a "/fail=N" parameter to the command line
// of the restarter app for each time they fail within the time
// period and leave it up to the restarter app to interpret
// this parameter and throttle restarts approprately.
// So...(here's the change request) we need to capture this
// value, and if "N" is greater than our limit for 1 day of
// restarting (hardcoded to 50), we should just exit the
// command line app with a success code without doing anything,
// i.e. "IISRESET.EXE /fail=50" should restart IIS,
// but "IISRESET.EXE /fail=51" should be a no-op.
// For simplicity, we should hardcode this value of 50 in
// our app-- if a user wants a different value, he can write
// a batch file wrapper to do it! You can see
// the SCM recovery tab for more info.
//
dwFailCount = atoi( argv[iA]+ 1 + sizeof("fail=") - 1 );
if ( dwFailCount > 50 )
{
return 0;
}
}
else if ( !lstrcmpiA( argv[iA]+1, "START" ) )
{
if ( fRebootRestart )
{
}
else if ( iCmd == CMD_STOP )
{
iCmd = CMD_RESTART;
}
else
{
iCmd = CMD_START;
}
}
else if ( !lstrcmpiA( argv[iA]+1, "STOP" ) )
{
if ( fRebootRestart )
{
}
if ( iCmd == CMD_START )
{
iCmd = CMD_RESTART;
}
else
{
iCmd = CMD_STOP;
}
}
else if ( !lstrcmpiA( argv[iA]+1, "REBOOT" ) )
{
iCmd = CMD_REBOOT;
fRebootRestart = TRUE;
}
else if ( !lstrcmpiA( argv[iA]+1, "KILL" ) )
{
iCmd = CMD_KILL;
fRebootRestart = TRUE;
}
else if ( !lstrcmpiA( argv[iA]+1, "RESTART" ) )
{
iCmd = CMD_RESTART;
fRebootRestart = TRUE;
}
else if ( !lstrcmpiA( argv[iA]+1, "STATUS" ) )
{
fStatus = TRUE;
}
else if ( !lstrcmpiA( argv[iA]+1, "REBOOTONERROR" ) )
{
fRebootOnError = TRUE;
fKillOnError = FALSE;
}
else if ( !lstrcmpiA( argv[iA]+1, "NOFORCE" ) )
{
fKillOnError = FALSE;
fForce = FALSE;
}
else if ( !lstrcmpiA( argv[iA]+1, "HELP" ) )
{
PrintMessage( IRSTASTR_USAGE, 0, NULL );
return 0;
}
else
{
invalid_param:
PrintMessage( IRSTASTR_USAGE, 0, NULL );
return ERROR_INVALID_PARAMETER;
}
}
else
{
pszMachineName = argv[iA];
}
}
if ( iCmd == CMD_NONE && !fNoCmd && !fStatus )
{
iCmd = CMD_RESTART;
}
//
//fill the structure for CoCreateInstanceEx
//
ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
if ( pszMachineName )
{
if ( !MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pszMachineName,
-1,
awchComputer,
sizeof(awchComputer) / sizeof(WCHAR)) )
{
return GetLastError();
}
csiMachineName.pwszName = awchComputer;
}
else
{
csiMachineName.pwszName = NULL;
}
if ( fNoCmd )
{
iCmd = CMD_NONE;
fStatus = FALSE;
}
if ( iCmd != CMD_NONE || fStatus )
{
BOOL fCoInitialized = true;
//
// call method
//
rgmq.pIID = &IID_IIisServiceControl;
rgmq.pItf = NULL;
rgmq.hr = 0;
if (FAILED(hRes = CoInitializeEx( NULL, COINIT_MULTITHREADED ))) {
fCoInitialized = false;
}
else if ( SUCCEEDED( hRes = CoCreateInstanceEx( CLSID_IisServiceControl,
NULL,
CLSCTX_SERVER,
&csiMachineName,
1,
&rgmq ) ) &&
SUCCEEDED( hRes = rgmq.hr ) )
{
pIf = (IIisServiceControl*)rgmq.pItf;
switch ( iCmd )
{
case CMD_START:
PrintMessage( IRSTASTR_START_ATTEMPT, 0, NULL );
hRes = pIf->Start( dwStartTimeout );
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_START_SUCCESS, 0, NULL );
}
else
{
CmdError( IRSTASTR_START_FAILED, hRes );
fErrDisplayed = TRUE;
}
break;
case CMD_STOP:
PrintMessage( IRSTASTR_STOP_ATTEMPT, 0, NULL );
hRes = pIf->Stop( dwStopTimeout, fKillOnError );
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_STOP_SUCCESS, 0, NULL );
}
else
{
CmdError( IRSTASTR_STOP_FAILED, hRes );
fErrDisplayed = TRUE;
}
break;
case CMD_REBOOT:
PrintMessage( IRSTASTR_REBOOT_ATTEMPT, 0, NULL );
hRes = pIf->Reboot( dwRestartTimeout, fForce );
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_REBOOT_SUCCESS, 0, NULL );
}
else
{
CmdError( IRSTASTR_REBOOT_FAILED, hRes );
fErrDisplayed = TRUE;
}
break;
case CMD_KILL:
PrintMessage( IRSTASTR_KILL_ON_ERROR, 0, NULL );
hRes = pIf->Kill();
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_KILL_SUCCESS, 0, NULL );
}
else
{
CmdError( IRSTASTR_KILL_FAILED, hRes );
fErrDisplayed = TRUE;
}
break;
case CMD_RESTART:
PrintMessage( IRSTASTR_STOP_ATTEMPT, 0, NULL );
hRes = pIf->Stop( dwRestartTimeout, fKillOnError );
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_STOP_SUCCESS, 0, NULL );
PrintMessage( IRSTASTR_START_ATTEMPT, 0, NULL );
hRes = pIf->Start( dwStartTimeout );
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_RESTART_SUCCESS, 0, NULL );
}
}
if ( FAILED( hRes ) )
{
CmdError( IRSTASTR_RESTART_FAILED, hRes );
fErrDisplayed = TRUE;
}
break;
}
if ( fStatus )
{
pbBuffer = NULL;
fErrDisplayed = FALSE;
if ( FAILED( hRes = pIf->Status( sizeof(abBuffer),
abBuffer,
&dwRequired,
&dwNumServices ) ) )
{
if ( RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER ) == hRes )
{
if ( (pbBuffer = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) == NULL )
{
hRes = RETURNCODETOHRESULT( ERROR_NOT_ENOUGH_MEMORY );
}
else
{
hRes = pIf->Status( dwRequired,
pbBuffer,
&dwRequired,
&dwNumServices );
}
}
}
else
{
pbBuffer = abBuffer;
}
if ( SUCCEEDED( hRes ) )
{
pbOutBuffer = NULL;
if ( FAILED( hRes = DeserializeEnumServiceBuffer( pbBuffer,
dwNumServices,
abOutBuffer,
sizeof(abOutBuffer),
&dwRequired ) ) )
{
if ( RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER ) == hRes )
{
if ( (pbOutBuffer = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) == NULL )
{
hRes = RETURNCODETOHRESULT( ERROR_NOT_ENOUGH_MEMORY );
}
else
{
hRes = DeserializeEnumServiceBuffer( pbBuffer,
dwNumServices,
pbOutBuffer,
dwRequired,
&dwRequired );
}
}
}
else
{
pbOutBuffer = abOutBuffer;
}
}
if ( SUCCEEDED( hRes ) )
{
for ( i = 0 ; i < dwNumServices ; ++i )
{
apvParams[0] = ((LPENUM_SERVICE_STATUS)pbOutBuffer)[i].lpDisplayName;
apvParams[1] = ((LPENUM_SERVICE_STATUS)pbOutBuffer)[i].lpServiceName;
switch ( ((LPENUM_SERVICE_STATUS)pbOutBuffer)[i].ServiceStatus.dwCurrentState )
{
case SERVICE_STOPPED:
apvParams[2] = GetString(IRSTASTR_SERVICE_STOPPED); break;
case SERVICE_START_PENDING:
apvParams[2] = GetString(IRSTASTR_SERVICE_START_PENDING); break;
case SERVICE_STOP_PENDING:
apvParams[2] = GetString(IRSTASTR_SERVICE_STOP_PENDING); break;
case SERVICE_RUNNING:
apvParams[2] = GetString(IRSTASTR_SERVICE_RUNNING); break;
case SERVICE_CONTINUE_PENDING:
apvParams[2] = GetString(IRSTASTR_SERVICE_CONTINUE_PENDING); break;
case SERVICE_PAUSE_PENDING:
apvParams[2] = GetString(IRSTASTR_SERVICE_PAUSE_PENDING); break;
case SERVICE_PAUSED:
apvParams[2] = GetString(IRSTASTR_SERVICE_PAUSED); break;
default:
apvParams[2] = GetString(IRSTASTR_SERVICE_DEFAULT); break;
}
PrintMessage( IRSTASTR_STATUS_ITEM, 3, apvParams );
}
}
if ( pbBuffer != NULL && pbBuffer != abBuffer )
{
LocalFree( pbBuffer );
}
if ( pbOutBuffer != NULL && pbOutBuffer != abOutBuffer )
{
LocalFree( pbOutBuffer );
}
}
if ( FAILED( hRes ) && fRebootOnError
&& ( iCmd == CMD_STOP || iCmd == CMD_RESTART ) )
{
fErrDisplayed = FALSE;
PrintMessage( IRSTASTR_REBOOT_ON_ERROR, 0, NULL );
hRes = pIf->Reboot( 0, fForce );
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_REBOOT_SUCCESS, 0, NULL );
}
}
#if 0
if ( FAILED( hRes ) && fKillOnError
&& ( iCmd == CMD_STOP || iCmd == CMD_RESTART ) )
{
fErrDisplayed = FALSE;
PrintMessage( IRSTASTR_KILL_ON_ERROR, 0, NULL );
hRes = pIf->Kill();
if ( SUCCEEDED( hRes ) )
{
PrintMessage( IRSTASTR_KILL_SUCCESS, 0, NULL );
}
}
#endif
pIf->Release();
if ( FAILED( hRes ) )
{
if ( !fErrDisplayed )
{
if ( hRes == RETURNCODETOHRESULT( ERROR_RESOURCE_DISABLED ) )
{
PrintMessage( IRSTASTR_REMOTE_DISABLED, 0, NULL );
}
else if ( hRes == RETURNCODETOHRESULT( ERROR_ACCESS_DENIED ) )
{
PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL );
}
else
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
}
}
Status = HRESULTTOWIN32( hRes );
}
}
else
{
if ( hRes == RETURNCODETOHRESULT( ERROR_ACCESS_DENIED ) )
{
PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL );
}
else
{
DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
}
Status = HRESULTTOWIN32( hRes );
}
if (fCoInitialized) {
CoUninitialize();
}
}
Exit:
return Status;
}