Pass arguments to the service program

Alexander Yaworsky yaworsky at migusoft.ru
Fri Sep 17 03:56:43 CDT 2004


Hello

ChangeLog:

Pass arguments to the service program

Index: dlls/advapi32/service.c
===================================================================
RCS file: /home/wine/wine/dlls/advapi32/service.c,v
retrieving revision 1.57
diff -u -r1.57 service.c
--- dlls/advapi32/service.c 16 Sep 2004 20:27:31 -0000 1.57
+++ dlls/advapi32/service.c 17 Sep 2004 08:41:13 -0000
@@ -34,18 +34,32 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 
+#define MAX_SERVICE_NAME 256
+
 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
       'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
       'S','e','r','v','i','c','e','s','\\',0 };
 static const WCHAR  szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
                                    'L','O','C','K',0};
+static const WCHAR  szServiceShmemNameFmtW[] = {'A','D','V','A','P','I','_',
+                                                'S','E','B','_','%','s',0};
+
+struct scm_lock_data    /* data contained in global SCM lock object */
+{
+    DWORD seb_size;     /* size of service environment block */
+    WCHAR service_name[ MAX_SERVICE_NAME ];
+};
+
+struct SEB              /* service environment block */
+{                       /*   resides in service's shared memory object */
+    DWORD argc;
+    /* variable part of SEB contains service arguments */
+};
 
 /******************************************************************************
  * SC_HANDLEs
  */
 
-#define MAX_SERVICE_NAME 256
-
 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
 
 struct sc_handle;
@@ -183,12 +197,12 @@
  * helper function for StartServiceCtrlDispatcherA/W
  *
  * SCM database is locked by StartService;
- * open global SCM lock object and read service name
+ * open global SCM lock object and read data
  */
-static BOOL read_scm_lock_data( LPWSTR buffer )
+static BOOL read_scm_lock_data( struct scm_lock_data *buffer )
 {
     HANDLE hLock;
-    LPWSTR argptr;
+    LPWSTR shmem_ptr;
 
     hLock = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, szSCMLock );
     if( NULL == hLock )
@@ -196,36 +210,66 @@
         SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT );
         return FALSE;
     }
-    argptr = MapViewOfFile( hLock, FILE_MAP_ALL_ACCESS,
-                            0, 0, MAX_SERVICE_NAME * sizeof(WCHAR) );
-    if( NULL == argptr )
+    shmem_ptr = MapViewOfFile( hLock, FILE_MAP_ALL_ACCESS,
+                               0, 0, sizeof(struct scm_lock_data) );
+    if( NULL == shmem_ptr )
     {
         CloseHandle( hLock );
         return FALSE;
     }
