From 3bd41ed16436119013eea5cf7e955d8de9a2dead Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 18 Dec 2005 19:50:53 +0000 Subject: [PATCH] Implement QueryServiceConfigW. svn path=/trunk/; revision=20255 --- reactos/include/idl/svcctl.idl | 27 +++ reactos/lib/advapi32/service/scm.c | 213 +++++++++++------ reactos/subsys/system/services/database.c | 33 +++ reactos/subsys/system/services/driver.c | 142 +++++++++++- reactos/subsys/system/services/rpcserver.c | 255 ++++++++++++++++++++- reactos/subsys/system/services/services.h | 2 + 6 files changed, 584 insertions(+), 88 deletions(-) diff --git a/reactos/include/idl/svcctl.idl b/reactos/include/idl/svcctl.idl index bfdaa0f66ef..311203e780e 100644 --- a/reactos/include/idl/svcctl.idl +++ b/reactos/include/idl/svcctl.idl @@ -5,6 +5,7 @@ //#include //#include +#define BYTE unsigned char #define DWORD unsigned long #define BOOL unsigned long #define SC_HANDLE unsigned int @@ -113,6 +114,25 @@ cpp_quote("#endif") [in] DWORD dwPasswordLength, [out] SC_HANDLE *hService); + /* Function 13 */ + DWORD ScmrEnumDependentServicesW([in] handle_t BindingHandle, + [in] SC_HANDLE hService, + [in] DWORD dwServiceState, + [out, size_is(cbBufSize)] BYTE *lpServices, + [in] DWORD cbBufSize, + [out] LPDWORD pcbBytesNeeded, + [out] LPDWORD lpServicesReturned); + + /* Function 14 */ + DWORD ScmrEnumServicesStatusW([in] handle_t BindingHandle, + [in] SC_HANDLE hSCManager, + [in] DWORD dwServiceType, + [in] DWORD dwServiceState, + [out, size_is(dwBufSize)] BYTE *lpServices, + [in] DWORD dwBufSize, + [out] LPDWORD pcbBytesNeeded, + [out] LPDWORD lpServicesReturned, + [in, out] LPDWORD lpResumeHandle); /* FIXME: unique */ /* Function 15 */ DWORD ScmrOpenSCManagerW([in] handle_t BindingHandle, @@ -128,6 +148,13 @@ cpp_quote("#endif") [in] DWORD dwDesiredAccess, [out] SC_HANDLE *hScm); + /* Function 17 */ + DWORD ScmrQueryServiceConfigW([in] handle_t BindingHandle, + [in] SC_HANDLE hService, + [out, unique, size_is(cbBufSize)] BYTE *lpServiceConfig, + [in] DWORD cbBufSize, + [out] DWORD *pcbBytesNeeded); + /* Function 20 */ DWORD ScmrGetServiceDisplayNameW([in] handle_t BindingHandle, diff --git a/reactos/lib/advapi32/service/scm.c b/reactos/lib/advapi32/service/scm.c index bbc8bddc8ab..dc0f137ddb6 100644 --- a/reactos/lib/advapi32/service/scm.c +++ b/reactos/lib/advapi32/service/scm.c @@ -204,7 +204,7 @@ CloseServiceHandle(SC_HANDLE hSCObject) /********************************************************************** * ControlService * - * @unimplemented + * @implemented */ BOOL STDCALL ControlService(SC_HANDLE hService, @@ -262,20 +262,19 @@ ControlServiceEx(IN SC_HANDLE hService, */ SC_HANDLE STDCALL -CreateServiceA( - SC_HANDLE hSCManager, - LPCSTR lpServiceName, - LPCSTR lpDisplayName, - DWORD dwDesiredAccess, - DWORD dwServiceType, - DWORD dwStartType, - DWORD dwErrorControl, - LPCSTR lpBinaryPathName, - LPCSTR lpLoadOrderGroup, - LPDWORD lpdwTagId, - LPCSTR lpDependencies, - LPCSTR lpServiceStartName, - LPCSTR lpPassword) +CreateServiceA(SC_HANDLE hSCManager, + LPCSTR lpServiceName, + LPCSTR lpDisplayName, + DWORD dwDesiredAccess, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCSTR lpDependencies, + LPCSTR lpServiceStartName, + LPCSTR lpPassword) { SC_HANDLE RetVal = NULL; LPWSTR lpServiceNameW = NULL; @@ -364,19 +363,18 @@ CreateServiceA( MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, lpPasswordW, len); RetVal = CreateServiceW(hSCManager, - lpServiceNameW, - lpDisplayNameW, - dwDesiredAccess, - dwServiceType, - dwStartType, - dwErrorControl, - lpBinaryPathNameW, - lpLoadOrderGroupW, - lpdwTagId, - lpDependenciesW, - lpServiceStartNameW, - lpPasswordW); - + lpServiceNameW, + lpDisplayNameW, + dwDesiredAccess, + dwServiceType, + dwStartType, + dwErrorControl, + lpBinaryPathNameW, + lpLoadOrderGroupW, + lpdwTagId, + lpDependenciesW, + lpServiceStartNameW, + lpPasswordW); cleanup: HeapFree(GetProcessHeap(), 0, lpServiceNameW); @@ -521,13 +519,12 @@ EnumDependentServicesA( */ BOOL STDCALL -EnumDependentServicesW( - SC_HANDLE hService, - DWORD dwServiceState, - LPENUM_SERVICE_STATUSW lpServices, - DWORD cbBufSize, - LPDWORD pcbBytesNeeded, - LPDWORD lpServicesReturned) +EnumDependentServicesW(SC_HANDLE hService, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned) { DPRINT1("EnumDependentServicesW is unimplemented\n"); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); @@ -542,7 +539,7 @@ EnumDependentServicesW( */ BOOL STDCALL -EnumServiceGroupW ( +EnumServiceGroupW( DWORD Unknown0, DWORD Unknown1, DWORD Unknown2, @@ -566,7 +563,7 @@ EnumServiceGroupW ( */ BOOL STDCALL -EnumServicesStatusA ( +EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, @@ -582,6 +579,58 @@ EnumServicesStatusA ( } +/********************************************************************** + * EnumServicesStatusW + * + * @unimplemented + */ +BOOL +STDCALL +EnumServicesStatusW(SC_HANDLE hSCManager, + DWORD dwServiceType, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle) +{ +#if 0 + DWORD dwError = ERROR_SUCCESS; + + DPRINT1("EnumServicesStatusW() called\n"); + + HandleBind(); + + dwError = ScmrEnumServicesStatusW(BindingHandle, + (unsigned int)hSCManager, + dwServiceType, + dwServiceState, + (unsigned char *)lpServices, + cbBufSize, + pcbBytesNeeded, + lpServicesReturned, + lpResumeHandle); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrEnumServicesStatusW() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return FALSE; + } + + + + DPRINT1("ScmrEnumServicesStatusW() done\n"); + + return TRUE; +#endif + + DPRINT1("EnumServicesStatusW is unimplemented\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + /********************************************************************** * EnumServicesStatusExA * @@ -630,29 +679,6 @@ EnumServicesStatusExW(SC_HANDLE hSCManager, } -/********************************************************************** - * EnumServicesStatusW - * - * @unimplemented - */ -BOOL -STDCALL -EnumServicesStatusW( - SC_HANDLE hSCManager, - DWORD dwServiceType, - DWORD dwServiceState, - LPENUM_SERVICE_STATUSW lpServices, - DWORD cbBufSize, - LPDWORD pcbBytesNeeded, - LPDWORD lpServicesReturned, - LPDWORD lpResumeHandle) -{ - DPRINT1("EnumServicesStatusW is unimplemented\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - - /********************************************************************** * GetServiceDisplayNameA * @@ -1007,30 +1033,67 @@ QueryServiceConfigA( /********************************************************************** * QueryServiceConfigW * - * @unimplemented + * @implemented */ BOOL STDCALL -QueryServiceConfigW( - SC_HANDLE hService, - LPQUERY_SERVICE_CONFIGW lpServiceConfig, - DWORD cbBufSize, - LPDWORD pcbBytesNeeded) +QueryServiceConfigW(SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGW lpServiceConfig, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded) { - DPRINT1("QueryServiceConfigW is unimplemented\n"); - if (lpServiceConfig && cbBufSize >= sizeof(QUERY_SERVICE_CONFIGW)) + DWORD dwError; + + DPRINT("QueryServiceConfigW(%p, %p, %lu, %p)\n", + hService, lpServiceConfig, cbBufSize, pcbBytesNeeded); + + HandleBind(); + + /* Call to services.exe using RPC */ + dwError = ScmrQueryServiceConfigW(BindingHandle, + (unsigned int)hService, + (unsigned char *)lpServiceConfig, + cbBufSize, + pcbBytesNeeded); + if (dwError != ERROR_SUCCESS) { - memset(lpServiceConfig, 0, *pcbBytesNeeded); - return TRUE; - } - else - { - *pcbBytesNeeded = sizeof(QUERY_SERVICE_CONFIGW); - SetLastError(ERROR_INSUFFICIENT_BUFFER); + DPRINT("ScmrQueryServiceConfigW() failed (Error %lu)\n", dwError); + SetLastError(dwError); return FALSE; } + + /* Adjust the pointers */ + if (lpServiceConfig->lpBinaryPathName) + lpServiceConfig->lpBinaryPathName = + (LPWSTR)((ULONG_PTR)lpServiceConfig + + (ULONG_PTR)lpServiceConfig->lpBinaryPathName); + + if (lpServiceConfig->lpLoadOrderGroup) + lpServiceConfig->lpLoadOrderGroup = + (LPWSTR)((ULONG_PTR)lpServiceConfig + + (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup); + + if (lpServiceConfig->lpDependencies) + lpServiceConfig->lpDependencies = + (LPWSTR)((ULONG_PTR)lpServiceConfig + + (ULONG_PTR)lpServiceConfig->lpDependencies); + + if (lpServiceConfig->lpServiceStartName) + lpServiceConfig->lpServiceStartName = + (LPWSTR)((ULONG_PTR)lpServiceConfig + + (ULONG_PTR)lpServiceConfig->lpServiceStartName); + + if (lpServiceConfig->lpDisplayName) + lpServiceConfig->lpDisplayName = + (LPWSTR)((ULONG_PTR)lpServiceConfig + + (ULONG_PTR)lpServiceConfig->lpDisplayName); + + DPRINT("QueryServiceConfigW() done\n"); + + return TRUE; } + /********************************************************************** * QueryServiceConfig2W * diff --git a/reactos/subsys/system/services/database.c b/reactos/subsys/system/services/database.c index 8473509ca80..efbe3d6a982 100644 --- a/reactos/subsys/system/services/database.c +++ b/reactos/subsys/system/services/database.c @@ -51,6 +51,7 @@ LIST_ENTRY GroupListHead; LIST_ENTRY ServiceListHead; static RTL_RESOURCE DatabaseLock; +static DWORD dwResumeCount = 1; /* FUNCTIONS *****************************************************************/ @@ -113,6 +114,35 @@ ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName) } +PSERVICE +ScmGetServiceEntryByResumeCount(DWORD dwResumeCount) +{ + PLIST_ENTRY ServiceEntry; + PSERVICE CurrentService; + + DPRINT("ScmGetServiceEntryByResumeCount() called\n"); + + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, + SERVICE, + ServiceListEntry); + if (CurrentService->dwResumeCount > dwResumeCount) + { + DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName); + return CurrentService; + } + + ServiceEntry = ServiceEntry->Flink; + } + + DPRINT("Couldn't find a matching service\n"); + + return NULL; +} + + static NTSTATUS STDCALL CreateGroupOrderListRoutine(PWSTR ValueName, ULONG ValueType, @@ -233,6 +263,9 @@ ScmCreateNewServiceRecord(LPWSTR lpServiceName, lpService->lpServiceName = lpService->szServiceName; lpService->lpDisplayName = lpService->lpServiceName; + /* Set the resume count */ + lpService->dwResumeCount = dwResumeCount++; + /* Append service entry */ InsertTailList(&ServiceListHead, &lpService->ServiceListEntry); diff --git a/reactos/subsys/system/services/driver.c b/reactos/subsys/system/services/driver.c index 24c634b60b9..976420076b6 100644 --- a/reactos/subsys/system/services/driver.c +++ b/reactos/subsys/system/services/driver.c @@ -70,6 +70,145 @@ ScmUnloadDriver(PSERVICE lpService) } +DWORD +ScmGetDriverStatus(PSERVICE lpService, + LPSERVICE_STATUS lpServiceStatus) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DirName; + HANDLE DirHandle; + NTSTATUS Status = STATUS_SUCCESS; + POBJECT_DIRECTORY_INFORMATION DirInfo; + ULONG BufferLength; + ULONG DataLength; + ULONG Index; + DWORD dwError = ERROR_SUCCESS; + BOOLEAN bFound = FALSE; + + DPRINT1("ScmGetDriverStatus() called\n"); + + memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS)); + + if (lpService->Status.dwServiceType == SERVICE_KERNEL_DRIVER) + { + RtlInitUnicodeString(&DirName, + L"\\Driver"); + } + else + { + RtlInitUnicodeString(&DirName, + L"\\FileSystem"); + } + + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + + Status = NtOpenDirectoryObject(&DirHandle, + DIRECTORY_QUERY | DIRECTORY_TRAVERSE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenDirectoryObject() failed!\n"); + return RtlNtStatusToDosError(Status); + } + + BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) + + 2 * MAX_PATH * sizeof(WCHAR); + DirInfo = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + BufferLength); + + Index = 0; + while (TRUE) + { + Status = NtQueryDirectoryObject(DirHandle, + DirInfo, + BufferLength, + TRUE, + FALSE, + &Index, + &DataLength); + if (Status == STATUS_NO_MORE_ENTRIES) + { + DPRINT("No more services\n"); + break; + } + + if (!NT_SUCCESS(Status)) + break; + + DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->ObjectName); + + if (_wcsicmp(lpService->lpServiceName, DirInfo->ObjectName.Buffer) == 0) + { + DPRINT1("Found: '%S' '%wZ'\n", + lpService->lpServiceName, &DirInfo->ObjectName); + bFound = TRUE; + + break; + } + } + + HeapFree(GetProcessHeap(), + 0, + DirInfo); + NtClose(DirHandle); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Status: %lx\n", Status); + return RtlNtStatusToDosError(Status); + } + + if ((bFound == TRUE) && + (lpService->Status.dwCurrentState != SERVICE_STOP_PENDING)) + { + if (lpService->Status.dwCurrentState == SERVICE_STOPPED) + { + lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; + lpService->Status.dwServiceSpecificExitCode = ERROR_SUCCESS; + lpService->Status.dwCheckPoint = 0; + lpService->Status.dwWaitHint = 0; + lpService->Status.dwControlsAccepted = 0; + } + else + { + lpService->Status.dwCurrentState = SERVICE_RUNNING; + lpService->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + if (lpService->Status.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) + lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; + } + } + else + { + lpService->Status.dwCurrentState = SERVICE_STOPPED; + lpService->Status.dwControlsAccepted = 0; + lpService->Status.dwCheckPoint = 0; + lpService->Status.dwWaitHint = 0; + + if (lpService->Status.dwCurrentState == SERVICE_STOP_PENDING) + lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; + else + lpService->Status.dwWin32ExitCode = ERROR_GEN_FAILURE; + } + + if (lpServiceStatus != NULL) + { + memcpy(lpServiceStatus, + &lpService->Status, + sizeof(SERVICE_STATUS)); + } + + DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError); + + return ERROR_SUCCESS; +} + + DWORD ScmControlDriver(PSERVICE lpService, DWORD dwControl, @@ -97,7 +236,8 @@ ScmControlDriver(PSERVICE lpService, break; case SERVICE_CONTROL_INTERROGATE: - dwError = ERROR_INVALID_SERVICE_CONTROL; + dwError = ScmGetDriverStatus(lpService, + lpServiceStatus); break; default: diff --git a/reactos/subsys/system/services/rpcserver.c b/reactos/subsys/system/services/rpcserver.c index 1e5d9b7cba6..4367fc78fc3 100644 --- a/reactos/subsys/system/services/rpcserver.c +++ b/reactos/subsys/system/services/rpcserver.c @@ -639,7 +639,8 @@ ScmrChangeServiceConfigW(handle_t BiningHandle, sizeof(DWORD)); if (dwError != ERROR_SUCCESS) goto done; - /* FIXME: lpService->dwType = dwServiceType; */ + + lpService->Status.dwServiceType = dwServiceType; } if (dwStartType != SERVICE_NO_CHANGE) @@ -653,6 +654,7 @@ ScmrChangeServiceConfigW(handle_t BiningHandle, sizeof(DWORD)); if (dwError != ERROR_SUCCESS) goto done; + lpService->dwStartType = dwStartType; } @@ -667,6 +669,7 @@ ScmrChangeServiceConfigW(handle_t BiningHandle, sizeof(DWORD)); if (dwError != ERROR_SUCCESS) goto done; + lpService->dwErrorControl = dwErrorControl; } @@ -1032,6 +1035,92 @@ done:; } +/* Function 13 */ +unsigned long +ScmrEnumDependentServicesW(handle_t BindingHandle, + unsigned int hService, + unsigned long dwServiceState, + unsigned char *lpServices, + unsigned long cbBufSize, + unsigned long *pcbBytesNeeded, + unsigned long *lpServicesReturned) +{ + DWORD dwError = ERROR_SUCCESS; + + DPRINT1("ScmrEnumDependentServicesW() called\n"); + + DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError); + + return dwError; +} + + +/* Function 14 */ +unsigned long +ScmrEnumServicesStatusW(handle_t BindingHandle, + unsigned int hSCManager, + unsigned long dwServiceType, + unsigned long dwServiceState, + unsigned char *lpServices, + unsigned long dwBufSize, + unsigned long *pcbBytesNeeded, + unsigned long *lpServicesReturned, + unsigned long *lpResumeHandle) +{ + PMANAGER_HANDLE hManager; + PSERVICE lpService; + DWORD dwError = ERROR_SUCCESS; + + DPRINT1("ScmrEnumServicesStatusW() called\n"); + + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + + hManager = (PMANAGER_HANDLE)hSCManager; + if (hManager->Handle.Tag != MANAGER_TAG) + { + DPRINT1("Invalid manager handle!\n"); + return ERROR_INVALID_HANDLE; + } + + /* Check access rights */ + if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, + SC_MANAGER_ENUMERATE_SERVICE)) + { + DPRINT1("Insufficient access rights! 0x%lx\n", + hManager->Handle.DesiredAccess); + return ERROR_ACCESS_DENIED; + } + + *pcbBytesNeeded = 0; + *lpServicesReturned = 0; + + /* Lock the service list shared */ + + lpService = ScmGetServiceEntryByResumeCount(*lpResumeHandle); + if (lpService == NULL) + { + dwError = ERROR_MORE_DATA; /* Hack! */ + goto done; + } + + DPRINT1("Service name: %S\n", lpService->lpServiceName); + +// DPRINT1("Display name: %S\n", lpService->lpDisplayName); + + + *lpResumeHandle = lpService->dwResumeCount; + +done:; + /* Unlock the service list */ + + + DPRINT1("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError); + + return dwError; +} + + /* Function 15 */ unsigned long ScmrOpenSCManagerW(handle_t BindingHandle, @@ -1147,6 +1236,149 @@ ScmrOpenServiceW(handle_t BindingHandle, } +/* Function 17 */ +unsigned long +ScmrQueryServiceConfigW(handle_t BindingHandle, + unsigned int hService, + unsigned char *lpServiceConfig, /* [out, unique, size_is(cbBufSize)] */ + unsigned long cbBufSize, /* [in] */ + unsigned long *pcbBytesNeeded) /* [out] */ +{ + DWORD dwError = ERROR_SUCCESS; + PSERVICE_HANDLE hSvc; + PSERVICE lpService = NULL; + HKEY hServiceKey = NULL; + LPWSTR lpImagePath = NULL; + DWORD dwRequiredSize; + LPQUERY_SERVICE_CONFIGW lpConfig; + LPWSTR lpStr; + + DPRINT1("ScmrQueryServiceConfigW() called\n"); + + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + + hSvc = (PSERVICE_HANDLE)hService; + if (hSvc->Handle.Tag != SERVICE_TAG) + { + DPRINT1("Invalid handle tag!\n"); + return ERROR_INVALID_HANDLE; + } + + if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, + SERVICE_QUERY_CONFIG)) + { + DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); + return ERROR_ACCESS_DENIED; + } + + lpService = hSvc->ServiceEntry; + if (lpService == NULL) + { + DPRINT1("lpService == NULL!\n"); + return ERROR_INVALID_HANDLE; + } + + /* FIXME: Lock the service database shared */ + + dwError = ScmOpenServiceKey(lpService->lpServiceName, + KEY_READ, + &hServiceKey); + if (dwError != ERROR_SUCCESS) + goto Done; + + dwError = ScmReadString(hServiceKey, + L"ImagePath", + &lpImagePath); + if (dwError != ERROR_SUCCESS) + goto Done; + + dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW); + + if (lpImagePath != NULL) + dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR)); + + if (lpService->lpServiceGroup != NULL) + dwRequiredSize += ((wcslen(lpService->lpServiceGroup) + 1) * sizeof(WCHAR)); + + /* FIXME: Add Dependencies length*/ + + /* FIXME: Add ServiceStartName length*/ + + if (lpService->lpDisplayName != NULL) + dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR)); + + if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) + { + dwError = ERROR_INSUFFICIENT_BUFFER; + } + else + { + lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig; + lpConfig->dwServiceType = lpService->Status.dwServiceType; + lpConfig->dwStartType = lpService->dwStartType; + lpConfig->dwErrorControl = lpService->dwErrorControl; + lpConfig->dwTagId = lpService->dwTag; + + lpStr = (LPWSTR)(lpConfig + 1); + + if (lpImagePath != NULL) + { + wcscpy(lpStr, lpImagePath); + lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); + lpStr += (wcslen(lpImagePath) + 1); + } + else + { + lpConfig->lpBinaryPathName = NULL; + } + + if (lpService->lpServiceGroup != NULL) + { + wcscpy(lpStr, lpService->lpServiceGroup); + lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); + lpStr += (wcslen(lpService->lpServiceGroup) + 1); + } + else + { + lpConfig->lpLoadOrderGroup = NULL; + } + + /* FIXME: Append Dependencies */ + lpConfig->lpDependencies = NULL; + + /* FIXME: Append ServiceStartName */ + lpConfig->lpServiceStartName = NULL; + + if (lpService->lpDisplayName != NULL) + { + wcscpy(lpStr, lpService->lpDisplayName); + lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); + } + else + { + lpConfig->lpDisplayName = NULL; + } + } + + if (pcbBytesNeeded != NULL) + *pcbBytesNeeded = dwRequiredSize; + +Done:; + if (lpImagePath != NULL) + HeapFree(GetProcessHeap(), 0, lpImagePath); + + if (hServiceKey != NULL) + RegCloseKey(hServiceKey); + + /* FIXME: Unlock the service database */ + + DPRINT1("ScmrQueryServiceConfigW() done\n"); + + return dwError; +} + + /* Function 20 */ unsigned long ScmrGetServiceDisplayNameW(handle_t BindingHandle, @@ -1160,11 +1392,11 @@ ScmrGetServiceDisplayNameW(handle_t BindingHandle, DWORD dwLength; DWORD dwError; - DPRINT1("ScmrGetServiceDisplayNameW() called\n"); - DPRINT1("hSCManager = %x\n", hSCManager); - DPRINT1("lpServiceName: %S\n", lpServiceName); - DPRINT1("lpDisplayName: %p\n", lpDisplayName); - DPRINT1("*lpcchBuffer: %lu\n", *lpcchBuffer); + DPRINT("ScmrGetServiceDisplayNameW() called\n"); + DPRINT("hSCManager = %x\n", hSCManager); + DPRINT("lpServiceName: %S\n", lpServiceName); + DPRINT("lpDisplayName: %p\n", lpDisplayName); + DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); // hManager = (PMANAGER_HANDLE)hSCManager; // if (hManager->Handle.Tag != MANAGER_TAG) @@ -1210,11 +1442,11 @@ ScmrGetServiceKeyNameW(handle_t BindingHandle, DWORD dwLength; DWORD dwError; - DPRINT1("ScmrGetServiceKeyNameW() called\n"); - DPRINT1("hSCManager = %x\n", hSCManager); - DPRINT1("lpDisplayName: %S\n", lpDisplayName); - DPRINT1("lpServiceName: %p\n", lpServiceName); - DPRINT1("*lpcchBuffer: %lu\n", *lpcchBuffer); + DPRINT("ScmrGetServiceKeyNameW() called\n"); + DPRINT("hSCManager = %x\n", hSCManager); + DPRINT("lpDisplayName: %S\n", lpDisplayName); + DPRINT("lpServiceName: %p\n", lpServiceName); + DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); // hManager = (PMANAGER_HANDLE)hSCManager; // if (hManager->Handle.Tag != MANAGER_TAG) @@ -1313,7 +1545,6 @@ ScmrOpenServiceA(handle_t BindingHandle, } - void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); diff --git a/reactos/subsys/system/services/services.h b/reactos/subsys/system/services/services.h index 997ec6a6a26..950a84eebcc 100644 --- a/reactos/subsys/system/services/services.h +++ b/reactos/subsys/system/services/services.h @@ -16,6 +16,7 @@ typedef struct _SERVICE LPWSTR lpDisplayName; LPWSTR lpServiceGroup; BOOL bDeleted; + DWORD dwResumeCount; SERVICE_STATUS Status; DWORD dwStartType; @@ -71,6 +72,7 @@ VOID ScmAutoStartServices(VOID); PSERVICE ScmGetServiceEntryByName(LPWSTR lpServiceName); PSERVICE ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName); +PSERVICE ScmGetServiceEntryByResumeCount(DWORD dwResumeCount); DWORD ScmCreateNewServiceRecord(LPWSTR lpServiceName, PSERVICE *lpServiceRecord); DWORD ScmMarkServiceForDelete(PSERVICE pService);