Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Service_GetStatus call - addressed issues mentioned in the previous request #8

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 1.5 (Next Release)

* **Features**:
* Added `Service_GetStatus` - (https://github.com/dblock/msiext/pull/8)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still missing a period :)

* **Bugs**:
* **Misc**:
* [#5] (https://github.com/dblock/msiext/pull/5) - Fixed WiX UI extension screens: texts, icons, margins, spacing - [@romanws](https://github.com/romanws).
Expand Down
21 changes: 21 additions & 0 deletions src/Common/Service/ServiceInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,27 @@ DWORD ServiceInstance::GetServiceState() const
return status.dwCurrentState;
}

static std::wstring serviceStateToString(DWORD dwCurrentState)
{
const wchar_t* st = L"Unknown";

switch (dwCurrentState) {
case SERVICE_STOPPED: st = L"Stopped"; break;
case SERVICE_START_PENDING: st = L"Starting"; break;
case SERVICE_STOP_PENDING: st = L"Stopping"; break;
case SERVICE_RUNNING: st = L"Running"; break;
case SERVICE_CONTINUE_PENDING: st = L"Resuming"; break;
case SERVICE_PAUSE_PENDING: st = L"Pausing"; break;
case SERVICE_PAUSED: st = L"Paused"; break;
}
return st;
}

std::wstring ServiceInstance::GetServiceStateString()
{
return serviceStateToString( GetServiceState() );
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the implementation in here, don't leave a "naked" static method out there, it doesn't do anything and is not reused.

}

bool ServiceInstance::Wait(DWORD timeout) const
{
DWORD slept = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/Common/Service/ServiceInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ namespace AppSecInc
void Continue();
//! return the service state
DWORD GetServiceState() const;
//! return string presentation of the service state
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string _re_presentation, no?

std::wstring GetServiceStateString();
//! returns true if the service is started
bool IsStarted() const { return (GetServiceState() == SERVICE_RUNNING); }
//! returns true if the service is stopped
Expand Down
10 changes: 10 additions & 0 deletions src/Common/Service/ServiceInstanceUnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ void ServiceInstanceUnitTests::testGetServiceProcessStatus()
CPPUNIT_ASSERT(0 != status.dwProcessId);
}

void ServiceInstanceUnitTests::testGetServiceStateString()
{
ServiceManager scm;
scm.Open();
ServiceInstance instance;
instance.Open(scm, L"W32Time");
std::wstring state = instance.GetServiceStateString();
CPPUNIT_ASSERT( L"Running" == state );
}

void ServiceInstanceUnitTests::testControl()
{
ServiceManager scm;
Expand Down
2 changes: 2 additions & 0 deletions src/Common/Service/ServiceInstanceUnitTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace AppSecInc
CPPUNIT_TEST( testCreateDelete );
CPPUNIT_TEST( testOpenClose );
CPPUNIT_TEST( testGetServiceProcessStatus );
CPPUNIT_TEST( testGetServiceStateString );
CPPUNIT_TEST( testControl );
CPPUNIT_TEST( testGetConfig );
CPPUNIT_TEST( testGetDescription );
Expand All @@ -23,6 +24,7 @@ namespace AppSecInc
void testOpenClose();
void testControl();
void testGetServiceProcessStatus();
void testGetServiceStateString();
void testGetConfig();
void testGetDescription();
};
Expand Down
24 changes: 24 additions & 0 deletions src/CustomActions/SystemTools/ServiceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,27 @@ CA_API UINT __stdcall Service_Exists(MSIHANDLE hInstall)
MSI_EXCEPTION_HANDLER_EPILOG;
return ERROR_SUCCESS;
}


CA_API UINT __stdcall Service_GetStatus(MSIHANDLE hInstall)
{
MSI_EXCEPTION_HANDLER_PROLOG;
MsiInstall msiInstall(hInstall);

std::wstring service_name = msiInstall.GetProperty(L"SERVICE_STATUS_SERVICE_NAME");
if (service_name.empty()) {
service_name = msiInstall.GetProperty(L"SERVICE_NAME");
}

AppSecInc::Service::ServiceManager scm;
scm.Open(SC_MANAGER_CONNECT|STANDARD_RIGHTS_READ);
AppSecInc::Service::ServiceInstance service;
service.Open( scm, service_name );
std::wstring state = service.GetServiceStateString();

msiInstall.SetProperty(L"SERVICE_STATUS", state);

MSI_EXCEPTION_HANDLER_EPILOG;
return ERROR_SUCCESS;
}

10 changes: 10 additions & 0 deletions src/CustomActions/SystemTools/ServiceImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,13 @@ CA_API UINT __stdcall Service_GetConfig(MSIHANDLE hInstall);
\return SERVICE_EXISTS set to "1" if service exists, "0" otherwise
*/
CA_API UINT __stdcall Service_Exists(MSIHANDLE hInstall);

