DWORD dwFreeTag = 0;
DWORD dwTagUsedBase = 1;
BOOLEAN TagUsed[TAG_ARRAY_SIZE];
- DWORD dwTagOffset;
+ INT nTagOffset;
DWORD i;
DWORD cbDataSize;
PLIST_ENTRY ServiceEntry;
/* mark tags in GroupOrderList as used */
for (i = 1; i <= dwGroupTagCount; i++)
{
- dwTagOffset = pdwGroupTags[i] - dwTagUsedBase;
- if (dwTagOffset >= 0 && dwTagOffset < TAG_ARRAY_SIZE)
- TagUsed[dwTagOffset] = TRUE;
+ nTagOffset = pdwGroupTags[i] - dwTagUsedBase;
+ if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE)
+ TagUsed[nTagOffset] = TRUE;
}
/* mark tags in service list as used */
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if (CurrentService->lpGroup == lpService->lpGroup)
{
- dwTagOffset = CurrentService->dwTag - dwTagUsedBase;
- if (dwTagOffset >= 0 && dwTagOffset < TAG_ARRAY_SIZE)
- TagUsed[dwTagOffset] = TRUE;
+ nTagOffset = CurrentService->dwTag - dwTagUsedBase;
+ if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE)
+ TagUsed[nTagOffset] = TRUE;
}
ServiceEntry = ServiceEntry->Flink;
}
dwTagUsedBase += TAG_ARRAY_SIZE;
- }
- while (!dwFreeTag);
+ } while (!dwFreeTag);
cleanup:
if (pdwGroupTags)
DPRINT("ScmConvertToBootPathName %S\n", CanonName);
+ if (!RelativeName)
+ return ERROR_INVALID_PARAMETER;
+
+ *RelativeName = NULL;
+
ServiceNameLen = wcslen(CanonName);
/* First check, if it's already good */
return ERROR_NOT_ENOUGH_MEMORY;
}
- /* Convert to NY-style path */
+ /* Convert to NT-style path */
if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL))
{
DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
NtPathName.Length + sizeof(UNICODE_NULL));
if (!Expanded)
{
- DPRINT("Error allocating memory for boot driver name!\n");
- return ERROR_NOT_ENOUGH_MEMORY;
+ DPRINT("Error allocating memory for boot driver name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
}
ExpandedLen = NtPathName.Length / sizeof(WCHAR);
if (BufferSize > 0xFFFD)
{
DPRINT("Too large buffer required\n");
- *RelativeName = 0;
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
HeapFree(GetProcessHeap(), 0, Expanded);
}
else
{
+ /* Failure */
DPRINT("Error, Status = %08X\n", Status);
HeapFree(GetProcessHeap(), 0, Expanded);
return ERROR_INVALID_PARAMETER;
}
-
- /* Failure */
- *RelativeName = NULL;
- return ERROR_INVALID_PARAMETER;
}
+
DWORD
ScmCanonDriverImagePath(DWORD dwStartType,
const wchar_t *lpServiceName,
return ERROR_INVALID_HANDLE;
}
-
/* Check the service entry point */
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
DesiredAccess = SERVICE_PAUSE_CONTINUE;
break;
- case SERVICE_INTERROGATE:
+ case SERVICE_CONTROL_INTERROGATE:
DesiredAccess = SERVICE_INTERROGATE;
break;
DesiredAccess))
return ERROR_ACCESS_DENIED;
+ /* Return the current service status information */
+ RtlCopyMemory(lpServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
if (dwControl == SERVICE_CONTROL_STOP)
{
/* Check if the service has dependencies running as windows
dwControlsAccepted = lpService->Status.dwControlsAccepted;
dwCurrentState = lpService->Status.dwCurrentState;
+ /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */
+ if (lpService->lpImage == NULL || dwCurrentState == SERVICE_STOPPED)
+ return ERROR_SERVICE_NOT_ACTIVE;
+
/* Check the current state before sending a control request */
switch (dwCurrentState)
{
sizeof(SERVICE_STATUS));
}
- if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
- dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
-
return dwError;
}
LPSERVICE_STATUS lpServiceStatus)
{
PSERVICE lpService;
+ DWORD dwPreviousState;
+ LPCWSTR lpErrorStrings[2];
+ WCHAR szErrorBuffer[32];
DPRINT("RSetServiceStatus() called\n");
DPRINT("hServiceStatus = %p\n", hServiceStatus);
/* Lock the service database exclusively */
ScmLockDatabaseExclusive();
+ /* Save the current service state */
+ dwPreviousState = lpService->Status.dwCurrentState;
+
RtlCopyMemory(&lpService->Status,
lpServiceStatus,
sizeof(SERVICE_STATUS));
/* Unlock the service database */
ScmUnlockDatabase();
+ /* Log a failed service stop */
+ if ((lpServiceStatus->dwCurrentState == SERVICE_STOPPED) &&
+ (dwPreviousState != SERVICE_STOPPED))
+ {
+ if (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS)
+ {
+ swprintf(szErrorBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
+ lpErrorStrings[0] = lpService->lpDisplayName;
+ lpErrorStrings[1] = szErrorBuffer;
+
+ ScmLogError(EVENT_SERVICE_EXIT_FAILED,
+ 2,
+ lpErrorStrings);
+ }
+ }
+
DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
DPRINT("RSetServiceStatus() done\n");
/* Unlock the service database */
ScmUnlockDatabase();
- /* check if it is marked for deletion */
+ /* Check if it is marked for deletion */
if (lpService->bDeleted)
return ERROR_SERVICE_MARKED_FOR_DELETE;
+
/* Return Error exist */
return ERROR_SERVICE_EXISTS;
}
LPBOUNDED_DWORD_256K lpServicesReturned,
LPBOUNDED_DWORD_256K lpResumeHandle)
{
- 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_STATUSW lpStatusPtr;
- LPWSTR lpStringPtr;
-
- DPRINT("REnumServicesStatusW() called\n");
-
- if (ScmShutdown)
- return ERROR_SHUTDOWN_IN_PROGRESS;
-
- hManager = ScmGetServiceManagerFromHandle(hSCManager);
- if (hManager == NULL)
- {
- DPRINT1("Invalid service manager handle!\n");
- return ERROR_INVALID_HANDLE;
- }
-
-
- *pcbBytesNeeded = 0;
- *lpServicesReturned = 0;
-
- if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
- {
- DPRINT("Not a valid Service Type!\n");
- return ERROR_INVALID_PARAMETER;
- }
-
- if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
- {
- DPRINT("Not a valid Service State!\n");
- return ERROR_INVALID_PARAMETER;
- }
-
- /* Check access rights */
- if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
- SC_MANAGER_ENUMERATE_SERVICE))
- {
- DPRINT("Insufficient access rights! 0x%lx\n",
- hManager->Handle.DesiredAccess);
- return ERROR_ACCESS_DENIED;
- }
-
- if (lpResumeHandle)
- dwLastResumeCount = *lpResumeHandle;
-
- /* Lock the service database shared */
- ScmLockDatabaseShared();
-
- 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;
-
- dwSize = sizeof(ENUM_SERVICE_STATUSW) +
- ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
- ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
-
- if (dwRequiredSize + dwSize > dwBufSize)
- {
- DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
- break;
- }
-
- DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
- dwRequiredSize += dwSize;
- dwServiceCount++;
- dwLastResumeCount = CurrentService->dwResumeCount;
- }
-
- 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;
-
- dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
- ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
- ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
-
- dwError = ERROR_MORE_DATA;
- }
-
- DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
-
- if (lpResumeHandle)
- *lpResumeHandle = dwLastResumeCount;
-
- *lpServicesReturned = dwServiceCount;
- *pcbBytesNeeded = dwRequiredSize;
-
- lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
- lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
- dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
-
- 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;
-
- dwSize = sizeof(ENUM_SERVICE_STATUSW) +
- ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
- ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
-
- if (dwRequiredSize + dwSize > dwBufSize)
- break;
-
- /* Copy the service name */
- wcscpy(lpStringPtr, CurrentService->lpServiceName);
- lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
- lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
-
- /* Copy the display name */
- wcscpy(lpStringPtr, CurrentService->lpDisplayName);
- lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
- lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
-
- /* Copy the status information */
- memcpy(&lpStatusPtr->ServiceStatus,
- &CurrentService->Status,
- sizeof(SERVICE_STATUS));
-
- lpStatusPtr++;
- dwRequiredSize += dwSize;
- }
-
- if (dwError == 0)
- {
- *pcbBytesNeeded = 0;
- if (lpResumeHandle) *lpResumeHandle = 0;
- }
-
-Done:;
- /* Unlock the service database */
- ScmUnlockDatabase();
-
- DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError);
-
- return dwError;
+ /* Enumerate all the services, not regarding of their group */
+ return REnumServiceGroupW(hSCManager,
+ dwServiceType,
+ dwServiceState,
+ lpBuffer,
+ dwBufSize,
+ pcbBytesNeeded,
+ lpServicesReturned,
+ lpResumeHandle,
+ NULL);
}
lpConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
if (lpDependencies != NULL)
- lpStr += dwDependenciesLength * sizeof(WCHAR);
+ lpStr += dwDependenciesLength;
else
lpStr += (wcslen(lpStr) + 1);
&lpDependencies,
&dwDependenciesLength);
- dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
+ dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGA);
if (lpImagePath != NULL)
dwRequiredSize += wcslen(lpImagePath) + 1;
lpStr = (LPSTR)(lpServiceConfig + 1);
/* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
- Verified in WINXP*/
+ Verified in WINXP */
if (lpImagePath)
{
LPBOUNDED_DWORD_256K lpResumeIndex,
LPCWSTR pszGroupName)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
+ 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_STATUSW lpStatusPtr;
+ LPWSTR lpStringPtr;
+ DPRINT("REnumServiceGroupW() called\n");
-//
-// WARNING: This function is untested
-//
-/* Function 36 */
-DWORD RChangeServiceConfig2A(
- SC_RPC_HANDLE hService,
- SC_RPC_CONFIG_INFOA Info)
-{
- SC_RPC_CONFIG_INFOW InfoW;
- DWORD dwRet, dwLength;
- PVOID ptr = NULL;
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
- DPRINT("RChangeServiceConfig2A() called\n");
- DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
- InfoW.dwInfoLevel = Info.dwInfoLevel;
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
+
+ if ((dwServiceType == 0) ||
+ ((dwServiceType & ~(SERVICE_DRIVER | SERVICE_WIN32)) != 0))
+ {
+ DPRINT("Not a valid Service Type!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceState != SERVICE_ACTIVE) &&
+ (dwServiceState != SERVICE_INACTIVE) &&
+ (dwServiceState != SERVICE_STATE_ALL))
+ {
+ DPRINT("Not a valid Service State!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hManager->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ if (lpResumeIndex)
+ dwLastResumeCount = *lpResumeIndex;
+
+ /* Lock the service database shared */
+ ScmLockDatabaseShared();
+
+ 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 (*pszGroupName == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
+ continue;
+ }
+ }
+
+ dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize > cbBufSize)
+ {
+ DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
+ break;
+ }
+
+ DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
+ dwRequiredSize += dwSize;
+ dwServiceCount++;
+ dwLastResumeCount = CurrentService->dwResumeCount;
+ }
+
+ 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 (*pszGroupName == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
+ continue;
+ }
+ }
+
+ dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+
+ dwError = ERROR_MORE_DATA;
+ }
+
+ DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+ if (lpResumeIndex)
+ *lpResumeIndex = dwLastResumeCount;
+
+ *lpServicesReturned = dwServiceCount;
+ *pcbBytesNeeded = dwRequiredSize;
+
+ lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
+ lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
+ dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
+
+ 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 (*pszGroupName == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
+ continue;
+ }
+ }
+
+ dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize > cbBufSize)
+ break;
+
+ /* Copy the service name */
+ wcscpy(lpStringPtr, CurrentService->lpServiceName);
+ lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+ /* Copy the display name */
+ wcscpy(lpStringPtr, CurrentService->lpDisplayName);
+ lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+
+ /* Copy the status information */
+ memcpy(&lpStatusPtr->ServiceStatus,
+ &CurrentService->Status,
+ sizeof(SERVICE_STATUS));
+
+ lpStatusPtr++;
+ dwRequiredSize += dwSize;
+ }
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeIndex) *lpResumeIndex = 0;
+ }
+
+Done:
+ /* Unlock the service database */
+ ScmUnlockDatabase();
+
+ DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+//
+// WARNING: This function is untested
+//
+/* Function 36 */
+DWORD RChangeServiceConfig2A(
+ SC_RPC_HANDLE hService,
+ SC_RPC_CONFIG_INFOA Info)
+{
+ SC_RPC_CONFIG_INFOW InfoW;
+ DWORD dwRet, dwLength;
+ PVOID ptr = NULL;
+
+ DPRINT("RChangeServiceConfig2A() called\n");
+ DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+
+ InfoW.dwInfoLevel = Info.dwInfoLevel;
if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
{
LPSERVICE_DESCRIPTIONW lpServiceDescription;
lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
- lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpServiceDescription + sizeof(LPSERVICE_DESCRIPTIONW));
if (lpServiceDescription != NULL &&
lpServiceDescription->lpDescription != NULL)
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
HKEY hServiceKey = NULL;
+ DWORD dwRequiredSize = 0;
+ DWORD dwType = 0;
LPWSTR lpDescriptionW = NULL;
- LPSTR lpDescription = NULL;
+ LPWSTR lpRebootMessageW = NULL;
+ LPWSTR lpFailureCommandW = NULL;
DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
{
lpServiceDescription->lpDescription = NULL;
dwError = ERROR_SUCCESS;
- goto done;
}
}
- else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
+ else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
- UNIMPLEMENTED;
- dwError = ERROR_CALL_NOT_IMPLEMENTED;
- goto done;
+ LPSERVICE_FAILURE_ACTIONSA lpFailureActions = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
+ LPSTR lpStr = NULL;
+
+ /* 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)
+ goto done;
+
+ dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize)
+ : sizeof(SERVICE_FAILURE_ACTIONSA);
+
+ /* Get the strings */
+ ScmReadString(hServiceKey,
+ L"FailureCommand",
+ &lpFailureCommandW);
+
+ ScmReadString(hServiceKey,
+ L"RebootMessage",
+ &lpRebootMessageW);
+
+ if (lpRebootMessageW)
+ dwRequiredSize += (wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR);
+
+ if (lpFailureCommandW)
+ dwRequiredSize += (wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR);
+
+ if (cbBufSize < dwRequiredSize)
+ {
+ *pcbBytesNeeded = dwRequiredSize;
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ goto done;
+ }
+
+ /* Now we can fill the buffer */
+ if (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 = sizeof(SERVICE_FAILURE_ACTIONSA);
+ }
+ else
+ {
+ dwError = ERROR_UNSUPPORTED_TYPE;
+ }
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ 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
+ {
+ lpFailureActions->dwResetPeriod = 0;
+ lpFailureActions->cActions = 0;
+ lpFailureActions->lpsaActions = NULL;
+ lpStr = (LPSTR)(lpFailureActions + 1);
+ }
+
+ lpFailureActions->lpRebootMsg = NULL;
+ lpFailureActions->lpCommand = NULL;
+
+ if (lpRebootMessageW)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpRebootMessageW,
+ -1,
+ lpStr,
+ wcslen(lpRebootMessageW),
+ NULL,
+ NULL);
+ lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
+ lpStr += strlen(lpStr) + 1;
+ }
+
+ if (lpFailureCommandW)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpFailureCommandW,
+ -1,
+ lpStr,
+ wcslen(lpFailureCommandW),
+ NULL,
+ NULL);
+ lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
+ /* lpStr += strlen(lpStr) + 1; */
+ }
+
+ dwError = ERROR_SUCCESS;
}
done:
/* Unlock the service database */
ScmUnlockDatabase();
- if (lpDescription != NULL)
- HeapFree(GetProcessHeap(), 0, lpDescription);
+ if (lpDescriptionW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDescriptionW);
+
+ if (lpRebootMessageW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpRebootMessageW);
+
+ if (lpFailureCommandW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpFailureCommandW);
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
- DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
+ DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError);
return dwError;
}
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
HKEY hServiceKey = NULL;
- DWORD dwRequiredSize;
+ DWORD dwRequiredSize = 0;
+ DWORD dwType = 0;
LPWSTR lpDescription = NULL;
- LPWSTR lpFailureCommand = NULL;
LPWSTR lpRebootMessage = NULL;
+ LPWSTR lpFailureCommand = NULL;
DPRINT("RQueryServiceConfig2W() called\n");
}
else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
- LPWSTR lpStr;
LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
+ LPWSTR lpStr = NULL;
- UNIMPLEMENTED;
-
- dwError = ScmReadString(hServiceKey,
- L"FailureCommand",
- &lpFailureCommand);
+ /* 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)
+ goto done;
- dwError = ScmReadString(hServiceKey,
- L"RebootMessage",
- &lpRebootMessage);
+ dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
+ : sizeof(SERVICE_FAILURE_ACTIONSW);
- dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+ /* Get the strings */
+ ScmReadString(hServiceKey,
+ L"FailureCommand",
+ &lpFailureCommand);
- if (lpFailureCommand)
- dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR);
+ ScmReadString(hServiceKey,
+ L"RebootMessage",
+ &lpRebootMessage);
if (lpRebootMessage)
dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
+ if (lpFailureCommand)
+ dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR);
+
if (cbBufSize < dwRequiredSize)
{
*pcbBytesNeeded = dwRequiredSize;
goto done;
}
- lpFailureActions->cActions = 0;
- lpFailureActions->dwResetPeriod = 0;
- lpFailureActions->lpCommand = NULL;
+ /* Now we can fill the buffer */
+ if (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 = sizeof(SERVICE_FAILURE_ACTIONSW);
+ }
+ else
+ {
+ dwError = ERROR_UNSUPPORTED_TYPE;
+ }
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ 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
+ {
+ lpFailureActions->dwResetPeriod = 0;
+ lpFailureActions->cActions = 0;
+ lpFailureActions->lpsaActions = NULL;
+ lpStr = (LPWSTR)(lpFailureActions + 1);
+ }
+
lpFailureActions->lpRebootMsg = NULL;
- lpFailureActions->lpsaActions = NULL;
+ lpFailureActions->lpCommand = NULL;
- lpStr = (LPWSTR)(lpFailureActions + 1);
if (lpRebootMessage)
{
wcscpy(lpStr, lpRebootMessage);
- lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage);
- lpStr += wcslen(lpRebootMessage) + 1;
+ lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
+ lpStr += wcslen(lpStr) + 1;
}
if (lpFailureCommand)
{
wcscpy(lpStr, lpFailureCommand);
- lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand);
- lpStr += wcslen(lpRebootMessage) + 1;
+ lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
+ /* lpStr += wcslen(lpStr) + 1; */
}
- dwError = STATUS_SUCCESS;
- goto done;
+
+ dwError = ERROR_SUCCESS;
}
done:
*pcbBytesNeeded = 0;
*lpServicesReturned = 0;
- if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+ if ((dwServiceType == 0) ||
+ ((dwServiceType & ~(SERVICE_DRIVER | SERVICE_WIN32)) != 0))
{
DPRINT("Not a valid Service Type!\n");
return ERROR_INVALID_PARAMETER;
}
- if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+ if ((dwServiceState != SERVICE_ACTIVE) &&
+ (dwServiceState != SERVICE_INACTIVE) &&
+ (dwServiceState != SERVICE_STATE_ALL))
{
DPRINT("Not a valid Service State!\n");
return ERROR_INVALID_PARAMETER;
else
{
if ((CurrentService->lpGroup == NULL) ||
- _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
continue;
}
}
else
{
if ((CurrentService->lpGroup == NULL) ||
- _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
continue;
}
}
else
{
if ((CurrentService->lpGroup == NULL) ||
- _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
continue;
}
}
void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject)
{
+ /* Close the handle */
+ RCloseServiceHandle(&hSCObject);
}
void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock)
{
+ /* Unlock the database */
+ RUnlockServiceDatabase(&Lock);
}