Revised: Pass arguments to the service program

Alexander Yaworsky yaworsky at migusoft.ru
Fri Sep 17 04:46:31 CDT 2004


Hello

now it looks better

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 09:34:57 -0000
@@ -39,6 +39,14 @@
       '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 SEB              /* service environment block */
+{                       /*   resides in service's shared memory object */
+    DWORD argc;
+    /* variable part of SEB contains service arguments */
+};
 
 /******************************************************************************
  * SC_HANDLEs
@@ -210,6 +218,34 @@
 }
 
 /******************************************************************************
+ * 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
@@ -217,9 +253,11 @@
 {
     LPSERVICE_MAIN_FUNCTIONA fpMain;
     WCHAR service_name[ MAX_SERVICE_NAME ];
-    LPWSTR argv0;
+    WCHAR object_name[ MAX_PATH ];
+    HANDLE hServiceShmem = NULL;
+    struct SEB *seb = NULL;
     DWORD  dwNumServiceArgs ;
-    LPWSTR *lpArgVecW;
+    LPWSTR *lpArgVecW = NULL;
     LPSTR  *lpArgVecA;
     unsigned int i;
 
@@ -238,18 +276,31 @@
         goto run_service;
     }
 
-    /* FIXME: other args */
-    dwNumServiceArgs = 1;
-    argv0            = service_name;
-    lpArgVecW        = &argv0;
+    snprintfW( object_name, MAX_PATH, szServiceShmemNameFmtW, 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, 0 );
+    if( NULL == seb )
+    {
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+
+    lpArgVecW = build_arg_vectors( seb );
+    if( NULL == lpArgVecW )
+    {
+        UnmapViewOfFile( seb );
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+    lpArgVecW[0] = 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 +324,9 @@
         HeapFree(GetProcessHeap(), 0, lpArgVecA);
     }
 
+    if( lpArgVecW ) HeapFree( GetProcessHeap(), 0, lpArgVecW );
+    if( seb ) UnmapViewOfFile( seb );
+    if( hServiceShmem ) CloseHandle( hServiceShmem );
     return TRUE;
 }
 
@@ -286,8 +340,10 @@
 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
 {
     LPSERVICE_MAIN_FUNCTIONW fpMain;
-    LPWSTR argv0;
     WCHAR service_name[ MAX_SERVICE_NAME ];
+    WCHAR object_name[ MAX_PATH ];
+    HANDLE hServiceShmem;
+    struct SEB *seb;
     DWORD  dwNumServiceArgs ;
     LPWSTR *lpServiceArgVectors ;
 
@@ -296,10 +352,27 @@
     if( ! read_scm_lock_data( service_name ) )
         return FALSE;
 
-    /* FIXME: other args */
-    dwNumServiceArgs    = 1;
-    argv0               = service_name;
-    lpServiceArgVectors = &argv0;
+    snprintfW( object_name, MAX_PATH, szServiceShmemNameFmtW, 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, 0 );
+    if( NULL == seb )
+    {
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+
+    lpServiceArgVectors = build_arg_vectors( seb );
+    if( NULL == lpServiceArgVectors )
+    {
+        UnmapViewOfFile( seb );
+        CloseHandle( hServiceShmem );
+        return FALSE;
+    }
+    lpServiceArgVectors[0] = service_name;
+    dwNumServiceArgs = seb->argc + 1;
 
     /* FIXME: should we blindly start all services? */
     while (servent->lpServiceName) {
@@ -312,6 +385,9 @@
         servent++;
     }
 
+    HeapFree( GetProcessHeap(), 0, lpServiceArgVectors );
+    UnmapViewOfFile( seb );
+    CloseHandle( hServiceShmem );
     return TRUE;
 }
 
@@ -904,10 +980,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 SEB *seb = NULL;
+    LPWSTR argptr;
     PROCESS_INFORMATION procinfo;
     STARTUPINFOW startupinfo;
     BOOL ret = FALSE;
@@ -941,6 +1021,40 @@
     }
     strcpyW( shmem_lock, hsvc->u.service.name );
 
+    /* create service environment block */
+    size = sizeof(struct SEB);
+    for( i = 0; i < dwNumServiceArgs; i++ )
+        size += sizeof(WCHAR) * (1 + strlenW( lpServiceArgVectors[ i ] ));
+
+    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, 0 );
+    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 +1062,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 +1097,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