I would like to tear apart the CreateService function call. It takes “only” 13 parameters. Here is some code I just wrote:
svc = CreateService(scm, SERVICE_NAME, SERVICE_NAME, SC_MANAGER_CREATE_SERVICE, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, // for now require manual // starting. SERVICE_ERROR_NORMAL, binPath, // Path to exe. NULL, // load order doesn't matter NULL, // tag order doesn't matter NULL, // no dependencies NULL, // use local system account NULL); // No password needed
The first parameter is a handle to a service control manager which you have to open with another function call that takes only three parameters (that’s reasonable) one of which is a sensible bitflag parameter.
The next 2 parameters are services names and display names. I think these should be the same. Having two makes little sense.
The next parameter specifies what sort of access you want to give the service. I think it would be better if a sensible default were used and a function provided to change the default, maybe ServiceSetAccess().
The next parameter is bit flags specifying what you really want to do. Did you know you can install a kernel driver using CreateService? Sure why not? I mean, who really needs KernelDriverInstall()? That wouldn’t make any sense at all when you can just put a flag in a call that already exists.
The next parameter is the start type. I’m OK with this parameter.
The next parameter is stupid. It specifies what you want the program that starts your program to do if your service errors out. WTF? Why should my service dictate the action of another program? stupid.
The next parameter is a full path to the service executable.
The next THREE parameters can all be NULL or you can specify 14 billion options for dependencies among other services, etc, etc. stupid. Why is this in this function? Why not have ServiceSetDependencies? One of these options is a “Pointer to a double null-terminated array of null-separated names of services or load ordering groups that the system must start before this service.” That’s nice and simple.
The last two parameters are to run the service as a different user. I disagree with providing a password since that means that the system needs to store the password and if the password changes for the user account then the service will not run. In addition this would be better as a different function, maybe ServiceSetUser(). Since a “super user” is starting the services that user ought to have enough privilege to switch to a different user context.
Truly I understand why there are so many crappy programmers out there when you see ridiculous code from a well respected company like Microsoft.
I’m honestly a bit surprised that the win32 API isn’t this: