diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 80af1f65497..aa57ad6227f 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -34,12 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi); -static DWORD start_dwNumServiceArgs; -static LPWSTR *start_lpServiceArgVectors; - -static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S', - 'e','r','v','i','c','e','S','t', - 'a','r','t','D','a','t','a',0}; 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 }; @@ -183,6 +177,38 @@ EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType, return FALSE; } +/****************************************************************************** + * read_scm_lock_data + * + * helper function for StartServiceCtrlDispatcherA/W + * + * SCM database is locked by StartService; + * open global SCM lock object and read service name + */ +static BOOL read_scm_lock_data( LPWSTR buffer ) +{ + HANDLE hLock; + LPWSTR argptr; + + hLock = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, szSCMLock ); + if( NULL == hLock ) + { + 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 ) + { + CloseHandle( hLock ); + return FALSE; + } + strcpyW( buffer, argptr ); + UnmapViewOfFile( argptr ); + CloseHandle( hLock ); + return TRUE; +} + /****************************************************************************** * StartServiceCtrlDispatcherA [ADVAPI32.@] */ @@ -190,24 +216,32 @@ BOOL WINAPI StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) { LPSERVICE_MAIN_FUNCTIONA fpMain; - HANDLE wait; + WCHAR service_name[ MAX_SERVICE_NAME ]; + LPWSTR argv0; DWORD dwNumServiceArgs ; LPWSTR *lpArgVecW; LPSTR *lpArgVecA; unsigned int i; TRACE("(%p)\n", servent); - wait = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW); - if (!wait) + + if( ! read_scm_lock_data( service_name ) ) { - ERR("Couldn't create data semaphore\n"); - return FALSE; + /* FIXME: Instead of exiting we fall through and allow + service to be executed as ordinary program. + This behaviour was specially introduced in the patch + submitted against revision 1.45 and so preserved here. + */ + FIXME("should fail with ERROR_FAILED_SERVICE_CONTROLLER_CONNECT\n"); + dwNumServiceArgs = 0; + lpArgVecA = NULL; + goto run_service; } - dwNumServiceArgs = start_dwNumServiceArgs; - lpArgVecW = start_lpServiceArgVectors; - - ReleaseSemaphore(wait, 1, NULL); + /* FIXME: other args */ + dwNumServiceArgs = 1; + argv0 = service_name; + lpArgVecW = &argv0; /* Convert the Unicode arg vectors back to ASCII */ if(dwNumServiceArgs) @@ -219,6 +253,7 @@ StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) for(i=0; ilpServiceName) { TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent); @@ -251,23 +286,20 @@ BOOL WINAPI StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent ) { LPSERVICE_MAIN_FUNCTIONW fpMain; - HANDLE wait; + LPWSTR argv0; + WCHAR service_name[ MAX_SERVICE_NAME ]; DWORD dwNumServiceArgs ; LPWSTR *lpServiceArgVectors ; TRACE("(%p)\n", servent); - wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW); - if(wait == 0) - { - ERR("Couldn't find wait semaphore\n"); - ERR("perhaps you need to start services using StartService\n"); + + if( ! read_scm_lock_data( service_name ) ) return FALSE; - } - dwNumServiceArgs = start_dwNumServiceArgs; - lpServiceArgVectors = start_lpServiceArgVectors; - - ReleaseSemaphore(wait, 1, NULL); + /* FIXME: other args */ + dwNumServiceArgs = 1; + argv0 = service_name; + lpServiceArgVectors = &argv0; /* FIXME: should we blindly start all services? */ while (servent->lpServiceName) { @@ -873,7 +905,9 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, WCHAR path[MAX_PATH],str[MAX_PATH]; DWORD type,size; long r; - HANDLE data,wait; + HANDLE hLock; + HANDLE wait = NULL; + LPWSTR shmem_lock = NULL; PROCESS_INFORMATION procinfo; STARTUPINFOW startupinfo; BOOL ret = FALSE; @@ -889,36 +923,36 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, TRACE("Starting service %s\n", debugstr_w(path) ); - data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW); - if (!data) - { - ERR("Couldn't create data semaphore\n"); + hLock = LockServiceDatabase( hsvc->u.service.sc_manager ); + if( NULL == hLock ) return FALSE; + + /* + * FIXME: start dependent services + */ + + /* pass 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) ); + if( NULL == shmem_lock ) + { + ERR("Couldn't map shared memory\n"); + goto done; } + strcpyW( shmem_lock, hsvc->u.service.name ); + wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW); if (!wait) { ERR("Couldn't create wait semaphore\n"); - return FALSE; + goto done; } /* * FIXME: lpServiceArgsVectors need to be stored and returned to * the service when it calls StartServiceCtrlDispatcher - * - * Chuck these in a global (yuk) so we can pass them to - * another process - address space separation will break this. */ - r = WaitForSingleObject(data,INFINITE); - - if( r == WAIT_FAILED) - return FALSE; - - FIXME("problematic because of address space separation.\n"); - start_dwNumServiceArgs = dwNumServiceArgs; - start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors; - ZeroMemory(&startupinfo,sizeof(STARTUPINFOW)); startupinfo.cb = sizeof(STARTUPINFOW); @@ -953,9 +987,9 @@ StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, ret = TRUE; done: - CloseHandle( wait ); - ReleaseSemaphore(data, 1, NULL); - CloseHandle( data ); + if( wait ) CloseHandle( wait ); + if( shmem_lock != NULL ) UnmapViewOfFile( shmem_lock ); + UnlockServiceDatabase( hLock ); return ret; }