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 2 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`
Copy link
Owner

Choose a reason for hiding this comment

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

Make this a link to the pull request, with your name, like the other ones below.

* **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
41 changes: 41 additions & 0 deletions src/CustomActions/SystemTools/ServiceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,44 @@ CA_API UINT __stdcall Service_Exists(MSIHANDLE hInstall)
MSI_EXCEPTION_HANDLER_EPILOG;
return ERROR_SUCCESS;
}


static std::wstring serviceStatusString(DWORD dwCurrentState)
Copy link
Owner

Choose a reason for hiding this comment

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

This should be moved into the service implementation itself as std::wstring GetServiceProcessStatusString and should have tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you want it to be moved as-is (i.e. ServiceInstance static function converting int to string), or member function similar to ServiceInstance::GetServiceState, but returning string?

Copy link
Owner

Choose a reason for hiding this comment

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

I don't think it should be static. Member function returning a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

GetServiceStateString() then?

{
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;
}

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 );
SERVICE_STATUS_PROCESS st;
service.GetServiceProcessStatus( &st );

msiInstall.SetProperty(L"SERVICE_STATUS", serviceStatusString(st.dwCurrentState));

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 unchainged
Copy link
Owner

Choose a reason for hiding this comment

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

typo here, 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 );
Copy link
Owner

Choose a reason for hiding this comment

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

nitpick: accepts should be Accepts, to match the rest of the code.

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