* COPYRIGHT: Copyright 2005-2006 Eric Kohl
* Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
- *
*/
/* INCLUDES ****************************************************************/
Ptr = (MANAGER_HANDLE*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
- sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
+ sizeof(MANAGER_HANDLE) + (wcslen(lpDatabaseName) + 1) * sizeof(WCHAR));
if (Ptr == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
}
+/* Internal recursive function */
+/* Need to search for every dependency on every service */
+static DWORD
+Int_EnumDependentServicesW(HKEY hServicesKey,
+ PSERVICE lpService,
+ DWORD dwServiceState,
+ PSERVICE *lpServices,
+ LPDWORD pcbBytesNeeded,
+ LPDWORD lpServicesReturned)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ WCHAR szNameBuf[MAX_PATH];
+ WCHAR szValueBuf[MAX_PATH];
+ WCHAR *lpszNameBuf = szNameBuf;
+ WCHAR *lpszValueBuf = szValueBuf;
+ DWORD dwSize;
+ DWORD dwNumSubKeys;
+ DWORD dwIteration;
+ PSERVICE lpCurrentService;
+ HKEY hServiceEnumKey;
+ DWORD dwCurrentServiceState = SERVICE_ACTIVE;
+ DWORD dwDependServiceStrPtr = 0;
+ DWORD dwRequiredSize = 0;
+
+ /* Get the number of service keys */
+ dwError = RegQueryInfoKeyW(hServicesKey,
+ NULL,
+ NULL,
+ NULL,
+ &dwNumSubKeys,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ERROR! Unable to get number of services keys.\n");
+ return dwError;
+ }
+
+ /* Iterate the service keys to see if another service depends on the this service */
+ for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++)
+ {
+ dwSize = MAX_PATH;
+ dwError = RegEnumKeyExW(hServicesKey,
+ dwIteration,
+ lpszNameBuf,
+ &dwSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ /* Open the Service key */
+ dwError = RegOpenKeyExW(hServicesKey,
+ lpszNameBuf,
+ 0,
+ KEY_READ,
+ &hServiceEnumKey);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ dwSize = MAX_PATH;
+
+ /* Check for the DependOnService Value */
+ dwError = RegQueryValueExW(hServiceEnumKey,
+ L"DependOnService",
+ NULL,
+ NULL,
+ (LPBYTE)lpszValueBuf,
+ &dwSize);
+
+ /* FIXME: Handle load order. */
+
+ /* If the service found has a DependOnService value */
+ if (dwError == ERROR_SUCCESS)
+ {
+ dwDependServiceStrPtr = 0;
+
+ /* Can be more than one Dependencies in the DependOnService string */
+ while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
+ {
+ if (wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
+ {
+ /* Get the current enumed service pointer */
+ lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
+
+ /* Check for valid Service */
+ if (!lpCurrentService)
+ {
+ /* This should never happen! */
+ DPRINT1("This should not happen at this point, report to Developer\n");
+ return ERROR_NOT_FOUND;
+ }
+
+ /* Determine state the service is in */
+ if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwCurrentServiceState = SERVICE_INACTIVE;
+
+ /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
+ if ((dwCurrentServiceState == dwServiceState) ||
+ (dwServiceState == SERVICE_STATE_ALL))
+ {
+ /* Calculate the required size */
+ dwRequiredSize += sizeof(SERVICE_STATUS);
+ dwRequiredSize += ((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
+ dwRequiredSize += ((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ /* Add the size for service name and display name pointers */
+ dwRequiredSize += (2 * sizeof(PVOID));
+
+ /* increase the BytesNeeded size */
+ *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize;
+
+ /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
+ comes first */
+
+ /* Recursive call to check for its dependencies */
+ Int_EnumDependentServicesW(hServicesKey,
+ lpCurrentService,
+ dwServiceState,
+ lpServices,
+ pcbBytesNeeded,
+ lpServicesReturned);
+
+ /* If the lpServices is valid set the service pointer */
+ if (lpServices)
+ lpServices[*lpServicesReturned] = lpCurrentService;
+
+ *lpServicesReturned = *lpServicesReturned + 1;
+ }
+ }
+
+ dwDependServiceStrPtr += (wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
+ }
+ }
+ else if (*pcbBytesNeeded)
+ {
+ dwError = ERROR_SUCCESS;
+ }
+
+ RegCloseKey(hServiceEnumKey);
+ }
+
+ return dwError;
+}
+
+
/* Function 0 */
DWORD RCloseServiceHandle(
handle_t BindingHandle,
LPSC_RPC_HANDLE hSCObject)
{
PMANAGER_HANDLE hManager;
+ PSERVICE_HANDLE hService;
+ PSERVICE lpService;
+ HKEY hServicesKey;
+ DWORD dwError;
+ DWORD pcbBytesNeeded = 0;
+ DWORD dwServicesReturned = 0;
DPRINT("RCloseServiceHandle() called\n");
return ERROR_INVALID_HANDLE;
hManager = (PMANAGER_HANDLE)*hSCObject;
+ hService = (PSERVICE_HANDLE)*hSCObject;
if (hManager->Handle.Tag == MANAGER_TAG)
{
DPRINT("Found manager handle\n");
hManager->Handle.RefCount--;
if (hManager->Handle.RefCount == 0)
{
- /* FIXME: add cleanup code */
+ /* FIXME: add handle cleanup code */
HeapFree(GetProcessHeap(), 0, hManager);
+ hManager = NULL;
}
DPRINT("RCloseServiceHandle() done\n");
return ERROR_SUCCESS;
}
- else if (hManager->Handle.Tag == SERVICE_TAG)
+ else if (hService->Handle.Tag == SERVICE_TAG)
{
DPRINT("Found service handle\n");
- hManager->Handle.RefCount--;
- if (hManager->Handle.RefCount == 0)
+ /* Get the pointer to the service record */
+ lpService = hService->ServiceEntry;
+
+ ASSERT(hService->Handle.RefCount > 0);
+
+ hService->Handle.RefCount--;
+ if (hService->Handle.RefCount == 0)
{
- /* FIXME: add cleanup code */
+ /* FIXME: add handle cleanup code */
- HeapFree(GetProcessHeap(), 0, hManager);
+ /* Free the handle */
+ HeapFree(GetProcessHeap(), 0, hService);
+ hService = NULL;
+ }
+
+ ASSERT(lpService->dwRefCount > 0);
+
+ lpService->dwRefCount--;
+ DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
+ lpService->dwRefCount);
+
+ if (lpService->dwRefCount == 0)
+ {
+ /* If this service has been marked for deletion */
+ if (lpService->bDeleted)
+ {
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_SET_VALUE | KEY_READ,
+ &hServicesKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("Failed to open services key\n");
+ return dwError;
+ }
+
+ /* Call the internal function with NULL, just to get bytes we need */
+ Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ SERVICE_ACTIVE,
+ NULL,
+ &pcbBytesNeeded,
+ &dwServicesReturned);
+
+ /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
+ if (pcbBytesNeeded)
+ {
+ DPRINT1("Deletion failed due to running dependencies.\n");
+ RegCloseKey(hServicesKey);
+ return ERROR_SUCCESS;
+ }
+
+ /* There are no references and no runnning dependencies,
+ it is now safe to delete the service */
+
+ /* Delete the Service Key */
+ dwError = RegDeleteKey(hServicesKey,
+ lpService->lpServiceName);
+
+ RegCloseKey(hServicesKey);
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("Failed to Delete the Service Registry key\n");
+ return dwError;
+ }
+
+ /* Delete the Service */
+ ScmDeleteServiceRecord(lpService);
+ }
}
DPRINT("RCloseServiceHandle() done\n");
PSERVICE lpService;
ACCESS_MASK DesiredAccess;
DWORD dwError = ERROR_SUCCESS;
+ DWORD pcbBytesNeeded = 0;
+ DWORD dwServicesReturned = 0;
+ HKEY hServicesKey = NULL;
DPRINT("RControlService() called\n");
return ERROR_INVALID_HANDLE;
}
+ /* Check the service entry point */
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT1("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
/* Check access rights */
switch (dwControl)
{
DesiredAccess))
return ERROR_ACCESS_DENIED;
- /* Check the service entry point */
- lpService = hSvc->ServiceEntry;
- if (lpService == NULL)
+ if (dwControl == SERVICE_CONTROL_STOP)
{
- DPRINT1("lpService == NULL!\n");
- return ERROR_INVALID_HANDLE;
+ /* Check if the service has dependencies running as windows
+ doesn't stop a service that does */
+
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_READ,
+ &hServicesKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("Failed to open services key\n");
+ return dwError;
+ }
+
+ /* Call the internal function with NULL, just to get bytes we need */
+ Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ SERVICE_ACTIVE,
+ NULL,
+ &pcbBytesNeeded,
+ &dwServicesReturned);
+
+ RegCloseKey(hServicesKey);
+
+ /* If pcbBytesNeeded is not zero then there are services running that
+ are dependent on this service */
+ if (pcbBytesNeeded != 0)
+ {
+ DPRINT("Service has running dependencies. Failed to stop service.\n");
+ return ERROR_DEPENDENT_SERVICES_RUNNING;
+ }
}
if (lpService->Status.dwServiceType & SERVICE_DRIVER)
lpServiceStatus);
}
+ if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
+ dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
+
/* Return service status information */
RtlCopyMemory(lpServiceStatus,
&lpService->Status,
}
+static BOOL
+ScmIsValidServiceState(DWORD dwCurrentState)
+{
+ switch (dwCurrentState)
+ {
+ case SERVICE_STOPPED:
+ case SERVICE_START_PENDING:
+ case SERVICE_STOP_PENDING:
+ case SERVICE_RUNNING:
+ case SERVICE_CONTINUE_PENDING:
+ case SERVICE_PAUSE_PENDING:
+ case SERVICE_PAUSED:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
/* Function 7 */
DWORD RSetServiceStatus(
handle_t BindingHandle,
PSERVICE lpService;
DPRINT("RSetServiceStatus() called\n");
-
- if (ScmShutdown)
- return ERROR_SHUTDOWN_IN_PROGRESS;
+ DPRINT("hServiceStatus = %p\n", hServiceStatus);
+ DPRINT("dwServiceType = %lu\n", lpServiceStatus->dwServiceType);
+ DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState);
+ DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted);
+ DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode);
+ DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode);
+ DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint);
+ DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint);
+
+ if (hServiceStatus == 0)
+ {
+ DPRINT1("hServiceStatus == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
lpService = ScmGetServiceEntryByClientHandle((ULONG)hServiceStatus);
if (lpService == NULL)
return ERROR_INVALID_HANDLE;
}
+ /* Check current state */
+ if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState))
+ {
+ DPRINT1("Invalid service state!\n");
+ return ERROR_INVALID_DATA;
+ }
+
+ /* Check service type */
+ if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
+ (lpServiceStatus->dwServiceType & SERVICE_DRIVER))
+ {
+ DPRINT1("Invalid service type!\n");
+ return ERROR_INVALID_DATA;
+ }
+
+ /* Check accepted controls */
+ if (lpServiceStatus->dwControlsAccepted == 0 ||
+ lpServiceStatus->dwControlsAccepted & ~0xFF)
+ {
+ DPRINT1("Invalid controls accepted!\n");
+ return ERROR_INVALID_DATA;
+ }
+
+
RtlCopyMemory(&lpService->Status,
lpServiceStatus,
sizeof(SERVICE_STATUS));
/* Function 10 */
-DWORD RSetServiceBitsW(
+DWORD RI_ScSetServiceBitsW(
handle_t BindingHandle,
SC_RPC_HANDLE hServiceStatus,
DWORD dwServiceBits,
(wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
if (dwError != ERROR_SUCCESS)
goto done;
- /* FIXME: update lpService->lpServiceGroup */
+ /* FIXME: Update lpService->lpServiceGroup */
}
if (lpdwTagId != NULL)
return dwError;
}
+
/* Create a path suitable for the bootloader out of the full path */
DWORD
ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
DPRINT("ScmConvertToBootPathName %S\n", CanonName);
ServiceNameLen = wcslen(CanonName);
+
/* First check, if it's already good */
if (ServiceNameLen > 12 &&
!wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
{
*RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
-
if (*RelativeName == NULL)
{
DPRINT1("Error allocating memory for boot driver name!\n");
Expanded = LocalAlloc(LMEM_ZEROINIT, BufferSize * sizeof(WCHAR) + sizeof(WCHAR));
if (!Expanded)
{
- DPRINT1("Error allocating memory for boot driver name!\n");
- return ERROR_NOT_ENOUGH_MEMORY;
+ DPRINT1("Error allocating memory for boot driver name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
}
/* Expand it */
/* Only \SystemRoot\ is missing */
*RelativeName = LocalAlloc(LMEM_ZEROINIT,
(ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
-
if (*RelativeName == NULL)
{
DPRINT1("Error allocating memory for boot driver name!\n");
return ERROR_ACCESS_DENIED;
}
- /* Fail if the service already exists! */
- if (ScmGetServiceEntryByName(lpServiceName) != NULL)
+ if (wcslen(lpServiceName) == 0)
+ {
+ return ERROR_INVALID_NAME;
+ }
+
+ if (wcslen(lpBinaryPathName) == 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
+ (lpServiceStartName))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceType > SERVICE_WIN32_SHARE_PROCESS) &&
+ (dwServiceType != (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
+ (dwServiceType != (SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS)))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (dwStartType > SERVICE_DISABLED)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ lpService = ScmGetServiceEntryByName(lpServiceName);
+ if (lpService)
+ {
+ /* check if it is marked for deletion */
+ if (lpService->bDeleted)
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ /* Return Error exist */
return ERROR_SERVICE_EXISTS;
+ }
+
+ if (lpDisplayName != NULL &&
+ ScmGetServiceEntryByDisplayName(lpDisplayName) != NULL)
+ return ERROR_DUPLICATE_SERVICE_NAME;
if (dwServiceType & SERVICE_DRIVER)
{
dwError = ScmCanonDriverImagePath(dwStartType,
- lpBinaryPathName,
- &lpImagePath);
-
+ lpBinaryPathName,
+ &lpImagePath);
if (dwError != ERROR_SUCCESS)
goto done;
}
+ else
+ {
+ if (dwStartType == SERVICE_BOOT_START ||
+ dwStartType == SERVICE_SYSTEM_START)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
/* Allocate a new service entry */
dwError = ScmCreateNewServiceRecord(lpServiceName,
goto done;
}
+ /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
+ if ((dwServiceType & SERVICE_WIN32) && (!lpServiceName))
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"ObjectName",
+ 0,
+ REG_SZ,
+ (LPBYTE)L"LocalSystem",
+ 24);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
if (lpPassword != NULL)
{
/* FIXME: Write password */
if (dwError != ERROR_SUCCESS)
goto done;
+ lpService->dwRefCount = 1;
+ DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount);
+
done:;
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
if (dwError == ERROR_SUCCESS)
{
DPRINT("hService %p\n", hServiceHandle);
- *lpServiceHandle = (unsigned long)hServiceHandle; /* FIXME: 64 bit portability */
+ *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle;
if (lpdwTagId != NULL)
*lpdwTagId = lpService->dwTag;
LPBOUNDED_DWORD_256K lpServicesReturned)
{
DWORD dwError = ERROR_SUCCESS;
+ DWORD dwServicesReturned = 0;
+ DWORD dwServiceCount;
+ HKEY hServicesKey = NULL;
+ LPSC_RPC_HANDLE hSCObject;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ PSERVICE *lpServicesArray = NULL;
+ LPENUM_SERVICE_STATUSW lpServicesPtr = NULL;
+ LPWSTR lpStr;
- UNIMPLEMENTED;
*pcbBytesNeeded = 0;
*lpServicesReturned = 0;
- DPRINT1("REnumDependentServicesW() done (Error %lu)\n", dwError);
+ DPRINT("REnumDependentServicesW() called\n");
+
+ hSCObject = &hService;
+ hSvc = (PSERVICE_HANDLE) *hSCObject;
+ lpService = hSvc->ServiceEntry;
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT1("Insufficient access rights! 0x%lx\n",
+ hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_READ,
+ &hServicesKey);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ /* First determine the bytes needed and get the number of dependent services */
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ NULL,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* If buffer size is less than the bytes needed or pointer is null */
+ if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
+ {
+ dwError = ERROR_MORE_DATA;
+ goto Done;
+ }
+
+ /* Allocate memory for array of service pointers */
+ lpServicesArray = HeapAlloc(GetProcessHeap(),
+ 0,
+ (dwServicesReturned + 1) * sizeof(PSERVICE));
+ if (!lpServicesArray)
+ {
+ DPRINT1("Could not allocate a buffer!!\n");
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Done;
+ }
+
+ dwServicesReturned = 0;
+ *pcbBytesNeeded = 0;
+
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ lpServicesArray,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ {
+ goto Done;
+ }
+
+ lpServicesPtr = (LPENUM_SERVICE_STATUSW) lpServices;
+ lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW)));
+
+ /* Copy EnumDepenedentService to Buffer */
+ for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
+ {
+ lpService = lpServicesArray[dwServiceCount];
+
+ /* Copy status info */
+ memcpy(&lpServicesPtr->ServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
+ /* Copy display name */
+ wcscpy(lpStr, lpService->lpDisplayName);
+ lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += (wcslen(lpService->lpDisplayName) + 1);
+
+ /* Copy service name */
+ wcscpy(lpStr, lpService->lpServiceName);
+ lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += (wcslen(lpService->lpServiceName) + 1);
+
+ lpServicesPtr ++;
+ }
+
+ *lpServicesReturned = dwServicesReturned;
+
+Done:
+ if (lpServicesArray != NULL)
+ HeapFree(GetProcessHeap(), 0, lpServicesArray);
+
+ RegCloseKey(hServicesKey);
+
+ DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError);
return dwError;
}
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
- if (dwRequiredSize + dwSize <= dwBufSize)
- {
- DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
- dwRequiredSize += dwSize;
- dwServiceCount++;
- dwLastResumeCount = CurrentService->dwResumeCount;
- }
- else
+ 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);
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
- if (dwRequiredSize + dwSize <= dwBufSize)
- {
- /* Copy the service name */
- wcscpy(lpStringPtr,
- CurrentService->lpServiceName);
- lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
- lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+ if (dwRequiredSize + dwSize > dwBufSize)
+ break;
- /* Copy the display name */
- wcscpy(lpStringPtr,
- CurrentService->lpDisplayName);
- lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
- lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+ /* Copy the service name */
+ wcscpy(lpStringPtr, CurrentService->lpServiceName);
+ lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
- /* Copy the status information */
- memcpy(&lpStatusPtr->ServiceStatus,
- &CurrentService->Status,
- sizeof(SERVICE_STATUS));
+ /* Copy the display name */
+ wcscpy(lpStringPtr, CurrentService->lpDisplayName);
+ lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
- lpStatusPtr++;
- dwRequiredSize += dwSize;
- }
- else
- {
- break;
- }
+ /* Copy the status information */
+ memcpy(&lpStatusPtr->ServiceStatus,
+ &CurrentService->Status,
+ sizeof(SERVICE_STATUS));
+ lpStatusPtr++;
+ dwRequiredSize += dwSize;
}
Done:;
return dwError;
}
- *lpScHandle = (unsigned long)hHandle; /* FIXME: 64 bit portability */
+ *lpScHandle = (SC_RPC_HANDLE)hHandle;
DPRINT("*hScm = %p\n", *lpScHandle);
DPRINT("ROpenSCManagerW() done\n");
return dwError;
}
- *lpServiceHandle = (unsigned long)hHandle; /* FIXME: 64 bit portability */
+ lpService->dwRefCount++;
+ DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount);
+
+ *lpServiceHandle = (SC_RPC_HANDLE)hHandle;
DPRINT("*hService = %p\n", *lpServiceHandle);
DPRINT("ROpenServiceW() done\n");
/* Function 22 */
-DWORD RSetServiceBitsA(
+DWORD RI_ScSetServiceBitsA(
handle_t BindingHandle,
SC_RPC_HANDLE hServiceStatus,
DWORD dwServiceBits,
lpDisplayName,
-1,
lpDisplayNameW,
- (wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR));
+ wcslen(lpDisplayNameW) + 1);
RegSetValueExW(hServiceKey,
L"DisplayName",
if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
{
lpBinaryPathNameW=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName)+1) * sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, (wcslen(lpBinaryPathNameW)+1) * sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, wcslen(lpBinaryPathNameW)+1);
dwError = RegSetValueExW(hServiceKey,
L"ImagePath",
0,
lpLoadOrderGroup,
-1,
lpLoadOrderGroupW,
- (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR));
+ wcslen(lpLoadOrderGroupW) + 1);
dwError = RegSetValueExW(hServiceKey,
L"Group",
lpDependencies,
dwDependSize,
lpDependenciesW,
- (wcslen(lpDependenciesW)+1) * sizeof(WCHAR));
+ wcslen(lpDependenciesW)+1);
dwError = ScmWriteDependencies(hServiceKey,
(LPWSTR)lpDependenciesW,
LPBOUNDED_DWORD_256K pcbBytesNeeded,
LPBOUNDED_DWORD_256K lpServicesReturned)
{
- UNIMPLEMENTED;
+ DWORD dwError = ERROR_SUCCESS;
+ DWORD dwServicesReturned = 0;
+ DWORD dwServiceCount;
+ HKEY hServicesKey = NULL;
+ LPSC_RPC_HANDLE hSCObject;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ PSERVICE *lpServicesArray = NULL;
+ LPENUM_SERVICE_STATUSA lpServicesPtr = NULL;
+ LPSTR lpStr;
+
*pcbBytesNeeded = 0;
*lpServicesReturned = 0;
- return ERROR_CALL_NOT_IMPLEMENTED;
+
+ DPRINT("REnumDependentServicesA() called\n");
+
+ hSCObject = &hService;
+ hSvc = (PSERVICE_HANDLE) *hSCObject;
+ lpService = hSvc->ServiceEntry;
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT1("Insufficient access rights! 0x%lx\n",
+ hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_READ,
+ &hServicesKey);
+
+ if (dwError != ERROR_SUCCESS) return dwError;
+
+ /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
+ both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
+ are the same for both. Verified in WINXP. */
+
+ /* First determine the bytes needed and get the number of dependent services*/
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ NULL,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* If buffer size is less than the bytes needed or pointer is null*/
+ if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
+ {
+ dwError = ERROR_MORE_DATA;
+ goto Done;
+ }
+
+ /* Allocate memory for array of service pointers */
+ lpServicesArray = HeapAlloc(GetProcessHeap(),
+ 0,
+ (dwServicesReturned + 1) * sizeof(PSERVICE));
+ if (!lpServicesArray)
+ {
+ DPRINT1("Could not allocate a buffer!!\n");
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Done;
+ }
+
+ dwServicesReturned = 0;
+ *pcbBytesNeeded = 0;
+
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ lpServicesArray,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ {
+ goto Done;
+ }
+
+ lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices;
+ lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA)));
+
+ /* Copy EnumDepenedentService to Buffer */
+ for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
+ {
+ lpService = lpServicesArray[dwServiceCount];
+
+ /* Copy the status info */
+ memcpy(&lpServicesPtr->ServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
+ /* Copy display name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpDisplayName,
+ -1,
+ lpStr,
+ wcslen(lpService->lpDisplayName),
+ 0,
+ 0);
+ lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += strlen(lpStr) + 1;
+
+ /* Copy service name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpServiceName,
+ -1,
+ lpStr,
+ wcslen(lpService->lpServiceName),
+ 0,
+ 0);
+ lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += strlen(lpStr) + 1;
+
+ lpServicesPtr ++;
+ }
+
+ *lpServicesReturned = dwServicesReturned;
+
+Done:
+ if (lpServicesArray)
+ HeapFree(GetProcessHeap(), 0, lpServicesArray);
+
+ RegCloseKey(hServicesKey);
+
+ DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError);
+
+ return dwError;
}
lpDatabaseName);
dwError = ROpenSCManagerW(BindingHandle,
- lpMachineName ? MachineName.Buffer : NULL,
- lpDatabaseName ? DatabaseName.Buffer : NULL,
- dwDesiredAccess,
- lpScHandle);
+ lpMachineName ? MachineName.Buffer : NULL,
+ lpDatabaseName ? DatabaseName.Buffer : NULL,
+ dwDesiredAccess,
+ lpScHandle);
if (lpMachineName)
RtlFreeUnicodeString(&MachineName);
lpServiceName);
dwError = ROpenServiceW(BindingHandle,
- hSCManager,
- ServiceName.Buffer,
- dwDesiredAccess,
- lpServiceHandle);
+ hSCManager,
+ lpServiceName ? ServiceName.Buffer : NULL,
+ dwDesiredAccess,
+ lpServiceHandle);
if (lpServiceName)
RtlFreeUnicodeString(&ServiceName);
/* Function 34 */
-DWORD RGetCurrentGroupStateW(
- handle_t BindingHandle)
+DWORD RI_ScGetCurrentGroupStateW(
+ handle_t BindingHandle,
+ SC_RPC_HANDLE hSCManager,
+ LPWSTR lpLoadOrderGroup,
+ LPDWORD lpState)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;