reactos/dll/win32/advapi32/service/scm.c

3163 lines
85 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/service/scm.c
* PURPOSE: Service control manager functions
* PROGRAMMER: Emanuele Aliberti
* Eric Kohl
* Pierre Schweitzer
*/
/* INCLUDES ******************************************************************/
#include <advapi32.h>
WINE_DEFAULT_DEBUG_CHANNEL(advapi);
NTSTATUS
WINAPI
SystemFunction004(
const struct ustring *in,
const struct ustring *key,
struct ustring *out);
NTSTATUS
WINAPI
SystemFunction028(
IN PVOID ContextHandle,
OUT LPBYTE SessionKey);
/* FUNCTIONS *****************************************************************/
handle_t __RPC_USER
SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
{
handle_t hBinding = NULL;
RPC_CSTR pszStringBinding;
RPC_STATUS status;
TRACE("SVCCTL_HANDLEA_bind(%s)\n",
debugstr_a(szMachineName));
status = RpcStringBindingComposeA(NULL,
(RPC_CSTR)"ncacn_np",
(RPC_CSTR)szMachineName,
(RPC_CSTR)"\\pipe\\ntsvcs",
NULL,
&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringBindingCompose returned 0x%x\n", status);
return NULL;
}
/* Set the binding handle that will be used to bind to the server. */
status = RpcBindingFromStringBindingA(pszStringBinding,
&hBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
}
status = RpcStringFreeA(&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringFree returned 0x%x\n", status);
}
return hBinding;
}
void __RPC_USER
SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
handle_t hBinding)
{
RPC_STATUS status;
TRACE("SVCCTL_HANDLEA_unbind(%s %p)\n",
debugstr_a(szMachineName), hBinding);
status = RpcBindingFree(&hBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFree returned 0x%x\n", status);
}
}
handle_t __RPC_USER
SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
{
handle_t hBinding = NULL;
RPC_WSTR pszStringBinding;
RPC_STATUS status;
TRACE("SVCCTL_HANDLEW_bind(%s)\n",
debugstr_w(szMachineName));
status = RpcStringBindingComposeW(NULL,
L"ncacn_np",
szMachineName,
L"\\pipe\\ntsvcs",
NULL,
&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringBindingCompose returned 0x%x\n", status);
return NULL;
}
/* Set the binding handle that will be used to bind to the server. */
status = RpcBindingFromStringBindingW(pszStringBinding,
&hBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
}
status = RpcStringFreeW(&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringFree returned 0x%x\n", status);
}
return hBinding;
}
void __RPC_USER
SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
handle_t hBinding)
{
RPC_STATUS status;
TRACE("SVCCTL_HANDLEW_unbind(%s %p)\n",
debugstr_w(szMachineName), hBinding);
status = RpcBindingFree(&hBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFree returned 0x%x\n", status);
}
}
DWORD
ScmRpcStatusToWinError(RPC_STATUS Status)
{
TRACE("ScmRpcStatusToWinError(%lx)\n",
Status);
switch (Status)
{
case STATUS_ACCESS_VIOLATION:
case RPC_S_INVALID_BINDING:
case RPC_X_SS_IN_NULL_CONTEXT:
return ERROR_INVALID_HANDLE;
case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
case RPC_X_BYTE_COUNT_TOO_SMALL:
return ERROR_INVALID_PARAMETER;
case RPC_X_NULL_REF_POINTER:
return ERROR_INVALID_ADDRESS;
default:
return (DWORD)Status;
}
}
static
DWORD
ScmEncryptPassword(
_In_ PVOID ContextHandle,
_In_ PCWSTR pClearTextPassword,
_Out_ PBYTE *pEncryptedPassword,
_Out_ PDWORD pEncryptedPasswordSize)
{
struct ustring inData, keyData, outData;
BYTE SessionKey[16];
PBYTE pBuffer;
NTSTATUS Status;
/* Get the session key */
Status = SystemFunction028(ContextHandle,
SessionKey);
if (!NT_SUCCESS(Status))
{
ERR("SystemFunction028 failed (Status 0x%08lx)\n", Status);
return RtlNtStatusToDosError(Status);
}
inData.Length = (wcslen(pClearTextPassword) + 1) * sizeof(WCHAR);
inData.MaximumLength = inData.Length;
inData.Buffer = (unsigned char *)pClearTextPassword;
keyData.Length = sizeof(SessionKey);
keyData.MaximumLength = keyData.Length;
keyData.Buffer = SessionKey;
outData.Length = 0;
outData.MaximumLength = 0;
outData.Buffer = NULL;
/* Get the required buffer size */
Status = SystemFunction004(&inData,
&keyData,
&outData);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
ERR("SystemFunction004 failed (Status 0x%08lx)\n", Status);
return RtlNtStatusToDosError(Status);
}
/* Allocate a buffer for the encrypted password */
pBuffer = HeapAlloc(GetProcessHeap(), 0, outData.Length);
if (pBuffer == NULL)
return ERROR_OUTOFMEMORY;
outData.MaximumLength = outData.Length;
outData.Buffer = pBuffer;
/* Encrypt the password */
Status = SystemFunction004(&inData,
&keyData,
&outData);
if (!NT_SUCCESS(Status))
{
ERR("SystemFunction004 failed (Status 0x%08lx)\n", Status);
HeapFree(GetProcessHeap(), 0, pBuffer);
return RtlNtStatusToDosError(Status);
}
*pEncryptedPassword = outData.Buffer;
*pEncryptedPasswordSize = outData.Length;
return ERROR_SUCCESS;
}
/**********************************************************************
* ChangeServiceConfig2A
*
* @implemented
*/
BOOL WINAPI
ChangeServiceConfig2A(SC_HANDLE hService,
DWORD dwInfoLevel,
LPVOID lpInfo)
{
SC_RPC_CONFIG_INFOA Info;
DWORD dwError;
TRACE("ChangeServiceConfig2A(%p %lu %p)\n",
hService, dwInfoLevel, lpInfo);
if (lpInfo == NULL) return TRUE;
/* Fill relevant field of the Info structure */
Info.dwInfoLevel = dwInfoLevel;
switch (dwInfoLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
Info.psd = lpInfo;
break;
case SERVICE_CONFIG_FAILURE_ACTIONS:
Info.psfa = lpInfo;
break;
default:
WARN("Unknown info level 0x%lx\n", dwInfoLevel);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RpcTryExcept
{
dwError = RChangeServiceConfig2A((SC_RPC_HANDLE)hService,
Info);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RChangeServiceConfig2A() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* ChangeServiceConfig2W
*
* @implemented
*/
BOOL WINAPI
ChangeServiceConfig2W(SC_HANDLE hService,
DWORD dwInfoLevel,
LPVOID lpInfo)
{
SC_RPC_CONFIG_INFOW Info;
DWORD dwError;
TRACE("ChangeServiceConfig2W(%p %lu %p)\n",
hService, dwInfoLevel, lpInfo);
if (lpInfo == NULL) return TRUE;
/* Fill relevant field of the Info structure */
Info.dwInfoLevel = dwInfoLevel;
switch (dwInfoLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
Info.psd = lpInfo;
break;
case SERVICE_CONFIG_FAILURE_ACTIONS:
Info.psfa = lpInfo;
break;
default:
WARN("Unknown info level 0x%lx\n", dwInfoLevel);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RpcTryExcept
{
dwError = RChangeServiceConfig2W((SC_RPC_HANDLE)hService,
Info);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RChangeServiceConfig2W() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* ChangeServiceConfigA
*
* @implemented
*/
BOOL WINAPI
ChangeServiceConfigA(SC_HANDLE hService,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCSTR lpBinaryPathName,
LPCSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCSTR lpDependencies,
LPCSTR lpServiceStartName,
LPCSTR lpPassword,
LPCSTR lpDisplayName)
{
DWORD dwError;
DWORD dwDependenciesLength = 0;
SIZE_T cchLength;
LPCSTR lpStr;
DWORD dwPasswordSize = 0;
LPWSTR lpPasswordW = NULL;
LPBYTE lpEncryptedPassword = NULL;
TRACE("ChangeServiceConfigA(%p %lu %lu %lu %s %s %p %s %s %s %s)\n",
hService, dwServiceType, dwStartType, dwErrorControl, debugstr_a(lpBinaryPathName),
debugstr_a(lpLoadOrderGroup), lpdwTagId, debugstr_a(lpDependencies),
debugstr_a(lpServiceStartName), debugstr_a(lpPassword), debugstr_a(lpDisplayName));
/* Calculate the Dependencies length*/
if (lpDependencies != NULL)
{
lpStr = lpDependencies;
while (*lpStr)
{
cchLength = strlen(lpStr) + 1;
dwDependenciesLength += (DWORD)cchLength;
lpStr = lpStr + cchLength;
}
dwDependenciesLength++;
}
if (lpPassword != NULL)
{
/* Convert the password to unicode */
lpPasswordW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
(strlen(lpPassword) + 1) * sizeof(WCHAR));
if (lpPasswordW == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
MultiByteToWideChar(CP_ACP,
0,
lpPassword,
-1,
lpPasswordW,
(int)(strlen(lpPassword) + 1));
/* Encrypt the unicode password */
dwError = ScmEncryptPassword(hService,
lpPasswordW,
&lpEncryptedPassword,
&dwPasswordSize);
if (dwError != ERROR_SUCCESS)
goto done;
}
RpcTryExcept
{
dwError = RChangeServiceConfigA((SC_RPC_HANDLE)hService,
dwServiceType,
dwStartType,
dwErrorControl,
(LPSTR)lpBinaryPathName,
(LPSTR)lpLoadOrderGroup,
lpdwTagId,
(LPBYTE)lpDependencies,
dwDependenciesLength,
(LPSTR)lpServiceStartName,
lpEncryptedPassword,
dwPasswordSize,
(LPSTR)lpDisplayName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
done:
if (lpPasswordW != NULL)
{
/* Wipe and release the password buffers */
SecureZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR));
HeapFree(GetProcessHeap(), 0, lpPasswordW);
if (lpEncryptedPassword != NULL)
{
SecureZeroMemory(lpEncryptedPassword, dwPasswordSize);
HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* ChangeServiceConfigW
*
* @implemented
*/
BOOL WINAPI
ChangeServiceConfigW(SC_HANDLE hService,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCWSTR lpBinaryPathName,
LPCWSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCWSTR lpDependencies,
LPCWSTR lpServiceStartName,
LPCWSTR lpPassword,
LPCWSTR lpDisplayName)
{
DWORD dwError;
DWORD dwDependenciesLength = 0;
SIZE_T cchLength;
LPCWSTR lpStr;
DWORD dwPasswordSize = 0;
LPBYTE lpEncryptedPassword = NULL;
TRACE("ChangeServiceConfigW(%p %lu %lu %lu %s %s %p %s %s %s %s)\n",
hService, dwServiceType, dwStartType, dwErrorControl, debugstr_w(lpBinaryPathName),
debugstr_w(lpLoadOrderGroup), lpdwTagId, debugstr_w(lpDependencies),
debugstr_w(lpServiceStartName), debugstr_w(lpPassword), debugstr_w(lpDisplayName));
/* Calculate the Dependencies length*/
if (lpDependencies != NULL)
{
lpStr = lpDependencies;
while (*lpStr)
{
cchLength = wcslen(lpStr) + 1;
dwDependenciesLength += (DWORD)cchLength;
lpStr = lpStr + cchLength;
}
dwDependenciesLength++;
dwDependenciesLength *= sizeof(WCHAR);
}
if (lpPassword != NULL)
{
dwError = ScmEncryptPassword(hService,
lpPassword,
&lpEncryptedPassword,
&dwPasswordSize);
if (dwError != ERROR_SUCCESS)
{
ERR("ScmEncryptPassword failed (Error %lu)\n", dwError);
goto done;
}
}
RpcTryExcept
{
dwError = RChangeServiceConfigW((SC_RPC_HANDLE)hService,
dwServiceType,
dwStartType,
dwErrorControl,
(LPWSTR)lpBinaryPathName,
(LPWSTR)lpLoadOrderGroup,
lpdwTagId,
(LPBYTE)lpDependencies,
dwDependenciesLength,
(LPWSTR)lpServiceStartName,
lpEncryptedPassword,
dwPasswordSize,
(LPWSTR)lpDisplayName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
done:
if (lpEncryptedPassword != NULL)
{
/* Wipe and release the password buffer */
SecureZeroMemory(lpEncryptedPassword, dwPasswordSize);
HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
}
if (dwError != ERROR_SUCCESS)
{
TRACE("RChangeServiceConfigW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* CloseServiceHandle
*
* @implemented
*/
BOOL WINAPI
CloseServiceHandle(SC_HANDLE hSCObject)
{
DWORD dwError;
TRACE("CloseServiceHandle(%p)\n",
hSCObject);
if (!hSCObject)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
RpcTryExcept
{
dwError = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError)
{
TRACE("RCloseServiceHandle() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("CloseServiceHandle() done\n");
return TRUE;
}
/**********************************************************************
* ControlService
*
* @implemented
*/
BOOL WINAPI
ControlService(SC_HANDLE hService,
DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus)
{
DWORD dwError;
TRACE("ControlService(%p %lu %p)\n",
hService, dwControl, lpServiceStatus);
RpcTryExcept
{
dwError = RControlService((SC_RPC_HANDLE)hService,
dwControl,
lpServiceStatus);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RControlService() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("ControlService() done\n");
return TRUE;
}
/**********************************************************************
* ControlServiceEx
*
* @unimplemented
*/
BOOL WINAPI
ControlServiceEx(IN SC_HANDLE hService,
IN DWORD dwControl,
IN DWORD dwInfoLevel,
IN OUT PVOID pControlParams)
{
FIXME("ControlServiceEx(%p %lu %lu %p)\n",
hService, dwControl, dwInfoLevel, pControlParams);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/**********************************************************************
* CreateServiceA
*
* @implemented
*/
SC_HANDLE WINAPI
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 hService = NULL;
DWORD dwDependenciesLength = 0;
DWORD dwError;
SIZE_T cchLength;
LPCSTR lpStr;
DWORD dwPasswordSize = 0;
LPWSTR lpPasswordW = NULL;
LPBYTE lpEncryptedPassword = NULL;
TRACE("CreateServiceA(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n",
hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName),
dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup), lpdwTagId,
debugstr_a(lpDependencies), debugstr_a(lpServiceStartName), debugstr_a(lpPassword));
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
/* Calculate the Dependencies length */
if (lpDependencies != NULL)
{
lpStr = lpDependencies;
while (*lpStr)
{
cchLength = strlen(lpStr) + 1;
dwDependenciesLength += (DWORD)cchLength;
lpStr = lpStr + cchLength;
}
dwDependenciesLength++;
}
if (lpPassword != NULL)
{
/* Convert the password to unicode */
lpPasswordW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
(strlen(lpPassword) + 1) * sizeof(WCHAR));
if (lpPasswordW == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
MultiByteToWideChar(CP_ACP,
0,
lpPassword,
-1,
lpPasswordW,
(int)(strlen(lpPassword) + 1));
/* Encrypt the password */
dwError = ScmEncryptPassword(hSCManager,
lpPasswordW,
&lpEncryptedPassword,
&dwPasswordSize);
if (dwError != ERROR_SUCCESS)
goto done;
}
RpcTryExcept
{
dwError = RCreateServiceA((SC_RPC_HANDLE)hSCManager,
(LPSTR)lpServiceName,
(LPSTR)lpDisplayName,
dwDesiredAccess,
dwServiceType,
dwStartType,
dwErrorControl,
(LPSTR)lpBinaryPathName,
(LPSTR)lpLoadOrderGroup,
lpdwTagId,
(LPBYTE)lpDependencies,
dwDependenciesLength,
(LPSTR)lpServiceStartName,
lpEncryptedPassword,
dwPasswordSize,
(SC_RPC_HANDLE *)&hService);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
done:
if (lpPasswordW != NULL)
{
/* Wipe and release the password buffers */
SecureZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR));
HeapFree(GetProcessHeap(), 0, lpPasswordW);
if (lpEncryptedPassword != NULL)
{
SecureZeroMemory(lpEncryptedPassword, dwPasswordSize);
HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
}
}
SetLastError(dwError);
if (dwError != ERROR_SUCCESS)
{
TRACE("RCreateServiceA() failed (Error %lu)\n", dwError);
return NULL;
}
return hService;
}
/**********************************************************************
* CreateServiceW
*
* @implemented
*/
SC_HANDLE WINAPI
CreateServiceW(SC_HANDLE hSCManager,
LPCWSTR lpServiceName,
LPCWSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCWSTR lpBinaryPathName,
LPCWSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCWSTR lpDependencies,
LPCWSTR lpServiceStartName,
LPCWSTR lpPassword)
{
SC_HANDLE hService = NULL;
DWORD dwDependenciesLength = 0;
DWORD dwError;
SIZE_T cchLength;
LPCWSTR lpStr;
DWORD dwPasswordSize = 0;
LPBYTE lpEncryptedPassword = NULL;
TRACE("CreateServiceW(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n",
hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName),
dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup), lpdwTagId,
debugstr_w(lpDependencies), debugstr_w(lpServiceStartName), debugstr_w(lpPassword));
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
/* Calculate the Dependencies length */
if (lpDependencies != NULL)
{
lpStr = lpDependencies;
while (*lpStr)
{
cchLength = wcslen(lpStr) + 1;
dwDependenciesLength += (DWORD)cchLength;
lpStr = lpStr + cchLength;
}
dwDependenciesLength++;
dwDependenciesLength *= sizeof(WCHAR);
}
if (lpPassword != NULL)
{
/* Encrypt the password */
dwError = ScmEncryptPassword(hSCManager,
lpPassword,
&lpEncryptedPassword,
&dwPasswordSize);
if (dwError != ERROR_SUCCESS)
goto done;
}
RpcTryExcept
{
dwError = RCreateServiceW((SC_RPC_HANDLE)hSCManager,
lpServiceName,
lpDisplayName,
dwDesiredAccess,
dwServiceType,
dwStartType,
dwErrorControl,
lpBinaryPathName,
lpLoadOrderGroup,
lpdwTagId,
(LPBYTE)lpDependencies,
dwDependenciesLength,
lpServiceStartName,
lpEncryptedPassword,
dwPasswordSize,
(SC_RPC_HANDLE *)&hService);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
done:
if (lpEncryptedPassword != NULL)
{
/* Wipe and release the password buffers */
SecureZeroMemory(lpEncryptedPassword, dwPasswordSize);
HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
}
SetLastError(dwError);
if (dwError != ERROR_SUCCESS)
{
TRACE("RCreateServiceW() failed (Error %lu)\n", dwError);
return NULL;
}
return hService;
}
/**********************************************************************
* DeleteService
*
* @implemented
*/
BOOL WINAPI
DeleteService(SC_HANDLE hService)
{
DWORD dwError;
TRACE("DeleteService(%p)\n",
hService);
RpcTryExcept
{
dwError = RDeleteService((SC_RPC_HANDLE)hService);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RDeleteService() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* EnumDependentServicesA
*
* @implemented
*/
BOOL WINAPI
EnumDependentServicesA(SC_HANDLE hService,
DWORD dwServiceState,
LPENUM_SERVICE_STATUSA lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned)
{
ENUM_SERVICE_STATUSA ServiceStatus;
LPENUM_SERVICE_STATUSA lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumDependentServicesA(%p %lu %p %lu %p %p)\n",
hService, dwServiceState, lpServices, cbBufSize,
pcbBytesNeeded, lpServicesReturned);
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUSA);
}
else
{
lpStatusPtr = lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = REnumDependentServicesA((SC_RPC_HANDLE)hService,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumDependentServicesA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumDependentServicesA() done\n");
return TRUE;
}
/**********************************************************************
* EnumDependentServicesW
*
* @implemented
*/
BOOL WINAPI
EnumDependentServicesW(SC_HANDLE hService,
DWORD dwServiceState,
LPENUM_SERVICE_STATUSW lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned)
{
ENUM_SERVICE_STATUSW ServiceStatus;
LPENUM_SERVICE_STATUSW lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumDependentServicesW(%p %lu %p %lu %p %p)\n",
hService, dwServiceState, lpServices, cbBufSize,
pcbBytesNeeded, lpServicesReturned);
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
}
else
{
lpStatusPtr = lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = REnumDependentServicesW((SC_RPC_HANDLE)hService,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumDependentServicesW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumDependentServicesW() done\n");
return TRUE;
}
/**********************************************************************
* EnumServiceGroupW
*
* @implemented
*/
BOOL WINAPI
EnumServiceGroupW(SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPENUM_SERVICE_STATUSW lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle,
LPCWSTR lpGroup)
{
ENUM_SERVICE_STATUSW ServiceStatus;
LPENUM_SERVICE_STATUSW lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumServiceGroupW(%p %lu %lu %p %lu %p %p %p %s)\n",
hSCManager, dwServiceType, dwServiceState, lpServices,
cbBufSize, pcbBytesNeeded, lpServicesReturned,
lpResumeHandle, debugstr_w(lpGroup));
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
{
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
}
else
{
lpStatusPtr = lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
if (lpGroup == NULL)
{
dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager,
dwServiceType,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned,
lpResumeHandle);
}
else
{
dwError = REnumServiceGroupW((SC_RPC_HANDLE)hSCManager,
dwServiceType,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned,
lpResumeHandle,
lpGroup);
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumServiceGroupW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumServiceGroupW() done\n");
return TRUE;
}
/**********************************************************************
* EnumServicesStatusA
*
* @implemented
*/
BOOL WINAPI
EnumServicesStatusA(SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPENUM_SERVICE_STATUSA lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle)
{
ENUM_SERVICE_STATUSA ServiceStatus;
LPENUM_SERVICE_STATUSA lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumServicesStatusA(%p %lu %lu %p %lu %p %p %p)\n",
hSCManager, dwServiceType, dwServiceState, lpServices,
cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
{
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUSA);
}
else
{
lpStatusPtr = lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = REnumServicesStatusA((SC_RPC_HANDLE)hSCManager,
dwServiceType,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned,
lpResumeHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumServicesStatusA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumServicesStatusA() done\n");
return TRUE;
}
/**********************************************************************
* EnumServicesStatusW
*
* @implemented
*/
BOOL WINAPI
EnumServicesStatusW(SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPENUM_SERVICE_STATUSW lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle)
{
ENUM_SERVICE_STATUSW ServiceStatus;
LPENUM_SERVICE_STATUSW lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumServicesStatusW(%p %lu %lu %p %lu %p %p %p)\n",
hSCManager, dwServiceType, dwServiceState, lpServices,
cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
{
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
}
else
{
lpStatusPtr = lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager,
dwServiceType,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned,
lpResumeHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumServicesStatusW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumServicesStatusW() done\n");
return TRUE;
}
/**********************************************************************
* EnumServicesStatusExA
*
* @implemented
*/
BOOL WINAPI
EnumServicesStatusExA(SC_HANDLE hSCManager,
SC_ENUM_TYPE InfoLevel,
DWORD dwServiceType,
DWORD dwServiceState,
LPBYTE lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle,
LPCSTR pszGroupName)
{
ENUM_SERVICE_STATUS_PROCESSA ServiceStatus;
LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumServicesStatusExA(%p %lu %lu %p %lu %p %p %p %s)\n",
hSCManager, dwServiceType, dwServiceState, lpServices,
cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle,
debugstr_a(pszGroupName));
if (InfoLevel != SC_ENUM_PROCESS_INFO)
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
{
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSA);
}
else
{
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager,
InfoLevel,
dwServiceType,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned,
lpResumeHandle,
(LPSTR)pszGroupName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
if (InfoLevel == SC_ENUM_PROCESS_INFO)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumServicesStatusExA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumServicesStatusExA() done\n");
return TRUE;
}
/**********************************************************************
* EnumServicesStatusExW
*
* @implemented
*/
BOOL WINAPI
EnumServicesStatusExW(SC_HANDLE hSCManager,
SC_ENUM_TYPE InfoLevel,
DWORD dwServiceType,
DWORD dwServiceState,
LPBYTE lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle,
LPCWSTR pszGroupName)
{
ENUM_SERVICE_STATUS_PROCESSW ServiceStatus;
LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
DWORD dwCount;
TRACE("EnumServicesStatusExW(%p %lu %lu %p %lu %p %p %p %s)\n",
hSCManager, dwServiceType, dwServiceState, lpServices,
cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle,
debugstr_w(pszGroupName));
if (InfoLevel != SC_ENUM_PROCESS_INFO)
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
{
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW))
{
lpStatusPtr = &ServiceStatus;
dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW);
}
else
{
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager,
InfoLevel,
dwServiceType,
dwServiceState,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded,
lpServicesReturned,
lpResumeHandle,
(LPWSTR)pszGroupName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{
if (InfoLevel == SC_ENUM_PROCESS_INFO)
{
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{
if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++;
}
}
}
if (dwError != ERROR_SUCCESS)
{
TRACE("REnumServicesStatusExW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
TRACE("EnumServicesStatusExW() done\n");
return TRUE;
}
/**********************************************************************
* GetServiceDisplayNameA
*
* @implemented
*/
BOOL WINAPI
GetServiceDisplayNameA(SC_HANDLE hSCManager,
LPCSTR lpServiceName,
LPSTR lpDisplayName,
LPDWORD lpcchBuffer)
{
DWORD dwError;
LPSTR lpNameBuffer;
CHAR szEmptyName[] = "";
TRACE("GetServiceDisplayNameA(%p %s %p %p)\n",
hSCManager, debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!lpDisplayName || *lpcchBuffer < sizeof(CHAR))
{
lpNameBuffer = szEmptyName;
*lpcchBuffer = sizeof(CHAR);
}
else
{
lpNameBuffer = lpDisplayName;
}
RpcTryExcept
{
dwError = RGetServiceDisplayNameA((SC_RPC_HANDLE)hSCManager,
lpServiceName,
lpNameBuffer,
lpcchBuffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* GetServiceDisplayNameW
*
* @implemented
*/
BOOL WINAPI
GetServiceDisplayNameW(SC_HANDLE hSCManager,
LPCWSTR lpServiceName,
LPWSTR lpDisplayName,
LPDWORD lpcchBuffer)
{
DWORD dwError;
LPWSTR lpNameBuffer;
WCHAR szEmptyName[] = L"";
TRACE("GetServiceDisplayNameW(%p %s %p %p)\n",
hSCManager, debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/*
* NOTE: A size of 1 character would be enough, but tests show that
* Windows returns 2 characters instead, certainly due to a WCHAR/bytes
* mismatch in their code.
*/
if (!lpDisplayName || *lpcchBuffer < sizeof(WCHAR))
{
lpNameBuffer = szEmptyName;
*lpcchBuffer = sizeof(WCHAR);
}
else
{
lpNameBuffer = lpDisplayName;
}
RpcTryExcept
{
dwError = RGetServiceDisplayNameW((SC_RPC_HANDLE)hSCManager,
lpServiceName,
lpNameBuffer,
lpcchBuffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* GetServiceKeyNameA
*
* @implemented
*/
BOOL WINAPI
GetServiceKeyNameA(SC_HANDLE hSCManager,
LPCSTR lpDisplayName,
LPSTR lpServiceName,
LPDWORD lpcchBuffer)
{
DWORD dwError;
LPSTR lpNameBuffer;
CHAR szEmptyName[] = "";
TRACE("GetServiceKeyNameA(%p %s %p %p)\n",
hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!lpServiceName || *lpcchBuffer < sizeof(CHAR))
{
lpNameBuffer = szEmptyName;
*lpcchBuffer = sizeof(CHAR);
}
else
{
lpNameBuffer = lpServiceName;
}
RpcTryExcept
{
dwError = RGetServiceKeyNameA((SC_RPC_HANDLE)hSCManager,
lpDisplayName,
lpNameBuffer,
lpcchBuffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
/* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* GetServiceKeyNameW
*
* @implemented
*/
BOOL WINAPI
GetServiceKeyNameW(SC_HANDLE hSCManager,
LPCWSTR lpDisplayName,
LPWSTR lpServiceName,
LPDWORD lpcchBuffer)
{
DWORD dwError;
LPWSTR lpNameBuffer;
WCHAR szEmptyName[] = L"";
TRACE("GetServiceKeyNameW(%p %s %p %p)\n",
hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/*
* NOTE: A size of 1 character would be enough, but tests show that
* Windows returns 2 characters instead, certainly due to a WCHAR/bytes
* mismatch in their code.
*/
if (!lpServiceName || *lpcchBuffer < sizeof(WCHAR))
{
lpNameBuffer = szEmptyName;
*lpcchBuffer = sizeof(WCHAR);
}
else
{
lpNameBuffer = lpServiceName;
}
RpcTryExcept
{
dwError = RGetServiceKeyNameW((SC_RPC_HANDLE)hSCManager,
lpDisplayName,
lpNameBuffer,
lpcchBuffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* I_ScGetCurrentGroupStateW
*
* @implemented
*/
DWORD WINAPI
I_ScGetCurrentGroupStateW(SC_HANDLE hSCManager,
LPWSTR pszGroupName,
LPDWORD pdwGroupState)
{
DWORD dwError;
TRACE("I_ScGetCurrentGroupStateW(%p %s %p)\n",
hSCManager, debugstr_w(pszGroupName), pdwGroupState);
RpcTryExcept
{
dwError = RI_ScGetCurrentGroupStateW((SC_RPC_HANDLE)hSCManager,
pszGroupName,
pdwGroupState);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept
if (dwError != ERROR_SUCCESS)
{
TRACE("RI_ScGetCurrentGroupStateW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
}
return dwError;
}
/**********************************************************************
* LockServiceDatabase
*
* @implemented
*/
SC_LOCK WINAPI
LockServiceDatabase(SC_HANDLE hSCManager)
{
SC_LOCK hLock;
DWORD dwError;
TRACE("LockServiceDatabase(%p)\n",
hSCManager);
RpcTryExcept
{
dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager,
(SC_RPC_LOCK *)&hLock);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RLockServiceDatabase() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return NULL;
}
TRACE("hLock = %p\n", hLock);
return hLock;
}
static VOID
WaitForSCManager(VOID)
{
HANDLE hEvent;
TRACE("WaitForSCManager()\n");
/* Try to open the existing event */
hEvent = OpenEventW(SYNCHRONIZE, FALSE, SCM_START_EVENT);
if (hEvent == NULL)
{
if (GetLastError() != ERROR_FILE_NOT_FOUND)
return;
/* Try to create a new event */
hEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
if (hEvent == NULL)
return;
}
/* Wait for 3 minutes */
WaitForSingleObject(hEvent, 180000);
CloseHandle(hEvent);
TRACE("ScmWaitForSCManager() done\n");
}
/**********************************************************************
* OpenSCManagerA
*
* @implemented
*/
SC_HANDLE WINAPI
OpenSCManagerA(LPCSTR lpMachineName,
LPCSTR lpDatabaseName,
DWORD dwDesiredAccess)
{
SC_HANDLE hScm = NULL;
DWORD dwError;
TRACE("OpenSCManagerA(%s %s %lx)\n",
debugstr_a(lpMachineName), debugstr_a(lpDatabaseName), dwDesiredAccess);
WaitForSCManager();
RpcTryExcept
{
dwError = ROpenSCManagerA((LPSTR)lpMachineName,
(LPSTR)lpDatabaseName,
dwDesiredAccess,
(SC_RPC_HANDLE *)&hScm);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
SetLastError(dwError);
if (dwError != ERROR_SUCCESS)
{
TRACE("ROpenSCManagerA() failed (Error %lu)\n", dwError);
return NULL;
}
TRACE("hScm = %p\n", hScm);
return hScm;
}
/**********************************************************************
* OpenSCManagerW
*
* @implemented
*/
SC_HANDLE WINAPI
OpenSCManagerW(LPCWSTR lpMachineName,
LPCWSTR lpDatabaseName,
DWORD dwDesiredAccess)
{
SC_HANDLE hScm = NULL;
DWORD dwError;
TRACE("OpenSCManagerW(%s %s %lx)\n",
debugstr_w(lpMachineName), debugstr_w(lpDatabaseName), dwDesiredAccess);
WaitForSCManager();
RpcTryExcept
{
dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
(LPWSTR)lpDatabaseName,
dwDesiredAccess,
(SC_RPC_HANDLE *)&hScm);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
SetLastError(dwError);
if (dwError != ERROR_SUCCESS)
{
TRACE("ROpenSCManagerW() failed (Error %lu)\n", dwError);
return NULL;
}
TRACE("hScm = %p\n", hScm);
return hScm;
}
/**********************************************************************
* OpenServiceA
*
* @implemented
*/
SC_HANDLE WINAPI
OpenServiceA(SC_HANDLE hSCManager,
LPCSTR lpServiceName,
DWORD dwDesiredAccess)
{
SC_HANDLE hService = NULL;
DWORD dwError;
TRACE("OpenServiceA(%p %s %lx)\n",
hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
RpcTryExcept
{
dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
(LPSTR)lpServiceName,
dwDesiredAccess,
(SC_RPC_HANDLE *)&hService);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
SetLastError(dwError);
if (dwError != ERROR_SUCCESS)
{
TRACE("ROpenServiceA() failed (Error %lu)\n", dwError);
return NULL;
}
TRACE("hService = %p\n", hService);
return hService;
}
/**********************************************************************
* OpenServiceW
*
* @implemented
*/
SC_HANDLE WINAPI
OpenServiceW(SC_HANDLE hSCManager,
LPCWSTR lpServiceName,
DWORD dwDesiredAccess)
{
SC_HANDLE hService = NULL;
DWORD dwError;
TRACE("OpenServiceW(%p %s %lx)\n",
hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
if (!hSCManager)
{
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
RpcTryExcept
{
dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
(LPWSTR)lpServiceName,
dwDesiredAccess,
(SC_RPC_HANDLE *)&hService);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
SetLastError(dwError);
if (dwError != ERROR_SUCCESS)
{
TRACE("ROpenServiceW() failed (Error %lu)\n", dwError);
return NULL;
}
TRACE("hService = %p\n", hService);
return hService;
}
/**********************************************************************
* QueryServiceConfigA
*
* @implemented
*/
BOOL WINAPI
QueryServiceConfigA(SC_HANDLE hService,
LPQUERY_SERVICE_CONFIGA lpServiceConfig,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
QUERY_SERVICE_CONFIGA ServiceConfig;
LPQUERY_SERVICE_CONFIGA lpConfigPtr;
DWORD dwBufferSize;
DWORD dwError;
TRACE("QueryServiceConfigA(%p %p %lu %p)\n",
hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
if (lpServiceConfig == NULL ||
cbBufSize < sizeof(QUERY_SERVICE_CONFIGA))
{
lpConfigPtr = &ServiceConfig;
dwBufferSize = sizeof(QUERY_SERVICE_CONFIGA);
}
else
{
lpConfigPtr = lpServiceConfig;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
(LPBYTE)lpConfigPtr,
dwBufferSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
/* Adjust the pointers */
if (lpConfigPtr->lpBinaryPathName)
lpConfigPtr->lpBinaryPathName =
(LPSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpBinaryPathName);
if (lpConfigPtr->lpLoadOrderGroup)
lpConfigPtr->lpLoadOrderGroup =
(LPSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
if (lpConfigPtr->lpDependencies)
lpConfigPtr->lpDependencies =
(LPSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpDependencies);
if (lpConfigPtr->lpServiceStartName)
lpConfigPtr->lpServiceStartName =
(LPSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpServiceStartName);
if (lpConfigPtr->lpDisplayName)
lpConfigPtr->lpDisplayName =
(LPSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpDisplayName);
TRACE("QueryServiceConfigA() done\n");
return TRUE;
}
/**********************************************************************
* QueryServiceConfigW
*
* @implemented
*/
BOOL WINAPI
QueryServiceConfigW(SC_HANDLE hService,
LPQUERY_SERVICE_CONFIGW lpServiceConfig,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
QUERY_SERVICE_CONFIGW ServiceConfig;
LPQUERY_SERVICE_CONFIGW lpConfigPtr;
DWORD dwBufferSize;
DWORD dwError;
TRACE("QueryServiceConfigW(%p %p %lu %p)\n",
hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
if (lpServiceConfig == NULL ||
cbBufSize < sizeof(QUERY_SERVICE_CONFIGW))
{
lpConfigPtr = &ServiceConfig;
dwBufferSize = sizeof(QUERY_SERVICE_CONFIGW);
}
else
{
lpConfigPtr = lpServiceConfig;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
(LPBYTE)lpConfigPtr,
dwBufferSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
/* Adjust the pointers */
if (lpConfigPtr->lpBinaryPathName)
lpConfigPtr->lpBinaryPathName =
(LPWSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpBinaryPathName);
if (lpConfigPtr->lpLoadOrderGroup)
lpConfigPtr->lpLoadOrderGroup =
(LPWSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
if (lpConfigPtr->lpDependencies)
lpConfigPtr->lpDependencies =
(LPWSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpDependencies);
if (lpConfigPtr->lpServiceStartName)
lpConfigPtr->lpServiceStartName =
(LPWSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpServiceStartName);
if (lpConfigPtr->lpDisplayName)
lpConfigPtr->lpDisplayName =
(LPWSTR)((ULONG_PTR)lpConfigPtr +
(ULONG_PTR)lpConfigPtr->lpDisplayName);
TRACE("QueryServiceConfigW() done\n");
return TRUE;
}
/**********************************************************************
* QueryServiceConfig2A
*
* @implemented
*/
BOOL WINAPI
QueryServiceConfig2A(SC_HANDLE hService,
DWORD dwInfoLevel,
LPBYTE lpBuffer,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
SERVICE_DESCRIPTIONA ServiceDescription;
SERVICE_FAILURE_ACTIONSA ServiceFailureActions;
LPBYTE lpTempBuffer;
BOOL bUseTempBuffer = FALSE;
DWORD dwBufferSize;
DWORD dwError;
TRACE("QueryServiceConfig2A(%p %lu %p %lu %p)\n",
hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
lpTempBuffer = lpBuffer;
dwBufferSize = cbBufSize;
switch (dwInfoLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA)))
{
lpTempBuffer = (LPBYTE)&ServiceDescription;
dwBufferSize = sizeof(SERVICE_DESCRIPTIONA);
bUseTempBuffer = TRUE;
}
break;
case SERVICE_CONFIG_FAILURE_ACTIONS:
if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA)))
{
lpTempBuffer = (LPBYTE)&ServiceFailureActions;
dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA);
bUseTempBuffer = TRUE;
}
break;
default:
WARN("Unknown info level 0x%lx\n", dwInfoLevel);
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
RpcTryExcept
{
dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
dwInfoLevel,
lpTempBuffer,
dwBufferSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
if (bUseTempBuffer != FALSE)
{
TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
*pcbBytesNeeded = dwBufferSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
switch (dwInfoLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
{
LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
if (lpPtr->lpDescription != NULL)
lpPtr->lpDescription =
(LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
}
break;
case SERVICE_CONFIG_FAILURE_ACTIONS:
{
LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer;
if (lpPtr->lpRebootMsg != NULL)
lpPtr->lpRebootMsg =
(LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
if (lpPtr->lpCommand != NULL)
lpPtr->lpCommand =
(LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
if (lpPtr->lpsaActions != NULL)
lpPtr->lpsaActions =
(LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
}
break;
}
TRACE("QueryServiceConfig2A() done\n");
return TRUE;
}
/**********************************************************************
* QueryServiceConfig2W
*
* @implemented
*/
BOOL WINAPI
QueryServiceConfig2W(SC_HANDLE hService,
DWORD dwInfoLevel,
LPBYTE lpBuffer,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
SERVICE_DESCRIPTIONW ServiceDescription;
SERVICE_FAILURE_ACTIONSW ServiceFailureActions;
LPBYTE lpTempBuffer;
BOOL bUseTempBuffer = FALSE;
DWORD dwBufferSize;
DWORD dwError;
TRACE("QueryServiceConfig2W(%p %lu %p %lu %p)\n",
hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
lpTempBuffer = lpBuffer;
dwBufferSize = cbBufSize;
switch (dwInfoLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW)))
{
lpTempBuffer = (LPBYTE)&ServiceDescription;
dwBufferSize = sizeof(SERVICE_DESCRIPTIONW);
bUseTempBuffer = TRUE;
}
break;
case SERVICE_CONFIG_FAILURE_ACTIONS:
if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW)))
{
lpTempBuffer = (LPBYTE)&ServiceFailureActions;
dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW);
bUseTempBuffer = TRUE;
}
break;
default:
WARN("Unknown info level 0x%lx\n", dwInfoLevel);
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
RpcTryExcept
{
dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
dwInfoLevel,
lpTempBuffer,
dwBufferSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
if (bUseTempBuffer != FALSE)
{
TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
*pcbBytesNeeded = dwBufferSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
switch (dwInfoLevel)
{
case SERVICE_CONFIG_DESCRIPTION:
{
LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
if (lpPtr->lpDescription != NULL)
lpPtr->lpDescription =
(LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
}
break;
case SERVICE_CONFIG_FAILURE_ACTIONS:
{
LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
if (lpPtr->lpRebootMsg != NULL)
lpPtr->lpRebootMsg =
(LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
if (lpPtr->lpCommand != NULL)
lpPtr->lpCommand =
(LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
if (lpPtr->lpsaActions != NULL)
lpPtr->lpsaActions =
(LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
}
break;
}
TRACE("QueryServiceConfig2W() done\n");
return TRUE;
}
/**********************************************************************
* QueryServiceLockStatusA
*
* @implemented
*/
BOOL WINAPI
QueryServiceLockStatusA(SC_HANDLE hSCManager,
LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
QUERY_SERVICE_LOCK_STATUSA LockStatus;
LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
TRACE("QueryServiceLockStatusA(%p %p %lu %p)\n",
hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
{
lpStatusPtr = &LockStatus;
dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
}
else
{
lpStatusPtr = lpLockStatus;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
if (lpStatusPtr->lpLockOwner != NULL)
{
lpStatusPtr->lpLockOwner =
(LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
}
TRACE("QueryServiceLockStatusA() done\n");
return TRUE;
}
/**********************************************************************
* QueryServiceLockStatusW
*
* @implemented
*/
BOOL WINAPI
QueryServiceLockStatusW(SC_HANDLE hSCManager,
LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
QUERY_SERVICE_LOCK_STATUSW LockStatus;
LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError;
TRACE("QueryServiceLockStatusW(%p %p %lu %p)\n",
hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
{
lpStatusPtr = &LockStatus;
dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
}
else
{
lpStatusPtr = lpLockStatus;
dwBufferSize = cbBufSize;
}
RpcTryExcept
{
dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
(LPBYTE)lpStatusPtr,
dwBufferSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
if (lpStatusPtr->lpLockOwner != NULL)
{
lpStatusPtr->lpLockOwner =
(LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
}
TRACE("QueryServiceLockStatusW() done\n");
return TRUE;
}
/**********************************************************************
* QueryServiceObjectSecurity
*
* @implemented
*/
BOOL WINAPI
QueryServiceObjectSecurity(SC_HANDLE hService,
SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
DWORD dwError;
TRACE("QueryServiceObjectSecurity(%p %lu %p)\n",
hService, dwSecurityInformation, lpSecurityDescriptor);
RpcTryExcept
{
dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
dwSecurityInformation,
(LPBYTE)lpSecurityDescriptor,
cbBufSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* SetServiceObjectSecurity
*
* @implemented
*/
BOOL WINAPI
SetServiceObjectSecurity(SC_HANDLE hService,
SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor)
{
PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
ULONG Length;
NTSTATUS Status;
DWORD dwError;
TRACE("SetServiceObjectSecurity(%p %lu %p)\n",
hService, dwSecurityInformation, lpSecurityDescriptor);
Length = 0;
Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
SelfRelativeSD,
&Length);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
if (SelfRelativeSD == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
SelfRelativeSD,
&Length);
if (!NT_SUCCESS(Status))
{
HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
RpcTryExcept
{
dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
dwSecurityInformation,
(LPBYTE)SelfRelativeSD,
Length);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
if (dwError != ERROR_SUCCESS)
{
TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* QueryServiceStatus
*
* @implemented
*/
BOOL WINAPI
QueryServiceStatus(SC_HANDLE hService,
LPSERVICE_STATUS lpServiceStatus)
{
DWORD dwError;
TRACE("QueryServiceStatus(%p %p)\n",
hService, lpServiceStatus);
if (!hService)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
RpcTryExcept
{
dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
lpServiceStatus);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* QueryServiceStatusEx
*
* @implemented
*/
BOOL WINAPI
QueryServiceStatusEx(SC_HANDLE hService,
SC_STATUS_TYPE InfoLevel,
LPBYTE lpBuffer,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
DWORD dwError;
TRACE("QueryServiceStatusEx(%p %lu %p %lu %p)\n",
hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
if (InfoLevel != SC_STATUS_PROCESS_INFO)
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
{
*pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
RpcTryExcept
{
dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
InfoLevel,
lpBuffer,
cbBufSize,
pcbBytesNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* StartServiceA
*
* @implemented
*/
BOOL WINAPI
StartServiceA(SC_HANDLE hService,
DWORD dwNumServiceArgs,
LPCSTR *lpServiceArgVectors)
{
DWORD dwError;
TRACE("StartServiceA(%p %lu %p)\n",
hService, dwNumServiceArgs, lpServiceArgVectors);
RpcTryExcept
{
dwError = RStartServiceA((SC_RPC_HANDLE)hService,
dwNumServiceArgs,
(LPSTRING_PTRSA)lpServiceArgVectors);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
ERR("RStartServiceA() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* StartServiceW
*
* @implemented
*/
BOOL WINAPI
StartServiceW(SC_HANDLE hService,
DWORD dwNumServiceArgs,
LPCWSTR *lpServiceArgVectors)
{
DWORD dwError;
TRACE("StartServiceW(%p %lu %p)\n",
hService, dwNumServiceArgs, lpServiceArgVectors);
RpcTryExcept
{
dwError = RStartServiceW((SC_RPC_HANDLE)hService,
dwNumServiceArgs,
(LPSTRING_PTRSW)lpServiceArgVectors);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
ERR("RStartServiceW() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* UnlockServiceDatabase
*
* @implemented
*/
BOOL WINAPI
UnlockServiceDatabase(SC_LOCK ScLock)
{
DWORD dwError;
TRACE("UnlockServiceDatabase(%x)\n",
ScLock);
RpcTryExcept
{
dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError == ERROR_INVALID_HANDLE)
dwError = ERROR_INVALID_SERVICE_LOCK;
if (dwError != ERROR_SUCCESS)
{
TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
/**********************************************************************
* NotifyBootConfigStatus
*
* @implemented
*/
BOOL WINAPI
NotifyBootConfigStatus(BOOL BootAcceptable)
{
DWORD dwError;
TRACE("NotifyBootConfigStatus(%u)\n",
BootAcceptable);
RpcTryExcept
{
dwError = RNotifyBootConfigStatus(NULL,
BootAcceptable);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
if (dwError != ERROR_SUCCESS)
{
TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
return TRUE;
}
DWORD
I_ScQueryServiceTagInfo(PVOID Unused,
TAG_INFO_LEVEL dwInfoLevel,
PTAG_INFO_NAME_FROM_TAG InOutParams)
{
SC_HANDLE hScm;
DWORD dwError;
PTAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams;
PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS OutParams;
LPWSTR lpszName;
/* We only support one class */
if (dwInfoLevel != TagInfoLevelNameFromTag)
{
return ERROR_RETRY;
}
/* Validate input structure */
if (InOutParams->InParams.dwPid == 0 || InOutParams->InParams.dwTag == 0)
{
return ERROR_INVALID_PARAMETER;
}
/* Validate output structure */
if (InOutParams->OutParams.pszName != NULL)
{
return ERROR_INVALID_PARAMETER;
}
/* Open service manager */
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if (hScm == NULL)
{
return GetLastError();
}
/* Setup call parameters */
InParams = &InOutParams->InParams;
OutParams = NULL;
/* Call SCM to query tag information */
RpcTryExcept
{
dwError = RI_ScQueryServiceTagInfo(hScm, TagInfoLevelNameFromTag, &InParams, &OutParams);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ScmRpcStatusToWinError(RpcExceptionCode());
}
RpcEndExcept;
/* Quit if not a success */
if (dwError != ERROR_SUCCESS)
{
goto Cleanup;
}
/* OutParams must be set now and we must have a name */
if (OutParams == NULL ||
OutParams->pszName == NULL)
{
dwError = ERROR_INVALID_DATA;
goto Cleanup;
}
/* Copy back what SCM returned */
lpszName = LocalAlloc(LPTR,
sizeof(WCHAR) * wcslen(OutParams->pszName) + sizeof(UNICODE_NULL));
if (lpszName == NULL)
{
dwError = GetLastError();
goto Cleanup;
}
wcscpy(lpszName, OutParams->pszName);
InOutParams->OutParams.pszName = lpszName;
InOutParams->OutParams.TagType = OutParams->TagType;
Cleanup:
CloseServiceHandle(hScm);
/* Free memory allocated by SCM */
if (OutParams != NULL)
{
if (OutParams->pszName != NULL)
{
midl_user_free(OutParams->pszName);
}
midl_user_free(OutParams);
}
return dwError;
}
/**********************************************************************
* I_QueryTagInformation
*
* @implemented
*/
DWORD WINAPI
I_QueryTagInformation(PVOID Unused,
TAG_INFO_LEVEL dwInfoLevel,
PTAG_INFO_NAME_FROM_TAG InOutParams)
{
/*
* We only support one information class and it
* needs parameters
*/
if (dwInfoLevel != TagInfoLevelNameFromTag ||
InOutParams == NULL)
{
return ERROR_INVALID_PARAMETER;
}
/* Validate input structure */
if (InOutParams->InParams.dwPid == 0 || InOutParams->InParams.dwTag == 0)
{
return ERROR_INVALID_PARAMETER;
}
/* Validate output structure */
if (InOutParams->OutParams.pszName != NULL)
{
return ERROR_INVALID_PARAMETER;
}
/* Call internal function for the RPC call */
return I_ScQueryServiceTagInfo(Unused, TagInfoLevelNameFromTag, InOutParams);
}
/* EOF */