Handling Windows Cryptographic Services (cryptsvc) dependency - c++

I have a Windows service say test which has a dependency on cryptsvc. In some systems (like windows XP), cryptsvc starts later than my service.
One way to handle this is adding cryptsvc as dependent service in my test service.
But this will delay the start of test service as well.
I tried manually starting of cryptsvc using startservice() as part of my service initialization, something like below:
SERVICE_STATUS Status;
Status.dwCurrentState = SERVICE_START_PENDING;
setservicestatus(hTestService, &Status);
ServiceInit();
Status.dwCurrentState = SERVICE_RUNNING;
setservicestatus(hTestService, &Status);
And
ServiceInit()
{
// launch a worker thread that
// calls startservice() to start cryptsvc.
}
But the call to startservice() seems to block for some time and eventually ends with 1056 error (There is already an instance running).
How can I ensure crypt service starts as early as possible, or how can I start crypt service as part of my service initialization. Note that I don't want to strictly ensure that crypt service comes up before my service gets up, but crypt service should be up as soon as possible.

Related

Extend the time the Windows service is stopped

I need the service to stop long enough. Approximately 5-10 minutes. Now on windows 10, my service system kills after 60 seconds without waiting for it to finish correctly. Saw a similar issue for C# using the net function RequestAdditionalTime. But I need a C++ implementation on the API.
setting the key value in the registry did not affect
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillService set to 300000
You should not mess with global registry settings.
When stopping your service please call SetServiceStatus with SERVICE_STOP_PENDING and set dwCheckPoint and dwWaitHint to a proper value. And according to the documentation for dwWaitHint call ServServiceStatus multiple times until you are done and the service is stopped (SetServiceStatus(h, SERVICE_STOPPED, ...)).

Stop C++ Service Application

I created a C++ Service Application and installed the service when I try to stop the service a warning is shown.
The Service contains just one implemented method that is:
void __fastcall TService1::ServiceExecute(TService *Sender)
{
bool a = true;
while(a){
sleep(5);
writeLog("test \n");
}
}
How can I stop the service by brute force, so does not show the warning?
The correct way to stop a service program is to implement a Service Control Handler Function, which can respond to the SERVICE_CONTROL_STOP control code. Usually the handler will set a stop event, which will cause the ServiceMain loop to exit (example here).
If you used a template to generate your service application, you may already have the stub interfaces implemented to do this. If not, you would need to implement them.
Implementing a native Windows Service is not trivial, and cannot be done with just a single executable method. A service application must implement the interfaces used by the Service Control Manager (SCM), such as the Service Entry Point, Service ServiceMain Function, and a Service Control Handler Function. It must also report status and state changes to the SCM. See a complete examples from Microsoft here and here.
MSDN reading reference: Service Programs
If you don't want to implement all of the required SCM interfaces and logic, there are options available from both Microsoft and third parties to run any executable as a service. See Microsoft's srvany.exe method, or Iain Patterson's NSSM for example.

Cross-platform notification that a service is running

I am looking for a cross platform method of notifying several client applications that a service/daemon has started and is able to handle incoming connections. The clients will be running all the time, whereas the service may not. Normally the service/daemon will be started automatically when the computer starts, but in some cases it may not and in those cases the clients should automatically connect when the service/daemon starts.
The basic flow of the client is to wait until they notice that the service is running, then connect. If the connection is interrupted or if they were unable to connect they just try again from the beginning.
For Windows I have a solution where the service signals a global event object when it starts so that the clients can wait on this event. This works ok in reality, but I am pretty sure that it does not handle all potential cases (such as a crashing service or multiple instances of the service running). I don't mind if the clients "accidentally" wake up every now and then even though the service isn't running. I just want to avoid that the clients enter a busy loop trying to connect all the time, while at the same time respond pretty quickly to the service starting. I.e. just adding a sleep between connection attempts is not great.
Is there a cross platform method to detect whether the service is running and ready to accept connections?
Update: I'll add a bit more information on how the current mechanism works on Windows using approximate code from memory, so please excuse any typos:
Service:
SECURITY_ATTRIBUTES sa;
// Set up empty SECURITY_ATTRIBUTES so that everyone has access
// ...
// Create a manual reset event, initially set to nonsignaled
HANDLE event = ::CreateEvent(&sa, TRUE, FALSE, "Global\\unique_name");
// Signal the event - service is running and ready
::SetEvent(event);
// Handle connections, do work
// If the service dies for whatever reason, Windows deletes the event handle
// The event is deleted when the last open handle to it is closed
// So the event is signaled for at least as long as the service lives
Clients:
while (true) {
// Set up event the same way as the service, including empty security attributes
// ...
HANDLE event = ::CreateEvent(&sa, TRUE, FALSE, "Global\\unique_name");
// Wait for the service to start
DWORD ret = ::WaitForSingleObject(event, INFINITE);
// Close the handle to avoid keeping the event object alive
// This isn´t enough in theory, but works in real usage as the number of clients
// will always be low
::CloseHandle(event);
// Check if we woke up because the event is signaled
if (WAIT_OBJECT_0 == ret) {
// connect to service, do work
// ...
}
}
How could I achieve approximately the same on OS X and Linux?

