Example #1
0
int ServiceCommand::executeCommand(SC_HANDLE scm) {
  LOG.LogDebugFormat(L"Opening %s with %s rights...", mySettings->getServiceName(), (CString)mySCRight);

  SC_HANDLE svc = OpenService(scm, mySettings->getServiceName(), mySCRight);

  if (svc == NULL) {
    DWORD err = GetLastError();
    CString msg = CreateFormatted(L"Failed to open service %s.", mySettings->getServiceName());
    switch(err) {
    case ERROR_ACCESS_DENIED:
      LOG.LogWarnFormat(L"%s Access denied", msg);
      return 1;
    
    case ERROR_INVALID_NAME:
      LOG.LogWarnFormat(L"%s Invalid service name", msg);
      return 1;

    case ERROR_SERVICE_DOES_NOT_EXIST:
      LOG.LogWarnFormat(L"%s Service does not exist", msg);
      return 1;
      break;
    case ERROR_INVALID_HANDLE:
    default:
      LOG.LogWarnFormat(L"%s. %s", msg, LOG.GetErrorText(err));
      return 1;
      break;
    }
  }

  int ret = executeCommand(scm, svc);

  CloseServiceHandle(svc);
  return ret;
}
void CreateServiceCommand::updateServiceDescription() {
  //Another possbile approach is to call ChangeServiceConfig2 
  //that is only supported from WinXP/2003
  LOG.LogDebug(L"Updating service description");

  CString path = CreateFormatted(L"SYSTEM\\CurrentControlSet\\Services\\%s", mySettings->getServiceName());
  CRegKey reg(HKEY_LOCAL_MACHINE);
  if (ERROR_SUCCESS != reg.Open(reg, path, KEY_WRITE)) {
    LOG.LogWarnFormat(L"Failed to open registry key %s", path);
    return;
  }

  CString key = L"Description";
  if (ERROR_SUCCESS != reg.SetStringValue(key, mySettings->getServiceDescription())) {
    LOG.LogWarnFormat(L"Failed to set %s for %s", key, path);
    return;
  }

  reg.Flush();
  LOG.LogDebug(L"Service description is updated");
}
void ProcessInterruptTerminateHandler::InterruptProcess(PROCESS_INFORMATION& info) {
  //block from second call
  if (IsInterrupted()) return;
  

  LOG.LogInfo(L"Service process will be killed, exit code would be 42");
  //TODO:implement kill process
  if (0 == TerminateProcess(info.hProcess, 42)) {
    LOG.LogWarnFormat(L"Failed to terminate service process. %s", LOG.GetLastError());
    return;
  }

  //mark interrupt to the process was sent
  Interrupt();
}
int CreateServiceCommand::executeCommand(SC_HANDLE scm) {
  LOG.LogDebugFormat(L"Creating and registering service: name=%s...", mySettings->getServiceName());
  
  CString sUserName = CreateFormatted(L"%s\\%s", mySettings->getDomain(), mySettings->getUserName());
  CString sPassword = mySettings->getPassword();

  LPCWSTR userName = NULL;
  LPCWSTR password = NULL;

  if (!mySettings->runAsSystem()) {
    //use declared variables to avoid strings from distruct
    userName = sUserName;
    password = sPassword;
    LOG.LogInfoFormat(L"Installing service for user: %s", userName);
  }

  SC_HANDLE service = CreateService(
    scm, //ServiceControlManager instance
    mySettings->getServiceName(),
    mySettings->getServiceDisplayName(),
    SERVICE_ALL_ACCESS, //any option here?
    SERVICE_WIN32_OWN_PROCESS, //Consider to have SERVICE_INTERACTIVE_PROCESS
    mySettings->isAutostart() ? SERVICE_AUTO_START : SERVICE_DEMAND_START, 
    SERVICE_ERROR_NORMAL, 
    mySettings->getServiceExecutable(), //executable command    
    NULL, //Start orger group
    NULL, //tag
    NULL, //dependencies
    userName,
    password
  );

  if (service == NULL) {
    DWORD err = GetLastError();
    CString msg = CreateFormatted(L"Failed to create service %s.", mySettings->getServiceName());
    switch(err) {
    case ERROR_ACCESS_DENIED:
      LOG.LogWarnFormat(L"%s Access denied", msg);
      return 1;
    case ERROR_CIRCULAR_DEPENDENCY:
      LOG.LogWarnFormat(L"%s A circular service dependency was specified", msg);
      return 1;
    case ERROR_DUPLICATE_SERVICE_NAME:
      LOG.LogWarnFormat(L"%s Service display name is already used", msg);
      return 1;
    case ERROR_INVALID_NAME:
      LOG.LogWarnFormat(L"%s The specified service name is invalid", msg);
      return 1;
    case ERROR_INVALID_PARAMETER:
      LOG.LogWarnFormat(L"%s A parameter that was specified is invalid", msg);
      return 1;
    case ERROR_INVALID_SERVICE_ACCOUNT:
      LOG.LogWarnFormat(L"%s Specified account does not exist", msg);
      return 1;
    case ERROR_SERVICE_EXISTS:
      LOG.LogWarnFormat(L"%s The service already exists", msg);
      return 1;
    case ERROR_SERVICE_MARKED_FOR_DELETE:
      LOG.LogWarnFormat(L"%s The service already exists and marked for deletion", msg);
      return 1;
    case ERROR_INVALID_HANDLE:
    default:
      LOG.LogErrorFormat(L"%s %s", msg, LOG.GetLastError());
      return 1;
    }    
  }

  LOG.LogInfoFormat(L"Service '%s' was created", mySettings->getServiceName());
  updateServiceDescription();

  CloseServiceHandle(service);

  return 0;
}