Hello

In fact, the existing implementation of service subsystem in advapi32 is very poor and 
is sufficient only for very simple services
or test programs. I tried to launch oracle 7 database under wine and that trial has 
been failed. The main problem was inability of
parameter passing. Not only oracle -- most services require that. I did some 
improvements. Although I still cannot start database,
because its launcher, oradim, requires CreateRemoteThread, the listener service works 
well (although, it cannot be fully tested
because no database instance exists, but there is nothing suspicious in trace logs).
I even tried to submit a patch but it was silently ignored. Let me remind about this 
patch --
http://www.winehq.org/hypermail/wine-patches/2004/06/0174.html maybe it will be 
useful. If you have suggestions, I promise to
rewrite it as required ;))

Also, maybe the diagram shown below will be useful.

Thanks.

This simplified diagram shows interaction between three main
components of win32 service subsystem.

Service Control |   Service Control Manager   |   Service Program
    Program     |                             |
----------------+-----------------------------+-----------------------------
                |                             |
 StartService-----> LockServiceDatabase       |
                |   IF OWN_PROCES or          |
                |      (SHARE_PROCESS and Service
                |      Program is not running)|
                |   THEN                      |
                |                             |
                |   CreateProcess===============> ...
                |   wait for call to          |   initialization
                |   StartServiceCtrlDispatcher|   must not be longer
                |   timeout=30s               |   than 30 seconds
                |                             |   ...
                |   if wait timed out then    |   ...
                |   TerminateProcess          |   ...
      failure <---- UnlockServiceDatabase     |   ...
                |                             |   ...
                |   wait satisfied <============= StartServiceCtrlDispatcher
                |                             |
                |   END IF                    |
                |                             |
                |   CreateThread ***************> ServiceMain
                |   (or CreateRemoteThread    |   ...
                |    for SHARE_PROCESS;       |    *
                |    if SHARE_PROCESS then    |    *
                |    find entry in service    |    **********************
                |    table by service name;   |                         *
                |    if OWN_PROCESS then use  |                         *
                |    first entry)             |                         *
      success <---- UnlockServiceDatabase     |                         *
                |                             |                         *
                |   accept control requests   |                         *
                |                             |                         *
 ControlService---> request accepted ===========> ServiceControlHandler *
                |                             |   ...                   *
      status <----- return status <============== SetServiceStatus      *
                |                             |                         *
                |                             |                         *
                |                             |    **********************
                |                             |    *
                |                             |   ...
                |                             |   SetServiceStatus
                |   ExitThread <***************** (STOPPED)
                |   if Service Program has    |
                |   now only one thread       |
                |   return control from       |
                |   StartServiceCtrlDispatcher==> ...
                |                             |   ExitProcess

legend:

--- Service Control Program's thread
=== Service Program's main thread (control thread)
*** Service Program's service thread
OWN_PROCESS == SERVICE_WIN32_OWN_PROCESS
SHARE_PROCESS == SERVICE_WIN32_SHARE_PROCESS


Implementation.

completely win32-based

Two basic things:
a) The only time the service control manager requests ownership of the lock is when it 
is starting a service.
   (C) M$DN;
b) When StartService creates a new service process, it must pass arguments, or at least
   argv[0] - the service name - for ServiceMain across process boundary.

So, use the existence of shared memory object as lock indicator and the content of 
object for
passing service name.

Also we need a wait object for monitoring process startup. The call to 
StartServiceCtrlDispatcher will satisfy
wait condition.

A dedicated shared memory object is used for each service thread. It holds other 
arguments,
control requests and status.

Also we need mutex object for serialization of control requests and two wait objects 
for
serialization of service control program thread and service control handler thread.


Reply via email to