From 9d590d5059e76f124592ff9edf1c0eb48d335a92 Mon Sep 17 00:00:00 2001 From: Alexander Yaworsky Date: Tue, 21 Sep 2004 00:23:32 +0000 Subject: [PATCH] Pass arguments to the service program. --- dlls/advapi32/service.c | 155 ++++++++++++++++++++++++++++++++++------ 1 file changed, 133 insertions(+), 22 deletions(-) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index aa57ad6227f..80889e6fafc 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -39,6 +39,14 @@ static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\', '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 @@ -209,6 +217,34 @@ static BOOL read_scm_lock_data( LPWSTR buffer ) 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.@] */ @@ -217,9 +253,11 @@ StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) { 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 @@ StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) 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; + + 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 */ - if(dwNumServiceArgs) - lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0, - dwNumServiceArgs*sizeof(LPSTR) ); - else - lpArgVecA = NULL; - + lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0, + dwNumServiceArgs*sizeof(LPSTR) ); for(i=0; iargc + 1; /* FIXME: should we blindly start all services? */ while (servent->lpServiceName) { @@ -312,6 +385,9 @@ StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent ) servent++; } + HeapFree( GetProcessHeap(), 0, lpServiceArgVectors ); + UnmapViewOfFile( seb ); + CloseHandle( hServiceShmem ); return TRUE; } @@ -904,10 +980,14 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, 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 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, } 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 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, 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 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, 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;