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]