Must my service name have the name of the executable in which it's contained?
It must be psychic debugging week 'round here. I received the following email on an internal mailing list earlier today:
Regarding windows service with ServiceType “SERVICE_WIN32_SHARE_PROCESS”, is there a restriction on the service name such that it can only take the same name as the service executable? I can install a service with share process under different names, but the service cannot be started. If I try to start it manually, it gives the following error, “Error 1083: The executable program that this service is configured to run in does not implement the service.” If I set the service name to be the same as the executable, it will install and start properly.
My psychic response was:
What names are you providing in your service call dispatch table?
In this case, the good news is that the error code mostly gives a reasonable hint as to where to start looking.
Essentially my thought processes were: "Hmm. I wonder where the service controller gets the list of services that are implemented in the process? If I remember correctly, it gets it from the service dispatch table passed into the StartServiceCtrlDispatcher API. Maybe I'll look there..."
That then led me to the SERVICE_TABLE_ENTRY structure passed into StartServiceCtrlDispatcher, which contains an lpServiceName field. Aha, I knew I was close. Then I saw the comment that says that the lpServiceName field is ignored if the service is a SERVICE_WIN32_OWN_PROCESS (which means that many services probably don't even bother setting the field to anything other than the empty string), and I knew I'd figured it out.
I'm not surprised that this caused problems, because it's not at all obvious that this random field in a data structure would change meaning depending on a flag in the service's configuration.
Comments
Anonymous
October 05, 2007
PingBack from http://www.artofbam.com/wordpress/?p=5530Anonymous
October 07, 2007
Well, by definition the service being started in a SERVICE_WIN32_OWN_PROCESS service's process is that service, so I'm not terribly surprised that it doesn't validate it. The history of Windows has been not fully validating all the parameters to functions, generally for speed reasons. However, we're now at a point where the processors are so fast relative to everything else that full validation almost doesn't cost anything. But we can't start validating this in case it breaks services which don't send the right value. Postel was wrong. 'Be liberal in what you accept' is a disaster for computing, particularly in security. I think a better idea would be, 'Be strict in what you accept AND in what you send'.Anonymous
October 08, 2007
Shouldn't the correct response have been, "Why are you writing a service, and do you really need to have it ?"Anonymous
October 08, 2007
Not always. In many cases, services are far more attractive than processes (I can disable services, I can't processes). My objections are with autostart services, not all services.Anonymous
October 08, 2007
Well, if you have a service, it pretty much needs to autostart if you are gonna get any use of it as a limited user (Only MS has services that somehow are started even if you are not admin(MSI,WMI, Media Center has 3 useless services I don't need that it always starts(I don't have a capture card)))Anonymous
October 08, 2007
The comment has been removedAnonymous
October 08, 2007
Don't you know everyone passes NULL for LPSECURITY_ATTRIBUTES? ;) Windows Installer doesn't help by not offering a way to secure a newly created service, and Visual Studio helps even less by not using the native Windows Installer functionality (the .NET Framework ServiceInstaller class is completely redundant).Anonymous
October 08, 2007
Monday, October 08, 2007 6:06 AM by Mike Dimmick > But we can't start validating this in case it breaks services > which don't send the right value. I think you mean "shouldn't" not "can't". For some APIs, MSDN says that some fields are ignored, and those fields used to be ignored, but later Windows versions started checking to see if those fields were zeros, giving errors if those fields weren't zeros. Since developers have already had to learn from this kind of breakage, maybe a bit more wouldn't matter much. Besides, this one is even documented, if I understand correctly.Anonymous
December 18, 2007
The comment has been removed