-    strcpyW( buffer, argptr );
-    UnmapViewOfFile( argptr );
+    memcpy( buffer, shmem_ptr, sizeof(struct scm_lock_data) );
+    UnmapViewOfFile( shmem_ptr );
     CloseHandle( hLock );
     return TRUE;
 }
 
 /******************************************************************************
+ * build_arg_vectors
+ *
+ * helper function for StartServiceCtrlDispatcherA/W
+ *
+ * Allocate and initialize array of LPWSTRs to arguments in variable part
+ * of service environment block.
+ * First entry in the array is reserved for service name and not initialized.
+ */
+static LPWSTR* build_arg_vectors( struct SEB* seb )
+{
+    LPWSTR *ret;
+    LPWSTR argptr;
+    DWORD i;
+
+    ret = HeapAlloc( GetProcessHeap(), 0, (1 + seb->argc) * sizeof(LPWSTR) );
+    if( NULL == ret )
+        return NULL;
+
+    argptr = (LPWSTR) &seb[1];
+    for( i = 0; i < seb->argc; i++ )
+    {
+        ret[ 1 + i ] = argptr;
+        argptr += 1 + strlenW( argptr );
+    }
+    return ret;
+}
+
+/******************************************************************************
  * StartServiceCtrlDispatcherA [ADVAPI32.@]
  */
 BOOL WINAPI
 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
 {
     LPSERVICE_MAIN_FUNCTIONA fpMain;
-    WCHAR service_name[ MAX_SERVICE_NAME ];
-    LPWSTR argv0;
+    struct scm_lock_data lock_data;
+    WCHAR object_name[ MAX_PATH ];
+    HANDLE hServiceShmem = NULL;
+    struct SEB *seb = NULL;
     DWORD  dwNumServiceArgs ;
-    LPWSTR *lpArgVecW;
+    LPWSTR *lpArgVecW = NULL;
     LPSTR  *lpArgVecA;
     unsigned int i;
 
     TRACE("(%p)\n", servent);
 
-    if( ! read_scm_lock_data( service_name ) )
+    if( ! read_scm_lock_data( &lock_data ) )
     {
         /* FIXME: Instead of exiting we fall through and allow
            service to be executed as ordinary program.
@@ -238,18 +282,31 @@
         goto run_service;
     }
 
-    /* FIXME: other args */
-    dwNumServiceArgs = 1;
-    argv0            = service_name;
-    lpArgVecW        = &argv0;
+    snprintfW( object_name, MAX_PATH, szServiceShmemNameFmtW, lock_data.service_name );
+    hServiceShmem = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, object_name );
+    if( NULL == hServiceShmem )
+        return FALSE;
 
-    /* Convert the Unicode arg vectors back to ASCII */
-    if(dwNumServiceArgs)
-        lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
-                                   dwNumServiceArgs*sizeof(LPSTR) );
-    else
-        lpArgVecA = NULL;
+    seb = MapViewOfFile( hServiceShmem, FILE_MAP_ALL_ACCESS, 0, 0, lock_data.seb_size );
+    if( NULL == seb )
+    {
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
 
+    lpArgVecW = build_arg_vectors( seb );
+    if( NULL == lpArgVecW )
+    {
+        UnmapViewOfFile( seb );
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+    lpArgVecW[0] = lock_data.service_name;
+    dwNumServiceArgs = seb->argc + 1;
+
+    /* Convert the Unicode arg vectors back to ASCII */
+    lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
+                                    dwNumServiceArgs*sizeof(LPSTR) );
     for(i=0; i<dwNumServiceArgs; i++)
         lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
 
@@ -273,6 +330,9 @@
         HeapFree(GetProcessHeap(), 0, lpArgVecA);
     }
 
+    if( lpArgVecW ) HeapFree( GetProcessHeap(), 0, lpArgVecW );
+    if( seb ) UnmapViewOfFile( seb );
+    if( hServiceShmem ) CloseHandle( hServiceShmem );
     return TRUE;
 }
 
