Debugging a service not being able to load?
So you have a DLL that you've written for services.exe and it's not loading? The list below deal with some of the most common problems and some mechanisms of getting more information should you have to post your request to a newsgroup or customer support.
In the article below I'm going to assume familiarity with services.exe. There is docs for it on MSDN as well as a white paper that I wrote with more background.
** COMMON MISTAKES **
* Your service DLL needs to be signed
On Windows Mobile 5 devices (and future generation too most likely), your service DLL needs to be signed. The type of certificate varies depending on your device manufacturer and whether you're targeting a smart phone or a PocketPC. Scott Yost has some info about working around the signing problem on PocketPCs + one-tier security model smartphones here. The ideal solution though is that you get your service signed with a real cert.
* Your service DLL doesn't export the correct functions
Services in CE 5.0/Windows Mobile MUST export xxx_Init(), xxx_Deinit, and xxx_IOControl functions regardless of whether they actually do any special processing in them. Note that they must be explicitly listed in the .def file -- just including them in your DLL isn't enough.
* Reg / DLL misconfiguration
Make sure that you have specified all the required registry entries in HKLM\Services\<YourServiceName>. To give a sense of what this could look like, the FTP server's service entry consists of
[HKEY_LOCAL_MACHINE\Services\FTPD]
"FriendlyName"="FTP"
"Dll"="FTPD.Dll"
"Order"=dword:9
"Keep"=dword:1
"Prefix"="FTP"
"Index"=dword:0
Also it sounds silly, but make sure that you're building the DLL for the right platform, you're not trying to run a CE DLL compiled for WinCE 5.0 on a CE 3.0 device (older OS's can't load DLLs compiled for newer ones).
* Misuse of "Context" registry setting
You're setting the "Context" DWORD but don't really know what it means
Some people have copied the Web Server (HTTPD) registry settings and included in this is a "mysterious" "Context" DWORD.
[HKEY_LOCAL_MACHINE\Services\HTTPD]
"Context"=dword:1
Note that this has a very specific meaning - namely that the web server is going to be run as a super-service. It also means that the web server MUST implement a bunch of IOCTLs in order to be a legal super-service and you can get into problems if you don't implement those IOCTLs.
If you don't have any idea what a super-service is, you don't want to be it or claim to be. So make sure you do not have a "Context" REG_DWORD at all or set it to 0.
* You're calling into an API that's not ready yet
Recall your service will be started quite early at boottime. It's possible you're calling into some subsystem that's not entirely initialized, such as a filesystem driver on a filesys that's not up yet or some display routine. Normally you'll get a nice runtime error, but there maybe cases where the execution thread will crash. Services.exe has a __try/__except block around all calls to services (since I don't entirely trust you guys :)) so it'll catch this, but it'll also unload your service if it happens during xxx_Init().
* xxx_Init() / DllMain() return codes
Your xxx_Init() and DllMain() both need to return non-zero return codes and also (obviously) not crash. If DllMain() returns FALSE, LoadLibrary on it will fail. If xxx_Init() returns 0, services.exe will assume you don't want the service loaded after all and unload it.
** DEBUGGING TIPS **
If none of the above seem to be your problem, then you'll need to debug some before you ask for help. A lot of times the act of debugging reveals the problem. Here's some ideas.
* DEBUGMSG's
If you're an OEM using Platform Builder, you have a wonderful kernel debugger at your disposal as well as the debug version of services.exe that you can drop into your image (or you can build a full debug image). Services.exe isn't that verbose with Debug output logging by default, but it can be configured to be very verbose via PB. A lot of times services.exe will tell you exactly why it's unhappy with your service and not loading.
* Shared Source
Again only for Platform Builder customers. Services.exe is shared source, so if push comes to shove you can install it and actually step through the code to see what's happening in it. Hopefully the DEBUGMSG's should get you all the way home, though.
* Debugging on non-Platform Builder
I believe using Embedded Visual Tools / Visual Studio with PPC connection, it's possible to actually debug through a service. You'd just need to attach to the services.exe process and put in appropriate break points. (I use the kernel debugger so I don't have a better sense of how to make this happen.) The key here though is that it's possible to actually debug a service at startup even using a non-kernel debugger. The kernel debugger (i.e. PB) is however required for debugging device drivers.
* ActivateService / "services load"
There's an API named ActivateService() that will cause services.exe to load your service through nearly the identical code path that your service is loaded by at boot-time. This is nice first of all because if you service isn't loading, it means you don't have to constantly recompile your service DLL and then reboot. You can just right a small app to keep loading it.
Or you can just call "services load MYSERVICE" which will do the same thing. This will also print out a Win32 error code which may (or may not) be helpful in tracking down the problem.
* Strip your service down to the essentials
To make sure you're not making any illegal function calls too early at boot time or your service itself isn't crashing, then remove all code except the actual services.exe exports and see if that's successful.
* Looking at the exports
There are various tools for verifying your service is exporting the functions you think it should be. 'link /dump /exports myservice.dll' or dumpbin, for instance. Also make sure the prefix of the service (the xxx portion) matches up to the three letter prefix you've specified in the registry. So in the FTPD example above, you need FTP_Init() -- HTP_Init won't work. Some people hit this issue when taking existing templates and not being careful.
* Manually loading your service DLL / exports
When all else fails, write an app to actually call LoadLibrary() on your service DLL. This can tell if it loaded or no and if it failed, give better error codes if something is wrong. Next, try doing GetProcAddress() on your xxx_Init() and calling it and seeing if that helps.
--
If none of this helps and you go out to a newsgroup, please indicate in your post you've done your due diligence on these steps because the first thing I'm going to do is point you back here for info.
[Author: John Spaith]
Comments
- Anonymous
April 03, 2006
Just clearify one thing about service loading, all 3rd party DLLs referenced by the service dll have to be signed too. It did take me some time to figure it out when developing our own service module. - Anonymous
April 19, 2006
Hi,
excellent article, it could be useful.
BTW, do you have the same kind of article for driver debugging. - Anonymous
May 10, 2006
Sorry for delay Edouard, the blog wasn't autonotifying me of posts like I wanted it to.
I don't know of any article for device driver debugging -- MSDN is the only place I can think of. However, device drivers and services are very very similiar (by design) so most of what I wrote above should be helpful as a how to get my driver loaded guide (the "Context" is way different on services+device.exe however and I don't know if device.exe is shared source or no).
John Spaith - Anonymous
November 09, 2006
HiIs anybody aware of a simple step by step approach to get HTTPD runing on Pocket PC's???There is a lot of chances in it. - and it can't get it going - Maybe a commandline for service.exe?BRDaniel - Anonymous
November 15, 2006
The comment has been removed - Anonymous
July 02, 2007
Bless your heart.I diligently followed the finger service example, which was apparently my first mistake.Many, many thanks for this article -- too bad I didn't find it before I spent 6 hours trying to get my service to stay loaded.Signed,Another "Context" victim - Anonymous
September 04, 2007
The comment has been removed - Anonymous
September 05, 2007
The comment has been removed - Anonymous
September 20, 2007
Pavel - 1st apologies in my slacking on checking the feedback. Happy the advice worked with starting. As far as HTP0: always starting, it's very odd because it should be loaded by default. Have you checked out "services list" to make sure it's running?Probably a better forum for this would be a newsgroup on http://blogs.msdn.com/cenet/archive/2005/12/05/500181.aspx, which we're better at checking.John - Anonymous
September 20, 2007
Ananda - it'd be helpful to know the error code LoadLibrary() returned. Also due to my long delays, like I did with Pavel I'm going to point you to newsgroups on http://blogs.msdn.com/cenet/archive/2005/12/05/500181.aspx as probably a better place to get helpJohn - Anonymous
April 25, 2008
Signing is mentioned as one of things we would miss for deployment.I got more confused in that as even though I had not signed the DLL, I was still able to load it in services.exe by calling ActivateService. Still the DLL never loaded on boot.After I signed the DLL it started to load on boot also. - Anonymous
April 28, 2008
Faizan - I think what's happening is that on boot Services.exe wants to LoadLibrary() your DLL, it's not signed, it asks the UI manager to pop a window asking for permission of user to load. But UI manager isn't ready yet since it's so early in boot, so the default answer is "not allowed to load." Doing the ActivateService() once device has booted saves you from this problem since UI mgr is up. So to have service loaded at boot it does need to be signed.John