Avoid the Windows CE ServiceIoControl API


The ServiceIoControl API on Windows CE should be avoided.  The way it works (not that you'll use it now that I've warned you, right :)) is that an application that wants to access a service running in services.exe use this API.  The app passes in an IOCTL code as well as input and output buffers.  In short it's like a DeviceIoControl for services.


What's the problem?  Well, DeviceIoControl on Windows CE works for services already.  So reason number one that ServiceIoControl should be avoided is that DeviceIoControl already does the same thing.  Furthermore, if your service DLL moves to device.exe (it does happen sometimes) then the app calling ServiceIoControl would no longer work.  If it had used DeviceIoControl, then the kernel automagically figures out whether to call device.exe or services.exe.  The gory details of how the kernel does this are described here for the curious.


Another, bigger problem with ServiceIoControl is that the way the service itself is called is different.  When you call DeviceIoControl, you first must call CreateFile on the service.  This causes the service's xxx_Open() to be called.  When you close the service handle via CloseHandle, the service's xxx_Close is called.  ServiceIoControl does not operate on file handles but instead on the service handle (as returned by GetServiceHandle() API for instance), meaning that the service open/close functions don't get called.  This may or may not be a problem, depending on the particular service.


The *very* curious may be wondering why Microsoft added this in the first place.  (And by Microsoft of course I mean John Spaith.)  We (I) wrote services.exe for CE 4.0.  We had the dream of being able to do a beta of services.exe for CE 3.0 devices - in particular for the PocketPC 2000 and even the Palmsized PC, back when we called it that.  We'd had a lot of luck with our web server beta for PocketPCs since it got so many people from the community playing with it and giving us really good feedback.


To make CreateFile know how to talk to services.exe, it required modifying the filesystem.  This was not an option given we wanted to ship services.exe as just a regular app and not require a new ROM image to replace filesys.exe on existing PPC devices.  So that meant no CreateFile and no DeviceIoControl, which meant that we had to do GetServiceHandle/ServiceIoControl to get similar functionality.  The really bad part here is that we never did this beta in the first place.  Ugh.


In conclusion: Don't use ServiceIoControl!



[Author: An older and wiser John Spaith]

Comments (2)
  1. Ravi Prakash says:

    Hi,

    I am working on Windows Mobile 6, and CreateFile doesn’t seem to call xxx_Open().

    Here’s my code:

    DWORD GPD_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)

    {

    MessageBox(NULL, L"Inside Open", NULL, MB_OK);
    
    return TRUE;
    

    }

    HANDLE gpd = CreateFile(L"GPD0:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);

    In fact, CreateFile is passing even if the service is not running. Its happy to pass as long as there is a registry entry for the service.

    Sad thing is, the deprecated GetServiceHandle and then ServiceIoControl are working perfectly fine. Could you please point me out to what might be the issue?

  2. ravpra says:

    Hi again.

    CreateFile’s working for me now, though I don’t understand why. Except I changed the Index value in my registry from 0 to 1. CreateFile(L"GPD0:"…) still passed but now so did CreateFile(L"GPD1:"….) and popped open the beloved "Inside Open" messagebox. Funny huh?? Probably something wrong with my code. Can you verify that John?

Comments are closed.

Skip to main content