dwError = ScmMarkServiceForDelete(lpService);
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
lpService->dwRefCount = 1;
DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount);
-done:;
+done:
/* Unlock the service database */
ScmUnlockDatabase();
*lpServiceHandle = (SC_RPC_HANDLE)hHandle;
DPRINT("*hService = %p\n", *lpServiceHandle);
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
if (pcbBytesNeeded != NULL)
*pcbBytesNeeded = dwRequiredSize;
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
LPBOUNDED_DWORD_256K lpResumeHandle)
{
LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
+ LPENUM_SERVICE_STATUSW lpStatusPtrIncrW;
LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
LPWSTR lpStringPtrW;
LPSTR lpStringPtrA;
if (*lpServicesReturned == 0)
goto Done;
+ lpStatusPtrIncrW = lpStatusPtrW;
lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
*lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
/* Copy the status information */
memcpy(&lpStatusPtrA->ServiceStatus,
- &lpStatusPtrW->ServiceStatus,
+ &lpStatusPtrIncrW->ServiceStatus,
sizeof(SERVICE_STATUS));
+ lpStatusPtrIncrW++;
lpStatusPtrA++;
}
-Done:;
+Done:
if (lpStatusPtrW)
HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
if (pcbBytesNeeded != NULL)
*pcbBytesNeeded = dwRequiredSize;
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
*lpServicesReturned = 0;
if ((dwServiceType == 0) ||
- ((dwServiceType & ~(SERVICE_DRIVER | SERVICE_WIN32)) != 0))
+ ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
{
DPRINT("Not a valid Service Type!\n");
return ERROR_INVALID_PARAMETER;
}
- if ((dwServiceState != SERVICE_ACTIVE) &&
- (dwServiceState != SERVICE_INACTIVE) &&
- (dwServiceState != SERVICE_STATE_ALL))
+ if ((dwServiceState == 0) ||
+ ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
{
DPRINT("Not a valid Service State!\n");
return ERROR_INVALID_PARAMETER;
}
+static DWORD
+ScmSetFailureActions(PSERVICE_HANDLE hSvc,
+ PSERVICE lpService,
+ HKEY hServiceKey,
+ LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
+{
+ LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL;
+ LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL;
+ BOOL bIsActionRebootSet = FALSE;
+ DWORD dwDesiredAccess = SERVICE_CHANGE_CONFIG;
+ DWORD dwRequiredSize = 0;
+ DWORD dwType = 0;
+ DWORD i = 0;
+ DWORD dwError;
+
+ /* There is nothing to be done if we have no failure actions */
+ if (lpFailureActions == NULL)
+ return ERROR_SUCCESS;
+
+ /*
+ * 1- Check whether or not we can set
+ * failure actions for this service.
+ */
+
+ /* Failure actions can only be set for Win32 services, not for drivers */
+ if (lpService->Status.dwServiceType & SERVICE_DRIVER)
+ return ERROR_CANNOT_DETECT_DRIVER_FAILURE;
+
+ /*
+ * If the service controller handles the SC_ACTION_RESTART action,
+ * hService must have the SERVICE_START access right.
+ *
+ * If you specify SC_ACTION_REBOOT, the caller must have the
+ * SE_SHUTDOWN_NAME privilege.
+ */
+ if (lpFailureActions->cActions > 0 &&
+ lpFailureActions->lpsaActions != NULL)
+ {
+ for (i = 0; i < lpFailureActions->cActions; ++i)
+ {
+ if (lpFailureActions->lpsaActions[i].Type == SC_ACTION_RESTART)
+ dwDesiredAccess |= SERVICE_START;
+ else if (lpFailureActions->lpsaActions[i].Type == SC_ACTION_REBOOT)
+ bIsActionRebootSet = TRUE;
+ }
+ }
+
+ /* Re-check the access rights */
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ dwDesiredAccess))
+ {
+ DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
+ if (bIsActionRebootSet)
+ {
+ }
+
+ /*
+ * 2- Retrieve the original value of FailureActions.
+ */
+
+ /* Query value length */
+ dwError = RegQueryValueExW(hServiceKey,
+ L"FailureActions",
+ NULL,
+ &dwType,
+ NULL,
+ &dwRequiredSize);
+ if (dwError != ERROR_SUCCESS &&
+ dwError != ERROR_MORE_DATA &&
+ dwError != ERROR_FILE_NOT_FOUND)
+ return dwError;
+
+ dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
+ : sizeof(SERVICE_FAILURE_ACTIONSW);
+
+ /* Initialize the read buffer */
+ lpReadBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwRequiredSize);
+ if (lpReadBuffer == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ /* Now we can fill the read buffer */
+ if (dwError != ERROR_FILE_NOT_FOUND &&
+ dwType == REG_BINARY)
+ {
+ dwError = RegQueryValueExW(hServiceKey,
+ L"FailureActions",
+ NULL,
+ NULL,
+ (LPBYTE)lpReadBuffer,
+ &dwRequiredSize);
+ if (dwError != ERROR_SUCCESS &&
+ dwError != ERROR_FILE_NOT_FOUND)
+ goto done;
+
+ if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW))
+ dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+ }
+ else
+ {
+ /*
+ * The value of the error doesn't really matter, the only
+ * important thing is that it must be != ERROR_SUCCESS.
+ */
+ dwError = ERROR_INVALID_DATA;
+ }
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ lpReadBuffer->cActions = min(lpReadBuffer->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION));
+ lpReadBuffer->lpsaActions = (lpReadBuffer->cActions > 0 ? (LPSC_ACTION)(lpReadBuffer + 1) : NULL);
+ }
+ else
+ {
+ lpReadBuffer->dwResetPeriod = 0;
+ lpReadBuffer->cActions = 0;
+ lpReadBuffer->lpsaActions = NULL;
+ }
+
+ lpReadBuffer->lpRebootMsg = NULL;
+ lpReadBuffer->lpCommand = NULL;
+
+ /*
+ * 3- Initialize the new value to set.
+ */
+
+ dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+
+ if (lpFailureActions->lpsaActions == NULL)
+ {
+ /*
+ * lpFailureActions->cActions is ignored.
+ * Therefore we use the original values
+ * of cActions and lpsaActions.
+ */
+ dwRequiredSize += lpReadBuffer->cActions * sizeof(SC_ACTION);
+ }
+ else
+ {
+ /*
+ * The reset period and array of failure actions
+ * are deleted if lpFailureActions->cActions == 0 .
+ */
+ dwRequiredSize += lpFailureActions->cActions * sizeof(SC_ACTION);
+ }
+
+ lpWriteBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwRequiredSize);
+ if (lpWriteBuffer == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ /* Clean the pointers as they have no meaning when the structure is stored in the registry */
+ lpWriteBuffer->lpRebootMsg = NULL;
+ lpWriteBuffer->lpCommand = NULL;
+ lpWriteBuffer->lpsaActions = NULL;
+
+ /* Set the members */
+ if (lpFailureActions->lpsaActions == NULL)
+ {
+ /*
+ * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored.
+ * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions.
+ */
+ lpWriteBuffer->dwResetPeriod = lpReadBuffer->dwResetPeriod;
+ lpWriteBuffer->cActions = lpReadBuffer->cActions;
+
+ if (lpReadBuffer->lpsaActions != NULL)
+ {
+ memmove(lpWriteBuffer + 1,
+ lpReadBuffer->lpsaActions,
+ lpReadBuffer->cActions * sizeof(SC_ACTION));
+ }
+ }
+ else
+ {
+ if (lpFailureActions->cActions > 0)
+ {
+ lpWriteBuffer->dwResetPeriod = lpFailureActions->dwResetPeriod;
+ lpWriteBuffer->cActions = lpFailureActions->cActions;
+
+ memmove(lpWriteBuffer + 1,
+ lpFailureActions->lpsaActions,
+ lpFailureActions->cActions * sizeof(SC_ACTION));
+ }
+ else
+ {
+ /* The reset period and array of failure actions are deleted */
+ lpWriteBuffer->dwResetPeriod = 0;
+ lpWriteBuffer->cActions = 0;
+ }
+ }
+
+ /* Save the new failure actions into the registry */
+ dwError = RegSetValueExW(hServiceKey,
+ L"FailureActions",
+ 0,
+ REG_BINARY,
+ (LPBYTE)lpWriteBuffer,
+ dwRequiredSize);
+
+ /* We modify the strings only in case of success.*/
+ if (dwError == ERROR_SUCCESS)
+ {
+ /* Modify the Reboot Message value, if specified */
+ if (lpFailureActions->lpRebootMsg != NULL)
+ {
+ /* If the Reboot Message is "" then we delete it */
+ if (*lpFailureActions->lpRebootMsg == 0)
+ {
+ DPRINT("Delete Reboot Message value\n");
+ RegDeleteValueW(hServiceKey, L"RebootMessage");
+ }
+ else
+ {
+ DPRINT("Setting Reboot Message value %S\n", lpFailureActions->lpRebootMsg);
+ RegSetValueExW(hServiceKey,
+ L"RebootMessage",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpFailureActions->lpRebootMsg,
+ (wcslen(lpFailureActions->lpRebootMsg) + 1) * sizeof(WCHAR));
+ }
+ }
+
+ /* Modify the Failure Command value, if specified */
+ if (lpFailureActions->lpCommand != NULL)
+ {
+ /* If the FailureCommand string is an empty string, delete the value */
+ if (*lpFailureActions->lpCommand == 0)
+ {
+ DPRINT("Delete Failure Command value\n");
+ RegDeleteValueW(hServiceKey, L"FailureCommand");
+ }
+ else
+ {
+ DPRINT("Setting Failure Command value %S\n", lpFailureActions->lpCommand);
+ RegSetValueExW(hServiceKey,
+ L"FailureCommand",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpFailureActions->lpCommand,
+ (wcslen(lpFailureActions->lpCommand) + 1) * sizeof(WCHAR));
+ }
+ }
+ }
+
+done:
+ if (lpWriteBuffer != NULL)
+ HeapFree(GetProcessHeap(), 0, lpWriteBuffer);
+
+ if (lpReadBuffer != NULL)
+ HeapFree(GetProcessHeap(), 0, lpReadBuffer);
+
+ return dwError;
+}
+
+
/* Function 37 */
DWORD RChangeServiceConfig2W(
SC_RPC_HANDLE hService,
/* Open the service key */
dwError = ScmOpenServiceKey(lpService->szServiceName,
- KEY_SET_VALUE,
+ KEY_READ | KEY_SET_VALUE,
&hServiceKey);
if (dwError != ERROR_SUCCESS)
goto done;
if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
{
- LPSERVICE_DESCRIPTIONW lpServiceDescription;
-
- lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
+ LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
+ /* Modify the service description, if specified */
if (lpServiceDescription != NULL &&
lpServiceDescription->lpDescription != NULL)
{
- DPRINT("Setting value %S\n", lpServiceDescription->lpDescription);
- dwError = RegSetValueExW(hServiceKey,
- L"Description",
- 0,
- REG_SZ,
- (LPBYTE)lpServiceDescription->lpDescription,
- (wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR));
- if (dwError != ERROR_SUCCESS)
- goto done;
+ /* If the description is "" then we delete it */
+ if (*lpServiceDescription->lpDescription == 0)
+ {
+ DPRINT("Delete service description\n");
+ dwError = RegDeleteValueW(hServiceKey, L"Description");
+
+ if (dwError == ERROR_FILE_NOT_FOUND)
+ dwError = ERROR_SUCCESS;
+ }
+ else
+ {
+ DPRINT("Setting service description value %S\n", lpServiceDescription->lpDescription);
+ dwError = RegSetValueExW(hServiceKey,
+ L"Description",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpServiceDescription->lpDescription,
+ (wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR));
+ }
+ }
+ else
+ {
+ dwError = ERROR_SUCCESS;
}
}
else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
- UNIMPLEMENTED;
- dwError = ERROR_CALL_NOT_IMPLEMENTED;
- goto done;
+ dwError = ScmSetFailureActions(hSvc,
+ lpService,
+ hServiceKey,
+ (LPSERVICE_FAILURE_ACTIONSW)Info.psfa);
}
done:
- /* Unlock the service database */
- ScmUnlockDatabase();
-
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
+ /* Unlock the service database */
+ ScmUnlockDatabase();
+
DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError);
return dwError;
else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
LPSERVICE_FAILURE_ACTIONSA lpFailureActions = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
- LPSTR lpStr;
+ LPSTR lpStr = NULL;
/* Query value length */
- dwRequiredSize = 0;
dwError = RegQueryValueExW(hServiceKey,
L"FailureActions",
NULL,
&dwType,
NULL,
&dwRequiredSize);
- if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
- goto done;
-
- if (dwType != REG_BINARY)
- {
- dwError = ERROR_UNSUPPORTED_TYPE;
+ if (dwError != ERROR_SUCCESS &&
+ dwError != ERROR_MORE_DATA &&
+ dwError != ERROR_FILE_NOT_FOUND)
goto done;
- }
- dwRequiredSize = max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize);
+ dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize)
+ : sizeof(SERVICE_FAILURE_ACTIONSA);
- dwError = ScmReadString(hServiceKey,
- L"FailureCommand",
- &lpFailureCommandW);
+ /* Get the strings */
+ ScmReadString(hServiceKey,
+ L"FailureCommand",
+ &lpFailureCommandW);
- dwError = ScmReadString(hServiceKey,
- L"RebootMessage",
- &lpRebootMessageW);
+ ScmReadString(hServiceKey,
+ L"RebootMessage",
+ &lpRebootMessageW);
if (lpRebootMessageW)
dwRequiredSize += (wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR);
}
/* Now we can fill the buffer */
- dwError = RegQueryValueExW(hServiceKey,
- L"FailureActions",
- NULL,
- NULL,
- (LPBYTE)lpFailureActions,
- &dwRequiredSize);
- if (dwError != ERROR_SUCCESS)
- goto done;
+ if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY)
+ {
+ dwError = RegQueryValueExW(hServiceKey,
+ L"FailureActions",
+ NULL,
+ NULL,
+ (LPBYTE)lpFailureActions,
+ &dwRequiredSize);
+ if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
+ goto done;
- if ((dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA)) ||
- (dwRequiredSize > cbBufSize))
+ if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA))
+ dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSA);
+ }
+ else
{
- dwError = ERROR_BUFFER_OVERFLOW;
- goto done;
+ /*
+ * The value of the error doesn't really matter, the only
+ * important thing is that it must be != ERROR_SUCCESS .
+ */
+ dwError = ERROR_INVALID_DATA;
}
if (dwError == ERROR_SUCCESS)
{
- lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - FIELD_OFFSET(SERVICE_FAILURE_ACTIONSA, lpsaActions)) / sizeof(SC_ACTION));
- lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0) ? (LPSC_ACTION)(lpFailureActions + 1) : NULL;
+ lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSA)) / sizeof(SC_ACTION));
+
+ /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
+ lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSA) : NULL);
+
lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
}
else
else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
- LPWSTR lpStr;
+ LPWSTR lpStr = NULL;
/* Query value length */
- dwRequiredSize = 0;
dwError = RegQueryValueExW(hServiceKey,
L"FailureActions",
NULL,
&dwType,
NULL,
&dwRequiredSize);
- if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
+ if (dwError != ERROR_SUCCESS &&
+ dwError != ERROR_MORE_DATA &&
+ dwError != ERROR_FILE_NOT_FOUND)
goto done;
- if (dwType != REG_BINARY)
- {
- dwError = ERROR_UNSUPPORTED_TYPE;
- goto done;
- }
-
- dwRequiredSize = max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize);
+ dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
+ : sizeof(SERVICE_FAILURE_ACTIONSW);
- dwError = ScmReadString(hServiceKey,
- L"FailureCommand",
- &lpFailureCommand);
+ /* Get the strings */
+ ScmReadString(hServiceKey,
+ L"FailureCommand",
+ &lpFailureCommand);
- dwError = ScmReadString(hServiceKey,
- L"RebootMessage",
- &lpRebootMessage);
+ ScmReadString(hServiceKey,
+ L"RebootMessage",
+ &lpRebootMessage);
if (lpRebootMessage)
dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
}
/* Now we can fill the buffer */
- dwError = RegQueryValueExW(hServiceKey,
- L"FailureActions",
- NULL,
- NULL,
- (LPBYTE)lpFailureActions,
- &dwRequiredSize);
- if (dwError != ERROR_SUCCESS)
- goto done;
+ if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY)
+ {
+ dwError = RegQueryValueExW(hServiceKey,
+ L"FailureActions",
+ NULL,
+ NULL,
+ (LPBYTE)lpFailureActions,
+ &dwRequiredSize);
+ if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND)
+ goto done;
- if ((dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) ||
- (dwRequiredSize > cbBufSize))
+ if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW))
+ dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+ }
+ else
{
- dwError = ERROR_BUFFER_OVERFLOW;
- goto done;
+ /*
+ * The value of the error doesn't really matter, the only
+ * important thing is that it must be != ERROR_SUCCESS .
+ */
+ dwError = ERROR_INVALID_DATA;
}
if (dwError == ERROR_SUCCESS)
{
- lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - FIELD_OFFSET(SERVICE_FAILURE_ACTIONSW, lpsaActions)) / sizeof(SC_ACTION));
- lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(lpFailureActions + 1) : NULL);
+ lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION));
+
+ /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */
+ lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSW) : NULL);
+
lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
}
else
LPCSTR pszGroupName)
{
LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
+ LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW;
LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
LPWSTR lpStringPtrW;
LPSTR lpStringPtrA;
if (*lpServicesReturned == 0)
goto Done;
+ lpStatusPtrIncrW = lpStatusPtrW;
lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer;
lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
*lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
/* Copy the status information */
memcpy(&lpStatusPtrA->ServiceStatusProcess,
- &lpStatusPtrW->ServiceStatusProcess,
+ &lpStatusPtrIncrW->ServiceStatusProcess,
sizeof(SERVICE_STATUS));
- lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrW->ServiceStatusProcess.dwProcessId; /* FIXME */
+ lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId; /* FIXME */
lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
+
+ lpStatusPtrIncrW++;
lpStatusPtrA++;
}
-Done:;
+Done:
if (pszGroupNameW)
HeapFree(GetProcessHeap(), 0, pszGroupNameW);
*lpServicesReturned = 0;
if ((dwServiceType == 0) ||
- ((dwServiceType & ~(SERVICE_DRIVER | SERVICE_WIN32)) != 0))
+ ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
{
DPRINT("Not a valid Service Type!\n");
return ERROR_INVALID_PARAMETER;
}
- if ((dwServiceState != SERVICE_ACTIVE) &&
- (dwServiceState != SERVICE_INACTIVE) &&
- (dwServiceState != SERVICE_STATE_ALL))
+ if ((dwServiceState == 0) ||
+ ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
{
DPRINT("Not a valid Service State!\n");
return ERROR_INVALID_PARAMETER;
*lpResumeIndex = 0;
}
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();