/*!

\brief Get status of a service
\param SERVICE_STATUS_SERVICE_NAME service name
\param SERVICE_NAME alternative property for service name, used when SERVICE_STATUS_SERVICE_NAME is not set
\return SERVICE_STATUS set to one of: Stopped, Starting, Stopping, Running, Resuming, Pausing, Paused depending on the current service state. Fails if service does not exist; SERVICE_STATUS is unchanged in this case.
*/
CA_API UINT __stdcall Service_GetStatus(MSIHANDLE hInstall);

35 changes: 35 additions & 0 deletions src/CustomActions/SystemTools/ServiceImplUnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void ServiceImplUnitTests::Test_EntryPoints()
CPPUNIT_ASSERT(NULL != GetProcAddress(h, "Service_Delete"));
CPPUNIT_ASSERT(NULL != GetProcAddress(h, "Service_GetConfig"));
CPPUNIT_ASSERT(NULL != GetProcAddress(h, "Service_Exists"));
CPPUNIT_ASSERT(NULL != GetProcAddress(h, "Service_GetStatus"));
::FreeLibrary(h);
}

Expand Down Expand Up @@ -218,3 +219,37 @@ void ServiceImplUnitTests::Test_Service_Exists()
CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"SystemTools.dll", L"Service_Exists"));
CPPUNIT_ASSERT(L"0" == msiInstall.GetProperty(L"SERVICE_EXISTS"));
}

void ServiceImplUnitTests::Test_Service_GetStatus()
{
AppSecInc::Msi::MsiShim hInstall;
MsiInstall msiInstall(hInstall);

msiInstall.SetProperty(L"SERVICE_STATUS_SERVICE_NAME", L"W32Time");
CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"SystemTools.dll", L"Service_GetStatus"));
CPPUNIT_ASSERT(L"Running" == msiInstall.GetProperty(L"SERVICE_STATUS"));

msiInstall.SetProperty(L"SERVICE_STATUS_SERVICE_NAME", L"Wecsvc");
CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"SystemTools.dll", L"Service_GetStatus"));
CPPUNIT_ASSERT(L"Stopped" == msiInstall.GetProperty(L"SERVICE_STATUS"));

msiInstall.SetProperty(L"SERVICE_STATUS_SERVICE_NAME", AppSecInc::Com::GenerateGUIDStringW());
CPPUNIT_ASSERT(ERROR_SUCCESS != hInstall.ExecuteCA(L"SystemTools.dll", L"Service_GetStatus"));
// SERVICE_STATUS should remain unchanged
CPPUNIT_ASSERT(L"Stopped" == msiInstall.GetProperty(L"SERVICE_STATUS"));
}

void ServiceImplUnitTests::Test_Service_GetStatus_Accepts_SERVICE_NAME()
{
AppSecInc::Msi::MsiShim hInstall;
MsiInstall msiInstall(hInstall);

msiInstall.SetProperty(L"SERVICE_NAME", L"W32Time");
CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"SystemTools.dll", L"Service_GetStatus"));
CPPUNIT_ASSERT(L"Running" == msiInstall.GetProperty(L"SERVICE_STATUS"));

// more specific name should override generic one:
msiInstall.SetProperty(L"SERVICE_STATUS_SERVICE_NAME", L"Wecsvc");
CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"SystemTools.dll", L"Service_GetStatus"));
CPPUNIT_ASSERT(L"Stopped" == msiInstall.GetProperty(L"SERVICE_STATUS"));
}
4 changes: 4 additions & 0 deletions src/CustomActions/SystemTools/ServiceImplUnitTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ namespace AppSecInc
CPPUNIT_TEST( Test_Service_Delete );
CPPUNIT_TEST( Test_Service_GetConfig );
CPPUNIT_TEST( Test_Service_Exists );
CPPUNIT_TEST( Test_Service_GetStatus );
CPPUNIT_TEST( Test_Service_GetStatus_Accepts_SERVICE_NAME );
CPPUNIT_TEST_SUITE_END();
private:
std::wstring service_name;
Expand All @@ -33,6 +35,8 @@ namespace AppSecInc
void Test_Service_Control();
void Test_Service_GetConfig();
void Test_Service_Exists();
void Test_Service_GetStatus();
void Test_Service_GetStatus_Accepts_SERVICE_NAME();
};
}
}
Expand Down
1 change: 1 addition & 0 deletions src/CustomActions/SystemTools/SystemTools.def
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ EXPORTS
Service_ChangeDescription
Service_GetConfig
Service_Exists
Service_GetStatus
TemplateFiles_Immediate
TemplateFiles_Deferred
Registry_CopyBranch
Expand Down