|
|
/*
IisRsta.cxx
Command line utility for access to IIisServiceControl
FILE HISTORY: Phillich 06-Oct-1998 Created
*/
#define INITGUID
#include <windows.h>
#include <winnlsp.h>
#include <tchar.h>
#include <stdio.h>
#include <ole2.h>
#include <locale.h>
#include "iisrsta.h"
#include "iisrstam.h"
// Including so we can use the WIN32_FROM_HRESULT macro that is defined there
#include "iisdef.h"
typedef BOOL (*PFNCHANGESERVICECONFIG2)(SC_HANDLE,DWORD,LPVOID);
#define MAX_STRINGIZED_ULONG_CHAR_COUNT 11 // "4294967295", including the terminating null
//
// 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;
p = _tcschr( pErr, TEXT('\r') ); if ( p != NULL ) { *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 == HRESULT_FROM_WIN32( ERROR_RESOURCE_DISABLED ) ) { PrintMessage( IRSTASTR_REMOTE_DISABLED, 0, NULL ); } else if ( hRes == HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) ) { PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL ); } else if ( hRes == HRESULT_FROM_WIN32( ERROR_SERVICE_NOT_ACTIVE ) ) { PrintMessage( IRSTASTR_SERVICE_NOT_ACTIVE, 0, NULL ); } else { DisplayErrorMessage( WIN32_FROM_HRESULT( 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()
--*/ { LPTSTR pBuf;
if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE, (LPCVOID)NULL, dwId, 0, (LPTSTR)&pBuf, 0, NULL ) ) { LPTSTR p;
p = _tcschr( pBuf, TEXT('\r') ); if ( p != NULL ) { *p = TEXT('\0'); } return pBuf; }
return NULL; }
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 = (UINT) _tcslen( (TCHAR*)(pbInBuffer + pessDependentServices[i].iServiceName) ) + 1; UINT cDisplayName = (UINT) _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 = HRESULT_FROM_WIN32( 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 HRESULT_FROM_WIN32( dwSt ); }
BOOL GetNumeric( LPSTR pszNumArg, LPDWORD pdwVal ) { // protect against being called wrong.
if ( pszNumArg == NULL || pdwVal == NULL ) { return FALSE; }
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( BOOL fEnable ) /*++
SetSCM
set SCM Recovery configuration for IISADMIN service. Does nothing on pre Windows 2000 systems.
Arguments: fEnable - TRUE to enable IISRESET invocation on service failure, FALSE to disable
Returns: status
--*/ { 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;
hAdvapi = LoadLibrary(_T("ADVAPI32.DLL")); if ( hAdvapi != NULL ) { pfnChangeServiceConfig2 = (PFNCHANGESERVICECONFIG2)GetProcAddress( hAdvapi, "ChangeServiceConfig2W" ); }
if ( pfnChangeServiceConfig2 ) { if ( !GetModuleFileName( NULL, achModuleName, sizeof(achModuleName)/sizeof(TCHAR) ) ) { hres = HRESULT_FROM_WIN32( GetLastError() ); }
if ( SUCCEEDED( hres ) ) { schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if ( schSCM == NULL ) { hres = HRESULT_FROM_WIN32( 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 ) { //achModuleName is MAX_PATH size, the rest of the string is less than 32 characters.
wsprintf( achFailureCommand, _T("\"%s\" /start /fail=%%1%%"), achModuleName ); } else { //achModuleName is MAX_PATH size, the rest of the string is less than 32 characters.
wsprintf( achFailureCommand, _T("\"%s\" /fail=%%1%%"), achModuleName ); }
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_CHANGE_CONFIG);
if ( schSrv ) { if ( !pfnChangeServiceConfig2( schSrv, SERVICE_CONFIG_FAILURE_ACTIONS, &sfaAction ) ) { hres = HRESULT_FROM_WIN32( GetLastError() ); }
CloseServiceHandle( schSrv ); } else { hres = HRESULT_FROM_WIN32( 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_CHANGE_CONFIG | SERVICE_START);
if ( schSrv ) { if ( !pfnChangeServiceConfig2( schSrv, SERVICE_CONFIG_FAILURE_ACTIONS, &sfaAction ) ) { hres = HRESULT_FROM_WIN32( GetLastError() ); }
CloseServiceHandle( schSrv ); } else { hres = HRESULT_FROM_WIN32( 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 };
// We use lstrcmpiA to compare arguments typed in with our cmd options
// on foreign code pages case insensitivity can be missed, but since we
// are comparing against the english letters, and don't use foreign letters
// I believe this will be ok.
#pragma prefast(push)
#pragma prefast(disable:400, "Don't complain about using lstrcmpiA")
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 = NULL; BYTE abBuffer[4096]; LPBYTE pbOutBuffer = NULL; 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; ULONG CodePage = 0; TCHAR CodePageString[MAX_STRINGIZED_ULONG_CHAR_COUNT + 1];
//
// Make sure international versions display text ok - RonaldM
//
_tsetlocale( LC_ALL, _T(".OCP") );
// in order to get output working when the user code page
// does not match the system code page or the system installed language
// we have added the following lines, thru the second _tsetlocale.
// this was recommended by Rostislav Shabalin. It was also recommended
// to keep the original _tsetlocale because it may be setting configuration
// that will not get changed in the second _tsetlocal call.
// See RAID Windows Bugs #712030 for more info.
CodePage = GetConsoleOutputCP();
CodePageString[0] = _T('.'); _ultot(CodePage, &(CodePageString[1]), 10 );
_tsetlocale( LC_ALL, CodePageString );
// Per issue: 439690 we need to make this call to make sure
// that localized builds work correctly in all cases.
SetThreadUILanguage(0);
_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 == HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) ) { PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL ); } else { DisplayErrorMessage( WIN32_FROM_HRESULT( hRes ) ); }
Status = WIN32_FROM_HRESULT( hRes ); } else { PrintMessage( IRSTASTR_ENABLED, 0, NULL ); }
fNoCmd = TRUE; } else if ( !lstrcmpiA( argv[iA]+1, "DISABLE" ) ) { hRes = SetEnableRemote( 0 );
if ( FAILED( hRes ) ) { if ( hRes == HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) ) { PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL ); } else { DisplayErrorMessage( WIN32_FROM_HRESULT( hRes ) ); }
Status = WIN32_FROM_HRESULT( hRes ); } else { PrintMessage( IRSTASTR_DISABLED, 0, NULL ); }
fNoCmd = TRUE; } else if ( !_strnicmp( argv[iA]+1, "SCM", sizeof("SCM")-1 ) ) { if ( FAILED( hRes = SetSCM( TRUE ) ) ) { DisplayErrorMessage( WIN32_FROM_HRESULT( hRes ) );
Status = WIN32_FROM_HRESULT( hRes ); } goto Exit; } else if ( !_strnicmp( argv[iA]+1, "NOSCM", sizeof("NOSCM")-1 ) ) { if ( FAILED( hRes = SetSCM( FALSE ) ) ) { DisplayErrorMessage( WIN32_FROM_HRESULT( hRes ) );
Status = WIN32_FROM_HRESULT( 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, // process whole string including null terminator
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 ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == hRes ) { if ( (pbBuffer = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) == NULL ) { hRes = HRESULT_FROM_WIN32( 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 ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == hRes ) { if ( (pbOutBuffer = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) == NULL ) { hRes = HRESULT_FROM_WIN32( 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 ); } }
pIf->Release();
if ( FAILED( hRes ) ) { if ( !fErrDisplayed ) { if ( hRes == HRESULT_FROM_WIN32( ERROR_RESOURCE_DISABLED ) ) { PrintMessage( IRSTASTR_REMOTE_DISABLED, 0, NULL ); } else if ( hRes == HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) ) { PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL ); } else { DisplayErrorMessage( WIN32_FROM_HRESULT( hRes ) ); } }
Status = WIN32_FROM_HRESULT( hRes ); } } else { if ( hRes == HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) ) { PrintMessage( IRSTASTR_ACCESS_DENIED, 0, NULL ); } else { DisplayErrorMessage( WIN32_FROM_HRESULT( hRes ) ); }
Status = WIN32_FROM_HRESULT( hRes ); } if (fCoInitialized) { CoUninitialize(); } }
Exit:
return Status; } #pragma prefast(pop)
|