Author: mjmartin
Date: Sun Oct 12 08:10:05 2008
New Revision: 36732
URL:
http://svn.reactos.org/svn/reactos?rev=36732&view=rev
Log:
- Implement REnumServicesStatusExA
- REnumServicesStatusA/W: Fixed returned param values to match Windows
- REnumServicesStatusExW: Dont try to access lpResumeIndex if it is NULL. Fixed returned
param values to match windows.
Modified:
trunk/reactos/base/system/services/rpcserver.c
Modified: trunk/reactos/base/system/services/rpcserver.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/rpcse…
==============================================================================
--- trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] Sun Oct 12 08:10:05 2008
@@ -2371,6 +2371,12 @@
dwRequiredSize += dwSize;
}
+ if (dwError != ERROR_MORE_DATA)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeHandle) *lpResumeHandle = 0;
+ }
+
Done:;
/* FIXME: Unlock the service list */
@@ -3451,8 +3457,8 @@
continue;
dwSize = sizeof(ENUM_SERVICE_STATUSA) +
- ((wcslen(CurrentService->lpServiceName) + 1)) +
- ((wcslen(CurrentService->lpDisplayName) + 1));
+ wcslen(CurrentService->lpServiceName) + 1 +
+ wcslen(CurrentService->lpDisplayName) + 1;
if (dwRequiredSize + dwSize > dwBufSize)
{
@@ -3487,9 +3493,9 @@
if ((dwState & dwServiceState) == 0)
continue;
- dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSA) +
- ((wcslen(CurrentService->lpServiceName) + 1)) +
- ((wcslen(CurrentService->lpDisplayName) + 1)));
+ dwRequiredSize += sizeof(ENUM_SERVICE_STATUSA) +
+ wcslen(CurrentService->lpServiceName) + 1 +
+ wcslen(CurrentService->lpDisplayName) + 1;
dwError = ERROR_MORE_DATA;
}
@@ -3524,8 +3530,8 @@
continue;
dwSize = sizeof(ENUM_SERVICE_STATUSA) +
- ((wcslen(CurrentService->lpServiceName) + 1)) +
- ((wcslen(CurrentService->lpDisplayName) + 1));
+ wcslen(CurrentService->lpServiceName) + 1 +
+ wcslen(CurrentService->lpDisplayName) + 1;
if (dwRequiredSize + dwSize > dwBufSize)
break;
@@ -3561,6 +3567,12 @@
lpStatusPtr++;
dwRequiredSize += dwSize;
+ }
+
+ if (dwError != ERROR_MORE_DATA)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeHandle) *lpResumeHandle = 0;
}
Done:;
@@ -4509,10 +4521,295 @@
LPBOUNDED_DWORD_256K lpResumeIndex,
LPCSTR pszGroupName)
{
- UNIMPLEMENTED;
+ PMANAGER_HANDLE hManager;
+ PSERVICE lpService;
+ DWORD dwError = ERROR_SUCCESS;
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+ DWORD dwState;
+ DWORD dwRequiredSize;
+ DWORD dwServiceCount;
+ DWORD dwSize;
+ DWORD dwLastResumeCount = 0;
+ LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
+ LPSTR lpStringPtr;
+ LPWSTR pszGroupNameW = NULL;
+
+ DPRINT("REnumServicesStatusExA() 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 || hManager->Handle.Tag != MANAGER_TAG)
+ {
+ DPRINT1("Invalid manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
*pcbBytesNeeded = 0;
*lpServicesReturned = 0;
- return ERROR_CALL_NOT_IMPLEMENTED;
+
+ if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+ {
+ DPRINT1("Not a valid Service Type!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+ {
+ DPRINT1("Not a valid Service State!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* 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;
+ }
+
+ if (lpResumeIndex) dwLastResumeCount = *lpResumeIndex;
+
+ /* FIXME: Lock the service list shared */
+
+ lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
+ if (lpService == NULL)
+ {
+ dwError = ERROR_SUCCESS;
+ goto Done;
+ }
+
+ dwRequiredSize = 0;
+ dwServiceCount = 0;
+
+ if (pszGroupName)
+ {
+ pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
(strlen(pszGroupName) + 1) * sizeof(WCHAR));
+ if (!pszGroupNameW)
+ {
+ DPRINT1("Failed to allocate buffer!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ pszGroupName,
+ -1,
+ pszGroupNameW,
+ strlen(pszGroupName) + 1);
+ }
+
+ 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 (pszGroupNameW)
+ {
+ if (*pszGroupNameW == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupNameW, CurrentService->lpGroup->lpGroupName))
+ continue;
+ }
+ }
+
+ dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+ (wcslen(CurrentService->lpServiceName) + 1) +
+ (wcslen(CurrentService->lpDisplayName) + 1);
+
+ if (dwRequiredSize + dwSize <= cbBufSize)
+ {
+ 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 (pszGroupNameW)
+ {
+ if (*pszGroupNameW == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupNameW, CurrentService->lpGroup->lpGroupName))
+ continue;
+ }
+ }
+
+ dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+ (wcslen(CurrentService->lpServiceName) + 1) +
+ (wcslen(CurrentService->lpDisplayName) + 1));
+
+ dwError = ERROR_MORE_DATA;
+ }
+
+ DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+ if (lpResumeIndex) *lpResumeIndex = dwLastResumeCount;
+ *lpServicesReturned = dwServiceCount;
+ *pcbBytesNeeded = dwRequiredSize;
+
+ /* If there was no services that matched */
+ if (!dwServiceCount)
+ {
+ dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+ goto Done;
+ }
+
+ lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer;
+ lpStringPtr = (LPSTR)((ULONG_PTR)lpBuffer +
+ dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
+
+ 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 (pszGroupNameW)
+ {
+ if (*pszGroupNameW == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupNameW, CurrentService->lpGroup->lpGroupName))
+ continue;
+ }
+ }
+
+ dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize <= cbBufSize)
+ {
+ /* Copy the service name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ CurrentService->lpServiceName,
+ -1,
+ lpStringPtr,
+ wcslen(CurrentService->lpServiceName),
+ 0,
+ 0);
+ lpStatusPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtr -
(ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+ /* Copy the display name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ CurrentService->lpDisplayName,
+ -1,
+ lpStringPtr,
+ wcslen(CurrentService->lpDisplayName),
+ 0,
+ 0);
+ lpStatusPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtr -
(ULONG_PTR)lpBuffer);
+ 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;
+ }
+ }
+
+ if (dwError != ERROR_MORE_DATA)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeIndex) *lpResumeIndex = 0;
+ }
+
+Done:;
+ /* Unlock the service list */
+
+ if (pszGroupNameW) HeapFree(GetProcessHeap(),0,pszGroupNameW);
+
+ DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError);
+
+ return dwError;
}
@@ -4539,7 +4836,7 @@
DWORD dwRequiredSize;
DWORD dwServiceCount;
DWORD dwSize;
- DWORD dwLastResumeCount;
+ DWORD dwLastResumeCount = 0;
LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
LPWSTR lpStringPtr;
@@ -4556,6 +4853,21 @@
{
DPRINT1("Invalid manager handle!\n");
return ERROR_INVALID_HANDLE;
+ }
+
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
+
+ if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+ {
+ DPRINT1("Not a valid Service Type!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+ {
+ DPRINT1("Not a valid Service State!\n");
+ return ERROR_INVALID_PARAMETER;
}
/* Check access rights */
@@ -4567,10 +4879,7 @@
return ERROR_ACCESS_DENIED;
}
- *pcbBytesNeeded = 0;
- *lpServicesReturned = 0;
-
- dwLastResumeCount = *lpResumeIndex;
+ if (lpResumeIndex) dwLastResumeCount = *lpResumeIndex;
/* Lock the service list shared */
@@ -4681,9 +4990,16 @@
DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
- *lpResumeIndex = dwLastResumeCount;
+ if (lpResumeIndex) *lpResumeIndex = dwLastResumeCount;
*lpServicesReturned = dwServiceCount;
*pcbBytesNeeded = dwRequiredSize;
+
+ /* If there was no services that matched */
+ if (!dwServiceCount)
+ {
+ dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+ goto Done;
+ }
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer;
lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
@@ -4755,7 +5071,12 @@
{
break;
}
-
+ }
+
+ if (dwError != ERROR_MORE_DATA)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeIndex) *lpResumeIndex = 0;
}
Done:;