From af5f6325e5e22fb53c772ea17d004dc19a18b115 Mon Sep 17 00:00:00 2001 From: Rolf Kalbermatter Date: Fri, 20 Apr 2007 10:36:19 +0200 Subject: [PATCH] advapi32: Implement QueryServiceStatusEx. Based on a patch by Anastasius Focht. --- dlls/advapi32/service.c | 71 +++++++++++++++++++++++++++++++++++++++-- include/winsvc.h | 9 ++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 60f8dcaf398..53ec9fc4c7e 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -1635,9 +1635,74 @@ BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded) { - FIXME("stub\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct sc_service *hsvc; + DWORD size, type, val; + HANDLE pipe; + LONG r; + LPSERVICE_STATUS_PROCESS pSvcStatusData; + + TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); + + if (InfoLevel != SC_STATUS_PROCESS_INFO) + { + SetLastError( ERROR_INVALID_LEVEL); + return FALSE; + } + + pSvcStatusData = (LPSERVICE_STATUS_PROCESS) lpBuffer; + if (pSvcStatusData == NULL) + { + SetLastError( ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS)) + { + if( pcbBytesNeeded != NULL) + *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS); + + SetLastError( ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + + /* FIXME: this would be the pid from service_start_process() */ + pSvcStatusData->dwProcessId = 0; + /* service is running in a process that is not a system process */ + pSvcStatusData->dwServiceFlags = 0; + + pipe = service_open_pipe(hsvc->name); + if (pipe != INVALID_HANDLE_VALUE) + { + r = service_get_status(pipe, &pSvcStatusData->status); + CloseHandle(pipe); + if (r) + return TRUE; + } + + TRACE("Failed to read service status\n"); + + /* read the service type from the registry */ + size = sizeof(val); + r = RegQueryValueExA(hsvc->hkey, "Type", NULL, &type, (LPBYTE)&val, &size); + if (r != ERROR_SUCCESS || type != REG_DWORD) + val = 0; + + pSvcStatusData->status.dwServiceType = val; + pSvcStatusData->status.dwCurrentState = SERVICE_STOPPED; /* stopped */ + pSvcStatusData->status.dwControlsAccepted = 0; + pSvcStatusData->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED; + pSvcStatusData->status.dwServiceSpecificExitCode = 0; + pSvcStatusData->status.dwCheckPoint = 0; + pSvcStatusData->status.dwWaitHint = 0; + + return TRUE; } /****************************************************************************** diff --git a/include/winsvc.h b/include/winsvc.h index 93ccaf6d72f..eeb953953ce 100644 --- a/include/winsvc.h +++ b/include/winsvc.h @@ -131,6 +131,15 @@ typedef struct _SERVICE_STATUS { DWORD dwWaitHint; } SERVICE_STATUS, *LPSERVICE_STATUS; +/* Service status process structure */ + +typedef struct _SERVICE_STATUS_PROCESS +{ + SERVICE_STATUS status; + DWORD dwProcessId; + DWORD dwServiceFlags; +} SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS; + typedef enum _SC_STATUS_TYPE { SC_STATUS_PROCESS_INFO = 0 } SC_STATUS_TYPE;