Correct way to register for pre-shutdown notification from C++

I write a local service application using C++ and I can't find the correct way of registering for a pre-shut-down notification (for OS later than Windows XP). I believe that SERVICE_CONTROL_PRESHUTDOWN notification has been added since Vista, but when you call SetServiceStatus do we need to specify:
dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PRESHUTDOWN;
or
dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PRESHUTDOWN;
You cannot accept both a shutdown and a preshutdown if your service is correctly coded. The documentation explicitly states this.
From http://msdn.microsoft.com/en-us/library/windows/desktop/ms683241(v=vs.85).aspx:
Referring to SERVICE_CONTROL_PRESHUTDOWN:
A service that handles this notification blocks system shutdown until the service stops or the preshutdown time-out interval specified through SERVICE_PRESHUTDOWN_INFO expires.
In the same page, the section about SERVICE_CONTROL_SHUTDOWN adds:
Note that services that register for SERVICE_CONTROL_PRESHUTDOWN notifications cannot receive this notification because they have already stopped.
So, the correct way is to set the dwControlsAccepted to include either SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PRESHUTDOWN, depending on your needs, but not to both at the same time.
But do note that you probably want to accept more controls. You should always allow at least SERVICE_CONTROL_INTERROGATE, and almost certainly allow SERVICE_CONTROL_STOP, since without the latter the service cannot be stopped (e.g. in order to uninstall the software) and the process will have to be forcibly terminated (i.e. killed).
As noted by the commenters above, you will need to choose from either SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PRESHUTDOWN (Vista or later). If you are using SERVICE_ACCEPT_PRESHUTDOWN, you will need to register your service with the SCM using RegisterServiceCtrlHandlerEx instead of RegisterServiceCtrlHandler else you will not be receiving the pre-shutdown notifications. The handler prototype also changes from Handler to HandlerEx.
Another point to note is that handling pure shutdown events is limited to 5 seconds in Windows Server 2012 (and presumably Windows 8), 12 seconds in Windows 7 and Windows Server 2008, 20 seconds in Windows XP before your service is killed while stopping. This is the reason why you may need the pre-shutdown notification. You may want to change this at \\HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout.
In the comment from alexpi there is a key piece of information. I found that the service handling PRESHUTDOWN needs to update the service status with a new checkpoint number (repeatedly) before WaitToKillServiceTimeout has elapsed. My server was configured to 5000 ms and my service only updated every 12000 ms, and the server went into the SHUTDOWN phase, which caused my attempt to stop another service to return the error that the shutdown was in progress.
These two notifications seem to be different as I get it from the documentation. If what you need is really to enable your service to recieve preshutdown notification, you should go with: dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PRESHUTDOWN; But if you also want to enable your service to receive shutdown notifications, you should go with your second option.

Stopping Windows service asynchronously

I am trying to control a service within an application. Starting the service via StartService (MSDN) works fine, the service needs about 10 seconds to start, but after calling StartService it gives the control back to the main-application immediately.
However, when stopping the service via ControlService (MSDN) - AFAIK there is no StopService - it blocks the main-application for the complete time until the service is stopped, which takes about 10 seconds.
Start: StartServiceW( handle, 0, NULL)
Stop: ControlService( handle, SERVICE_CONTROL_STOP, status )
Is there a way for a non-blocking / asynchronously stopping of a windows service?
I would probably look at stopping the service in a new thread. That will eliminate the blocking of your main thread.
The SCM processes control requests in a serialized manner. If any service is busy processing a control request, ControlService() will be blocked until the SCM can process the new request. This is stated as much in the documentation:
The SCM processes service control notifications in a serial fashion—it
will wait for one service to complete processing a service control
notification before sending the next one. Because of this, a call to
ControlService will block for 30 seconds if any service is busy
handling a control code. If the busy service still has not returned
from its handler function when the timeout expires, ControlService
fails with ERROR_SERVICE_REQUEST_TIMEOUT.
The service is doing its cleanup in its control handler routine. That's OK for a service that will only take a fraction of a second to exit, but a service that's going to take ten seconds should definitely be setting a status of STOP_PENDING and then cleaning up asynchronously.
If this is your own service, you should correct that problem. I'd start by making sure that all of the cleanup is really necessary; for example, there's no need to free memory before stopping (unless the service is sharing a process with other services). If the cleanup really can't be made fast enough, launch a separate thread (or signal your main thread) to perform the service shutdown and set the service status to STOP_PENDING.
If this is someone else's service, the only solution is to issue the stop request from a separate thread or in a subprocess.