advapi32/service.c; patch 3/7: Introduced service thread.

Alexander Yaworsky yaworsky at migusoft.ru
Thu Nov 11 21:33:37 CST 2004


Hello,

do not confuse with service thread that was removed from wine long ago ;)
According to M$ ideas, the main thread is running inside StartServiceCtrlDispatcher
accepting control requests and calling ControlHandler; while the ServiceMain
is doing its work in a separate thread.

ChangeLog:

Introduced service thread.

diff -urN out1/dlls/advapi32/service.c out2/dlls/advapi32/service.c
--- out1/dlls/advapi32/service.c	2004-11-11 21:25:40.000000000 +0600
+++ out2/dlls/advapi32/service.c	2004-11-11 21:52:56.000000000 +0600
@@ -309,21 +309,43 @@
  }

  /******************************************************************************
+ * service thread
+ */
+struct service_thread_data
+{
+    WCHAR service_name[ MAX_SERVICE_NAME ];
+    CHAR service_nameA[ MAX_SERVICE_NAME ];
+    LPSERVICE_MAIN_FUNCTIONW service_main;
+    DWORD argc;
+    LPWSTR *argv;
+};
+
+static DWORD WINAPI service_thread( LPVOID arg )
+{
+    struct service_thread_data *data = arg;
+
+    data->service_main( data->argc, data->argv );
+    return 0;
+}
+
+/******************************************************************************
   * service_ctrl_dispatcher
   *
   * helper function for StartServiceCtrlDispatcherA/W
   */
  static BOOL service_ctrl_dispatcher( LPSERVICE_TABLE_ENTRYW servent, BOOL ascii )
  {
-    WCHAR service_name[ MAX_SERVICE_NAME ];
      HANDLE hServiceShmem = NULL;
      struct SEB *seb = NULL;
-    DWORD  dwNumServiceArgs;
-    LPWSTR *lpArgVecW = NULL;
+    struct service_thread_data *thread_data;
      unsigned int i;
-    BOOL ret = FALSE;
+    HANDLE thread;

-    if( ! read_scm_lock_data( service_name ) )
+    thread_data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct service_thread_data) );
+    if( NULL == thread_data )
+        return FALSE;
+
+    if( ! read_scm_lock_data( thread_data->service_name ) )
      {
          /* FIXME: Instead of exiting we allow
             service to be executed as ordinary program.
@@ -332,44 +354,65 @@
           */
          FIXME("should fail with ERROR_FAILED_SERVICE_CONTROLLER_CONNECT\n");
          servent->lpServiceProc( 0, NULL );
+        HeapFree( GetProcessHeap(), 0, thread_data );
          return TRUE;
      }

-    seb = open_seb_shmem( service_name, &hServiceShmem );
+    seb = open_seb_shmem( thread_data->service_name, &hServiceShmem );
      if( NULL == seb )
-        return FALSE;
+        goto error;

-    lpArgVecW = build_arg_vectors( seb );
-    if( NULL == lpArgVecW )
-        goto done;
+    thread_data->argv = build_arg_vectors( seb );
+    if( NULL == thread_data->argv )
+        goto error;

-    lpArgVecW[0] = service_name;
-    dwNumServiceArgs = seb->argc + 1;
+    thread_data->argv[0] = thread_data->service_name;
+    thread_data->argc = seb->argc + 1;

      if( ascii )
-        /* Convert the Unicode arg vectors back to ASCII */
-        for(i=0; i<dwNumServiceArgs; i++)
+    {
+        /* Convert the Unicode arg vectors back to ASCII;
+         * but we'll need unicode service name (argv[0]) for object names */
+        WideCharToMultiByte( CP_ACP, 0, thread_data->argv[0], -1,
+                             thread_data->service_nameA, MAX_SERVICE_NAME, NULL, NULL );
+        thread_data->argv[0] = (LPWSTR) thread_data->service_nameA;
+
+        for(i=1; i<thread_data->argc; i++)
          {
-            LPWSTR src = lpArgVecW[i];
+            LPWSTR src = thread_data->argv[i];
              int len = WideCharToMultiByte( CP_ACP, 0, src, -1, NULL, 0, NULL, NULL );
              LPSTR dest = HeapAlloc( GetProcessHeap(), 0, len );
              if( NULL == dest )
-                goto done;
+                goto error;
              WideCharToMultiByte( CP_ACP, 0, src, -1, dest, len, NULL, NULL );
              /* copy converted string back  */
              memcpy( src, dest, len );
              HeapFree( GetProcessHeap(), 0, dest );
          }
+    }

-    /* try to start the service */
-    servent->lpServiceProc( dwNumServiceArgs, lpArgVecW);
-    ret = TRUE;
+    /* start the service thread */
+    thread_data->service_main = servent->lpServiceProc;
+    thread = CreateThread( NULL, 0, service_thread, thread_data, 0, NULL );
+    if( NULL == thread )
+        goto error;

-done:
-    if( lpArgVecW ) HeapFree( GetProcessHeap(), 0, lpArgVecW );
+    /* FIXME: dispatch control requests */
+    WaitForSingleObject( thread, INFINITE );
+    CloseHandle( thread );
+
+    HeapFree( GetProcessHeap(), 0, thread_data->argv );
+    HeapFree( GetProcessHeap(), 0, thread_data );
+    UnmapViewOfFile( seb );
+    CloseHandle( hServiceShmem );
+    return TRUE;
+
+error:
+    if( thread_data->argv ) HeapFree( GetProcessHeap(), 0, thread_data->argv );
      if( seb ) UnmapViewOfFile( seb );
      if( hServiceShmem ) CloseHandle( hServiceShmem );
-    return ret;
+    HeapFree( GetProcessHeap(), 0, thread_data );
+    return FALSE;
  }

  /******************************************************************************




More information about the wine-patches mailing list