#include "services.h"
+#include <winnls.h>
+
#define NDEBUG
#include <debug.h>
if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
goto findFreeTag;
- pdwGroupTags = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
+ pdwGroupTags = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDataSize);
if (!pdwGroupTags)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
DWORD
ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
{
- DWORD ServiceNameLen, BufferSize, ExpandedLen;
+ SIZE_T ServiceNameLen, ExpandedLen;
+ DWORD BufferSize;
WCHAR Dest;
WCHAR *Expanded;
UNICODE_STRING NtPathName, SystemRoot, LinkTarget;
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;
}
const wchar_t *lpServiceName,
wchar_t **lpCanonName)
{
- DWORD ServiceNameLen, Result;
+ DWORD Result;
+ SIZE_T ServiceNameLen;
UNICODE_STRING NtServiceName;
WCHAR *RelativeName;
const WCHAR *SourceName = lpServiceName;
{
/* Calculate the required size */
dwRequiredSize += sizeof(SERVICE_STATUS);
- dwRequiredSize += ((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
- dwRequiredSize += ((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+ dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
+ dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
/* Add the size for service name and display name pointers */
dwRequiredSize += (2 * sizeof(PVOID));
}
}
- dwDependServiceStrPtr += (wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
+ dwDependServiceStrPtr += (DWORD)(wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
}
}
else if (*pcbBytesNeeded)
DWORD dwControlsAccepted;
DWORD dwCurrentState;
HKEY hServicesKey = NULL;
+ LPCWSTR lpErrorStrings[2];
DPRINT("RControlService() called\n");
DesiredAccess = SERVICE_PAUSE_CONTINUE;
break;
- case SERVICE_INTERROGATE:
+ case SERVICE_CONTROL_INTERROGATE:
DesiredAccess = SERVICE_INTERROGATE;
break;
sizeof(SERVICE_STATUS));
}
- if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
- dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
+ if (dwError == ERROR_SUCCESS)
+ {
+ if (dwControl != SERVICE_CONTROL_INTERROGATE)
+ {
+ /* Log a sucessful send control */
+ lpErrorStrings[0] = lpService->lpDisplayName;
+
+ switch(dwControl)
+ {
+ case SERVICE_CONTROL_STOP:
+ lpErrorStrings[1] = L"stop";
+ break;
+
+ case SERVICE_CONTROL_PAUSE:
+ lpErrorStrings[1] = L"pause";
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ lpErrorStrings[1] = L"continue";
+ break;
+
+ default:
+ lpErrorStrings[1] = L"other";
+ break;
+ }
+
+ ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS,
+ EVENTLOG_INFORMATION_TYPE,
+ 2,
+ lpErrorStrings);
+ }
+ }
return dwError;
}
dwError = ScmMarkServiceForDelete(lpService);
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
DPRINT("RLockServiceDatabase() called\n");
- *lpLock = 0;
+ *lpLock = NULL;
hMgr = ScmGetServiceManagerFromHandle(hSCManager);
if (hMgr == NULL)
SC_MANAGER_LOCK))
return ERROR_ACCESS_DENIED;
-// return ScmLockDatabase(0, hMgr->0xC, hLock);
-
- /* FIXME: Lock the database */
- *lpLock = (SC_RPC_LOCK)0x12345678; /* Dummy! */
-
- return ERROR_SUCCESS;
+ return ScmAcquireServiceStartLock(FALSE, lpLock);
}
{
PSERVICE lpService;
DWORD dwPreviousState;
+ DWORD dwPreviousType;
LPCWSTR lpErrorStrings[2];
WCHAR szErrorBuffer[32];
DPRINT("RSetServiceStatus() called\n");
- DPRINT("hServiceStatus = %p\n", hServiceStatus);
- DPRINT("dwServiceType = %lu\n", lpServiceStatus->dwServiceType);
+ DPRINT("hServiceStatus = %lu\n", hServiceStatus);
+ DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus->dwServiceType);
DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState);
DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted);
DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode);
}
lpService = (PSERVICE)hServiceStatus;
- if (lpService == NULL)
- {
- DPRINT("lpService == NULL!\n");
- return ERROR_INVALID_HANDLE;
- }
/* Check current state */
if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState))
return ERROR_INVALID_DATA;
}
+ /* Set the wait hint and check point only if the service is in a pending state,
+ otherwise they should be 0 */
+ if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED ||
+ lpServiceStatus->dwCurrentState == SERVICE_PAUSED ||
+ lpServiceStatus->dwCurrentState == SERVICE_RUNNING)
+ {
+ lpServiceStatus->dwWaitHint = 0;
+ lpServiceStatus->dwCheckPoint = 0;
+ }
+
/* Lock the service database exclusively */
ScmLockDatabaseExclusive();
/* Save the current service state */
dwPreviousState = lpService->Status.dwCurrentState;
+ /* Save the current service type */
+ dwPreviousType = lpService->Status.dwServiceType;
+
+ /* Update the service status */
RtlCopyMemory(&lpService->Status,
lpServiceStatus,
sizeof(SERVICE_STATUS));
+ /* Restore the previous service type */
+ lpService->Status.dwServiceType = dwPreviousType;
+
/* Unlock the service database */
ScmUnlockDatabase();
- /* Log a failed service stop */
if ((lpServiceStatus->dwCurrentState == SERVICE_STOPPED) &&
- (dwPreviousState != SERVICE_STOPPED))
+ (dwPreviousState != SERVICE_STOPPED) &&
+ (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS))
{
- if (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS)
+ /* Log a failed service stop */
+ swprintf(szErrorBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
+ lpErrorStrings[0] = lpService->lpDisplayName;
+ lpErrorStrings[1] = szErrorBuffer;
+
+ ScmLogEvent(EVENT_SERVICE_EXIT_FAILED,
+ EVENTLOG_ERROR_TYPE,
+ 2,
+ lpErrorStrings);
+ }
+ else if (lpServiceStatus->dwCurrentState != dwPreviousState &&
+ (lpServiceStatus->dwCurrentState == SERVICE_STOPPED ||
+ lpServiceStatus->dwCurrentState == SERVICE_RUNNING ||
+ lpServiceStatus->dwCurrentState == SERVICE_PAUSED))
+ {
+ /* Log a successful service status change */
+ lpErrorStrings[0] = lpService->lpDisplayName;
+
+ switch(lpServiceStatus->dwCurrentState)
{
- swprintf(szErrorBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
- lpErrorStrings[0] = lpService->lpDisplayName;
- lpErrorStrings[1] = szErrorBuffer;
+ case SERVICE_STOPPED:
+ lpErrorStrings[1] = L"stopped";
+ break;
+
+ case SERVICE_RUNNING:
+ lpErrorStrings[1] = L"running";
+ break;
- ScmLogError(EVENT_SERVICE_EXIT_FAILED,
- 2,
- lpErrorStrings);
+ case SERVICE_PAUSED:
+ lpErrorStrings[1] = L"paused";
+ break;
}
+
+ ScmLogEvent(EVENT_SERVICE_STATUS_SUCCESS,
+ EVENTLOG_INFORMATION_TYPE,
+ 2,
+ lpErrorStrings);
}
DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
DWORD RUnlockServiceDatabase(
LPSC_RPC_LOCK Lock)
{
- UNIMPLEMENTED;
- return ERROR_SUCCESS;
+ DPRINT("RUnlockServiceDatabase(%p)\n", Lock);
+ return ScmReleaseServiceStartLock(Lock);
}
LPWSTR lpImagePathW = NULL;
DPRINT("RChangeServiceConfigW() called\n");
- DPRINT("dwServiceType = %lu\n", dwServiceType);
+ DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
DPRINT("dwStartType = %lu\n", dwStartType);
DPRINT("dwErrorControl = %lu\n", dwErrorControl);
DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
0,
REG_SZ,
(LPBYTE)lpDisplayName,
- (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR)));
/* Update the display name */
lpDisplayNameW = HeapAlloc(GetProcessHeap(),
- 0,
+ HEAP_ZERO_MEMORY,
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
if (lpDisplayNameW == NULL)
{
0,
REG_EXPAND_SZ,
(LPBYTE)lpImagePathW,
- (wcslen(lpImagePathW) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpImagePathW) + 1) * sizeof(WCHAR)));
if (lpImagePathW != lpBinaryPathName)
HeapFree(GetProcessHeap(), 0, lpImagePathW);
0,
REG_SZ,
(LPBYTE)lpLoadOrderGroup,
- (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
if (lpPassword != NULL)
{
- /* FIXME: Write password */
+ /* FIXME: Decrypt and write password */
}
done:
DPRINT("lpServiceName = %S\n", lpServiceName);
DPRINT("lpDisplayName = %S\n", lpDisplayName);
DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
- DPRINT("dwServiceType = %lu\n", dwServiceType);
+ DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
DPRINT("dwStartType = %lu\n", dwStartType);
DPRINT("dwErrorControl = %lu\n", dwErrorControl);
DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
*lpDisplayName != 0 &&
_wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
{
- lpService->lpDisplayName = HeapAlloc(GetProcessHeap(), 0,
+ lpService->lpDisplayName = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
if (lpService->lpDisplayName == NULL)
{
0,
REG_SZ,
(LPBYTE)lpDisplayName,
- (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR)));
}
/* Set the service type */
0,
REG_EXPAND_SZ,
(LPBYTE)lpBinaryPathName,
- (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
}
0,
REG_EXPAND_SZ,
(LPBYTE)lpImagePath,
- (wcslen(lpImagePath) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
}
0,
REG_SZ,
(LPBYTE)lpLoadOrderGroup,
- (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
}
0,
REG_SZ,
(LPBYTE)lpObjectName,
- (wcslen(lpObjectName) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpObjectName) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
}
if (lpPassword != NULL)
{
- /* FIXME: Write password */
+ /* FIXME: Decrypt and write password */
}
dwError = ScmCreateServiceHandle(lpService,
lpService->dwRefCount = 1;
DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount);
-done:;
+done:
/* Unlock the service database */
ScmUnlockDatabase();
/* Allocate memory for array of service pointers */
lpServicesArray = HeapAlloc(GetProcessHeap(),
- 0,
+ HEAP_ZERO_MEMORY,
(dwServicesReturned + 1) * sizeof(PSERVICE));
if (!lpServicesArray)
{
goto Done;
}
- lpServicesPtr = (LPENUM_SERVICE_STATUSW) lpServices;
+ lpServicesPtr = (LPENUM_SERVICE_STATUSW)lpServices;
lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW)));
/* Copy EnumDepenedentService to Buffer */
lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
lpStr += (wcslen(lpService->lpServiceName) + 1);
- lpServicesPtr ++;
+ lpServicesPtr++;
}
*lpServicesReturned = dwServicesReturned;
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 == 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 (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 == ERROR_SUCCESS)
- {
- *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);
}
*lpServiceHandle = (SC_RPC_HANDLE)hHandle;
DPRINT("*hService = %p\n", *lpServiceHandle);
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
LPWSTR lpDependencies = NULL;
DWORD dwDependenciesLength = 0;
DWORD dwRequiredSize;
- LPQUERY_SERVICE_CONFIGW lpConfig = NULL;
WCHAR lpEmptyString[] = {0,0};
LPWSTR lpStr;
dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
if (lpImagePath != NULL)
- dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
+ dwRequiredSize += (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
else
dwRequiredSize += 2 * sizeof(WCHAR);
- if (lpService->lpGroup != NULL)
- dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
+ if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
+ dwRequiredSize += (DWORD)((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
else
dwRequiredSize += 2 * sizeof(WCHAR);
dwRequiredSize += 2 * sizeof(WCHAR);
if (lpServiceStartName != NULL)
- dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
+ dwRequiredSize += (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
else
dwRequiredSize += 2 * sizeof(WCHAR);
if (lpService->lpDisplayName != NULL)
- dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
+ dwRequiredSize += (DWORD)((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
else
dwRequiredSize += 2 * sizeof(WCHAR);
}
else
{
- lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
- lpConfig->dwServiceType = lpService->Status.dwServiceType;
- lpConfig->dwStartType = lpService->dwStartType;
- lpConfig->dwErrorControl = lpService->dwErrorControl;
- lpConfig->dwTagId = lpService->dwTag;
+ lpServiceConfig->dwServiceType = lpService->Status.dwServiceType;
+ lpServiceConfig->dwStartType = lpService->dwStartType;
+ lpServiceConfig->dwErrorControl = lpService->dwErrorControl;
+ lpServiceConfig->dwTagId = lpService->dwTag;
- lpStr = (LPWSTR)(lpConfig + 1);
+ lpStr = (LPWSTR)(lpServiceConfig + 1);
/* Append the image path */
if (lpImagePath != NULL)
wcscpy(lpStr, lpEmptyString);
}
- lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
lpStr += (wcslen(lpStr) + 1);
/* Append the group name */
- if (lpService->lpGroup != NULL)
+ if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
{
wcscpy(lpStr, lpService->lpGroup->lpGroupName);
}
wcscpy(lpStr, lpEmptyString);
}
- lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
lpStr += (wcslen(lpStr) + 1);
/* Append Dependencies */
wcscpy(lpStr, lpEmptyString);
}
- lpConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
if (lpDependencies != NULL)
- lpStr += dwDependenciesLength * sizeof(WCHAR);
+ lpStr += dwDependenciesLength;
else
lpStr += (wcslen(lpStr) + 1);
wcscpy(lpStr, lpEmptyString);
}
- lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
lpStr += (wcslen(lpStr) + 1);
/* Append the display name */
wcscpy(lpStr, lpEmptyString);
}
- lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
if (pcbBytesNeeded != NULL)
*pcbBytesNeeded = dwRequiredSize;
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
/* Function 18 */
DWORD RQueryServiceLockStatusW(
SC_RPC_HANDLE hSCManager,
- LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
+ LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
DWORD cbBufSize,
LPBOUNDED_DWORD_4K pcbBytesNeeded)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
+ LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus = (LPQUERY_SERVICE_LOCK_STATUSW)lpBuf;
+ PMANAGER_HANDLE hMgr;
+ DWORD dwRequiredSize;
+ if (!lpLockStatus || !pcbBytesNeeded)
+ return ERROR_INVALID_PARAMETER;
-/* Function 19 */
-DWORD RStartServiceW(
- SC_RPC_HANDLE hService,
+ hMgr = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hMgr == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
+ SC_MANAGER_QUERY_LOCK_STATUS))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* FIXME: we need to compute instead the real length of the owner name */
+ dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSW) + sizeof(WCHAR);
+ *pcbBytesNeeded = dwRequiredSize;
+
+ if (cbBufSize < dwRequiredSize)
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ ScmQueryServiceLockStatusW(lpLockStatus);
+
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 19 */
+DWORD RStartServiceW(
+ SC_RPC_HANDLE hService,
DWORD argc,
LPSTRING_PTRSW argv)
{
DWORD dwError = ERROR_SUCCESS;
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
+
+#ifndef NDEBUG
DWORD i;
DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv);
{
for (i = 0; i < argc; i++)
{
- DPRINT(" argv[%lu]: %S\n", i, argv[i]);
+ DPRINT(" argv[%lu]: %S\n", i, argv[i].StringPtr);
}
}
+#endif
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
*lpcchBuffer = 2;
if (lpDisplayName != NULL)
{
- *lpDisplayName = '\0';
+ *lpDisplayName = 0;
}
}
if (!lpService->lpDisplayName)
{
- dwLength = wcslen(lpService->lpServiceName);
+ dwLength = (DWORD)wcslen(lpService->lpServiceName);
if (lpDisplayName != NULL &&
*lpcchBuffer > dwLength)
}
else
{
- dwLength = wcslen(lpService->lpDisplayName);
+ dwLength = (DWORD)wcslen(lpService->lpDisplayName);
if (lpDisplayName != NULL &&
*lpcchBuffer > dwLength)
*lpcchBuffer = 2;
if (lpServiceName != NULL)
{
- *lpServiceName = '\0';
+ *lpServiceName = 0;
}
}
return ERROR_SERVICE_DOES_NOT_EXIST;
}
- dwLength = wcslen(lpService->lpServiceName);
+ dwLength = (DWORD)wcslen(lpService->lpServiceName);
if (lpServiceName != NULL &&
*lpcchBuffer > dwLength)
LPSTR lpBinaryPathName,
LPSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
- LPSTR lpDependencies,
+ LPBYTE lpDependencies,
DWORD dwDependSize,
LPSTR lpServiceStartName,
LPBYTE lpPassword,
LPWSTR lpCanonicalImagePathW = NULL;
LPWSTR lpLoadOrderGroupW = NULL;
LPWSTR lpDependenciesW = NULL;
- // LPWSTR lpPasswordW = NULL;
DPRINT("RChangeServiceConfigA() called\n");
DPRINT("dwServiceType = %lu\n", dwServiceType);
{
/* Set the display name */
lpDisplayNameW = HeapAlloc(GetProcessHeap(),
- 0,
+ HEAP_ZERO_MEMORY,
(strlen(lpDisplayName) + 1) * sizeof(WCHAR));
if (lpDisplayNameW == NULL)
{
lpDisplayName,
-1,
lpDisplayNameW,
- strlen(lpDisplayName) + 1);
+ (int)(strlen(lpDisplayName) + 1));
RegSetValueExW(hServiceKey,
L"DisplayName",
0,
REG_SZ,
(LPBYTE)lpDisplayNameW,
- (wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR)));
/* Update lpService->lpDisplayName */
if (lpService->lpDisplayName)
{
/* Set the image path */
lpBinaryPathNameW = HeapAlloc(GetProcessHeap(),
- 0,
+ HEAP_ZERO_MEMORY,
(strlen(lpBinaryPathName) + 1) * sizeof(WCHAR));
if (lpBinaryPathNameW == NULL)
{
lpBinaryPathName,
-1,
lpBinaryPathNameW,
- strlen(lpBinaryPathName) + 1);
+ (int)(strlen(lpBinaryPathName) + 1));
if (lpService->Status.dwServiceType & SERVICE_DRIVER)
{
0,
REG_EXPAND_SZ,
(LPBYTE)lpBinaryPathNameW,
- (wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR)));
HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
{
lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(),
- 0,
+ HEAP_ZERO_MEMORY,
(strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
if (lpLoadOrderGroupW == NULL)
{
lpLoadOrderGroup,
-1,
lpLoadOrderGroupW,
- strlen(lpLoadOrderGroup) + 1);
+ (int)(strlen(lpLoadOrderGroup) + 1));
dwError = RegSetValueExW(hServiceKey,
L"Group",
0,
REG_SZ,
(LPBYTE)lpLoadOrderGroupW,
- (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
if (lpDependencies != NULL && *lpDependencies != 0)
{
lpDependenciesW = HeapAlloc(GetProcessHeap(),
- 0,
- (strlen(lpDependencies) + 1) * sizeof(WCHAR));
+ HEAP_ZERO_MEMORY,
+ (strlen((LPSTR)lpDependencies) + 1) * sizeof(WCHAR));
if (lpDependenciesW == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
MultiByteToWideChar(CP_ACP,
0,
- lpDependencies,
+ (LPSTR)lpDependencies,
dwDependSize,
lpDependenciesW,
- strlen(lpDependencies) + 1);
+ (int)(strlen((LPSTR)lpDependencies) + 1));
dwError = ScmWriteDependencies(hServiceKey,
(LPWSTR)lpDependenciesW,
if (lpPassword != NULL)
{
- /* FIXME: Write password */
+ /* FIXME: Decrypt and write password */
}
done:
LPWSTR lpDependenciesW = NULL;
LPWSTR lpServiceStartNameW = NULL;
DWORD dwDependenciesLength = 0;
- DWORD dwLength;
+ SIZE_T cchLength;
int len;
LPCSTR lpStr;
if (lpServiceName)
{
len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
- lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ lpServiceNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
if (!lpServiceNameW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
if (lpDisplayName)
{
len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
- lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
if (!lpDisplayNameW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
if (lpBinaryPathName)
{
len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
- lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
if (!lpBinaryPathNameW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
if (lpLoadOrderGroup)
{
len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
- lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
if (!lpLoadOrderGroupW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
lpStr = (LPCSTR)lpDependencies;
while (*lpStr)
{
- dwLength = strlen(lpStr) + 1;
- dwDependenciesLength += dwLength;
- lpStr = lpStr + dwLength;
+ cchLength = strlen(lpStr) + 1;
+ dwDependenciesLength += (DWORD)cchLength;
+ lpStr = lpStr + cchLength;
}
dwDependenciesLength++;
- lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
+ lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR));
if (!lpDependenciesW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
if (lpServiceStartName)
{
len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
- lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
if (!lpServiceStartNameW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
/* Allocate memory for array of service pointers */
lpServicesArray = HeapAlloc(GetProcessHeap(),
- 0,
+ HEAP_ZERO_MEMORY,
(dwServicesReturned + 1) * sizeof(PSERVICE));
if (!lpServicesArray)
{
lpService->lpDisplayName,
-1,
lpStr,
- wcslen(lpService->lpDisplayName),
+ (int)wcslen(lpService->lpDisplayName),
0,
0);
lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
lpService->lpServiceName,
-1,
lpStr,
- wcslen(lpService->lpServiceName),
+ (int)wcslen(lpService->lpServiceName),
0,
0);
lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
lpStr += strlen(lpStr) + 1;
- lpServicesPtr ++;
+ lpServicesPtr++;
}
*lpServicesReturned = dwServicesReturned;
LPBOUNDED_DWORD_256K lpResumeHandle)
{
LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
+ LPENUM_SERVICE_STATUSW lpStatusPtrIncrW;
LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
LPWSTR lpStringPtrW;
LPSTR lpStringPtrA;
DPRINT("REnumServicesStatusA() called\n");
+ if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+ {
+ return ERROR_INVALID_ADDRESS;
+ }
+
if ((dwBufSize > 0) && (lpBuffer))
{
lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize);
if (*lpServicesReturned == 0)
goto Done;
+ lpStatusPtrIncrW = lpStatusPtrW;
lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
*lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
lpStringPtrW,
-1,
lpStringPtrA,
- wcslen(lpStringPtrW),
+ (int)wcslen(lpStringPtrW),
0,
0);
lpStringPtrW,
-1,
lpStringPtrA,
- wcslen(lpStringPtrW),
+ (int)wcslen(lpStringPtrW),
0,
0);
/* Copy the status information */
memcpy(&lpStatusPtrA->ServiceStatus,
- &lpStatusPtrW->ServiceStatus,
+ &lpStatusPtrIncrW->ServiceStatus,
sizeof(SERVICE_STATUS));
+ lpStatusPtrIncrW++;
lpStatusPtrA++;
}
-Done:;
+Done:
if (lpStatusPtrW)
HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
LPWSTR lpDependencies = NULL;
DWORD dwDependenciesLength = 0;
DWORD dwRequiredSize;
- LPQUERY_SERVICE_CONFIGA lpConfig = NULL;
CHAR lpEmptyString[]={0,0};
LPSTR lpStr;
&lpDependencies,
&dwDependenciesLength);
- dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
+ dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGA);
if (lpImagePath != NULL)
- dwRequiredSize += wcslen(lpImagePath) + 1;
+ dwRequiredSize += (DWORD)(wcslen(lpImagePath) + 1);
else
dwRequiredSize += 2;
if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
- dwRequiredSize += wcslen(lpService->lpGroup->lpGroupName) + 1;
+ dwRequiredSize += (DWORD)(wcslen(lpService->lpGroup->lpGroupName) + 1);
else
dwRequiredSize += 2;
dwRequiredSize += 2;
if (lpServiceStartName != NULL)
- dwRequiredSize += wcslen(lpServiceStartName) + 1;
+ dwRequiredSize += (DWORD)(wcslen(lpServiceStartName) + 1);
else
dwRequiredSize += 2;
if (lpService->lpDisplayName != NULL)
- dwRequiredSize += wcslen(lpService->lpDisplayName) + 1;
+ dwRequiredSize += (DWORD)(wcslen(lpService->lpDisplayName) + 1);
else
dwRequiredSize += 2;
}
else
{
- lpConfig = (LPQUERY_SERVICE_CONFIGA)lpServiceConfig;
- lpConfig->dwServiceType = lpService->Status.dwServiceType;
- lpConfig->dwStartType = lpService->dwStartType;
- lpConfig->dwErrorControl = lpService->dwErrorControl;
- lpConfig->dwTagId = lpService->dwTag;
+ lpServiceConfig->dwServiceType = lpService->Status.dwServiceType;
+ lpServiceConfig->dwStartType = lpService->dwStartType;
+ lpServiceConfig->dwErrorControl = lpService->dwErrorControl;
+ lpServiceConfig->dwTagId = lpService->dwTag;
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)
{
lpImagePath,
-1,
lpStr,
- wcslen(lpImagePath) + 1,
+ (int)(wcslen(lpImagePath) + 1),
0,
0);
}
strcpy(lpStr, lpEmptyString);
}
- lpConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
lpStr += (strlen((LPSTR)lpStr) + 1);
if (lpService->lpGroup && lpService->lpGroup->lpGroupName)
lpService->lpGroup->lpGroupName,
-1,
lpStr,
- wcslen(lpService->lpGroup->lpGroupName) + 1,
+ (int)(wcslen(lpService->lpGroup->lpGroupName) + 1),
0,
0);
}
strcpy(lpStr, lpEmptyString);
}
- lpConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
lpStr += (strlen(lpStr) + 1);
/* Append Dependencies */
strcpy(lpStr, lpEmptyString);
}
- lpConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
if (lpDependencies)
lpStr += dwDependenciesLength;
else
lpServiceStartName,
-1,
lpStr,
- wcslen(lpServiceStartName) + 1,
+ (int)(wcslen(lpServiceStartName) + 1),
0,
0);
}
strcpy(lpStr, lpEmptyString);
}
- lpConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
lpStr += (strlen(lpStr) + 1);
if (lpService->lpDisplayName)
lpService->lpDisplayName,
-1,
lpStr,
- wcslen(lpService->lpDisplayName) + 1,
+ (int)(wcslen(lpService->lpDisplayName) + 1),
0,
0);
}
strcpy(lpStr, lpEmptyString);
}
- lpConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpServiceConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
if (pcbBytesNeeded != NULL)
*pcbBytesNeeded = dwRequiredSize;
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
/* Function 30 */
DWORD RQueryServiceLockStatusA(
SC_RPC_HANDLE hSCManager,
- LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
+ LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
DWORD cbBufSize,
LPBOUNDED_DWORD_4K pcbBytesNeeded)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus = (LPQUERY_SERVICE_LOCK_STATUSA)lpBuf;
+ PMANAGER_HANDLE hMgr;
+ DWORD dwRequiredSize;
+
+ if (!lpLockStatus || !pcbBytesNeeded)
+ return ERROR_INVALID_PARAMETER;
+
+ hMgr = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hMgr == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
+ SC_MANAGER_QUERY_LOCK_STATUS))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* FIXME: we need to compute instead the real length of the owner name */
+ dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSA) + sizeof(CHAR);
+ *pcbBytesNeeded = dwRequiredSize;
+
+ if (cbBufSize < dwRequiredSize)
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ ScmQueryServiceLockStatusA(lpLockStatus);
+
+ return ERROR_SUCCESS;
}
if (lpServiceName != NULL)
{
- dwLength = strlen(lpServiceName) + 1;
+ dwLength = (DWORD)(strlen(lpServiceName) + 1);
lpServiceNameW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwLength * sizeof(WCHAR));
*lpcchBuffer = 1;
if (lpDisplayName != NULL)
{
- *lpDisplayName = '\0';
+ *lpDisplayName = 0;
}
}
return ERROR_SERVICE_DOES_NOT_EXIST;
if (!lpService->lpDisplayName)
{
- dwLength = wcslen(lpService->lpServiceName);
+ dwLength = (DWORD)wcslen(lpService->lpServiceName);
if (lpDisplayName != NULL &&
*lpcchBuffer > dwLength)
{
WideCharToMultiByte(CP_ACP,
0,
lpService->lpServiceName,
- wcslen(lpService->lpServiceName),
+ (int)wcslen(lpService->lpServiceName),
lpDisplayName,
dwLength + 1,
NULL,
}
else
{
- dwLength = wcslen(lpService->lpDisplayName);
+ dwLength = (DWORD)wcslen(lpService->lpDisplayName);
if (lpDisplayName != NULL &&
*lpcchBuffer > dwLength)
{
WideCharToMultiByte(CP_ACP,
0,
lpService->lpDisplayName,
- wcslen(lpService->lpDisplayName),
+ (int)wcslen(lpService->lpDisplayName),
lpDisplayName,
dwLength + 1,
NULL,
DPRINT("lpServiceName: %p\n", lpServiceName);
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
- dwLength = strlen(lpDisplayName) + 1;
+ dwLength = (DWORD)(strlen(lpDisplayName) + 1);
lpDisplayNameW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwLength * sizeof(WCHAR));
*lpcchBuffer = 1;
if (lpServiceName != NULL)
{
- *lpServiceName = '\0';
+ *lpServiceName = 0;
}
}
return ERROR_SERVICE_DOES_NOT_EXIST;
}
- dwLength = wcslen(lpService->lpServiceName);
+ dwLength = (DWORD)wcslen(lpService->lpServiceName);
if (lpServiceName != NULL &&
*lpcchBuffer > dwLength)
{
WideCharToMultiByte(CP_ACP,
0,
lpService->lpServiceName,
- wcslen(lpService->lpServiceName),
+ (int)wcslen(lpService->lpServiceName),
lpServiceName,
dwLength + 1,
NULL,
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;
-//
-// 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("REnumServiceGroupW() called\n");
- DPRINT("RChangeServiceConfig2A() called\n");
- DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
- InfoW.dwInfoLevel = Info.dwInfoLevel;
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
- if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
+ if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
{
- LPSERVICE_DESCRIPTIONW lpServiceDescriptonW;
- //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
+ return ERROR_INVALID_ADDRESS;
+ }
- //lpServiceDescriptonA = Info.psd;
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
- ///if (lpServiceDescriptonA &&
- ///lpServiceDescriptonA->lpDescription)
- ///{
- dwLength = (strlen(Info.lpDescription) + 1) * sizeof(WCHAR);
+ if ((dwServiceType == 0) ||
+ ((dwServiceType & ~SERVICE_TYPE_ALL) != 0))
+ {
+ DPRINT("Not a valid Service Type!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
- lpServiceDescriptonW = HeapAlloc(GetProcessHeap(),
- 0,
- dwLength + sizeof(SERVICE_DESCRIPTIONW));
- if (!lpServiceDescriptonW)
- {
- return ERROR_NOT_ENOUGH_MEMORY;
- }
+ if ((dwServiceState == 0) ||
+ ((dwServiceState & ~SERVICE_STATE_ALL) != 0))
+ {
+ DPRINT("Not a valid Service State!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
- lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1);
+ /* 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;
+ }
- MultiByteToWideChar(CP_ACP,
- 0,
- Info.lpDescription,
- -1,
- lpServiceDescriptonW->lpDescription,
- dwLength);
+ if (lpResumeIndex)
+ dwLastResumeCount = *lpResumeIndex;
- ptr = lpServiceDescriptonW;
- InfoW.psd = lpServiceDescriptonW;
- ///}
+ /* Lock the service database shared */
+ ScmLockDatabaseShared();
+
+ lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
+ if (lpService == NULL)
+ {
+ dwError = ERROR_SUCCESS;
+ goto Done;
}
- else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+
+ dwRequiredSize = 0;
+ dwServiceCount = 0;
+
+ for (ServiceEntry = &lpService->ServiceListEntry;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
{
- LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
- LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
- DWORD dwRebootLen = 0;
- DWORD dwCommandLen = 0;
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
- lpServiceFailureActionsA = Info.psfa;
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
- if (lpServiceFailureActionsA)
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ if (pszGroupName)
{
- if (lpServiceFailureActionsA->lpRebootMsg)
+ if (*pszGroupName == 0)
{
- dwRebootLen = (strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR);
+ if (CurrentService->lpGroup != NULL)
+ continue;
}
- if (lpServiceFailureActionsA->lpCommand)
+ else
{
- dwCommandLen = (strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR);
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
+ continue;
}
- dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW);
+ }
- lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
- 0,
- dwLength);
- if (!lpServiceFailureActionsW)
- {
- return ERROR_NOT_ENOUGH_MEMORY;
- }
+ dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+ (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
- lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
- lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
- CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION));
+ if (dwRequiredSize + dwSize > cbBufSize)
+ {
+ DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
+ break;
+ }
- if (lpServiceFailureActionsA->lpRebootMsg)
+ 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)
{
- MultiByteToWideChar(CP_ACP,
- 0,
- lpServiceFailureActionsA->lpRebootMsg,
- -1,
- lpServiceFailureActionsW->lpRebootMsg,
- dwRebootLen);
+ if (CurrentService->lpGroup != NULL)
+ continue;
}
-
- if (lpServiceFailureActionsA->lpCommand)
+ else
{
- MultiByteToWideChar(CP_ACP,
- 0,
- lpServiceFailureActionsA->lpCommand,
- -1,
- lpServiceFailureActionsW->lpCommand,
- dwCommandLen);
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
+ continue;
}
-
- ptr = lpServiceFailureActionsW;
}
+
+ dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
+ (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+
+ dwError = ERROR_MORE_DATA;
}
- dwRet = RChangeServiceConfig2W(hService, InfoW);
+ DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
- HeapFree(GetProcessHeap(), 0, ptr);
+ if (lpResumeIndex)
+ *lpResumeIndex = dwLastResumeCount;
- return dwRet;
-}
+ *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) +
+ (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ (DWORD)((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;
+}
+
+
+/* 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 lpServiceDescriptionW;
+ //LPSERVICE_DESCRIPTIONA lpServiceDescriptionA;
+
+ //lpServiceDescriptionA = Info.psd;
+
+ ///if (lpServiceDescriptionA &&
+ ///lpServiceDescriptionA->lpDescription)
+ ///{
+ dwLength = (DWORD)((strlen(Info.lpDescription) + 1) * sizeof(WCHAR));
+
+ lpServiceDescriptionW = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwLength + sizeof(SERVICE_DESCRIPTIONW));
+ if (!lpServiceDescriptionW)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1);
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ Info.lpDescription,
+ -1,
+ lpServiceDescriptionW->lpDescription,
+ dwLength);
+
+ ptr = lpServiceDescriptionW;
+ InfoW.psd = lpServiceDescriptionW;
+ ///}
+ }
+ else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
+ LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
+ DWORD dwRebootLen = 0;
+ DWORD dwCommandLen = 0;
+ DWORD dwActionArrayLen = 0;
+ LPWSTR lpStr = NULL;
+
+ lpServiceFailureActionsA = Info.psfa;
+
+ if (lpServiceFailureActionsA)
+ {
+ /*
+ * The following code is inspired by the
+ * SERVICE_CONFIG_FAILURE_ACTIONS case of
+ * the RQueryServiceConfig2W function.
+ */
+
+ /* Retrieve the needed length for the two data strings */
+ if (lpServiceFailureActionsA->lpRebootMsg)
+ {
+ dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR));
+ }
+ if (lpServiceFailureActionsA->lpCommand)
+ {
+ dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR));
+ }
+
+ /*
+ * Retrieve the size of the lpsaActions array if needed.
+ * We will copy the lpsaActions array only if there is at
+ * least one action AND that the original array is valid.
+ */
+ if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions)
+ {
+ dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION);
+ }
+
+ /* Compute the total length for the UNICODE structure, including data */
+ dwLength = sizeof(SERVICE_FAILURE_ACTIONSW) +
+ dwActionArrayLen + dwRebootLen + dwCommandLen;
+
+ /* Allocate the structure */
+ lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwLength);
+ if (!lpServiceFailureActionsW)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Copy the members */
+ lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
+ lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
+
+ /* Copy the lpsaActions array if needed */
+ if (dwActionArrayLen > 0)
+ {
+ /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */
+ lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1));
+
+ /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */
+ RtlCopyMemory(lpServiceFailureActionsW->lpsaActions,
+ lpServiceFailureActionsA->lpsaActions,
+ dwActionArrayLen);
+ }
+ else
+ {
+ /* No lpsaActions array */
+ lpServiceFailureActionsW->lpsaActions = NULL;
+ }
+ /* The data strings are stored just after the lpsaActions array */
+ lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen);
+
+ /*
+ * Convert the data strings to UNICODE
+ */
+
+ lpServiceFailureActionsW->lpRebootMsg = NULL;
+ lpServiceFailureActionsW->lpCommand = NULL;
+
+ if (dwRebootLen)
+ {
+ /* lpRebootMsg points just after the lpsaActions array */
+ lpServiceFailureActionsW->lpRebootMsg = lpStr;
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpServiceFailureActionsA->lpRebootMsg,
+ -1,
+ lpServiceFailureActionsW->lpRebootMsg,
+ dwRebootLen);
+
+ lpStr += dwRebootLen / sizeof(WCHAR);
+ }
+
+ if (dwCommandLen)
+ {
+ /* lpRebootMsg points just after the lpRebootMsg data string */
+ lpServiceFailureActionsW->lpCommand = lpStr;
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpServiceFailureActionsA->lpCommand,
+ -1,
+ lpServiceFailureActionsW->lpCommand,
+ dwCommandLen);
+ }
+
+ /* Set the pointers */
+ ptr = lpServiceFailureActionsW;
+ InfoW.psfa = lpServiceFailureActionsW;
+ }
+ }
+
+ dwRet = RChangeServiceConfig2W(hService, InfoW);
+
+ HeapFree(GetProcessHeap(), 0, ptr);
+
+ return dwRet;
+}
+
+
+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,
+ (DWORD)((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,
+ (DWORD)((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 */
/* 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;
- lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpServiceDescription + sizeof(LPSERVICE_DESCRIPTIONW));
+ 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,
+ (DWORD)((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;
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
HKEY hServiceKey = NULL;
+ DWORD dwRequiredSize = 0;
+ DWORD dwType = 0;
LPWSTR lpDescriptionW = 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);
*pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA);
if (dwError == ERROR_SUCCESS)
- *pcbBytesNeeded += ((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
+ *pcbBytesNeeded += (DWORD)((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
if (cbBufSize < *pcbBytesNeeded)
{
lpDescriptionW,
-1,
lpStr,
- wcslen(lpDescriptionW),
+ (int)wcslen(lpDescriptionW),
NULL,
NULL);
lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
{
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 += (DWORD)((wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR));
+
+ if (lpFailureCommandW)
+ dwRequiredSize += (DWORD)((wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR));
+
+ if (cbBufSize < dwRequiredSize)
+ {
+ *pcbBytesNeeded = dwRequiredSize;
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ goto done;
+ }
+
+ /* Now we can fill the buffer */
+ 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 = sizeof(SERVICE_FAILURE_ACTIONSA);
+ }
+ 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)
+ {
+ 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,
+ (int)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,
+ (int)wcslen(lpFailureCommandW),
+ NULL,
+ NULL);
+ lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
+ /* lpStr += strlen(lpStr) + 1; */
+ }
+
+ dwError = ERROR_SUCCESS;
}
done:
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");
*pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONW);
if (dwError == ERROR_SUCCESS)
- *pcbBytesNeeded += ((wcslen(lpDescription) + 1) * sizeof(WCHAR));
+ *pcbBytesNeeded += (DWORD)((wcslen(lpDescription) + 1) * sizeof(WCHAR));
if (cbBufSize < *pcbBytesNeeded)
{
}
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);
+ dwRequiredSize += (DWORD)((wcslen(lpRebootMessage) + 1) * sizeof(WCHAR));
+
+ if (lpFailureCommand)
+ dwRequiredSize += (DWORD)((wcslen(lpFailureCommand) + 1) * sizeof(WCHAR));
if (cbBufSize < dwRequiredSize)
{
goto done;
}
- lpFailureActions->cActions = 0;
- lpFailureActions->dwResetPeriod = 0;
- lpFailureActions->lpCommand = NULL;
+ /* Now we can fill the buffer */
+ 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 = 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)
+ {
+ 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:
LPCSTR pszGroupName)
{
LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
+ LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW;
LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
LPWSTR lpStringPtrW;
LPSTR lpStringPtrA;
DPRINT("REnumServicesStatusExA() called\n");
+ if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+ {
+ return ERROR_INVALID_ADDRESS;
+ }
+
if (pszGroupName)
{
pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR));
pszGroupName,
-1,
pszGroupNameW,
- strlen(pszGroupName) + 1);
+ (int)(strlen(pszGroupName) + 1));
}
if ((cbBufSize > 0) && (lpBuffer))
if (*lpServicesReturned == 0)
goto Done;
+ lpStatusPtrIncrW = lpStatusPtrW;
lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer;
lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
*lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
lpStringPtrW,
-1,
lpStringPtrA,
- wcslen(lpStringPtrW),
+ (int)wcslen(lpStringPtrW),
0,
0);
lpStringPtrW,
-1,
lpStringPtrA,
- wcslen(lpStringPtrW),
+ (int)wcslen(lpStringPtrW),
0,
0);
/* 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);
return ERROR_INVALID_HANDLE;
}
+ if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+ {
+ return ERROR_INVALID_ADDRESS;
+ }
+
*pcbBytesNeeded = 0;
*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;
else
{
if ((CurrentService->lpGroup == NULL) ||
- _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
continue;
}
}
dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
- ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
- ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
if (dwRequiredSize + dwSize <= cbBufSize)
{
else
{
if ((CurrentService->lpGroup == NULL) ||
- _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
continue;
}
}
dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
- ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
- ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+ (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
dwError = ERROR_MORE_DATA;
}
else
{
if ((CurrentService->lpGroup == NULL) ||
- _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0)
continue;
}
}
dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
- ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
- ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+ (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
if (dwRequiredSize + dwSize <= cbBufSize)
{
*lpResumeIndex = 0;
}
-Done:;
+Done:
/* Unlock the service database */
ScmUnlockDatabase();
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);
}