[ADVAPI32] Few improvements for Services.

- Set some last errors.
- Fix error code returned by ScLookupServiceByServiceName().
- Check the validity of the handler proc in RegisterServiceCtrlHandler(Ex)W().
- Improve some traces; comment some code.
This commit is contained in:
Hermès Bélusca-Maïto 2018-02-25 23:35:35 +01:00
parent 2e3f80f940
commit 295ea36f9e
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -135,15 +135,19 @@ ScDestroyStatusBinding(VOID)
} }
static PACTIVE_SERVICE static DWORD
ScLookupServiceByServiceName(LPCWSTR lpServiceName) ScLookupServiceByServiceName(IN LPCWSTR lpServiceName,
OUT PACTIVE_SERVICE* pService)
{ {
DWORD i; DWORD i;
TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName); TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
if (lpActiveServices[0].bOwnProcess) if (lpActiveServices[0].bOwnProcess)
return &lpActiveServices[0]; {
*pService = &lpActiveServices[0];
return ERROR_SUCCESS;
}
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
@ -151,15 +155,14 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0) if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
{ {
TRACE("Found!\n"); TRACE("Found!\n");
return &lpActiveServices[i]; *pService = &lpActiveServices[i];
return ERROR_SUCCESS;
} }
} }
TRACE("No service found!\n"); TRACE("No service found!\n");
*pService = NULL;
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); return ERROR_SERVICE_NOT_IN_EXE;
return NULL;
} }
@ -268,7 +271,7 @@ ScConnectControlPipe(HANDLE *hPipe)
dwProcessId = GetCurrentProcessId(); dwProcessId = GetCurrentProcessId();
WriteFile(*hPipe, WriteFile(*hPipe,
&dwProcessId, &dwProcessId,
sizeof(DWORD), sizeof(dwProcessId),
&dwBytesWritten, &dwBytesWritten,
NULL); NULL);
@ -588,8 +591,8 @@ ScServiceDispatcher(HANDLE hPipe,
if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN) if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
lpActiveServices[0].bOwnProcess = TRUE; lpActiveServices[0].bOwnProcess = TRUE;
lpService = ScLookupServiceByServiceName(lpServiceName); dwError = ScLookupServiceByServiceName(lpServiceName, &lpService);
if (lpService != NULL) if ((dwError == ERROR_SUCCESS) && (lpService != NULL))
{ {
/* Execute command */ /* Execute command */
switch (ControlPacket->dwControl) switch (ControlPacket->dwControl)
@ -611,10 +614,6 @@ ScServiceDispatcher(HANDLE hPipe,
break; break;
} }
} }
else
{
dwError = ERROR_SERVICE_DOES_NOT_EXIST;
}
} }
ReplyPacket.dwError = dwError; ReplyPacket.dwError = dwError;
@ -647,21 +646,21 @@ RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
{ {
ANSI_STRING ServiceNameA; ANSI_STRING ServiceNameA;
UNICODE_STRING ServiceNameU; UNICODE_STRING ServiceNameU;
SERVICE_STATUS_HANDLE SHandle; SERVICE_STATUS_HANDLE hServiceStatus;
RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName); RtlInitAnsiString(&ServiceNameA, lpServiceName);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE))) if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
{ {
SetLastError(ERROR_OUTOFMEMORY); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (SERVICE_STATUS_HANDLE)0; return NULL;
} }
SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer, hServiceStatus = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
lpHandlerProc); lpHandlerProc);
RtlFreeUnicodeString(&ServiceNameU); RtlFreeUnicodeString(&ServiceNameU);
return SHandle; return hServiceStatus;
} }
@ -674,18 +673,26 @@ SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
LPHANDLER_FUNCTION lpHandlerProc) LPHANDLER_FUNCTION lpHandlerProc)
{ {
DWORD dwError;
PACTIVE_SERVICE Service; PACTIVE_SERVICE Service;
Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName); dwError = ScLookupServiceByServiceName(lpServiceName, &Service);
if (Service == NULL) if ((dwError != ERROR_SUCCESS) || (Service == NULL))
{ {
return (SERVICE_STATUS_HANDLE)NULL; SetLastError(dwError);
return NULL;
} }
Service->HandlerFunction = lpHandlerProc; if (!lpHandlerProc)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
Service->HandlerFunction = lpHandlerProc;
Service->HandlerFunctionEx = NULL; Service->HandlerFunctionEx = NULL;
TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus); TRACE("RegisterServiceCtrlHandler returning 0x%p\n", Service->hServiceStatus);
return Service->hServiceStatus; return Service->hServiceStatus;
} }
@ -703,22 +710,22 @@ RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
{ {
ANSI_STRING ServiceNameA; ANSI_STRING ServiceNameA;
UNICODE_STRING ServiceNameU; UNICODE_STRING ServiceNameU;
SERVICE_STATUS_HANDLE SHandle; SERVICE_STATUS_HANDLE hServiceStatus;
RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName); RtlInitAnsiString(&ServiceNameA, lpServiceName);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE))) if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
{ {
SetLastError(ERROR_OUTOFMEMORY); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (SERVICE_STATUS_HANDLE)0; return NULL;
} }
SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer, hServiceStatus = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
lpHandlerProc, lpHandlerProc,
lpContext); lpContext);
RtlFreeUnicodeString(&ServiceNameU); RtlFreeUnicodeString(&ServiceNameU);
return SHandle; return hServiceStatus;
} }
@ -732,19 +739,27 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
LPHANDLER_FUNCTION_EX lpHandlerProc, LPHANDLER_FUNCTION_EX lpHandlerProc,
LPVOID lpContext) LPVOID lpContext)
{ {
DWORD dwError;
PACTIVE_SERVICE Service; PACTIVE_SERVICE Service;
Service = ScLookupServiceByServiceName(lpServiceName); dwError = ScLookupServiceByServiceName(lpServiceName, &Service);
if (Service == NULL) if ((dwError != ERROR_SUCCESS) || (Service == NULL))
{ {
return (SERVICE_STATUS_HANDLE)NULL; SetLastError(dwError);
return NULL;
} }
Service->HandlerFunction = NULL; if (!lpHandlerProc)
Service->HandlerFunctionEx = lpHandlerProc; {
Service->HandlerContext = lpContext; SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus); Service->HandlerFunction = NULL;
Service->HandlerFunctionEx = lpHandlerProc;
Service->HandlerContext = lpContext;
TRACE("RegisterServiceCtrlHandlerEx returning 0x%p\n", Service->hServiceStatus);
return Service->hServiceStatus; return Service->hServiceStatus;
} }
@ -942,11 +957,14 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
} }
dwActiveServiceCount = i; dwActiveServiceCount = i;
/* Initialize the service table */
lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(), lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
dwActiveServiceCount * sizeof(ACTIVE_SERVICE)); dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
if (lpActiveServices == NULL) if (lpActiveServices == NULL)
{ {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE; return FALSE;
} }
@ -956,16 +974,18 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName, RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName); lpServiceStartTable[i].lpServiceName);
lpActiveServices[i].ServiceMain.A = lpServiceStartTable[i].lpServiceProc; lpActiveServices[i].ServiceMain.A = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].hServiceStatus = 0; lpActiveServices[i].hServiceStatus = NULL;
lpActiveServices[i].bUnicode = FALSE; lpActiveServices[i].bUnicode = FALSE;
lpActiveServices[i].bOwnProcess = FALSE; lpActiveServices[i].bOwnProcess = FALSE;
} }
/* Initialize the connection to the SCM */
dwError = ScConnectControlPipe(&hPipe); dwError = ScConnectControlPipe(&hPipe);
if (dwError != ERROR_SUCCESS) if (dwError != ERROR_SUCCESS)
{ {
bRet = FALSE; bRet = FALSE;
goto done; goto Done;
} }
dwBufSize = sizeof(SCM_CONTROL_PACKET) + dwBufSize = sizeof(SCM_CONTROL_PACKET) +
@ -976,22 +996,24 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
dwBufSize); dwBufSize);
if (ControlPacket == NULL) if (ControlPacket == NULL)
{ {
dwError = ERROR_NOT_ENOUGH_MEMORY;
bRet = FALSE; bRet = FALSE;
goto done; goto Done;
} }
ScCreateStatusBinding(); ScCreateStatusBinding();
/* Start the dispatcher loop */
ScServiceDispatcher(hPipe, ControlPacket, dwBufSize); ScServiceDispatcher(hPipe, ControlPacket, dwBufSize);
/* Close the connection */
ScDestroyStatusBinding(); ScDestroyStatusBinding();
CloseHandle(hPipe); CloseHandle(hPipe);
/* Free the control packet */ /* Free the control packet */
RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket); RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket);
done: Done:
/* Free the service table */ /* Free the service table */
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
@ -1001,6 +1023,8 @@ done:
lpActiveServices = NULL; lpActiveServices = NULL;
dwActiveServiceCount = 0; dwActiveServiceCount = 0;
if (!bRet) SetLastError(dwError);
return bRet; return bRet;
} }
@ -1029,11 +1053,14 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
} }
dwActiveServiceCount = i; dwActiveServiceCount = i;
/* Initialize the service table */
lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(), lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
dwActiveServiceCount * sizeof(ACTIVE_SERVICE)); dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
if (lpActiveServices == NULL) if (lpActiveServices == NULL)
{ {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE; return FALSE;
} }
@ -1043,16 +1070,18 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName, RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName); lpServiceStartTable[i].lpServiceName);
lpActiveServices[i].ServiceMain.W = lpServiceStartTable[i].lpServiceProc; lpActiveServices[i].ServiceMain.W = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].hServiceStatus = 0; lpActiveServices[i].hServiceStatus = NULL;
lpActiveServices[i].bUnicode = TRUE; lpActiveServices[i].bUnicode = TRUE;
lpActiveServices[i].bOwnProcess = FALSE; lpActiveServices[i].bOwnProcess = FALSE;
} }
/* Initialize the connection to the SCM */
dwError = ScConnectControlPipe(&hPipe); dwError = ScConnectControlPipe(&hPipe);
if (dwError != ERROR_SUCCESS) if (dwError != ERROR_SUCCESS)
{ {
bRet = FALSE; bRet = FALSE;
goto done; goto Done;
} }
dwBufSize = sizeof(SCM_CONTROL_PACKET) + dwBufSize = sizeof(SCM_CONTROL_PACKET) +
@ -1063,22 +1092,24 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
dwBufSize); dwBufSize);
if (ControlPacket == NULL) if (ControlPacket == NULL)
{ {
dwError = ERROR_NOT_ENOUGH_MEMORY;
bRet = FALSE; bRet = FALSE;
goto done; goto Done;
} }
ScCreateStatusBinding(); ScCreateStatusBinding();
/* Start the dispatcher loop */
ScServiceDispatcher(hPipe, ControlPacket, dwBufSize); ScServiceDispatcher(hPipe, ControlPacket, dwBufSize);
/* Close the connection */
ScDestroyStatusBinding(); ScDestroyStatusBinding();
CloseHandle(hPipe); CloseHandle(hPipe);
/* Free the control packet */ /* Free the control packet */
RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket); RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket);
done: Done:
/* Free the service table */ /* Free the service table */
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
@ -1088,6 +1119,8 @@ done:
lpActiveServices = NULL; lpActiveServices = NULL;
dwActiveServiceCount = 0; dwActiveServiceCount = 0;
if (!bRet) SetLastError(dwError);
return bRet; return bRet;
} }