From: Eric Kohl Date: Mon, 26 Dec 2005 15:06:46 +0000 (+0000) Subject: -Implement EnumServicesStatusExW. X-Git-Tag: backups/expat-rbuild@40467~800 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=5531d9e68d12bc342a9c1f26ac616d4eced56ff8 -Implement EnumServicesStatusExW. -Add missing [unique] Attributes to svcctrl.idl. svn path=/trunk/; revision=20335 --- diff --git a/reactos/include/idl/svcctl.idl b/reactos/include/idl/svcctl.idl index 239fe646c17..ed6e758e3a8 100644 --- a/reactos/include/idl/svcctl.idl +++ b/reactos/include/idl/svcctl.idl @@ -12,6 +12,7 @@ #define SC_LOCK unsigned int #define SERVICE_STATUS_HANDLE unsigned long #define SC_STATUS_TYPE unsigned long +#define SC_ENUM_TYPE unsigned long #define LPSTR char* #define LPCSTR char* #define LPWSTR wchar_t* @@ -138,7 +139,7 @@ cpp_quote("#endif") DWORD ScmrEnumDependentServicesW([in] handle_t BindingHandle, [in] SC_HANDLE hService, [in] DWORD dwServiceState, - [out, size_is(cbBufSize)] LPBYTE lpServices, + [out, unique, size_is(cbBufSize)] LPBYTE lpServices, [in] DWORD cbBufSize, [out] LPDWORD pcbBytesNeeded, [out] LPDWORD lpServicesReturned); @@ -148,7 +149,7 @@ cpp_quote("#endif") [in] SC_HANDLE hSCManager, [in] DWORD dwServiceType, [in] DWORD dwServiceState, - [out, size_is(dwBufSize)] LPBYTE lpServices, + [out, unique, size_is(dwBufSize)] LPBYTE lpServices, [in] DWORD dwBufSize, [out] LPDWORD pcbBytesNeeded, [out] LPDWORD lpServicesReturned, @@ -178,7 +179,7 @@ cpp_quote("#endif") /* Function 18 */ DWORD ScmrQueryServiceLockStatusW([in] handle_t BindingHandle, [in] SC_HANDLE hSCManager, - [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus, + [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus, [in] DWORD cbBufSize, [out] LPDWORD pcbBytesNeeded); @@ -249,7 +250,7 @@ cpp_quote("#endif") DWORD ScmrEnumDependentServicesA([in] handle_t BindingHandle, [in] SC_HANDLE hService, [in] DWORD dwServiceState, - [out, size_is(cbBufSize)] LPBYTE lpServices, + [out, unique, size_is(cbBufSize)] LPBYTE lpServices, [in] DWORD cbBufSize, [out] LPDWORD pcbBytesNeeded, [out] LPDWORD lpServicesReturned); @@ -259,7 +260,7 @@ cpp_quote("#endif") [in] SC_HANDLE hSCManager, [in] DWORD dwServiceType, [in] DWORD dwServiceState, - [out, size_is(dwBufSize)] LPBYTE lpServices, + [out, unique, size_is(dwBufSize)] LPBYTE lpServices, [in] DWORD dwBufSize, [out] LPDWORD pcbBytesNeeded, [out] LPDWORD lpServicesReturned, @@ -289,7 +290,7 @@ cpp_quote("#endif") /* Function 30 */ // DWORD ScmrQueryServiceLockStatusA([in] handle_t BindingHandle, // [in] SC_HANDLE hSCManager, -// [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus, +// [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus, // [in] DWORD cbBufSize, // [out] LPDWORD pcbBytesNeeded); @@ -297,20 +298,20 @@ cpp_quote("#endif") // DWORD ScmrStartServiceA([in] handle_t BindingHandle, // [in] SC_HANDLE hService, // [in] DWORD dwNumServiceArgs, -// [in, string, size_is(dwNumServiceArgs, ), unique] LPSTR *lpServiceArgVectors); +// [in, unique, string, size_is(dwNumServiceArgs, )] LPSTR *lpServiceArgVectors); /* Function 32 */ DWORD ScmrGetServiceDisplayNameA([in] handle_t BindingHandle, [in] SC_HANDLE hSCManager, [in, string, ref] LPCSTR lpServiceName, - [out, size_is(*lpcchBuffer), unique] LPSTR lpDisplayName, + [out, unique, size_is(*lpcchBuffer)] LPSTR lpDisplayName, [in, out, ref] LPDWORD lpcchBuffer); /* Function 33 */ DWORD ScmrGetServiceKeyNameA([in] handle_t BindingHandle, [in] SC_HANDLE hSCManager, [in, string, ref] LPCSTR lpDisplayName, - [out, size_is(*lpcchBuffer), unique] LPSTR lpServiceName, + [out, unique, size_is(*lpcchBuffer)] LPSTR lpServiceName, [in, out, ref] LPDWORD lpcchBuffer); /* Function 35 */ @@ -335,15 +336,35 @@ cpp_quote("#endif") DWORD ScmrQueryServiceStatusEx([in] handle_t BindingHandle, [in] SC_HANDLE hService, [in] SC_STATUS_TYPE InfoLevel, - [out, size_is(cbBufSize)] LPBYTE lpBuffer, + [out, unique, size_is(cbBufSize)] LPBYTE lpBuffer, [in] DWORD cbBufSize, [out] LPDWORD pcbBytesNeeded); /* Function 41 */ - /* ScmrEnumServicesStatusExA */ +// DWORD ScmrEnumServicesStatusExA([in] handle_t BindingHandle, +// [in] SC_HANDLE hService, +// [in] SC_ENUM_TYPE InfoLevel, +// [in] DWORD dwServiceType, +// [in] DWORD dwServiceState, +// [out, unique, size_is(cbBufSize)] LPBYTE lpServices, +// [in] DWORD cbBufSize, +// [out] LPDWORD pcbBytesNeeded, +// [out] LPDWORD lpServicesReturned, +// [in, out, unique] LPDWORD lpResumeHandle, +// [in, string] LPCSTR pszGroupName); /* Function 42 */ - /* ScmrEnumServicesStatusExW */ + DWORD ScmrEnumServicesStatusExW([in] handle_t BindingHandle, + [in] SC_HANDLE hService, + [in] SC_ENUM_TYPE InfoLevel, + [in] DWORD dwServiceType, + [in] DWORD dwServiceState, + [out, unique, size_is(cbBufSize)] LPBYTE lpServices, + [in] DWORD cbBufSize, + [out] LPDWORD pcbBytesNeeded, + [out] LPDWORD lpServicesReturned, + [in, out, unique] LPDWORD lpResumeHandle, + [in, string] LPCWSTR pszGroupName); /* Function 43 */ /* ScmrSendTSMessage */ diff --git a/reactos/lib/advapi32/service/scm.c b/reactos/lib/advapi32/service/scm.c index 20befe27eb0..e148407d46f 100644 --- a/reactos/lib/advapi32/service/scm.c +++ b/reactos/lib/advapi32/service/scm.c @@ -708,24 +708,64 @@ EnumServicesStatusExA(SC_HANDLE hSCManager, /********************************************************************** * EnumServicesStatusExW * - * @unimplemented + * @implemented */ -BOOL -STDCALL -EnumServicesStatusExW(SC_HANDLE hSCManager, - SC_ENUM_TYPE InfoLevel, - DWORD dwServiceType, - DWORD dwServiceState, - LPBYTE lpServices, - DWORD cbBufSize, - LPDWORD pcbBytesNeeded, - LPDWORD lpServicesReturned, - LPDWORD lpResumeHandle, - LPCWSTR pszGroupName) +BOOL STDCALL +EnumServicesStatusExW(SC_HANDLE hSCManager, + SC_ENUM_TYPE InfoLevel, + DWORD dwServiceType, + DWORD dwServiceState, + LPBYTE lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle, + LPCWSTR pszGroupName) { - DPRINT1("EnumServicesStatusExW is unimplemented\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; + DWORD dwError = ERROR_SUCCESS; + DWORD dwCount; + + DPRINT1("EnumServicesStatusExW() called\n"); + + HandleBind(); + + dwError = ScmrEnumServicesStatusExW(BindingHandle, + (unsigned int)hSCManager, + (unsigned long)InfoLevel, + dwServiceType, + dwServiceState, + (unsigned char *)lpServices, + cbBufSize, + pcbBytesNeeded, + lpServicesReturned, + lpResumeHandle, + (wchar_t *)pszGroupName); + + lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices; + for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) + { + if (lpStatusPtr->lpServiceName) + lpStatusPtr->lpServiceName = + (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); + + if (lpStatusPtr->lpDisplayName) + lpStatusPtr->lpDisplayName = + (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); + + lpStatusPtr++; + } + + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrEnumServicesStatusExW() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return FALSE; + } + + DPRINT1("ScmrEnumServicesStatusExW() done\n"); + + return TRUE; } @@ -1390,7 +1430,7 @@ QueryServiceStatusEx(SC_HANDLE hService, pcbBytesNeeded); if (dwError != ERROR_SUCCESS) { - DPRINT1("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError); + DPRINT("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError); SetLastError(dwError); return FALSE; } diff --git a/reactos/subsys/system/services/rpcserver.c b/reactos/subsys/system/services/rpcserver.c index bae5348eb59..58164ad8869 100644 --- a/reactos/subsys/system/services/rpcserver.c +++ b/reactos/subsys/system/services/rpcserver.c @@ -1393,9 +1393,9 @@ ScmrEnumServicesStatusW(handle_t BindingHandle, *lpServicesReturned = dwServiceCount; *pcbBytesNeeded = dwRequiredSize; - lpStatusPtr = (LPENUM_SERVICE_STATUS)lpServices; + lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices; lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices + - dwServiceCount * sizeof(ENUM_SERVICE_STATUS)); + dwServiceCount * sizeof(ENUM_SERVICE_STATUSW)); dwRequiredSize = 0; for (ServiceEntry = &lpService->ServiceListEntry; @@ -2138,7 +2138,227 @@ ScmrQueryServiceStatusEx(handle_t BindingHandle, /* Function 42 */ -/* ScmrEnumServicesStatusExW */ +unsigned long +ScmrEnumServicesStatusExW(handle_t BindingHandle, + unsigned int hSCManager, + unsigned long InfoLevel, + unsigned long dwServiceType, + unsigned long dwServiceState, + unsigned char *lpServices, + unsigned long dwBufSize, + unsigned long *pcbBytesNeeded, + unsigned long *lpServicesReturned, + unsigned long *lpResumeHandle, + wchar_t *pszGroupName) +{ + PMANAGER_HANDLE hManager; + PSERVICE lpService; + DWORD dwError = ERROR_SUCCESS; + PLIST_ENTRY ServiceEntry; + PSERVICE CurrentService; + DWORD dwState; + DWORD dwRequiredSize; + DWORD dwServiceCount; + DWORD dwSize; + DWORD dwLastResumeCount; + LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; + LPWSTR lpStringPtr; + + DPRINT("ScmrEnumServicesStatusExW() called\n"); + + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + + if (InfoLevel != SC_ENUM_PROCESS_INFO) + return ERROR_INVALID_LEVEL; + + hManager = (PMANAGER_HANDLE)hSCManager; + if (hManager->Handle.Tag != MANAGER_TAG) + { + DPRINT1("Invalid manager handle!\n"); + return ERROR_INVALID_HANDLE; + } + + /* Check access rights */ + if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, + SC_MANAGER_ENUMERATE_SERVICE)) + { + DPRINT1("Insufficient access rights! 0x%lx\n", + hManager->Handle.DesiredAccess); + return ERROR_ACCESS_DENIED; + } + + *pcbBytesNeeded = 0; + *lpServicesReturned = 0; + + dwLastResumeCount = *lpResumeHandle; + + /* Lock the service list shared */ + + lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); + if (lpService == NULL) + { + dwError = ERROR_SUCCESS; + goto Done; + } + + dwRequiredSize = 0; + dwServiceCount = 0; + + for (ServiceEntry = &lpService->ServiceListEntry; + ServiceEntry != &ServiceListHead; + ServiceEntry = ServiceEntry->Flink) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, + SERVICE, + ServiceListEntry); + + if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) + continue; + + dwState = SERVICE_ACTIVE; + if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) + dwState = SERVICE_INACTIVE; + + if ((dwState & dwServiceState) == 0) + continue; + + if (pszGroupName) + { + if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup)) + continue; + } + + dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + + ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + + ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); + + if (dwRequiredSize + dwSize <= dwBufSize) + { + DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); + dwRequiredSize += dwSize; + dwServiceCount++; + dwLastResumeCount = CurrentService->dwResumeCount; + } + else + { + DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); + break; + } + + } + + DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); + DPRINT("dwServiceCount: %lu\n", dwServiceCount); + + for (; + ServiceEntry != &ServiceListHead; + ServiceEntry = ServiceEntry->Flink) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, + SERVICE, + ServiceListEntry); + + if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) + continue; + + dwState = SERVICE_ACTIVE; + if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) + dwState = SERVICE_INACTIVE; + + if ((dwState & dwServiceState) == 0) + continue; + + if (pszGroupName) + { + if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup)) + continue; + } + + dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) + + ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + + ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); + + dwError = ERROR_MORE_DATA; + } + + DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); + + *lpResumeHandle = dwLastResumeCount; + *lpServicesReturned = dwServiceCount; + *pcbBytesNeeded = dwRequiredSize; + + lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices; + lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices + + dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); + + dwRequiredSize = 0; + for (ServiceEntry = &lpService->ServiceListEntry; + ServiceEntry != &ServiceListHead; + ServiceEntry = ServiceEntry->Flink) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, + SERVICE, + ServiceListEntry); + + if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) + continue; + + dwState = SERVICE_ACTIVE; + if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) + dwState = SERVICE_INACTIVE; + + if ((dwState & dwServiceState) == 0) + continue; + + if (pszGroupName) + { + if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup)) + continue; + } + + dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + + ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + + ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); + + if (dwRequiredSize + dwSize <= dwBufSize) + { + /* Copy the service name */ + wcscpy(lpStringPtr, + CurrentService->lpServiceName); + lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices); + lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); + + /* Copy the display name */ + wcscpy(lpStringPtr, + CurrentService->lpDisplayName); + lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices); + lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); + + /* Copy the status information */ + memcpy(&lpStatusPtr->ServiceStatusProcess, + &CurrentService->Status, + sizeof(SERVICE_STATUS)); + lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */ + lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ + + lpStatusPtr++; + dwRequiredSize += dwSize; + } + else + { + break; + } + + } + +Done:; + /* Unlock the service list */ + + DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError); + + return dwError; +} /* Function 43 */