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