blob: ba4ab2aebc0a81939d1f6f602a89ed32913035eb [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/chrome_cleaner/test/test_scoped_service_handle.h"
#include <windows.h>
#include "base/base_paths.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/strings/string16.h"
#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
#include "chrome/chrome_cleaner/test/test_executables.h"
#include "chrome/chrome_cleaner/test/test_strings.h"
namespace chrome_cleaner {
TestScopedServiceHandle::~TestScopedServiceHandle() {
StopAndDelete();
}
bool TestScopedServiceHandle::InstallService() {
// Construct the full-path of the test service.
base::FilePath module_path;
if (!base::PathService::Get(base::DIR_EXE, &module_path)) {
PLOG(ERROR) << "Cannot retrieve module name.";
return false;
}
module_path = module_path.Append(kTestServiceExecutableName);
return InstallCustomService(kServiceName, module_path);
}
bool TestScopedServiceHandle::InstallCustomService(
const base::string16& service_name,
const base::FilePath& module_path) {
DCHECK(!service_name.empty());
DCHECK(!service_manager_.IsValid());
DCHECK(!service_.IsValid());
DCHECK(service_name_.empty());
// Make sure a service with this name doesn't already exist.
StopAndDeleteService(service_name);
// Get a handle to the service manager.
service_manager_.Set(
::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS));
if (!service_manager_.IsValid()) {
PLOG(ERROR) << "Cannot open service manager.";
return false;
}
const base::string16 service_desc =
base::StrCat({service_name, L" - ", kServiceDescription});
service_.Set(::CreateServiceW(
service_manager_.Get(), service_name.c_str(), service_desc.c_str(),
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL, module_path.value().c_str(), nullptr, nullptr,
nullptr, nullptr, nullptr));
if (!service_.IsValid()) {
// Unable to create the service.
PLOG(ERROR) << "Cannot create service '" << service_name << "'.";
return false;
}
service_name_ = service_name;
return true;
}
bool TestScopedServiceHandle::StartService() {
if (!::StartService(service_.Get(), 0, nullptr))
return false;
SERVICE_STATUS service_status = {};
for (int iteration = 0; iteration < kServiceQueryRetry; ++iteration) {
if (!::QueryServiceStatus(service_.Get(), &service_status))
return false;
if (service_status.dwCurrentState == SERVICE_RUNNING)
return true;
::Sleep(kServiceQueryWaitTimeMs);
}
return false;
}
bool TestScopedServiceHandle::StopAndDelete() {
Close();
if (service_name_.empty())
return false;
bool result = StopAndDeleteService(service_name_.c_str());
service_name_.clear();
return result;
}
void TestScopedServiceHandle::Close() {
service_.Close();
service_manager_.Close();
}
bool TestScopedServiceHandle::StopAndDeleteService(
const base::string16& service_name) {
return StopService(service_name.c_str()) &&
DeleteService(service_name.c_str()) &&
WaitForServiceDeleted(service_name.c_str());
}
} // namespace chrome_cleaner