@@ -286,20 +346,39 @@
 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
 {
     LPSERVICE_MAIN_FUNCTIONW fpMain;
-    LPWSTR argv0;
-    WCHAR service_name[ MAX_SERVICE_NAME ];
+    struct scm_lock_data lock_data;
+    WCHAR object_name[ MAX_PATH ];
+    HANDLE hServiceShmem;
+    struct SEB *seb;
     DWORD  dwNumServiceArgs ;
     LPWSTR *lpServiceArgVectors ;
 
     TRACE("(%p)\n", servent);
 
-    if( ! read_scm_lock_data( service_name ) )
+    if( ! read_scm_lock_data( &lock_data ) )
         return FALSE;
 
-    /* FIXME: other args */
-    dwNumServiceArgs    = 1;
-    argv0               = service_name;
-    lpServiceArgVectors = &argv0;
+    snprintfW( object_name, MAX_PATH, szServiceShmemNameFmtW, lock_data.service_name );
+    hServiceShmem = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, object_name );
+    if( NULL == hServiceShmem )
+        return FALSE;
+
+    seb = MapViewOfFile( hServiceShmem, FILE_MAP_ALL_ACCESS, 0, 0, lock_data.seb_size );
+    if( NULL == seb )
+    {
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+
+    lpServiceArgVectors = build_arg_vectors( seb );
+    if( NULL == lpServiceArgVectors )
+    {
+        UnmapViewOfFile( seb );
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+    lpServiceArgVectors[0] = lock_data.service_name;
+    dwNumServiceArgs = seb->argc + 1;
 
     /* FIXME: should we blindly start all services? */
     while (servent->lpServiceName) {
@@ -312,6 +391,9 @@
         servent++;
     }
 
+    HeapFree( GetProcessHeap(), 0, lpServiceArgVectors );
+    UnmapViewOfFile( seb );
+    CloseHandle( hServiceShmem );
     return TRUE;
 }
 
@@ -904,10 +986,14 @@
     struct sc_handle *hsvc = hService;
     WCHAR path[MAX_PATH],str[MAX_PATH];
     DWORD type,size;
+    DWORD i;
     long r;
     HANDLE hLock;
+    HANDLE hServiceShmem = NULL;
     HANDLE wait = NULL;
-    LPWSTR shmem_lock = NULL;
+    struct scm_lock_data *shmem_lock = NULL;
+    struct SEB *seb = NULL;
+    LPWSTR argptr;
     PROCESS_INFORMATION procinfo;
     STARTUPINFOW startupinfo;
     BOOL ret = FALSE;
@@ -931,15 +1017,52 @@
      * FIXME: start dependent services
      */
 
-    /* pass argv[0] (service name) to the service via global SCM lock object */
+    /* calculate size of service environment block */
+    size = sizeof(struct SEB);
+    for( i = 0; i < dwNumServiceArgs; i++ )
+        size += sizeof(WCHAR) * (1 + strlenW( lpServiceArgVectors[ i ] ));
+
+    /* pass size of SEB and argv[0] (service name)
+       to the service via global SCM lock object */
     shmem_lock = MapViewOfFile( hLock, FILE_MAP_ALL_ACCESS,
-                                0, 0, MAX_SERVICE_NAME * sizeof(WCHAR) );
+                                0, 0, sizeof(struct scm_lock_data) );
     if( NULL == shmem_lock )
     {
         ERR("Couldn't map shared memory\n");
         goto done;
     }
-    strcpyW( shmem_lock, hsvc->u.service.name );
+    shmem_lock->seb_size = size;
+    strcpyW( shmem_lock->service_name, hsvc->u.service.name );
+
+    /* create service environment block */
+    snprintfW( str, MAX_PATH, szServiceShmemNameFmtW, hsvc->u.service.name );
+    hServiceShmem = CreateFileMappingW( INVALID_HANDLE_VALUE,
+                                        NULL, PAGE_READWRITE, 0, size, str );
+    if( NULL == hServiceShmem )
+    {
+        ERR("Couldn't create shared memory object\n");
+        goto done;
+    }
+    if( GetLastError() == ERROR_ALREADY_EXISTS )
+    {
+        SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
+        goto done;
+    }
+    seb = MapViewOfFile( hServiceShmem, FILE_MAP_ALL_ACCESS, 0, 0, size );
+    if( NULL == seb )
+    {
+        ERR("Couldn't map shared memory\n");
+        goto done;
+    }
+
+    /* copy service args to SEB */
+    seb->argc = dwNumServiceArgs;
+    argptr = (LPWSTR) &seb[1];
+    for( i = 0; i < dwNumServiceArgs; i++ )
+    {
+        strcpyW( argptr, lpServiceArgVectors[ i ] );
+        argptr += 1 + strlenW( argptr );
+    }
 
     wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
     if (!wait)
@@ -948,11 +1071,6 @@
         goto done;
     }
 
-    /*
-     * FIXME: lpServiceArgsVectors need to be stored and returned to
-     *        the service when it calls StartServiceCtrlDispatcher
-     */
-
     ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
     startupinfo.cb = sizeof(STARTUPINFOW);
 
@@ -988,6 +1106,8 @@
 
 done:
     if( wait ) CloseHandle( wait );
+    if( seb != NULL ) UnmapViewOfFile( seb );
+    if( hServiceShmem != NULL ) CloseHandle( hServiceShmem );
     if( shmem_lock != NULL ) UnmapViewOfFile( shmem_lock );
     UnlockServiceDatabase( hLock );
     return ret;




More information about the wine-patches mailing list